source: vendor/flex/2.5.33/scanopt.c@ 3408

Last change on this file since 3408 was 3031, checked in by bird, 18 years ago

flex 2.5.33.

File size: 19.8 KB
Line 
1/* flex - tool to generate fast lexical analyzers */
2
3/* Copyright (c) 1990 The Regents of the University of California. */
4/* All rights reserved. */
5
6/* This code is derived from software contributed to Berkeley by */
7/* Vern Paxson. */
8
9/* The United States Government has rights in this work pursuant */
10/* to contract no. DE-AC03-76SF00098 between the United States */
11/* Department of Energy and the University of California. */
12
13/* This file is part of flex. */
14
15/* Redistribution and use in source and binary forms, with or without */
16/* modification, are permitted provided that the following conditions */
17/* are met: */
18
19/* 1. Redistributions of source code must retain the above copyright */
20/* notice, this list of conditions and the following disclaimer. */
21/* 2. Redistributions in binary form must reproduce the above copyright */
22/* notice, this list of conditions and the following disclaimer in the */
23/* documentation and/or other materials provided with the distribution. */
24
25/* Neither the name of the University nor the names of its contributors */
26/* may be used to endorse or promote products derived from this software */
27/* without specific prior written permission. */
28
29/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
30/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
31/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
32/* PURPOSE. */
33
34
35#include "flexdef.h"
36#include "scanopt.h"
37
38
39/* Internal structures */
40
41#ifdef HAVE_STRCASECMP
42#define STRCASECMP(a,b) strcasecmp(a,b)
43#else
44static int STRCASECMP PROTO ((const char *, const char *));
45
46static int STRCASECMP (a, b)
47 const char *a;
48 const char *b;
49{
50 while (tolower (*a++) == tolower (*b++)) ;
51 return b - a;
52}
53#endif
54
55#define ARG_NONE 0x01
56#define ARG_REQ 0x02
57#define ARG_OPT 0x04
58#define IS_LONG 0x08
59
60struct _aux {
61 int flags; /* The above hex flags. */
62 int namelen; /* Length of the actual option word, e.g., "--file[=foo]" is 4 */
63 int printlen; /* Length of entire string, e.g., "--file[=foo]" is 12 */
64};
65
66
67struct _scanopt_t {
68 const optspec_t *options; /* List of options. */
69 struct _aux *aux; /* Auxiliary data about options. */
70 int optc; /* Number of options. */
71 int argc; /* Number of args. */
72 char **argv; /* Array of strings. */
73 int index; /* Used as: argv[index][subscript]. */
74 int subscript;
75 char no_err_msg; /* If true, do not print errors. */
76 char has_long;
77 char has_short;
78};
79
80/* Accessor functions. These WOULD be one-liners, but portability calls. */
81static const char *NAME PROTO ((struct _scanopt_t *, int));
82static int PRINTLEN PROTO ((struct _scanopt_t *, int));
83static int RVAL PROTO ((struct _scanopt_t *, int));
84static int FLAGS PROTO ((struct _scanopt_t *, int));
85static const char *DESC PROTO ((struct _scanopt_t *, int));
86static int scanopt_err PROTO ((struct _scanopt_t *, int, int, int));
87static int matchlongopt PROTO ((char *, char **, int *, char **, int *));
88static int find_opt
89PROTO ((struct _scanopt_t *, int, char *, int, int *, int *opt_offset));
90
91static const char *NAME (s, i)
92 struct _scanopt_t *s;
93 int i;
94{
95 return s->options[i].opt_fmt +
96 ((s->aux[i].flags & IS_LONG) ? 2 : 1);
97}
98
99static int PRINTLEN (s, i)
100 struct _scanopt_t *s;
101 int i;
102{
103 return s->aux[i].printlen;
104}
105
106static int RVAL (s, i)
107 struct _scanopt_t *s;
108 int i;
109{
110 return s->options[i].r_val;
111}
112
113static int FLAGS (s, i)
114 struct _scanopt_t *s;
115 int i;
116{
117 return s->aux[i].flags;
118}
119
120static const char *DESC (s, i)
121 struct _scanopt_t *s;
122 int i;
123{
124 return s->options[i].desc ? s->options[i].desc : "";
125}
126
127#ifndef NO_SCANOPT_USAGE
128static int get_cols PROTO ((void));
129
130static int get_cols ()
131{
132 char *env;
133 int cols = 80; /* default */
134
135#ifdef HAVE_NCURSES_H
136 initscr ();
137 endwin ();
138 if (COLS > 0)
139 return COLS;
140#endif
141
142 if ((env = getenv ("COLUMNS")) != NULL)
143 cols = atoi (env);
144
145 return cols;
146}
147#endif
148
149/* Macro to check for NULL before assigning a value. */
150#define SAFE_ASSIGN(ptr,val) \
151 do{ \
152 if((ptr)!=NULL) \
153 *(ptr) = val; \
154 }while(0)
155
156/* Macro to assure we reset subscript whenever we adjust s->index.*/
157#define INC_INDEX(s,n) \
158 do{ \
159 (s)->index += (n); \
160 (s)->subscript= 0; \
161 }while(0)
162
163scanopt_t *scanopt_init (options, argc, argv, flags)
164 const optspec_t *options;
165 int argc;
166 char **argv;
167 int flags;
168{
169 int i;
170 struct _scanopt_t *s;
171 s = (struct _scanopt_t *) malloc (sizeof (struct _scanopt_t));
172
173 s->options = options;
174 s->optc = 0;
175 s->argc = argc;
176 s->argv = (char **) argv;
177 s->index = 1;
178 s->subscript = 0;
179 s->no_err_msg = (flags & SCANOPT_NO_ERR_MSG);
180 s->has_long = 0;
181 s->has_short = 0;
182
183 /* Determine option count. (Find entry with all zeros). */
184 s->optc = 0;
185 while (options[s->optc].opt_fmt
186 || options[s->optc].r_val || options[s->optc].desc)
187 s->optc++;
188
189 /* Build auxiliary data */
190 s->aux = (struct _aux *) malloc (s->optc * sizeof (struct _aux));
191
192 for (i = 0; i < s->optc; i++) {
193 const char *p, *pname;
194 const struct optspec_t *opt;
195 struct _aux *aux;
196
197 opt = s->options + i;
198 aux = s->aux + i;
199
200 aux->flags = ARG_NONE;
201
202 if (opt->opt_fmt[0] == '-' && opt->opt_fmt[1] == '-') {
203 aux->flags |= IS_LONG;
204 pname = opt->opt_fmt + 2;
205 s->has_long = 1;
206 }
207 else {
208 pname = opt->opt_fmt + 1;
209 s->has_short = 1;
210 }
211 aux->printlen = strlen (opt->opt_fmt);
212
213 aux->namelen = 0;
214 for (p = pname + 1; *p; p++) {
215 /* detect required arg */
216 if (*p == '=' || isspace (*p)
217 || !(aux->flags & IS_LONG)) {
218 if (aux->namelen == 0)
219 aux->namelen = p - pname;
220 aux->flags |= ARG_REQ;
221 aux->flags &= ~ARG_NONE;
222 }
223 /* detect optional arg. This overrides required arg. */
224 if (*p == '[') {
225 if (aux->namelen == 0)
226 aux->namelen = p - pname;
227 aux->flags &= ~(ARG_REQ | ARG_NONE);
228 aux->flags |= ARG_OPT;
229 break;
230 }
231 }
232 if (aux->namelen == 0)
233 aux->namelen = p - pname;
234 }
235 return (scanopt_t *) s;
236}
237
238#ifndef NO_SCANOPT_USAGE
239/* these structs are for scanopt_usage(). */
240struct usg_elem {
241 int idx;
242 struct usg_elem *next;
243 struct usg_elem *alias;
244};
245typedef struct usg_elem usg_elem;
246
247
248/* Prints a usage message based on contents of optlist.
249 * Parameters:
250 * scanner - The scanner, already initialized with scanopt_init().
251 * fp - The file stream to write to.
252 * usage - Text to be prepended to option list.
253 * Return: Always returns 0 (zero).
254 * The output looks something like this:
255
256[indent][option, alias1, alias2...][indent][description line1
257 description line2...]
258 */
259int scanopt_usage (scanner, fp, usage)
260 scanopt_t *scanner;
261 FILE *fp;
262 const char *usage;
263{
264 struct _scanopt_t *s;
265 int i, columns, indent = 2;
266 usg_elem *byr_val = NULL; /* option indices sorted by r_val */
267 usg_elem *store; /* array of preallocated elements. */
268 int store_idx = 0;
269 usg_elem *ue;
270 int maxlen[2];
271 int desccol = 0;
272 int print_run = 0;
273
274 maxlen[0] = 0;
275 maxlen[1] = 0;
276
277 s = (struct _scanopt_t *) scanner;
278
279 if (usage) {
280 fprintf (fp, "%s\n", usage);
281 }
282 else {
283 /* Find the basename of argv[0] */
284 const char *p;
285
286 p = s->argv[0] + strlen (s->argv[0]);
287 while (p != s->argv[0] && *p != '/')
288 --p;
289 if (*p == '/')
290 p++;
291
292 fprintf (fp, _("Usage: %s [OPTIONS]...\n"), p);
293 }
294 fprintf (fp, "\n");
295
296 /* Sort by r_val and string. Yes, this is O(n*n), but n is small. */
297 store = (usg_elem *) malloc (s->optc * sizeof (usg_elem));
298 for (i = 0; i < s->optc; i++) {
299
300 /* grab the next preallocate node. */
301 ue = store + store_idx++;
302 ue->idx = i;
303 ue->next = ue->alias = NULL;
304
305 /* insert into list. */
306 if (!byr_val)
307 byr_val = ue;
308 else {
309 int found_alias = 0;
310 usg_elem **ue_curr, **ptr_if_no_alias = NULL;
311
312 ue_curr = &byr_val;
313 while (*ue_curr) {
314 if (RVAL (s, (*ue_curr)->idx) ==
315 RVAL (s, ue->idx)) {
316 /* push onto the alias list. */
317 ue_curr = &((*ue_curr)->alias);
318 found_alias = 1;
319 break;
320 }
321 if (!ptr_if_no_alias
322 &&
323 STRCASECMP (NAME (s, (*ue_curr)->idx),
324 NAME (s, ue->idx)) > 0) {
325 ptr_if_no_alias = ue_curr;
326 }
327 ue_curr = &((*ue_curr)->next);
328 }
329 if (!found_alias && ptr_if_no_alias)
330 ue_curr = ptr_if_no_alias;
331 ue->next = *ue_curr;
332 *ue_curr = ue;
333 }
334 }
335
336#if 0
337 if (1) {
338 printf ("ORIGINAL:\n");
339 for (i = 0; i < s->optc; i++)
340 printf ("%2d: %s\n", i, NAME (s, i));
341 printf ("SORTED:\n");
342 ue = byr_val;
343 while (ue) {
344 usg_elem *ue2;
345
346 printf ("%2d: %s\n", ue->idx, NAME (s, ue->idx));
347 for (ue2 = ue->alias; ue2; ue2 = ue2->next)
348 printf (" +---> %2d: %s\n", ue2->idx,
349 NAME (s, ue2->idx));
350 ue = ue->next;
351 }
352 }
353#endif
354
355 /* Now build each row of output. */
356
357 /* first pass calculate how much room we need. */
358 for (ue = byr_val; ue; ue = ue->next) {
359 usg_elem *ap;
360 int len = 0;
361 int nshort = 0, nlong = 0;
362
363
364#define CALC_LEN(i) do {\
365 if(FLAGS(s,i) & IS_LONG) \
366 len += (nlong++||nshort) ? 2+PRINTLEN(s,i) : PRINTLEN(s,i);\
367 else\
368 len += (nshort++||nlong)? 2+PRINTLEN(s,i) : PRINTLEN(s,i);\
369 }while(0)
370
371 if (!(FLAGS (s, ue->idx) & IS_LONG))
372 CALC_LEN (ue->idx);
373
374 /* do short aliases first. */
375 for (ap = ue->alias; ap; ap = ap->next) {
376 if (FLAGS (s, ap->idx) & IS_LONG)
377 continue;
378 CALC_LEN (ap->idx);
379 }
380
381 if (FLAGS (s, ue->idx) & IS_LONG)
382 CALC_LEN (ue->idx);
383
384 /* repeat the above loop, this time for long aliases. */
385 for (ap = ue->alias; ap; ap = ap->next) {
386 if (!(FLAGS (s, ap->idx) & IS_LONG))
387 continue;
388 CALC_LEN (ap->idx);
389 }
390
391 if (len > maxlen[0])
392 maxlen[0] = len;
393
394 /* It's much easier to calculate length for description column! */
395 len = strlen (DESC (s, ue->idx));
396 if (len > maxlen[1])
397 maxlen[1] = len;
398 }
399
400 /* Determine how much room we have, and how much we will allocate to each col.
401 * Do not address pathological cases. Output will just be ugly. */
402 columns = get_cols () - 1;
403 if (maxlen[0] + maxlen[1] + indent * 2 > columns) {
404 /* col 0 gets whatever it wants. we'll wrap the desc col. */
405 maxlen[1] = columns - (maxlen[0] + indent * 2);
406 if (maxlen[1] < 14) /* 14 is arbitrary lower limit on desc width. */
407 maxlen[1] = INT_MAX;
408 }
409 desccol = maxlen[0] + indent * 2;
410
411#define PRINT_SPACES(fp,n)\
412 do{\
413 int _n;\
414 _n=(n);\
415 while(_n-- > 0)\
416 fputc(' ',(fp));\
417 }while(0)
418
419
420 /* Second pass (same as above loop), this time we print. */
421 /* Sloppy hack: We iterate twice. The first time we print short and long options.
422 The second time we print those lines that have ONLY long options. */
423 while (print_run++ < 2) {
424 for (ue = byr_val; ue; ue = ue->next) {
425 usg_elem *ap;
426 int nwords = 0, nchars = 0, has_short = 0;
427
428/* TODO: get has_short schtick to work */
429 has_short = !(FLAGS (s, ue->idx) & IS_LONG);
430 for (ap = ue->alias; ap; ap = ap->next) {
431 if (!(FLAGS (s, ap->idx) & IS_LONG)) {
432 has_short = 1;
433 break;
434 }
435 }
436 if ((print_run == 1 && !has_short) ||
437 (print_run == 2 && has_short))
438 continue;
439
440 PRINT_SPACES (fp, indent);
441 nchars += indent;
442
443/* Print, adding a ", " between aliases. */
444#define PRINT_IT(i) do{\
445 if(nwords++)\
446 nchars+=fprintf(fp,", ");\
447 nchars+=fprintf(fp,"%s",s->options[i].opt_fmt);\
448 }while(0)
449
450 if (!(FLAGS (s, ue->idx) & IS_LONG))
451 PRINT_IT (ue->idx);
452
453 /* print short aliases first. */
454 for (ap = ue->alias; ap; ap = ap->next) {
455 if (!(FLAGS (s, ap->idx) & IS_LONG))
456 PRINT_IT (ap->idx);
457 }
458
459
460 if (FLAGS (s, ue->idx) & IS_LONG)
461 PRINT_IT (ue->idx);
462
463 /* repeat the above loop, this time for long aliases. */
464 for (ap = ue->alias; ap; ap = ap->next) {
465 if (FLAGS (s, ap->idx) & IS_LONG)
466 PRINT_IT (ap->idx);
467 }
468
469 /* pad to desccol */
470 PRINT_SPACES (fp, desccol - nchars);
471
472 /* Print description, wrapped to maxlen[1] columns. */
473 if (1) {
474 const char *pstart;
475
476 pstart = DESC (s, ue->idx);
477 while (1) {
478 int n = 0;
479 const char *lastws = NULL, *p;
480
481 p = pstart;
482
483 while (*p && n < maxlen[1]
484 && *p != '\n') {
485 if (isspace (*p)
486 || *p == '-') lastws =
487 p;
488 n++;
489 p++;
490 }
491
492 if (!*p) { /* hit end of desc. done. */
493 fprintf (fp, "%s\n",
494 pstart);
495 break;
496 }
497 else if (*p == '\n') { /* print everything up to here then wrap. */
498 fprintf (fp, "%.*s\n", n,
499 pstart);
500 PRINT_SPACES (fp, desccol);
501 pstart = p + 1;
502 continue;
503 }
504 else { /* we hit the edge of the screen. wrap at space if possible. */
505 if (lastws) {
506 fprintf (fp,
507 "%.*s\n",
508 lastws -
509 pstart,
510 pstart);
511 pstart =
512 lastws + 1;
513 }
514 else {
515 fprintf (fp,
516 "%.*s\n",
517 n,
518 pstart);
519 pstart = p + 1;
520 }
521 PRINT_SPACES (fp, desccol);
522 continue;
523 }
524 }
525 }
526 }
527 } /* end while */
528 free (store);
529 return 0;
530}
531#endif /* no scanopt_usage */
532
533
534static int scanopt_err (s, opt_offset, is_short, err)
535 struct _scanopt_t *s;
536 int opt_offset;
537 int is_short;
538 int err;
539{
540 const char *optname = "";
541 char optchar[2];
542 const optspec_t *opt = NULL;
543
544 if (opt_offset >= 0)
545 opt = s->options + opt_offset;
546
547 if (!s->no_err_msg) {
548
549 if (s->index > 0 && s->index < s->argc) {
550 if (is_short) {
551 optchar[0] =
552 s->argv[s->index][s->subscript];
553 optchar[1] = '\0';
554 optname = optchar;
555 }
556 else {
557 optname = s->argv[s->index];
558 }
559 }
560
561 fprintf (stderr, "%s: ", s->argv[0]);
562 switch (err) {
563 case SCANOPT_ERR_ARG_NOT_ALLOWED:
564 fprintf (stderr,
565 _
566 ("option `%s' doesn't allow an argument\n"),
567 optname);
568 break;
569 case SCANOPT_ERR_ARG_NOT_FOUND:
570 fprintf (stderr,
571 _("option `%s' requires an argument\n"),
572 optname);
573 break;
574 case SCANOPT_ERR_OPT_AMBIGUOUS:
575 fprintf (stderr, _("option `%s' is ambiguous\n"),
576 optname);
577 break;
578 case SCANOPT_ERR_OPT_UNRECOGNIZED:
579 fprintf (stderr, _("Unrecognized option `%s'\n"),
580 optname);
581 break;
582 default:
583 fprintf (stderr, _("Unknown error=(%d)\n"), err);
584 break;
585 }
586 }
587 return err;
588}
589
590
591
592/* Internal. Match str against the regex ^--([^=]+)(=(.*))?
593 * return 1 if *looks* like a long option.
594 * 'str' is the only input argument, the rest of the arguments are output only.
595 * optname will point to str + 2
596 *
597 */
598static int matchlongopt (str, optname, optlen, arg, arglen)
599 char *str;
600 char **optname;
601 int *optlen;
602 char **arg;
603 int *arglen;
604{
605 char *p;
606
607 *optname = *arg = (char *) 0;
608 *optlen = *arglen = 0;
609
610 /* Match regex /--./ */
611 p = str;
612 if (p[0] != '-' || p[1] != '-' || !p[2])
613 return 0;
614
615 p += 2;
616 *optname = (char *) p;
617
618 /* find the end of optname */
619 while (*p && *p != '=')
620 ++p;
621
622 *optlen = p - *optname;
623
624 if (!*p)
625 /* an option with no '=...' part. */
626 return 1;
627
628
629 /* We saw an '=' char. The rest of p is the arg. */
630 p++;
631 *arg = p;
632 while (*p)
633 ++p;
634 *arglen = p - *arg;
635
636 return 1;
637}
638
639
640
641/* Internal. Look up long or short option by name.
642 * Long options must match a non-ambiguous prefix, or exact match.
643 * Short options must be exact.
644 * Return boolean true if found and no error.
645 * Error stored in err_code or zero if no error. */
646static int find_opt (s, lookup_long, optstart, len, err_code, opt_offset)
647 struct _scanopt_t *s;
648 int lookup_long;
649 char *optstart;
650 int len;
651 int *err_code;
652 int *opt_offset;
653{
654 int nmatch = 0, lastr_val = 0, i;
655
656 *err_code = 0;
657 *opt_offset = -1;
658
659 if (!optstart)
660 return 0;
661
662 for (i = 0; i < s->optc; i++) {
663 char *optname;
664
665 optname =
666 (char *) (s->options[i].opt_fmt +
667 (lookup_long ? 2 : 1));
668
669 if (lookup_long && (s->aux[i].flags & IS_LONG)) {
670 if (len > s->aux[i].namelen)
671 continue;
672
673 if (strncmp (optname, optstart, len) == 0) {
674 nmatch++;
675 *opt_offset = i;
676
677 /* exact match overrides all. */
678 if (len == s->aux[i].namelen) {
679 nmatch = 1;
680 break;
681 }
682
683 /* ambiguity is ok between aliases. */
684 if (lastr_val
685 && lastr_val ==
686 s->options[i].r_val) nmatch--;
687 lastr_val = s->options[i].r_val;
688 }
689 }
690 else if (!lookup_long && !(s->aux[i].flags & IS_LONG)) {
691 if (optname[0] == optstart[0]) {
692 nmatch++;
693 *opt_offset = i;
694 }
695 }
696 }
697
698 if (nmatch == 0) {
699 *err_code = SCANOPT_ERR_OPT_UNRECOGNIZED;
700 *opt_offset = -1;
701 }
702 else if (nmatch > 1) {
703 *err_code = SCANOPT_ERR_OPT_AMBIGUOUS;
704 *opt_offset = -1;
705 }
706
707 return *err_code ? 0 : 1;
708}
709
710
711
712int scanopt (svoid, arg, optindex)
713 scanopt_t *svoid;
714 char **arg;
715 int *optindex;
716{
717 char *optname = NULL, *optarg = NULL, *pstart;
718 int namelen = 0, arglen = 0;
719 int errcode = 0, has_next;
720 const optspec_t *optp;
721 struct _scanopt_t *s;
722 struct _aux *auxp;
723 int is_short;
724 int opt_offset = -1;
725
726 s = (struct _scanopt_t *) svoid;
727
728 /* Normalize return-parameters. */
729 SAFE_ASSIGN (arg, NULL);
730 SAFE_ASSIGN (optindex, s->index);
731
732 if (s->index >= s->argc)
733 return 0;
734
735 /* pstart always points to the start of our current scan. */
736 pstart = s->argv[s->index] + s->subscript;
737 if (!pstart)
738 return 0;
739
740 if (s->subscript == 0) {
741
742 /* test for exact match of "--" */
743 if (pstart[0] == '-' && pstart[1] == '-' && !pstart[2]) {
744 SAFE_ASSIGN (optindex, s->index + 1);
745 INC_INDEX (s, 1);
746 return 0;
747 }
748
749 /* Match an opt. */
750 if (matchlongopt
751 (pstart, &optname, &namelen, &optarg, &arglen)) {
752
753 /* it LOOKS like an opt, but is it one?! */
754 if (!find_opt
755 (s, 1, optname, namelen, &errcode,
756 &opt_offset)) {
757 scanopt_err (s, opt_offset, 0, errcode);
758 return errcode;
759 }
760 /* We handle this below. */
761 is_short = 0;
762
763 /* Check for short opt. */
764 }
765 else if (pstart[0] == '-' && pstart[1]) {
766 /* Pass through to below. */
767 is_short = 1;
768 s->subscript++;
769 pstart++;
770 }
771
772 else {
773 /* It's not an option. We're done. */
774 return 0;
775 }
776 }
777
778 /* We have to re-check the subscript status because it
779 * may have changed above. */
780
781 if (s->subscript != 0) {
782
783 /* we are somewhere in a run of short opts,
784 * e.g., at the 'z' in `tar -xzf` */
785
786 optname = pstart;
787 namelen = 1;
788 is_short = 1;
789
790 if (!find_opt
791 (s, 0, pstart, namelen, &errcode, &opt_offset)) {
792 return scanopt_err (s, opt_offset, 1, errcode);
793 }
794
795 optarg = pstart + 1;
796 arglen = 0;
797 while (optarg[arglen])
798 arglen++;
799
800 if (arglen == 0)
801 optarg = NULL;
802 }
803
804 /* At this point, we have a long or short option matched at opt_offset into
805 * the s->options array (and corresponding aux array).
806 * A trailing argument is in {optarg,arglen}, if any.
807 */
808
809 /* Look ahead in argv[] to see if there is something
810 * that we can use as an argument (if needed). */
811 has_next = s->index + 1 < s->argc
812 && strcmp ("--", s->argv[s->index + 1]) != 0;
813
814 optp = s->options + opt_offset;
815 auxp = s->aux + opt_offset;
816
817 /* case: no args allowed */
818 if (auxp->flags & ARG_NONE) {
819 if (optarg) {
820 scanopt_err (s, opt_offset, is_short, errcode =
821 SCANOPT_ERR_ARG_NOT_ALLOWED);
822 INC_INDEX (s, 1);
823 return errcode;
824 }
825 INC_INDEX (s, 1);
826 return optp->r_val;
827 }
828
829 /* case: required */
830 if (auxp->flags & ARG_REQ) {
831 if (!optarg && !has_next)
832 return scanopt_err (s, opt_offset, is_short,
833 SCANOPT_ERR_ARG_NOT_FOUND);
834
835 if (!optarg) {
836 /* Let the next argv element become the argument. */
837 SAFE_ASSIGN (arg, s->argv[s->index + 1]);
838 INC_INDEX (s, 2);
839 }
840 else {
841 SAFE_ASSIGN (arg, (char *) optarg);
842 INC_INDEX (s, 1);
843 }
844 return optp->r_val;
845 }
846
847 /* case: optional */
848 if (auxp->flags & ARG_OPT) {
849 SAFE_ASSIGN (arg, optarg);
850 INC_INDEX (s, 1);
851 return optp->r_val;
852 }
853
854
855 /* Should not reach here. */
856 return 0;
857}
858
859
860int scanopt_destroy (svoid)
861 scanopt_t *svoid;
862{
863 struct _scanopt_t *s;
864
865 s = (struct _scanopt_t *) svoid;
866 if (s) {
867 if (s->aux)
868 free (s->aux);
869 free (s);
870 }
871 return 0;
872}
873
874
875/* vim:set tabstop=8 softtabstop=4 shiftwidth=4: */
Note: See TracBrowser for help on using the repository browser.