Add APIC_ID to extract apic id from local apic id field
[dragonfly.git] / contrib / com_err / getarg.c
1 /*
2  * Copyright (c) 1997, 1998 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden). 
4  * All rights reserved. 
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met: 
9  *
10  * 1. Redistributions of source code must retain the above copyright 
11  *    notice, this list of conditions and the following disclaimer. 
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright 
14  *    notice, this list of conditions and the following disclaimer in the 
15  *    documentation and/or other materials provided with the distribution. 
16  *
17  * 3. All advertising materials mentioning features or use of this software 
18  *    must display the following acknowledgement: 
19  *      This product includes software developed by Kungliga Tekniska 
20  *      Högskolan and its contributors. 
21  *
22  * 4. Neither the name of the Institute nor the names of its contributors 
23  *    may be used to endorse or promote products derived from this software 
24  *    without specific prior written permission. 
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
36  * SUCH DAMAGE. 
37  */
38
39 #if 0
40 RCSID("$Id: getarg.c,v 1.25 1998/11/22 09:45:05 assar Exp $");
41 #endif
42
43 #include <sys/ttycom.h>
44 #include <time.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include "getarg.h"
49
50 #define ISFLAG(X) ((X).type == arg_flag || (X).type == arg_negative_flag)
51
52 static size_t
53 print_arg (char *string, size_t len, int mdoc, int longp, struct getargs *arg)
54 {
55     const char *s;
56
57     *string = '\0';
58
59     if (ISFLAG(*arg))
60         return 0;
61
62     if(mdoc){
63         if(longp)
64             strncat(string, "= Ns", len);
65         strncat(string, " Ar ", len);
66     }else
67         if (longp)
68             strncat (string, "=", len);
69         else
70             strncat (string, " ", len);
71
72     if (arg->arg_help)
73         s = arg->arg_help;
74     else if (arg->type == arg_integer)
75         s = "number";
76     else if (arg->type == arg_string)
77         s = "string";
78     else
79         s = "<undefined>";
80
81     strncat(string, s, len);
82     return 1 + strlen(s);
83 }
84
85 static int
86 check_column(FILE *f, int col, int len, int columns)
87 {
88     if(col + len > columns) {
89         fprintf(f, "\n");
90         col = fprintf(f, "  ");
91     }
92     return col;
93 }
94
95 void
96 arg_printusage (struct getargs *args,
97                 size_t num_args,
98                 const char *progname,
99                 const char *extra_string)
100 {
101     int i;
102     size_t max_len = 0;
103     char buf[128];
104     int col = 0, columns;
105     struct winsize ws;
106
107     columns = 80;
108     col = 0;
109     col += fprintf (stderr, "Usage: %s", progname);
110     for (i = 0; i < num_args; ++i) {
111         size_t len = 0;
112
113         if (args[i].long_name) {
114             buf[0] = '\0';
115             strncat(buf, "[--", sizeof(buf));
116             len += 2;
117             if(args[i].type == arg_negative_flag) {
118                 strncat(buf, "no-", sizeof(buf));
119                 len += 3;
120             }
121             strncat(buf, args[i].long_name, sizeof(buf));
122             len += strlen(args[i].long_name);
123             len += print_arg(buf + strlen(buf), sizeof(buf) - strlen(buf), 
124                              0, 1, &args[i]);
125             strncat(buf, "]", sizeof(buf));
126             if(args[i].type == arg_strings)
127                 strncat(buf, "...", sizeof(buf));
128             col = check_column(stderr, col, strlen(buf) + 1, columns);
129             col += fprintf(stderr, " %s", buf);
130         }
131         if (args[i].short_name) {
132             snprintf(buf, sizeof(buf), "[-%c", args[i].short_name);
133             len += 2;
134             len += print_arg(buf + strlen(buf), sizeof(buf) - strlen(buf), 
135                              0, 0, &args[i]);
136             strncat(buf, "]", sizeof(buf));
137             if(args[i].type == arg_strings)
138                 strncat(buf, "...", sizeof(buf));
139             col = check_column(stderr, col, strlen(buf) + 1, columns);
140             col += fprintf(stderr, " %s", buf);
141         }
142         if (args[i].long_name && args[i].short_name)
143             len += 2; /* ", " */
144         max_len = max(max_len, len);
145     }
146     if (extra_string) {
147         col = check_column(stderr, col, strlen(extra_string) + 1, columns);
148         fprintf (stderr, " %s\n", extra_string);
149     } else
150         fprintf (stderr, "\n");
151     for (i = 0; i < num_args; ++i) {
152         if (args[i].help) {
153             size_t count = 0;
154
155             if (args[i].short_name) {
156                 count += fprintf (stderr, "-%c", args[i].short_name);
157                 print_arg (buf, sizeof(buf), 0, 0, &args[i]);
158                 count += fprintf(stderr, "%s", buf);
159             }
160             if (args[i].short_name && args[i].long_name)
161                 count += fprintf (stderr, ", ");
162             if (args[i].long_name) {
163                 count += fprintf (stderr, "--");
164                 if (args[i].type == arg_negative_flag)
165                     count += fprintf (stderr, "no-");
166                 count += fprintf (stderr, "%s", args[i].long_name);
167                 print_arg (buf, sizeof(buf), 0, 1, &args[i]);
168                 count += fprintf(stderr, "%s", buf);
169             }
170             while(count++ <= max_len)
171                 putc (' ', stderr);
172             fprintf (stderr, "%s\n", args[i].help);
173         }
174     }
175 }
176
177 static void
178 add_string(getarg_strings *s, char *value)
179 {
180     s->strings = realloc(s->strings,
181                          (s->num_strings + 1) * sizeof(*s->strings));
182     s->strings[s->num_strings] = value;
183     s->num_strings++;
184 }
185
186 static int
187 arg_match_long(struct getargs *args, size_t num_args,
188                char *argv)
189 {
190     int i;
191     char *optarg = NULL;
192     int negate = 0;
193     int partial_match = 0;
194     struct getargs *partial = NULL;
195     struct getargs *current = NULL;
196     int argv_len;
197     char *p;
198
199     argv_len = strlen(argv);
200     p = strchr (argv, '=');
201     if (p != NULL)
202         argv_len = p - argv;
203
204     for (i = 0; i < num_args; ++i) {
205         if(args[i].long_name) {
206             int len = strlen(args[i].long_name);
207             char *p = argv;
208             int p_len = argv_len;
209             negate = 0;
210
211             for (;;) {
212                 if (strncmp (args[i].long_name, p, p_len) == 0) {
213                     if(p_len == len)
214                         current = &args[i];
215                     else {
216                         ++partial_match;
217                         partial = &args[i];
218                     }
219                     optarg  = p + p_len;
220                 } else if (ISFLAG(args[i]) && strncmp (p, "no-", 3) == 0) {
221                     negate = !negate;
222                     p += 3;
223                     p_len -= 3;
224                     continue;
225                 }
226                 break;
227             }
228             if (current)
229                 break;
230         }
231     }
232     if (current == NULL) {
233         if (partial_match == 1)
234             current = partial;
235         else
236             return ARG_ERR_NO_MATCH;
237     }
238     
239     if(*optarg == '\0' && !ISFLAG(*current))
240         return ARG_ERR_NO_MATCH;
241     switch(current->type){
242     case arg_integer:
243     {
244         int tmp;
245         if(sscanf(optarg + 1, "%d", &tmp) != 1)
246             return ARG_ERR_BAD_ARG;
247         *(int*)current->value = tmp;
248         return 0;
249     }
250     case arg_string:
251     {
252         *(char**)current->value = optarg + 1;
253         return 0;
254     }
255     case arg_strings:
256     {
257         add_string((getarg_strings*)current->value, optarg + 1);
258         return 0;
259     }
260     case arg_flag:
261     case arg_negative_flag:
262     {
263         int *flag = current->value;
264         if(*optarg == '\0' ||
265            strcmp(optarg + 1, "yes") == 0 || 
266            strcmp(optarg + 1, "true") == 0){
267             *flag = !negate;
268             return 0;
269         } else if (*optarg && strcmp(optarg + 1, "maybe") == 0) {
270             *flag = rand() & 1;
271         } else {
272             *flag = negate;
273             return 0;
274         }
275         return ARG_ERR_BAD_ARG;
276     }
277     default:
278         abort ();
279     }
280 }
281
282 int
283 getarg(struct getargs *args, size_t num_args, 
284        int argc, char **argv, int *optind)
285 {
286     int i, j, k;
287     int ret = 0;
288
289     srand (time(NULL));
290     (*optind)++;
291     for(i = *optind; i < argc; i++) {
292         if(argv[i][0] != '-')
293             break;
294         if(argv[i][1] == '-'){
295             if(argv[i][2] == 0){
296                 i++;
297                 break;
298             }
299             ret = arg_match_long (args, num_args, argv[i] + 2);
300             if(ret)
301                 return ret;
302         }else{
303             for(j = 1; argv[i][j]; j++) {
304                 for(k = 0; k < num_args; k++) {
305                     char *optarg;
306                     if(args[k].short_name == 0)
307                         continue;
308                     if(argv[i][j] == args[k].short_name){
309                         if(args[k].type == arg_flag){
310                             *(int*)args[k].value = 1;
311                             break;
312                         }
313                         if(args[k].type == arg_negative_flag){
314                             *(int*)args[k].value = 0;
315                             break;
316                         }
317                         if(argv[i][j + 1])
318                             optarg = &argv[i][j + 1];
319                         else{
320                             i++;
321                             optarg = argv[i];
322                         }
323                         if(optarg == NULL)
324                             return ARG_ERR_NO_ARG;
325                         if(args[k].type == arg_integer){
326                             int tmp;
327                             if(sscanf(optarg, "%d", &tmp) != 1)
328                                 return ARG_ERR_BAD_ARG;
329                             *(int*)args[k].value = tmp;
330                             goto out;
331                         }else if(args[k].type == arg_string){
332                             *(char**)args[k].value = optarg;
333                             goto out;
334                         }else if(args[k].type == arg_strings){
335                             add_string((getarg_strings*)args[k].value, optarg);
336                             goto out;
337                         }
338                         return ARG_ERR_BAD_ARG;
339                     }
340                         
341                 }
342                 if (k == num_args)
343                     return ARG_ERR_NO_MATCH;
344             }
345         out:;
346         }
347     }
348     *optind = i;
349     return 0;
350 }
351
352 #if TEST
353 int foo_flag = 2;
354 int flag1 = 0;
355 int flag2 = 0;
356 int bar_int;
357 char *baz_string;
358
359 struct getargs args[] = {
360     { NULL, '1', arg_flag, &flag1, "one", NULL },
361     { NULL, '2', arg_flag, &flag2, "two", NULL },
362     { "foo", 'f', arg_negative_flag, &foo_flag, "foo", NULL },
363     { "bar", 'b', arg_integer, &bar_int, "bar", "seconds"},
364     { "baz", 'x', arg_string, &baz_string, "baz", "name" },
365 };
366
367 int main(int argc, char **argv)
368 {
369     int optind = 0;
370     while(getarg(args, 5, argc, argv, &optind))
371         printf("Bad arg: %s\n", argv[optind]);
372     printf("flag1 = %d\n", flag1);  
373     printf("flag2 = %d\n", flag2);  
374     printf("foo_flag = %d\n", foo_flag);  
375     printf("bar_int = %d\n", bar_int);
376     printf("baz_flag = %s\n", baz_string);
377     arg_printusage (args, 5, argv[0], "nothing here");
378 }
379 #endif