source: benchmark/io/http/parseargs.cfa @ 3f1d9b5

arm-ehenumforall-pointer-decayjacob/cs343-translationnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 3f1d9b5 was 3f1d9b5, checked in by Thierry Delisle <tdelisle@…>, 3 years ago

Parse args help now properly formats on narrow terminals

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