@@ 27,5 27,7 @@ For this reason, the core of the language is very close to ANSI C.
* Usage (doc/cc/usage.txt)
* Implementation details (doc/cc/impl.txt)
* Usage (doc/cc/usage)
* Implementation details (doc/cc/impl)
* Standard Library (doc/cc/lib)
* DuskCC's Forth VM details (doc/cc/forth)
@@ 0,0 1,91 @@
# DuskCC standard library
While DuskCC's core language tries to stay very close to ANSI C, we allow
ourselves significant deviations from ANSI when it comes to the standard
library. Dusk's I/O is different from a regular UNIX, it handles counted strings
rather than null-terminated strings, etc. The standard library needs
The standard library lives in /comp/c/lib.fs. That library is not loaded
automatically when you load /comp/c/cc.fs. If you need that library, you should
ensure that it's loaded with `?f<< /comp/c/lib.fs`.
## Standard Library API
unsigned char strlen(char *str)
Return the length of string `str`.
void memset(int *addr, char c, int n)
Fills `n` bytes, starting at address `addr`, with character `c`.
int isdigit(char c)
Returns 1 if char is in the 0-9 range, 0 otherwise.
The I/O API is a simple layer over the system I/O described at doc/io. `hdl` is
a regular I/O handle.
char fgetc(int hdl) --> IO :getc
void fputc(char c, int hdl) --> IO :putc
void fputback(char c, int hdl) --> IO :putback
char* freadline(int hdl) --> IO :putback
int fopen(char *path) --> Path :find# + Path :open
void fread(int *addr, int n, int hdl) --> IO :read
void fwrite(int *addr, int n, int hdl) --> IO :write
void fseek(int pos, int hdl) --> File :seek
void fclose(int hdl) --> IO :close
void fputs(char *str, int hdl) --> IO :puts
void puts(char *str) --> fputs(StdOut)
(see below for details about printf/scanf)
void fprintf(... char *fmt, int hdl) --> IO :printf
void printf(... char *fmt) --> fprintf(StdOut)
char* sprintf(... char *fmt)
int fscanf(char *fmt, int hdl) --> see below
int scanf(char *fmt) --> fscanf(StdIn)
int sscanf(char *fmt, char *str)
### printf/scanf and variants
fprintf behaves a bit like the standard one, but supports less formatting
arguments and, most importantly, has a very different argument signature.
The I/O handle goes last, preceded by the formatting string, then preceded by a
variable number of arguments which must match the number of formatting
placeholder in `fmt`, *in reverse order* (this simplifies the implementation
logic a lot). For example, `printf(3, 2, 1, "%b %w %d")` prints `01 0002 3`.
printf formatting arguments are described in doc/io.
fscanf doesn't exist in sys/io yet and is only and CC stdlib. It supports only
the `%d` placeholder. Like printf, it's funky in its arguments, but in the
opposite way. It *pushes* a variable number of arguments, corresponding to the
number of placeholders in the format string, to PS. It then pushes a 1 in case
of scan success.
If it couldn't properly scan the input stream, it pushes *no* argument, only a 0
to indicate failure.
For example, `sscanf("%d %d %d", "5 6 7")` results in PS receiveing elements
`5 6 7 1`, `1` being on top. `sscanf("%d %d %d", "5 6 foo")` yields only a `0`
printf and scanf each have `f` and `s` variants. Without a variant, printing and
scanning is done through StdOut and StdIn (see doc/io). The `f` variant allow us
to choose another target I/O handle.
For the `s` variant, we have a static buffer wrapped around a `MemFile` that is
used. The resulting string is a memory in that buffer and is overwritten at each
`sprintf` and `sscanf` call.
void qsort(unsigned int *addr, unsigned int count)
Sorts an array of `count` integers at address `addr` using the QuickSort
@@ 134,3 134,24 @@ When loading a file to be interpreted by the system (with ":fload" or "f<<"),
those redirections are expected to stay as-is while the file is loaded. For this
reason, unless you know what you are doing, you shouldn't redirect StdIn at the
"interpret" level of a Forth source file.
An interesting augmentation of the I/O subsystem is implemented in lib/fmt.fs,
IO :printf ( ... fmt hdl -- ). It takes a format string, for example "hello %d"
which contains placeholder elements identified by the character '%' followed by
That formatting string must be preceded by a number of arguments equal to the
number of placeholders in the string, in reverse order. Example:
3 2 1 S" hello %d %d %d" StdOut IO :printf --> prints "hello 1 2 3"
The letter following the '%' chars determines how the argument is formatted and
these letters are supported (others produce an error):
d - decimal
x - 4b hexadecimal
w - 2b hexadecimal
b - 1b hexadecimal
s - string