/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1985-2010 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* Phong Vo <kpv@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Glenn Fowler
* AT&T Research
*
* command line option parser and usage formatter
* its a monster but its all in one place
* widen your window while you're at it
*/
#include <optlib.h>
#include <debug.h>
#include <ccode.h>
#include <ctype.h>
#include <errno.h>
typedef struct Attr_s
{
const char* name;
int flag;
} Attr_t;
typedef struct Help_s
{
} Help_t;
typedef struct Font_s
{
} Font_t;
typedef struct List_s
{
} List_t;
typedef struct Msg_s
{
} Msg_t;
typedef struct Save_s
{
} Save_t;
typedef struct Push_s
{
} Push_t;
typedef struct Indent_s
{
} Indent_t;
{
0,2, 4,10, 12,18, 20,26, 28,34, 36,42, 44,50, 0,0
};
{
"", "", "", "", "", "",
"", "", "", "", "", "",
"</TT>","<TT>","\\fP", "\\f5", "", "",
};
#if !_PACKAGE_astsa
#define C(s) ERROR_catalog(s)
#define T(i,c,m) (X(c)?translate(i,c,C(m)):(m))
#define X(c) (ERROR_translating()&&(c)!=native)
#define Z(x) C(x),sizeof(x)-1
/*
* translate with C_LC_MESSAGES_libast[] check
*/
static char*
{
if (!X(cat))
return (char*)msg;
}
#else
#define C(s) s
#define T(i,c,m) m
#define X(c) 0
#define Z(x) C(x),sizeof(x)-1
#endif
{
'-', 0,
0,
'+', C("NAME"),
C("options available to all \bast\b commands"),
'+', C("DESCRIPTION"),
C("\b-?\b and \b--?\b* options are the same \
for all \bast\b commands. For any \aitem\a below, if \b--\b\aitem\a is not \
supported by a given command then it is equivalent to \b--\?\?\b\aitem\a. The \
\b--\?\?\b form should be used for portability. All output is written to the \
standard error."),
};
{
Z("List all implementation info."),
Z("List detailed info in program readable form."),
C("help"), "", -1,
Z("List detailed help option info."),
Z("List detailed info in html."),
Z("List the usage translation key strings with C style escapes."),
Z("List long option usage."),
Z("List detailed info in displayed man page form."),
Z("List detailed info in nroff."),
Z("List short and long option details."),
Z("List posix getopt usage."),
Z("List short option usage."),
Z("List the usage string with C style escapes."),
};
{
':', C("\?\?-\alabel\a"),
C("List implementation info matching \alabel\a*."),
':', C("\?\?\aname\a"),
C("Equivalent to \b--help=\b\aname\a."),
':', C("\?\?"),
C("Equivalent to \b--\?\?options\b."),
':', C("\?\?\?\?"),
C("Equivalent to \b--\?\?man\b."),
':', C("\?\?\?\?\?\?"),
C("Equivalent to \b--\?\?help\b."),
':', C("\?\?\?\?\?\?\aitem\a"),
C("If the next argument is \b--\b\aoption\a then list \
the \aoption\a output in the \aitem\a style. Otherwise print \
\bversion=\b\an\a where \an\a>0 if \b--\?\?\b\aitem\a is supported, \b0\b \
if not."),
':', C("\?\?\?\?\?\?ESC"),
C("Emit escape codes even if output is not a terminal."),
':', C("\?\?\?\?\?\?TEST"),
C("Massage the output for regression testing."),
};
{
"flag", OPT_flag,
"hidden", OPT_hidden,
"ignorecase", OPT_ignorecase,
"invert", OPT_invert,
"listof", OPT_listof,
"number", OPT_number,
"oneof", OPT_oneof,
"optional", OPT_optional,
"string", OPT_string,
};
static const char* heading[] =
{
C("INDEX"),
C("USER COMMANDS"),
C("SYSTEM LIBRARY"),
C("USER LIBRARY"),
C("FILE FORMATS"),
C("MISCELLANEOUS"),
C("GAMES and DEMOS"),
C("SPECIAL FILES"),
C("ADMINISTRATIVE COMMANDS"),
C("GUIs"),
};
/*
* list of common man page strings
* NOTE: add but do not delete from this table
*/
{
{ C("APPLICATION USAGE") },
{ C("ASYNCHRONOUS EVENTS") },
{ C("BUGS") },
{ C("CAVEATS") },
{ C("CONSEQUENCES OF ERRORS") },
{ C("DESCRIPTION") },
{ C("ENVIRONMENT VARIABLES") },
{ C("EXAMPLES") },
{ C("EXIT STATUS") },
{ C("EXTENDED DESCRIPTION") },
{ C("INPUT FILES") },
{ C("LIBRARY") },
{ C("NAME") },
{ C("OPERANDS") },
{ C("OPTIONS") },
{ C("OUTPUT FILES") },
{ C("SEE ALSO") },
{ C("STDERR") },
{ C("STDIN") },
{ C("STDOUT") },
{ C("SYNOPSIS") },
{ C("author") },
{ C("copyright") },
{ C("license") },
{ C("name") },
{ C("path") },
{ C("version") },
};
/*
* 2007-03-19 move opt_info from _opt_info_ to (*_opt_data_)
* to allow future Opt_t growth
* by 2009 _opt_info_ can be static
*/
#if _BLD_ast && defined(__EXPORT__)
#define extern extern __EXPORT__
#endif
extern Opt_t _opt_info_;
#undef extern
#if _BLD_DEBUG
/*
* debug usage string segment format
*/
static char*
show(register char* s)
{
register int c;
register char* t;
register char* e;
if (!s)
return "(null)";
t = buf;
while (t < e)
{
switch (c = *s++)
{
case 0:
goto done;
case '\a':
*t++ = '\\';
c = 'a';
break;
case '\b':
*t++ = '\\';
c = 'b';
break;
case '\f':
*t++ = '\\';
c = 'f';
break;
case '\n':
*t++ = '\\';
c = 'n';
break;
case '\t':
*t++ = '\\';
c = 't';
break;
case '\v':
*t++ = '\\';
c = 'v';
break;
}
*t++ = c;
}
done:
*t = 0;
return buf;
}
#endif
/*
* pop the push stack
*/
static Push_t*
{
{
}
return 0;
}
/*
* skip over line space to the next token
*/
static char*
{
register char* b;
s++;
if (*s == '\n')
{
b = s;
while (*++s == ' ' || *s == '\t' || *s == '\r');
if (*s == '\n')
return b;
}
return s;
}
/*
* skip to t1 or t2 or t3, whichever first, in s
* n==0 outside [...]
* n==1 inside [...] before ?
* n==2 inside [...] after ?
* b==0 outside {...}
* b==1 inside {...}
* past skips past the terminator to the next token
* otherwise a pointer to the terminator is returned
*
* ]] for ] inside [...]
* ?? for ? inside [...] before ?
* :: for : inside [...] before ?
*/
static char*
skip(register char* s, register int t1, register int t2, register int t3, register int n, register int b, int past, int version)
{
register int c;
register int on = n;
register int ob = b;
if (version < 1)
{
n = n >= 1;
for (;;)
{
switch (*s++)
{
case 0:
break;
case '[':
n++;
continue;
case ']':
if (--n <= 0)
break;
continue;
default:
continue;
}
break;
}
}
else while (c = *s++)
{
message((-22, "optget: skip t1=%c t2=%c t3=%c n=%d b=%d `%s'", t1 ? t1 : '@', t2 ? t2 : '@', t3 ? t3 : '@', n, b, show(s - 1)));
if (c == '[')
{
if (!n)
n = 1;
}
else if (c == ']')
{
if (n)
{
if (*s == ']')
s++;
else if (on == 1)
break;
else
n = 0;
}
}
else if (c == GO)
{
if (n == 0)
b++;
}
else if (c == OG)
{
if (n == 0 && b-- == ob)
break;
}
else if (c == '?')
{
if (n == 1)
{
if (*s == '?')
s++;
else
{
break;
n = 2;
}
}
}
{
if (n == 1 && c == ':' && *s == c)
s++;
else
break;
}
}
}
/*
* match s with t
* t translated if possible
* imbedded { - _ ' } ignored
* * separates required prefix from optional suffix
* otherwise prefix match
*/
static int
{
register char* w;
register char* x;
char* xw;
char* ww;
int n;
int v;
int j;
for (n = 0; n < 2; n++)
{
if (n)
x = t;
else
{
if (catalog)
{
w = sfprints("%-.*s", w - t, t);
if (x == w)
continue;
}
if (x == t)
continue;
}
do
{
v = 0;
xw = x;
w = ww = s;
while (*x && *w)
{
if (isupper(*x))
xw = x;
if (isupper(*w))
ww = w;
if (*x == '*' && !v++ || *x == '\a')
{
if (*x == '\a')
do
{
if (!*++x)
{
x--;
break;
}
} while (*x != '\a');
j = *(x + 1);
if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
while (*w)
w++;
}
else if (sep(*x))
xw = ++x;
else if (sep(*w) && w != s)
ww = ++w;
else if (*x == *w)
{
x++;
w++;
}
break;
else
{
if (x != xw)
{
x++;
if (!*x)
break;
if (sep(*x))
x++;
xw = x;
}
while (w > ww && *w != *x)
w--;
}
}
if (!*w)
{
if (!v)
{
for (;;)
{
switch (*x++)
{
case 0:
case ':':
case '|':
case '?':
case ']':
return 1;
case '*':
break;
default:
continue;
}
break;
}
break;
}
return 1;
}
}
return 0;
}
/*
* prefix search for s in tab with num elements of size
* with optional translation
*/
static void*
{
register char* p;
register char* e;
return (void*)p;
return 0;
}
/*
* save s and return the saved pointer
*/
static char*
save(const char* s)
{
Save_t* p;
Dtdisc_t* d;
if (!dict)
{
return (char*)s;
return (char*)s;
}
{
return (char*)s;
}
return p->text;
}
/*
* initialize the attributes for pass p from opt string s
*/
static int
{
register char* t;
register char* u;
register int c;
register int a;
register int n;
{
#if !_PACKAGE_astsa
#endif
for (n = 0; n < elementsof(C_LC_MESSAGES_libast); n++)
for (n = 0, t = OPT_FLAGS; *t; t++)
map[*t] = ++n;
}
#if _BLD_DEBUG
#endif
p->oopts = s;
p->version = 0;
p->prefix = 2;
p->section = 1;
p->flags = 0;
p->catalog = 0;
s = next(s, 0);
if (*s == ':')
s++;
if (*s == '+')
s++;
s = next(s, 0);
if (*s++ == '[')
{
if (*s == '+')
p->version = 1;
else if (*s++ == '-')
{
if (*s == '?' || *s == ']')
p->version = 1;
else
{
if (!isdigit(*s))
p->version = 1;
else
while (isdigit(*s))
while (*s && *s != '?' && *s != ']')
{
c = *s++;
if (!isdigit(*s))
n = 1;
else
{
n = 0;
while (isdigit(*s))
n = n * 10 + (*s++ - '0');
}
switch (c)
{
case '+':
break;
case 'c':
break;
case 'i':
p->flags |= OPT_ignore;
break;
case 'l':
break;
case 'n':
p->flags |= OPT_numeric;
break;
case 'o':
break;
case 'p':
p->prefix = n;
break;
case 's':
p->section = n;
if (n > 1 && n < 6)
{
p->flags |= OPT_functions;
p->prefix = 0;
}
break;
}
}
}
}
while (*s)
if (*s++ == ']')
{
while (isspace(*s))
s++;
if (*s++ == '[')
{
if (*s++ != '-')
{
{
for (s += 5; *s == '\a' || *s == '\b' || *s == '\v' || *s == ' '; s++);
if (*s != '\f')
{
for (t = s; *t && *t != ' ' && *t != ']'; t++);
if (t > s)
{
u = t;
if (*(t - 1) == '\a' || *(t - 1) == '\b' || *(t - 1) == '\v')
t--;
if (t > s)
{
while (*u == ' ' || *u == '\\')
u++;
if (*u == '-' || *u == ']')
}
}
}
}
break;
}
if (*s == '-')
s++;
p->catalog = s += 8;
}
}
}
if (!error_info.id)
{
p->id = "command";
}
if (s = p->catalog)
p->catalog = ((t = strchr(s, ']')) && (!p->id || (t - s) != strlen(p->id) || !strneq(s, p->id, t - s))) ? save(sfprints("%-.*s", t - s, s)) : (char*)0;
if (!p->catalog)
{
else
}
s = p->oopts;
if (*s == ':')
s++;
if (*s == '+')
{
s++;
}
s = next(s, 0);
if (*s != '[')
for (t = s, a = 0; *t; t++)
if (!a && *t == '-')
{
break;
}
else if (*t == '[')
a++;
else if (*t == ']')
a--;
if (!p->version && (t = strchr(s, '(')) && strchr(t, ')') && (opt_info.state->cp || (opt_info.state->cp = sfstropen())))
{
/*
* solaris long option compatibility
*/
p->version = 1;
for (t = p->oopts; t < s; t++)
n = t - p->oopts;
c = *s++;
while (c)
{
if (a = (c = *s++) == ':')
c = *s++;
if (c == '(')
{
for (;;)
{
while ((c = *s++) && c != ')')
if (!c || (c = *s++) != '(')
break;
}
}
if (a)
}
return -1;
s += n;
}
p->opts = s;
message((-1, "version=%d prefix=%d section=%d flags=%04x id=%s catalog=%s", p->version, p->prefix, p->section, p->flags, p->id, p->catalog));
return 0;
}
/*
*/
static const char*
{
switch (style)
{
case STYLE_html:
case STYLE_nroff:
case STYLE_short:
case STYLE_long:
case STYLE_posix:
case STYLE_api:
break;
default:
break;
}
return "";
}
/*
* expand \f...\f info
* *p set to next char after second \f
* expanded value returned
*/
static char*
{
register int c;
register char* b = s;
int n;
c = 1;
while ((!e || s < e) && (c = *s++) && c != '\f');
if (!c)
s--;
if (*b == '?')
{
if (!*++b || streq(b, "NAME"))
{
if (!(b = id))
b = "command";
n = 0;
}
else
n = 1;
}
else if (!opt_info.disc || !opt_info.disc->infof || (*opt_info.disc->infof)(&opt_info, ip, b, opt_info.disc) < 0)
n = 0;
*p = s;
s += n;
else
s = "error";
return s;
}
/*
* push \f...\f info
*/
static Push_t*
{
register char* b;
int n;
n = strlen(b);
{
}
else
return tsp;
}
/*
* push translation
*/
static Push_t*
localize(Push_t* psp, char* s, char* e, int term, int n, Sfio_t* ip, int version, char* id, char* catalog)
{
char* t;
char* u;
int c;
if (e && t > e)
t = e;
while (s < t)
{
switch (c = *s++)
{
case ':':
case '?':
if (term && *s == c)
s++;
break;
case ']':
if (*s == c)
s++;
break;
}
}
return 0;
n = strlen(u);
{
}
return tsp;
}
/*
* output label s from [ ...label...[?...] ] to sp
* 1 returned if the label was translated
*/
static int
label(register Sfio_t* sp, int sep, register char* s, int about, int z, int level, int style, int f, Sfio_t* ip, int version, char* id, char* catalog)
{
register int c;
register char* t;
register char* e;
int ostyle;
int a;
int i;
char* p;
char* w;
char* y;
int va;
int r = 0;
int n = 1;
style = 0;
if (z < 0)
e = s + strlen(s);
else
e = s + z;
if (sep > 0)
{
}
va = 0;
y = 0;
if (about)
if (version < 1)
{
a = 0;
for (;;)
{
if (s >= e)
return r;
switch (c = *s++)
{
case '[':
a++;
break;
case ']':
if (--a < 0)
return r;
break;
}
}
}
{
va = 0;
if (*++p == '?' || *p == *(p - 1))
{
p++;
va |= OPT_optional;
}
y = p + 1;
}
{
}
switch (*s)
{
case '\a':
if (f == FONT_ITALIC)
s++;
f = 0;
break;
case '\b':
if (f == FONT_BOLD)
s++;
f = 0;
break;
case '\v':
if (f == FONT_LITERAL)
s++;
f = 0;
break;
default:
if (f)
break;
}
for (;;)
{
if (s >= e)
{
goto restore;
continue;
}
switch (c = *s++)
{
case '(':
if (n)
{
n = 0;
if (f)
{
f = 0;
}
}
break;
case '?':
case ':':
case ']':
break;
if (y)
{
if (va & OPT_optional)
if (va & OPT_optional)
y = 0;
}
switch (c)
{
case '?':
if (*s == '?')
s++;
else if (*s == ']' && *(s + 1) != ']')
continue;
else if (sep)
goto restore;
{
}
break;
case ']':
if (sep && *s++ != ']')
goto restore;
break;
case ':':
if (sep && *s++ != ':')
goto restore;
break;
}
break;
case '\a':
a = FONT_ITALIC;
if (f & ~a)
{
f = 0;
}
if (!f && style == STYLE_html)
{
if (*t == c && *++t == '(')
{
w = t;
while (++t < e && isdigit(*t));
if (t < e && *t == ')' && t > w + 1)
{
, t - w - 1, w + 1
, w - s - 1, s
, w - s - 1, s
, t - w + 1, w
);
s = t + 1;
continue;
}
}
}
continue;
case '\b':
a = FONT_BOLD;
goto setfont;
case '\f':
{
}
else
{
}
continue;
case '\n':
for (i = 0; i < level; i++)
continue;
case '\v':
a = FONT_LITERAL;
goto setfont;
case '<':
if (style == STYLE_html)
{
c = 0;
for (t = s; t < e; t++)
{
if (*t == '@')
{
if (c)
break;
c = 1;
}
else if (*t == '>')
{
if (c)
{
s = t + 1;
}
break;
}
else
break;
}
continue;
}
break;
case '>':
if (style == STYLE_html)
{
continue;
}
break;
case '&':
if (style == STYLE_html)
{
continue;
}
break;
case '-':
if (ostyle == STYLE_nroff)
break;
case '.':
if (ostyle == STYLE_nroff)
{
}
break;
case '\\':
if (ostyle == STYLE_nroff)
{
c = 'e';
}
break;
case ' ':
if (ostyle == STYLE_nroff)
break;
}
}
if (f)
if (about)
if (psp)
return r;
}
/*
* output args description to sp from p of length n
*/
static void
args(register Sfio_t* sp, register char* p, register int n, int flags, int style, Sfio_t* ip, int version, char* id, char* catalog)
{
register int i;
register char* t;
register char* o;
register char* a = 0;
char* b;
int sep;
if (flags & OPT_functions)
sep = '\t';
else
{
sep = ' ';
for (;;)
{
t = (char*)memchr(p, '\n', n);
{
if (!(a = id))
a = "...";
sfprintf(sp, "\t%s%s%s%s[%s%s%s%s%s]", font(FONT_BOLD, style, 1), a, font(FONT_BOLD, style, 0), b, b, font(FONT_ITALIC, style, 1), o, font(FONT_ITALIC, style, 0), b);
}
else if (a)
sfprintf(sp, "%*.*s%s%s%s[%s%s%s]", OPT_USAGE - 1, OPT_USAGE - 1, T(NiL, ID, "Or:"), b, a, b, b, o, b);
else
{
a = "...";
}
if (!t)
break;
i = ++t - p;
if (i)
{
if (X(catalog))
{
else
}
else
}
if (style == STYLE_html)
else if (style == STYLE_nroff)
p = t;
n -= i;
while (n > 0 && (*p == ' ' || *p == '\t'))
{
p++;
n--;
}
}
}
if (n)
}
/*
* output [+-...label...?...] label s to sp
* according to {...} level and style
* return 0:header 1:paragraph
*/
static int
item(Sfio_t* sp, char* s, int about, int level, int style, Sfio_t* ip, int version, char* id, char* catalog)
{
register char* t;
int n;
int par;
if (*s == '\n')
{
par = 0;
if (style >= STYLE_nroff)
else
{
if (style == STYLE_html)
else
for (n = 0; n < level; n++)
}
if (style >= STYLE_nroff)
else if (style == STYLE_html)
}
else if (*s != ']' && (*s != '?' || *(s + 1) == '?'))
{
par = 0;
if (level)
{
if (style >= STYLE_nroff)
else
for (n = 0; n < level; n++)
}
if (style == STYLE_html)
{
if (!level)
if (s[-1] == '-' && s[0] == 'l' && s[1] == 'i' && s[2] == 'c' && s[3] == 'e' && s[4] == 'n' && s[5] == 's' && s[6] == 'e' && s[7] == '?')
for (t = s + 8; *t && *t != ']'; t++)
if (t[0] == 'p' && (!strncmp(t, "proprietary", 11) || !strncmp(t, "private", 7)) || t[0] == 'n' && !strncmp(t, "noncommercial", 13))
{
break;
}
if (!level)
}
else
{
if (!level)
{
if (style >= STYLE_nroff)
}
}
}
else
{
par = 1;
if (style >= STYLE_nroff)
}
for (n = 0; n < level; n++)
return par;
}
/*
* output text to sp from p according to style
*/
#if _BLD_DEBUG
static char*
trace_textout(Sfio_t* sp, register char* p, int style, int level, int bump, Sfio_t* ip, int version, char* id, char* catalog, int line)
{
static int depth = 0;
message((-21, "opthelp: txt#%d +++ %2d \"%s\" style=%d level=%d bump=%d", line, ++depth, show(p), style, level, bump));
return p;
}
#endif
static char*
textout(Sfio_t* sp, register char* p, int style, int level, int bump, Sfio_t* ip, int version, char* id, char* catalog)
{
#if _BLD_DEBUG
#define textout(sp,p,style,level,bump,ip,version,id,catalog) trace_textout(sp,p,style,level,bump,ip,version,id,catalog,__LINE__)
#endif
register char* t;
register int c;
register int n;
char* e;
int a;
int f;
int par;
int about;
int ident = 0;
about = 0;
if ((c = *p) == GO)
{
for (;;)
{
if (*p == GO)
{
if (level > 1)
level++;
level++;
}
else if (*p != OG)
{
if (level <= 1 || *p != '[' || *(p + 1) != '-' || style == STYLE_man && *(p + 2) == '?' || isalpha(*(p + 2)))
break;
}
return p + 1;
}
if (*p == '\f')
{
else
{
}
}
if (*p != '[')
return p;
c = *++p;
if (level > 1)
level++;
level++;
}
{
{
about = 1;
if (*(p + 1) == '-')
p++;
}
else
for (;;)
{
if (*p == '[')
{
if ((c = *++p) != '-')
break;
}
else if (*p == GO)
goto again;
else if (*p == OG)
return p + 1;
}
}
{
{
if ((c = *p) != '?')
e = C("version");
for (;;)
{
while (isspace(*(p + 1)))
p++;
e = p;
if (e[1] == '@' && e[2] == '(' && e[3] == '#' && e[4] == ')')
p = e + 4;
else if (e[1] == '$' && e[2] == 'I' && e[3] == 'd' && e[4] == ':' && e[5] == ' ')
{
p = e + 5;
ident = 1;
}
else
break;
}
}
else
{
{
while (isdigit(*t))
t++;
if (*t == ':')
t++;
}
else if (isalnum(c) && *t-- == ':')
{
if (X(catalog) || *t == *(t + 2))
t += 2;
else
{
*((t = e) + 1) = '|';
}
}
c = *p;
}
par = 0;
}
else
{
if (style >= STYLE_nroff)
else if (c == '?')
for (n = 0; n < level; n++)
par = 0;
}
if (c == ':')
if ((c == ']' || c == '?' && *(p + 1) == ']' && *(p + 2) != ']' && p++) && (c = *(p = next(p + 1, version))) == GO)
{
{
p++;
goto again;
}
}
else if (c == '?' || c == ' ')
{
p++;
if (c == ' ')
else
{
{
}
if (style < STYLE_nroff)
for (n = 0; n < bump + 1; n++)
}
f = 0;
for (;;)
{
switch (c = *p++)
{
case 0:
{
if (f)
return p - 1;
}
continue;
case ']':
break;
if (*p != ']')
{
if (f)
{
f = 0;
}
for (;;)
{
{
char* o;
char* v;
int j;
int m;
int ol;
int vl;
a = 0;
o = 0;
v = 0;
if (*++p == '?' || *p == *(p - 1))
{
p++;
a |= OPT_optional;
}
{
while (*p == ':')
{
m = p - t;
if (*t == '!')
{
o = t + 1;
ol = m - 1;
}
else if (*t == '=')
{
v = t + 1;
vl = m - 1;
}
else
for (j = 0; j < elementsof(attrs); j++)
{
break;
}
}
}
if (a & OPT_optional)
{
if (o)
{
t = o + ol;
while (o < t)
{
if (((c = *o++) == ':' || c == '?') && *o == c)
o++;
}
}
else
}
if (v)
{
t = v + vl;
while (v < t)
{
if (((c = *v++) == ':' || c == '?') && *v == c)
v++;
}
}
}
{
{
p++;
goto again;
}
}
{
p++;
goto again;
}
else if (*p == '\f')
{
p++;
if (style != STYLE_keys)
{
else
{
}
}
}
else if (!*p)
{
break;
}
else if (*p != OG)
break;
else
{
p++;
break;
}
}
return p;
}
p++;
break;
case '\a':
a = FONT_ITALIC;
if (f & ~a)
{
f = 0;
}
if (!f && style == STYLE_html)
{
if (*t == c && *++t == '(')
{
e = t;
while (isdigit(*++t));
if (*t == ')' && t > e + 1)
{
, t - e - 1, e + 1
, e - p - 1, p
, e - p - 1, p
, t - e + 1, e
);
p = t + 1;
continue;
}
}
}
continue;
case '\b':
a = FONT_BOLD;
goto setfont;
case '\f':
if (style != STYLE_keys)
{
else
{
}
}
continue;
case '\v':
a = FONT_LITERAL;
goto setfont;
case ' ':
if (ident && *p == '$')
{
while (*++p)
if (*p == ']')
{
if (*(p + 1) != ']')
break;
p++;
}
continue;
}
case '\n':
case '\r':
case '\t':
while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
p++;
continue;
c = ' ';
break;
case '<':
if (style == STYLE_html)
{
c = 0;
for (t = p; *t; t++)
{
if (*t == '@')
{
if (c)
break;
c = 1;
}
else if (*t == '>')
{
if (c)
{
p = t + 1;
}
break;
}
else
break;
}
continue;
}
break;
case '>':
if (style == STYLE_html)
{
continue;
}
break;
case '&':
if (style == STYLE_html)
{
continue;
}
break;
case '-':
if (style == STYLE_nroff)
break;
case '.':
if (style == STYLE_nroff)
{
}
break;
case '\\':
if (style == STYLE_nroff)
{
c = 'e';
}
break;
}
}
}
{
p++;
goto again;
}
return p;
}
/*
* generate optget() help [...] list from lp
*/
static void
{
{
}
}
/*
* return pointer to help message sans `Usage: command'
* if oopts is 0 then opt_info.state->pass is used
* what:
* 0 ?short by default, ?long if any long options used
* * otherwise see help_text[] (--???)
* external formatter:
* \a...\a italic
* \b...\b bold
* \f...\f discipline infof callback on ...
* \v...\v literal
* internal formatter:
* \t indent
* \n newline
* margin flush pops to previous indent
*/
char*
{
register int c;
register char* p;
char* t;
char* x;
char* w;
char* u;
char* y;
char* s;
char* d;
char* v;
char* ov;
char* pp;
char* rb;
char* re;
int f;
int i;
int j;
int m;
int n;
int a;
int sl;
int vl;
int ol;
int wl;
int xl;
int rm;
int ts;
int co;
int z;
int style;
int head;
int margin;
int mode;
int mutex;
int prefix;
int version;
long tp;
char* id;
char* catalog;
Optpass_t* o;
Optpass_t* q;
Optpass_t* e;
short* pt;
int flags = 0;
int matched = 0;
int paragraph = 0;
goto nospace;
if (!what)
else if (!*what)
else if (*what != '?')
style = STYLE_match;
else if (!*(what + 1))
else if ((hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), (char*)what + 1)) && hp->style >= 0)
{
}
else
{
goto nospace;
for (i = 0; i < elementsof(help_head); i++)
for (i = 0; i < elementsof(styles); i++)
for (i = 0; i < elementsof(help_tail); i++)
goto nospace;
}
if (opts)
{
{
break;
}
{
o = &one;
goto nospace;
}
e = o + 1;
}
{
}
{
e = o + 1;
}
else
if (style <= STYLE_usage)
{
goto nospace;
goto nospace;
}
switch (style)
{
case STYLE_api:
case STYLE_html:
case STYLE_nroff:
break;
case STYLE_usage:
case STYLE_keys:
for (q = o; q < e; q++)
o = q;
/*FALLTHROUGH*/
case STYLE_posix:
break;
default:
{
if (x = getenv("ERROR_OPTIONS"))
{
if (strmatch(x, "*noemphasi*"))
break;
if (strmatch(x, "*emphasi*"))
{
break;
}
}
}
break;
}
x = "";
xl = 0;
for (q = o; q < e; q++)
{
if (q->flags & OPT_ignore)
continue;
p = q->opts;
switch (style)
{
case STYLE_usage:
if (xl)
else
xl = 1;
psp = 0;
for (;;)
{
switch (c = *p++)
{
case 0:
goto style_usage;
continue;
case '\a':
c = 'a';
break;
case '\b':
c = 'b';
break;
case '\f':
else
{
}
continue;
case '\n':
c = 'n';
break;
case '\r':
c = 'r';
break;
case '\t':
c = 't';
break;
case '\v':
c = 'v';
break;
case '"':
c = '"';
break;
case '\'':
c = '\'';
break;
case '\\':
c = '\\';
break;
default:
continue;
}
}
continue;
case STYLE_keys:
a = 0;
psp = 0;
vl = 0;
for (;;)
{
if (!(c = *p++))
{
break;
continue;
}
if (c == '\f')
{
else
{
}
continue;
}
f = z = 1;
t = 0;
if (a == 0 && (c == ' ' || c == '\n' && *p == '\n'))
{
if (c == ' ' && *p == ']')
{
p++;
continue;
}
if (*p == '\n')
p++;
a = c;
}
else if (c == '\n')
{
if (a == ' ')
a = -1;
else if (a == '\n' || *p == '\n')
{
a = -1;
p++;
}
continue;
}
else if ((c == ':' || c == '#') && (*p == '[' || *p == '?' && *(p + 1) == '[' && p++))
p++;
else if (c != '[')
{
if (c == GO)
vl++;
else if (c == OG)
vl--;
continue;
}
else if (*p == ' ')
{
p++;
continue;
}
else if (*p == '-')
{
z = 0;
if (*++p == '-')
{
continue;
}
}
else if (*p == '+')
{
p++;
if (vl > 0 && *p != '\a')
{
f = 0;
if (*p == '?')
p++;
}
}
else
{
if (*p == ':')
p++;
}
if (f && *p == '?' && *(p + 1) != '?')
{
f = 0;
if (z)
p++;
else
}
if (*p == ']' && *(p + 1) != ']')
{
p++;
continue;
}
if (!*p)
{
if (!t)
break;
p = t;
t = 0;
}
xl = 1;
/*UNDENT...*/
for (;;)
{
if (!(c = *p++))
{
if (t)
{
p = t;
t = 0;
}
{
p--;
break;
}
continue;
}
if (a > 0)
{
if (c == '\n')
{
if (a == ' ')
{
a = -1;
break;
}
if (a == '\n' || *p == '\n')
{
a = -1;
p++;
break;
}
}
}
else if (c == ']')
{
if (*p != ']')
{
{
xl = 0;
}
else
break;
}
continue;
}
switch (c)
{
case '?':
if (f)
{
if (*p == '?')
{
p++;
}
else
{
f = 0;
{
xl = 0;
}
else
if (z && (*p != ']' || *(p + 1) == ']'))
{
if (xl)
{
}
xl = 1;
}
else
{
if (*p == '?')
p++;
}
}
}
else
continue;
case ':':
if (f && *p == ':')
p++;
continue;
case '\a':
c = 'a';
break;
case '\b':
c = 'b';
break;
case '\f':
c = 'f';
break;
case '\n':
c = 'n';
break;
case '\r':
c = 'r';
break;
case '\t':
c = 't';
break;
case '\v':
c = 'v';
break;
case '"':
c = '"';
break;
case '\\':
c = '\\';
break;
case CC_esc:
c = 'E';
break;
default:
continue;
}
}
/*...INDENT*/
if (xl)
{
}
}
continue;
}
z = 0;
head = 0;
mode = 0;
mutex = 0;
{
style = STYLE_short;
if (sp_body)
{
sp_body = 0;
}
}
style = STYLE_long;
if (*p == ':')
p++;
if (*p == '+')
{
p++;
goto nospace;
}
else if (style >= STYLE_match)
else
psp = 0;
for (;;)
{
{
break;
continue;
}
if (*p == '\f')
{
else
{
}
continue;
}
if (*p == '\n' || *p == ' ')
{
while (*++p)
if (*p == '\n')
{
while (*++p == ' ' || *p == '\t' || *p == '\r');
if (*p == '\n')
break;
}
xl = p - x;
if (!*p)
break;
continue;
}
if (*p == OG)
{
p++;
continue;
}
if (z < 0)
z = 0;
a = 0;
f = 0;
w = 0;
d = 0;
s = 0;
sl = 0;
vl = 0;
if (*p == '[')
{
{
{
if (*(p + 1) != '-')
{
goto nospace;
else
continue;
}
}
{
s = C("version");
else
s = p + 1;
w = (char*)what;
if (*s != '-' || *(w + 1) == '-')
{
if (*s == '-')
s++;
if (*(w + 1) == '-')
w++;
{
if (*(p + 1) == '-')
p++;
matched = -1;
continue;
}
}
}
if (!z)
z = -1;
}
else if (c == '+')
{
{
if (!sp_head)
{
goto nospace;
}
continue;
}
{
if (paragraph)
{
if (p[1] == '?')
{
continue;
}
paragraph = 0;
}
{
matched = -1;
paragraph = 1;
continue;
}
}
if (!z)
z = -1;
}
{
mutex++;
continue;
}
else
{
if (c == '!')
{
a |= OPT_invert;
p++;
}
rb = p;
if (*p != ':')
{
s = p;
if (*(p + 1) == '|')
{
while (*++p && *p != '=' && *p != '!' && *p != ':' && *p != '?');
if ((p - s) > 1)
sl = p - s;
if (*p == '!')
a |= OPT_invert;
}
if (*(p + 1) == '\f')
p++;
else
if (sl || (p - s) == 1 || *(s + 1) == '=' || *(s + 1) == '!' && (a |= OPT_invert) || *(s + 1) == '|')
f = *s;
}
re = p;
if (style <= STYLE_short)
{
if (!z && !f)
z = -1;
}
else
{
else
t = 0;
if (*p == ':')
{
if (!(wl = p - w))
w = 0;
}
else
wl = 0;
if (*p == ':' || *p == '?')
{
d = p;
}
else
d = 0;
if (style == STYLE_match)
{
wl = 0;
if ((!wl || *w == ':' || *w == '?') && (what[1] || sl && !memchr(s, what[0], sl) || !sl && what[0] != f))
{
w = 0;
if (!z)
z = -1;
}
else
matched = 1;
}
if (t)
{
p = t;
if (*p == ':' || *p == '?')
{
d = p;
}
}
}
}
if (*p == GO)
}
else if (*p == ']')
{
if (mutex)
{
if (style >= STYLE_nroff)
if (!(mutex & 1))
{
mutex--;
if (style <= STYLE_long)
{
}
}
mutex--;
}
p++;
continue;
}
else if (*p == '?')
{
if (style < STYLE_match)
z = 1;
mode |= OPT_hidden;
p++;
continue;
}
{
if (*++p)
p++;
continue;
}
else
{
f = *p++;
s = 0;
if (style == STYLE_match && !z)
z = -1;
}
if (!z)
{
f = 0;
else if (style <= STYLE_short)
w = 0;
if (!f && !w)
z = -1;
}
ov = 0;
u = v = y = 0;
{
if (*++p == '?' || *p == *(p - 1))
{
p++;
a |= OPT_optional;
}
{
if (!z)
{
while (*p == ':')
{
m = p - t;
if (*t == '!')
{
ov = t + 1;
ol = m - 1;
}
else if (*t == '=')
{
v = t + 1;
vl = m - 1;
}
else
for (j = 0; j < elementsof(attrs); j++)
{
break;
}
}
if (*p == '?')
u = p;
}
else
}
else
}
else
a |= OPT_flag;
if (!z)
{
{
{
}
if (!sl)
else
for (c = 0; c < sl; c++)
if (s[c] != '|')
if (style == STYLE_posix && y)
}
else
{
if (style >= STYLE_match)
{
if (!head)
{
head = 1;
item(sp_body, (flags & OPT_functions) ? C("FUNCTIONS") : C("OPTIONS"), 0, 0, style, sp_info, version, id, ID);
}
if (style >= STYLE_nroff)
{
if (mutex & 1)
{
mutex++;
}
}
else
}
else
{
if (sp_body)
goto nospace;
if (mutex)
{
if (mutex & 1)
{
mutex++;
}
else
}
else
}
if (style >= STYLE_nroff)
{
if (flags & OPT_functions)
{
else
if (w)
}
else
{
if (sl)
else
if (w)
{
{
}
}
else
m = a & OPT_TYPE;
for (j = 0; j < elementsof(attrs); j++)
{
break;
}
if (m = (a & ~m) | mode)
for (j = 0; j < elementsof(attrs); j++)
{
}
if (y)
else
if (v)
}
}
else
{
if (f)
{
if (!sl)
{
if (f == '-' && y)
{
y = 0;
}
}
else
if (w)
{
}
}
{
}
if (w)
{
if (prefix > 0)
{
if (prefix > 1)
}
{
}
}
if (y)
{
if (a & OPT_optional)
else if (!w)
if (w)
if (a & OPT_optional)
}
}
if (style >= STYLE_match)
{
if (d)
if (u)
if ((a & OPT_invert) && w && (d || u))
{
if (f)
sfprintf(sp_info, " %s; -\b%c\b %s --\bno%-.*s\b.", T(NiL, ID, "On by default"), f, T(NiL, ID, "means"), u - w, w);
else
sfprintf(sp_info, " %s %s\bno%-.*s\b %s.", T(NiL, ID, "On by default; use"), "--"+2-prefix, u - w, w, T(NiL, ID, "to turn off"));
goto nospace;
}
if (*p == GO)
{
p = u ? skip(p + 1, 0, 0, 0, 0, 1, 1, version) : textout(sp_body, p, style, 4, 0, sp_info, version, id, catalog);
y = "+?";
}
else
y = " ";
if (a & OPT_optional)
{
if (ov)
{
while (ov < t)
{
ov++;
}
}
else
goto nospace;
y = " ";
}
if (v)
{
t = v + vl;
while (v < t)
{
if (((c = *v++) == ':' || c == '?') && *v == c)
v++;
}
goto nospace;
}
}
else if (!mutex)
}
if (*p == GO)
{
if (style >= STYLE_match)
else
}
}
else if (*p == GO)
}
if (sp_misc)
{
goto nospace;
for (t = p; *t == '\t' || *t == '\n'; t++);
if (*t)
{
}
}
}
if (style >= STYLE_keys)
{
if (sp_info)
goto nospace;
}
if (style == STYLE_nroff)
{
s = o->id;
t = ud;
{
if (islower(c))
c = toupper(c);
*t++ = c;
}
*t = 0;
.\\\" format with nroff|troff|groff -man\n\
.fp 5 CW\n\
.nr mH 5\n\
.de H0\n\
.nr mH 0\n\
.in 5n\n\
\\fB\\\\$1\\fP\n\
.in 7n\n\
..\n\
.de H1\n\
.nr mH 1\n\
.in 7n\n\
\\fB\\\\$1\\fP\n\
.in 9n\n\
..\n\
.de H2\n\
.nr mH 2\n\
.in 11n\n\
\\fB\\\\$1\\fP\n\
.in 13n\n\
..\n\
.de H3\n\
.nr mH 3\n\
.in 15n\n\
\\fB\\\\$1\\fP\n\
.in 17n\n\
..\n\
.de H4\n\
.nr mH 4\n\
.in 19n\n\
\\fB\\\\$1\\fP\n\
.in 21n\n\
..\n\
.de OP\n\
.nr mH 0\n\
.ie !'\\\\$1'-' \\{\n\
.ds mO \\\\fB\\\\-\\\\$1\\\\fP\n\
.ds mS ,\\\\0\n\
.\\}\n\
.el \\{\n\
.ds mO \\\\&\n\
.ds mS \\\\&\n\
.\\}\n\
.ie '\\\\$2'-' \\{\n\
.if !'\\\\$4'-' .as mO \\\\0\\\\fI\\\\$4\\\\fP\n\
.\\}\n\
.el \\{\n\
.as mO \\\\*(mS\\\\fB%s\\\\$2\\\\fP\n\
.if !'\\\\$4'-' .as mO =\\\\fI\\\\$4\\\\fP\n\
.\\}\n\
.in 5n\n\
\\\\*(mO\n\
.in 9n\n\
..\n\
.de SP\n\
.if \\\\n(mH==2 .in 9n\n\
.if \\\\n(mH==3 .in 13n\n\
.if \\\\n(mH==4 .in 17n\n\
..\n\
.de FN\n\
.nr mH 0\n\
.in 5n\n\
\\\\$1 \\\\$2\n\
.in 9n\n\
..\n\
.de DS\n\
.in +3n\n\
.ft 5\n\
.nf\n\
..\n\
.de DE\n\
.fi\n\
.ft R\n\
.in -3n\n\
..\n\
.TH %s %d\n\
"
, ud
, section
);
}
if (style == STYLE_match)
{
if (!matched)
{
{
goto nospace;
goto nospace;
goto again;
}
s = (char*)unknown;
goto nope;
}
else if (matched < 0)
x = 0;
}
if (sp_plus)
{
{
goto nospace;
}
}
{
if (sp_head)
{
goto nospace;
for (; *t == '\n'; t++);
sp_head = 0;
}
}
if (x)
{
xl = t - x;
if (style >= STYLE_match)
{
x = 0;
}
}
if (sp_body)
{
{
goto nospace;
}
sp_body = 0;
}
if (x && style != STYLE_posix)
if (sp_info)
{
sp_info = 0;
}
if (sp_misc)
{
sp_misc = 0;
}
goto nospace;
m = strlen((style <= STYLE_long && error_info.id && !strchr(error_info.id, '/')) ? error_info.id : id) + 1;
{
{
ts = 0;
}
else
if (style == STYLE_html)
{
s = id;
t = ud;
{
if (islower(c))
c = toupper(c);
*t++ = c;
}
*t = 0;
sfprintf(mp, "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n<HTML>\n<HEAD>\n<META name=\"generator\" content=\"optget (AT&T Research) 2000-04-01\">\n%s<TITLE>%s man document</TITLE>\n</HEAD>\n<BODY bgcolor=white>\n", (opt_info.state->flags & OPT_proprietary) ? "<!--INTERNAL-->\n" : "", id);
sfprintf(mp, "<H4><TABLE width=100%%><TR><TH align=left> %s ( %d ) <TH align=center><A href=\".\" title=\"Index\">%s</A><TH align=right>%s ( %d )</TR></TABLE></H4>\n<HR>\n", ud, section, T(NiL, ID, heading[section % 10]), ud, section);
co = 2;
}
else
co = 0;
rm = OPT_MARGIN;
tp = 0;
n = 0;
head = 1;
while (*p == '\n')
p++;
while (c = *p++)
{
if (c == '\n')
{
n = 0;
tp = 0;
co = 0;
if (*p == '\n')
{
while (*++p == '\n');
{
p--;
else
}
}
{
y = p;
while (*p == '\t')
p++;
if (*p == '\n')
continue;
j = p - y;
if (j > *pt)
{
*++pt = j;
}
else while (j < *pt)
{
}
}
}
else if (c == '\t')
{
if (style == STYLE_html)
{
while (*p == '\t')
p++;
if (*p != '\n')
}
else
{
{
do
{
ip++;
if (*p != '\t')
break;
p++;
if (*p == '\n')
continue;
{
co = 0;
}
}
{
co++;
}
}
}
else
{
if (c == ' ' && !n)
{
tp = 0;
else
{
pp = p;
}
continue;
}
else if (style == STYLE_html)
{
if (c == '<')
{
n++;
{
for (y = p += 6; (c = *p) && c != ' ' && c != '\t' && c != '\n' && c != '<'; p++)
if (c == '[')
else if (c == ']')
else
c = '>';
tp = 0;
co += p - y + 6;
}
}
else if (c == '>' && !n)
{
for (y = --p; (c = *p) && c != ' ' && c != '\t' && c != '\n' && c != '<'; p++)
if (c == '[')
else if (c == ']')
else
if (p > y + 1)
{
tp = 0;
co += p - y - 1;
}
tp = 0;
else
{
pp = p;
}
}
else if (c == '[')
{
c = ';';
}
else if (c == ']')
{
c = ';';
}
else if (c == 'h')
{
y = p;
if (*y++ == 't' && *y++ == 't' && *y++ == 'p' && (*y == ':' || *y++ == 's' && *y == ':') && *y++ == ':' && *y++ == '/' && *y++ == '/')
{
y++;
if (*y == '?')
while (isalnum(*y) || *y == '_' || *y == '/' || *y == '-' || *y == '.' || *y == '?' || *y == '=' || *y == '%' || *y == '&' || *y == ';' || *y == '#')
y++;
if (*(y - 1) == '.')
y--;
p--;
p = y;
c = '>';
}
}
else if (c == 'C')
{
y = p;
if (*y++ == 'o' && *y++ == 'p' && *y++ == 'y' && *y++ == 'r' && *y++ == 'i' && *y++ == 'g' && *y++ == 'h' && *y++ == 't' && *y++ == ' ' && *y++ == '(' && (*y++ == 'c' || *(y - 1) == 'C') && *y++ == ')')
{
p = y;
c = ';';
}
}
}
else if (c == ']')
{
if (n)
n--;
}
else if (c == '[')
n++;
if (c == CC_esc)
{
do
{
if (!(c = *p++))
{
p--;
break;
}
} while (c < 'a' || c > 'z');
}
{
if (tp)
{
tp = 0;
p = pp;
n = 0;
}
else if (c != ' ' && c != '\n')
if (*p == ' ')
p++;
if (*p != '\n')
{
}
}
else
}
}
for (d = sfstrbase(mp), t = sfstrseek(mp, 0, SEEK_CUR); t > d && ((c = *(t - 1)) == '\n' || c == '\r' || c == ' ' || c == '\t'); t--);
if (style == STYLE_html)
{
{
}
}
}
else
goto nospace;
if (sp)
nope:
if (psp)
if (sp_help)
if (sp_text)
if (sp_plus)
if (sp_info)
if (sp_head)
if (sp_body)
if (sp_misc)
return s;
}
/*
* compatibility wrapper to opthelp()
*/
char*
{
}
/*
* convert number using strtonll() *except* that
* 0*[[:digit:]].* is treated as [[:digit:]].*
* i.e., it looks octal but isn't, to meet
* posix Utility Argument Syntax -- use
* 0x.* or <base>#* for alternate bases
*/
static intmax_t
optnumber(const char* s, char** t, int* e)
{
intmax_t n;
int oerrno;
s++;
errno = 0;
if (e)
*e = errno;
return n;
}
/*
* p points to opts location for opt_info.name
* optget() return value is returned
*/
static int
{
register char* s;
register int c;
goto nospace;
if (*p == '!')
{
while (*s == '-')
}
if (*p == '#' || *p == ':')
{
if (*p == '#')
{
}
{
while (s < p)
{
if ((c = *s++) == '?' || c == ']')
s++;
}
if (!X(catalog))
else
goto nospace;
}
}
else if (*p == '*' || *p == '&')
{
p = *p == '&' ? C("ambiguous option argument value") : C("unknown option argument value");
}
else if (*p == '=' || *p == '!')
p = C("value not expected");
else if (*p == '?')
p = *(p + 1) == '?' ? C("optget: option not supported") : C("ambiguous option");
else if (*p == '+')
p = C("section not found");
else
{
if (opt_info.option[0] != '?' && opt_info.option[0] != '-' || opt_info.option[1] != '?' && opt_info.option[1] != '-')
p = C("unknown option");
}
if (err)
return ':';
return ':';
}
/*
* argv: command line argv where argv[0] is command name
*
* opts: option control string
*
* '[' [flag][=][index][:<long-name>[|<alias-name>...]['?'description]] ']'
* long option name, index, description; -index returned
* ':' option takes string arg
* '#' option takes numeric arg (concat option may follow)
* '?' (option) following options not in usage
* (following # or :) optional arg
* '[' '[' ... ] ... '[' ... ']' ']'
* mutually exclusive option grouping
* '[' name [:attr]* [?description] ']'
* (following # or :) optional option arg description
* '\n'[' '|'\t']* ignored for legibility
* ' ' ... optional argument(s) description (to end of string)
* or after blank line
* ']]' literal ']' within '[' ... ']'
*
* return:
* 0 no more options
* '?' usage: opt_info.arg points to message sans
* `Usage: command '
* ':' error: opt_info.arg points to message sans `command: '
*
* ':' '#' ' ' '[' ']'
* invalid option chars
*
* -- terminates option list and returns 0
*
* + as first opts char makes + equivalent to -
*
* if any # option is specified then numeric options (e.g., -123)
* are associated with the leftmost # option in opts
*
* usage info in placed opt_info.arg when '?' returned
* see help_text[] (--???) for more info
*/
int
{
register int c;
register char* s;
char* a;
char* b;
char* e;
char* f;
char* g;
char* v;
char* w;
char* p;
char* q;
char* t;
char* y;
char* numopt;
char* opts;
char* id;
char* catalog;
int n;
int m;
int k;
int j;
int x;
int err;
int no;
int nov;
int num;
int numchr;
int prefix;
int version;
/*
* these are not initialized by all dlls!
*/
extern Error_info_t _error_info_;
extern Opt_t _opt_info_;
if (!_error_infop_)
if (!_opt_infop_)
#endif
if (!oopts)
return 0;
{
{
}
}
if (!argv)
cache = 0;
else
break;
if (cache)
{
if (pcache)
{
}
}
else
{
if (!argv)
n = 0;
{
n = m;
else
{
}
}
if (!argv)
return 0;
}
catalog = 0;
else /* if (!error_info.catalog) */
psp = 0;
/*
* check if any options remain and determine if the
* next option is short or long
*/
opt_info.assignment = 0;
num = 1;
w = v = 0;
x = 0;
for (;;)
{
{
/*
* finished with the previous arg
*/
{
}
return 0;
if (!prefix)
{
/*
* long with no prefix (dd style)
*/
n = 2;
if ((c = *s) != '-' && c != '+')
c = '-';
else if (*++s == c)
{
if (!*++s)
{
return 0;
}
else if (*s == c)
return 0;
}
else if (*s == '?')
n = 1;
}
else if ((c = *s++) != '-' && (c != '+' || !(pass->flags & OPT_plus) && (!(pass->flags & OPT_numeric) || !isdigit(*s))))
{
return 0;
s--;
n = 1;
}
else if (*s == c)
{
if (!*++s)
{
/*
* -- or ++ end of options
*/
return 0;
}
else if (*s == c)
{
/*
* ---* or +++* are operands
*/
return 0;
}
{
/*
* long with double prefix
*/
n = 2;
}
else
{
/*
* short option char '-'
*/
s--;
n = 1;
}
}
{
/*
* long with single prefix (find style)
*/
n = 2;
}
else
{
/*
* short (always with single prefix)
*/
n = 1;
}
/*
* just a prefix is an option (e.g., `-' == stdin)
*/
if (!*s)
return 0;
if (c == '+')
if (n == 2)
{
x = 0;
if ((*s == 'n' || *s == 'N') && (*(s + 1) == 'o' || *(s + 1) == 'O') && *(s + 2) && *(s + 2) != '=')
else
no = 0;
for (c = *s; *s; s++)
{
if (*s == '=')
{
if (*(s + 1) == '=')
s++;
w--;
v = ++s;
break;
}
if (w < &opt_info.name[elementsof(opt_info.name) - 1] && *s != ':' && *s != '|' && *s != '[' && *s != ']')
*w++ = *s;
}
*w = 0;
c = *w;
break;
}
}
return 0;
{
k = '-';
break;
}
}
/*
* at this point:
*
* c the first character of the option
* w long option name if != 0, otherwise short
* v long option value (via =) if w != 0
*/
if (c == '?')
{
/*
* ? always triggers internal help
*/
v = w + 1;
if (!w)
{
}
goto help;
}
numopt = 0;
f = 0;
s = opts;
/*
* no option can start with these characters
*/
if (c == ':' || c == '#' || c == ' ' || c == '[' || c == ']')
{
if (c != *s)
s = "";
}
else
{
a = 0;
{
if (cache)
{
{
/*
* this is a ksh getopts workaround
*/
if (!(k & (OPT_cache_string|OPT_cache_numeric)))
return c;
{
if (!(k & OPT_cache_numeric))
{
return c;
}
{
if (!err && (k & OPT_cache_optional))
{
return c;
}
}
else if (*e)
{
return c;
}
else
{
return c;
}
}
{
if ((k & OPT_cache_optional) && (*opt_info.arg == '-' || (pass->flags & OPT_plus) && *opt_info.arg == '+') && *(opt_info.arg + 1))
{
return c;
}
if (k & OPT_cache_string)
{
return c;
}
if (!err)
{
if (!*e)
{
return c;
}
if (k & OPT_cache_optional)
{
return c;
}
}
}
else if (k & OPT_cache_optional)
{
return c;
}
}
cache = 0;
}
{
c = 0;
}
}
else
cache = 0;
for (;;)
{
{
{
if (cache)
{
/*
* the first loop pass
* initialized the cache
* so one more pass to
* check the cache or
* bail for a full scan
*/
cache = 0;
s = opts;
continue;
}
if (!x && catalog)
{
/*
* the first loop pass
* translated long
* options and there
* were no matches so
* one more pass for C
* locale
*/
catalog = 0;
s = opts;
continue;
}
s = "";
break;
}
continue;
}
if (*s == '\f')
{
else
{
}
continue;
}
if (*s == c && !w)
break;
else if (*s == '[')
{
k = *f;
if (k == '+' || k == '-')
/* ignore */;
continue;
else if (w && !cache)
{
{
if (*s)
*(f = s - 1) = k;
else
{
if (s = strrchr(f, ':'))
f = s - 1;
else
s = f + 1;
}
}
else
t = 0;
if (*s != ':')
if (*s == ':')
{
if (catalog)
{
if (g == e)
p = 0;
else
{
goto nospace;
}
}
else
p = 0;
y = w;
for (;;)
{
n = m = 0;
e = s + 1;
while (*++s)
{
if (*s == '*' || *s == '\a')
{
if (*s == '\a')
do
{
if (!*++s)
{
s--;
break;
}
} while (*s != '\a');
j = *(s + 1);
if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
{
while (*w)
w++;
m = 0;
break;
}
m = 1;
}
w++;
else if (*w == 0)
break;
else if (!sep(*s))
{
if (sep(*w))
{
if (*++w == *s)
{
w++;
continue;
}
}
break;
if (!sep(*q))
break;
for (s = q; w > y && *w != *(s + 1); w--);
}
else if (*w != *(s + 1))
break;
}
if (!*w)
{
nov = 0;
break;
}
if (n = no)
{
m = 0;
s = e - 1;
w = y + n;
while (*++s)
{
if (*s == '*' || *s == '\a')
{
if (*s == '\a')
do
{
if (!*++s)
{
s--;
break;
}
} while (*s != '\a');
j = *(s + 1);
if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
{
while (*w)
w++;
m = 0;
break;
}
m = 1;
}
w++;
else if (*w == 0)
break;
else if (!sep(*s))
{
if (sep(*w))
{
if (*++w == *s)
{
w++;
continue;
}
}
break;
if (!sep(*q))
break;
for (s = q; w > y && *w != *(s + 1); w--);
}
else if (*w != *(s + 1))
break;
}
if (!*w)
break;
}
break;
w = y;
}
if (p)
s = p;
if (!*w)
{
if (n)
num = 0;
if (!(n = (m || *s == ':' || *s == '|' || *s == '?' || *s == ']' || *s == 0)) && x)
{
}
for (x = k; *(f + 1) == '|' && (j = *(f + 2)) && j != '!' && j != '=' && j != ':' && j != '?' && j != ']'; f += 2);
if (*f == ':')
{
x = -1;
}
else if (*(f + 1) == ':' || *(f + 1) == '!' && *(f + 2) == ':')
{
}
else
{
a = f;
if (*a == '=')
a++;
else
{
if (*(a + 1) == '!')
a++;
if (*(a + 1) == '=')
a += 2;
}
x = -strtol(a, &b, 0);
}
b = e;
if (t)
{
s = t;
t = 0;
}
if (n)
{
w = y;
break;
}
}
w = y;
}
else if (k == c && prefix == 1)
{
w = 0;
break;
}
if (t)
{
s = t;
if (a)
a = t;
}
}
if (*s == GO)
if (cache)
{
m = OPT_cache_flag;
v = s;
if (*v == '#')
{
v++;
m |= OPT_cache_numeric;
}
else if (*v == ':')
{
v++;
m |= OPT_cache_string;
}
if (*v == '?')
{
v++;
m |= OPT_cache_optional;
}
else if (*v == *(v - 1))
v++;
if (*v != GO)
{
v = f;
for (;;)
{
while (isdigit(*(f + 1)))
f++;
else if (*(f + 1) == '=')
break;
else
j = 0;
while (*(f + 1) == '|')
{
f += 2;
if (!(j = *f) || j == '!' || j == '=' || j == ':' || j == '?' || j == ']')
break;
}
if (j != '!' || (m & OPT_cache_invert))
break;
f = v;
m |= OPT_cache_invert;
}
}
}
else
{
m = 0;
if (!w)
{
k = -1;
if (c == k)
m = 1;
while (*(f + 1) == '|')
{
f += 2;
if (!(j = *f))
{
m = 0;
break;
}
else if (j == c)
m = 1;
else if (j == '!' || j == '=' || j == ':' || j == '?' || j == ']')
break;
}
}
if (m)
{
s--;
if (*++f == '!')
{
f++;
num = 0;
}
if (*f == '=')
{
c = -strtol(++f, &b, 0);
}
else
c = k;
break;
}
}
if (*s == '#')
{
{
numopt = s - 1;
numchr = k;
if (*f == ':')
numchr = -1;
else if (*(f + 1) != ':' && *(f + 1) != '!' && *(f + 1) != ']')
{
a = f;
if (*a == '=')
a++;
else
{
if (*(a + 1) == '!')
a++;
if (*(a + 1) == '=')
a += 2;
}
}
}
}
else if (*s != ':')
continue;
}
else if (*s == ']')
{
s++;
continue;
}
else if (*s == '#')
{
}
else if (*s != ':')
{
if (cache)
{
m = OPT_cache_flag;
if (*(s + 1) == '#')
{
m |= OPT_cache_numeric;
if (*(s + 2) == '?')
m |= OPT_cache_optional;
}
else if (*(s + 1) == ':')
{
m |= OPT_cache_string;
if (*(s + 2) == '?')
m |= OPT_cache_optional;
}
}
s++;
continue;
}
if (*++s == '?' || *s == *(s - 1))
s++;
{
if (*s == GO)
}
}
if (w && x)
{
if (v && (a == 0 || *a == 0 || *(a + 1) != ':' && *(a + 1) != '#') && (*v == '0' || *v == '1') && !*(v + 1))
{
if (*v == '0')
v = 0;
}
for (;;)
{
if (b >= s)
{
*w = 0;
break;
}
if (*b == '*')
break;
*w++ = *b++;
}
if (!num && v)
c = x;
s = a;
}
}
if (!*s)
{
if (w)
{
{
if (!v)
goto help;
}
if (!v)
{
goto help;
}
}
{
}
s = numopt;
}
/*
* this is a ksh getopts workaround
*/
{
if (w)
{
if (nov)
{
if (v)
{
}
}
else
{
{
}
{
if (*(s + 1) != '?')
{
{
}
}
if (*++t == '!')
{
if (!v || *v == '1')
{
}
else
{
}
break;
}
}
{
{
}
}
}
goto optarg;
}
{
if (*s == '#')
{
{
{
}
else
{
}
return c;
}
else if (*e)
{
return c;
}
}
}
{
if (*(s + 1) == '?' && (*opt_info.arg == '-' || (pass->flags & OPT_plus) && *opt_info.arg == '+') && *(opt_info.arg + 1))
{
}
else if (*s == '#')
{
if (err || *e)
{
{
}
else
{
}
}
}
}
else if (*(s + 1) != '?')
{
}
if (*s == ':' && *(s = skip(s, 0, 0, 0, 1, 0, 1, version)) == GO && *(s = next(s + 1, version)) == '[' && isalnum(*(s + 1)))
{
x = 0;
{
do
{
k = *f;
if (k == *w && isalpha(k) && !*(w + 1))
{
x = k;
break;
}
if (*s == '+' || *s == '-')
continue;
continue;
else
{
if (*s != ':')
if (*s == ':')
{
if (catalog)
{
if (b == e)
p = 0;
else
{
goto nospace;
}
}
else
p = 0;
for (;;)
{
n = m = 0;
e = s + 1;
while (*++s)
{
if (*s == '*' || *s == '\a')
{
if (*s == '\a')
do
{
if (!*++s)
{
s--;
break;
}
} while (*s != '\a');
j = *(s + 1);
if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
{
while (*w)
w++;
m = 0;
break;
}
m = 1;
}
w++;
else if (*w == 0)
break;
else if (!sep(*s))
{
if (sep(*w))
{
if (*++w == *s)
{
w++;
continue;
}
}
break;
if (!sep(*q))
break;
for (s = q; w > y && *w != *(s + 1); w--);
}
else if (*w != *(s + 1))
break;
}
if (!*w)
{
nov = 0;
break;
}
break;
w = y;
}
if (p)
s = p;
if (!*w)
{
if (n)
num = 0;
if (!(n = (m || *s == ':' || *s == '|' || *s == '?' || *s == ']')) && x)
{
}
for (x = k; *(f + 1) == '|' && (j = *(f + 2)) && j != '!' && j != '=' && j != ':' && j != '?' && j != ']'; f += 2);
if (*f == ':')
x = -1;
else if (*(f + 1) == ':' || *(f + 1) == '!' && *(f + 2) == ':')
/* ok */;
else
{
a = f;
if (*a == '=')
a++;
else
{
if (*(a + 1) == '!')
a++;
if (*(a + 1) == '=')
a += 2;
}
x = -strtol(a, &b, 0);
}
b = e;
if (n)
break;
}
}
}
{
}
}
}
}
else if (w && v)
{
}
else
{
{
}
}
return c;
help:
if (v && *v == '?' && *(v + 1) == '?' && *(v + 2))
{
s = v + 2;
if ((s[0] == 'n' || s[0] == 'N') && (s[1] == 'o' || s[1] == 'O'))
{
s += 2;
n = -1;
}
else
n = 1;
{
{
return '?';
}
}
{
}
else
{
}
return '#';
goto again;
}
{
}
return '?';
}
/*
* parse long options with 0,1,2 leading '-' or '+' from string and pass to optget()
* syntax is the unquoted
*
* <length> [-|+|--|++]<name>[[-+:|&=]=<value>\n (or \0 for the last)
*
* or the quoted
*
* [-|+|--|++][no]name[[-+:|&=]=['"{(]value[)}"']][, ]...
*
* with \x escapes passed to chresc()
*
* return '#' for `label:', with opt_info.name==label
* str[opt_info.offset] next arg
*
* optstr(s, 0)
* return '-' if arg, 0 otherwise
* optstr(0, opts)
* use previous parsed str
*/
int
{
register char* s = (char*)str;
register int c;
register int ql;
register int qr;
register int qc;
int v;
char* e;
if (s)
{
return 0;
while (*s == ',' || *s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')
s++;
if (!*s)
{
return 0;
}
if (*s == '-' || *s == '+')
{
c = *s++;
if (*s == c)
{
s++;
}
}
else
{
}
if (isdigit(*s) && (v = (int)strtol(s, &e, 10)) > 1 && isspace(*e) && --v <= strlen(s) && (s[v] == 0 || s[v] == '\n'))
{
s += v;
while (isspace(*++e));
}
else
{
while (*s && *s != ',' && *s != ' ' && *s != '\t' && *s != '\n' && *s != '\r' && *s != '=' && *s != ':')
if ((c = *s) == ':' && *(s + 1) != '=')
{
goto nospace;
s += 2;
return '#';
}
if (c == ':' || c == '=')
{
while (c = *++s)
{
if (c == '\\')
{
s = e - 1;
}
else if (c == qr)
{
if (--qc <= 0)
}
else if (c == ql)
{
qc++;
}
else if (qr)
else if (c == ',' || c == ' ' || c == '\t' || c == '\n' || c == '\r')
break;
else if (c == '"' || c == '\'')
{
qc = 1;
}
else
{
if (c == GO)
{
ql = c;
qc = 1;
}
else if (c == '(')
{
ql = c;
qr = ')';
qc = 1;
}
}
}
}
}
goto nospace;
}
if (opts)
{
{
return 0;
}
if (c == '#')
{
goto again;
}
if (*s++ == '-' && *s++ == '-' && *s)
{
while (*e++ = *s++);
}
}
else
c = '-';
return c;
}