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 static struct bench_state benchstate;
61 const struct tvec_info tvec_adhocinfo =
62 { 0, 1, 1, sizeof(struct tvec_reg) };
64 static const struct outform *find_outform(const char *p)
66 const struct outform *best = 0, *of;
69 for (of = outtab; of->name; of++)
70 if (!STRNCMP(p, ==, of->name, n))
72 else if (!of->name[n])
75 die(2, "ambiguous output format name (`%s' or `%s'?)",
76 best->name, of->name);
79 if (best) return (best);
80 else die(2, "unknown output format `%s'", optarg);
83 static void version(FILE *fp)
84 { pquis(fp, "$, mLib test-vector framework version " VERSION "\n"); }
86 static void usage(FILE *fp)
89 usage: $ [-f FORMAT] [-o OUTPUT] [-t SECS] [TEST-FILE ...]\n\
93 static void help(FILE *fp)
95 version(fp); fputc('\n', fp);
98 -h, --help show this help text.\n\
99 -v, --version show version number.\n\
100 -u, --usage show usage synopsis.\n\
102 -f, --format=FORMAT produce output in FORMAT.\n\
103 -o, --output=OUTPUT write output to OUTPUT file.\n\
104 -t, --target=SECS aim to run benchmarks for SECS.\n\
108 void tvec_parseargs(int argc, char *argv[], struct tvec_state *tv_out,
109 int *argpos_out, const struct tvec_info *info)
112 const struct outform *of = 0;
113 struct tvec_output *o;
114 struct bench_timer *tm;
115 const char *p; char *q;
121 static const struct option options[] = {
122 { "help", 0, 0, 'h' },
123 { "version", 0, 0, 'v' },
124 { "usage", 0, 0, 'u' },
126 { "format", OPTF_ARGREQ, 0, 'f' },
127 { "output", OPTF_ARGREQ, 0, 'o' },
128 { "target", OPTF_ARGREQ, 0, 't' },
132 tvec_benchstate = &benchstate;
133 tm = bench_createtimer(); bench_init(&benchstate, tm);
136 opt = mdwopt(argc, argv, "hvu" "f:o:t:", options, 0, 0, 0);
139 case 'h': help(stdout); exit(0);
140 case 'v': version(stdout); exit(0);
141 case 'u': usage(stdout); exit(0);
143 case 'f': of = find_outform(optarg); break;
145 if (ofp) fclose(ofp);
146 ofp = fopen(optarg, "w");
148 die(2, "failed to open `%s' for writing: %s",
149 optarg, strerror(errno));
152 errno = 0; t = strtod(optarg, &q);
153 while (ISSPACE(*q)) q++;
154 if (errno || *q || t < 0) die(2, "invalid time `%s'", optarg);
155 benchstate.target_s = t;
163 if (f&f_bogus) { usage(stderr); exit(2); }
164 if (!ofp) ofp = stdout;
166 p = getenv("TVEC_FORMAT");
167 if (p) of = find_outform(p);
169 if (of) o = of->makefn(ofp);
170 else o = tvec_dfltout(ofp);
172 tvec_begin(tv_out, info, o); *argpos_out = optind;
175 int tvec_readstdin(struct tvec_state *tv)
176 { return (tvec_read(tv, "<stdin>", stdin)); }
178 int tvec_readfile(struct tvec_state *tv, const char *file)
183 fp = fopen(file, "r");
185 tvec_error(tv, "failed to open `%s' for reading: %s",
186 file, strerror(errno));
189 if (tvec_read(tv, file, fp)) { rc = -1; goto end; }
196 int tvec_readdflt(struct tvec_state *tv, const char *file)
203 p = getenv("srcdir");
204 if (p) { dstr_putf(&d, "%s/%s", p, file); file = d.buf; }
205 rc = tvec_readfile(tv, file);
206 } else if (isatty(0))
207 rc = tvec_error(tv, "use `-' to force reading from interactive stdin");
209 rc = tvec_readstdin(tv);
214 int tvec_readarg(struct tvec_state *tv, const char *arg)
218 if (STRCMP(arg, ==, "-")) rc = tvec_readstdin(tv);
219 else rc = tvec_readfile(tv, arg);
223 int tvec_readargs(int argc, char *argv[], struct tvec_state *tv,
224 int *argpos_inout, const char *dflt)
226 int i = *argpos_inout;
229 if (i == argc) rc = tvec_readdflt(tv, dflt);
233 if (tvec_readarg(tv, argv[i++])) rc = -1;
239 int tvec_main(int argc, char *argv[],
240 const struct tvec_info *info, const char *dflt)
242 struct tvec_state tv;
245 tvec_parseargs(argc, argv, &tv, &argpos, info);
246 tvec_readargs(argc, argv, &tv, &argpos, dflt);
247 return (tvec_end(&tv));
250 /*----- That's all, folks -------------------------------------------------*/