std/c/: Delete the old Perl tests in src/t/, 0:84
[sunny256-utils.git] / Lib / std / c / src / std.c
blob8875c0a353360545105216039061b696b46969ac
1 /*
2 * STDfilenameDTS
3 * File ID: STDuuidDTS
5 * (C)opyleft STDyearDTS- Øyvind A. Holm <sunny@sunbase.org>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "STDexecDTS.h"
24 * Global variables
27 char *progname;
28 struct Options opt;
31 * msg() - Print a message prefixed with "[progname]: " to stderr if the
32 * current verbose level is equal or higher than the first argument. The rest
33 * of the arguments are delivered to vfprintf().
34 * Returns the number of characters written.
37 int msg(const VerboseLevel verbose, const char *format, ...)
39 int retval = 0;
41 assert(format);
42 assert(strlen(format));
44 if (opt.verbose >= verbose) {
45 va_list ap;
47 va_start(ap, format);
48 retval = fprintf(stderr, "%s: ", progname);
49 retval += vfprintf(stderr, format, ap);
50 retval += fprintf(stderr, "\n");
51 va_end(ap);
54 return retval;
58 * std_strerror() - Replacement for `strerror()` that returns a predictable
59 * error message on every platform so the tests work everywhere.
62 const char *std_strerror(const int errnum)
64 switch (errnum) {
65 case EACCES:
66 return "Permission denied";
67 default:
69 * Should never happen. If this line is executed, an `errno`
70 * value is missing from `std_strerror()`, and tests may fail
71 * on other platforms.
73 fprintf(stderr,
74 "%s: %s(): Unknown errnum received: %d, \"%s\"\n",
75 progname, __func__, errnum, strerror(errnum));
76 return strerror(errnum);
81 * myerror() - Print an error message to stderr using this format:
83 * a: b: c
85 * where `a` is the name of the program (the value of `progname`), `b` is the
86 * output from the printf-like string and optional arguments, and `c` is the
87 * error message from `errno`. If `errno` indicates no error, the ": c" part is
88 * not printed. Returns the number of characters written.
91 int myerror(const char *format, ...)
93 va_list ap;
94 int retval = 0;
95 const int orig_errno = errno;
97 assert(format);
98 assert(strlen(format));
100 retval = fprintf(stderr, "%s: ", progname);
101 va_start(ap, format);
102 retval += vfprintf(stderr, format, ap);
103 va_end(ap);
104 if (orig_errno)
105 retval += fprintf(stderr, ": %s", std_strerror(orig_errno));
106 retval += fprintf(stderr, "\n");
108 return retval;
112 * print_license() - Display the program license. Returns `EXIT_SUCCESS`.
115 static int print_license(void)
117 puts("(C)opyleft STDyearDTS- Øyvind A. Holm <sunny@sunbase.org>");
118 puts("");
119 puts("This program is free software; you can redistribute it"
120 " and/or modify it \n"
121 "under the terms of the GNU General Public License as"
122 " published by the \n"
123 "Free Software Foundation; either version 2 of the License,"
124 " or (at your \n"
125 "option) any later version.");
126 puts("");
127 puts("This program is distributed in the hope that it will be"
128 " useful, but \n"
129 "WITHOUT ANY WARRANTY; without even the implied warranty of \n"
130 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
131 puts("See the GNU General Public License for more details.");
132 puts("");
133 puts("You should have received a copy of"
134 " the GNU General Public License along \n"
135 "with this program. If not, see <http://www.gnu.org/licenses/>.");
137 return EXIT_SUCCESS;
141 * print_version() - Print version information on stdout. If `-q` is used, only
142 * the version number is printed. Returns `EXIT_SUCCESS`.
145 static int print_version(void)
147 #ifdef FAKE_MEMLEAK
148 char *p;
150 p = malloc(100);
151 if (p) { }
152 #endif
154 if (opt.verbose <= VERBOSE_QUIET) {
155 puts(EXEC_VERSION);
156 return EXIT_SUCCESS;
158 printf("%s %s (%s)\n", progname, EXEC_VERSION, EXEC_DATE);
159 #ifdef FAKE_MEMLEAK
160 printf("has FAKE_MEMLEAK\n");
161 #endif
162 #ifdef GCOV
163 printf("has GCOV\n");
164 #endif
165 #ifdef NDEBUG
166 printf("has NDEBUG\n");
167 #endif
168 #ifdef PROF
169 printf("has PROF\n");
170 #endif
171 #ifdef UNUSED
172 printf("has UNUSED\n");
173 #endif
175 return EXIT_SUCCESS;
179 * usage() - Prints a help screen. Returns `retval`.
182 static int usage(const int retval)
184 if (retval != EXIT_SUCCESS) {
185 myerror("Type \"%s --help\" for help screen."
186 " Returning with value %d.", progname, retval);
187 return retval;
189 puts("");
190 if (opt.verbose >= 1) {
191 print_version();
192 puts("");
194 printf("Usage: %s [options]\n", progname);
195 printf("\n");
196 printf("Options:\n");
197 printf("\n");
198 printf(" -h, --help\n"
199 " Show this help.\n");
200 printf(" --license\n"
201 " Print the software license.\n");
202 printf(" -q, --quiet\n"
203 " Be more quiet. Can be repeated to increase silence.\n");
204 printf(" -v, --verbose\n"
205 " Increase level of verbosity. Can be repeated.\n");
206 printf(" --selftest [arg]\n"
207 " Run the built-in test suite. If specified, the argument"
208 " can contain \n"
209 " one or more of these strings: \"exec\" (the tests use the"
210 " executable \n"
211 " file), \"func\" (runs function tests), or \"all\"."
212 " Multiple strings \n"
213 " should be separated by commas. If no argument is"
214 " specified, default \n"
215 " is \"all\".\n");
216 printf(" --valgrind [arg]\n"
217 " Run the built-in test suite with Valgrind memory checking."
218 " Accepts \n"
219 " the same optional argument as --selftest, with the same"
220 " defaults.\n");
221 printf(" --version\n"
222 " Print version information.\n");
223 printf("\n");
225 return retval;
229 * choose_opt_action() - Decide what to do when option `c` is found. Read
230 * definitions for long options from `opts`.
231 * Returns 0 if ok, or 1 if `c` is unknown or anything fails.
234 static int choose_opt_action(const int c, const struct option *opts)
236 int retval = 0;
238 assert(opts);
240 switch (c) {
241 case 0:
242 if (!strcmp(opts->name, "license"))
243 opt.license = true;
244 else if (!strcmp(opts->name, "selftest"))
245 opt.selftest = true;
246 else if (!strcmp(opts->name, "valgrind"))
247 opt.valgrind = opt.selftest = true;
248 else if (!strcmp(opts->name, "version"))
249 opt.version = true;
250 break;
251 case 'h':
252 opt.help = true;
253 break;
254 case 'q':
255 opt.verbose--;
256 break;
257 case 'v':
258 opt.verbose++;
259 break;
260 default:
261 msg(VERBOSE_DEBUG,
262 "%s(): getopt_long() returned character code %d",
263 __func__, c);
264 retval = 1;
265 break;
268 return retval;
272 * parse_options() - Parse command line options.
273 * Returns 0 if succesful, or 1 if an error occurs.
276 static int parse_options(const int argc, char * const argv[])
278 int retval = 0;
280 assert(argv);
282 opt.help = false;
283 opt.license = false;
284 opt.selftest = false;
285 opt.testexec = false;
286 opt.testfunc = false;
287 opt.valgrind = false;
288 opt.verbose = 0;
289 opt.version = false;
291 while (!retval) {
292 int c;
293 int option_index = 0;
294 static const struct option long_options[] = {
295 {"help", no_argument, NULL, 'h'},
296 {"license", no_argument, NULL, 0},
297 {"quiet", no_argument, NULL, 'q'},
298 {"selftest", no_argument, NULL, 0},
299 {"valgrind", no_argument, NULL, 0},
300 {"verbose", no_argument, NULL, 'v'},
301 {"version", no_argument, NULL, 0},
302 {0, 0, 0, 0}
305 c = getopt_long(argc, argv,
306 "h" /* --help */
307 "q" /* --quiet */
308 "v" /* --verbose */
309 , long_options, &option_index);
310 if (c == -1)
311 break;
312 retval = choose_opt_action(c, &long_options[option_index]);
315 return retval;
319 * setup_options() - Do necessary changes to `o` based on the user input.
321 * - Parse the optional argument to --selftest and set `o->testexec` and
322 * `o->testfunc`.
324 * Returns 0 if everything is ok, otherwise it returns 1.
327 static int setup_options(struct Options *o, const int argc, char *argv[])
329 if (o->selftest) {
330 if (optind < argc) {
331 const char *s = argv[optind];
332 if (!s) {
333 myerror("%s(): argv[optind] is" /* gncov */
334 " NULL", __func__);
335 return 1; /* gncov */
337 if (strstr(s, "all"))
338 o->testexec = o->testfunc = true; /* gncov */
339 if (strstr(s, "exec"))
340 o->testexec = true; /* gncov */
341 if (strstr(s, "func"))
342 o->testfunc = true; /* gncov */
343 } else {
344 o->testexec = o->testfunc = true;
348 return 0;
352 * main()
355 int main(int argc, char *argv[])
357 int retval = EXIT_SUCCESS;
359 progname = argv[0];
360 errno = 0;
362 if (parse_options(argc, argv)) {
363 myerror("Option error");
364 return usage(EXIT_FAILURE);
367 msg(VERBOSE_DEBUG, "%s(): Using verbose level %d",
368 __func__, opt.verbose);
369 msg(VERBOSE_DEBUG, "%s(): argc = %d, optind = %d",
370 __func__, argc, optind);
372 if (setup_options(&opt, argc, argv))
373 return EXIT_FAILURE; /* gncov */
375 if (opt.help)
376 return usage(EXIT_SUCCESS);
377 if (opt.selftest)
378 return opt_selftest();
379 if (opt.version)
380 return print_version();
381 if (opt.license)
382 return print_license();
384 if (optind < argc) {
385 int t;
387 for (t = optind; t < argc; t++) {
388 msg(VERBOSE_DEBUG, "%s(): Non-option arg %d: %s",
389 __func__, t, argv[t]);
393 msg(VERBOSE_DEBUG, "Returning from %s() with value %d",
394 __func__, retval);
395 return retval;
398 /* vim: set ts=8 sw=8 sts=8 noet fo+=w tw=79 fenc=UTF-8 : */