3 * Main entry point for test-vector processing
5 * (c) 2023 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of the mLib utilities library.
12 * mLib is free software: you can redistribute it and/or modify it under
13 * the terms of the GNU Library General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or (at
15 * your option) any later version.
17 * mLib is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
20 * License for more details.
22 * You should have received a copy of the GNU Library General Public
23 * License along with mLib. If not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
28 /*----- Header files ------------------------------------------------------*/
48 /*----- Main code ---------------------------------------------------------*/
50 static const struct outform {
52 struct tvec_output *(*makefn)(FILE *fp);
54 { "human", tvec_humanoutput },
55 { "tap", tvec_tapoutput },
59 const struct tvec_config tvec_adhocconfig =
60 { 0, 1, 1, sizeof(struct tvec_reg) };
62 static const struct outform *find_outform(const char *p)
64 const struct outform *best = 0, *of;
67 for (of = outtab; of->name; of++)
68 if (!STRNCMP(p, ==, of->name, n))
70 else if (!of->name[n])
73 die(2, "ambiguous output format name (`%s' or `%s'?)",
74 best->name, of->name);
77 if (best) return (best);
78 else die(2, "unknown output format `%s'", optarg);
81 static void version(FILE *fp)
82 { pquis(fp, "$, mLib test-vector framework version " VERSION "\n"); }
84 static void usage(FILE *fp)
87 usage: $ [-f FORMAT] [-o OUTPUT] [-t SECS] [TEST-FILE ...]\n\
91 static void help(FILE *fp)
93 version(fp); fputc('\n', fp);
96 -h, --help show this help text.\n\
97 -v, --version show version number.\n\
98 -u, --usage show usage synopsis.\n\
100 -f, --format=FORMAT produce output in FORMAT.\n\
101 -o, --output=OUTPUT write output to OUTPUT file.\n\
105 void tvec_parseargs(int argc, char *argv[], struct tvec_state *tv_out,
106 int *argpos_out, const struct tvec_config *config)
109 const struct outform *of = 0;
110 struct tvec_output *o;
116 static const struct option options[] = {
117 { "help", 0, 0, 'h' },
118 { "version", 0, 0, 'v' },
119 { "usage", 0, 0, 'u' },
121 { "format", OPTF_ARGREQ, 0, 'f' },
122 { "output", OPTF_ARGREQ, 0, 'o' },
128 opt = mdwopt(argc, argv, "hvu" "f:o:", options, 0, 0, 0);
131 case 'h': help(stdout); exit(0);
132 case 'v': version(stdout); exit(0);
133 case 'u': usage(stdout); exit(0);
135 case 'f': of = find_outform(optarg); break;
137 if (ofp) fclose(ofp);
138 ofp = fopen(optarg, "w");
140 die(2, "failed to open `%s' for writing: %s",
141 optarg, strerror(errno));
149 if (f&f_bogus) { usage(stderr); exit(2); }
150 if (!ofp) ofp = stdout;
152 p = getenv("TVEC_FORMAT");
153 if (p) of = find_outform(p);
155 if (of) o = of->makefn(ofp);
156 else o = tvec_dfltout(ofp);
158 tvec_begin(tv_out, config, o); *argpos_out = optind;
161 int tvec_readstdin(struct tvec_state *tv)
162 { return (tvec_read(tv, "<stdin>", stdin)); }
164 int tvec_readfile(struct tvec_state *tv, const char *file)
169 fp = fopen(file, "r");
171 tvec_error(tv, "failed to open `%s' for reading: %s",
172 file, strerror(errno));
175 if (tvec_read(tv, file, fp)) { rc = -1; goto end; }
182 int tvec_readdflt(struct tvec_state *tv, const char *file)
189 p = getenv("srcdir");
190 if (p) { dstr_putf(&d, "%s/%s", p, file); file = d.buf; }
191 rc = tvec_readfile(tv, file);
192 } else if (isatty(0))
193 rc = tvec_error(tv, "use `-' to force reading from interactive stdin");
195 rc = tvec_readstdin(tv);
200 int tvec_readarg(struct tvec_state *tv, const char *arg)
204 if (STRCMP(arg, ==, "-")) rc = tvec_readstdin(tv);
205 else rc = tvec_readfile(tv, arg);
209 int tvec_readargs(int argc, char *argv[], struct tvec_state *tv,
210 int *argpos_inout, const char *dflt)
212 int i = *argpos_inout;
215 if (i == argc) rc = tvec_readdflt(tv, dflt);
219 if (tvec_readarg(tv, argv[i++])) rc = -1;
225 int tvec_main(int argc, char *argv[],
226 const struct tvec_config *config, const char *dflt)
228 struct tvec_state tv;
231 tvec_parseargs(argc, argv, &tv, &argpos, config);
232 tvec_readargs(argc, argv, &tv, &argpos, dflt);
233 return (tvec_end(&tv));
236 /*----- That's all, folks -------------------------------------------------*/