source: libcfa/src/parseargs.cfa @ 7874d77

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 7874d77 was 7874d77, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Parseargs now magically figures out argc/argv

  • Property mode set to 100644
File size: 4.5 KB
Line 
1#include "parseargs.hfa"
2
3#include <stdint.h>
4#include <string.h>
5#include <errno.h>
6#include <unistd.h>
7extern "C" {
8        #include <getopt.h>
9        #include <sys/ioctl.h>
10
11        struct FILE;
12        extern FILE * stderr;
13        extern FILE * stdout;
14
15        extern int fileno(FILE *stream);
16
17        extern int fprintf ( FILE * stream, const char * format, ... );
18
19        extern          long long int strtoll (const char* str, char** endptr, int base);
20        extern unsigned long long int strtoull(const char* str, char** endptr, int base);
21}
22
23#include "common.hfa"
24#include "limits.hfa"
25
26extern int cfa_args_argc;
27extern char ** cfa_args_argv;
28extern char ** cfa_args_envp;
29
30void printopt(FILE * out, int width, int max, char sn, const char * ln, const char * help) {
31        int hwidth = max - (11 + width);
32        if(hwidth <= 0) hwidth = max;
33
34        fprintf(out, "  -%c, --%-*s   %.*s\n", sn, width, ln, hwidth, help);
35        for() {
36                help += min(strlen(help), hwidth);
37                if('\0' == *help) break;
38                fprintf(out, "%*s%.*s\n", width + 11, "", hwidth, help);
39        }
40}
41
42void parse_args( cfa_option options[], size_t opt_count, const char * usage, char ** & left ) {
43        parse_args(cfa_args_argc, cfa_args_argv, options, opt_count, usage, left );
44}
45
46void parse_args(
47        int argc,
48        char * argv[],
49        cfa_option options[],
50        size_t opt_count,
51        const char * usage,
52        char ** & left
53) {
54        struct option optarr[opt_count + 2];
55        int width = 0;
56        int max_width = 1_000_000;
57        {
58                int idx = 0;
59                for(i; opt_count) {
60                        if(options[i].long_name) {
61                                optarr[idx].name = options[i].long_name;
62                                optarr[idx].flag = 0p;
63                                optarr[idx].val  = options[i].short_name;
64                                if(    ((intptr_t)options[i].parse) == ((intptr_t)parse_settrue)
65                                    || ((intptr_t)options[i].parse) == ((intptr_t)parse_setfalse) ) {
66                                        optarr[idx].has_arg = no_argument;
67                                } else {
68                                        optarr[idx].has_arg = required_argument;
69                                }
70                                idx++;
71
72                                int w = strlen(options[i].long_name);
73                                if(w > width) width = w;
74                        }
75                }
76                optarr[idx+0].[name, has_arg, flag, val] = ["help", no_argument, 0, 'h'];
77                optarr[idx+1].[name, has_arg, flag, val] = [0, no_argument, 0, 0];
78        }
79
80        char optstring[opt_count * 3] = { '\0' };
81        {
82                int idx = 0;
83                for(i; opt_count) {
84                        optstring[idx] = options[i].short_name;
85                        idx++;
86                        if(    ((intptr_t)options[i].parse) != ((intptr_t)parse_settrue)
87                            && ((intptr_t)options[i].parse) != ((intptr_t)parse_setfalse) ) {
88                                optstring[idx] = ':';
89                                idx++;
90                        }
91                }
92                optstring[idx+0] = 'h';
93                optstring[idx+1] = '\0';
94        }
95
96        FILE * out = stderr;
97        NEXT_ARG:
98        for() {
99                int idx = 0;
100                int opt = getopt_long(argc, argv, optstring, optarr, &idx);
101                switch(opt) {
102                        case -1:
103                                if(&left != 0p) left = argv + optind;
104                                return;
105                        case 'h':
106                                out = stdout;
107                        case '?':
108                                goto USAGE;
109                        default:
110                                for(i; opt_count) {
111                                        if(opt == options[i].short_name) {
112                                                const char * arg = optarg ? optarg : "";
113                                                bool success = options[i].parse( arg, options[i].variable );
114                                                if(success) continue NEXT_ARG;
115
116                                                fprintf(out, "Argument '%s' for option %c could not be parsed\n\n", arg, (char)opt);
117                                                goto USAGE;
118                                        }
119                                }
120                                abort("Internal parse arg error\n");
121                }
122
123        }
124
125        USAGE:;
126        int outfd = fileno(out);
127        if(isatty(outfd)) {
128                struct winsize size;
129                int ret = ioctl(outfd, TIOCGWINSZ, &size);
130                if(ret < 0) abort( "ioctl error: (%d) %s\n", (int)errno, strerror(errno) );
131                max_width = size.ws_col;
132        }
133
134        fprintf(out, "Usage:\n  %s %s\n", argv[0], usage);
135
136        for(i; opt_count) {
137                printopt(out, width, max_width, options[i].short_name, options[i].long_name, options[i].help);
138        }
139        fprintf(out, "  -%c, --%-*s   %s\n", 'h', width, "help", "print this help message");
140        exit(out == stdout ? 0 : 1);
141}
142
143bool parse_yesno(const char * arg, bool & value ) {
144        if(strcmp(arg, "yes") == 0) {
145                value = true;
146                return true;
147        }
148
149        if(strcmp(arg, "no") == 0) {
150                value = false;
151                return true;
152        }
153
154        return false;
155}
156
157bool parse_settrue (const char *, bool & value ) {
158        value = true;
159        return true;
160}
161
162bool parse_setfalse(const char *, bool & value )  {
163        value = false;
164        return true;
165}
166
167bool parse(const char * arg, const char * & value ) {
168        value = arg;
169        return true;
170}
171
172bool parse(const char * arg, unsigned & value) {
173        char * end;
174        unsigned long long int r = strtoull(arg, &end, 10);
175        if(*end != '\0') return false;
176        if(r > (unsigned)MAX) return false;
177
178        value = r;
179        return true;
180}
181
182bool parse(const char * arg, size_t & value) {
183        char * end;
184        unsigned long long int r = strtoull(arg, &end, 10);
185        if(*end != '\0') return false;
186        if(r > (size_t)MAX) return false;
187
188        value = r;
189        return true;
190}
191
192bool parse(const char * arg, int & value) {
193        char * end;
194        int r = strtoll(arg, &end, 10);
195        if(*end != '\0') return false;
196
197        value = r;
198        return true;
199}
Note: See TracBrowser for help on using the repository browser.