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

The standard library lives in comp/c/lib.fs. That library is not loaded
automatically when you load comp/c.fs. If you need that library, you should
ensure that it's loaded with `needs comp/c/lib`.

## Standard Library API

### Proxied Forth words

void abort();
void quit();
void noop();
void dump(void *a);
void abortmsg(char *msg);
uint min(uint a, uint b);
uint max(uint a, uint b);
void emit(char c);
void stype(char *str);
int zstrlen(char *zstr);
void* allot(uint n);                      --> allot@
void* allot0(uint n);                     --> here# + allot0
void memset(void *addr, char c, int n)    --> cfill
void memcpy(void *dst, void *src, uint n) --> cmove
void emitstacks();                        --> .S
void emithex(uint n);                     --> .x
ushort le_fetch16(void *addr);            --> wle@
uint le_fetch32(void *addr);              --> le@
void le_store16(void *addr, ushort val);  --> wle!
void le_store32(void *addr, uint val);    --> le!
ushort be_fetch16(void *addr);            --> wbe@
uint be_fetch32(void *addr);              --> be@
void be_store16(void *addr, ushort val);  --> wbe!
void be_store32(void *addr, uint val);    --> be!

int llend(int ll);
void llappend(int ll, int elem);
int llcnt(int ll);

### Strings

uchar strlen(char *str)

  Return the length of string `str`. Same as "c@".

uint strequal(char* s1, char *s2)

  Returns 1 if s1 and s2 are equal, otherwise 0. Same as "s=".
  Note that the name of this function is purposefully not strcmp(), which is
  absent from this API. The idea is too avoid porting errors while at the same
  time avoiding this weirdness of having the concept of "s1 < s2", which is way
  too ambiguous to be a core function.

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(void* hdl)                         --> getc
void fputc(void* hdl, char c)                --> putc
int fopen(char *path)                        --> bootfs openpath
int fread(void* hdl, void *addr, int n)      --> read
int freadbuf(void* hdl, void **addr, uint n) --> readbuf
int fwrite(void* hdl, void *addr, int n)     --> write
int fwritebuf(void* hdl, void *addr, int n)  --> writebuf
void fseek(void* hdl, int pos)               --> seek
void fclose(void* hdl)                       --> close
void fputs(void* hdl, char *str)             --> puts
(see below for details about printf)
void fprintf(void* hdl, char *fmt, ...)      --> streamprintf
void printf(char *fmt, ...)                  --> printf
char* sprintf(char *fmt, ...)                --> sprintf

### 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 and variants

fprintf behaves a bit like the standard one, but supports less formatting
arguments.

The I/O handle goes first, followed by the formatting string, then followed by a
variable number of arguments which must match the number of formatting
placeholder in `fmt`. For example, `printf("%b %w %d", 1, 2, 3)` prints
`01 0002 3`.

printf formatting arguments are described in [doc/lib/fmt].

printf has `f` and `s` variants. Without a variant, printing is done through
rtype. The `f` variant allow us to choose another target stream.

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

### nbelem()

nbelem() is an immediate function that returns the number of elements in an
array. It errors out if the expression doesn't yield an array. Example:

  int x[42];
  return nbelem(x); // returns 42

  int *x;
  return nbelem(x); // error! not an array

### Others

void assert(uint n)
  If "n" is zero, abort with message "assertion error".
