X-Git-Url: https://git.distorted.org.uk/~mdw/mLib/blobdiff_plain/c5e0e40378b7e209521d2e9a52f055575a948313..814e42ff7421d66c0a2e33af5765afa2078bc18f:/test/tvec-main.c diff --git a/test/tvec-main.c b/test/tvec-main.c index a9cff8f..fc1a2ae 100644 --- a/test/tvec-main.c +++ b/test/tvec-main.c @@ -47,6 +47,7 @@ /*----- Main code ---------------------------------------------------------*/ +/* Table of output formats. */ static const struct outform { const char *name; struct tvec_output *(*makefn)(FILE *fp); @@ -56,9 +57,20 @@ static const struct outform { { 0, 0 } }; +/* Configuration for ad-hoc testing. */ const struct tvec_config tvec_adhocconfig = { 0, 1, 1, sizeof(struct tvec_reg) }; +/* --- @find_outform@ --- + * + * Arguments: @const char *p@ = output name + * + * Returns: Pointer to output format record. + * + * Use: Looks up an output format by name. Reports a fatal error if + * no matching record is found. + */ + static const struct outform *find_outform(const char *p) { const struct outform *best = 0, *of; @@ -78,6 +90,15 @@ static const struct outform *find_outform(const char *p) else die(2, "unknown output format `%s'", optarg); } +/* --- @version@, @usage@, @help@ --- * + * + * Arguments: @FILE *fp@ = stream to write on + * + * Returns: --- + * + * Use: Output information about the program. + */ + static void version(FILE *fp) { pquis(fp, "$, mLib test-vector framework version " VERSION "\n"); } @@ -102,6 +123,21 @@ Options:\n\ ", fp); } +/* --- @tvec_parseargs@ --- * + * + * Arguments: @int argc@ = number of command-line arguments + * @char *argv[]@ = vector of argument strings + * @struct tvec_state *tv_out@ = test vector state to initialize + * @int *argpos_out@ = where to leave unread argument index + * @const struct tvec_config *cofig@ = test vector configuration + * + * Returns: --- + * + * Use: Parse arguments and set up the test vector state @*tv_out@. + * If errors occur, print messages to standard error and exit + * with status 2. + */ + void tvec_parseargs(int argc, char *argv[], struct tvec_state *tv_out, int *argpos_out, const struct tvec_config *config) { @@ -158,6 +194,19 @@ void tvec_parseargs(int argc, char *argv[], struct tvec_state *tv_out, tvec_begin(tv_out, config, o); *argpos_out = optind; } +/* --- @tvec_readstdin@, @tvec_readfile@, @tvec_readarg@ --- * + * + * Arguments: @struct tvec_state *tv@ = test vector state + * @const char *file@ = pathname of file to read + * @const char *arg@ = argument to interpret + * + * Returns: Zero on success, @-1@ on error. + * + * Use: Read test vector data from stdin or a named file. The + * @tvec_readarg@ function reads from stdin if @arg@ is `%|-|%', + * and from the named file otherwise. + */ + int tvec_readstdin(struct tvec_state *tv) { return (tvec_read(tv, "", stdin)); } @@ -179,16 +228,39 @@ end: return (rc); } -int tvec_readdflt(struct tvec_state *tv, const char *file) +int tvec_readarg(struct tvec_state *tv, const char *arg) +{ + int rc; + + if (STRCMP(arg, ==, "-")) rc = tvec_readstdin(tv); + else rc = tvec_readfile(tv, arg); + return (rc); +} + +/* --- @tvec_readdflt@ --- * + * + * Arguments: @struct tvec_state *tv@ = test vector state + * @const char *dflt@ = defsault filename or null + * + * Returns: Zero on success, @-1@ on error. + * + * Use: Reads from the default test vector data. If @file@ is null, + * then read from standard input, unless that's a terminal; if + * @file@ is not null, then read the named file, looking in the + * directory named by the `%|srcdir|%' environment variable if + * that's set, or otherwise in the current directory. + */ + +int tvec_readdflt(struct tvec_state *tv, const char *dflt) { dstr d = DSTR_INIT; const char *p; int rc; - if (file) { + if (dflt) { p = getenv("srcdir"); - if (p) { dstr_putf(&d, "%s/%s", p, file); file = d.buf; } - rc = tvec_readfile(tv, file); + if (p) { dstr_putf(&d, "%s/%s", p, dflt); dflt = d.buf; } + rc = tvec_readfile(tv, dflt); } else if (isatty(0)) rc = tvec_error(tv, "use `-' to force reading from interactive stdin"); else @@ -197,14 +269,21 @@ int tvec_readdflt(struct tvec_state *tv, const char *file) return (rc); } -int tvec_readarg(struct tvec_state *tv, const char *arg) -{ - int rc; - - if (STRCMP(arg, ==, "-")) rc = tvec_readstdin(tv); - else rc = tvec_readfile(tv, arg); - return (rc); -} +/* --- @tvec_readargs@ --- * + * + * Arguments: @int argc@ = number of command-line arguments + * @char *argv[]@ = vector of argument strings + * @struct tvec_state *tv@ = test vector state + * @int *argpos_inout@ = current argument position (updated) + * @const char *dflt@ = default filename or null + * + * Returns: Zero on success, @-1@ on error. + * + * Use: Reads from the sources indicated by the command-line + * arguments, in order, interpreting each as for @tvec_readarg@; + * if no arguments are given then read from @dflt@ as for + * @tvec_readdflt@. + */ int tvec_readargs(int argc, char *argv[], struct tvec_state *tv, int *argpos_inout, const char *dflt) @@ -212,7 +291,8 @@ int tvec_readargs(int argc, char *argv[], struct tvec_state *tv, int i = *argpos_inout; int rc; - if (i == argc) rc = tvec_readdflt(tv, dflt); + if (i == argc) + rc = tvec_readdflt(tv, dflt); else { rc = 0; while (i < argc) @@ -222,6 +302,21 @@ int tvec_readargs(int argc, char *argv[], struct tvec_state *tv, return (rc); } +/* --- @tvec_main@ --- * + * + * Arguments: @int argc@ = number of command-line arguments + * @char *argv[]@ = vector of argument strings + * @const struct tvec_config *cofig@ = test vector configuration + * @const char *dflt@ = default filename or null + * + * Returns: Exit code. + * + * Use: All-in-one test vector front-end. Parse options from the + * command-line as for @tvec_parseargs@, and then process the + * remaining positional arguments as for @tvec_readargs@. The + * function constructs and disposes of a test vector state. + */ + int tvec_main(int argc, char *argv[], const struct tvec_config *config, const char *dflt) {