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