@@@ wip type definitions in manpage synopses
authorMark Wooding <mdw@distorted.org.uk>
Wed, 10 May 2023 01:26:19 +0000 (02:26 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Wed, 10 May 2023 23:10:03 +0000 (00:10 +0100)
29 files changed:
buf/lbuf.3
buf/pkbuf.3
codec/base64.3
codec/codec.3
codec/url.3
hash/unihash.3
mem/arena.3
mem/pool.3
mem/sub.3
sel/bres.3
sel/conn.3
sel/ident.3
sel/sel.3
sel/selbuf.3
sel/selpk.3
sel/sig.3
struct/assoc.3
struct/atom.3
struct/buf.3
struct/darray.3
struct/dspool.3
struct/dstr.3
struct/hash.3
struct/sym.3
sys/fwatch.3
sys/lock.3
sys/mdup.3
test/testrig.3
ui/mdwopt.3

index 6595f30..d1663a2 100644 (file)
@@ -13,6 +13,20 @@ lbuf \- split lines out of asynchronously received blocks
 .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 );
@@ -161,12 +175,7 @@ and return only the initial portion.  It will ignore the rest of the
 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
index 80eed4b..01c4240 100644 (file)
@@ -13,6 +13,19 @@ pkbuf \- split packets out of asynchronously received blocks
 .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 );
@@ -140,15 +153,8 @@ to the packet buffer and a size
 .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
index 8f5c44b..39de50d 100644 (file)
@@ -17,6 +17,12 @@ base64, base32, hex \- obsolete binary encoding functions
 .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 );
@@ -25,6 +31,12 @@ base64, base32, hex \- obsolete binary encoding functions
 .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 );
@@ -33,6 +45,12 @@ base64, base32, hex \- obsolete binary encoding functions
 .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 );
index fd797c5..ee5a447 100644 (file)
@@ -18,6 +18,43 @@ codec \- binary encoding and decoding
 .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;"
index f68bf33..c3b4e98 100644 (file)
@@ -22,6 +22,20 @@ url \- manipulation of form-urlencoded strings
 .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 ,
index 28cb580..c6b4c58 100644 (file)
@@ -45,6 +45,8 @@ unihash \- simple and efficient universal hashing for hashtables
 .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 );
index 2a36820..3baf4e6 100644 (file)
@@ -15,6 +15,17 @@ arena \- control of memory allocation
 .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;"
 
@@ -86,13 +97,13 @@ The
 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 ,
@@ -106,11 +117,11 @@ bytes long.  You can use
 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
index 4881bf1..5acc7b2 100644 (file)
@@ -29,6 +29,18 @@ pool \- resource pool management
 .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 );
@@ -119,15 +131,9 @@ for memory allocation.
 .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
index b1f6083..c41041f 100644 (file)
--- a/mem/sub.3
+++ b/mem/sub.3
@@ -31,6 +31,8 @@ sub \- efficient allocation and freeing of small blocks
 .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 );
index 0a0dd7a..a18e24e 100644 (file)
@@ -11,6 +11,8 @@ bres \- background name resolver
 .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 ),
index 60008e5..f115605 100644 (file)
@@ -9,6 +9,8 @@ conn \- selector for nonblocking connections
 .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 ),
index c6c14f5..326d508 100644 (file)
@@ -9,6 +9,23 @@ ident \- identd (RFC931) client
 .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 ,
index 0442b37..021b1c9 100644 (file)
--- a/sel/sel.3
+++ b/sel/sel.3
@@ -17,6 +17,31 @@ sel \- low level interface for waiting for I/O
 .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(
index a704366..032f9f1 100644 (file)
@@ -11,6 +11,8 @@ selbuf \- line-buffering input selector
 .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 );
index 1c8e6b1..952c84f 100644 (file)
@@ -11,6 +11,8 @@ selpk \- packet-buffering input selector
 .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 );
index f9effa9..68b58c9 100644 (file)
--- a/sel/sig.3
+++ b/sel/sig.3
@@ -9,6 +9,8 @@ sig \- more controlled signal handling
 .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 );
index 5b4ead0..cbec2c2 100644 (file)
@@ -27,6 +27,9 @@ assoc \- tables indexed by atoms
 .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 );
 
index 65c655a..e5ecf00 100644 (file)
@@ -36,6 +36,9 @@ atom \- atom table manager
 .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 );
 
index 8964a09..10b52cf 100644 (file)
@@ -152,6 +152,8 @@ buf \- reading and writing stuff in buffers
 .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 );
index 8f7953c..a48bedc 100644 (file)
@@ -58,8 +58,18 @@ darray \- dense, dynamically resizing arrays
 .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 );
 
index 59e91b4..9d2ab00 100644 (file)
@@ -26,6 +26,8 @@ dspool \- pools of preallocated dynamic strings
 .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 );
index e59f370..1aadd35 100644 (file)
@@ -53,6 +53,9 @@ dstr \- a simple dynamic string type
 .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 );
@@ -70,7 +73,6 @@ dstr \- a simple dynamic string type
 .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 );
@@ -98,15 +100,7 @@ multiple times.
 .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
index 6093258..19522ee 100644 (file)
@@ -38,6 +38,19 @@ hash \- low-level hashtable implementation
 .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 );
index c566017..045ea54 100644 (file)
@@ -29,6 +29,10 @@ sym \- symbol table manager
 .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 );
 
index c2329ea..9afe273 100644 (file)
@@ -10,6 +10,8 @@ fwatch \- watch a file for changes
 .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 );
index 75460b4..2d80fad 100644 (file)
@@ -7,6 +7,12 @@ lock \- oversimplified file locking interface
 .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
index 9ce3b85..1e1b836 100644 (file)
@@ -26,6 +26,11 @@ mdup \- renumber file descriptors
 .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
@@ -41,16 +46,7 @@ to a vector of
 .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
index 77cdfce..07e1f48 100644 (file)
@@ -19,6 +19,35 @@ testrig \- generic test rig
 .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 ,
@@ -123,14 +152,9 @@ following character.
 .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
@@ -145,21 +169,15 @@ required and the function to call in order to test the system against
 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
@@ -177,14 +195,9 @@ designated field type, and then passing the completed array of fields 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
index 7afd2d2..f186e7d 100644 (file)
@@ -7,6 +7,39 @@ mdwopt \- command-line option parser
 .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 ,