source: libcfa/src/parseargs.cfa @ 8e516fd

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

Moved example parseargs to libcfa

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