# DuskCC standard library

Prerequisites: sys/io

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
adjustements.

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

### Proxied Forth words

void abort();
void abortmsg(char *msg);
uint min(uint a, uint b);
uint max(uint a, uint b);
void stype(char *str);
int Console();   --> console :self
uchar stdin();
void stdout(uchar c);

### Strings

uchar 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.

### I/O

The I/O API is a simple layer over the system I/O. `hdl` is a regular I/O
handle.

int 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
int freadbuf(int **addr, int n, int hdl) --> IO :readbuf
void fwrite(int *addr, int n, int hdl)   --> IO :write
int fwritebuf(int *addr, int n, int hdl) --> IO :writebuf
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)                     --> console :puts
(see below for details about printf/scanf)
void fprintf(... char *fmt, int hdl)     --> IO :printf
void printf(... char *fmt)               --> console :printf
char* sprintf(... char *fmt)
int fscanf(char *fmt, int hdl)           --> see below
int scanf(char *fmt)                     --> fscanf(console readio)
int sscanf(char *fmt, char *str)

### freadbuf

This function is special because :readbuf returns two arguments. The return
value of freadbuf() is "read-n", but "a" is returned through a pointer to an
address which you supply as an argument. If :readbuf is successful, that the
resulting address is written there. Otherwise, nothing is written.

### 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/lib/fmt].

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`
to PS.

printf and scanf each have `f` and `s` variants. Without a variant, printing and
scanning is done through Console. The `f` variant allow us to choose another
target I/O handle.

For the `s` variant, we have a static buffer wrapped around a `MemIO` that is
used. The resulting string is a memory in that buffer and is overwritten at each
`sprintf` and `sscanf` call.

### Others

void qsort(uint *addr, uint count)

    Sorts an array of `count` integers at address `addr` using the QuickSort
    algorithm.
