.nf
.B "#include <mLib/lbuf.h>"
+.B "enum {"
+.B "\h'4n'LBUF_CRLF,"
+.B "\h'4n'LBUF_STRICTCRLF,"
+.B "\h'4n'..."
+.B "};"
+.B "#define LBUF_ENABLE ..."
+
+.B "typedef struct {"
+.B "\h'4n'unsigned f;"
+.B "\h'4n'..."
+.B "} lbuf;"
+
+.B "typedef void lbuf_func(char *" s ", size_t " len ", void *" p );
+
.BI "void lbuf_flush(lbuf *" b ", char *" p ", size_t " len );
.BI "void lbuf_close(lbuf *" b );
.BI "size_t lbuf_free(lbuf *" b ", char **" p );
line completely.
.SS "Line-handler functions"
Completed lines, as already said, are passed to the caller's
-line-handler function. This function has the signature
-.IP
-.B "void"
-.IB func "(char *" s ", size_t " len ", void *" p );
-.PP
-It is given three arguments: the address
+line-handler function. It is given three arguments: the address
.I s
of the line which has just been read; the length
.I len
.nf
.B "#include <mLib/pkbuf.h>"
+.B "enum {"
+.B "\h'4n'PKBUF_ENABLE = ..."
+.B "};"
+
+.B "typedef struct {"
+.B "\h'4n'unsigned f;"
+.B "\h'4n'..."
+.B "} pkbuf;"
+
+.ds mT \fBtypedef void pkbuf_func(
+.B "\*(mToctet *" b ", size_t " sz ", pkbuf *" p ,
+.BI "\h'\w'\*(mT'u'size_t *" keep ", void *" p );
+
.BI "void pkbuf_flush(pkbuf *" pk ", octet *" p ", size_t " len );
.BI "void pkbuf_close(pkbuf *" pk );
.BI "size_t pkbuf_free(pkbuf *" pk ", octet **" p );
.I sz
of the packet.
.PP
-When enough data has arrived, the packet-handler function is called.
-This has the signature
-.IP
-.nf
-.BI "void (*" func ")(octet *" b ", size_t " sz ", pkbuf *" p ,
-.BI " size_t *" keep ", void *" p );
-.fi
-.PP
-It is passed:
+When enough data has arrived, the packet-handler function is called. It
+is passed:
.TP
.BI "octet *" b
A pointer to the packet data in the buffer, or zero to signify
.B "#include <mLib/base32.h>"
.B "#include <mLib/hex.h>"
+.B "typedef struct {"
+.B "\h'4n'char *indent;"
+.B "\h'4n'unsigned maxline;"
+.B "\h'4n'..."
+.B "} base64_ctx;"
+
.BI "void base64_encode(base64_ctx *" ctx ,
.BI " const void *" p ", size_t " sz ,
.BI " dstr *" d );
.BI " dstr *" d );
.BI "void base64_init(base64_ctx *" ctx );
+.B "typedef struct {"
+.B "\h'4n'char *indent;"
+.B "\h'4n'unsigned maxline;"
+.B "\h'4n'..."
+.B "} base32_ctx;"
+
.BI "void base32_encode(base32_ctx *" ctx ,
.BI " const void *" p ", size_t " sz ,
.BI " dstr *" d );
.BI " dstr *" d );
.BI "void base32_init(base32_ctx *" ctx );
+.B "typedef struct {"
+.B "\h'4n'char *indent;"
+.B "\h'4n'unsigned maxline;"
+.B "\h'4n'..."
+.B "} hex_ctx;"
+
.BI "void hex_encode(hex_ctx *" ctx ,
.BI " const void *" p ", size_t " sz ,
.BI " dstr *" d );
.B "#include <mLib/base32.h>"
.B "#include <mLib/hex.h>"
+.B "#define CDCF_LOWERC ..."
+.B "#define CDCF_IGNCASE ..."
+.B "#define CDCF_NOEQPAD ..."
+.B "#define CDCF_IGNEQPAD ..."
+.B "#define CDCF_IGNEQMID ..."
+.B "#define CDCF_IGNZPAD ..."
+.B "#define CDCF_IGNNEWL ..."
+.B "#define CDCF_IGNINVCH ..."
+.B "#define CDCF_IGNSPC ..."
+.B "#define CDCF_IGNJUNK ..."
+
+.B "enum {"
+.B "\h'4n'CDCERR_OK = ...,"
+.B "\h'4n'CDCERR_INVCH = ...,"
+.B "\h'4n'CDCERR_INVEQPAD = ...,"
+.B "\h'4n'CDCERR_INVZPAD = ..."
+.B "};"
+
+.B "typedef struct {"
+.B "\h'4n'const char *name;"
+.ds mT \fBcodec *(*encoder)(
+.BI "\h'4n'\*(mTunsigned " flags ,
+.BI "\h'4n+\w'\*(mT'u'const char *" indent ", unsigned " maxlen );
+.BI "\h'4n'codec *(*decoder)(unsigned " flags );
+.B "\h'4n'...\&"
+.B "} codec_class;"
+
+.B "typedef struct {"
+.B "\h'4n'const codec_ops *ops;"
+.B "} codec;"
+
+.B "typedef struct {"
+.B "\h'4n'const codec_class *c;"
+.BI "\h'4n'int (*code)(codec *" c ", const void *" p ", size_t " sz ", dstr *" d );
+.BI "\h'4n'void (*destroy)(codec *" c );
+.B "} codec_ops;"
+
.B "codec_class null_codec_class;"
.B "codec_class base64_class, file64_class, base64url_class;"
.B "codec_class base32_class, base32hex_class;"
.nf
.B "#include <mLib/url.h>"
+.B "typedef struct {"
+.B "\h'4n'unsigned f;"
+.B "\h'4n'..."
+.B "} url_ectx;"
+
+.B "typedef struct {"
+.B "\h'4n'unsigned f;"
+.B "\h'4n'..."
+.B "} url_dctx;"
+
+.B "#define URLF_STRICT ..."
+.B "#define URLF_LAX ..."
+.B "#define URLF_SEMI ..."
+
.BI "void url_initenc(url_ectx *" ctx );
.ds mT \fBvoid url_enc(
.BI "\*(mTurl_ectx *" ctx ", dstr *" d ,
.nf
.B "#include <mLib/unihash.h>"
+.B "typedef struct { ...\& } unihash_info;"
+
.B "unihash_info unihash_global;"
.BI "void unihash_setkey(unihash_info *" i ", uint32 " k );
.nf
.B "#include <mLib/arena.h>"
+.B "typedef struct {"
+.B "\h'4n'const struct arena_ops *ops";
+.B "} arena;"
+
+.B "typedef struct {"
+.BI "\h'4n'void *(*alloc)(arena *" a ", size_t " sz );
+.BI "\h'4n'void *(*realloc)(arena *" a ", void *" p ", size_t " sz ", size_t " osz );
+.BI "\h'4n'void *(*free)(arena *" a ", void *" p );
+.BI "\h'4n'void *(*purge)(arena *" a );
+.B "} arena_ops;"
+
.BI "arena *arena_global;"
.BI "arena arena_stdlib;"
table contains function pointers which are called to perform various
memory allocation tasks:
.TP
-.BI "void *(*" alloc ")(arena *" a ", size_t " sz );
+.BI "void *(*alloc)(arena *" a ", size_t " sz );
Allocates a block of memory, of at least
.I sz
bytes in size, appropriately aligned, and returns its address.
.nf
.TP
-.BI "void *(*" realloc ")(arena *" a ", void *" p ", size_t " sz ", size_t " osz );
+.BI "void *(*realloc)(arena *" a ", void *" p ", size_t " sz ", size_t " osz );
.fi
Resizes the block pointed to by
.IR p ,
here, to fake resizing by allocating, copying and freeing, if your arena
doesn't make doing something more efficient easy.
.TP
-.BI "void (*" free ")(arena *" a ", void *" p );
+.BI "void (*free)(arena *" a ", void *" p );
Frees the block pointed to by
.IR p .
.TP
-.BI "void (*" purge ")(arena *" a );
+.BI "void (*purge)(arena *" a );
Frees all blocks in the arena. Used when the arena is being destroyed.
.PP
The behaviour of the
.nf
.B "#include <mLib/pool.h>"
+.B "typedef struct { ...\& } pool;"
+
+.B "typedef struct {"
+.B "\h'4n'pool_resource *next;"
+.BI "\h'4n'void (*destroy)(pool_resource *" r );
+.B "} pool_resource;"
+
+.B "typedef struct {"
+.B "\h'4n'FILE *fp;"
+.B "\h'4n'..."
+.B "} pool_file;"
+
.BI "void pool_init(pool *" p ", arena *" a );
.BI "pool *pool_create(arena *" a );
.BI "pool *pool_sub(pool *" p );
.SS "Other resources"
Pool resources have a header of type
.B pool_resource
-with the structure:
-.VS
-typedef struct pool_resource {
- struct pool_resource *next;
- void (*destroy)(struct pool_resource */*r*/);
-} pool_resource;
-.VE
-Resources are added to the pool by passing a pointer to the pool, the
-resource block and a destruction function to
+with the structure shown in the synopsis. Resources are added to the
+pool by passing a pointer to the pool, the resource block and a
+destruction function to
.BR pool_add .
.PP
If your resource is freed before the pool is destroyed, manually zero
.nf
.B "#include <mLib/sub.h>"
+.B "typedef struct { ...\& } subarena;"
+
.BI "void subarena_create(subarena *" s ", arena *" a );
.BI "void subarena_destroy(subarena *" s );
.BI "void subarena_alloc(subarena *" s ", size_t " sz );
.nf
.B "#include <mLib/bres.h>"
+.B "typedef struct { ...\& } bres_client;"
+
.ds mT \fBvoid bres_byname(
.BI "\*(mTbres_client *" rc ", const char *" name ,
.BI "\h'\w'\*(mT'u'void (*" func ")(struct hostent *" h ", void *" p ),
.nf
.B "#include <mLib/conn.h>"
+.B "typedef struct { ...\& } conn;"
+
.ds mT \fBint conn_fd(
.BI "\*(mTconn *" c ", sel_state *" s ", int " fd ,
.BI "\h'\w'\*(mT'u'void (*" func ")(int " fd ", void *" p ),
.nf
.B "#include <mLib/ident>"
+.B "typedef struct { ...\& } ident_request;"
+
+.B "enum ["
+.B "\h'4n'IDENT_USERID = ...,"
+.B "\h'4n'IDENT_ERROR = ...,"
+.B "\h'4n'IDENT_BAD = ..."
+.B "};"
+
+.B "typedef struct {"
+.B "\h'4n'unsigned short sport, dport;"
+.B "\h'4n'unsigned type;"
+.B "\h'4n'union {"
+.B "\h'8n'struct { char *os, *user; } userid;"
+.B "\h'8n'char *error;"
+.B "\h'4n'} u;"
+.B "} ident_reply;"
+
.BI "void ident_abort(ident_request *" rq );
.ds mT \fBvoid ident(
.BI "\*(mTident_request *" rq ", sel_state *" s ,
.nf
.B "#include <mLib/sel.h>"
+.B "enum {"
+.B "\h'4n'SEL_READ = ...,"
+.B "\h'4n'SEL_WRITE = ...,"
+.B "\h'4n'SEL_EXC = ...,"
+.B "\h'4n'SEL_MODES = ..."
+.B "};"
+
+.B "typedef struct { ...\& } sel_state;"
+.B "typedef struct { ...\& } sel_timer;"
+.B "typedef struct { ...\& } sel_hook;"
+
+.B "typedef struct {"
+.B "\h'4n'int fd;"
+.B "\h'4n'..."
+.B "} sel_file;"
+
+.B "typedef struct {"
+.B "\h'4n'int maxfd;"
+.B "\h'4n'fd_set fd[SEL_MODES];"
+.B "\h'4n'struct timeval tv, *tvp;"
+.B "\h'4n'struct timeval now;"
+.B "} sel_args;"
+
+.BI "typedef void (*sel_hookfn)(sel_state *" s ", sel_args *" a ", void *" p );
+
.BI "void sel_init(sel_state *" s );
.ds mT \fBvoid sel_initfile(
.nf
.B "#include <mLib/selbuf.h>"
+.B "typedef struct { ...\& } selbuf;"
+
.BI "void selbuf_enable(selbuf *" b );
.BI "void selbuf_disable(selbuf *" b );
.BI "void selbuf_setsize(selbuf *" b ", size_t " sz );
.nf
.B "#include <mLib/selpk.h>"
+.B "typedef struct { ...\& } selpk;"
+
.BI "void selpk_enable(selpk *" pk );
.BI "void selpk_disable(selpk *" pk );
.BI "void selpk_want(selpk *" pk ", size_t " sz );
.nf
.B "#include <mLib/sig.h>"
+.B "typedef struct { ...\& } sig;"
+
.ds mT \fBvoid sig_add(
.BI "\*(mTsig *" s ", int " n ,
.BI "\h'\w'\*(mT'u'void (*" proc ")(int " n ", void *" p "), void *" p );
.nf
.B "#include <mLib/assoc.h>"
+.B "typedef struct { ...\& } assoc_table;"
+.B "typedef struct { ...\& } assoc_base;"
+
.BI "void assoc_create(assoc_table *" t );
.BI "void assoc_destroy(assoc_table *" t );
.nf
.B "#include <mLib/atom.h>"
+.B "typedef struct { ...\& } atom_table;"
+.B "typedef struct { ...\& } atom;"
+
.BI "void atom_createtable(atom_table *" t );
.BI "void atom_destroytable(atom_table *" t );
.nf
.B "#include <mLib/dstr.h>"
+.B "typedef struct { ...\& } buf;"
+
.BI "void buf_init(buf *" b ", void *" p ", size_t " sz );
.BI "void buf_flip(buf *" b );
.BI "octet *BBASE(buf *" b );
.nf
.B "#include <mLib/darray.h>"
+.B "typedef struct {"
+.B "\h'4n'size_t sz, len, off;"
+.B "\h'4n'unsigned push, unshift;"
+.B "\h'4n'arena *a;"
+.B "} da_base;"
+
+.B "#define DA_INIT ..."
+
+.B "#define DAEXC_UFLOW EXC_ALLOCN(EXC_MLIB, ...)"
+.B "#define DAEXC_OFLOW EXC_ALLOCN(EXC_MLIB, ...)"
+
.BI DA_DECL( type_v ", " type );
-.IB type_v " " a " = DA_INIT;"
.BI "void DA_CREATE(" type_v " *" a );
.BI "void DA_DESTROY(" type_v " *" a );
.nf
.B "#include <mLib/dspool.h>"
+.B "typedef struct { ...\& } dspool;"
+
.BI "void dspool_create(dspool *" p ", size_t " isz );
.BI "void dspool_destroy(dspool *" p );
.BI "dstr *dspool_get(dspool *" p );
.nf
.B "#include <mLib/dstr.h>"
+.B "typedef struct { ...\& } dstr;"
+.B "#define DSTR_INIT ..."
+
.BI "void dstr_create(dstr *" d );
.BI "void dstr_destroy(dstr *" d );
.BI "void dstr_reset(dstr *" d );
.BI "int dstr_putline(dstr *" d ", FILE *" fp );
.BI "size_t dstr_write(const dstr *" d ", FILE *" fp );
-.BI "dstr " d " = DSTR_INIT;"
.BI "void DCREATE(dstr *" d );
.BI "void DDESTROY(dstr *" d );
.BI "void DRESET(dstr *" d );
.SS "Underlying type"
A
.B dstr
-object is a small structure with the following members:
-.VS
-typedef struct dstr {
- char *buf; /* Pointer to string buffer */
- size_t sz; /* Size of the buffer */
- size_t len; /* Length of the string */
- arena *a; /* Pointer to arena */
-} dstr;
-.VE
+object is a small structure with the following members.
The
.B buf
member points to the actual character data in the string. The data may
.nf
.B "#include <mLib/hash.h>"
+.B "typedef struct {"
+.B "\h'4n'uint32 mask;"
+.B "\h'4n'hash_base **v;"
+.B "\h'4n'arena *a;"
+.B "} hash_table;"
+
+.B "typedef struct {"
+.B "\h'4n'hash_base *next;"
+.B "\h'4n'uint32 hash;"
+.B "} hash_base;"
+
+.B "typedef struct { ...\& } hash_iter;"
+
.BI "void hash_create(hash_table *" t ", size_t " n );
.BI "void hash_destroy(hash_table *" t );
.BI "hash_base **hash_bin(hash_table *" t ", uint32 " hash );
.nf
.B "#include <mLib/sym.h>"
+.B "type struct { ...\& } sym_table;"
+.B "type struct { ...\& } sym_base;"
+.B "type struct { ...\& } sym_iter;"
+
.BI "void sym_create(sym_table *" t );
.BI "void sym_destroy(sym_table *" t );
.nf
.B "#include <mLib/fwatch.h>"
+.B "typedef struct { ...\& } fwatch;"
+
.BI "void fwatch_init(fwatch *" f ", const char *" name );
.BI "void fwatch_initfd(fwatch *" f ", int " fd );
.BI "int fwatch_update(fwatch *" f ", const char *" name );
.nf
.B "#include <mLib/lock.h>"
+.B "enum {"
+.B "\h'4n'LOCK_UNLOCK = ...,"
+.B "\h'4n'LOCK_EXCL = ...,"
+.B "\h'4n'LOCK_NONEXCL = ..."
+.B "};"
+
.BI "int lock_file(int " fd ", unsigned " how );
.fi
.SH DESCRIPTION
.nf
.B "#include <mLib/mdup.h>"
+.B "typedef struct {"
+.B "\h'4'int cur;"
+.B "\h'4n'int want;"
+.B "} mdup_fd;"
+
.BI "int mdup(mdup_fd *" v ", size_t " n ");"
.fi
.SH DESCRIPTION
.B mdup_fd
structures, and the length
.I n
-of this vector, in elements. The
-.B mdup_fd
-structure is defined as
-.VS
-typedef struct mdup_fd {
- int cur;
- int want;
-} mdup_fd;
-.VE
-Each `slot' (element) in the vector
+of this vector, in elements. Each `slot' (element) in the vector
.I v
represents a file. The slot's
.B cur
.nf
.B "#include <mLib/testrig.h>"
+.B "#define TEST_FIELDMAX ..."
+
+.B "typedef struct {"
+.B "\h'4n'unsigned tests, failed;"
+.B "} test_results";
+
+.B "typedef struct {"
+.BI "\h'4n'void (*cvt)(const char *" buf ", dstr *" d );
+.BI "\h'4n'void (*dump)(dstr *" d ", FILE *" fp );
+.B "} test_type";
+
+.B "typedef struct {"
+.B "\h'4n'const char *name;"
+.BI "\h'4n'void (*test)(dstr " dv "[]);"
+.B "\h'4n'const test_type *f[TEST_FIELDMAX];"
+.B "} test_chunk";
+
+.B "typedef struct {"
+.B "\h'4n'const char *name;"
+.B "\h'4n'const test_chunk *chunks;"
+.B "} test_suite";
+
+.B "const test_type type_hex;"
+.B "const test_type type_string;"
+.B "const test_type type_int;"
+.B "const test_type type_long;"
+.B "const test_type type_ulong;"
+.B "const test_type type_uint32;"
+
.ds mT \fBint test_do(
.BI "\*(mTconst test_suite " suite [],
.BI "\h'\w'\*(mT'u'FILE *" fp ,
.SS "Suite definitions"
A
.I suite definition
-is described by the structure
-.VS
-typedef struct test_suite {
- const char *name; /* Name of this suite */
- const test_chunk *chunks; /* Pointer to chunks */
-} test_suite;
-.VE
-The
+is described by the
+.B test_suite
+structure. The
.I suite
argument to
.B test_do
that test vector. The array is terminated by a chunk definition whose
name field is a null pointer.
.PP
-A chunk definition is described by the following structure:
-.VS
-typedef struct test_chunk {
- const char *name; /* Name of this chunk */
- int (*test)(dstr dv[]); /* Test verification function */
- test_type *f[TEST_FIELDMAX]; /* Field definitions */
-} test_chunk;
-.VE
-The members of this structure are as follows:
+A chunk definition is described by the
+.B test_chunk
+structure. The members of this structure are as follows:
.TP
.B "const char *name"
The name of the chunk described by this chunk definition, or null if
this is the termination marker.
.TP
-.B "int (*test)(dstr dv[])"
+.BI "int (*test)(dstr " dv "[])"
The test function. It is passed an array of dynamic strings, one for
each field, and must return nonzero if the test succeeded or zero if the
test failed. On success, the function should not write anything to
the test function.
.SS "Field types"
A field type describes how a field is to be read and written. A field
-type is described by a structure:
-.VS
-typedef struct test_type {
- void (*cvt)(const char *buf, dstr *d);
- void (*dump)(dstr *d, FILE *fp);
-} test_type;
-.VE
-The
+type is described by a
+.B test_type
+structure. The
.B cvt
member is a function called to read an input string stored in
.B buf
.nf
.B "#include <mLib/mdwopt.h>"
+.B "typedef struct {"
+.B "\h'4n'char *arg, *prog;"
+.B "\h'4n'int opt, ind, err;"
+.B "\h'4n'..."
+.B "} mdwopt_data;"
+
+.B "char *optarg, optprog;"
+.B "int optopt, opterr, optind;"
+
+.B "struct option {"
+.B "\h'4n'const char *name;"
+.B "\h'4n'int has_arg;"
+.B "\h'4n'int *flag;"
+.B "\h'4n'int val;"
+.B "};"
+
+.B "#define OPTF_NOARG = ..."
+.B "#define OPTF_ARGREQ = ..."
+.B "#define OPTF_ARGOPT = ..."
+.B "#define OPTF_ARG = ..."
+.B "#define OPTF_SWITCH = ..."
+.B "#define OPTF_NEGATE = ..."
+
+.B "#define OPTF_NOLONGS = ..."
+.B "#define OPTF_NOSHORTS = ..."
+.B "#define OPTF_NUMBERS = ..."
+.B "#define OPTF_NEGATION = ..."
+.B "#define OPTF_ENVVAR = ..."
+.B "#define OPTF_NOPROGNAME = ..."
+.B "#define OPTF_NEGNUMBER = ..."
+
+.B "#define OPTF_NEGATED = ..."
+
.ds mT \fBint mdwopt(
.BI "\*(mTint " argc ", char *const *" argv ,
.BI "\h'\w'\*(mT'u'const char *" shortopt ,