Update the pciconf(8) database.
[dragonfly.git] / contrib / flex / scanopt.c
blobf76ecd34dac07b9cc6d0682f2bfa1ca75c8ef664
1 /* flex - tool to generate fast lexical analyzers */
3 /* Copyright (c) 1990 The Regents of the University of California. */
4 /* All rights reserved. */
6 /* This code is derived from software contributed to Berkeley by */
7 /* Vern Paxson. */
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. */
13 /* This file is part of flex. */
15 /* Redistribution and use in source and binary forms, with or without */
16 /* modification, are permitted provided that the following conditions */
17 /* are met: */
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. */
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. */
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. */
34 #include "flexdef.h"
35 #include "scanopt.h"
38 /* Internal structures */
40 #ifdef HAVE_STRCASECMP
41 #define STRCASECMP(a,b) strcasecmp(a,b)
42 #else
43 static int STRCASECMP PROTO ((const char *, const char *));
45 static int STRCASECMP (a, b)
46 const char *a;
47 const char *b;
49 while (tolower (*a++) == tolower (*b++)) ;
50 return b - a;
52 #endif
54 #define ARG_NONE 0x01
55 #define ARG_REQ 0x02
56 #define ARG_OPT 0x04
57 #define IS_LONG 0x08
59 struct _aux {
60 int flags; /* The above hex flags. */
61 int namelen; /* Length of the actual option word, e.g., "--file[=foo]" is 4 */
62 int printlen; /* Length of entire string, e.g., "--file[=foo]" is 12 */
66 struct _scanopt_t {
67 const optspec_t *options; /* List of options. */
68 struct _aux *aux; /* Auxiliary data about options. */
69 int optc; /* Number of options. */
70 int argc; /* Number of args. */
71 char **argv; /* Array of strings. */
72 int index; /* Used as: argv[index][subscript]. */
73 int subscript;
74 char no_err_msg; /* If true, do not print errors. */
75 char has_long;
76 char has_short;
79 /* Accessor functions. These WOULD be one-liners, but portability calls. */
80 static const char *NAME PROTO ((struct _scanopt_t *, int));
81 static int PRINTLEN PROTO ((struct _scanopt_t *, int));
82 static int RVAL PROTO ((struct _scanopt_t *, int));
83 static int FLAGS PROTO ((struct _scanopt_t *, int));
84 static const char *DESC PROTO ((struct _scanopt_t *, int));
85 static int scanopt_err PROTO ((struct _scanopt_t *, int, int, int));
86 static int matchlongopt PROTO ((char *, char **, int *, char **, int *));
87 static int find_opt
88 PROTO ((struct _scanopt_t *, int, char *, int, int *, int *opt_offset));
90 static const char *NAME (s, i)
91 struct _scanopt_t *s;
92 int i;
94 return s->options[i].opt_fmt +
95 ((s->aux[i].flags & IS_LONG) ? 2 : 1);
98 static int PRINTLEN (s, i)
99 struct _scanopt_t *s;
100 int i;
102 return s->aux[i].printlen;
105 static int RVAL (s, i)
106 struct _scanopt_t *s;
107 int i;
109 return s->options[i].r_val;
112 static int FLAGS (s, i)
113 struct _scanopt_t *s;
114 int i;
116 return s->aux[i].flags;
119 static const char *DESC (s, i)
120 struct _scanopt_t *s;
121 int i;
123 return s->options[i].desc ? s->options[i].desc : "";
126 #ifndef NO_SCANOPT_USAGE
127 static int get_cols PROTO ((void));
129 static int get_cols ()
131 char *env;
132 int cols = 80; /* default */
134 #ifdef HAVE_NCURSES_H
135 initscr ();
136 endwin ();
137 if (COLS > 0)
138 return COLS;
139 #endif
141 if ((env = getenv ("COLUMNS")) != NULL)
142 cols = atoi (env);
144 return cols;
146 #endif
148 /* Macro to check for NULL before assigning a value. */
149 #define SAFE_ASSIGN(ptr,val) \
150 do{ \
151 if((ptr)!=NULL) \
152 *(ptr) = val; \
153 }while(0)
155 /* Macro to assure we reset subscript whenever we adjust s->index.*/
156 #define INC_INDEX(s,n) \
157 do{ \
158 (s)->index += (n); \
159 (s)->subscript= 0; \
160 }while(0)
162 scanopt_t *scanopt_init (options, argc, argv, flags)
163 const optspec_t *options;
164 int argc;
165 char **argv;
166 int flags;
168 int i;
169 struct _scanopt_t *s;
170 s = (struct _scanopt_t *) malloc (sizeof (struct _scanopt_t));
172 s->options = options;
173 s->optc = 0;
174 s->argc = argc;
175 s->argv = (char **) argv;
176 s->index = 1;
177 s->subscript = 0;
178 s->no_err_msg = (flags & SCANOPT_NO_ERR_MSG);
179 s->has_long = 0;
180 s->has_short = 0;
182 /* Determine option count. (Find entry with all zeros). */
183 s->optc = 0;
184 while (options[s->optc].opt_fmt
185 || options[s->optc].r_val || options[s->optc].desc)
186 s->optc++;
188 /* Build auxiliary data */
189 s->aux = (struct _aux *) malloc (s->optc * sizeof (struct _aux));
191 for (i = 0; i < s->optc; i++) {
192 const Char *p, *pname;
193 const struct optspec_t *opt;
194 struct _aux *aux;
196 opt = s->options + i;
197 aux = s->aux + i;
199 aux->flags = ARG_NONE;
201 if (opt->opt_fmt[0] == '-' && opt->opt_fmt[1] == '-') {
202 aux->flags |= IS_LONG;
203 pname = (const Char *)(opt->opt_fmt + 2);
204 s->has_long = 1;
206 else {
207 pname = (const Char *)(opt->opt_fmt + 1);
208 s->has_short = 1;
210 aux->printlen = strlen (opt->opt_fmt);
212 aux->namelen = 0;
213 for (p = pname + 1; *p; p++) {
214 /* detect required arg */
215 if (*p == '=' || isspace (*p)
216 || !(aux->flags & IS_LONG)) {
217 if (aux->namelen == 0)
218 aux->namelen = p - pname;
219 aux->flags |= ARG_REQ;
220 aux->flags &= ~ARG_NONE;
222 /* detect optional arg. This overrides required arg. */
223 if (*p == '[') {
224 if (aux->namelen == 0)
225 aux->namelen = p - pname;
226 aux->flags &= ~(ARG_REQ | ARG_NONE);
227 aux->flags |= ARG_OPT;
228 break;
231 if (aux->namelen == 0)
232 aux->namelen = p - pname;
234 return (scanopt_t *) s;
237 #ifndef NO_SCANOPT_USAGE
238 /* these structs are for scanopt_usage(). */
239 struct usg_elem {
240 int idx;
241 struct usg_elem *next;
242 struct usg_elem *alias;
244 typedef struct usg_elem usg_elem;
247 /* Prints a usage message based on contents of optlist.
248 * Parameters:
249 * scanner - The scanner, already initialized with scanopt_init().
250 * fp - The file stream to write to.
251 * usage - Text to be prepended to option list.
252 * Return: Always returns 0 (zero).
253 * The output looks something like this:
255 [indent][option, alias1, alias2...][indent][description line1
256 description line2...]
258 int scanopt_usage (scanner, fp, usage)
259 scanopt_t *scanner;
260 FILE *fp;
261 const char *usage;
263 struct _scanopt_t *s;
264 int i, columns, indent = 2;
265 usg_elem *byr_val = NULL; /* option indices sorted by r_val */
266 usg_elem *store; /* array of preallocated elements. */
267 int store_idx = 0;
268 usg_elem *ue;
269 int maxlen[2];
270 int desccol = 0;
271 int print_run = 0;
273 maxlen[0] = 0;
274 maxlen[1] = 0;
276 s = (struct _scanopt_t *) scanner;
278 if (usage) {
279 fprintf (fp, "%s\n", usage);
281 else {
282 /* Find the basename of argv[0] */
283 const char *p;
285 p = s->argv[0] + strlen (s->argv[0]);
286 while (p != s->argv[0] && *p != '/')
287 --p;
288 if (*p == '/')
289 p++;
291 fprintf (fp, _("Usage: %s [OPTIONS]...\n"), p);
293 fprintf (fp, "\n");
295 /* Sort by r_val and string. Yes, this is O(n*n), but n is small. */
296 store = (usg_elem *) malloc (s->optc * sizeof (usg_elem));
297 for (i = 0; i < s->optc; i++) {
299 /* grab the next preallocate node. */
300 ue = store + store_idx++;
301 ue->idx = i;
302 ue->next = ue->alias = NULL;
304 /* insert into list. */
305 if (!byr_val)
306 byr_val = ue;
307 else {
308 int found_alias = 0;
309 usg_elem **ue_curr, **ptr_if_no_alias = NULL;
311 ue_curr = &byr_val;
312 while (*ue_curr) {
313 if (RVAL (s, (*ue_curr)->idx) ==
314 RVAL (s, ue->idx)) {
315 /* push onto the alias list. */
316 ue_curr = &((*ue_curr)->alias);
317 found_alias = 1;
318 break;
320 if (!ptr_if_no_alias
322 STRCASECMP (NAME (s, (*ue_curr)->idx),
323 NAME (s, ue->idx)) > 0) {
324 ptr_if_no_alias = ue_curr;
326 ue_curr = &((*ue_curr)->next);
328 if (!found_alias && ptr_if_no_alias)
329 ue_curr = ptr_if_no_alias;
330 ue->next = *ue_curr;
331 *ue_curr = ue;
335 #if 0
336 if (1) {
337 printf ("ORIGINAL:\n");
338 for (i = 0; i < s->optc; i++)
339 printf ("%2d: %s\n", i, NAME (s, i));
340 printf ("SORTED:\n");
341 ue = byr_val;
342 while (ue) {
343 usg_elem *ue2;
345 printf ("%2d: %s\n", ue->idx, NAME (s, ue->idx));
346 for (ue2 = ue->alias; ue2; ue2 = ue2->next)
347 printf (" +---> %2d: %s\n", ue2->idx,
348 NAME (s, ue2->idx));
349 ue = ue->next;
352 #endif
354 /* Now build each row of output. */
356 /* first pass calculate how much room we need. */
357 for (ue = byr_val; ue; ue = ue->next) {
358 usg_elem *ap;
359 int len = 0;
360 int nshort = 0, nlong = 0;
363 #define CALC_LEN(i) do {\
364 if(FLAGS(s,i) & IS_LONG) \
365 len += (nlong++||nshort) ? 2+PRINTLEN(s,i) : PRINTLEN(s,i);\
366 else\
367 len += (nshort++||nlong)? 2+PRINTLEN(s,i) : PRINTLEN(s,i);\
368 }while(0)
370 if (!(FLAGS (s, ue->idx) & IS_LONG))
371 CALC_LEN (ue->idx);
373 /* do short aliases first. */
374 for (ap = ue->alias; ap; ap = ap->next) {
375 if (FLAGS (s, ap->idx) & IS_LONG)
376 continue;
377 CALC_LEN (ap->idx);
380 if (FLAGS (s, ue->idx) & IS_LONG)
381 CALC_LEN (ue->idx);
383 /* repeat the above loop, this time for long aliases. */
384 for (ap = ue->alias; ap; ap = ap->next) {
385 if (!(FLAGS (s, ap->idx) & IS_LONG))
386 continue;
387 CALC_LEN (ap->idx);
390 if (len > maxlen[0])
391 maxlen[0] = len;
393 /* It's much easier to calculate length for description column! */
394 len = strlen (DESC (s, ue->idx));
395 if (len > maxlen[1])
396 maxlen[1] = len;
399 /* Determine how much room we have, and how much we will allocate to each col.
400 * Do not address pathological cases. Output will just be ugly. */
401 columns = get_cols () - 1;
402 if (maxlen[0] + maxlen[1] + indent * 2 > columns) {
403 /* col 0 gets whatever it wants. we'll wrap the desc col. */
404 maxlen[1] = columns - (maxlen[0] + indent * 2);
405 if (maxlen[1] < 14) /* 14 is arbitrary lower limit on desc width. */
406 maxlen[1] = INT_MAX;
408 desccol = maxlen[0] + indent * 2;
410 #define PRINT_SPACES(fp,n)\
411 do{\
412 int _n;\
413 _n=(n);\
414 while(_n-- > 0)\
415 fputc(' ',(fp));\
416 }while(0)
419 /* Second pass (same as above loop), this time we print. */
420 /* Sloppy hack: We iterate twice. The first time we print short and long options.
421 The second time we print those lines that have ONLY long options. */
422 while (print_run++ < 2) {
423 for (ue = byr_val; ue; ue = ue->next) {
424 usg_elem *ap;
425 int nwords = 0, nchars = 0, has_short = 0;
427 /* TODO: get has_short schtick to work */
428 has_short = !(FLAGS (s, ue->idx) & IS_LONG);
429 for (ap = ue->alias; ap; ap = ap->next) {
430 if (!(FLAGS (s, ap->idx) & IS_LONG)) {
431 has_short = 1;
432 break;
435 if ((print_run == 1 && !has_short) ||
436 (print_run == 2 && has_short))
437 continue;
439 PRINT_SPACES (fp, indent);
440 nchars += indent;
442 /* Print, adding a ", " between aliases. */
443 #define PRINT_IT(i) do{\
444 if(nwords++)\
445 nchars+=fprintf(fp,", ");\
446 nchars+=fprintf(fp,"%s",s->options[i].opt_fmt);\
447 }while(0)
449 if (!(FLAGS (s, ue->idx) & IS_LONG))
450 PRINT_IT (ue->idx);
452 /* print short aliases first. */
453 for (ap = ue->alias; ap; ap = ap->next) {
454 if (!(FLAGS (s, ap->idx) & IS_LONG))
455 PRINT_IT (ap->idx);
459 if (FLAGS (s, ue->idx) & IS_LONG)
460 PRINT_IT (ue->idx);
462 /* repeat the above loop, this time for long aliases. */
463 for (ap = ue->alias; ap; ap = ap->next) {
464 if (FLAGS (s, ap->idx) & IS_LONG)
465 PRINT_IT (ap->idx);
468 /* pad to desccol */
469 PRINT_SPACES (fp, desccol - nchars);
471 /* Print description, wrapped to maxlen[1] columns. */
472 if (1) {
473 const char *pstart;
475 pstart = DESC (s, ue->idx);
476 while (1) {
477 int n = 0;
478 const char *lastws = NULL, *p;
480 p = pstart;
482 while (*p && n < maxlen[1]
483 && *p != '\n') {
484 if (isspace ((Char)(*p))
485 || *p == '-') lastws =
487 n++;
488 p++;
491 if (!*p) { /* hit end of desc. done. */
492 fprintf (fp, "%s\n",
493 pstart);
494 break;
496 else if (*p == '\n') { /* print everything up to here then wrap. */
497 fprintf (fp, "%.*s\n", n,
498 pstart);
499 PRINT_SPACES (fp, desccol);
500 pstart = p + 1;
501 continue;
503 else { /* we hit the edge of the screen. wrap at space if possible. */
504 if (lastws) {
505 fprintf (fp,
506 "%.*s\n",
507 (int)(lastws - pstart),
508 pstart);
509 pstart =
510 lastws + 1;
512 else {
513 fprintf (fp,
514 "%.*s\n",
516 pstart);
517 pstart = p + 1;
519 PRINT_SPACES (fp, desccol);
520 continue;
525 } /* end while */
526 free (store);
527 return 0;
529 #endif /* no scanopt_usage */
532 static int scanopt_err (s, opt_offset, is_short, err)
533 struct _scanopt_t *s;
534 int opt_offset;
535 int is_short;
536 int err;
538 const char *optname = "";
539 char optchar[2];
540 const optspec_t *opt = NULL;
542 if (opt_offset >= 0)
543 opt = s->options + opt_offset;
545 if (!s->no_err_msg) {
547 if (s->index > 0 && s->index < s->argc) {
548 if (is_short) {
549 optchar[0] =
550 s->argv[s->index][s->subscript];
551 optchar[1] = '\0';
552 optname = optchar;
554 else {
555 optname = s->argv[s->index];
559 fprintf (stderr, "%s: ", s->argv[0]);
560 switch (err) {
561 case SCANOPT_ERR_ARG_NOT_ALLOWED:
562 fprintf (stderr,
564 ("option `%s' doesn't allow an argument\n"),
565 optname);
566 break;
567 case SCANOPT_ERR_ARG_NOT_FOUND:
568 fprintf (stderr,
569 _("option `%s' requires an argument\n"),
570 optname);
571 break;
572 case SCANOPT_ERR_OPT_AMBIGUOUS:
573 fprintf (stderr, _("option `%s' is ambiguous\n"),
574 optname);
575 break;
576 case SCANOPT_ERR_OPT_UNRECOGNIZED:
577 fprintf (stderr, _("Unrecognized option `%s'\n"),
578 optname);
579 break;
580 default:
581 fprintf (stderr, _("Unknown error=(%d)\n"), err);
582 break;
585 return err;
589 /* Internal. Match str against the regex ^--([^=]+)(=(.*))?
590 * return 1 if *looks* like a long option.
591 * 'str' is the only input argument, the rest of the arguments are output only.
592 * optname will point to str + 2
595 static int matchlongopt (str, optname, optlen, arg, arglen)
596 char *str;
597 char **optname;
598 int *optlen;
599 char **arg;
600 int *arglen;
602 char *p;
604 *optname = *arg = (char *) 0;
605 *optlen = *arglen = 0;
607 /* Match regex /--./ */
608 p = str;
609 if (p[0] != '-' || p[1] != '-' || !p[2])
610 return 0;
612 p += 2;
613 *optname = (char *) p;
615 /* find the end of optname */
616 while (*p && *p != '=')
617 ++p;
619 *optlen = p - *optname;
621 if (!*p)
622 /* an option with no '=...' part. */
623 return 1;
626 /* We saw an '=' char. The rest of p is the arg. */
627 p++;
628 *arg = p;
629 while (*p)
630 ++p;
631 *arglen = p - *arg;
633 return 1;
637 /* Internal. Look up long or short option by name.
638 * Long options must match a non-ambiguous prefix, or exact match.
639 * Short options must be exact.
640 * Return boolean true if found and no error.
641 * Error stored in err_code or zero if no error. */
642 static int find_opt (s, lookup_long, optstart, len, err_code, opt_offset)
643 struct _scanopt_t *s;
644 int lookup_long;
645 char *optstart;
646 int len;
647 int *err_code;
648 int *opt_offset;
650 int nmatch = 0, lastr_val = 0, i;
652 *err_code = 0;
653 *opt_offset = -1;
655 if (!optstart)
656 return 0;
658 for (i = 0; i < s->optc; i++) {
659 char *optname;
661 optname =
662 (char *) (s->options[i].opt_fmt +
663 (lookup_long ? 2 : 1));
665 if (lookup_long && (s->aux[i].flags & IS_LONG)) {
666 if (len > s->aux[i].namelen)
667 continue;
669 if (strncmp (optname, optstart, len) == 0) {
670 nmatch++;
671 *opt_offset = i;
673 /* exact match overrides all. */
674 if (len == s->aux[i].namelen) {
675 nmatch = 1;
676 break;
679 /* ambiguity is ok between aliases. */
680 if (lastr_val
681 && lastr_val ==
682 s->options[i].r_val) nmatch--;
683 lastr_val = s->options[i].r_val;
686 else if (!lookup_long && !(s->aux[i].flags & IS_LONG)) {
687 if (optname[0] == optstart[0]) {
688 nmatch++;
689 *opt_offset = i;
694 if (nmatch == 0) {
695 *err_code = SCANOPT_ERR_OPT_UNRECOGNIZED;
696 *opt_offset = -1;
698 else if (nmatch > 1) {
699 *err_code = SCANOPT_ERR_OPT_AMBIGUOUS;
700 *opt_offset = -1;
703 return *err_code ? 0 : 1;
707 int scanopt (svoid, arg, optindex)
708 scanopt_t *svoid;
709 char **arg;
710 int *optindex;
712 char *optname = NULL, *optarg = NULL, *pstart;
713 int namelen = 0, arglen = 0;
714 int errcode = 0, has_next;
715 const optspec_t *optp;
716 struct _scanopt_t *s;
717 struct _aux *auxp;
718 int is_short;
719 int opt_offset = -1;
721 s = (struct _scanopt_t *) svoid;
723 /* Normalize return-parameters. */
724 SAFE_ASSIGN (arg, NULL);
725 SAFE_ASSIGN (optindex, s->index);
727 if (s->index >= s->argc)
728 return 0;
730 /* pstart always points to the start of our current scan. */
731 pstart = s->argv[s->index] + s->subscript;
732 if (!pstart)
733 return 0;
735 if (s->subscript == 0) {
737 /* test for exact match of "--" */
738 if (pstart[0] == '-' && pstart[1] == '-' && !pstart[2]) {
739 SAFE_ASSIGN (optindex, s->index + 1);
740 INC_INDEX (s, 1);
741 return 0;
744 /* Match an opt. */
745 if (matchlongopt
746 (pstart, &optname, &namelen, &optarg, &arglen)) {
748 /* it LOOKS like an opt, but is it one?! */
749 if (!find_opt
750 (s, 1, optname, namelen, &errcode,
751 &opt_offset)) {
752 scanopt_err (s, opt_offset, 0, errcode);
753 return errcode;
755 /* We handle this below. */
756 is_short = 0;
758 /* Check for short opt. */
760 else if (pstart[0] == '-' && pstart[1]) {
761 /* Pass through to below. */
762 is_short = 1;
763 s->subscript++;
764 pstart++;
767 else {
768 /* It's not an option. We're done. */
769 return 0;
773 /* We have to re-check the subscript status because it
774 * may have changed above. */
776 if (s->subscript != 0) {
778 /* we are somewhere in a run of short opts,
779 * e.g., at the 'z' in `tar -xzf` */
781 optname = pstart;
782 namelen = 1;
783 is_short = 1;
785 if (!find_opt
786 (s, 0, pstart, namelen, &errcode, &opt_offset)) {
787 return scanopt_err (s, opt_offset, 1, errcode);
790 optarg = pstart + 1;
791 if (!*optarg) {
792 optarg = NULL;
793 arglen = 0;
795 else
796 arglen = strlen (optarg);
799 /* At this point, we have a long or short option matched at opt_offset into
800 * the s->options array (and corresponding aux array).
801 * A trailing argument is in {optarg,arglen}, if any.
804 /* Look ahead in argv[] to see if there is something
805 * that we can use as an argument (if needed). */
806 has_next = s->index + 1 < s->argc
807 && strcmp ("--", s->argv[s->index + 1]) != 0;
809 optp = s->options + opt_offset;
810 auxp = s->aux + opt_offset;
812 /* case: no args allowed */
813 if (auxp->flags & ARG_NONE) {
814 if (optarg && !is_short) {
815 scanopt_err (s, opt_offset, is_short, errcode =
816 SCANOPT_ERR_ARG_NOT_ALLOWED);
817 INC_INDEX (s, 1);
818 return errcode;
820 else if (!optarg)
821 INC_INDEX (s, 1);
822 else
823 s->subscript++;
824 return optp->r_val;
827 /* case: required */
828 if (auxp->flags & ARG_REQ) {
829 if (!optarg && !has_next)
830 return scanopt_err (s, opt_offset, is_short,
831 SCANOPT_ERR_ARG_NOT_FOUND);
833 if (!optarg) {
834 /* Let the next argv element become the argument. */
835 SAFE_ASSIGN (arg, s->argv[s->index + 1]);
836 INC_INDEX (s, 2);
838 else {
839 SAFE_ASSIGN (arg, (char *) optarg);
840 INC_INDEX (s, 1);
842 return optp->r_val;
845 /* case: optional */
846 if (auxp->flags & ARG_OPT) {
847 SAFE_ASSIGN (arg, optarg);
848 INC_INDEX (s, 1);
849 return optp->r_val;
853 /* Should not reach here. */
854 return 0;
858 int scanopt_destroy (svoid)
859 scanopt_t *svoid;
861 struct _scanopt_t *s;
863 s = (struct _scanopt_t *) svoid;
864 if (s) {
865 if (s->aux)
866 free (s->aux);
867 free (s);
869 return 0;
873 /* vim:set tabstop=8 softtabstop=4 shiftwidth=4: */