/* flex - tool to generate fast lexical analyzers */
/* Copyright (c) 1990 The Regents of the University of California. */ /* All rights reserved. */
/* This code is derived from software contributed to Berkeley by */ /* Vern Paxson. */
/* The United States Government has rights in this work pursuant */ /* to contract no. DE-AC03-76SF00098 between the United States */ /* Department of Energy and the University of California. */
/* This file is part of flex. */
/* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */
/* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */
/* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */
struct _aux { int flags; /* The above hex flags. */ int namelen; /* Length of the actual option word, e.g., "--file[=foo]" is 4 */ int printlen; /* Length of entire string, e.g., "--file[=foo]" is 12 */
};
struct _scanopt_t { const optspec_t *options; /* List of options. */ struct _aux *aux; /* Auxiliary data about options. */ int optc; /* Number of options. */ int argc; /* Number of args. */ char **argv; /* Array of strings. */ int index; /* Used as: argv[index][subscript]. */ int subscript; char no_err_msg; /* If true, do not print errors. */ char has_long; char has_short;
};
/* Accessor functions. These WOULD be one-liners, but portability calls. */ staticconstchar *NAME PROTO ((struct _scanopt_t *, int)); staticint PRINTLEN PROTO ((struct _scanopt_t *, int)); staticint RVAL PROTO ((struct _scanopt_t *, int)); staticint FLAGS PROTO ((struct _scanopt_t *, int)); staticconstchar *DESC PROTO ((struct _scanopt_t *, int)); staticint scanopt_err PROTO ((struct _scanopt_t *, int, int)); staticint matchlongopt PROTO ((char *, char **, int *, char **, int *)); staticint find_opt
PROTO ((struct _scanopt_t *, int, char *, int, int *, int *opt_offset));
aux->namelen = 0; for (p = pname + 1; *p; p++) { /* detect required arg */ if (*p == '=' || isspace ((unsignedchar)*p)
|| !(aux->flags & IS_LONG)) { if (aux->namelen == 0)
aux->namelen = p - pname;
aux->flags |= ARG_REQ;
aux->flags &= ~ARG_NONE;
} /* detect optional arg. This overrides required arg. */ if (*p == '[') { if (aux->namelen == 0)
aux->namelen = p - pname;
aux->flags &= ~(ARG_REQ | ARG_NONE);
aux->flags |= ARG_OPT; break;
}
} if (aux->namelen == 0)
aux->namelen = p - pname;
} return (scanopt_t *) s;
}
#ifndef NO_SCANOPT_USAGE /* these structs are for scanopt_usage(). */ struct usg_elem { int idx; struct usg_elem *next; struct usg_elem *alias;
}; typedefstruct usg_elem usg_elem;
/* Prints a usage message based on contents of optlist. *Parameters: *scanner-Thescanner,alreadyinitializedwithscanopt_init(). *fp-Thefilestreamtowriteto. *usage-Texttobeprependedtooptionlist. *Return:Alwaysreturns0(zero). *Theoutputlookssomethinglikethis:
[indent][option,alias1,alias2...][indent][descriptionline1 descriptionline2...]
*/ int scanopt_usage (scanner, fp, usage)
scanopt_t *scanner;
FILE *fp; constchar *usage;
{ struct _scanopt_t *s; int i, columns, indent = 2;
usg_elem *byr_val = NULL; /* option indices sorted by r_val */
usg_elem *store; /* array of preallocated elements. */ int store_idx = 0;
usg_elem *ue; int maxlen[2]; int desccol = 0; int print_run = 0;
maxlen[0] = 0;
maxlen[1] = 0;
s = (struct _scanopt_t *) scanner;
if (usage) {
fprintf (fp, "%s\n", usage);
} else { /* Find the basename of argv[0] */ constchar *p;
p = s->argv[0] + strlen (s->argv[0]); while (p != s->argv[0] && *p != '/')
--p; if (*p == '/')
p++;
/* Sort by r_val and string. Yes, this is O(n*n), but n is small. */
store = (usg_elem *) malloc (s->optc * sizeof (usg_elem)); for (i = 0; i < s->optc; i++) {
/* grab the next preallocate node. */
ue = store + store_idx++;
ue->idx = i;
ue->next = ue->alias = NULL;
/* insert into list. */ if (!byr_val)
byr_val = ue; else { int found_alias = 0;
usg_elem **ue_curr, **ptr_if_no_alias = NULL;
ue_curr = &byr_val; while (*ue_curr) { if (RVAL (s, (*ue_curr)->idx) ==
RVAL (s, ue->idx)) { /* push onto the alias list. */
ue_curr = &((*ue_curr)->alias);
found_alias = 1; break;
} if (!ptr_if_no_alias
&&
STRCASECMP (NAME (s, (*ue_curr)->idx),
NAME (s, ue->idx)) > 0) {
ptr_if_no_alias = ue_curr;
}
ue_curr = &((*ue_curr)->next);
} if (!found_alias && ptr_if_no_alias)
ue_curr = ptr_if_no_alias;
ue->next = *ue_curr;
*ue_curr = ue;
}
}
#if0 if (1) {
printf ("ORIGINAL:\n"); for (i = 0; i < s->optc; i++)
printf ("%2d: %s\n", i, NAME (s, i));
printf ("SORTED:\n");
ue = byr_val; while (ue) {
usg_elem *ue2;
printf ("%2d: %s\n", ue->idx, NAME (s, ue->idx)); for (ue2 = ue->alias; ue2; ue2 = ue2->next)
printf (" +---> %2d: %s\n", ue2->idx,
NAME (s, ue2->idx));
ue = ue->next;
}
} #endif
/* Now build each row of output. */
/* first pass calculate how much room we need. */ for (ue = byr_val; ue; ue = ue->next) {
usg_elem *ap; int len = 0; int nshort = 0, nlong = 0;
#define CALC_LEN(i) do {\ if(FLAGS(s,i) & IS_LONG) \
len += (nlong++||nshort) ? 2+PRINTLEN(s,i) : PRINTLEN(s,i);\ else\
len += (nshort++||nlong)? 2+PRINTLEN(s,i) : PRINTLEN(s,i);\
}while(0)
if (!(FLAGS (s, ue->idx) & IS_LONG))
CALC_LEN (ue->idx);
/* do short aliases first. */ for (ap = ue->alias; ap; ap = ap->next) { if (FLAGS (s, ap->idx) & IS_LONG) continue;
CALC_LEN (ap->idx);
}
if (FLAGS (s, ue->idx) & IS_LONG)
CALC_LEN (ue->idx);
/* repeat the above loop, this time for long aliases. */ for (ap = ue->alias; ap; ap = ap->next) { if (!(FLAGS (s, ap->idx) & IS_LONG)) continue;
CALC_LEN (ap->idx);
}
if (len > maxlen[0])
maxlen[0] = len;
/* It's much easier to calculate length for description column! */
len = strlen (DESC (s, ue->idx)); if (len > maxlen[1])
maxlen[1] = len;
}
/* Determine how much room we have, and how much we will allocate to each col.
* Do not address pathological cases. Output will just be ugly. */
columns = get_cols () - 1; if (maxlen[0] + maxlen[1] + indent * 2 > columns) { /* col 0 gets whatever it wants. we'll wrap the desc col. */
maxlen[1] = columns - (maxlen[0] + indent * 2); if (maxlen[1] < 14) /* 14 is arbitrary lower limit on desc width. */
maxlen[1] = INT_MAX;
}
desccol = maxlen[0] + indent * 2;
/* Second pass (same as above loop), this time we print. */ /* Sloppy hack: We iterate twice. The first time we print short and long options.
The second time we print those lines that have ONLY long options. */ while (print_run++ < 2) { for (ue = byr_val; ue; ue = ue->next) {
usg_elem *ap; int nwords = 0, nchars = 0, has_short = 0;
/* TODO: get has_short schtick to work */
has_short = !(FLAGS (s, ue->idx) & IS_LONG); for (ap = ue->alias; ap; ap = ap->next) { if (!(FLAGS (s, ap->idx) & IS_LONG)) {
has_short = 1; break;
}
} if ((print_run == 1 && !has_short) ||
(print_run == 2 && has_short)) continue;
PRINT_SPACES (fp, indent);
nchars += indent;
/* Print, adding a ", " between aliases. */ #define PRINT_IT(i) do{\ if(nwords++)\
nchars+=fprintf(fp,", ");\
nchars+=fprintf(fp,"%s",s->options[i].opt_fmt);\
}while(0)
if (!(FLAGS (s, ue->idx) & IS_LONG))
PRINT_IT (ue->idx);
/* print short aliases first. */ for (ap = ue->alias; ap; ap = ap->next) { if (!(FLAGS (s, ap->idx) & IS_LONG))
PRINT_IT (ap->idx);
}
if (FLAGS (s, ue->idx) & IS_LONG)
PRINT_IT (ue->idx);
/* repeat the above loop, this time for long aliases. */ for (ap = ue->alias; ap; ap = ap->next) { if (FLAGS (s, ap->idx) & IS_LONG)
PRINT_IT (ap->idx);
}
/* pad to desccol */
PRINT_SPACES (fp, desccol - nchars);
/* Print description, wrapped to maxlen[1] columns. */ if (1) { constchar *pstart;
pstart = DESC (s, ue->idx); while (1) { int n = 0; constchar *lastws = NULL, *p;
p = pstart;
while (*p && n < maxlen[1]
&& *p != '\n') { if (isspace ((unsignedchar)(*p))
|| *p == '-') lastws =
p;
n++;
p++;
}
if (!*p) { /* hit end of desc. done. */
fprintf (fp, "%s\n",
pstart); break;
} elseif (*p == '\n') { /* print everything up to here then wrap. */
fprintf (fp, "%.*s\n", n,
pstart);
PRINT_SPACES (fp, desccol);
pstart = p + 1; continue;
} else { /* we hit the edge of the screen. wrap at space if possible. */ if (lastws) {
fprintf (fp, "%.*s\n",
(int)(lastws - pstart),
pstart);
pstart =
lastws + 1;
} else {
fprintf (fp, "%.*s\n",
n,
pstart);
pstart = p + 1;
}
PRINT_SPACES (fp, desccol); continue;
}
}
}
}
} /* end while */
free (store); return0;
} #endif/* no scanopt_usage */
staticint scanopt_err (s, is_short, err) struct _scanopt_t *s; int is_short; int err;
{ constchar *optname = ""; char optchar[2];
/* Match regex /--./ */
p = str; if (p[0] != '-' || p[1] != '-' || !p[2]) return0;
p += 2;
*optname = (char *) p;
/* find the end of optname */ while (*p && *p != '=')
++p;
*optlen = p - *optname;
if (!*p) /* an option with no '=...' part. */ return1;
/* We saw an '=' char. The rest of p is the arg. */
p++;
*arg = p; while (*p)
++p;
*arglen = p - *arg;
return1;
}
/* Internal. Look up long or short option by name. *Longoptionsmustmatchanon-ambiguousprefix,orexactmatch. *Shortoptionsmustbeexact. *Returnbooleantrueiffoundandnoerror.
* Error stored in err_code or zero if no error. */ staticint find_opt (s, lookup_long, optstart, len, err_code, opt_offset) struct _scanopt_t *s; int lookup_long; char *optstart; int len; int *err_code; int *opt_offset;
{ int nmatch = 0, lastr_val = 0, i;
/* pstart always points to the start of our current scan. */
pstart = s->argv[s->index] + s->subscript; if (!pstart) return0;
if (s->subscript == 0) {
/* test for exact match of "--" */ if (pstart[0] == '-' && pstart[1] == '-' && !pstart[2]) {
SAFE_ASSIGN (optindex, s->index + 1);
INC_INDEX (s, 1); return0;
}
/* Match an opt. */ if (matchlongopt
(pstart, &optname, &namelen, &optarg, &arglen)) {
/* it LOOKS like an opt, but is it one?! */ if (!find_opt
(s, 1, optname, namelen, &errcode,
&opt_offset)) {
scanopt_err (s, 0, errcode); return errcode;
} /* We handle this below. */
is_short = 0;
/* Check for short opt. */
} elseif (pstart[0] == '-' && pstart[1]) { /* Pass through to below. */
is_short = 1;
s->subscript++;
pstart++;
}
else { /* It's not an option. We're done. */ return0;
}
}
/* We have to re-check the subscript status because it
* may have changed above. */
if (s->subscript != 0) {
/* we are somewhere in a run of short opts,
* e.g., at the 'z' in `tar -xzf` */
/* At this point, we have a long or short option matched at opt_offset into *thes->optionsarray(andcorrespondingauxarray). *Atrailingargumentisin{optarg,arglen},ifany.
*/
/* Look ahead in argv[] to see if there is something
* that we can use as an argument (if needed). */
has_next = s->index + 1 < s->argc
&& strcmp ("--", s->argv[s->index + 1]) != 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.