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* 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* 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* 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* 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* 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 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* 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* 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 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* 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* 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* 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* 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 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 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 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* 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* 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 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* 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* 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 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 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 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 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