]> git.draconx.ca Git - dxcommon.git/blob - t/helpopt.c
DX_C_ALIGNAS: Work around bash-5 parsing bug.
[dxcommon.git] / t / helpopt.c
1 /*
2  * Copyright © 2021-2022 Nick Bowler
3  *
4  * Test helper application to verify help_print_optstring operation.
5  *
6  * Command-line arguments are collected to create the options to be formatted.
7  * There are six basic forms:
8  *
9  *   --long-option-only
10  *   --long-option-with-argument arg
11  *   --long-option-with-optional-argument [arg]
12  *   --short-option -s arg
13  *   --short-option-with-argument -s arg
14  *   --short-option-with-optional-argument -s [arg]
15  *
16  * Adding an argument of '&' to any form will set the "flag" member of
17  * the option structure to a non-null value.
18  *
19  * Based on these arguments, a suitable 'struct option' is constructed and
20  * passed to help_print_optstring.  Then a tab character is printed, followed
21  * by the return value of help_print_optsring (via printf %d).  Then further
22  * arguments are considered to output more options.
23  *
24  * Initially, the "l" value passed to help_print_optstring is 20.  This can be
25  * changed at any point by a numeric command-line argument, which will set a
26  * new value that applies to all subsequent calls until it is changed again.
27  *
28  * License WTFPL2: Do What The Fuck You Want To Public License, version 2.
29  * This is free software: you are free to do what the fuck you want to.
30  * There is NO WARRANTY, to the extent permitted by law.
31  */
32 #include "help.h"
33 #include "tap.h"
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <limits.h>
39 #include <errno.h>
40
41 #include <getopt.h>
42
43 int arg_to_int(const char *s)
44 {
45         char *end;
46         long val;
47
48         errno = 0;
49         val = strtol(s, &end, 0);
50         if (*end != 0)
51                 tap_bail_out("%s: numeric argument expected", s);
52         else if (val < INT_MIN || val > INT_MAX || errno == ERANGE)
53                 tap_bail_out("%s: %s", s, strerror(ERANGE));
54         else if (errno)
55                 tap_bail_out("%s: %s", s, strerror(errno));
56
57         return val;
58 }
59
60 void print_opt(struct option *opt, const char *argname, int w)
61 {
62         w = help_print_optstring(opt, argname, w);
63         printf("\t%d\n", w);
64 }
65
66 int main(int argc, char **argv)
67 {
68         struct option opt = {0};
69         const char *argname = 0;
70         int i, w = 20;
71
72         for (i = 1; i < argc; i++) {
73                 if (argv[i][0] == '-' && argv[i][1] == '-') {
74                         if (opt.name)
75                                 print_opt(&opt, argname, w);
76                         opt.val = UCHAR_MAX+1;
77                         opt.has_arg = 0;
78                         opt.name = argv[i]+2;
79                         opt.flag = NULL;
80                 } else if (argv[i][0] == '-') {
81                         opt.val = argv[i][1];
82                 } else if (argv[i][0] == '[') {
83                         char *c;
84
85                         argname = argv[i]+1;
86                         if ((c = strchr(argname, ']')))
87                                 *c = 0;
88                         opt.has_arg = 2;
89                 } else if (argv[i][0] == '&') {
90                         static int dummy;
91                         opt.flag = &dummy;
92                 } else if (argv[i][0] >= '0' && argv[i][0] <= '9') {
93                         w = arg_to_int(argv[i]);
94                 } else {
95                         argname = argv[i];
96                         opt.has_arg = 1;
97                 }
98         }
99
100         if (opt.name)
101                 print_opt(&opt, argname, w);
102
103         return 0;
104 }