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