2 * (c) 2008-2009 Frank Mehnert <fm3@os.inf.tu-dresden.de>,
3 * Torsten Frenzel <frenzel@os.inf.tu-dresden.de>,
4 * Jork Löser <jork@os.inf.tu-dresden.de>
5 * economic rights: Technische Universität Dresden (Germany)
6 * This file is part of TUD:OS and distributed under the terms of the
7 * GNU Lesser General Public License 2.1.
8 * Please see the COPYING-LGPL-2.1 file for details.
11 * Parse the command-line for specified arguments and store the values into
14 * For a more detailed documentation, see parse_cmd.h in the include dir.
22 #include <l4/util/getopt.h>
23 #include <l4/util/parse_cmd.h>
25 struct parse_cmdline_struct{
26 enum parse_cmd_type type; // which type (int, switch, string)
27 char shortform; // short symbol
28 const char *longform; // long name
30 void *argptr; // ptr to variable getting the value
31 parse_cmd_fn_t fn; // function to call
32 parse_cmd_fn_arg_t fn_arg; // function to call with args
35 int switch_to; // value a switch sets
36 const char* default_string; // default string value
37 unsigned default_int; // default int value
38 int id; // identifier to pass to function
40 const char *comment; // a description for the generated help
43 #define TRASH(type, val) { type dummy __attribute__ ((unused)) = (val); }
45 int parse_cmdline(int *argc, const char***argv, char arg0, ...){
49 /* calculate the number of argument-descriptors */
51 err = parse_cmdlinev(argc, argv, arg0, va);
56 int parse_cmdlinev(int *argc, const char***argv, char arg0, va_list va0){
58 int c, count, shortform, cur_longopt;
59 const char*longform, *comment;
60 struct option *longopts, *longptr;
61 char *optstring, *optptr;
62 struct parse_cmdline_struct *pa;
66 /* calculate the number of argument-descriptors */
68 for(count=0; shortform; count++){
70 int standard_int, *int_p;
71 const char *standard_string, **string_p;
73 longform = va_arg(va, const char*);
74 comment = va_arg(va, const char*);
75 type = va_arg(va, int);
78 standard_int = va_arg(va, int);
79 int_p = va_arg(va, int*);
80 *int_p = standard_int;
82 case PARSE_CMD_SWITCH:
83 TRASH(int, va_arg(va, int));
84 TRASH(int*, va_arg(va, int*));
86 case PARSE_CMD_STRING:
87 standard_string = va_arg(va, char*);
88 string_p = va_arg(va, const char**);
89 *string_p = standard_string;
92 case PARSE_CMD_FN_ARG:
93 TRASH(int, va_arg(va, int));
94 TRASH(parse_cmd_fn_t, va_arg(va, parse_cmd_fn_t));
97 standard_int = va_arg(va, int);
98 int_p = va_arg(va, int*);
99 *int_p = standard_int;
102 standard_int = va_arg(va, int);
103 int_p = va_arg(va, int*);
104 *int_p = standard_int;
109 shortform = va_arg(va, int);
112 /* consider the --help and -h */
115 /* allocate the fields for short options, long options and parse args */
116 longopts = (struct option*)alloca(sizeof(struct option)*(count+1));
117 if(longopts==0) return -2;
119 optstring = (char*)alloca(count*2+1);
120 if(optstring==0) return -2;
122 pa = (struct parse_cmdline_struct*)
123 alloca(count * sizeof(struct parse_cmdline_struct));
126 /* fill in the short options field, longopts and parse args */
132 /* Prefill the 'help' switches. We know it is the first entry, so
133 we can check for idx 0 when parsing the table. */
136 pa->longform = "help";
137 pa->comment = "this help";
138 pa->type = PARSE_CMD_SWITCH;
139 longptr->name = pa->longform;
140 longptr->flag = &cur_longopt;
142 longptr->has_arg = 0;
145 for(c=1;shortform; c++){
146 if(shortform!=' ') *optptr++ = shortform;
147 pa[c].shortform = shortform;
148 pa[c].longform = va_arg(va, const char*);
149 pa[c].comment = va_arg(va, const char*);
150 pa[c].type = va_arg(va, int);
152 /* prefill a few of the longoptions fields */
154 longptr->name = pa[c].longform;
155 longptr->flag = &cur_longopt;
160 if(shortform!=' ') *optptr++ = ':';
161 if(pa[c].longform) longptr->has_arg = 1;
163 pa[c].val.default_int = va_arg(va, int);
164 pa[c].arg.argptr = va_arg(va, int*);
167 case PARSE_CMD_SWITCH:
168 if(pa[c].longform) longptr->has_arg = 0;
170 pa[c].val.switch_to = va_arg(va, int);
171 pa[c].arg.argptr = va_arg(va, int*);
173 case PARSE_CMD_STRING:
174 if(shortform!=' ') *optptr++ = ':';
175 if(pa[c].longform) longptr->has_arg = 1;
177 pa[c].val.default_string = va_arg(va, char*);
178 pa[c].arg.argptr = va_arg(va, char**);
181 if(pa[c].longform) longptr->has_arg = 0;
183 pa[c].val.id = va_arg(va, int);
184 pa[c].arg.fn = va_arg(va, parse_cmd_fn_t);
186 case PARSE_CMD_FN_ARG:
187 if(shortform!=' ') *optptr++ = ':';
188 if(pa[c].longform) longptr->has_arg = 1;
190 pa[c].val.id = va_arg(va, int);
191 pa[c].arg.fn_arg = va_arg(va, parse_cmd_fn_arg_t);
195 if(pa[c].longform) longptr->has_arg = 0;
197 TRASH(int, va_arg(va, int));
198 pa[c].arg.argptr = va_arg(va, int*);
202 if(pa[c].longform) longptr++;
204 shortform = va_arg(va, int);
207 // end the optstring string
210 // end the longopt field
218 /* now, parse the arguments */
223 val = getopt_long_only(*argc, (char**)*argv, optstring, longopts, &idx);
226 printf("Option -%c requires an argument\n",optopt);
230 printf("Unrecognized option: - %c\n", optopt ? optopt : '?');
240 /* we got an option. If it is a short option (val!=0),
243 for(idx = 0; idx < count; idx++){
244 if(pa[idx].shortform == val) break;
247 /* it was a long option. We are lucky, the pa-element is
248 stored in the cur_longopt variable. */
256 switch(pa[idx].type){
258 *((int*)pa[idx].arg.argptr) = strtol(optarg, 0, 0);
260 case PARSE_CMD_SWITCH:
261 *((int*)pa[idx].arg.argptr) = pa[idx].val.switch_to;
263 case PARSE_CMD_STRING:
264 *((const char**)pa[idx].arg.argptr) = optarg;
267 pa[idx].arg.fn(pa[idx].val.id);
269 case PARSE_CMD_FN_ARG:
270 pa[idx].arg.fn_arg(pa[idx].val.id,
271 optarg, strtol(optarg, 0, 0));
274 (*((int*)pa[idx].arg.argptr))++;
277 (*((int*)pa[idx].arg.argptr))--;
287 printf("Usage: %s <options>. Option list:\n", *argv[0]);
288 for(c=0;c<count;c++){
292 if(pa[c].shortform!=' '){
293 buf[0]='-';buf[1]=pa[c].shortform;buf[2]=0;
298 l = printf(" [ %s%s%s%s%s ]",
300 (buf[0] && pa[c].longform) ? " | " : "",
301 pa[c].longform ? "--" : "",
302 pa[c].longform ? pa[c].longform : "",
303 pa[c].type==PARSE_CMD_INT ? " num" :
304 pa[c].type==PARSE_CMD_STRING ? " string" : "");
305 if(pa[c].comment) printf(" %*s- %s", l<25?25-l:0,
307 if(pa[c].type == PARSE_CMD_STRING)
308 printf(" (\"%s\")", pa[c].val.default_string);
309 if(pa[c].type == PARSE_CMD_INT)
310 printf(" (%#x)", pa[c].val.default_int);
317 int parse_cmdline_extra(const char*argv0, const char*line, char delim,
325 if((line_ = alloca(strlen(line)))==0) return -2;
328 for(s=line_;*s;s++)if(*s==delim) argc_++;
330 argv_ = alloca(sizeof(char*)*argc_);
334 if(line) while(*line){
336 while((*s=*line)!=0 && *s!=delim){line++; s++;}
342 i = parse_cmdlinev(&argc_, &argv_, arg0, va);