14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * Glenn Fowler <gsf@research.att.com> *
184887Schin * David Korn <dgk@research.att.com> *
194887Schin * Phong Vo <kpv@research.att.com> *
204887Schin * *
214887Schin ***********************************************************************/
224887Schin #pragma prototyped
234887Schin /*
244887Schin * Glenn Fowler
254887Schin * AT&T Research
264887Schin *
274887Schin * command line option parser and usage formatter
284887Schin * its a monster but its all in one place
294887Schin * widen your window while you're at it
304887Schin */
314887Schin
324887Schin #include <optlib.h>
334887Schin #include <debug.h>
344887Schin #include <ccode.h>
354887Schin #include <ctype.h>
364887Schin #include <errno.h>
374887Schin
384887Schin #define KEEP "*[A-Za-z][A-Za-z]*"
394887Schin #define OMIT "*@(\\[[-+]*\\?*\\]|\\@\\(#\\)|Copyright \\(c\\)|\\$\\I\\d\\: )*"
404887Schin
414887Schin #define GO '{' /* group nest open */
424887Schin #define OG '}' /* group nest close */
434887Schin
444887Schin #define OPT_WIDTH 80 /* default help text width */
454887Schin #define OPT_MARGIN 10 /* default help text margin */
464887Schin #define OPT_USAGE 7 /* usage continuation indent */
474887Schin
484887Schin #define OPT_flag 0x001 /* flag ( 0 or 1 ) */
494887Schin #define OPT_hidden 0x002 /* remaining are hidden */
504887Schin #define OPT_ignorecase 0x004 /* arg match ignores case */
514887Schin #define OPT_invert 0x008 /* flag inverts long sense */
524887Schin #define OPT_listof 0x010 /* arg is ' ' or ',' list */
5310898Sroland.mainz@nrubsig.org #define OPT_number 0x020 /* arg is strtonll() number */
5410898Sroland.mainz@nrubsig.org #define OPT_oneof 0x040 /* arg may be set once */
5510898Sroland.mainz@nrubsig.org #define OPT_optional 0x080 /* arg is optional */
5610898Sroland.mainz@nrubsig.org #define OPT_string 0x100 /* arg is string */
574887Schin
584887Schin #define OPT_preformat 0001 /* output preformat string */
5910898Sroland.mainz@nrubsig.org #define OPT_proprietary 0002 /* proprietary docs */
604887Schin
614887Schin #define OPT_TYPE (OPT_flag|OPT_number|OPT_string)
624887Schin
634887Schin #define STYLE_posix 0 /* posix getopt usage */
644887Schin #define STYLE_short 1 /* [default] short usage */
654887Schin #define STYLE_long 2 /* long usage */
664887Schin #define STYLE_match 3 /* long description of matches */
674887Schin #define STYLE_options 4 /* short and long descriptions */
684887Schin #define STYLE_man 5 /* pretty details */
694887Schin #define STYLE_html 6 /* html details */
704887Schin #define STYLE_nroff 7 /* nroff details */
714887Schin #define STYLE_api 8 /* program details */
724887Schin #define STYLE_keys 9 /* translation key strings */
734887Schin #define STYLE_usage 10 /* escaped usage string */
744887Schin
754887Schin #define FONT_BOLD 1
764887Schin #define FONT_ITALIC 2
774887Schin #define FONT_LITERAL 4
784887Schin
794887Schin #define sep(c) ((c)=='-'||(c)=='_')
804887Schin
814887Schin typedef struct Attr_s
824887Schin {
834887Schin const char* name;
844887Schin int flag;
854887Schin } Attr_t;
864887Schin
874887Schin typedef struct Help_s
884887Schin {
894887Schin const char* match; /* builtin help match name */
904887Schin const char* name; /* builtin help name */
914887Schin int style; /* STYLE_* */
924887Schin const char* text; /* --? text */
934887Schin unsigned int size; /* strlen text */
944887Schin } Help_t;
954887Schin
964887Schin typedef struct Font_s
974887Schin {
984887Schin const char* html[2];
994887Schin const char* nroff[2];
1004887Schin const char* term[2];
1014887Schin } Font_t;
1024887Schin
1034887Schin typedef struct List_s
1044887Schin {
1054887Schin int type; /* { - + : } */
1064887Schin const char* name; /* list name */
1074887Schin const char* text; /* help text */
1084887Schin } List_t;
1094887Schin
1104887Schin typedef struct Msg_s
1114887Schin {
1124887Schin const char* text; /* default message text */
1134887Schin Dtlink_t link; /* cdt link */
1144887Schin } Msg_t;
1154887Schin
1164887Schin typedef struct Save_s
1174887Schin {
1184887Schin Dtlink_t link; /* cdt link */
1194887Schin char text[1]; /* saved text text */
1204887Schin } Save_t;
1214887Schin
1224887Schin typedef struct Push_s
1234887Schin {
1244887Schin struct Push_s* next; /* next string */
1254887Schin char* ob; /* next char in old string */
1264887Schin char* oe; /* end of old string */
1274887Schin char* nb; /* next char in new string */
1284887Schin char* ne; /* end of new string */
1294887Schin int ch; /* localize() translation */
1304887Schin } Push_t;
1314887Schin
1324887Schin typedef struct Indent_s
1334887Schin {
1344887Schin int stop; /* tab column position */
1354887Schin } Indent_t;
1364887Schin
1374887Schin static Indent_t indent[] =
1384887Schin {
1394887Schin 0,2, 4,10, 12,18, 20,26, 28,34, 36,42, 44,50, 0,0
1404887Schin };
1414887Schin
1424887Schin static const char term_off[] = {CC_esc,'[','0','m',0};
1434887Schin static const char term_B_on[] = {CC_esc,'[','1','m',0};
1444887Schin static const char term_I_on[] = {CC_esc,'[','1',';','4','m',0};
1454887Schin
1464887Schin static const Font_t fonts[] =
1474887Schin {
1484887Schin "", "", "", "", "", "",
1494887Schin "</B>", "<B>", "\\fP", "\\fB", &term_off[0], &term_B_on[0],
1504887Schin "</I>", "<I>", "\\fP", "\\fI", &term_off[0], &term_I_on[0],
1514887Schin "", "", "", "", "", "",
1524887Schin "</TT>","<TT>","\\fP", "\\f5", "", "",
1534887Schin };
1544887Schin
1554887Schin static char native[] = "";
1564887Schin
1574887Schin #if !_PACKAGE_astsa
1584887Schin
1594887Schin #define ID ast.id
1604887Schin
1614887Schin #define C(s) ERROR_catalog(s)
1624887Schin #define D(s) (opt_info.state->msgdict && dtmatch(opt_info.state->msgdict, (s)))
1634887Schin #define T(i,c,m) (X(c)?translate(i,c,C(m)):(m))
1644887Schin #define X(c) (ERROR_translating()&&(c)!=native)
1654887Schin #define Z(x) C(x),sizeof(x)-1
1664887Schin
1674887Schin /*
1684887Schin * translate with C_LC_MESSAGES_libast[] check
1694887Schin */
1704887Schin
1714887Schin static char*
translate(const char * cmd,const char * cat,const char * msg)1724887Schin translate(const char* cmd, const char* cat, const char* msg)
1734887Schin {
1744887Schin if (!X(cat))
1754887Schin return (char*)msg;
1764887Schin if (cat != (const char*)ID && D(msg))
1774887Schin cat = (const char*)ID;
1784887Schin return errorx(NiL, cmd, cat, msg);
1794887Schin }
1804887Schin
1814887Schin #else
1824887Schin
1834887Schin static char ID[] = "ast";
1844887Schin
1854887Schin #define C(s) s
1864887Schin #define D(s) (opt_info.state->msgdict && dtmatch(opt_info.state->msgdict, (s)))
1874887Schin #define T(i,c,m) m
1884887Schin #define X(c) 0
1894887Schin #define Z(x) C(x),sizeof(x)-1
1904887Schin
1914887Schin #endif
1924887Schin
1934887Schin static const List_t help_head[] =
1944887Schin {
1954887Schin '-', 0,
1964887Schin 0,
1974887Schin '+', C("NAME"),
1984887Schin C("options available to all \bast\b commands"),
1994887Schin '+', C("DESCRIPTION"),
2004887Schin C("\b-?\b and \b--?\b* options are the same \
2014887Schin for all \bast\b commands. For any \aitem\a below, if \b--\b\aitem\a is not \
2024887Schin supported by a given command then it is equivalent to \b--\?\?\b\aitem\a. The \
2034887Schin \b--\?\?\b form should be used for portability. All output is written to the \
2044887Schin standard error."),
2054887Schin };
2064887Schin
2074887Schin static const Help_t styles[] =
2084887Schin {
2094887Schin C("about"), "-", STYLE_match,
2104887Schin Z("List all implementation info."),
2114887Schin C("api"), "?api", STYLE_api,
2124887Schin Z("List detailed info in program readable form."),
2134887Schin C("help"), "", -1,
2144887Schin Z("List detailed help option info."),
2154887Schin C("html"), "?html", STYLE_html,
2164887Schin Z("List detailed info in html."),
2174887Schin C("keys"), "?keys", STYLE_keys,
2184887Schin Z("List the usage translation key strings with C style escapes."),
2194887Schin C("long"), "?long", STYLE_long,
2204887Schin Z("List long option usage."),
2214887Schin C("man"), "?man", STYLE_man,
2224887Schin Z("List detailed info in displayed man page form."),
2234887Schin C("nroff"), "?nroff", STYLE_nroff,
2244887Schin Z("List detailed info in nroff."),
2254887Schin C("options"), "?options", STYLE_options,
2264887Schin Z("List short and long option details."),
2274887Schin C("posix"), "?posix", STYLE_posix,
2284887Schin Z("List posix getopt usage."),
2294887Schin C("short"), "?short", STYLE_short,
2304887Schin Z("List short option usage."),
2314887Schin C("usage"), "?usage", STYLE_usage,
2324887Schin Z("List the usage string with C style escapes."),
2334887Schin };
2344887Schin
2354887Schin static const List_t help_tail[] =
2364887Schin {
2374887Schin ':', C("\?\?-\alabel\a"),
2384887Schin C("List implementation info matching \alabel\a*."),
2394887Schin ':', C("\?\?\aname\a"),
2404887Schin C("Equivalent to \b--help=\b\aname\a."),
2414887Schin ':', C("\?\?"),
2424887Schin C("Equivalent to \b--\?\?options\b."),
2434887Schin ':', C("\?\?\?\?"),
2444887Schin C("Equivalent to \b--\?\?man\b."),
2454887Schin ':', C("\?\?\?\?\?\?"),
2464887Schin C("Equivalent to \b--\?\?help\b."),
2474887Schin ':', C("\?\?\?\?\?\?\aitem\a"),
2484887Schin C("If the next argument is \b--\b\aoption\a then list \
2494887Schin the \aoption\a output in the \aitem\a style. Otherwise print \
2504887Schin \bversion=\b\an\a where \an\a>0 if \b--\?\?\b\aitem\a is supported, \b0\b \
2514887Schin if not."),
2524887Schin ':', C("\?\?\?\?\?\?ESC"),
2534887Schin C("Emit escape codes even if output is not a terminal."),
2544887Schin ':', C("\?\?\?\?\?\?TEST"),
2554887Schin C("Massage the output for regression testing."),
2564887Schin };
2574887Schin
2584887Schin static const Attr_t attrs[] =
2594887Schin {
2604887Schin "flag", OPT_flag,
2614887Schin "hidden", OPT_hidden,
2624887Schin "ignorecase", OPT_ignorecase,
2634887Schin "invert", OPT_invert,
2644887Schin "listof", OPT_listof,
2654887Schin "number", OPT_number,
2664887Schin "oneof", OPT_oneof,
2674887Schin "optional", OPT_optional,
2684887Schin "string", OPT_string,
2694887Schin };
2704887Schin
2714887Schin static const char unknown[] = C("unknown option or attribute");
2724887Schin
2734887Schin static const char* heading[] =
2744887Schin {
2754887Schin C("INDEX"),
2764887Schin C("USER COMMANDS"),
2774887Schin C("SYSTEM LIBRARY"),
2784887Schin C("USER LIBRARY"),
2794887Schin C("FILE FORMATS"),
2804887Schin C("MISCELLANEOUS"),
2814887Schin C("GAMES and DEMOS"),
2824887Schin C("SPECIAL FILES"),
2834887Schin C("ADMINISTRATIVE COMMANDS"),
2844887Schin C("GUIs"),
2854887Schin };
2864887Schin
2874887Schin /*
2884887Schin * list of common man page strings
2894887Schin * NOTE: add but do not delete from this table
2904887Schin */
2914887Schin
2924887Schin static Msg_t C_LC_MESSAGES_libast[] =
2934887Schin {
2944887Schin { C("APPLICATION USAGE") },
2954887Schin { C("ASYNCHRONOUS EVENTS") },
2964887Schin { C("BUGS") },
2974887Schin { C("CAVEATS") },
2984887Schin { C("CONSEQUENCES OF ERRORS") },
2994887Schin { C("DESCRIPTION") },
3004887Schin { C("ENVIRONMENT VARIABLES") },
3014887Schin { C("EXAMPLES") },
3024887Schin { C("EXIT STATUS") },
3034887Schin { C("EXTENDED DESCRIPTION") },
3044887Schin { C("INPUT FILES") },
3054887Schin { C("LIBRARY") },
3064887Schin { C("NAME") },
3074887Schin { C("OPERANDS") },
3084887Schin { C("OPTIONS") },
3094887Schin { C("OUTPUT FILES") },
3104887Schin { C("SEE ALSO") },
3114887Schin { C("STDERR") },
3124887Schin { C("STDIN") },
3134887Schin { C("STDOUT") },
3144887Schin { C("SYNOPSIS") },
3154887Schin { C("author") },
3164887Schin { C("copyright") },
3174887Schin { C("license") },
3184887Schin { C("name") },
3194887Schin { C("path") },
3204887Schin { C("version") },
3214887Schin };
3224887Schin
3234887Schin static unsigned char map[UCHAR_MAX];
3244887Schin
3254887Schin static Optstate_t state;
3264887Schin
3274887Schin /*
3284887Schin * 2007-03-19 move opt_info from _opt_info_ to (*_opt_data_)
3294887Schin * to allow future Opt_t growth
3304887Schin * by 2009 _opt_info_ can be static
3314887Schin */
3324887Schin
3334887Schin #if _BLD_ast && defined(__EXPORT__)
3344887Schin #define extern extern __EXPORT__
3354887Schin #endif
3364887Schin
3374887Schin extern Opt_t _opt_info_;
3384887Schin
3394887Schin Opt_t _opt_info_ = { 0,0,0,0,0,0,0,{0},{0},0,0,0,{0},{0},&state };
3404887Schin
3414887Schin #undef extern
3424887Schin
3434887Schin __EXTERN__(Opt_t, _opt_info_);
3444887Schin
3454887Schin __EXTERN__(Opt_t*, _opt_infop_);
3464887Schin
3474887Schin Opt_t* _opt_infop_ = &_opt_info_;
3484887Schin
3494887Schin #if _BLD_DEBUG
3504887Schin
3514887Schin /*
3524887Schin * debug usage string segment format
3534887Schin */
3544887Schin
3554887Schin static char*
show(register char * s)3564887Schin show(register char* s)
3574887Schin {
3584887Schin register int c;
3594887Schin register char* t;
3604887Schin register char* e;
3614887Schin
3624887Schin static char buf[32];
3634887Schin
3644887Schin if (!s)
3654887Schin return "(null)";
3664887Schin t = buf;
3674887Schin e = buf + sizeof(buf) - 2;
3684887Schin while (t < e)
3694887Schin {
3704887Schin switch (c = *s++)
3714887Schin {
3724887Schin case 0:
3734887Schin goto done;
3744887Schin case '\a':
3754887Schin *t++ = '\\';
3764887Schin c = 'a';
3774887Schin break;
3784887Schin case '\b':
3794887Schin *t++ = '\\';
3804887Schin c = 'b';
3814887Schin break;
3824887Schin case '\f':
3834887Schin *t++ = '\\';
3844887Schin c = 'f';
3854887Schin break;
386*12068SRoger.Faulkner@Oracle.COM case '\n':
387*12068SRoger.Faulkner@Oracle.COM *t++ = '\\';
388*12068SRoger.Faulkner@Oracle.COM c = 'n';
389*12068SRoger.Faulkner@Oracle.COM break;
390*12068SRoger.Faulkner@Oracle.COM case '\t':
391*12068SRoger.Faulkner@Oracle.COM *t++ = '\\';
392*12068SRoger.Faulkner@Oracle.COM c = 't';
393*12068SRoger.Faulkner@Oracle.COM break;
3944887Schin case '\v':
3954887Schin *t++ = '\\';
3964887Schin c = 'v';
3974887Schin break;
3984887Schin }
3994887Schin *t++ = c;
4004887Schin }
4014887Schin done:
4024887Schin *t = 0;
4034887Schin return buf;
4044887Schin }
4054887Schin
4064887Schin #endif
4074887Schin
4084887Schin /*
4094887Schin * pop the push stack
4104887Schin */
4114887Schin
4124887Schin static Push_t*
pop(register Push_t * psp)4134887Schin pop(register Push_t* psp)
4144887Schin {
4154887Schin register Push_t* tsp;
4164887Schin
4174887Schin while (tsp = psp)
4184887Schin {
4194887Schin psp = psp->next;
4204887Schin free(tsp);
4214887Schin }
4224887Schin return 0;
4234887Schin }
4244887Schin
4254887Schin /*
4264887Schin * skip over line space to the next token
4274887Schin */
4284887Schin
4294887Schin static char*
next(register char * s,int version)4304887Schin next(register char* s, int version)
4314887Schin {
4324887Schin register char* b;
4334887Schin
4344887Schin while (*s == '\t' || *s == '\r' || version >= 1 && *s == ' ')
4354887Schin s++;
4364887Schin if (*s == '\n')
4374887Schin {
4384887Schin b = s;
4394887Schin while (*++s == ' ' || *s == '\t' || *s == '\r');
4404887Schin if (*s == '\n')
4414887Schin return b;
4424887Schin }
4434887Schin return s;
4444887Schin }
4454887Schin
4464887Schin /*
4474887Schin * skip to t1 or t2 or t3, whichever first, in s
4484887Schin * n==0 outside [...]
4494887Schin * n==1 inside [...] before ?
4504887Schin * n==2 inside [...] after ?
4514887Schin * b==0 outside {...}
4524887Schin * b==1 inside {...}
4534887Schin * past skips past the terminator to the next token
4544887Schin * otherwise a pointer to the terminator is returned
4554887Schin *
4564887Schin * ]] for ] inside [...]
4574887Schin * ?? for ? inside [...] before ?
4584887Schin * :: for : inside [...] before ?
4594887Schin */
4604887Schin
4614887Schin 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)4624887Schin skip(register char* s, register int t1, register int t2, register int t3, register int n, register int b, int past, int version)
4634887Schin {
4644887Schin register int c;
4654887Schin register int on = n;
4664887Schin register int ob = b;
4674887Schin
4684887Schin if (version < 1)
4694887Schin {
4704887Schin n = n >= 1;
4714887Schin for (;;)
4724887Schin {
4734887Schin switch (*s++)
4744887Schin {
4754887Schin case 0:
4764887Schin break;
4774887Schin case '[':
4784887Schin n++;
4794887Schin continue;
4804887Schin case ']':
4814887Schin if (--n <= 0)
4824887Schin break;
4834887Schin continue;
4844887Schin default:
4854887Schin continue;
4864887Schin }
4874887Schin break;
4884887Schin }
4894887Schin }
4904887Schin else while (c = *s++)
4914887Schin {
4924887Schin 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)));
4934887Schin if (c == '[')
4944887Schin {
4954887Schin if (!n)
4964887Schin n = 1;
4974887Schin }
4984887Schin else if (c == ']')
4994887Schin {
5004887Schin if (n)
5014887Schin {
5024887Schin if (*s == ']')
5034887Schin s++;
5044887Schin else if (on == 1)
5054887Schin break;
5064887Schin else
5074887Schin n = 0;
5084887Schin }
5094887Schin }
5104887Schin else if (c == GO)
5114887Schin {
5124887Schin if (n == 0)
5134887Schin b++;
5144887Schin }
5154887Schin else if (c == OG)
5164887Schin {
5174887Schin if (n == 0 && b-- == ob)
5184887Schin break;
5194887Schin }
5204887Schin else if (c == '?')
5214887Schin {
5224887Schin if (n == 1)
5234887Schin {
5244887Schin if (*s == '?')
5254887Schin s++;
5264887Schin else
5274887Schin {
5284887Schin if (n == on && (c == t1 || c == t2 || c == t3))
5294887Schin break;
5304887Schin n = 2;
5314887Schin }
5324887Schin }
5334887Schin }
5344887Schin else if (n == on && (c == t1 || c == t2 || c == t3))
5354887Schin {
5364887Schin if (n == 1 && c == ':' && *s == c)
5374887Schin s++;
5384887Schin else
5394887Schin break;
5404887Schin }
5414887Schin }
5424887Schin return past && *(s - 1) ? next(s, version) : s - 1;
5434887Schin }
5444887Schin
5454887Schin /*
5464887Schin * match s with t
5474887Schin * t translated if possible
5484887Schin * imbedded { - _ ' } ignored
5494887Schin * * separates required prefix from optional suffix
5504887Schin * otherwise prefix match
5514887Schin */
5524887Schin
5534887Schin static int
match(char * s,char * t,int version,const char * id,const char * catalog)554*12068SRoger.Faulkner@Oracle.COM match(char* s, char* t, int version, const char* id, const char* catalog)
5554887Schin {
5564887Schin register char* w;
5574887Schin register char* x;
5584887Schin char* xw;
5594887Schin char* ww;
5604887Schin int n;
5614887Schin int v;
5624887Schin int j;
5634887Schin
5644887Schin for (n = 0; n < 2; n++)
5654887Schin {
5664887Schin if (n)
5674887Schin x = t;
5684887Schin else
5694887Schin {
5704887Schin if (catalog)
5714887Schin {
5724887Schin w = skip(t, ':', '?', 0, 1, 0, 0, version);
5734887Schin w = sfprints("%-.*s", w - t, t);
574*12068SRoger.Faulkner@Oracle.COM x = T(id, catalog, w);
5754887Schin if (x == w)
5764887Schin continue;
5774887Schin }
5784887Schin x = T(NiL, ID, t);
5794887Schin if (x == t)
5804887Schin continue;
5814887Schin }
5824887Schin do
5834887Schin {
5844887Schin v = 0;
5854887Schin xw = x;
5864887Schin w = ww = s;
5874887Schin while (*x && *w)
5884887Schin {
5894887Schin if (isupper(*x))
5904887Schin xw = x;
5914887Schin if (isupper(*w))
5924887Schin ww = w;
5934887Schin if (*x == '*' && !v++ || *x == '\a')
5944887Schin {
5954887Schin if (*x == '\a')
5964887Schin do
5974887Schin {
5984887Schin if (!*++x)
5994887Schin {
6004887Schin x--;
6014887Schin break;
6024887Schin }
6034887Schin } while (*x != '\a');
6044887Schin j = *(x + 1);
6054887Schin if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
6064887Schin while (*w)
6074887Schin w++;
6084887Schin }
6094887Schin else if (sep(*x))
6104887Schin xw = ++x;
6114887Schin else if (sep(*w) && w != s)
6124887Schin ww = ++w;
6134887Schin else if (*x == *w)
6144887Schin {
6154887Schin x++;
6164887Schin w++;
6174887Schin }
6184887Schin else if (w == ww && x == xw)
6194887Schin break;
6204887Schin else
6214887Schin {
6224887Schin if (x != xw)
6234887Schin {
6244887Schin while (*x && !sep(*x) && !isupper(*x))
6254887Schin x++;
6264887Schin if (!*x)
6274887Schin break;
6284887Schin if (sep(*x))
6294887Schin x++;
6304887Schin xw = x;
6314887Schin }
6324887Schin while (w > ww && *w != *x)
6334887Schin w--;
6344887Schin }
6354887Schin }
6364887Schin if (!*w)
6374887Schin {
6384887Schin if (!v)
6394887Schin {
6404887Schin for (;;)
6414887Schin {
6424887Schin switch (*x++)
6434887Schin {
6444887Schin case 0:
6454887Schin case ':':
6464887Schin case '|':
6474887Schin case '?':
6484887Schin case ']':
6494887Schin return 1;
6504887Schin case '*':
6514887Schin break;
6524887Schin default:
6534887Schin continue;
6544887Schin }
6554887Schin break;
6564887Schin }
6574887Schin break;
6584887Schin }
6594887Schin return 1;
6604887Schin }
6614887Schin } while (*(x = skip(x, '|', 0, 0, 1, 0, 0, version)) == '|' && x++);
6624887Schin }
6634887Schin return 0;
6644887Schin }
6654887Schin
6664887Schin /*
6674887Schin * prefix search for s in tab with num elements of size
6684887Schin * with optional translation
6694887Schin */
6704887Schin
6714887Schin static void*
search(const void * tab,size_t num,size_t siz,char * s)6724887Schin search(const void* tab, size_t num, size_t siz, char* s)
6734887Schin {
6744887Schin register char* p;
6754887Schin register char* e;
6764887Schin
6774887Schin for (e = (p = (char*)tab) + num * siz; p < e; p += siz)
678*12068SRoger.Faulkner@Oracle.COM if (match(s, *((char**)p), -1, NiL, NiL))
6794887Schin return (void*)p;
6804887Schin return 0;
6814887Schin }
6824887Schin
6834887Schin /*
6844887Schin * save s and return the saved pointer
6854887Schin */
6864887Schin
6874887Schin static char*
save(const char * s)6884887Schin save(const char* s)
6894887Schin {
6904887Schin Save_t* p;
6918462SApril.Chin@Sun.COM Dtdisc_t* d;
6924887Schin
6934887Schin static Dt_t* dict;
6944887Schin
6954887Schin if (!dict)
6964887Schin {
6978462SApril.Chin@Sun.COM if (!(d = newof(0, Dtdisc_t, 1, 0)))
6988462SApril.Chin@Sun.COM return (char*)s;
6998462SApril.Chin@Sun.COM d->key = offsetof(Save_t, text);
7008462SApril.Chin@Sun.COM if (!(dict = dtopen(d, Dthash)))
7014887Schin return (char*)s;
7024887Schin }
7034887Schin if (!(p = (Save_t*)dtmatch(dict, s)))
7044887Schin {
7054887Schin if (!(p = newof(0, Save_t, 1, strlen(s))))
7064887Schin return (char*)s;
7074887Schin strcpy(p->text, s);
7084887Schin dtinsert(dict, p);
7094887Schin }
7104887Schin return p->text;
7114887Schin }
7124887Schin
7134887Schin /*
7144887Schin * initialize the attributes for pass p from opt string s
7154887Schin */
7164887Schin
7174887Schin static int
init(register char * s,Optpass_t * p)7184887Schin init(register char* s, Optpass_t* p)
7194887Schin {
7204887Schin register char* t;
721*12068SRoger.Faulkner@Oracle.COM register char* u;
7224887Schin register int c;
7234887Schin register int a;
7244887Schin register int n;
7254887Schin
7264887Schin if (!opt_info.state->msgdict)
7274887Schin {
7284887Schin #if !_PACKAGE_astsa
7294887Schin if (!ast.locale.serial)
7304887Schin setlocale(LC_ALL, "");
7314887Schin #endif
7324887Schin opt_info.state->vp = sfstropen();
7334887Schin opt_info.state->xp = sfstropen();
7344887Schin opt_info.state->msgdisc.key = offsetof(Msg_t, text);
7354887Schin opt_info.state->msgdisc.size = -1;
7364887Schin opt_info.state->msgdisc.link = offsetof(Msg_t, link);
7374887Schin if (opt_info.state->msgdict = dtopen(&opt_info.state->msgdisc, Dthash))
7384887Schin for (n = 0; n < elementsof(C_LC_MESSAGES_libast); n++)
7394887Schin dtinsert(opt_info.state->msgdict, C_LC_MESSAGES_libast + n);
7404887Schin if (!map[OPT_FLAGS[0]])
7414887Schin for (n = 0, t = OPT_FLAGS; *t; t++)
7424887Schin map[*t] = ++n;
7434887Schin }
7444887Schin #if _BLD_DEBUG
7454887Schin error(-1, "optget debug");
7464887Schin #endif
7474887Schin p->oopts = s;
7484887Schin p->version = 0;
7494887Schin p->prefix = 2;
7504887Schin p->section = 1;
7514887Schin p->flags = 0;
752*12068SRoger.Faulkner@Oracle.COM p->id = error_info.id;
7534887Schin p->catalog = 0;
7544887Schin s = next(s, 0);
7554887Schin if (*s == ':')
7564887Schin s++;
7574887Schin if (*s == '+')
7584887Schin s++;
7594887Schin s = next(s, 0);
7604887Schin if (*s++ == '[')
7614887Schin {
7624887Schin if (*s == '+')
7634887Schin p->version = 1;
7644887Schin else if (*s++ == '-')
7654887Schin {
7664887Schin if (*s == '?' || *s == ']')
7674887Schin p->version = 1;
7684887Schin else
7694887Schin {
7708462SApril.Chin@Sun.COM if (!isdigit(*s))
7714887Schin p->version = 1;
7724887Schin else
7738462SApril.Chin@Sun.COM while (isdigit(*s))
7744887Schin p->version = p->version * 10 + (*s++ - '0');
7754887Schin while (*s && *s != '?' && *s != ']')
7764887Schin {
7774887Schin c = *s++;
7788462SApril.Chin@Sun.COM if (!isdigit(*s))
7794887Schin n = 1;
7804887Schin else
7814887Schin {
7824887Schin n = 0;
7838462SApril.Chin@Sun.COM while (isdigit(*s))
7844887Schin n = n * 10 + (*s++ - '0');
7854887Schin }
7864887Schin switch (c)
7874887Schin {
7888462SApril.Chin@Sun.COM case '+':
7898462SApril.Chin@Sun.COM p->flags |= OPT_plus;
7908462SApril.Chin@Sun.COM break;
7914887Schin case 'c':
7924887Schin p->flags |= OPT_cache;
7934887Schin break;
7944887Schin case 'i':
7954887Schin p->flags |= OPT_ignore;
7964887Schin break;
7974887Schin case 'l':
7984887Schin p->flags |= OPT_long;
7994887Schin break;
8008462SApril.Chin@Sun.COM case 'n':
8018462SApril.Chin@Sun.COM p->flags |= OPT_numeric;
8028462SApril.Chin@Sun.COM break;
8034887Schin case 'o':
8044887Schin p->flags |= OPT_old;
8054887Schin break;
8064887Schin case 'p':
8074887Schin p->prefix = n;
8084887Schin break;
8094887Schin case 's':
8104887Schin p->section = n;
8114887Schin if (n > 1 && n < 6)
8124887Schin {
8134887Schin p->flags |= OPT_functions;
8144887Schin p->prefix = 0;
8154887Schin }
8164887Schin break;
8174887Schin }
8184887Schin }
8194887Schin }
8204887Schin }
8214887Schin while (*s)
822*12068SRoger.Faulkner@Oracle.COM if (*s++ == ']')
8234887Schin {
824*12068SRoger.Faulkner@Oracle.COM while (isspace(*s))
825*12068SRoger.Faulkner@Oracle.COM s++;
826*12068SRoger.Faulkner@Oracle.COM if (*s++ == '[')
8274887Schin {
828*12068SRoger.Faulkner@Oracle.COM if (*s++ != '-')
8294887Schin {
830*12068SRoger.Faulkner@Oracle.COM if (strneq(s - 1, "+NAME?", 6))
831*12068SRoger.Faulkner@Oracle.COM {
832*12068SRoger.Faulkner@Oracle.COM for (s += 5; *s == '\a' || *s == '\b' || *s == '\v' || *s == ' '; s++);
833*12068SRoger.Faulkner@Oracle.COM if (*s != '\f')
834*12068SRoger.Faulkner@Oracle.COM {
835*12068SRoger.Faulkner@Oracle.COM for (t = s; *t && *t != ' ' && *t != ']'; t++);
836*12068SRoger.Faulkner@Oracle.COM if (t > s)
837*12068SRoger.Faulkner@Oracle.COM {
838*12068SRoger.Faulkner@Oracle.COM u = t;
839*12068SRoger.Faulkner@Oracle.COM if (*(t - 1) == '\a' || *(t - 1) == '\b' || *(t - 1) == '\v')
840*12068SRoger.Faulkner@Oracle.COM t--;
841*12068SRoger.Faulkner@Oracle.COM if (t > s)
842*12068SRoger.Faulkner@Oracle.COM {
843*12068SRoger.Faulkner@Oracle.COM while (*u == ' ' || *u == '\\')
844*12068SRoger.Faulkner@Oracle.COM u++;
845*12068SRoger.Faulkner@Oracle.COM if (*u == '-' || *u == ']')
846*12068SRoger.Faulkner@Oracle.COM p->id = save(sfprints("%-.*s", t - s, s));
847*12068SRoger.Faulkner@Oracle.COM }
848*12068SRoger.Faulkner@Oracle.COM }
849*12068SRoger.Faulkner@Oracle.COM }
850*12068SRoger.Faulkner@Oracle.COM }
851*12068SRoger.Faulkner@Oracle.COM break;
8524887Schin }
853*12068SRoger.Faulkner@Oracle.COM if (*s == '-')
854*12068SRoger.Faulkner@Oracle.COM s++;
855*12068SRoger.Faulkner@Oracle.COM if (strneq(s, "catalog?", 8))
856*12068SRoger.Faulkner@Oracle.COM p->catalog = s += 8;
8574887Schin }
8584887Schin }
8594887Schin }
860*12068SRoger.Faulkner@Oracle.COM if (!error_info.id)
861*12068SRoger.Faulkner@Oracle.COM {
862*12068SRoger.Faulkner@Oracle.COM if (!(error_info.id = p->id))
863*12068SRoger.Faulkner@Oracle.COM p->id = "command";
864*12068SRoger.Faulkner@Oracle.COM }
865*12068SRoger.Faulkner@Oracle.COM else if (p->id == error_info.id)
866*12068SRoger.Faulkner@Oracle.COM p->id = save(p->id);
867*12068SRoger.Faulkner@Oracle.COM if (s = p->catalog)
868*12068SRoger.Faulkner@Oracle.COM 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;
8694887Schin if (!p->catalog)
8704887Schin {
871*12068SRoger.Faulkner@Oracle.COM if (opt_info.disc && opt_info.disc->catalog && (!p->id || !streq(opt_info.disc->catalog, p->id)))
8724887Schin p->catalog = opt_info.disc->catalog;
8734887Schin else
8744887Schin p->catalog = ID;
8754887Schin }
8764887Schin s = p->oopts;
8774887Schin if (*s == ':')
8784887Schin s++;
8794887Schin if (*s == '+')
8804887Schin {
8814887Schin s++;
8824887Schin p->flags |= OPT_plus;
8834887Schin }
8848462SApril.Chin@Sun.COM s = next(s, 0);
8854887Schin if (*s != '[')
8864887Schin for (t = s, a = 0; *t; t++)
8874887Schin if (!a && *t == '-')
8884887Schin {
8894887Schin p->flags |= OPT_minus;
8904887Schin break;
8914887Schin }
8924887Schin else if (*t == '[')
8934887Schin a++;
8944887Schin else if (*t == ']')
8954887Schin a--;
8964887Schin if (!p->version && (t = strchr(s, '(')) && strchr(t, ')') && (opt_info.state->cp || (opt_info.state->cp = sfstropen())))
8974887Schin {
8984887Schin /*
8994887Schin * solaris long option compatibility
9004887Schin */
9014887Schin
9024887Schin p->version = 1;
9034887Schin for (t = p->oopts; t < s; t++)
9044887Schin sfputc(opt_info.state->cp, *t);
9054887Schin n = t - p->oopts;
9064887Schin sfputc(opt_info.state->cp, '[');
9074887Schin sfputc(opt_info.state->cp, '-');
9084887Schin sfputc(opt_info.state->cp, ']');
909*12068SRoger.Faulkner@Oracle.COM c = *s++;
910*12068SRoger.Faulkner@Oracle.COM while (c)
9114887Schin {
9124887Schin sfputc(opt_info.state->cp, '[');
9134887Schin sfputc(opt_info.state->cp, c);
9144887Schin if (a = (c = *s++) == ':')
9154887Schin c = *s++;
9164887Schin if (c == '(')
9174887Schin {
9184887Schin sfputc(opt_info.state->cp, ':');
9194887Schin for (;;)
9204887Schin {
9214887Schin while ((c = *s++) && c != ')')
9224887Schin sfputc(opt_info.state->cp, c);
923*12068SRoger.Faulkner@Oracle.COM if (!c || (c = *s++) != '(')
9244887Schin break;
9254887Schin sfputc(opt_info.state->cp, '|');
9264887Schin }
9274887Schin }
9284887Schin sfputc(opt_info.state->cp, ']');
9294887Schin if (a)
9304887Schin sfputr(opt_info.state->cp, ":[string]", -1);
9314887Schin }
9324887Schin if (!(p->oopts = s = sfstruse(opt_info.state->cp)))
9334887Schin return -1;
9344887Schin s += n;
9354887Schin }
9364887Schin p->opts = s;
937*12068SRoger.Faulkner@Oracle.COM 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));
9384887Schin return 0;
9394887Schin }
9404887Schin
9414887Schin /*
9424887Schin * return the bold set/unset sequence for style
9434887Schin */
9444887Schin
9454887Schin static const char*
font(int f,int style,int set)9464887Schin font(int f, int style, int set)
9474887Schin {
9484887Schin switch (style)
9494887Schin {
9504887Schin case STYLE_html:
9514887Schin return fonts[f].html[set];
9524887Schin case STYLE_nroff:
9534887Schin return fonts[f].nroff[set];
9544887Schin case STYLE_short:
9554887Schin case STYLE_long:
9564887Schin case STYLE_posix:
9574887Schin case STYLE_api:
9584887Schin break;
9594887Schin default:
9604887Schin if (opt_info.state->emphasis > 0)
9614887Schin return fonts[f].term[set];
9624887Schin break;
9634887Schin }
9644887Schin return "";
9654887Schin }
9664887Schin
9674887Schin /*
9684887Schin * expand \f...\f info
9694887Schin * *p set to next char after second \f
9704887Schin * expanded value returned
9714887Schin */
9724887Schin
9734887Schin static char*
expand(register char * s,register char * e,char ** p,Sfio_t * ip,char * id)974*12068SRoger.Faulkner@Oracle.COM expand(register char* s, register char* e, char** p, Sfio_t* ip, char* id)
9754887Schin {
9764887Schin register int c;
9774887Schin register char* b = s;
9784887Schin int n;
9794887Schin
9804887Schin n = sfstrtell(ip);
9814887Schin c = 1;
9824887Schin while ((!e || s < e) && (c = *s++) && c != '\f');
9834887Schin sfwrite(ip, b, s - b - 1);
9844887Schin sfputc(ip, 0);
9854887Schin b = sfstrbase(ip) + n;
9864887Schin n = sfstrtell(ip);
9874887Schin if (!c)
9884887Schin s--;
9894887Schin if (*b == '?')
9904887Schin {
9914887Schin if (!*++b || streq(b, "NAME"))
9924887Schin {
993*12068SRoger.Faulkner@Oracle.COM if (!(b = id))
9944887Schin b = "command";
9954887Schin sfstrseek(ip, 0, SEEK_SET);
9964887Schin sfputr(ip, b, -1);
9974887Schin n = 0;
9984887Schin }
9994887Schin else
10004887Schin n = 1;
10014887Schin }
10024887Schin else if (!opt_info.disc || !opt_info.disc->infof || (*opt_info.disc->infof)(&opt_info, ip, b, opt_info.disc) < 0)
10034887Schin n = 0;
10044887Schin *p = s;
10054887Schin if (s = sfstruse(ip))
10064887Schin s += n;
10074887Schin else
10084887Schin s = "error";
10094887Schin return s;
10104887Schin }
10114887Schin
10124887Schin /*
10134887Schin * push \f...\f info
10144887Schin */
10154887Schin
10164887Schin static Push_t*
info(Push_t * psp,char * s,char * e,Sfio_t * ip,char * id)1017*12068SRoger.Faulkner@Oracle.COM info(Push_t* psp, char* s, char* e, Sfio_t* ip, char* id)
10184887Schin {
10194887Schin register char* b;
10204887Schin int n;
10214887Schin Push_t* tsp;
10224887Schin
10234887Schin static Push_t push;
10244887Schin
1025*12068SRoger.Faulkner@Oracle.COM b = expand(s, e, &s, ip, id);
10264887Schin n = strlen(b);
10274887Schin if (tsp = newof(0, Push_t, 1, n + 1))
10284887Schin {
10294887Schin tsp->nb = (char*)(tsp + 1);
10304887Schin tsp->ne = tsp->nb + n;
10314887Schin strcpy(tsp->nb, b);
10324887Schin }
10334887Schin else
10344887Schin tsp = &push;
10354887Schin tsp->next = psp;
10364887Schin tsp->ob = s;
10374887Schin tsp->oe = e;
10384887Schin return tsp;
10394887Schin }
10404887Schin
10414887Schin /*
10424887Schin * push translation
10434887Schin */
10444887Schin
10454887Schin static Push_t*
localize(Push_t * psp,char * s,char * e,int term,int n,Sfio_t * ip,int version,char * id,char * catalog)1046*12068SRoger.Faulkner@Oracle.COM localize(Push_t* psp, char* s, char* e, int term, int n, Sfio_t* ip, int version, char* id, char* catalog)
10474887Schin {
10484887Schin char* t;
10494887Schin char* u;
10504887Schin Push_t* tsp;
10514887Schin int c;
10524887Schin
10534887Schin t = skip(s, term, 0, 0, n, 0, 0, version);
10544887Schin if (e && t > e)
10554887Schin t = e;
10564887Schin while (s < t)
10574887Schin {
10584887Schin switch (c = *s++)
10594887Schin {
10604887Schin case ':':
10614887Schin case '?':
10624887Schin if (term && *s == c)
10634887Schin s++;
10644887Schin break;
10654887Schin case ']':
10664887Schin if (*s == c)
10674887Schin s++;
10684887Schin break;
10694887Schin }
10704887Schin sfputc(ip, c);
10714887Schin }
1072*12068SRoger.Faulkner@Oracle.COM if (!(s = sfstruse(ip)) || (u = T(id, catalog, s)) == s)
10734887Schin return 0;
10744887Schin n = strlen(u);
10754887Schin if (tsp = newof(0, Push_t, 1, n + 1))
10764887Schin {
10774887Schin tsp->nb = (char*)(tsp + 1);
10784887Schin tsp->ne = tsp->nb + n;
10794887Schin strcpy(tsp->nb, u);
10804887Schin tsp->ob = t;
10814887Schin tsp->oe = e;
10824887Schin tsp->ch = 1;
10834887Schin }
10844887Schin tsp->next = psp;
10854887Schin return tsp;
10864887Schin }
10874887Schin
10884887Schin /*
10894887Schin * output label s from [ ...label...[?...] ] to sp
10904887Schin * 1 returned if the label was translated
10914887Schin */
10924887Schin
10934887Schin 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)1094*12068SRoger.Faulkner@Oracle.COM 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)
10954887Schin {
10964887Schin register int c;
10974887Schin register char* t;
10984887Schin register char* e;
10994887Schin int ostyle;
11004887Schin int a;
11014887Schin int i;
11024887Schin char* p;
11034887Schin char* w;
11044887Schin char* y;
11054887Schin int va;
11064887Schin Push_t* tsp;
11074887Schin
11084887Schin int r = 0;
11094887Schin int n = 1;
11104887Schin Push_t* psp = 0;
11114887Schin
11124887Schin if ((ostyle = style) > (STYLE_nroff - (sep <= 0)) && f != FONT_LITERAL)
11134887Schin style = 0;
11144887Schin if (z < 0)
11154887Schin e = s + strlen(s);
11164887Schin else
11174887Schin e = s + z;
11184887Schin if (sep > 0)
11194887Schin {
11204887Schin if (sep == ' ' && style == STYLE_nroff)
11214887Schin sfputc(sp, '\\');
11224887Schin sfputc(sp, sep);
11234887Schin }
11244887Schin sep = !sep || z < 0;
11254887Schin va = 0;
11264887Schin y = 0;
11278462SApril.Chin@Sun.COM if (about)
11288462SApril.Chin@Sun.COM sfputc(sp, '(');
11294887Schin if (version < 1)
11304887Schin {
11314887Schin a = 0;
11324887Schin for (;;)
11334887Schin {
11344887Schin if (s >= e)
11354887Schin return r;
11364887Schin switch (c = *s++)
11374887Schin {
11384887Schin case '[':
11394887Schin a++;
11404887Schin break;
11414887Schin case ']':
11424887Schin if (--a < 0)
11434887Schin return r;
11444887Schin break;
11454887Schin }
11464887Schin sfputc(sp, c);
11474887Schin }
11484887Schin }
11494887Schin else if (level && (*(p = skip(s, 0, 0, 0, 1, level, 1, version)) == ':' || *p == '#'))
11504887Schin {
11514887Schin va = 0;
11524887Schin if (*++p == '?' || *p == *(p - 1))
11534887Schin {
11544887Schin p++;
11554887Schin va |= OPT_optional;
11564887Schin }
11574887Schin if (*(p = next(p, version)) == '[')
11584887Schin y = p + 1;
11594887Schin }
11604887Schin if (X(catalog) && (!level || *s == '\a' || *(s - 1) != '+') &&
1161*12068SRoger.Faulkner@Oracle.COM (tsp = localize(psp, s, e, (sep || level) ? '?' : 0, sep || level, ip, version, id, catalog)))
11624887Schin {
11634887Schin psp= tsp;
11644887Schin s = psp->nb;
11654887Schin e = psp->ne;
11664887Schin r = psp->ch > 0;
11674887Schin }
11684887Schin switch (*s)
11694887Schin {
11704887Schin case '\a':
11714887Schin if (f == FONT_ITALIC)
11724887Schin s++;
11734887Schin f = 0;
11744887Schin break;
11754887Schin case '\b':
11764887Schin if (f == FONT_BOLD)
11774887Schin s++;
11784887Schin f = 0;
11794887Schin break;
11804887Schin case '\v':
11814887Schin if (f == FONT_LITERAL)
11824887Schin s++;
11834887Schin f = 0;
11844887Schin break;
11854887Schin default:
11864887Schin if (f)
11874887Schin sfputr(sp, font(f, style, 1), -1);
11884887Schin break;
11894887Schin }
11904887Schin for (;;)
11914887Schin {
11924887Schin if (s >= e)
11934887Schin {
11944887Schin if (!(tsp = psp))
11954887Schin goto restore;
11964887Schin s = psp->ob;
11974887Schin e = psp->oe;
11984887Schin psp = psp->next;
11994887Schin free(tsp);
12004887Schin continue;
12014887Schin }
12024887Schin switch (c = *s++)
12034887Schin {
12044887Schin case '(':
12054887Schin if (n)
12064887Schin {
12074887Schin n = 0;
12084887Schin if (f)
12094887Schin {
12104887Schin sfputr(sp, font(f, style, 0), -1);
12114887Schin f = 0;
12124887Schin }
12134887Schin }
12144887Schin break;
12154887Schin case '?':
12164887Schin case ':':
12174887Schin case ']':
12184887Schin if (psp && psp->ch)
12194887Schin break;
12204887Schin if (y)
12214887Schin {
12224887Schin if (va & OPT_optional)
12234887Schin sfputc(sp, '[');
12244887Schin sfputc(sp, '=');
1225*12068SRoger.Faulkner@Oracle.COM label(sp, 0, y, 0, -1, 0, style, FONT_ITALIC, ip, version, id, catalog);
12264887Schin if (va & OPT_optional)
12274887Schin sfputc(sp, ']');
12284887Schin y = 0;
12294887Schin }
12304887Schin switch (c)
12314887Schin {
12324887Schin case '?':
12334887Schin if (*s == '?')
12344887Schin s++;
12354887Schin else if (*s == ']' && *(s + 1) != ']')
12364887Schin continue;
12374887Schin else if (sep)
12384887Schin goto restore;
1239*12068SRoger.Faulkner@Oracle.COM else if (X(catalog) && (tsp = localize(psp, s, e, 0, 1, ip, version, id, catalog)))
12404887Schin {
12414887Schin psp = tsp;
12424887Schin s = psp->nb;
12434887Schin e = psp->ne;
12444887Schin }
12454887Schin break;
12464887Schin case ']':
12474887Schin if (sep && *s++ != ']')
12484887Schin goto restore;
12494887Schin break;
12504887Schin case ':':
12514887Schin if (sep && *s++ != ':')
12524887Schin goto restore;
12534887Schin break;
12544887Schin }
12554887Schin break;
12564887Schin case '\a':
12574887Schin a = FONT_ITALIC;
12584887Schin setfont:
12594887Schin if (f & ~a)
12604887Schin {
12614887Schin sfputr(sp, font(f, style, 0), -1);
12624887Schin f = 0;
12634887Schin }
12644887Schin if (!f && style == STYLE_html)
12654887Schin {
12664887Schin for (t = s; t < e && !isspace(*t) && !iscntrl(*t); t++);
12674887Schin if (*t == c && *++t == '(')
12684887Schin {
12694887Schin w = t;
12704887Schin while (++t < e && isdigit(*t));
12714887Schin if (t < e && *t == ')' && t > w + 1)
12724887Schin {
12734887Schin sfprintf(sp, "<NOBR><A href=\"../man%-.*s/%-.*s.html\">%s%-.*s%s</A>%-.*s</NOBR>"
12744887Schin , t - w - 1, w + 1
12754887Schin , w - s - 1, s
12764887Schin , font(a, style, 1)
12774887Schin , w - s - 1, s
12784887Schin , font(a, style, 0)
12794887Schin , t - w + 1, w
12804887Schin );
12814887Schin s = t + 1;
12824887Schin continue;
12834887Schin }
12844887Schin }
12854887Schin }
12864887Schin sfputr(sp, font(a, style, !!(f ^= a)), -1);
12874887Schin continue;
12884887Schin case '\b':
12894887Schin a = FONT_BOLD;
12904887Schin goto setfont;
12914887Schin case '\f':
1292*12068SRoger.Faulkner@Oracle.COM psp = info(psp, s, e, ip, id);
12934887Schin if (psp->nb)
12944887Schin {
12954887Schin s = psp->nb;
12964887Schin e = psp->ne;
12974887Schin }
12984887Schin else
12994887Schin {
13004887Schin s = psp->ob;
13014887Schin psp = psp->next;
13024887Schin }
13034887Schin continue;
13044887Schin case '\n':
13054887Schin sfputc(sp, c);
13064887Schin for (i = 0; i < level; i++)
13074887Schin sfputc(sp, '\t');
13084887Schin continue;
13094887Schin case '\v':
13104887Schin a = FONT_LITERAL;
13114887Schin goto setfont;
13124887Schin case '<':
13134887Schin if (style == STYLE_html)
13144887Schin {
13154887Schin sfputr(sp, "<", -1);
13164887Schin c = 0;
13174887Schin for (t = s; t < e; t++)
13184887Schin if (!isalnum(*t) && *t != '_' && *t != '.' && *t != '-')
13194887Schin {
13204887Schin if (*t == '@')
13214887Schin {
13224887Schin if (c)
13234887Schin break;
13244887Schin c = 1;
13254887Schin }
13264887Schin else if (*t == '>')
13274887Schin {
13284887Schin if (c)
13294887Schin {
13304887Schin sfprintf(sp, "<A href=\"mailto:%-.*s>%-.*s</A>>", t - s, s, t - s, s);
13314887Schin s = t + 1;
13324887Schin }
13334887Schin break;
13344887Schin }
13354887Schin else
13364887Schin break;
13374887Schin }
13384887Schin continue;
13394887Schin }
13404887Schin break;
13414887Schin case '>':
13424887Schin if (style == STYLE_html)
13434887Schin {
13444887Schin sfputr(sp, ">", -1);
13454887Schin continue;
13464887Schin }
13474887Schin break;
13484887Schin case '&':
13494887Schin if (style == STYLE_html)
13504887Schin {
13514887Schin sfputr(sp, "&", -1);
13524887Schin continue;
13534887Schin }
13544887Schin break;
13554887Schin case '-':
13564887Schin if (ostyle == STYLE_nroff)
13574887Schin sfputc(sp, '\\');
13584887Schin break;
13594887Schin case '.':
13604887Schin if (ostyle == STYLE_nroff)
13614887Schin {
13624887Schin sfputc(sp, '\\');
13634887Schin sfputc(sp, '&');
13644887Schin }
13654887Schin break;
13664887Schin case '\\':
13674887Schin if (ostyle == STYLE_nroff)
13684887Schin {
13694887Schin c = 'e';
13704887Schin sfputc(sp, '\\');
13714887Schin }
13724887Schin break;
13734887Schin case ' ':
13744887Schin if (ostyle == STYLE_nroff)
13754887Schin sfputc(sp, '\\');
13764887Schin break;
13774887Schin }
13784887Schin sfputc(sp, c);
13794887Schin }
13804887Schin restore:
13814887Schin if (f)
13824887Schin sfputr(sp, font(f, style, 0), -1);
13838462SApril.Chin@Sun.COM if (about)
13848462SApril.Chin@Sun.COM sfputc(sp, ')');
13854887Schin if (psp)
13864887Schin pop(psp);
13874887Schin return r;
13884887Schin }
13894887Schin
13904887Schin /*
13914887Schin * output args description to sp from p of length n
13924887Schin */
13934887Schin
13944887Schin 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)1395*12068SRoger.Faulkner@Oracle.COM args(register Sfio_t* sp, register char* p, register int n, int flags, int style, Sfio_t* ip, int version, char* id, char* catalog)
13964887Schin {
13974887Schin register int i;
13984887Schin register char* t;
13994887Schin register char* o;
14004887Schin register char* a = 0;
14014887Schin char* b;
14024887Schin int sep;
14034887Schin
14044887Schin if (flags & OPT_functions)
14054887Schin sep = '\t';
14064887Schin else
14074887Schin {
14084887Schin sep = ' ';
14094887Schin o = T(NiL, ID, "options");
14104887Schin b = style == STYLE_nroff ? "\\ " : " ";
14114887Schin for (;;)
14124887Schin {
14134887Schin t = (char*)memchr(p, '\n', n);
14144887Schin if (style >= STYLE_man)
14154887Schin {
1416*12068SRoger.Faulkner@Oracle.COM if (!(a = id))
14174887Schin a = "...";
14184887Schin 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);
14194887Schin }
14204887Schin else if (a)
14214887Schin 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);
14224887Schin else
14234887Schin {
1424*12068SRoger.Faulkner@Oracle.COM if (!(a = error_info.id) && !(a = id))
14254887Schin a = "...";
14264887Schin if (!sfstrtell(sp))
14274887Schin sfprintf(sp, "[%s%s%s]", b, o, b);
14284887Schin }
14294887Schin if (!t)
14304887Schin break;
14314887Schin i = ++t - p;
14324887Schin if (i)
14334887Schin {
14344887Schin sfputr(sp, b, -1);
14354887Schin if (X(catalog))
14364887Schin {
14374887Schin sfwrite(ip, p, i);
14384887Schin if (b = sfstruse(ip))
1439*12068SRoger.Faulkner@Oracle.COM sfputr(sp, T(id, catalog, b), -1);
14404887Schin else
14414887Schin sfwrite(sp, p, i);
14424887Schin }
14434887Schin else
14444887Schin sfwrite(sp, p, i);
14454887Schin }
14464887Schin if (style == STYLE_html)
14474887Schin sfputr(sp, "<BR>", '\n');
14484887Schin else if (style == STYLE_nroff)
14494887Schin sfputr(sp, ".br", '\n');
14504887Schin else if (style == STYLE_api)
14514887Schin sfputr(sp, ".BR", '\n');
14524887Schin p = t;
14534887Schin n -= i;
14544887Schin while (n > 0 && (*p == ' ' || *p == '\t'))
14554887Schin {
14564887Schin p++;
14574887Schin n--;
14584887Schin }
14594887Schin }
14604887Schin }
14614887Schin if (n)
1462*12068SRoger.Faulkner@Oracle.COM label(sp, sep, p, 0, n, 0, style, 0, ip, version, id, catalog);
14634887Schin }
14644887Schin
14654887Schin /*
14664887Schin * output [+-...label...?...] label s to sp
14674887Schin * according to {...} level and style
14684887Schin * return 0:header 1:paragraph
14694887Schin */
14704887Schin
14714887Schin static int
item(Sfio_t * sp,char * s,int about,int level,int style,Sfio_t * ip,int version,char * id,char * catalog)1472*12068SRoger.Faulkner@Oracle.COM item(Sfio_t* sp, char* s, int about, int level, int style, Sfio_t* ip, int version, char* id, char* catalog)
14734887Schin {
14744887Schin register char* t;
14754887Schin int n;
14764887Schin int par;
14774887Schin
14784887Schin sfputc(sp, '\n');
14794887Schin if (*s == '\n')
14804887Schin {
14814887Schin par = 0;
14824887Schin if (style >= STYLE_nroff)
14834887Schin sfprintf(sp, ".DS\n");
14844887Schin else
14854887Schin {
14864887Schin if (style == STYLE_html)
14874887Schin sfprintf(sp, "<PRE>\n");
14884887Schin else
14894887Schin sfputc(sp, '\n');
14904887Schin for (n = 0; n < level; n++)
14914887Schin sfputc(sp, '\t');
14924887Schin }
1493*12068SRoger.Faulkner@Oracle.COM label(sp, 0, s + 1, about, -1, level, style, FONT_LITERAL, ip, version, id, catalog);
14944887Schin sfputc(sp, '\n');
14954887Schin if (style >= STYLE_nroff)
14964887Schin sfprintf(sp, ".DE");
14974887Schin else if (style == STYLE_html)
14984887Schin sfprintf(sp, "</PRE>");
14994887Schin }
15004887Schin else if (*s != ']' && (*s != '?' || *(s + 1) == '?'))
15014887Schin {
15024887Schin par = 0;
15034887Schin if (level)
15044887Schin {
15054887Schin if (style >= STYLE_nroff)
15068462SApril.Chin@Sun.COM sfprintf(sp, ".H%d ", (level - (level > 2)) / 2);
15074887Schin else
15084887Schin for (n = 0; n < level; n++)
15094887Schin sfputc(sp, '\t');
15104887Schin }
15114887Schin if (style == STYLE_html)
15124887Schin {
15134887Schin if (!level)
15144887Schin sfputr(sp, "<H4>", -1);
15154887Schin sfputr(sp, "<A name=\"", -1);
15164887Schin 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] == '?')
15174887Schin for (t = s + 8; *t && *t != ']'; t++)
15184887Schin if (t[0] == 'p' && (!strncmp(t, "proprietary", 11) || !strncmp(t, "private", 7)) || t[0] == 'n' && !strncmp(t, "noncommercial", 13))
15194887Schin {
15204887Schin opt_info.state->flags |= OPT_proprietary;
15214887Schin break;
15224887Schin }
1523*12068SRoger.Faulkner@Oracle.COM label(sp, 0, s, about, -1, level, 0, 0, ip, version, id, catalog);
15244887Schin sfputr(sp, "\">", -1);
1525*12068SRoger.Faulkner@Oracle.COM label(sp, 0, s, about, -1, level, style, level ? FONT_BOLD : 0, ip, version, id, catalog);
15264887Schin sfputr(sp, "</A>", -1);
15274887Schin if (!level)
15284887Schin sfputr(sp, "</H4>", -1);
15294887Schin }
15304887Schin else
15314887Schin {
15324887Schin if (!level)
15334887Schin {
15344887Schin if (style >= STYLE_nroff)
15354887Schin sfprintf(sp, ".SH ");
15364887Schin else if (style == STYLE_man)
15374887Schin sfputc(sp, '\n');
15384887Schin else if (style != STYLE_options && style != STYLE_match || *s == '-' || *s == '+')
15394887Schin sfputc(sp, '\t');
15404887Schin }
1541*12068SRoger.Faulkner@Oracle.COM label(sp, 0, s, about, -1, level, style, FONT_BOLD, ip, version, id, catalog);
15424887Schin }
15434887Schin }
15444887Schin else
15454887Schin {
15464887Schin par = 1;
15474887Schin if (style >= STYLE_nroff)
15488462SApril.Chin@Sun.COM sfputr(sp, level ? ".SP" : ".PP", -1);
15494887Schin }
15504887Schin if (style >= STYLE_nroff || !level)
15514887Schin sfputc(sp, '\n');
15524887Schin if (par && style < STYLE_nroff)
15534887Schin for (n = 0; n < level; n++)
15544887Schin sfputc(sp, '\t');
15554887Schin return par;
15564887Schin }
15574887Schin
15584887Schin /*
15594887Schin * output text to sp from p according to style
15604887Schin */
15614887Schin
1562*12068SRoger.Faulkner@Oracle.COM #if _BLD_DEBUG
1563*12068SRoger.Faulkner@Oracle.COM
1564*12068SRoger.Faulkner@Oracle.COM static char* textout(Sfio_t*, char*, int, int, int, Sfio_t*, int, char*, char*);
1565*12068SRoger.Faulkner@Oracle.COM
15664887Schin 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)1567*12068SRoger.Faulkner@Oracle.COM 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)
15684887Schin {
1569*12068SRoger.Faulkner@Oracle.COM static int depth = 0;
1570*12068SRoger.Faulkner@Oracle.COM
1571*12068SRoger.Faulkner@Oracle.COM message((-21, "opthelp: txt#%d +++ %2d \"%s\" style=%d level=%d bump=%d", line, ++depth, show(p), style, level, bump));
1572*12068SRoger.Faulkner@Oracle.COM p = textout(sp, p, style, level, bump, ip, version, id, catalog);
1573*12068SRoger.Faulkner@Oracle.COM message((-21, "opthelp: txt#%d --- %2d \"%s\"", line, depth--, show(p)));
1574*12068SRoger.Faulkner@Oracle.COM return p;
1575*12068SRoger.Faulkner@Oracle.COM }
1576*12068SRoger.Faulkner@Oracle.COM
1577*12068SRoger.Faulkner@Oracle.COM #endif
1578*12068SRoger.Faulkner@Oracle.COM
1579*12068SRoger.Faulkner@Oracle.COM static char*
textout(Sfio_t * sp,register char * p,int style,int level,int bump,Sfio_t * ip,int version,char * id,char * catalog)1580*12068SRoger.Faulkner@Oracle.COM textout(Sfio_t* sp, register char* p, int style, int level, int bump, Sfio_t* ip, int version, char* id, char* catalog)
1581*12068SRoger.Faulkner@Oracle.COM {
1582*12068SRoger.Faulkner@Oracle.COM #if _BLD_DEBUG
1583*12068SRoger.Faulkner@Oracle.COM #define textout(sp,p,style,level,bump,ip,version,id,catalog) trace_textout(sp,p,style,level,bump,ip,version,id,catalog,__LINE__)
15844887Schin #endif
15854887Schin register char* t;
15864887Schin register int c;
15874887Schin register int n;
15884887Schin char* e;
15894887Schin int a;
15904887Schin int f;
15914887Schin int par;
15928462SApril.Chin@Sun.COM int about;
15934887Schin Push_t* tsp;
15944887Schin
15954887Schin int ident = 0;
15964887Schin int lev = level;
15974887Schin Push_t* psp = 0;
15984887Schin
15994887Schin again:
16008462SApril.Chin@Sun.COM about = 0;
16014887Schin if ((c = *p) == GO)
16024887Schin {
16034887Schin for (;;)
16044887Schin {
16054887Schin while (*(p = next(p + 1, version)) == '\n');
16064887Schin if (*p == GO)
16074887Schin {
16084887Schin if (level > 1)
16094887Schin level++;
16104887Schin level++;
16114887Schin }
16124887Schin else if (*p != OG)
16134887Schin {
16148462SApril.Chin@Sun.COM if (level <= 1 || *p != '[' || *(p + 1) != '-' || style == STYLE_man && *(p + 2) == '?' || isalpha(*(p + 2)))
16154887Schin break;
16164887Schin p = skip(p, 0, 0, 0, 1, level, 0, version);
16174887Schin }
16184887Schin else if ((level -= 2) <= lev)
16194887Schin return p + 1;
16204887Schin }
16214887Schin if (*p == '\f')
16224887Schin {
1623*12068SRoger.Faulkner@Oracle.COM psp = info(psp, p + 1, NiL, ip, id);
16244887Schin if (psp->nb)
16254887Schin p = psp->nb;
16264887Schin else
16274887Schin {
16284887Schin p = psp->ob;
16294887Schin psp = psp->next;
16304887Schin }
16314887Schin }
16324887Schin if (*p != '[')
16334887Schin return p;
16344887Schin c = *++p;
16354887Schin if (level > 1)
16364887Schin level++;
16374887Schin level++;
16384887Schin }
16394887Schin if (c == '-' && level > 1)
16408462SApril.Chin@Sun.COM {
16418462SApril.Chin@Sun.COM if (style == STYLE_man)
16428462SApril.Chin@Sun.COM {
16438462SApril.Chin@Sun.COM about = 1;
16448462SApril.Chin@Sun.COM if (*(p + 1) == '-')
16458462SApril.Chin@Sun.COM p++;
16468462SApril.Chin@Sun.COM }
16478462SApril.Chin@Sun.COM else
16488462SApril.Chin@Sun.COM for (;;)
16498462SApril.Chin@Sun.COM {
16508462SApril.Chin@Sun.COM p = skip(p, 0, 0, 0, 1, level, 0, version);
16518462SApril.Chin@Sun.COM while (*(p = next(p + 1, version)) == '\n');
16528462SApril.Chin@Sun.COM if (*p == '[')
16538462SApril.Chin@Sun.COM {
16548462SApril.Chin@Sun.COM if ((c = *++p) != '-')
16558462SApril.Chin@Sun.COM break;
16568462SApril.Chin@Sun.COM }
16578462SApril.Chin@Sun.COM else if (*p == GO)
16588462SApril.Chin@Sun.COM goto again;
16598462SApril.Chin@Sun.COM else if (*p == OG)
16608462SApril.Chin@Sun.COM return p + 1;
16618462SApril.Chin@Sun.COM }
16628462SApril.Chin@Sun.COM }
16634887Schin if (c == '+' || c == '-' && (bump = 3) || c != ' ' && level > 1)
16644887Schin {
16654887Schin p = skip(t = p + 1, '?', 0, 0, 1, level, 0, version);
16668462SApril.Chin@Sun.COM if (c == '-' && (*t == '?' || isdigit(*t) || *p == '?' && *(p + 1) == '\n'))
16674887Schin {
16684887Schin if ((c = *p) != '?')
16694887Schin return skip(p, 0, 0, 0, 1, level, 1, version);
16708462SApril.Chin@Sun.COM e = C("version");
1671*12068SRoger.Faulkner@Oracle.COM par = item(sp, e, about, level, style, ip, version, id, ID);
16724887Schin for (;;)
16734887Schin {
16744887Schin while (isspace(*(p + 1)))
16754887Schin p++;
16764887Schin e = p;
16774887Schin if (e[1] == '@' && e[2] == '(' && e[3] == '#' && e[4] == ')')
16784887Schin p = e + 4;
16794887Schin else if (e[1] == '$' && e[2] == 'I' && e[3] == 'd' && e[4] == ':' && e[5] == ' ')
16804887Schin {
16814887Schin p = e + 5;
16824887Schin ident = 1;
16834887Schin }
16844887Schin else
16854887Schin break;
16864887Schin }
16874887Schin }
16884887Schin else
16894887Schin {
16904887Schin if (isdigit(c) && isdigit(*t))
16914887Schin {
16924887Schin while (isdigit(*t))
16934887Schin t++;
16944887Schin if (*t == ':')
16954887Schin t++;
16964887Schin }
16974887Schin else if (isalnum(c) && *t-- == ':')
16984887Schin {
16994887Schin if (X(catalog) || *t == *(t + 2))
17004887Schin t += 2;
17014887Schin else
17024887Schin {
17034887Schin sfprintf(ip, "%s", t);
17044887Schin if (e = sfstruse(ip))
17054887Schin *((t = e) + 1) = '|';
17064887Schin }
17074887Schin }
1708*12068SRoger.Faulkner@Oracle.COM par = item(sp, t, about, level, style, ip, version, id, catalog);
17094887Schin c = *p;
17104887Schin }
17118462SApril.Chin@Sun.COM if (!about && level)
17124887Schin par = 0;
17134887Schin }
17144887Schin else
17154887Schin {
17164887Schin if (style >= STYLE_nroff)
17174887Schin sfputc(sp, '\n');
17184887Schin else if (c == '?')
17194887Schin for (n = 0; n < level; n++)
17204887Schin sfputc(sp, '\t');
17214887Schin par = 0;
17224887Schin }
17234887Schin if (c == ':')
17244887Schin c = *(p = skip(p, '?', 0, 0, 1, 0, 0, version));
17254887Schin if ((c == ']' || c == '?' && *(p + 1) == ']' && *(p + 2) != ']' && p++) && (c = *(p = next(p + 1, version))) == GO)
1726*12068SRoger.Faulkner@Oracle.COM {
1727*12068SRoger.Faulkner@Oracle.COM p = textout(sp, p, style, level + bump + par + 1, 0, ip, version, id, catalog);
1728*12068SRoger.Faulkner@Oracle.COM if (level > lev && *p && *(p = next(p, version)) == '[')
1729*12068SRoger.Faulkner@Oracle.COM {
1730*12068SRoger.Faulkner@Oracle.COM p++;
1731*12068SRoger.Faulkner@Oracle.COM message((-21, "textout#%d p=%s", __LINE__, show(p)));
1732*12068SRoger.Faulkner@Oracle.COM goto again;
1733*12068SRoger.Faulkner@Oracle.COM }
1734*12068SRoger.Faulkner@Oracle.COM }
17354887Schin else if (c == '?' || c == ' ')
17364887Schin {
17374887Schin p++;
17384887Schin if (c == ' ')
17394887Schin sfputc(sp, c);
17404887Schin else
17414887Schin {
1742*12068SRoger.Faulkner@Oracle.COM if (X(catalog) && (tsp = localize(psp, p, NiL, 0, 1, ip, version, id, catalog)))
17434887Schin {
17444887Schin psp = tsp;
17454887Schin p = psp->nb;
17464887Schin }
17474887Schin if (style < STYLE_nroff)
17484887Schin for (n = 0; n < bump + 1; n++)
17494887Schin sfputc(sp, '\t');
17504887Schin }
17514887Schin f = 0;
17524887Schin for (;;)
17534887Schin {
17544887Schin switch (c = *p++)
17554887Schin {
17564887Schin case 0:
17574887Schin if (!(tsp = psp))
17584887Schin {
17594887Schin if (f)
17604887Schin sfputr(sp, font(f, style, 0), -1);
17614887Schin return p - 1;
17624887Schin }
17634887Schin p = psp->ob;
17644887Schin psp = psp->next;
17654887Schin free(tsp);
17664887Schin continue;
17674887Schin case ']':
17684887Schin if (psp && psp->ch)
17694887Schin break;
17704887Schin if (*p != ']')
17714887Schin {
17724887Schin if (f)
17734887Schin {
17744887Schin sfputr(sp, font(f, style, 0), -1);
17754887Schin f = 0;
17764887Schin }
17774887Schin for (;;)
17784887Schin {
17794887Schin if ((*p == '#' || *p == ':') && level > lev)
17804887Schin {
17814887Schin char* o;
17824887Schin char* v;
17834887Schin int j;
17844887Schin int m;
17854887Schin int ol;
17864887Schin int vl;
17874887Schin
17884887Schin a = 0;
17894887Schin o = 0;
17904887Schin v = 0;
17914887Schin if (*++p == '?' || *p == *(p - 1))
17924887Schin {
17934887Schin p++;
17944887Schin a |= OPT_optional;
17954887Schin }
17964887Schin if (*(p = next(p, version)) == '[')
17974887Schin {
17984887Schin p = skip(p + 1, ':', '?', 0, 1, 0, 0, version);
17994887Schin while (*p == ':')
18004887Schin {
18014887Schin p = skip(t = p + 1, ':', '?', 0, 1, 0, 0, version);
18024887Schin m = p - t;
18034887Schin if (*t == '!')
18044887Schin {
18054887Schin o = t + 1;
18064887Schin ol = m - 1;
18074887Schin }
18084887Schin else if (*t == '=')
18094887Schin {
18104887Schin v = t + 1;
18114887Schin vl = m - 1;
18124887Schin }
18134887Schin else
18144887Schin for (j = 0; j < elementsof(attrs); j++)
18154887Schin if (strneq(t, attrs[j].name, m))
18164887Schin {
18174887Schin a |= attrs[j].flag;
18184887Schin break;
18194887Schin }
18204887Schin }
18214887Schin }
18224887Schin if (a & OPT_optional)
18234887Schin {
18244887Schin if (o)
18254887Schin {
18264887Schin sfprintf(sp, " %s ", T(NiL, ID, "If the option value is omitted then"));
18274887Schin sfputr(sp, font(FONT_BOLD, style, 1), -1);
18284887Schin t = o + ol;
18294887Schin while (o < t)
18304887Schin {
18314887Schin if (((c = *o++) == ':' || c == '?') && *o == c)
18324887Schin o++;
18334887Schin sfputc(sp, c);
18344887Schin }
18354887Schin sfputr(sp, font(FONT_BOLD, style, 0), -1);
18364887Schin sfprintf(sp, " %s.", T(NiL, ID, "is assumed"));
18374887Schin }
18384887Schin else
18394887Schin sfprintf(sp, " %s", T(NiL, ID, "The option value may be omitted."));
18404887Schin }
18414887Schin if (v)
18424887Schin {
18434887Schin sfprintf(sp, " %s ", T(NiL, ID, "The default value is"));
18444887Schin sfputr(sp, font(FONT_BOLD, style, 1), -1);
18454887Schin t = v + vl;
18464887Schin while (v < t)
18474887Schin {
18484887Schin if (((c = *v++) == ':' || c == '?') && *v == c)
18494887Schin v++;
18504887Schin sfputc(sp, c);
18514887Schin }
18524887Schin sfputr(sp, font(FONT_BOLD, style, 0), -1);
18534887Schin sfputc(sp, '.');
18544887Schin }
18554887Schin p = skip(p, 0, 0, 0, 1, 0, 1, version);
18564887Schin }
18574887Schin if (*(p = next(p, version)) == GO)
1858*12068SRoger.Faulkner@Oracle.COM {
1859*12068SRoger.Faulkner@Oracle.COM p = textout(sp, p, style, level + bump + !level, 0, ip, version, id, catalog);
1860*12068SRoger.Faulkner@Oracle.COM if (*p && *(p = next(p, version)) == '[' && !isalnum(*(p + 1)))
1861*12068SRoger.Faulkner@Oracle.COM {
1862*12068SRoger.Faulkner@Oracle.COM p++;
1863*12068SRoger.Faulkner@Oracle.COM message((-21, "textout#%d p=%s", __LINE__, show(p)));
1864*12068SRoger.Faulkner@Oracle.COM goto again;
1865*12068SRoger.Faulkner@Oracle.COM }
1866*12068SRoger.Faulkner@Oracle.COM }
18674887Schin else if (*p == '[' && level > lev)
18684887Schin {
18694887Schin p++;
18704887Schin goto again;
18714887Schin }
18724887Schin else if (*p == '\f')
18734887Schin {
18744887Schin p++;
18754887Schin if (style != STYLE_keys)
18764887Schin {
1877*12068SRoger.Faulkner@Oracle.COM psp = info(psp, p, NiL, ip, id);
18784887Schin if (psp->nb)
18794887Schin p = psp->nb;
18804887Schin else
18814887Schin {
18824887Schin p = psp->ob;
18834887Schin psp = psp->next;
18844887Schin }
18854887Schin }
18864887Schin }
18874887Schin else if (!*p)
18884887Schin {
18894887Schin if (!(tsp = psp))
18904887Schin break;
18914887Schin p = psp->ob;
18924887Schin psp = psp->next;
18934887Schin free(tsp);
18944887Schin }
18954887Schin else if (*p != OG)
18964887Schin break;
18974887Schin else
18984887Schin {
18994887Schin p++;
19004887Schin if ((level -= 2) <= lev)
19014887Schin break;
19024887Schin }
19034887Schin }
19044887Schin return p;
19054887Schin }
19064887Schin p++;
19074887Schin break;
19084887Schin case '\a':
19094887Schin a = FONT_ITALIC;
19104887Schin setfont:
19114887Schin if (f & ~a)
19124887Schin {
19134887Schin sfputr(sp, font(f, style, 0), -1);
19144887Schin f = 0;
19154887Schin }
19164887Schin if (!f && style == STYLE_html)
19174887Schin {
19184887Schin for (t = p; *t && !isspace(*t) && !iscntrl(*t); t++);
19194887Schin if (*t == c && *++t == '(')
19204887Schin {
19214887Schin e = t;
19224887Schin while (isdigit(*++t));
19234887Schin if (*t == ')' && t > e + 1)
19244887Schin {
19254887Schin sfprintf(sp, "<NOBR><A href=\"../man%-.*s/%-.*s.html\">%s%-.*s%s</A>%-.*s</NOBR>"
19264887Schin , t - e - 1, e + 1
19274887Schin , e - p - 1, p
19284887Schin , font(a, style, 1)
19294887Schin , e - p - 1, p
19304887Schin , font(a, style, 0)
19314887Schin , t - e + 1, e
19324887Schin );
19334887Schin p = t + 1;
19344887Schin continue;
19354887Schin }
19364887Schin }
19374887Schin }
19384887Schin sfputr(sp, font(a, style, !!(f ^= a)), -1);
19394887Schin continue;
19404887Schin case '\b':
19414887Schin a = FONT_BOLD;
19424887Schin goto setfont;
19434887Schin case '\f':
19444887Schin if (style != STYLE_keys)
19454887Schin {
1946*12068SRoger.Faulkner@Oracle.COM psp = info(psp, p, NiL, ip, id);
19474887Schin if (psp->nb)
19484887Schin p = psp->nb;
19494887Schin else
19504887Schin {
19514887Schin p = psp->ob;
19524887Schin psp = psp->next;
19534887Schin }
19544887Schin }
19554887Schin continue;
19564887Schin case '\v':
19574887Schin a = FONT_LITERAL;
19584887Schin goto setfont;
19594887Schin case ' ':
19604887Schin if (ident && *p == '$')
19614887Schin {
19624887Schin while (*++p)
19634887Schin if (*p == ']')
19644887Schin {
19654887Schin if (*(p + 1) != ']')
19664887Schin break;
19674887Schin p++;
19684887Schin }
19694887Schin continue;
19704887Schin }
19714887Schin case '\n':
19724887Schin case '\r':
19734887Schin case '\t':
19744887Schin while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
19754887Schin p++;
19764887Schin if (*p == ']' && *(p + 1) != ']' && (!psp || !psp->ch))
19774887Schin continue;
19784887Schin c = ' ';
19794887Schin break;
19804887Schin case '<':
19814887Schin if (style == STYLE_html)
19824887Schin {
19834887Schin sfputr(sp, "<", -1);
19844887Schin c = 0;
19854887Schin for (t = p; *t; t++)
19864887Schin if (!isalnum(*t) && *t != '_' && *t != '.' && *t != '-')
19874887Schin {
19884887Schin if (*t == '@')
19894887Schin {
19904887Schin if (c)
19914887Schin break;
19924887Schin c = 1;
19934887Schin }
19944887Schin else if (*t == '>')
19954887Schin {
19964887Schin if (c)
19974887Schin {
19984887Schin sfprintf(sp, "<A href=\"mailto:%-.*s\">%-.*s</A>>", t - p, p, t - p, p);
19994887Schin p = t + 1;
20004887Schin }
20014887Schin break;
20024887Schin }
20034887Schin else
20044887Schin break;
20054887Schin }
20064887Schin continue;
20074887Schin }
20084887Schin break;
20094887Schin case '>':
20104887Schin if (style == STYLE_html)
20114887Schin {
20124887Schin sfputr(sp, ">", -1);
20134887Schin continue;
20144887Schin }
20154887Schin break;
20164887Schin case '&':
20174887Schin if (style == STYLE_html)
20184887Schin {
20194887Schin sfputr(sp, "&", -1);
20204887Schin continue;
20214887Schin }
20224887Schin break;
20234887Schin case '-':
20244887Schin if (style == STYLE_nroff)
20254887Schin sfputc(sp, '\\');
20264887Schin break;
20274887Schin case '.':
20284887Schin if (style == STYLE_nroff)
20294887Schin {
20304887Schin sfputc(sp, '\\');
20314887Schin sfputc(sp, '&');
20324887Schin }
20334887Schin break;
20344887Schin case '\\':
20354887Schin if (style == STYLE_nroff)
20364887Schin {
20374887Schin sfputc(sp, c);
20384887Schin c = 'e';
20394887Schin }
20404887Schin break;
20414887Schin }
20424887Schin sfputc(sp, c);
20434887Schin }
20444887Schin }
20454887Schin else if (c == '[' && level > lev)
20464887Schin {
20474887Schin p++;
20484887Schin goto again;
20494887Schin }
20504887Schin return p;
20514887Schin }
20524887Schin
20534887Schin /*
20544887Schin * generate optget() help [...] list from lp
20554887Schin */
20564887Schin
20574887Schin static void
list(Sfio_t * sp,register const List_t * lp)20584887Schin list(Sfio_t* sp, register const List_t* lp)
20594887Schin {
20604887Schin sfprintf(sp, "[%c", lp->type);
20614887Schin if (lp->name)
20624887Schin {
20634887Schin sfprintf(sp, "%s", lp->name);
20644887Schin if (lp->text)
20654887Schin sfprintf(sp, "?%s", lp->text);
20664887Schin }
20674887Schin sfputc(sp, ']');
20684887Schin }
20694887Schin
20704887Schin /*
20714887Schin * return pointer to help message sans `Usage: command'
20724887Schin * if oopts is 0 then opt_info.state->pass is used
20734887Schin * what:
20744887Schin * 0 ?short by default, ?long if any long options used
20754887Schin * * otherwise see help_text[] (--???)
20764887Schin * external formatter:
20774887Schin * \a...\a italic
20784887Schin * \b...\b bold
20794887Schin * \f...\f discipline infof callback on ...
20804887Schin * \v...\v literal
20814887Schin * internal formatter:
20824887Schin * \t indent
20834887Schin * \n newline
20844887Schin * margin flush pops to previous indent
20854887Schin */
20864887Schin
20874887Schin char*
opthelp(const char * oopts,const char * what)20884887Schin opthelp(const char* oopts, const char* what)
20894887Schin {
20904887Schin register Sfio_t* sp;
20914887Schin register Sfio_t* mp;
20924887Schin register int c;
20934887Schin register char* p;
20944887Schin register Indent_t* ip;
20954887Schin char* t;
20964887Schin char* x;
20974887Schin char* w;
20984887Schin char* u;
20994887Schin char* y;
21004887Schin char* s;
21014887Schin char* d;
21024887Schin char* v;
21034887Schin char* ov;
21044887Schin char* pp;
21054887Schin char* rb;
21064887Schin char* re;
21074887Schin int f;
21084887Schin int i;
21094887Schin int j;
21104887Schin int m;
21114887Schin int n;
21124887Schin int a;
21134887Schin int sl;
21144887Schin int vl;
21154887Schin int ol;
21164887Schin int wl;
21174887Schin int xl;
21184887Schin int rm;
21194887Schin int ts;
21204887Schin int co;
21214887Schin int z;
21224887Schin int style;
21234887Schin int head;
21248462SApril.Chin@Sun.COM int margin;
21254887Schin int mode;
21264887Schin int mutex;
21274887Schin int prefix;
21284887Schin int version;
21294887Schin long tp;
2130*12068SRoger.Faulkner@Oracle.COM char* id;
21314887Schin char* catalog;
21324887Schin Optpass_t* o;
21334887Schin Optpass_t* q;
21344887Schin Optpass_t* e;
21354887Schin Optpass_t one;
21364887Schin Help_t* hp;
21374887Schin short ptstk[elementsof(indent) + 2];
21384887Schin short* pt;
21394887Schin Sfio_t* vp;
21404887Schin Push_t* tsp;
21414887Schin
21424887Schin char* opts = (char*)oopts;
21434887Schin int flags = 0;
21444887Schin int matched = 0;
21454887Schin int paragraph = 0;
21464887Schin int section = 1;
21474887Schin Push_t* psp = 0;
21484887Schin Sfio_t* sp_help = 0;
21494887Schin Sfio_t* sp_text = 0;
21504887Schin Sfio_t* sp_plus = 0;
21514887Schin Sfio_t* sp_head = 0;
21524887Schin Sfio_t* sp_body = 0;
21534887Schin Sfio_t* sp_info = 0;
21544887Schin Sfio_t* sp_misc = 0;
21554887Schin
21564887Schin if (!(mp = opt_info.state->mp) && !(mp = opt_info.state->mp = sfstropen()))
21574887Schin goto nospace;
21584887Schin if (!what)
21594887Schin style = opt_info.state->style;
21604887Schin else if (!*what)
21614887Schin style = STYLE_options;
21624887Schin else if (*what != '?')
21634887Schin style = STYLE_match;
21644887Schin else if (!*(what + 1))
21654887Schin style = STYLE_man;
21664887Schin else if ((hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), (char*)what + 1)) && hp->style >= 0)
21674887Schin {
21684887Schin style = hp->style;
21694887Schin if (*hp->name != '?')
21704887Schin what = hp->name;
21714887Schin }
21724887Schin else
21734887Schin {
21744887Schin if ((style = opt_info.state->force) < STYLE_man)
21754887Schin style = STYLE_man;
21764887Schin if (!(sp_help = sfstropen()))
21774887Schin goto nospace;
21784887Schin for (i = 0; i < elementsof(help_head); i++)
21794887Schin list(sp_help, &help_head[i]);
21804887Schin for (i = 0; i < elementsof(styles); i++)
21814887Schin sfprintf(sp_help, "[:%s?%s]", styles[i].match, styles[i].text);
21824887Schin for (i = 0; i < elementsof(help_tail); i++)
21834887Schin list(sp_help, &help_tail[i]);
21844887Schin if (!(opts = sfstruse(sp_help)))
21854887Schin goto nospace;
21864887Schin }
21874887Schin again:
21884887Schin if (opts)
21894887Schin {
21904887Schin for (i = 0; i < opt_info.state->npass; i++)
21914887Schin if (opt_info.state->pass[i].oopts == opts)
21924887Schin {
21934887Schin o = &opt_info.state->pass[i];
21944887Schin break;
21954887Schin }
21964887Schin if (i >= opt_info.state->npass)
21974887Schin {
21984887Schin o = &one;
21994887Schin if (init((char*)opts, o))
22004887Schin goto nospace;
22014887Schin }
22024887Schin e = o + 1;
22034887Schin }
22044887Schin else if (opt_info.state->npass > 0)
22054887Schin {
22064887Schin o = opt_info.state->pass;
22074887Schin e = o + opt_info.state->npass;
22084887Schin }
22094887Schin else if (opt_info.state->npass < 0)
22104887Schin {
22114887Schin o = &opt_info.state->cache->pass;
22124887Schin e = o + 1;
22134887Schin }
22144887Schin else
22154887Schin return T(NiL, ID, "[* call optget() before opthelp() *]");
221610898Sroland.mainz@nrubsig.org if (style <= STYLE_usage)
22174887Schin {
22184887Schin if (!(sp_text = sfstropen()) || !(sp_info = sfstropen()))
22194887Schin goto nospace;
22204887Schin if (style >= STYLE_match && style < STYLE_keys && !(sp_body = sfstropen()))
22214887Schin goto nospace;
22224887Schin }
22234887Schin switch (style)
22244887Schin {
22254887Schin case STYLE_api:
22264887Schin case STYLE_html:
22274887Schin case STYLE_nroff:
22284887Schin opt_info.state->emphasis = 0;
22294887Schin break;
22304887Schin case STYLE_usage:
22314887Schin case STYLE_keys:
22324887Schin for (q = o; q < e; q++)
22334887Schin if (!(q->flags & OPT_ignore) && !streq(q->catalog, o->catalog))
22344887Schin o = q;
22354887Schin /*FALLTHROUGH*/
22364887Schin case STYLE_posix:
22374887Schin sfputc(mp, '\f');
22384887Schin break;
22394887Schin default:
22404887Schin if (!opt_info.state->emphasis)
22414887Schin {
22424887Schin if (x = getenv("ERROR_OPTIONS"))
22434887Schin {
22444887Schin if (strmatch(x, "*noemphasi*"))
22454887Schin break;
22464887Schin if (strmatch(x, "*emphasi*"))
22474887Schin {
22484887Schin opt_info.state->emphasis = 1;
22494887Schin break;
22504887Schin }
22514887Schin }
22524887Schin if ((x = getenv("TERM")) && strmatch(x, "(ansi|vt100|xterm)*") && isatty(sffileno(sfstderr)))
22534887Schin opt_info.state->emphasis = 1;
22544887Schin }
22554887Schin break;
22564887Schin }
22574887Schin x = "";
22584887Schin xl = 0;
22594887Schin for (q = o; q < e; q++)
22604887Schin {
22614887Schin if (q->flags & OPT_ignore)
22624887Schin continue;
22634887Schin if (section < q->section)
22644887Schin section = q->section;
22654887Schin section = q->section;
22664887Schin flags |= q->flags;
22674887Schin p = q->opts;
22684887Schin prefix = q->prefix;
22694887Schin version = q->version;
2270*12068SRoger.Faulkner@Oracle.COM id = q->id;
22714887Schin catalog = q->catalog;
22724887Schin switch (style)
22734887Schin {
22744887Schin case STYLE_usage:
22754887Schin if (xl)
22764887Schin sfputc(mp, '\n');
22774887Schin else
22784887Schin xl = 1;
227910898Sroland.mainz@nrubsig.org psp = 0;
228010898Sroland.mainz@nrubsig.org for (;;)
22814887Schin {
228210898Sroland.mainz@nrubsig.org switch (c = *p++)
22834887Schin {
228410898Sroland.mainz@nrubsig.org case 0:
228510898Sroland.mainz@nrubsig.org if (!(tsp = psp))
228610898Sroland.mainz@nrubsig.org goto style_usage;
228710898Sroland.mainz@nrubsig.org p = psp->ob;
228810898Sroland.mainz@nrubsig.org psp = psp->next;
228910898Sroland.mainz@nrubsig.org free(tsp);
229010898Sroland.mainz@nrubsig.org continue;
22914887Schin case '\a':
22924887Schin c = 'a';
22934887Schin break;
22944887Schin case '\b':
22954887Schin c = 'b';
22964887Schin break;
22974887Schin case '\f':
2298*12068SRoger.Faulkner@Oracle.COM psp = info(psp, p, NiL, sp_info, id);
229910898Sroland.mainz@nrubsig.org if (psp->nb)
230010898Sroland.mainz@nrubsig.org p = psp->nb;
230110898Sroland.mainz@nrubsig.org else
230210898Sroland.mainz@nrubsig.org {
230310898Sroland.mainz@nrubsig.org p = psp->ob;
230410898Sroland.mainz@nrubsig.org psp = psp->next;
230510898Sroland.mainz@nrubsig.org }
230610898Sroland.mainz@nrubsig.org continue;
23074887Schin case '\n':
23084887Schin c = 'n';
23094887Schin break;
23104887Schin case '\r':
23114887Schin c = 'r';
23124887Schin break;
23134887Schin case '\t':
23144887Schin c = 't';
23154887Schin break;
23164887Schin case '\v':
23174887Schin c = 'v';
23184887Schin break;
23194887Schin case '"':
23204887Schin c = '"';
23214887Schin break;
23224887Schin case '\'':
23234887Schin c = '\'';
23244887Schin break;
23254887Schin case '\\':
23264887Schin c = '\\';
23274887Schin break;
23284887Schin default:
23294887Schin sfputc(mp, c);
23304887Schin continue;
23314887Schin }
23324887Schin sfputc(mp, '\\');
23334887Schin sfputc(mp, c);
23344887Schin }
233510898Sroland.mainz@nrubsig.org style_usage:
23364887Schin continue;
23374887Schin case STYLE_keys:
23384887Schin a = 0;
23394887Schin psp = 0;
23404887Schin vl = 0;
23414887Schin for (;;)
23424887Schin {
23434887Schin if (!(c = *p++))
23444887Schin {
23454887Schin if (!(tsp = psp))
23464887Schin break;
23474887Schin p = psp->ob;
23484887Schin psp = psp->next;
23494887Schin free(tsp);
23504887Schin continue;
23514887Schin }
23524887Schin if (c == '\f')
23534887Schin {
2354*12068SRoger.Faulkner@Oracle.COM psp = info(psp, p, NiL, sp_info, id);
23554887Schin if (psp->nb)
23564887Schin p = psp->nb;
23574887Schin else
23584887Schin {
23594887Schin p = psp->ob;
23604887Schin psp = psp->next;
23614887Schin }
23624887Schin continue;
23634887Schin }
23644887Schin f = z = 1;
23654887Schin t = 0;
23664887Schin if (a == 0 && (c == ' ' || c == '\n' && *p == '\n'))
23674887Schin {
23684887Schin if (c == ' ' && *p == ']')
23694887Schin {
23704887Schin p++;
23714887Schin continue;
23724887Schin }
23734887Schin if (*p == '\n')
23744887Schin p++;
23754887Schin a = c;
23764887Schin }
23774887Schin else if (c == '\n')
23784887Schin {
23794887Schin if (a == ' ')
23804887Schin a = -1;
23814887Schin else if (a == '\n' || *p == '\n')
23824887Schin {
23834887Schin a = -1;
23844887Schin p++;
23854887Schin }
23864887Schin continue;
23874887Schin }
23884887Schin else if ((c == ':' || c == '#') && (*p == '[' || *p == '?' && *(p + 1) == '[' && p++))
23894887Schin p++;
23904887Schin else if (c != '[')
23914887Schin {
23928462SApril.Chin@Sun.COM if (c == GO)
23934887Schin vl++;
23948462SApril.Chin@Sun.COM else if (c == OG)
23954887Schin vl--;
23964887Schin continue;
23974887Schin }
23984887Schin else if (*p == ' ')
23994887Schin {
24004887Schin p++;
24014887Schin continue;
24024887Schin }
24034887Schin else if (*p == '-')
24044887Schin {
24054887Schin z = 0;
24064887Schin if (*++p == '-')
24074887Schin {
24084887Schin p = skip(p, 0, 0, 0, 1, 0, 1, version);
24094887Schin continue;
24104887Schin }
24114887Schin }
24124887Schin else if (*p == '+')
24134887Schin {
24144887Schin p++;
24154887Schin if (vl > 0 && *p != '\a')
24164887Schin {
24174887Schin f = 0;
24184887Schin p = skip(p, '?', 0, 0, 1, 0, 0, version);
24194887Schin if (*p == '?')
24204887Schin p++;
24214887Schin }
24224887Schin }
24234887Schin else
24244887Schin {
24254887Schin if (*(p + 1) == '\f' && (vp = opt_info.state->vp))
2426*12068SRoger.Faulkner@Oracle.COM p = expand(p + 2, NiL, &t, vp, id);
24274887Schin p = skip(p, ':', '?', 0, 1, 0, 0, version);
24284887Schin if (*p == ':')
24294887Schin p++;
24304887Schin }
24314887Schin if (f && *p == '?' && *(p + 1) != '?')
24324887Schin {
24334887Schin f = 0;
24344887Schin if (z)
24354887Schin p++;
24364887Schin else
24374887Schin p = skip(p, 0, 0, 0, 1, 0, 0, version);
24384887Schin }
24394887Schin if (*p == ']' && *(p + 1) != ']')
24404887Schin {
24414887Schin p++;
24424887Schin continue;
24434887Schin }
24444887Schin if (!*p)
24454887Schin {
24464887Schin if (!t)
24474887Schin break;
24484887Schin p = t;
24494887Schin t = 0;
24504887Schin }
24514887Schin m = sfstrtell(mp);
24524887Schin sfputc(mp, '"');
24534887Schin xl = 1;
24544887Schin /*UNDENT...*/
24554887Schin
24564887Schin for (;;)
24574887Schin {
24584887Schin if (!(c = *p++))
24594887Schin {
24604887Schin if (t)
24614887Schin {
24624887Schin p = t;
24634887Schin t = 0;
24644887Schin }
24654887Schin if (!(tsp = psp))
24664887Schin {
24674887Schin p--;
24684887Schin break;
24694887Schin }
24704887Schin p = psp->ob;
24714887Schin psp = psp->next;
24724887Schin free(tsp);
24734887Schin continue;
24744887Schin }
24754887Schin if (a > 0)
24764887Schin {
24774887Schin if (c == '\n')
24784887Schin {
24794887Schin if (a == ' ')
24804887Schin {
24814887Schin a = -1;
24824887Schin break;
24834887Schin }
24844887Schin if (a == '\n' || *p == '\n')
24854887Schin {
24864887Schin a = -1;
24874887Schin p++;
24884887Schin break;
24894887Schin }
24904887Schin }
24914887Schin }
24924887Schin else if (c == ']')
24934887Schin {
24944887Schin if (*p != ']')
24954887Schin {
24964887Schin sfputc(mp, 0);
24974887Schin y = sfstrbase(mp) + m + 1;
24984887Schin if (D(y) || !strmatch(y, KEEP) || strmatch(y, OMIT))
24994887Schin {
25004887Schin sfstrseek(mp, m, SEEK_SET);
25014887Schin xl = 0;
25024887Schin }
25034887Schin else
25044887Schin sfstrseek(mp, -1, SEEK_CUR);
25054887Schin break;
25064887Schin }
25074887Schin sfputc(mp, *p++);
25084887Schin continue;
25094887Schin }
25104887Schin switch (c)
25114887Schin {
25124887Schin case '?':
25134887Schin if (f)
25144887Schin {
25154887Schin if (*p == '?')
25164887Schin {
25174887Schin p++;
25184887Schin sfputc(mp, c);
25194887Schin }
25204887Schin else
25214887Schin {
25224887Schin f = 0;
25234887Schin sfputc(mp, 0);
25244887Schin y = sfstrbase(mp) + m + 1;
25254887Schin if (D(y) || !strmatch(y, KEEP) || strmatch(y, OMIT))
25264887Schin {
25274887Schin sfstrseek(mp, m, SEEK_SET);
25284887Schin xl = 0;
25294887Schin }
25304887Schin else
25314887Schin sfstrseek(mp, -1, SEEK_CUR);
25324887Schin if (z && (*p != ']' || *(p + 1) == ']'))
25334887Schin {
25344887Schin if (xl)
25354887Schin {
25364887Schin sfputc(mp, '"');
25374887Schin sfputc(mp, '\n');
25384887Schin }
25394887Schin m = sfstrtell(mp);
25404887Schin sfputc(mp, '"');
25414887Schin xl = 1;
25424887Schin }
25434887Schin else
25444887Schin {
25454887Schin p = skip(p, 0, 0, 0, 1, 0, 0, version);
25464887Schin if (*p == '?')
25474887Schin p++;
25484887Schin }
25494887Schin }
25504887Schin }
25514887Schin else
25524887Schin sfputc(mp, c);
25534887Schin continue;
25544887Schin case ':':
25554887Schin if (f && *p == ':')
25564887Schin p++;
25574887Schin sfputc(mp, c);
25584887Schin continue;
25594887Schin case '\a':
25604887Schin c = 'a';
25614887Schin break;
25624887Schin case '\b':
25634887Schin c = 'b';
25644887Schin break;
25654887Schin case '\f':
25664887Schin c = 'f';
25674887Schin break;
25684887Schin case '\n':
25694887Schin c = 'n';
25704887Schin break;
25714887Schin case '\r':
25724887Schin c = 'r';
25734887Schin break;
25744887Schin case '\t':
25754887Schin c = 't';
25764887Schin break;
25774887Schin case '\v':
25784887Schin c = 'v';
25794887Schin break;
25804887Schin case '"':
25814887Schin c = '"';
25824887Schin break;
25834887Schin case '\\':
25844887Schin c = '\\';
25854887Schin break;
25864887Schin case CC_esc:
25874887Schin c = 'E';
25884887Schin break;
25894887Schin default:
25904887Schin sfputc(mp, c);
25914887Schin continue;
25924887Schin }
25934887Schin sfputc(mp, '\\');
25944887Schin sfputc(mp, c);
25954887Schin }
25964887Schin
25974887Schin /*...INDENT*/
25984887Schin if (xl)
25994887Schin {
26004887Schin sfputc(mp, '"');
26014887Schin sfputc(mp, '\n');
26024887Schin }
26034887Schin }
26044887Schin continue;
26054887Schin }
26064887Schin z = 0;
26074887Schin head = 0;
26084887Schin mode = 0;
26094887Schin mutex = 0;
26104887Schin if (style > STYLE_short && style < STYLE_nroff && version < 1)
26114887Schin {
26124887Schin style = STYLE_short;
26134887Schin if (sp_body)
26144887Schin {
26154887Schin sfclose(sp_body);
26164887Schin sp_body = 0;
26174887Schin }
26184887Schin }
26194887Schin else if (style == STYLE_short && prefix < 2)
26204887Schin style = STYLE_long;
26214887Schin if (*p == ':')
26224887Schin p++;
26234887Schin if (*p == '+')
26244887Schin {
26254887Schin p++;
26264887Schin if (!(sp = sp_plus) && !(sp = sp_plus = sfstropen()))
26274887Schin goto nospace;
26284887Schin }
26294887Schin else if (style >= STYLE_match)
26304887Schin sp = sp_body;
26314887Schin else
26324887Schin sp = sp_text;
26334887Schin psp = 0;
26344887Schin for (;;)
26354887Schin {
26364887Schin if (!(*(p = next(p, version))))
26374887Schin {
26384887Schin if (!(tsp = psp))
26394887Schin break;
26404887Schin p = psp->ob;
26414887Schin psp = psp->next;
26424887Schin free(tsp);
26434887Schin continue;
26444887Schin }
26454887Schin if (*p == '\f')
26464887Schin {
2647*12068SRoger.Faulkner@Oracle.COM psp = info(psp, p + 1, NiL, sp_info, id);
26484887Schin if (psp->nb)
26494887Schin p = psp->nb;
26504887Schin else
26514887Schin {
26524887Schin p = psp->ob;
26534887Schin psp = psp->next;
26544887Schin }
26554887Schin continue;
26564887Schin }
26574887Schin if (*p == '\n' || *p == ' ')
26584887Schin {
26594887Schin if (*(x = p = next(p + 1, version)))
26604887Schin while (*++p)
26614887Schin if (*p == '\n')
26624887Schin {
26634887Schin while (*++p == ' ' || *p == '\t' || *p == '\r');
26644887Schin if (*p == '\n')
26654887Schin break;
26664887Schin }
26674887Schin xl = p - x;
26684887Schin if (!*p)
26694887Schin break;
26704887Schin continue;
26714887Schin }
26728462SApril.Chin@Sun.COM if (*p == OG)
26734887Schin {
26744887Schin p++;
26754887Schin continue;
26764887Schin }
26774887Schin message((-20, "opthelp: opt %s", show(p)));
26784887Schin if (z < 0)
26794887Schin z = 0;
26804887Schin a = 0;
26814887Schin f = 0;
26824887Schin w = 0;
26834887Schin d = 0;
26844887Schin s = 0;
26858462SApril.Chin@Sun.COM rb = re = 0;
26864887Schin sl = 0;
26878462SApril.Chin@Sun.COM vl = 0;
26884887Schin if (*p == '[')
26894887Schin {
26904887Schin if ((c = *(p = next(p + 1, version))) == '-')
26914887Schin {
26924887Schin if (style >= STYLE_man)
26934887Schin {
26944887Schin if (*(p + 1) != '-')
26954887Schin {
26964887Schin if (!sp_misc && !(sp_misc = sfstropen()))
26974887Schin goto nospace;
26984887Schin else
2699*12068SRoger.Faulkner@Oracle.COM p = textout(sp_misc, p, style, 1, 3, sp_info, version, id, catalog);
27004887Schin continue;
27014887Schin }
27024887Schin }
27034887Schin else if (style == STYLE_match && *what == '-')
27044887Schin {
27058462SApril.Chin@Sun.COM if (*(p + 1) == '?' || isdigit(*(p + 1)))
27064887Schin s = C("version");
27074887Schin else
27084887Schin s = p + 1;
27094887Schin w = (char*)what;
27104887Schin if (*s != '-' || *(w + 1) == '-')
27114887Schin {
27124887Schin if (*s == '-')
27134887Schin s++;
27144887Schin if (*(w + 1) == '-')
27154887Schin w++;
2716*12068SRoger.Faulkner@Oracle.COM if (match(w + 1, s, version, id, catalog))
27174887Schin {
27184887Schin if (*(p + 1) == '-')
27194887Schin p++;
2720*12068SRoger.Faulkner@Oracle.COM p = textout(sp, p, style, 1, 3, sp_info, version, id, catalog);
27214887Schin matched = -1;
27224887Schin continue;
27234887Schin }
27244887Schin }
27254887Schin }
27264887Schin if (!z)
27274887Schin z = -1;
27284887Schin }
27294887Schin else if (c == '+')
27304887Schin {
27314887Schin if (style >= STYLE_man)
27324887Schin {
2733*12068SRoger.Faulkner@Oracle.COM p = textout(sp_body, p, style, 0, 0, sp_info, version, id, catalog);
27344887Schin if (!sp_head)
27354887Schin {
27364887Schin sp_head = sp_body;
27374887Schin if (!(sp_body = sfstropen()))
27384887Schin goto nospace;
27394887Schin }
27404887Schin continue;
27414887Schin }
27424887Schin else if (style == STYLE_match && *what == '+')
27434887Schin {
27444887Schin if (paragraph)
27454887Schin {
27464887Schin if (p[1] == '?')
27474887Schin {
2748*12068SRoger.Faulkner@Oracle.COM p = textout(sp, p, style, 1, 3, sp_info, version, id, catalog);
27494887Schin continue;
27504887Schin }
27514887Schin paragraph = 0;
27524887Schin }
2753*12068SRoger.Faulkner@Oracle.COM if (match((char*)what + 1, p + 1, version, id, catalog))
27544887Schin {
2755*12068SRoger.Faulkner@Oracle.COM p = textout(sp, p, style, 1, 3, sp_info, version, id, catalog);
27564887Schin matched = -1;
27574887Schin paragraph = 1;
27584887Schin continue;
27594887Schin }
27604887Schin }
27614887Schin if (!z)
27624887Schin z = -1;
27634887Schin }
27644887Schin else if (c == '[' || version < 1)
27654887Schin {
27664887Schin mutex++;
27674887Schin continue;
27684887Schin }
27694887Schin else
27704887Schin {
27714887Schin if (c == '!')
27724887Schin {
27734887Schin a |= OPT_invert;
27744887Schin p++;
27754887Schin }
27764887Schin rb = p;
27774887Schin if (*p != ':')
27784887Schin {
27794887Schin s = p;
27804887Schin if (*(p + 1) == '|')
27814887Schin {
27824887Schin while (*++p && *p != '=' && *p != '!' && *p != ':' && *p != '?');
27834887Schin if ((p - s) > 1)
27844887Schin sl = p - s;
27854887Schin if (*p == '!')
27864887Schin a |= OPT_invert;
27874887Schin }
27884887Schin if (*(p + 1) == '\f')
27894887Schin p++;
27904887Schin else
27914887Schin p = skip(p, ':', '?', 0, 1, 0, 0, version);
27924887Schin if (sl || (p - s) == 1 || *(s + 1) == '=' || *(s + 1) == '!' && (a |= OPT_invert) || *(s + 1) == '|')
27934887Schin f = *s;
27944887Schin }
27954887Schin re = p;
27964887Schin if (style <= STYLE_short)
27974887Schin {
27984887Schin if (!z && !f)
27994887Schin z = -1;
28004887Schin }
28014887Schin else
28024887Schin {
28034887Schin if (*p == '\f' && (vp = opt_info.state->vp))
2804*12068SRoger.Faulkner@Oracle.COM p = expand(p + 1, NiL, &t, vp, id);
28054887Schin else
28064887Schin t = 0;
28074887Schin if (*p == ':')
28084887Schin {
28094887Schin p = skip(w = p + 1, ':', '?', 0, 1, 0, 0, version);
28104887Schin if (!(wl = p - w))
28114887Schin w = 0;
28124887Schin }
28134887Schin else
28144887Schin wl = 0;
28154887Schin if (*p == ':' || *p == '?')
28164887Schin {
28174887Schin d = p;
28184887Schin p = skip(p, 0, 0, 0, 1, 0, 0, version);
28194887Schin }
28204887Schin else
28214887Schin d = 0;
28224887Schin if (style == STYLE_match)
28234887Schin {
2824*12068SRoger.Faulkner@Oracle.COM if (wl && !match((char*)what, w, version, id, catalog))
28254887Schin wl = 0;
28264887Schin if ((!wl || *w == ':' || *w == '?') && (what[1] || sl && !memchr(s, what[0], sl) || !sl && what[0] != f))
28274887Schin {
28284887Schin w = 0;
28294887Schin if (!z)
28304887Schin z = -1;
28314887Schin }
28324887Schin else
28334887Schin matched = 1;
28344887Schin }
28354887Schin if (t)
28364887Schin {
28374887Schin p = t;
28384887Schin if (*p == ':' || *p == '?')
28394887Schin {
28404887Schin d = p;
28414887Schin p = skip(p, 0, 0, 0, 1, 0, 0, version);
28424887Schin }
28434887Schin }
28444887Schin }
28454887Schin }
28464887Schin p = skip(p, 0, 0, 0, 1, 0, 1, version);
28474887Schin if (*p == GO)
28484887Schin p = skip(p + 1, 0, 0, 0, 0, 1, 1, version);
28494887Schin }
28504887Schin else if (*p == ']')
28514887Schin {
28524887Schin if (mutex)
28534887Schin {
28544887Schin if (style >= STYLE_nroff)
28554887Schin sfputr(sp_body, "\n.OP - - anyof", '\n');
28564887Schin if (!(mutex & 1))
28574887Schin {
28584887Schin mutex--;
28594887Schin if (style <= STYLE_long)
28604887Schin {
28614887Schin sfputc(sp_body, ' ');
28624887Schin sfputc(sp_body, ']');
28634887Schin }
28644887Schin }
28654887Schin mutex--;
28664887Schin }
28674887Schin p++;
28684887Schin continue;
28694887Schin }
28704887Schin else if (*p == '?')
28714887Schin {
28724887Schin if (style < STYLE_match)
28734887Schin z = 1;
28744887Schin mode |= OPT_hidden;
28754887Schin p++;
28764887Schin continue;
28774887Schin }
28784887Schin else if (*p == '\\' && style==STYLE_posix)
28794887Schin {
28804887Schin if (*++p)
28814887Schin p++;
28824887Schin continue;
28834887Schin }
28844887Schin else
28854887Schin {
28864887Schin f = *p++;
28874887Schin s = 0;
28884887Schin if (style == STYLE_match && !z)
28894887Schin z = -1;
28904887Schin }
28914887Schin if (!z)
28924887Schin {
28934887Schin if (style == STYLE_long || prefix < 2 || (q->flags & OPT_long))
28944887Schin f = 0;
28954887Schin else if (style <= STYLE_short)
28964887Schin w = 0;
28974887Schin if (!f && !w)
28984887Schin z = -1;
28994887Schin }
29008462SApril.Chin@Sun.COM ov = 0;
29018462SApril.Chin@Sun.COM u = v = y = 0;
29024887Schin if (*p == ':' && (a |= OPT_string) || *p == '#' && (a |= OPT_number))
29034887Schin {
29044887Schin message((-21, "opthelp: arg %s", show(p)));
29054887Schin if (*++p == '?' || *p == *(p - 1))
29064887Schin {
29074887Schin p++;
29084887Schin a |= OPT_optional;
29094887Schin }
29104887Schin if (*(p = next(p, version)) == '[')
29114887Schin {
29124887Schin if (!z)
29134887Schin {
29144887Schin p = skip(y = p + 1, ':', '?', 0, 1, 0, 0, version);
29154887Schin while (*p == ':')
29164887Schin {
29174887Schin p = skip(t = p + 1, ':', '?', 0, 1, 0, 0, version);
29184887Schin m = p - t;
29194887Schin if (*t == '!')
29204887Schin {
29214887Schin ov = t + 1;
29224887Schin ol = m - 1;
29234887Schin }
29244887Schin else if (*t == '=')
29254887Schin {
29264887Schin v = t + 1;
29274887Schin vl = m - 1;
29284887Schin }
29294887Schin else
29304887Schin for (j = 0; j < elementsof(attrs); j++)
29314887Schin if (strneq(t, attrs[j].name, m))
29324887Schin {
29334887Schin a |= attrs[j].flag;
29344887Schin break;
29354887Schin }
29364887Schin }
29374887Schin if (*p == '?')
29384887Schin u = p;
29394887Schin p = skip(p, 0, 0, 0, 1, 0, 1, version);
29404887Schin }
29414887Schin else
29424887Schin p = skip(p + 1, 0, 0, 0, 1, 0, 1, version);
29434887Schin }
29444887Schin else
29454887Schin y = (a & OPT_number) ? T(NiL, ID, "#") : T(NiL, ID, "arg");
29464887Schin }
29474887Schin else
29484887Schin a |= OPT_flag;
29494887Schin if (!z)
29504887Schin {
29514887Schin if (style <= STYLE_short && !y && !mutex || style == STYLE_posix)
29524887Schin {
29534887Schin if (style != STYLE_posix && !sfstrtell(sp))
29544887Schin {
29554887Schin sfputc(sp, '[');
29564887Schin if (sp == sp_plus)
29574887Schin sfputc(sp, '+');
29584887Schin sfputc(sp, '-');
29594887Schin }
29604887Schin if (!sl)
29614887Schin sfputc(sp, f);
29624887Schin else
29634887Schin for (c = 0; c < sl; c++)
29644887Schin if (s[c] != '|')
29654887Schin sfputc(sp, s[c]);
29664887Schin if (style == STYLE_posix && y)
29674887Schin sfputc(sp, ':');
29684887Schin }
29694887Schin else
29704887Schin {
29714887Schin if (style >= STYLE_match)
29724887Schin {
29734887Schin sfputc(sp_body, '\n');
29744887Schin if (!head)
29754887Schin {
29764887Schin head = 1;
2977*12068SRoger.Faulkner@Oracle.COM item(sp_body, (flags & OPT_functions) ? C("FUNCTIONS") : C("OPTIONS"), 0, 0, style, sp_info, version, id, ID);
29784887Schin }
29794887Schin if (style >= STYLE_nroff)
29804887Schin {
29814887Schin if (mutex & 1)
29824887Schin {
29834887Schin mutex++;
29844887Schin sfputr(sp_body, "\n.OP - - oneof", '\n');
29854887Schin }
29864887Schin }
29874887Schin else
29884887Schin sfputc(sp_body, '\t');
29894887Schin }
29904887Schin else
29914887Schin {
29924887Schin if (sp_body)
29934887Schin sfputc(sp_body, ' ');
29944887Schin else if (!(sp_body = sfstropen()))
29954887Schin goto nospace;
29964887Schin if (mutex)
29974887Schin {
29984887Schin if (mutex & 1)
29994887Schin {
30004887Schin mutex++;
30014887Schin sfputc(sp_body, '[');
30024887Schin }
30034887Schin else
30044887Schin sfputc(sp_body, '|');
30054887Schin sfputc(sp_body, ' ');
30064887Schin }
30074887Schin else
30084887Schin sfputc(sp_body, '[');
30094887Schin }
30104887Schin if (style >= STYLE_nroff)
30114887Schin {
30124887Schin if (flags & OPT_functions)
30134887Schin {
30144887Schin sfputr(sp_body, ".FN", ' ');
30154887Schin if (re > rb)
30164887Schin sfwrite(sp_body, rb, re - rb);
30174887Schin else
30184887Schin sfputr(sp, "void", -1);
30194887Schin if (w)
3020*12068SRoger.Faulkner@Oracle.COM label(sp_body, ' ', w, 0, -1, 0, style, FONT_BOLD, sp_info, version, id, catalog);
30214887Schin }
30224887Schin else
30234887Schin {
30244887Schin sfputr(sp_body, ".OP", ' ');
30254887Schin if (sl)
30264887Schin sfwrite(sp_body, s, sl);
30274887Schin else
30284887Schin sfputc(sp_body, f ? f : '-');
30294887Schin sfputc(sp_body, ' ');
30304887Schin if (w)
30314887Schin {
3032*12068SRoger.Faulkner@Oracle.COM if (label(sp_body, 0, w, 0, -1, 0, style, 0, sp_info, version, id, catalog))
30334887Schin {
30344887Schin sfputc(sp_body, '|');
3035*12068SRoger.Faulkner@Oracle.COM label(sp_body, 0, w, 0, -1, 0, style, 0, sp_info, version, id, native);
30364887Schin }
30374887Schin }
30384887Schin else
30394887Schin sfputc(sp_body, '-');
30404887Schin sfputc(sp_body, ' ');
30414887Schin m = a & OPT_TYPE;
30424887Schin for (j = 0; j < elementsof(attrs); j++)
30434887Schin if (m & attrs[j].flag)
30444887Schin {
30454887Schin sfputr(sp_body, attrs[j].name, -1);
30464887Schin break;
30474887Schin }
30484887Schin if (m = (a & ~m) | mode)
30494887Schin for (j = 0; j < elementsof(attrs); j++)
30504887Schin if (m & attrs[j].flag)
30514887Schin {
30524887Schin sfputc(sp_body, ':');
30534887Schin sfputr(sp_body, attrs[j].name, -1);
30544887Schin }
30554887Schin sfputc(sp_body, ' ');
30564887Schin if (y)
3057*12068SRoger.Faulkner@Oracle.COM label(sp_body, 0, y, 0, -1, 0, style, 0, sp_info, version, id, catalog);
30584887Schin else
30594887Schin sfputc(sp_body, '-');
30604887Schin if (v)
30614887Schin sfprintf(sp_body, " %-.*s", vl, v);
30624887Schin }
30634887Schin }
30644887Schin else
30654887Schin {
30664887Schin if (f)
30674887Schin {
30684887Schin if (sp_body == sp_plus)
30694887Schin sfputc(sp_body, '+');
30704887Schin sfputc(sp_body, '-');
30714887Schin sfputr(sp_body, font(FONT_BOLD, style, 1), -1);
30724887Schin if (!sl)
30734887Schin {
30744887Schin sfputc(sp_body, f);
30754887Schin if (f == '-' && y)
30764887Schin {
30774887Schin y = 0;
30784887Schin sfputr(sp_body, C("long-option[=value]"), -1);
30794887Schin }
30804887Schin }
30814887Schin else
30824887Schin sfwrite(sp_body, s, sl);
30834887Schin sfputr(sp_body, font(FONT_BOLD, style, 0), -1);
30844887Schin if (w)
30854887Schin {
30864887Schin sfputc(sp_body, ',');
30874887Schin sfputc(sp_body, ' ');
30884887Schin }
30894887Schin }
30904887Schin else if ((flags & OPT_functions) && re > rb)
30914887Schin {
30924887Schin sfwrite(sp_body, rb, re - rb);
30934887Schin sfputc(sp_body, ' ');
30944887Schin }
30954887Schin if (w)
30964887Schin {
30974887Schin if (prefix > 0)
30984887Schin {
30994887Schin sfputc(sp_body, '-');
31004887Schin if (prefix > 1)
31014887Schin sfputc(sp_body, '-');
31024887Schin }
3103*12068SRoger.Faulkner@Oracle.COM if (label(sp_body, 0, w, 0, -1, 0, style, FONT_BOLD, sp_info, version, id, catalog))
31044887Schin {
31054887Schin sfputc(sp_body, '|');
3106*12068SRoger.Faulkner@Oracle.COM label(sp_body, 0, w, 0, -1, 0, style, FONT_BOLD, sp_info, version, id, native);
31074887Schin }
31084887Schin }
31094887Schin if (y)
31104887Schin {
31114887Schin if (a & OPT_optional)
31124887Schin sfputc(sp_body, '[');
31134887Schin else if (!w)
31144887Schin sfputc(sp_body, ' ');
31154887Schin if (w)
31164887Schin sfputc(sp_body, prefix == 1 ? ' ' : '=');
3117*12068SRoger.Faulkner@Oracle.COM label(sp_body, 0, y, 0, -1, 0, style, FONT_ITALIC, sp_info, version, id, catalog);
31184887Schin if (a & OPT_optional)
31194887Schin sfputc(sp_body, ']');
31204887Schin }
31214887Schin }
31224887Schin if (style >= STYLE_match)
31234887Schin {
31244887Schin if (d)
3125*12068SRoger.Faulkner@Oracle.COM textout(sp_body, d, style, 0, 3, sp_info, version, id, catalog);
31264887Schin if (u)
3127*12068SRoger.Faulkner@Oracle.COM textout(sp_body, u, style, 0, 3, sp_info, version, id, catalog);
31284887Schin if ((a & OPT_invert) && w && (d || u))
31294887Schin {
31304887Schin u = skip(w, ':', '?', 0, 1, 0, 0, version);
31314887Schin if (f)
31324887Schin 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);
31334887Schin else
31344887Schin 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"));
31354887Schin if (!(t = sfstruse(sp_info)))
31364887Schin goto nospace;
3137*12068SRoger.Faulkner@Oracle.COM textout(sp_body, t, style, 0, 0, sp_info, version, NiL, NiL);
31384887Schin }
31394887Schin if (*p == GO)
31404887Schin {
3141*12068SRoger.Faulkner@Oracle.COM p = u ? skip(p + 1, 0, 0, 0, 0, 1, 1, version) : textout(sp_body, p, style, 4, 0, sp_info, version, id, catalog);
31424887Schin y = "+?";
31434887Schin }
31444887Schin else
31454887Schin y = " ";
31464887Schin if (a & OPT_optional)
31474887Schin {
31484887Schin if (ov)
31494887Schin {
31504887Schin sfprintf(sp_info, "%s%s \b", y, T(NiL, ID, "If the option value is omitted then"));
31514887Schin t = ov + ol;
31524887Schin while (ov < t)
31534887Schin {
31544887Schin if (((c = *ov++) == ':' || c == '?') && *ov == c)
31554887Schin ov++;
31564887Schin sfputc(sp_info, c);
31574887Schin }
31584887Schin sfprintf(sp_info, "\b %s.", T(NiL, ID, "is assumed"));
31594887Schin }
31604887Schin else
31614887Schin sfprintf(sp_info, "%s%s", y, T(NiL, ID, "The option value may be omitted."));
31624887Schin if (!(t = sfstruse(sp_info)))
31634887Schin goto nospace;
3164*12068SRoger.Faulkner@Oracle.COM textout(sp_body, t, style, 4, 0, sp_info, version, NiL, NiL);
31654887Schin y = " ";
31664887Schin }
31674887Schin if (v)
31684887Schin {
31694887Schin sfprintf(sp_info, "%s%s \b", y, T(NiL, ID, "The default value is"));
31704887Schin t = v + vl;
31714887Schin while (v < t)
31724887Schin {
31734887Schin if (((c = *v++) == ':' || c == '?') && *v == c)
31744887Schin v++;
31754887Schin sfputc(sp_info, c);
31764887Schin }
31774887Schin sfputc(sp_info, '\b');
31784887Schin sfputc(sp_info, '.');
31794887Schin if (!(t = sfstruse(sp_info)))
31804887Schin goto nospace;
3181*12068SRoger.Faulkner@Oracle.COM textout(sp_body, t, style, 4, 0, sp_info, version, NiL, NiL);
31824887Schin }
31834887Schin }
31844887Schin else if (!mutex)
31854887Schin sfputc(sp_body, ']');
31864887Schin }
31874887Schin if (*p == GO)
31884887Schin {
31894887Schin if (style >= STYLE_match)
3190*12068SRoger.Faulkner@Oracle.COM p = textout(sp_body, p, style, 4, 0, sp_info, version, id, catalog);
31914887Schin else
31924887Schin p = skip(p + 1, 0, 0, 0, 0, 1, 1, version);
31934887Schin }
31944887Schin }
31954887Schin else if (*p == GO)
31964887Schin p = skip(p + 1, 0, 0, 0, 0, 1, 1, version);
31974887Schin }
31984887Schin psp = pop(psp);
31994887Schin if (sp_misc)
32004887Schin {
32014887Schin if (!(p = sfstruse(sp_misc)))
32024887Schin goto nospace;
32034887Schin for (t = p; *t == '\t' || *t == '\n'; t++);
32044887Schin if (*t)
32054887Schin {
3206*12068SRoger.Faulkner@Oracle.COM item(sp_body, C("IMPLEMENTATION"), 0, 0, style, sp_info, version, id, ID);
32074887Schin sfputr(sp_body, p, -1);
32084887Schin }
32094887Schin }
32104887Schin }
32114887Schin version = o->version;
3212*12068SRoger.Faulkner@Oracle.COM id = o->id;
32134887Schin catalog = o->catalog;
32144887Schin if (style >= STYLE_keys)
32154887Schin {
32164887Schin if (sp_info)
32174887Schin sfclose(sp_info);
32184887Schin if (style == STYLE_keys && sfstrtell(mp) > 1)
32194887Schin sfstrseek(mp, -1, SEEK_CUR);
32204887Schin if (!(p = sfstruse(mp)))
32214887Schin goto nospace;
32224887Schin return opt_info.msg = p;
32234887Schin }
32244887Schin sp = sp_text;
32254887Schin if (sfstrtell(sp) && style != STYLE_posix)
32264887Schin sfputc(sp, ']');
32274887Schin if (style == STYLE_nroff)
32284887Schin {
3229*12068SRoger.Faulkner@Oracle.COM char ud[64];
3230*12068SRoger.Faulkner@Oracle.COM
3231*12068SRoger.Faulkner@Oracle.COM s = o->id;
3232*12068SRoger.Faulkner@Oracle.COM t = ud;
3233*12068SRoger.Faulkner@Oracle.COM while (t < &ud[sizeof(ud)-2] && (c = *s++))
3234*12068SRoger.Faulkner@Oracle.COM {
3235*12068SRoger.Faulkner@Oracle.COM if (islower(c))
3236*12068SRoger.Faulkner@Oracle.COM c = toupper(c);
3237*12068SRoger.Faulkner@Oracle.COM *t++ = c;
3238*12068SRoger.Faulkner@Oracle.COM }
3239*12068SRoger.Faulkner@Oracle.COM *t = 0;
32404887Schin sfprintf(sp, "\
32414887Schin .\\\" format with nroff|troff|groff -man\n\
32424887Schin .fp 5 CW\n\
32438462SApril.Chin@Sun.COM .nr mH 5\n\
32448462SApril.Chin@Sun.COM .de H0\n\
32458462SApril.Chin@Sun.COM .nr mH 0\n\
32468462SApril.Chin@Sun.COM .in 5n\n\
32478462SApril.Chin@Sun.COM \\fB\\\\$1\\fP\n\
32488462SApril.Chin@Sun.COM .in 7n\n\
32494887Schin ..\n\
32504887Schin .de H1\n\
32518462SApril.Chin@Sun.COM .nr mH 1\n\
32528462SApril.Chin@Sun.COM .in 7n\n\
32534887Schin \\fB\\\\$1\\fP\n\
32548462SApril.Chin@Sun.COM .in 9n\n\
32554887Schin ..\n\
32564887Schin .de H2\n\
32578462SApril.Chin@Sun.COM .nr mH 2\n\
32588462SApril.Chin@Sun.COM .in 11n\n\
32594887Schin \\fB\\\\$1\\fP\n\
32608462SApril.Chin@Sun.COM .in 13n\n\
32614887Schin ..\n\
32624887Schin .de H3\n\
32638462SApril.Chin@Sun.COM .nr mH 3\n\
32648462SApril.Chin@Sun.COM .in 15n\n\
32654887Schin \\fB\\\\$1\\fP\n\
32668462SApril.Chin@Sun.COM .in 17n\n\
32674887Schin ..\n\
32684887Schin .de H4\n\
32698462SApril.Chin@Sun.COM .nr mH 4\n\
32708462SApril.Chin@Sun.COM .in 19n\n\
32714887Schin \\fB\\\\$1\\fP\n\
32728462SApril.Chin@Sun.COM .in 21n\n\
32734887Schin ..\n\
32744887Schin .de OP\n\
32758462SApril.Chin@Sun.COM .nr mH 0\n\
32764887Schin .ie !'\\\\$1'-' \\{\n\
32774887Schin .ds mO \\\\fB\\\\-\\\\$1\\\\fP\n\
32784887Schin .ds mS ,\\\\0\n\
32794887Schin .\\}\n\
32804887Schin .el \\{\n\
32814887Schin .ds mO \\\\&\n\
32824887Schin .ds mS \\\\&\n\
32834887Schin .\\}\n\
32844887Schin .ie '\\\\$2'-' \\{\n\
32854887Schin .if !'\\\\$4'-' .as mO \\\\0\\\\fI\\\\$4\\\\fP\n\
32864887Schin .\\}\n\
32874887Schin .el \\{\n\
32884887Schin .as mO \\\\*(mS\\\\fB%s\\\\$2\\\\fP\n\
32894887Schin .if !'\\\\$4'-' .as mO =\\\\fI\\\\$4\\\\fP\n\
32904887Schin .\\}\n\
32918462SApril.Chin@Sun.COM .in 5n\n\
32924887Schin \\\\*(mO\n\
32938462SApril.Chin@Sun.COM .in 9n\n\
32948462SApril.Chin@Sun.COM ..\n\
32958462SApril.Chin@Sun.COM .de SP\n\
32968462SApril.Chin@Sun.COM .if \\\\n(mH==2 .in 9n\n\
32978462SApril.Chin@Sun.COM .if \\\\n(mH==3 .in 13n\n\
32988462SApril.Chin@Sun.COM .if \\\\n(mH==4 .in 17n\n\
32994887Schin ..\n\
33004887Schin .de FN\n\
33018462SApril.Chin@Sun.COM .nr mH 0\n\
33028462SApril.Chin@Sun.COM .in 5n\n\
33034887Schin \\\\$1 \\\\$2\n\
33048462SApril.Chin@Sun.COM .in 9n\n\
33058462SApril.Chin@Sun.COM ..\n\
33068462SApril.Chin@Sun.COM .de DS\n\
33078462SApril.Chin@Sun.COM .in +3n\n\
33088462SApril.Chin@Sun.COM .ft 5\n\
33098462SApril.Chin@Sun.COM .nf\n\
33108462SApril.Chin@Sun.COM ..\n\
33118462SApril.Chin@Sun.COM .de DE\n\
33128462SApril.Chin@Sun.COM .fi\n\
33138462SApril.Chin@Sun.COM .ft R\n\
33148462SApril.Chin@Sun.COM .in -3n\n\
33154887Schin ..\n\
33164887Schin .TH %s %d\n\
33174887Schin "
33184887Schin , o->prefix == 2 ? "\\\\-\\\\-" : o->prefix == 1 ? "\\\\-" : ""
3319*12068SRoger.Faulkner@Oracle.COM , ud
33204887Schin , section
33214887Schin );
33224887Schin }
33234887Schin if (style == STYLE_match)
33244887Schin {
33254887Schin if (!matched)
33264887Schin {
33274887Schin if (hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), (char*)what))
33284887Schin {
33294887Schin if (!sp_help && !(sp_help = sfstropen()))
33304887Schin goto nospace;
33314887Schin sfprintf(sp_help, "[-][:%s?%s]", hp->match, hp->text);
33324887Schin if (!(opts = sfstruse(sp_help)))
33334887Schin goto nospace;
33344887Schin goto again;
33354887Schin }
33364887Schin s = (char*)unknown;
33374887Schin goto nope;
33384887Schin }
33394887Schin else if (matched < 0)
33404887Schin x = 0;
33414887Schin }
33424887Schin if (sp_plus)
33434887Schin {
33444887Schin if (sfstrtell(sp_plus))
33454887Schin {
33464887Schin if (sfstrtell(sp))
33474887Schin sfputc(sp, ' ');
33484887Schin if (!(t = sfstruse(sp_plus)))
33494887Schin goto nospace;
33504887Schin sfputr(sp, t, ']');
33514887Schin }
33524887Schin sfclose(sp_plus);
33534887Schin }
33544887Schin if (style >= STYLE_man)
33554887Schin {
33564887Schin if (sp_head)
33574887Schin {
33584887Schin if (!(t = sfstruse(sp_head)))
33594887Schin goto nospace;
33604887Schin for (; *t == '\n'; t++);
33614887Schin sfputr(sp, t, '\n');
33624887Schin sfclose(sp_head);
33634887Schin sp_head = 0;
33644887Schin }
3365*12068SRoger.Faulkner@Oracle.COM item(sp, C("SYNOPSIS"), 0, 0, style, sp_info, version, id, ID);
33664887Schin }
33674887Schin if (x)
33684887Schin {
33694887Schin for (t = x + xl; t > x && (*(t - 1) == '\n' || *(t - 1) == '\r'); t--);
33704887Schin xl = t - x;
33714887Schin if (style >= STYLE_match)
33724887Schin {
3373*12068SRoger.Faulkner@Oracle.COM args(sp, x, xl, flags, style, sp_info, version, id, catalog);
33744887Schin x = 0;
33754887Schin }
33764887Schin }
33774887Schin if (sp_body)
33784887Schin {
33794887Schin if (sfstrtell(sp_body))
33804887Schin {
33814887Schin if (style < STYLE_match && sfstrtell(sp))
33824887Schin sfputc(sp, ' ');
33834887Schin if (!(t = sfstruse(sp_body)))
33844887Schin goto nospace;
33854887Schin sfputr(sp, t, -1);
33864887Schin }
33874887Schin sfclose(sp_body);
33884887Schin sp_body = 0;
33894887Schin }
33904887Schin if (x && style != STYLE_posix)
3391*12068SRoger.Faulkner@Oracle.COM args(sp, x, xl, flags, style, sp_info, version, id, catalog);
33924887Schin if (sp_info)
33934887Schin {
33944887Schin sfclose(sp_info);
33954887Schin sp_info = 0;
33964887Schin }
33974887Schin if (sp_misc)
33984887Schin {
33994887Schin sfclose(sp_misc);
34004887Schin sp_misc = 0;
34014887Schin }
34024887Schin if (!(p = sfstruse(sp)))
34034887Schin goto nospace;
3404*12068SRoger.Faulkner@Oracle.COM astwinsize(1, NiL, &opt_info.state->width);
3405*12068SRoger.Faulkner@Oracle.COM if (opt_info.state->width < 20)
3406*12068SRoger.Faulkner@Oracle.COM opt_info.state->width = OPT_WIDTH;
3407*12068SRoger.Faulkner@Oracle.COM m = strlen((style <= STYLE_long && error_info.id && !strchr(error_info.id, '/')) ? error_info.id : id) + 1;
34088462SApril.Chin@Sun.COM margin = style == STYLE_api ? (8 * 1024) : (opt_info.state->width - 1);
34094887Schin if (!(opt_info.state->flags & OPT_preformat))
34104887Schin {
34114887Schin if (style >= STYLE_man || matched < 0)
34124887Schin {
34134887Schin sfputc(mp, '\f');
34144887Schin ts = 0;
34154887Schin }
34164887Schin else
34174887Schin ts = OPT_USAGE + m;
34184887Schin if (style == STYLE_html)
34194887Schin {
3420*12068SRoger.Faulkner@Oracle.COM char ud[64];
3421*12068SRoger.Faulkner@Oracle.COM
3422*12068SRoger.Faulkner@Oracle.COM s = id;
3423*12068SRoger.Faulkner@Oracle.COM t = ud;
3424*12068SRoger.Faulkner@Oracle.COM while (t < &ud[sizeof(ud)-2] && (c = *s++))
3425*12068SRoger.Faulkner@Oracle.COM {
3426*12068SRoger.Faulkner@Oracle.COM if (islower(c))
3427*12068SRoger.Faulkner@Oracle.COM c = toupper(c);
3428*12068SRoger.Faulkner@Oracle.COM *t++ = c;
3429*12068SRoger.Faulkner@Oracle.COM }
3430*12068SRoger.Faulkner@Oracle.COM *t = 0;
3431*12068SRoger.Faulkner@Oracle.COM 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);
3432*12068SRoger.Faulkner@Oracle.COM 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);
34334887Schin sfprintf(mp, "<DL compact>\n<DT>");
34344887Schin co = 2;
34354887Schin *(pt = ptstk) = 0;
34364887Schin }
34374887Schin else
34384887Schin co = 0;
34398462SApril.Chin@Sun.COM if ((rm = margin - ts) < OPT_MARGIN)
34404887Schin rm = OPT_MARGIN;
34414887Schin ip = indent;
34424887Schin ip->stop = (ip+1)->stop = style >= STYLE_html ? 0 : 2;
34434887Schin tp = 0;
34444887Schin n = 0;
34454887Schin head = 1;
34464887Schin while (*p == '\n')
34474887Schin p++;
34484887Schin while (c = *p++)
34494887Schin {
34504887Schin if (c == '\n')
34514887Schin {
34524887Schin ip = indent;
34534887Schin n = 0;
34544887Schin tp = 0;
34554887Schin sfputc(mp, '\n');
34564887Schin co = 0;
34578462SApril.Chin@Sun.COM rm = margin;
34584887Schin ts = ip->stop;
34594887Schin if (*p == '\n')
34604887Schin {
34614887Schin while (*++p == '\n');
34624887Schin if ((style == STYLE_man || style == STYLE_html) && (!head || *p != ' ' && *p != '\t'))
34634887Schin {
34644887Schin if (style == STYLE_man)
34654887Schin p--;
34664887Schin else
34674887Schin sfprintf(mp, "<P>\n");
34684887Schin }
34694887Schin }
34704887Schin head = *p != ' ' && *p != '\t';
34714887Schin if (style == STYLE_html && (*p != '<' || !strneq(p, "<BR>", 4) && !strneq(p, "<P>", 3)))
34724887Schin {
34734887Schin y = p;
34744887Schin while (*p == '\t')
34754887Schin p++;
34764887Schin if (*p == '\n')
34774887Schin continue;
34784887Schin j = p - y;
34794887Schin if (j > *pt)
34804887Schin {
34814887Schin if (pt > ptstk)
34824887Schin sfprintf(mp, "<DL compact>\n");
34834887Schin *++pt = j;
34844887Schin sfprintf(mp, "<DL compact>\n");
34854887Schin }
34864887Schin else while (j < *pt)
34874887Schin {
34884887Schin if (--pt > ptstk)
34894887Schin sfprintf(mp, "</DL>\n");
34904887Schin sfprintf(mp, "</DL>\n");
34914887Schin }
34924887Schin co += sfprintf(mp, "<DT>");
34934887Schin }
34944887Schin }
34954887Schin else if (c == '\t')
34964887Schin {
34974887Schin if (style == STYLE_html)
34984887Schin {
34994887Schin while (*p == '\t')
35004887Schin p++;
35014887Schin if (*p != '\n')
35024887Schin co += sfprintf(mp, "<DD>");
35034887Schin }
35044887Schin else
35054887Schin {
35064887Schin if ((ip+1)->stop)
35074887Schin {
35084887Schin do
35094887Schin {
35104887Schin ip++;
35114887Schin if (*p != '\t')
35124887Schin break;
35134887Schin p++;
35144887Schin } while ((ip+1)->stop);
35154887Schin if (*p == '\n')
35164887Schin continue;
35174887Schin ts = ip->stop;
35184887Schin if (co >= ts)
35194887Schin {
35204887Schin sfputc(mp, '\n');
35214887Schin co = 0;
35228462SApril.Chin@Sun.COM rm = margin;
35234887Schin ts = ip->stop;
35244887Schin }
35254887Schin }
35264887Schin while (co < ts)
35274887Schin {
35284887Schin sfputc(mp, ' ');
35294887Schin co++;
35304887Schin }
35314887Schin }
35324887Schin }
35334887Schin else
35344887Schin {
35354887Schin if (c == ' ' && !n)
35364887Schin {
35374887Schin if (co >= rm)
35384887Schin tp = 0;
35394887Schin else
35404887Schin {
35414887Schin tp = sfstrtell(mp);
35424887Schin pp = p;
35434887Schin }
35444887Schin if (style == STYLE_nroff && !co)
35454887Schin continue;
35464887Schin }
35474887Schin else if (style == STYLE_html)
35484887Schin {
35494887Schin if (c == '<')
35504887Schin {
35514887Schin if (strneq(p, "NOBR>", 5))
35524887Schin n++;
35534887Schin else if (n && strneq(p, "/NOBR>", 6) && !--n)
35544887Schin {
35554887Schin for (y = p += 6; (c = *p) && c != ' ' && c != '\t' && c != '\n' && c != '<'; p++)
35564887Schin if (c == '[')
35574887Schin sfputr(mp, "[", -1);
35584887Schin else if (c == ']')
35594887Schin sfputr(mp, "]", -1);
35604887Schin else
35614887Schin sfputc(mp, c);
35624887Schin sfwrite(mp, "</NOBR", 6);
35634887Schin c = '>';
35644887Schin tp = 0;
35654887Schin co += p - y + 6;
35664887Schin }
35674887Schin }
35684887Schin else if (c == '>' && !n)
35694887Schin {
35704887Schin for (y = --p; (c = *p) && c != ' ' && c != '\t' && c != '\n' && c != '<'; p++)
35714887Schin if (c == '[')
35724887Schin sfputr(mp, "[", -1);
35734887Schin else if (c == ']')
35744887Schin sfputr(mp, "]", -1);
35754887Schin else
35764887Schin sfputc(mp, c);
35774887Schin c = *sfstrseek(mp, -1, SEEK_CUR);
35784887Schin if (p > y + 1)
35794887Schin {
35804887Schin tp = 0;
35814887Schin co += p - y - 1;
35824887Schin }
35834887Schin if (co >= rm)
35844887Schin tp = 0;
35854887Schin else
35864887Schin {
35874887Schin tp = sfstrtell(mp);
35884887Schin pp = p;
35894887Schin }
35904887Schin }
35914887Schin else if (c == '[')
35924887Schin {
35934887Schin sfputr(mp, "[", -1);
35944887Schin c = ';';
35954887Schin }
35964887Schin else if (c == ']')
35974887Schin {
35984887Schin sfputr(mp, "]", -1);
35994887Schin c = ';';
36004887Schin }
36014887Schin else if (c == 'h')
36024887Schin {
36034887Schin y = p;
36044887Schin if (*y++ == 't' && *y++ == 't' && *y++ == 'p' && (*y == ':' || *y++ == 's' && *y == ':') && *y++ == ':' && *y++ == '/' && *y++ == '/')
36054887Schin {
36064887Schin while (isalnum(*y) || *y == '_' || *y == '/' || *y == '-' || *y == '.')
36074887Schin y++;
36084887Schin if (*y == '?')
36094887Schin while (isalnum(*y) || *y == '_' || *y == '/' || *y == '-' || *y == '.' || *y == '?' || *y == '=' || *y == '%' || *y == '&' || *y == ';' || *y == '#')
36104887Schin y++;
36114887Schin if (*(y - 1) == '.')
36124887Schin y--;
36134887Schin p--;
36144887Schin sfprintf(mp, "<A href=\"%-.*s\">%-.*s</A", y - p, p, y - p, p);
36154887Schin p = y;
36164887Schin c = '>';
36174887Schin }
36184887Schin }
36194887Schin else if (c == 'C')
36204887Schin {
36214887Schin y = p;
36224887Schin 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++ == ')')
36234887Schin {
36244887Schin sfputr(mp, "Copyright ©", -1);
36254887Schin p = y;
36264887Schin c = ';';
36274887Schin }
36284887Schin }
36294887Schin }
36304887Schin else if (c == ']')
36314887Schin {
36324887Schin if (n)
36334887Schin n--;
36344887Schin }
36354887Schin else if (c == '[')
36364887Schin n++;
36374887Schin if (c == CC_esc)
36384887Schin {
36394887Schin sfputc(mp, c);
36404887Schin do
36414887Schin {
36424887Schin if (!(c = *p++))
36434887Schin {
36444887Schin p--;
36454887Schin break;
36464887Schin }
36474887Schin sfputc(mp, c);
36484887Schin } while (c < 'a' || c > 'z');
36494887Schin }
36504887Schin else if (co++ >= rm && !n)
36514887Schin {
36524887Schin if (tp)
36534887Schin {
36544887Schin if (*sfstrseek(mp, tp, SEEK_SET) != ' ')
36554887Schin sfstrseek(mp, 1, SEEK_CUR);
36564887Schin tp = 0;
36574887Schin p = pp;
36584887Schin n = 0;
36594887Schin }
36604887Schin else if (c != ' ' && c != '\n')
36614887Schin sfputc(mp, c);
36624887Schin if (*p == ' ')
36634887Schin p++;
36644887Schin if (*p != '\n')
36654887Schin {
36664887Schin sfputc(mp, '\n');
36674887Schin for (co = 0; co < ts; co++)
36684887Schin sfputc(mp, ' ');
36698462SApril.Chin@Sun.COM rm = margin;
36704887Schin }
36714887Schin }
36724887Schin else
36734887Schin sfputc(mp, c);
36744887Schin }
36754887Schin }
36764887Schin for (d = sfstrbase(mp), t = sfstrseek(mp, 0, SEEK_CUR); t > d && ((c = *(t - 1)) == '\n' || c == '\r' || c == ' ' || c == '\t'); t--);
36774887Schin sfstrseek(mp, t - d, SEEK_SET);
36784887Schin if (style == STYLE_html)
36794887Schin {
36804887Schin while (pt > ptstk)
36814887Schin {
36824887Schin if (--pt > ptstk)
36834887Schin sfprintf(mp, "\n</DL>");
36844887Schin sfprintf(mp, "\n</DL>");
36854887Schin }
36864887Schin sfprintf(mp, "</DL>\n</BODY>\n</HTML>");
36874887Schin }
36884887Schin }
36894887Schin else
36904887Schin sfputr(mp, p, 0);
36914887Schin if (!(p = sfstruse(mp)))
36924887Schin goto nospace;
36934887Schin if (sp)
36944887Schin sfclose(sp);
36954887Schin return opt_info.msg = p;
36964887Schin nospace:
36974887Schin s = T(NiL, ID, "[* out of space *]");
36984887Schin nope:
36994887Schin if (psp)
37004887Schin pop(psp);
37014887Schin if (sp_help)
37024887Schin sfclose(sp_help);
37034887Schin if (sp_text)
37044887Schin sfclose(sp_text);
37054887Schin if (sp_plus)
37064887Schin sfclose(sp_plus);
37074887Schin if (sp_info)
37084887Schin sfclose(sp_info);
37094887Schin if (sp_head)
37104887Schin sfclose(sp_head);
37114887Schin if (sp_body)
37124887Schin sfclose(sp_body);
37134887Schin if (sp_misc)
37144887Schin sfclose(sp_misc);
37154887Schin return s;
37164887Schin }
37174887Schin
37184887Schin /*
37194887Schin * compatibility wrapper to opthelp()
37204887Schin */
37214887Schin
37224887Schin char*
optusage(const char * opts)37234887Schin optusage(const char* opts)
37244887Schin {
37254887Schin return opthelp(opts, NiL);
37264887Schin }
37274887Schin
37284887Schin /*
37294887Schin * convert number using strtonll() *except* that
37304887Schin * 0*[[:digit:]].* is treated as [[:digit:]].*
37314887Schin * i.e., it looks octal but isn't, to meet
37324887Schin * posix Utility Argument Syntax -- use
37334887Schin * 0x.* or <base>#* for alternate bases
37344887Schin */
37354887Schin
37364887Schin static intmax_t
optnumber(const char * s,char ** t,int * e)37374887Schin optnumber(const char* s, char** t, int* e)
37384887Schin {
37394887Schin intmax_t n;
37404887Schin int oerrno;
37414887Schin
37424887Schin while (*s == '0' && isdigit(*(s + 1)))
37434887Schin s++;
37444887Schin oerrno = errno;
37454887Schin errno = 0;
37464887Schin n = strtonll(s, t, NiL, 0);
37474887Schin if (e)
37484887Schin *e = errno;
37494887Schin errno = oerrno;
37504887Schin return n;
37514887Schin }
37524887Schin
37534887Schin /*
37544887Schin * point opt_info.arg to an error/info message for opt_info.name
37554887Schin * p points to opts location for opt_info.name
37564887Schin * optget() return value is returned
37574887Schin */
37584887Schin
37594887Schin static int
opterror(register char * p,int err,int version,char * id,char * catalog)3760*12068SRoger.Faulkner@Oracle.COM opterror(register char* p, int err, int version, char* id, char* catalog)
37614887Schin {
37624887Schin register Sfio_t* mp;
37634887Schin register Sfio_t* tp;
37644887Schin register char* s;
37654887Schin register int c;
37664887Schin
37674887Schin if (opt_info.num != LONG_MIN)
376810898Sroland.mainz@nrubsig.org opt_info.num = (long)(opt_info.number = 0);
37694887Schin if (!p || !(mp = opt_info.state->mp) && !(mp = opt_info.state->mp = sfstropen()))
37704887Schin goto nospace;
37714887Schin s = *p == '-' ? p : opt_info.name;
37724887Schin if (*p == '!')
37734887Schin {
37744887Schin while (*s == '-')
37754887Schin sfputc(mp, *s++);
37764887Schin sfputc(mp, 'n');
37774887Schin sfputc(mp, 'o');
37784887Schin }
37794887Schin sfputr(mp, s, ':');
37804887Schin sfputc(mp, ' ');
37814887Schin if (*p == '#' || *p == ':')
37824887Schin {
37834887Schin if (*p == '#')
37844887Schin {
37854887Schin s = T(NiL, ID, "numeric");
37864887Schin sfputr(mp, s, ' ');
37874887Schin }
37884887Schin if (*(p = next(p + 1, version)) == '[')
37894887Schin {
37904887Schin p = skip(s = p + 1, ':', '?', 0, 1, 0, 0, version);
37914887Schin tp = X(catalog) ? opt_info.state->xp : mp;
37924887Schin while (s < p)
37934887Schin {
37944887Schin if ((c = *s++) == '?' || c == ']')
37954887Schin s++;
37964887Schin sfputc(tp, c);
37974887Schin }
37984887Schin if (!X(catalog))
37994887Schin sfputc(mp, ' ');
38004887Schin else if (p = sfstruse(tp))
3801*12068SRoger.Faulkner@Oracle.COM sfputr(mp, T(id, catalog, p), ' ');
38024887Schin else
38034887Schin goto nospace;
38044887Schin }
38054887Schin p = opt_info.name[2] ? C("value expected") : C("argument expected");
38064887Schin }
38074887Schin else if (*p == '*' || *p == '&')
38084887Schin {
38094887Schin sfputr(mp, opt_info.arg, ':');
38104887Schin sfputc(mp, ' ');
38114887Schin p = *p == '&' ? C("ambiguous option argument value") : C("unknown option argument value");
38124887Schin }
38134887Schin else if (*p == '=' || *p == '!')
38144887Schin p = C("value not expected");
38154887Schin else if (*p == '?')
38164887Schin p = *(p + 1) == '?' ? C("optget: option not supported") : C("ambiguous option");
38174887Schin else if (*p == '+')
38184887Schin p = C("section not found");
38194887Schin else
38204887Schin {
38214887Schin if (opt_info.option[0] != '?' && opt_info.option[0] != '-' || opt_info.option[1] != '?' && opt_info.option[1] != '-')
38224887Schin opt_info.option[0] = 0;
38234887Schin p = C("unknown option");
38244887Schin }
38254887Schin p = T(NiL, ID, p);
38264887Schin sfputr(mp, p, -1);
38274887Schin if (err)
38284887Schin sfputr(mp, " -- out of range", -1);
38294887Schin if (opt_info.arg = sfstruse(mp))
38304887Schin return ':';
38314887Schin nospace:
38324887Schin opt_info.arg = T(NiL, ID, "[* out of space *]");
38334887Schin return ':';
38344887Schin }
38354887Schin
38364887Schin /*
38374887Schin * argv: command line argv where argv[0] is command name
38384887Schin *
38394887Schin * opts: option control string
38404887Schin *
38414887Schin * '[' [flag][=][index][:<long-name>[|<alias-name>...]['?'description]] ']'
38424887Schin * long option name, index, description; -index returned
38434887Schin * ':' option takes string arg
38444887Schin * '#' option takes numeric arg (concat option may follow)
38454887Schin * '?' (option) following options not in usage
38464887Schin * (following # or :) optional arg
38474887Schin * '[' '[' ... ] ... '[' ... ']' ']'
38484887Schin * mutually exclusive option grouping
38494887Schin * '[' name [:attr]* [?description] ']'
38504887Schin * (following # or :) optional option arg description
38514887Schin * '\n'[' '|'\t']* ignored for legibility
38524887Schin * ' ' ... optional argument(s) description (to end of string)
38534887Schin * or after blank line
38544887Schin * ']]' literal ']' within '[' ... ']'
38554887Schin *
38564887Schin * return:
38574887Schin * 0 no more options
38584887Schin * '?' usage: opt_info.arg points to message sans
38594887Schin * `Usage: command '
38604887Schin * ':' error: opt_info.arg points to message sans `command: '
38614887Schin *
386210898Sroland.mainz@nrubsig.org * ':' '#' ' ' '[' ']'
38634887Schin * invalid option chars
38644887Schin *
38654887Schin * -- terminates option list and returns 0
38664887Schin *
38674887Schin * + as first opts char makes + equivalent to -
38684887Schin *
38694887Schin * if any # option is specified then numeric options (e.g., -123)
38704887Schin * are associated with the leftmost # option in opts
38714887Schin *
38724887Schin * usage info in placed opt_info.arg when '?' returned
38734887Schin * see help_text[] (--???) for more info
38744887Schin */
38754887Schin
38764887Schin int
optget(register char ** argv,const char * oopts)38774887Schin optget(register char** argv, const char* oopts)
38784887Schin {
38794887Schin register int c;
38804887Schin register char* s;
38814887Schin char* a;
38824887Schin char* b;
38834887Schin char* e;
38844887Schin char* f;
38854887Schin char* g;
38864887Schin char* v;
38874887Schin char* w;
38884887Schin char* p;
38894887Schin char* q;
38904887Schin char* t;
38914887Schin char* y;
38924887Schin char* numopt;
38934887Schin char* opts;
3894*12068SRoger.Faulkner@Oracle.COM char* id;
38954887Schin char* catalog;
38964887Schin int n;
38974887Schin int m;
38984887Schin int k;
38994887Schin int j;
39004887Schin int x;
39014887Schin int err;
39024887Schin int no;
39034887Schin int nov;
39044887Schin int num;
39054887Schin int numchr;
39064887Schin int prefix;
39074887Schin int version;
39084887Schin Help_t* hp;
39094887Schin Push_t* psp;
39104887Schin Push_t* tsp;
39114887Schin Sfio_t* vp;
39124887Schin Sfio_t* xp;
39134887Schin Optcache_t* cache;
39144887Schin Optcache_t* pcache;
39154887Schin Optpass_t* pass;
39164887Schin
39178462SApril.Chin@Sun.COM #if !_PACKAGE_astsa && !_YOU_FIGURED_OUT_HOW_TO_GET_ALL_DLLS_TO_DO_THIS_
39184887Schin /*
39194887Schin * these are not initialized by all dlls!
39204887Schin */
39214887Schin
39224887Schin extern Error_info_t _error_info_;
39234887Schin extern Opt_t _opt_info_;
39244887Schin
39254887Schin if (!_error_infop_)
39264887Schin _error_infop_ = &_error_info_;
39274887Schin if (!_opt_infop_)
39284887Schin _opt_infop_ = &_opt_info_;
39294887Schin if (!opt_info.state)
39304887Schin opt_info.state = &state;
39314887Schin #endif
39324887Schin if (!oopts)
39334887Schin return 0;
39344887Schin opt_info.state->pindex = opt_info.index;
39354887Schin opt_info.state->poffset = opt_info.offset;
39364887Schin if (!opt_info.index)
39374887Schin {
39384887Schin opt_info.index = 1;
39394887Schin opt_info.offset = 0;
39404887Schin if (opt_info.state->npass)
39414887Schin {
39424887Schin opt_info.state->npass = 0;
39434887Schin opt_info.state->join = 0;
39444887Schin }
39454887Schin }
39464887Schin if (!argv)
39474887Schin cache = 0;
39484887Schin else
39494887Schin for (pcache = 0, cache = opt_info.state->cache; cache; pcache = cache, cache = cache->next)
39504887Schin if (cache->pass.oopts == (char*)oopts)
39514887Schin break;
39524887Schin if (cache)
39534887Schin {
39544887Schin if (pcache)
39554887Schin {
39564887Schin pcache->next = cache->next;
39574887Schin cache->next = opt_info.state->cache;
39584887Schin opt_info.state->cache = cache;
39594887Schin }
39604887Schin pass = &cache->pass;
39614887Schin opt_info.state->npass = -1;
39624887Schin }
39634887Schin else
39644887Schin {
39654887Schin if (!argv)
39664887Schin n = opt_info.state->npass ? opt_info.state->npass : 1;
39674887Schin else if ((n = opt_info.state->join - 1) < 0)
39684887Schin n = 0;
39694887Schin if (n >= opt_info.state->npass || opt_info.state->pass[n].oopts != (char*)oopts)
39704887Schin {
39714887Schin for (m = 0; m < opt_info.state->npass && opt_info.state->pass[m].oopts != (char*)oopts; m++);
39724887Schin if (m < opt_info.state->npass)
39734887Schin n = m;
39744887Schin else
39754887Schin {
39764887Schin if (n >= elementsof(opt_info.state->pass))
39774887Schin n = elementsof(opt_info.state->pass) - 1;
39784887Schin init((char*)oopts, &opt_info.state->pass[n]);
39794887Schin if (opt_info.state->npass <= n)
39804887Schin opt_info.state->npass = n + 1;
39814887Schin }
39824887Schin }
39834887Schin if (!argv)
39844887Schin return 0;
39854887Schin pass = &opt_info.state->pass[n];
39864887Schin }
39874887Schin opts = pass->opts;
39884887Schin prefix = pass->prefix;
39894887Schin version = pass->version;
3990*12068SRoger.Faulkner@Oracle.COM id = pass->id;
39914887Schin if (!(xp = opt_info.state->xp) || (catalog = pass->catalog) && !X(catalog))
39924887Schin catalog = 0;
39934887Schin else /* if (!error_info.catalog) */
39944887Schin error_info.catalog = catalog;
39954887Schin again:
39964887Schin psp = 0;
39974887Schin
39984887Schin /*
39994887Schin * check if any options remain and determine if the
40004887Schin * next option is short or long
40014887Schin */
40024887Schin
40034887Schin opt_info.assignment = 0;
40044887Schin num = 1;
40054887Schin w = v = 0;
40064887Schin x = 0;
40074887Schin for (;;)
40084887Schin {
40094887Schin if (!opt_info.offset)
40104887Schin {
40114887Schin /*
40124887Schin * finished with the previous arg
40134887Schin */
40144887Schin
40154887Schin if (opt_info.index == 1 && opt_info.argv != opt_info.state->strv)
40164887Schin {
40174887Schin opt_info.argv = 0;
40184887Schin opt_info.state->argv[0] = 0;
40194887Schin if (argv[0] && (opt_info.state->argv[0] = save(argv[0])))
40204887Schin opt_info.argv = opt_info.state->argv;
40214887Schin opt_info.state->style = STYLE_short;
40224887Schin }
40234887Schin if (!(s = argv[opt_info.index]))
40244887Schin return 0;
40254887Schin if (!prefix)
40264887Schin {
40274887Schin /*
40284887Schin * long with no prefix (dd style)
40294887Schin */
40304887Schin
40314887Schin n = 2;
40324887Schin if ((c = *s) != '-' && c != '+')
40334887Schin c = '-';
40344887Schin else if (*++s == c)
40354887Schin {
40364887Schin if (!*++s)
40374887Schin {
40384887Schin opt_info.index++;
40394887Schin return 0;
40404887Schin }
40418462SApril.Chin@Sun.COM else if (*s == c)
40428462SApril.Chin@Sun.COM return 0;
40434887Schin }
40444887Schin else if (*s == '?')
40454887Schin n = 1;
40464887Schin }
40478462SApril.Chin@Sun.COM else if ((c = *s++) != '-' && (c != '+' || !(pass->flags & OPT_plus) && (!(pass->flags & OPT_numeric) || !isdigit(*s))))
40484887Schin {
40494887Schin if (!(pass->flags & OPT_old) || !isalpha(c))
40504887Schin return 0;
40514887Schin s--;
40524887Schin n = 1;
40534887Schin opt_info.offset--;
40544887Schin }
40554887Schin else if (*s == c)
40564887Schin {
40574887Schin if (!*++s)
40584887Schin {
40594887Schin /*
40604887Schin * -- or ++ end of options
40614887Schin */
40624887Schin
40634887Schin opt_info.index++;
40644887Schin return 0;
40654887Schin }
40668462SApril.Chin@Sun.COM else if (*s == c)
40678462SApril.Chin@Sun.COM {
40688462SApril.Chin@Sun.COM /*
40698462SApril.Chin@Sun.COM * ---* or +++* are operands
40708462SApril.Chin@Sun.COM */
40718462SApril.Chin@Sun.COM
40728462SApril.Chin@Sun.COM return 0;
40738462SApril.Chin@Sun.COM }
40744887Schin if (version || *s == '?' || !(pass->flags & OPT_minus))
40754887Schin {
40764887Schin /*
40774887Schin * long with double prefix
40784887Schin */
40794887Schin
40804887Schin n = 2;
40814887Schin }
40824887Schin else
40834887Schin {
40844887Schin /*
40854887Schin * short option char '-'
40864887Schin */
40874887Schin
40884887Schin s--;
40894887Schin n = 1;
40904887Schin }
40914887Schin }
40924887Schin else if (prefix == 1 && *s != '?')
40934887Schin {
40944887Schin /*
40954887Schin * long with single prefix (find style)
40964887Schin */
40974887Schin
40984887Schin n = 2;
40994887Schin }
41004887Schin else
41014887Schin {
41024887Schin /*
41034887Schin * short (always with single prefix)
41044887Schin */
41054887Schin
41064887Schin n = 1;
41074887Schin }
41084887Schin
41094887Schin /*
41104887Schin * just a prefix is an option (e.g., `-' == stdin)
41114887Schin */
41124887Schin
41134887Schin if (!*s)
41144887Schin return 0;
41154887Schin if (c == '+')
41164887Schin opt_info.arg = 0;
411710898Sroland.mainz@nrubsig.org message((-2, "c='%c' n=%d", c, n));
41184887Schin if (n == 2)
41194887Schin {
41204887Schin x = 0;
41214887Schin opt_info.state->style = STYLE_long;
41224887Schin opt_info.option[0] = opt_info.name[0] = opt_info.name[1] = c;
41234887Schin w = &opt_info.name[prefix];
41244887Schin if ((*s == 'n' || *s == 'N') && (*(s + 1) == 'o' || *(s + 1) == 'O') && *(s + 2) && *(s + 2) != '=')
41254887Schin no = *(s + 2) == '-' ? 3 : 2;
41264887Schin else
41274887Schin no = 0;
41284887Schin for (c = *s; *s; s++)
41294887Schin {
41304887Schin if (*s == '=')
41314887Schin {
41324887Schin if (*(s + 1) == '=')
41334887Schin s++;
41344887Schin if (!isalnum(*(s - 1)) && *(w - 1) == (opt_info.assignment = *(s - 1)))
41354887Schin w--;
41364887Schin v = ++s;
41374887Schin break;
41384887Schin }
41394887Schin if (w < &opt_info.name[elementsof(opt_info.name) - 1] && *s != ':' && *s != '|' && *s != '[' && *s != ']')
41404887Schin *w++ = *s;
41414887Schin }
41424887Schin *w = 0;
41434887Schin w = &opt_info.name[prefix];
41444887Schin c = *w;
41454887Schin opt_info.offset = 0;
41464887Schin opt_info.index++;
41474887Schin break;
41484887Schin }
41494887Schin opt_info.offset++;
41504887Schin }
41514887Schin if (!argv[opt_info.index])
41524887Schin return 0;
41534887Schin if (c = argv[opt_info.index][opt_info.offset++])
41544887Schin {
41554887Schin if ((k = argv[opt_info.index][0]) != '-' && k != '+')
41564887Schin k = '-';
41574887Schin opt_info.option[0] = opt_info.name[0] = k;
41584887Schin opt_info.option[1] = opt_info.name[1] = c;
41594887Schin opt_info.option[2] = opt_info.name[2] = 0;
41604887Schin break;
41614887Schin }
41624887Schin opt_info.offset = 0;
41634887Schin opt_info.index++;
41644887Schin }
41654887Schin
41664887Schin /*
41674887Schin * at this point:
41684887Schin *
41694887Schin * c the first character of the option
41704887Schin * w long option name if != 0, otherwise short
41714887Schin * v long option value (via =) if w != 0
41724887Schin */
41734887Schin
41744887Schin if (c == '?')
41754887Schin {
41764887Schin /*
41774887Schin * ? always triggers internal help
41784887Schin */
41794887Schin
41804887Schin if (w && !v && (*(w + 1) || !(v = argv[opt_info.index]) || !++opt_info.index))
41814887Schin v = w + 1;
41824887Schin opt_info.option[1] = c;
41834887Schin opt_info.option[2] = 0;
41844887Schin if (!w)
41854887Schin {
41864887Schin opt_info.name[1] = c;
41874887Schin opt_info.name[2] = 0;
41884887Schin }
41894887Schin goto help;
41904887Schin }
41914887Schin numopt = 0;
41924887Schin f = 0;
41934887Schin s = opts;
41944887Schin
41954887Schin /*
41964887Schin * no option can start with these characters
41974887Schin */
41984887Schin
41994887Schin if (c == ':' || c == '#' || c == ' ' || c == '[' || c == ']')
42004887Schin {
42014887Schin if (c != *s)
42024887Schin s = "";
42034887Schin }
42044887Schin else
42054887Schin {
42064887Schin a = 0;
42074887Schin if (!w && (pass->flags & OPT_cache))
42084887Schin {
42094887Schin if (cache)
42104887Schin {
42114887Schin if (k = cache->flags[map[c]])
42124887Schin {
42134887Schin opt_info.arg = 0;
42144887Schin
42154887Schin /*
42164887Schin * this is a ksh getopts workaround
42174887Schin */
42184887Schin
42194887Schin if (opt_info.num != LONG_MIN)
422010898Sroland.mainz@nrubsig.org opt_info.num = (long)(opt_info.number = !(k & OPT_cache_invert));
42214887Schin if (!(k & (OPT_cache_string|OPT_cache_numeric)))
42224887Schin return c;
42234887Schin if (*(opt_info.arg = &argv[opt_info.index++][opt_info.offset]))
42244887Schin {
42254887Schin if (!(k & OPT_cache_numeric))
42264887Schin {
42274887Schin opt_info.offset = 0;
42284887Schin return c;
42294887Schin }
42304887Schin opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
42314887Schin if (err || e == opt_info.arg)
42324887Schin {
42334887Schin if (!err && (k & OPT_cache_optional))
42344887Schin {
42354887Schin opt_info.arg = 0;
42364887Schin opt_info.index--;
42374887Schin return c;
42384887Schin }
42394887Schin }
42404887Schin else if (*e)
42414887Schin {
42424887Schin opt_info.offset += e - opt_info.arg;
42434887Schin opt_info.index--;
42444887Schin return c;
42454887Schin }
42464887Schin else
42474887Schin {
42484887Schin opt_info.offset = 0;
42494887Schin return c;
42504887Schin }
42514887Schin }
42524887Schin else if (opt_info.arg = argv[opt_info.index])
42534887Schin {
42544887Schin opt_info.index++;
42554887Schin if ((k & OPT_cache_optional) && (*opt_info.arg == '-' || (pass->flags & OPT_plus) && *opt_info.arg == '+') && *(opt_info.arg + 1))
42564887Schin {
42574887Schin opt_info.arg = 0;
42584887Schin opt_info.index--;
42594887Schin opt_info.offset = 0;
42604887Schin return c;
42614887Schin }
42624887Schin if (k & OPT_cache_string)
42634887Schin {
42644887Schin opt_info.offset = 0;
42654887Schin return c;
42664887Schin }
42674887Schin opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
42684887Schin if (!err)
42694887Schin {
42704887Schin if (!*e)
42714887Schin {
42724887Schin opt_info.offset = 0;
42734887Schin return c;
42744887Schin }
42754887Schin if (k & OPT_cache_optional)
42764887Schin {
42774887Schin opt_info.arg = 0;
42784887Schin opt_info.index--;
42794887Schin opt_info.offset = 0;
42804887Schin return c;
42814887Schin }
42824887Schin }
42834887Schin }
42844887Schin else if (k & OPT_cache_optional)
42854887Schin {
42864887Schin opt_info.offset = 0;
42874887Schin return c;
42884887Schin }
42894887Schin opt_info.index--;
42904887Schin }
42914887Schin cache = 0;
42924887Schin }
42934887Schin else if (cache = newof(0, Optcache_t, 1, 0))
42944887Schin {
42954887Schin cache->caching = c;
42964887Schin c = 0;
42974887Schin cache->pass = *pass;
42984887Schin cache->next = opt_info.state->cache;
42994887Schin opt_info.state->cache = cache;
43004887Schin }
43014887Schin }
43024887Schin else
43034887Schin cache = 0;
43044887Schin for (;;)
43054887Schin {
43064887Schin if (!(*(s = next(s, version))) || *s == '\n' || *s == ' ')
43074887Schin {
43084887Schin if (!(tsp = psp))
43094887Schin {
43104887Schin if (cache)
43114887Schin {
43124887Schin /*
43134887Schin * the first loop pass
43144887Schin * initialized the cache
43154887Schin * so one more pass to
43164887Schin * check the cache or
43174887Schin * bail for a full scan
43184887Schin */
43194887Schin
43204887Schin cache->flags[0] = 0;
43214887Schin c = cache->caching;
43224887Schin cache->caching = 0;
43234887Schin cache = 0;
43244887Schin s = opts;
43254887Schin continue;
43264887Schin }
43274887Schin if (!x && catalog)
43284887Schin {
43294887Schin /*
43304887Schin * the first loop pass
43314887Schin * translated long
43324887Schin * options and there
43334887Schin * were no matches so
43344887Schin * one more pass for C
43354887Schin * locale
43364887Schin */
43374887Schin
43384887Schin catalog = 0;
43394887Schin s = opts;
43404887Schin continue;
43414887Schin }
43424887Schin s = "";
43434887Schin break;
43444887Schin }
43454887Schin s = psp->ob;
43464887Schin psp = psp->next;
43474887Schin free(tsp);
43484887Schin continue;
43494887Schin }
43504887Schin if (*s == '\f')
43514887Schin {
4352*12068SRoger.Faulkner@Oracle.COM psp = info(psp, s + 1, NiL, opt_info.state->xp, id);
43534887Schin if (psp->nb)
43544887Schin s = psp->nb;
43554887Schin else
43564887Schin {
43574887Schin s = psp->ob;
43584887Schin psp = psp->next;
43594887Schin }
43604887Schin continue;
43614887Schin }
436210898Sroland.mainz@nrubsig.org message((-20, "optget: opt %s c %c w %s num %ld", show(s), c, w, num));
43634887Schin if (*s == c && !w)
43644887Schin break;
43654887Schin else if (*s == '[')
43664887Schin {
43674887Schin f = s = next(s + 1, version);
43684887Schin k = *f;
43694887Schin if (k == '+' || k == '-')
43704887Schin /* ignore */;
43714887Schin else if (k == '[' || version < 1)
43724887Schin continue;
43734887Schin else if (w && !cache)
43744887Schin {
43754887Schin nov = no;
43764887Schin if (*(s + 1) == '\f' && (vp = opt_info.state->vp))
43774887Schin {
43784887Schin sfputc(vp, k);
4379*12068SRoger.Faulkner@Oracle.COM s = expand(s + 2, NiL, &t, vp, id);
43804887Schin if (*s)
43814887Schin *(f = s - 1) = k;
43824887Schin else
43834887Schin {
43844887Schin f = sfstrbase(vp);
43854887Schin if (s = strrchr(f, ':'))
43864887Schin f = s - 1;
43874887Schin else
43884887Schin s = f + 1;
43894887Schin }
43904887Schin }
43914887Schin else
43924887Schin t = 0;
43934887Schin if (*s != ':')
43944887Schin s = skip(s, ':', '?', 0, 1, 0, 0, version);
43954887Schin if (*s == ':')
43964887Schin {
43974887Schin if (catalog)
43984887Schin {
43994887Schin p = skip(s + 1, '?', 0, 0, 1, 0, 0, version);
44004887Schin e = sfprints("%-.*s", p - (s + 1), s + 1);
4401*12068SRoger.Faulkner@Oracle.COM g = T(id, catalog, e);
44024887Schin if (g == e)
44034887Schin p = 0;
44044887Schin else
44054887Schin {
44064887Schin sfprintf(xp, ":%s|%s?", g, e);
44074887Schin if (!(s = sfstruse(xp)))
44084887Schin goto nospace;
44094887Schin }
44104887Schin }
44114887Schin else
44124887Schin p = 0;
44134887Schin y = w;
44144887Schin for (;;)
44154887Schin {
44164887Schin n = m = 0;
44174887Schin e = s + 1;
44184887Schin while (*++s)
44194887Schin {
44204887Schin if (*s == '*' || *s == '\a')
44214887Schin {
44224887Schin if (*s == '\a')
44234887Schin do
44244887Schin {
44254887Schin if (!*++s)
44264887Schin {
44274887Schin s--;
44284887Schin break;
44294887Schin }
44304887Schin } while (*s != '\a');
44314887Schin j = *(s + 1);
44324887Schin if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
44334887Schin {
44344887Schin while (*w)
44354887Schin w++;
44364887Schin m = 0;
44374887Schin break;
44384887Schin }
44394887Schin m = 1;
44404887Schin }
44414887Schin else if (*s == *w || sep(*s) && sep(*w))
44424887Schin w++;
44434887Schin else if (*w == 0)
44444887Schin break;
44454887Schin else if (!sep(*s))
44464887Schin {
44474887Schin if (sep(*w))
44484887Schin {
44494887Schin if (*++w == *s)
44504887Schin {
44514887Schin w++;
44524887Schin continue;
44534887Schin }
44544887Schin }
44554887Schin else if (w == y || sep(*(w - 1)) || isupper(*(w - 1)) && islower(*w))
44564887Schin break;
44574887Schin for (q = s; *q && !sep(*q) && *q != '|' && *q != '?' && *q != ']'; q++);
44584887Schin if (!sep(*q))
44594887Schin break;
44604887Schin for (s = q; w > y && *w != *(s + 1); w--);
44614887Schin }
44624887Schin else if (*w != *(s + 1))
44634887Schin break;
44644887Schin }
44654887Schin if (!*w)
44664887Schin {
44674887Schin nov = 0;
44684887Schin break;
44694887Schin }
44704887Schin if (n = no)
44714887Schin {
44724887Schin m = 0;
44734887Schin s = e - 1;
44744887Schin w = y + n;
44754887Schin while (*++s)
44764887Schin {
44774887Schin if (*s == '*' || *s == '\a')
44784887Schin {
44794887Schin if (*s == '\a')
44804887Schin do
44814887Schin {
44824887Schin if (!*++s)
44834887Schin {
44844887Schin s--;
44854887Schin break;
44864887Schin }
44874887Schin } while (*s != '\a');
44884887Schin j = *(s + 1);
44894887Schin if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
44904887Schin {
44914887Schin while (*w)
44924887Schin w++;
44934887Schin m = 0;
44944887Schin break;
44954887Schin }
44964887Schin m = 1;
44974887Schin }
44984887Schin else if (*s == *w || sep(*s) && sep(*w))
44994887Schin w++;
45004887Schin else if (*w == 0)
45014887Schin break;
45024887Schin else if (!sep(*s))
45034887Schin {
45044887Schin if (sep(*w))
45054887Schin {
45064887Schin if (*++w == *s)
45074887Schin {
45084887Schin w++;
45094887Schin continue;
45104887Schin }
45114887Schin }
45124887Schin else if (w == y || sep(*(w - 1)) || isupper(*(w - 1)) && islower(*w))
45134887Schin break;
45144887Schin for (q = s; *q && !sep(*q) && *q != '|' && *q != '?' && *q != ']'; q++);
45154887Schin if (!sep(*q))
45164887Schin break;
45174887Schin for (s = q; w > y && *w != *(s + 1); w--);
45184887Schin }
45194887Schin else if (*w != *(s + 1))
45204887Schin break;
45214887Schin }
45224887Schin if (!*w)
45234887Schin break;
45244887Schin }
45254887Schin if (*(s = skip(s, ':', '|', '?', 1, 0, 0, version)) != '|')
45264887Schin break;
45274887Schin w = y;
45284887Schin }
45294887Schin if (p)
45304887Schin s = p;
45314887Schin if (!*w)
45324887Schin {
45334887Schin if (n)
45344887Schin num = 0;
45354887Schin if (!(n = (m || *s == ':' || *s == '|' || *s == '?' || *s == ']' || *s == 0)) && x)
45364887Schin {
45374887Schin psp = pop(psp);
4538*12068SRoger.Faulkner@Oracle.COM return opterror("?", 0, version, id, catalog);
45394887Schin }
45404887Schin for (x = k; *(f + 1) == '|' && (j = *(f + 2)) && j != '!' && j != '=' && j != ':' && j != '?' && j != ']'; f += 2);
45414887Schin if (*f == ':')
45424887Schin {
45434887Schin x = -1;
45444887Schin opt_info.option[1] = '-';
45454887Schin opt_info.option[2] = 0;
45464887Schin }
45474887Schin else if (*(f + 1) == ':' || *(f + 1) == '!' && *(f + 2) == ':')
45484887Schin {
45494887Schin opt_info.option[1] = x;
45504887Schin opt_info.option[2] = 0;
45514887Schin }
45524887Schin else
45534887Schin {
45544887Schin a = f;
45554887Schin if (*a == '=')
45564887Schin a++;
45574887Schin else
45584887Schin {
45594887Schin if (*(a + 1) == '!')
45604887Schin a++;
45614887Schin if (*(a + 1) == '=')
45624887Schin a += 2;
45634887Schin }
45644887Schin x = -strtol(a, &b, 0);
45654887Schin if ((b - a) > sizeof(opt_info.option) - 2)
45664887Schin b = a + sizeof(opt_info.option) - 2;
45674887Schin memcpy(&opt_info.option[1], a, b - a);
45684887Schin opt_info.option[b - a + 1] = 0;
45694887Schin }
45704887Schin b = e;
45714887Schin if (t)
45724887Schin {
45734887Schin s = t;
45744887Schin t = 0;
45754887Schin }
45764887Schin a = s = skip(s, 0, 0, 0, 1, 0, 0, version);
45774887Schin if (n)
45784887Schin {
45794887Schin w = y;
45804887Schin break;
45814887Schin }
45824887Schin }
45834887Schin w = y;
45844887Schin }
45854887Schin else if (k == c && prefix == 1)
45864887Schin {
45874887Schin w = 0;
45884887Schin opt_info.name[1] = c;
45894887Schin opt_info.name[2] = 0;
45904887Schin opt_info.offset = 2;
45914887Schin opt_info.index--;
45924887Schin break;
45934887Schin }
45944887Schin if (t)
45954887Schin {
45964887Schin s = t;
45974887Schin if (a)
45984887Schin a = t;
45994887Schin }
46004887Schin }
46014887Schin s = skip(s, 0, 0, 0, 1, 0, 1, version);
46024887Schin if (*s == GO)
46034887Schin s = skip(s + 1, 0, 0, 0, 0, 1, 1, version);
46044887Schin if (cache)
46054887Schin {
46064887Schin m = OPT_cache_flag;
46074887Schin v = s;
46084887Schin if (*v == '#')
46094887Schin {
46104887Schin v++;
46114887Schin m |= OPT_cache_numeric;
46124887Schin }
46134887Schin else if (*v == ':')
46144887Schin {
46154887Schin v++;
46164887Schin m |= OPT_cache_string;
46174887Schin }
46184887Schin if (*v == '?')
46194887Schin {
46204887Schin v++;
46214887Schin m |= OPT_cache_optional;
46224887Schin }
46234887Schin else if (*v == *(v - 1))
46244887Schin v++;
46254887Schin if (*(v = next(v, version)) == '[')
46264887Schin v = skip(v + 1, 0, 0, 0, 1, 0, 1, version);
46274887Schin if (*v != GO)
46284887Schin {
46294887Schin v = f;
46304887Schin for (;;)
46314887Schin {
46324887Schin if (isdigit(*f) && isdigit(*(f + 1)))
46334887Schin while (isdigit(*(f + 1)))
46344887Schin f++;
46354887Schin else if (*(f + 1) == '=')
46364887Schin break;
46374887Schin else
46384887Schin cache->flags[map[*f]] = m;
46394887Schin j = 0;
46404887Schin while (*(f + 1) == '|')
46414887Schin {
46424887Schin f += 2;
46434887Schin if (!(j = *f) || j == '!' || j == '=' || j == ':' || j == '?' || j == ']')
46444887Schin break;
46454887Schin cache->flags[map[j]] = m;
46464887Schin }
46474887Schin if (j != '!' || (m & OPT_cache_invert))
46484887Schin break;
46494887Schin f = v;
46504887Schin m |= OPT_cache_invert;
46514887Schin }
46524887Schin }
46534887Schin }
46544887Schin else
46554887Schin {
46564887Schin m = 0;
46574887Schin if (!w)
46584887Schin {
46594887Schin if (isdigit(*f) && isdigit(*(f + 1)))
46604887Schin k = -1;
46614887Schin if (c == k)
46624887Schin m = 1;
46634887Schin while (*(f + 1) == '|')
46644887Schin {
46654887Schin f += 2;
46664887Schin if (!(j = *f))
46674887Schin {
46684887Schin m = 0;
46694887Schin break;
46704887Schin }
46714887Schin else if (j == c)
46724887Schin m = 1;
46734887Schin else if (j == '!' || j == '=' || j == ':' || j == '?' || j == ']')
46744887Schin break;
46754887Schin }
46764887Schin }
46774887Schin if (m)
46784887Schin {
46794887Schin s--;
46804887Schin if (*++f == '!')
46814887Schin {
46824887Schin f++;
46834887Schin num = 0;
46844887Schin }
46854887Schin if (*f == '=')
46864887Schin {
46874887Schin c = -strtol(++f, &b, 0);
46884887Schin if ((b - f) > sizeof(opt_info.option) - 2)
46894887Schin b = f + sizeof(opt_info.option) - 2;
46904887Schin memcpy(&opt_info.option[1], f, b - f);
46914887Schin opt_info.option[b - f + 1] = 0;
46924887Schin }
46934887Schin else
46944887Schin c = k;
46954887Schin break;
46964887Schin }
46974887Schin }
46984887Schin if (*s == '#')
46994887Schin {
47004887Schin if (!numopt && s > opts)
47014887Schin {
47024887Schin numopt = s - 1;
47034887Schin numchr = k;
47044887Schin if (*f == ':')
47054887Schin numchr = -1;
47064887Schin else if (*(f + 1) != ':' && *(f + 1) != '!' && *(f + 1) != ']')
47074887Schin {
47084887Schin a = f;
47094887Schin if (*a == '=')
47104887Schin a++;
47114887Schin else
47124887Schin {
47134887Schin if (*(a + 1) == '!')
47144887Schin a++;
47154887Schin if (*(a + 1) == '=')
47164887Schin a += 2;
47174887Schin }
47184887Schin numchr = -strtol(a, NiL, 0);
47194887Schin }
47204887Schin }
47214887Schin }
47224887Schin else if (*s != ':')
47234887Schin continue;
47244887Schin }
47254887Schin else if (*s == ']')
47264887Schin {
47274887Schin s++;
47284887Schin continue;
47294887Schin }
47304887Schin else if (*s == '#')
47314887Schin {
47324887Schin if (!numopt && s > opts)
47334887Schin numchr = *(numopt = s - 1);
47344887Schin }
47354887Schin else if (*s != ':')
47364887Schin {
47374887Schin if (cache)
47384887Schin {
47394887Schin m = OPT_cache_flag;
47404887Schin if (*(s + 1) == '#')
47414887Schin {
47424887Schin m |= OPT_cache_numeric;
47434887Schin if (*(s + 2) == '?')
47444887Schin m |= OPT_cache_optional;
47454887Schin }
47464887Schin else if (*(s + 1) == ':')
47474887Schin {
47484887Schin m |= OPT_cache_string;
47494887Schin if (*(s + 2) == '?')
47504887Schin m |= OPT_cache_optional;
47514887Schin }
47524887Schin cache->flags[map[*s]] = m;
47534887Schin }
47544887Schin s++;
47554887Schin continue;
47564887Schin }
47574887Schin message((-21, "optget: opt %s", show(s)));
47584887Schin if (*++s == '?' || *s == *(s - 1))
47594887Schin s++;
47604887Schin if (*(s = next(s, version)) == '[')
47614887Schin {
47624887Schin s = skip(s + 1, 0, 0, 0, 1, 0, 1, version);
47634887Schin if (*s == GO)
47644887Schin s = skip(s + 1, 0, 0, 0, 0, 1, 1, version);
47654887Schin }
476610898Sroland.mainz@nrubsig.org message((-21, "optget: opt %s", show(s)));
47674887Schin }
47684887Schin if (w && x)
47694887Schin {
47704887Schin s = skip(b, '|', '?', 0, 1, 0, 0, version);
47714887Schin if (v && (a == 0 || *a == 0 || *(a + 1) != ':' && *(a + 1) != '#') && (*v == '0' || *v == '1') && !*(v + 1))
47724887Schin {
47734887Schin if (*v == '0')
47744887Schin num = !num;
47754887Schin v = 0;
47764887Schin }
47774887Schin if ((s - b) >= elementsof(opt_info.name))
47784887Schin s = b + elementsof(opt_info.name) - 1;
47794887Schin for (;;)
47804887Schin {
47814887Schin if (b >= s)
47824887Schin {
47834887Schin *w = 0;
47844887Schin break;
47854887Schin }
47864887Schin if (*b == '*')
47874887Schin break;
47884887Schin *w++ = *b++;
47894887Schin }
47904887Schin if (!num && v)
4791*12068SRoger.Faulkner@Oracle.COM return opterror(no ? "!" : "=", 0, version, id, catalog);
47924887Schin w = &opt_info.name[prefix];
47934887Schin c = x;
47944887Schin s = a;
47954887Schin }
47964887Schin }
47974887Schin if (!*s)
47984887Schin {
47994887Schin if (w)
48004887Schin {
48014887Schin if (hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), w))
48024887Schin {
48034887Schin if (!v)
48044887Schin v = (char*)hp->name;
48054887Schin goto help;
48064887Schin }
48074887Schin if (!v)
48084887Schin {
48094887Schin v = opt_info.name;
48104887Schin goto help;
48114887Schin }
48124887Schin }
48138462SApril.Chin@Sun.COM if (w || !isdigit(c) || !numopt || !(pass->flags & OPT_numeric))
48144887Schin {
48154887Schin pop(psp);
4816*12068SRoger.Faulkner@Oracle.COM return opterror("", 0, version, id, catalog);
48174887Schin }
48184887Schin s = numopt;
48194887Schin c = opt_info.option[1] = numchr;
48204887Schin opt_info.offset--;
48214887Schin }
48224887Schin opt_info.arg = 0;
48234887Schin
48244887Schin /*
48254887Schin * this is a ksh getopts workaround
48264887Schin */
48274887Schin
48284887Schin if (opt_info.num != LONG_MIN)
482910898Sroland.mainz@nrubsig.org opt_info.num = (long)(opt_info.number = num);
48304887Schin if ((n = *++s == '#') || *s == ':' || w && !nov && v && (optnumber(v, &e, NiL), n = !*e))
48314887Schin {
48324887Schin if (w)
48334887Schin {
48344887Schin if (nov)
48354887Schin {
48364887Schin if (v)
48374887Schin {
48384887Schin pop(psp);
4839*12068SRoger.Faulkner@Oracle.COM return opterror("!", 0, version, id, catalog);
48404887Schin }
484110898Sroland.mainz@nrubsig.org opt_info.num = (long)(opt_info.number = 0);
48424887Schin }
48434887Schin else
48444887Schin {
48454887Schin if (!v && *(s + 1) != '?' && (v = argv[opt_info.index]))
48464887Schin {
48474887Schin opt_info.index++;
48484887Schin opt_info.offset = 0;
48494887Schin }
48504887Schin if (!(opt_info.arg = v) || (*v == '0' || *v == '1') && !*(v + 1))
48514887Schin {
48524887Schin if (*(s + 1) != '?')
48534887Schin {
48544887Schin if (!opt_info.arg)
48554887Schin {
48564887Schin pop(psp);
4857*12068SRoger.Faulkner@Oracle.COM return opterror(s, 0, version, id, catalog);
48584887Schin }
48594887Schin }
48604887Schin else if (*(t = next(s + 2, version)) == '[')
48614887Schin while (*(t = skip(t, ':', 0, 0, 1, 0, 0, version)) == ':')
48624887Schin if (*++t == '!')
48634887Schin {
48644887Schin if (!v || *v == '1')
48654887Schin {
48664887Schin e = skip(t, ':', '?', ']', 1, 0, 0, version);
48674887Schin opt_info.arg = sfprints("%-.*s", e - t - 1, t + 1);
48684887Schin }
48694887Schin else
48704887Schin {
48714887Schin opt_info.arg = 0;
487210898Sroland.mainz@nrubsig.org opt_info.num = (long)(opt_info.number = 0);
48734887Schin }
48744887Schin break;
48754887Schin }
48764887Schin }
48774887Schin if (opt_info.arg && n)
48784887Schin {
48794887Schin opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
48804887Schin if (err || e == opt_info.arg)
48814887Schin {
48824887Schin pop(psp);
4883*12068SRoger.Faulkner@Oracle.COM return opterror(s, err, version, id, catalog);
48844887Schin }
48854887Schin }
48864887Schin }
48874887Schin goto optarg;
48884887Schin }
48894887Schin else if (*(opt_info.arg = &argv[opt_info.index++][opt_info.offset]))
48904887Schin {
48914887Schin if (*s == '#')
48924887Schin {
48934887Schin opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
48944887Schin if (err || e == opt_info.arg)
48954887Schin {
48964887Schin if (!err && *(s + 1) == '?')
48974887Schin {
48984887Schin opt_info.arg = 0;
48994887Schin opt_info.index--;
49004887Schin }
49014887Schin else
49024887Schin {
49034887Schin opt_info.offset = 0;
4904*12068SRoger.Faulkner@Oracle.COM c = opterror(s, err, version, id, catalog);
49054887Schin }
49064887Schin pop(psp);
49074887Schin return c;
49084887Schin }
49094887Schin else if (*e)
49104887Schin {
49114887Schin opt_info.offset += e - opt_info.arg;
49124887Schin opt_info.index--;
49134887Schin pop(psp);
49144887Schin return c;
49154887Schin }
49164887Schin }
49174887Schin }
49184887Schin else if (opt_info.arg = argv[opt_info.index])
49194887Schin {
49204887Schin opt_info.index++;
49214887Schin if (*(s + 1) == '?' && (*opt_info.arg == '-' || (pass->flags & OPT_plus) && *opt_info.arg == '+') && *(opt_info.arg + 1))
49224887Schin {
49234887Schin opt_info.index--;
49244887Schin opt_info.arg = 0;
49254887Schin }
49264887Schin else if (*s == '#')
49274887Schin {
49284887Schin opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
49294887Schin if (err || *e)
49304887Schin {
49314887Schin if (!err && *(s + 1) == '?')
49324887Schin {
49334887Schin opt_info.arg = 0;
49344887Schin opt_info.index--;
49354887Schin }
49364887Schin else
49374887Schin {
49384887Schin pop(psp);
49394887Schin opt_info.offset = 0;
4940*12068SRoger.Faulkner@Oracle.COM return opterror(s, err, version, id, catalog);
49414887Schin }
49424887Schin }
49434887Schin }
49444887Schin }
49454887Schin else if (*(s + 1) != '?')
49464887Schin {
49474887Schin opt_info.index--;
49484887Schin pop(psp);
4949*12068SRoger.Faulkner@Oracle.COM return opterror(s, 0, version, id, catalog);
49504887Schin }
49514887Schin opt_info.offset = 0;
49524887Schin optarg:
49534887Schin if (*s == ':' && *(s = skip(s, 0, 0, 0, 1, 0, 1, version)) == GO && *(s = next(s + 1, version)) == '[' && isalnum(*(s + 1)))
49544887Schin {
49554887Schin x = 0;
49564887Schin if (opt_info.arg)
49574887Schin {
49584887Schin do
49594887Schin {
49604887Schin w = y = opt_info.arg;
49614887Schin f = s = next(s + 1, version);
49624887Schin k = *f;
49634887Schin if (k == *w && isalpha(k) && !*(w + 1))
49644887Schin {
49654887Schin x = k;
49664887Schin break;
49674887Schin }
49684887Schin if (*s == '+' || *s == '-')
49694887Schin continue;
49704887Schin else if (*s == '[' || version < 1)
49714887Schin continue;
49724887Schin else
49734887Schin {
49744887Schin if (*s != ':')
49754887Schin s = skip(s, ':', '?', 0, 1, 0, 0, version);
49764887Schin if (*s == ':')
49774887Schin {
49784887Schin if (catalog)
49794887Schin {
49804887Schin p = skip(s + 1, '?', 0, 0, 1, 0, 0, version);
49814887Schin e = sfprints("%-.*s", p - (s + 1), s + 1);
4982*12068SRoger.Faulkner@Oracle.COM b = T(id, catalog, e);
49834887Schin if (b == e)
49844887Schin p = 0;
49854887Schin else
49864887Schin {
49874887Schin sfprintf(xp, ":%s|%s?", b, e);
49884887Schin if (!(s = sfstruse(xp)))
49894887Schin goto nospace;
49904887Schin }
49914887Schin }
49924887Schin else
49934887Schin p = 0;
49944887Schin for (;;)
49954887Schin {
49964887Schin n = m = 0;
49974887Schin e = s + 1;
49984887Schin while (*++s)
49994887Schin {
50004887Schin if (*s == '*' || *s == '\a')
50014887Schin {
50024887Schin if (*s == '\a')
50034887Schin do
50044887Schin {
50054887Schin if (!*++s)
50064887Schin {
50074887Schin s--;
50084887Schin break;
50094887Schin }
50104887Schin } while (*s != '\a');
50114887Schin j = *(s + 1);
50124887Schin if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
50134887Schin {
50144887Schin while (*w)
50154887Schin w++;
50164887Schin m = 0;
50174887Schin break;
50184887Schin }
50194887Schin m = 1;
50204887Schin }
50214887Schin else if (*s == *w || sep(*s) && sep(*w))
50224887Schin w++;
50234887Schin else if (*w == 0)
50244887Schin break;
50254887Schin else if (!sep(*s))
50264887Schin {
50274887Schin if (sep(*w))
50284887Schin {
50294887Schin if (*++w == *s)
50304887Schin {
50314887Schin w++;
50324887Schin continue;
50334887Schin }
50344887Schin }
50354887Schin else if (w == y || sep(*(w - 1)) || isupper(*(w - 1)) && islower(*w))
50364887Schin break;
50374887Schin for (q = s; *q && !sep(*q) && *q != '|' && *q != '?' && *q != ']'; q++);
50384887Schin if (!sep(*q))
50394887Schin break;
50404887Schin for (s = q; w > y && *w != *(s + 1); w--);
50414887Schin }
50424887Schin else if (*w != *(s + 1))
50434887Schin break;
50444887Schin }
50454887Schin if (!*w)
50464887Schin {
50474887Schin nov = 0;
50484887Schin break;
50494887Schin }
50504887Schin if (*(s = skip(s, ':', '|', '?', 1, 0, 0, version)) != '|')
50514887Schin break;
50524887Schin w = y;
50534887Schin }
50544887Schin if (p)
50554887Schin s = p;
50564887Schin if (!*w)
50574887Schin {
50584887Schin if (n)
50594887Schin num = 0;
50604887Schin if (!(n = (m || *s == ':' || *s == '|' || *s == '?' || *s == ']')) && x)
50614887Schin {
50624887Schin pop(psp);
5063*12068SRoger.Faulkner@Oracle.COM return opterror("&", 0, version, id, catalog);
50644887Schin }
50654887Schin for (x = k; *(f + 1) == '|' && (j = *(f + 2)) && j != '!' && j != '=' && j != ':' && j != '?' && j != ']'; f += 2);
50664887Schin if (*f == ':')
50674887Schin x = -1;
50684887Schin else if (*(f + 1) == ':' || *(f + 1) == '!' && *(f + 2) == ':')
50694887Schin /* ok */;
50704887Schin else
50714887Schin {
50724887Schin a = f;
50734887Schin if (*a == '=')
50744887Schin a++;
50754887Schin else
50764887Schin {
50774887Schin if (*(a + 1) == '!')
50784887Schin a++;
50794887Schin if (*(a + 1) == '=')
50804887Schin a += 2;
50814887Schin }
50824887Schin x = -strtol(a, &b, 0);
50834887Schin }
50844887Schin b = e;
50854887Schin a = s = skip(s, 0, 0, 0, 1, 0, 0, version);
50864887Schin if (n)
50874887Schin break;
50884887Schin }
50894887Schin }
50904887Schin }
50914887Schin } while (*(s = skip(s, 0, 0, 0, 1, 0, 1, version)) == '[');
509210898Sroland.mainz@nrubsig.org if (!(opt_info.num = (long)(opt_info.number = x)))
50934887Schin {
50944887Schin pop(psp);
5095*12068SRoger.Faulkner@Oracle.COM return opterror("*", 0, version, id, catalog);
50964887Schin }
50974887Schin }
50984887Schin }
50994887Schin }
51004887Schin else if (w && v)
51014887Schin {
51024887Schin pop(psp);
5103*12068SRoger.Faulkner@Oracle.COM return opterror("=", 0, version, id, catalog);
51044887Schin }
51054887Schin else
51064887Schin {
510710898Sroland.mainz@nrubsig.org opt_info.num = (long)(opt_info.number = num);
51084887Schin if (!w && !argv[opt_info.index][opt_info.offset])
51094887Schin {
51104887Schin opt_info.offset = 0;
51114887Schin opt_info.index++;
51124887Schin }
51134887Schin }
51144887Schin pop(psp);
51154887Schin return c;
51164887Schin help:
51174887Schin if (v && *v == '?' && *(v + 1) == '?' && *(v + 2))
51184887Schin {
51194887Schin s = v + 2;
51204887Schin if ((s[0] == 'n' || s[0] == 'N') && (s[1] == 'o' || s[1] == 'O'))
51214887Schin {
51224887Schin s += 2;
51234887Schin n = -1;
51244887Schin }
51254887Schin else
51264887Schin n = 1;
51274887Schin if (hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), s))
51284887Schin {
51294887Schin if (hp->style < STYLE_man || !(s = argv[opt_info.index]) || s[0] != '-' || s[1] != '-' || !s[2])
51304887Schin {
51314887Schin opt_info.arg = sfprints("\fversion=%d", version);
51324887Schin pop(psp);
51334887Schin return '?';
51344887Schin }
51354887Schin opt_info.state->force = hp->style;
51364887Schin }
5137*12068SRoger.Faulkner@Oracle.COM else if (match(s, "ESC", -1, ID, NiL) || match(s, "EMPHASIS", -1, ID, NiL))
51384887Schin opt_info.state->emphasis = n;
5139*12068SRoger.Faulkner@Oracle.COM else if (match(s, "PREFORMAT", -1, ID, NiL))
51404887Schin opt_info.state->flags |= OPT_preformat;
5141*12068SRoger.Faulkner@Oracle.COM else if (match(s, "TEST", -1, ID, NiL))
51424887Schin {
51434887Schin opt_info.state->width = OPT_WIDTH;
51444887Schin opt_info.state->emphasis = 1;
51454887Schin }
51464887Schin else
51474887Schin {
51484887Schin pop(psp);
5149*12068SRoger.Faulkner@Oracle.COM return opterror(v, 0, version, id, catalog);
51504887Schin }
51514887Schin psp = pop(psp);
51524887Schin if (argv == opt_info.state->strv)
51534887Schin return '#';
51544887Schin goto again;
51554887Schin }
51564887Schin if ((opt_info.arg = opthelp(NiL, v)) == (char*)unknown)
51574887Schin {
51584887Schin pop(psp);
5159*12068SRoger.Faulkner@Oracle.COM return opterror(v, 0, version, id, catalog);
51604887Schin }
51614887Schin pop(psp);
51624887Schin return '?';
51634887Schin nospace:
51644887Schin pop(psp);
5165*12068SRoger.Faulkner@Oracle.COM return opterror(NiL, 0, 0, NiL, NiL);
51664887Schin }
51674887Schin
51684887Schin /*
51694887Schin * parse long options with 0,1,2 leading '-' or '+' from string and pass to optget()
51704887Schin * syntax is the unquoted
51714887Schin *
51724887Schin * <length> [-|+|--|++]<name>[[-+:|&=]=<value>\n (or \0 for the last)
51734887Schin *
51744887Schin * or the quoted
51754887Schin *
51764887Schin * [-|+|--|++][no]name[[-+:|&=]=['"{(]value[)}"']][, ]...
51774887Schin *
51784887Schin * with \x escapes passed to chresc()
51794887Schin *
51804887Schin * return '#' for `label:', with opt_info.name==label
51814887Schin * str[opt_info.offset] next arg
51824887Schin *
51834887Schin * optstr(s, 0)
51844887Schin * return '-' if arg, 0 otherwise
51854887Schin * optstr(0, opts)
51864887Schin * use previous parsed str
51874887Schin */
51884887Schin
51894887Schin int
optstr(const char * str,const char * opts)51904887Schin optstr(const char* str, const char* opts)
51914887Schin {
51924887Schin register char* s = (char*)str;
51934887Schin register Sfio_t* mp;
51944887Schin register int c;
51954887Schin register int ql;
51964887Schin register int qr;
51974887Schin register int qc;
51984887Schin int v;
51994887Schin char* e;
52004887Schin
52014887Schin again:
52024887Schin if (s)
52034887Schin {
52044887Schin if (!(mp = opt_info.state->strp) && !(mp = opt_info.state->strp = sfstropen()))
52054887Schin return 0;
52064887Schin if (opt_info.state->str != s)
52074887Schin opt_info.state->str = s;
52084887Schin else if (opt_info.index == 1)
52094887Schin s += opt_info.offset;
52104887Schin while (*s == ',' || *s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')
52114887Schin s++;
52124887Schin if (!*s)
52134887Schin {
52144887Schin opt_info.state->str = 0;
52154887Schin return 0;
52164887Schin }
52174887Schin if (*s == '-' || *s == '+')
52184887Schin {
52194887Schin c = *s++;
52204887Schin sfputc(mp, c);
52214887Schin if (*s == c)
52224887Schin {
52234887Schin sfputc(mp, c);
52244887Schin s++;
52254887Schin }
52264887Schin }
52274887Schin else
52284887Schin {
52294887Schin sfputc(mp, '-');
52304887Schin sfputc(mp, '-');
52314887Schin }
52324887Schin if (isdigit(*s) && (v = (int)strtol(s, &e, 10)) > 1 && isspace(*e) && --v <= strlen(s) && (s[v] == 0 || s[v] == '\n'))
52334887Schin {
52344887Schin s += v;
52354887Schin while (isspace(*++e));
52364887Schin sfwrite(mp, e, s - e);
52374887Schin }
52384887Schin else
52394887Schin {
52404887Schin while (*s && *s != ',' && *s != ' ' && *s != '\t' && *s != '\n' && *s != '\r' && *s != '=' && *s != ':')
52414887Schin sfputc(mp, *s++);
52424887Schin if ((c = *s) == ':' && *(s + 1) != '=')
52434887Schin {
52444887Schin opt_info.index = 1;
52454887Schin opt_info.offset = ++s - (char*)str;
52464887Schin if (!(s = sfstruse(mp)))
52474887Schin goto nospace;
52484887Schin s += 2;
52494887Schin e = opt_info.name;
52504887Schin while (e < &opt_info.name[sizeof(opt_info.name)-1] && (*e++ = *s++));
52514887Schin opt_info.arg = 0;
525210898Sroland.mainz@nrubsig.org opt_info.num = (long)(opt_info.number = 0);
52534887Schin opt_info.option[0] = ':';
52544887Schin opt_info.option[1] = 0;
52554887Schin return '#';
52564887Schin }
52574887Schin if (c == ':' || c == '=')
52584887Schin {
52594887Schin sfputc(mp, c);
52604887Schin ql = qr = 0;
52614887Schin while (c = *++s)
52624887Schin {
52634887Schin if (c == '\\')
52644887Schin {
52654887Schin sfputc(mp, chresc(s, &e));
52664887Schin s = e - 1;
52674887Schin }
52684887Schin else if (c == qr)
52694887Schin {
52704887Schin if (qr != ql)
52714887Schin sfputc(mp, c);
52724887Schin if (--qc <= 0)
52734887Schin qr = ql = 0;
52744887Schin }
52754887Schin else if (c == ql)
52764887Schin {
52774887Schin sfputc(mp, c);
52784887Schin qc++;
52794887Schin }
52804887Schin else if (qr)
52814887Schin sfputc(mp, c);
52824887Schin else if (c == ',' || c == ' ' || c == '\t' || c == '\n' || c == '\r')
52834887Schin break;
52844887Schin else if (c == '"' || c == '\'')
52854887Schin {
52864887Schin ql = qr = c;
52874887Schin qc = 1;
52884887Schin }
52894887Schin else
52904887Schin {
52914887Schin sfputc(mp, c);
52924887Schin if (c == GO)
52934887Schin {
52944887Schin ql = c;
52954887Schin qr = OG;
52964887Schin qc = 1;
52974887Schin }
52984887Schin else if (c == '(')
52994887Schin {
53004887Schin ql = c;
53014887Schin qr = ')';
53024887Schin qc = 1;
53034887Schin }
53044887Schin }
53054887Schin }
53064887Schin }
53074887Schin }
53084887Schin opt_info.argv = opt_info.state->strv;
53094887Schin opt_info.state->strv[0] = T(NiL, ID, "option");
53104887Schin if (!(opt_info.state->strv[1] = sfstruse(mp)))
53114887Schin goto nospace;
53124887Schin opt_info.state->strv[2] = 0;
53134887Schin opt_info.offset = s - (char*)str;
53144887Schin }
53154887Schin if (opts)
53164887Schin {
53174887Schin if (!opt_info.state->strv[1])
53184887Schin {
53194887Schin opt_info.state->str = 0;
53204887Schin return 0;
53214887Schin }
53224887Schin opt_info.index = 1;
53234887Schin v = opt_info.offset;
53244887Schin opt_info.offset = 0;
53254887Schin c = optget(opt_info.state->strv, opts);
53264887Schin opt_info.index = 1;
53274887Schin opt_info.offset = v;
53284887Schin if (c == '#')
53294887Schin {
53304887Schin s = opt_info.state->str;
53314887Schin goto again;
53324887Schin }
53334887Schin if ((c == '?' || c == ':') && (opt_info.arg[0] == '-' && opt_info.arg[1] == '-'))
53344887Schin opt_info.arg += 2;
53354887Schin s = opt_info.name;
53364887Schin if (*s++ == '-' && *s++ == '-' && *s)
53374887Schin {
53384887Schin e = opt_info.name;
53394887Schin while (*e++ = *s++);
53404887Schin }
53414887Schin }
53424887Schin else
53434887Schin c = '-';
53444887Schin return c;
53454887Schin nospace:
5346*12068SRoger.Faulkner@Oracle.COM return opterror(NiL, 0, 0, NiL, NiL);
53474887Schin }
5348