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)
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
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"
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
, ...)
42 assert(strlen(format
));
44 if (opt
.verbose
>= verbose
) {
48 retval
= fprintf(stderr
, "%s: ", progname
);
49 retval
+= vfprintf(stderr
, format
, ap
);
50 retval
+= fprintf(stderr
, "\n");
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
)
66 return "Permission denied";
69 * Should never happen. If this line is executed, an `errno`
70 * value is missing from `std_strerror()`, and tests may fail
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:
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
, ...)
95 const int orig_errno
= errno
;
98 assert(strlen(format
));
100 retval
= fprintf(stderr
, "%s: ", progname
);
101 va_start(ap
, format
);
102 retval
+= vfprintf(stderr
, format
, ap
);
105 retval
+= fprintf(stderr
, ": %s", std_strerror(orig_errno
));
106 retval
+= fprintf(stderr
, "\n");
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>");
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,"
125 "option) any later version.");
127 puts("This program is distributed in the hope that it will be"
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.");
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/>.");
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)
154 if (opt
.verbose
<= VERBOSE_QUIET
) {
158 printf("%s %s (%s)\n", progname
, EXEC_VERSION
, EXEC_DATE
);
160 printf("has FAKE_MEMLEAK\n");
163 printf("has GCOV\n");
166 printf("has NDEBUG\n");
169 printf("has PROF\n");
172 printf("has UNUSED\n");
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
);
190 if (opt
.verbose
>= 1) {
194 printf("Usage: %s [options]\n", progname
);
196 printf("Options:\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"
209 " one or more of these strings: \"exec\" (the tests use the"
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"
216 printf(" --valgrind [arg]\n"
217 " Run the built-in test suite with Valgrind memory checking."
219 " the same optional argument as --selftest, with the same"
221 printf(" --version\n"
222 " Print version information.\n");
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
)
242 if (!strcmp(opts
->name
, "license"))
244 else if (!strcmp(opts
->name
, "selftest"))
246 else if (!strcmp(opts
->name
, "valgrind"))
247 opt
.valgrind
= opt
.selftest
= true;
248 else if (!strcmp(opts
->name
, "version"))
262 "%s(): getopt_long() returned character code %d",
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
[])
284 opt
.selftest
= false;
285 opt
.testexec
= false;
286 opt
.testfunc
= false;
287 opt
.valgrind
= false;
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},
305 c
= getopt_long(argc
, argv
,
309 , long_options
, &option_index
);
312 retval
= choose_opt_action(c
, &long_options
[option_index
]);
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
324 * Returns 0 if everything is ok, otherwise it returns 1.
327 static int setup_options(struct Options
*o
, const int argc
, char *argv
[])
331 const char *s
= argv
[optind
];
333 myerror("%s(): argv[optind] is" /* gncov */
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 */
344 o
->testexec
= o
->testfunc
= true;
355 int main(int argc
, char *argv
[])
357 int retval
= EXIT_SUCCESS
;
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 */
376 return usage(EXIT_SUCCESS
);
378 return opt_selftest();
380 return print_version();
382 return print_license();
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",
398 /* vim: set ts=8 sw=8 sts=8 noet fo+=w tw=79 fenc=UTF-8 : */