14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*10898Sroland.mainz@nrubsig.org * Copyright (c) 1985-2009 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 */ 53*10898Sroland.mainz@nrubsig.org #define OPT_number 0x020 /* arg is strtonll() number */ 54*10898Sroland.mainz@nrubsig.org #define OPT_oneof 0x040 /* arg may be set once */ 55*10898Sroland.mainz@nrubsig.org #define OPT_optional 0x080 /* arg is optional */ 56*10898Sroland.mainz@nrubsig.org #define OPT_string 0x100 /* arg is string */ 574887Schin 584887Schin #define OPT_preformat 0001 /* output preformat string */ 59*10898Sroland.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; 3864887Schin case '\v': 3874887Schin *t++ = '\\'; 3884887Schin c = 'v'; 3894887Schin break; 3904887Schin } 3914887Schin *t++ = c; 3924887Schin } 3934887Schin done: 3944887Schin *t = 0; 3954887Schin return buf; 3964887Schin } 3974887Schin 3984887Schin #endif 3994887Schin 4004887Schin /* 4014887Schin * pop the push stack 4024887Schin */ 4034887Schin 4044887Schin static Push_t* 4054887Schin pop(register Push_t* psp) 4064887Schin { 4074887Schin register Push_t* tsp; 4084887Schin 4094887Schin while (tsp = psp) 4104887Schin { 4114887Schin psp = psp->next; 4124887Schin free(tsp); 4134887Schin } 4144887Schin return 0; 4154887Schin } 4164887Schin 4174887Schin /* 4184887Schin * skip over line space to the next token 4194887Schin */ 4204887Schin 4214887Schin static char* 4224887Schin next(register char* s, int version) 4234887Schin { 4244887Schin register char* b; 4254887Schin 4264887Schin while (*s == '\t' || *s == '\r' || version >= 1 && *s == ' ') 4274887Schin s++; 4284887Schin if (*s == '\n') 4294887Schin { 4304887Schin b = s; 4314887Schin while (*++s == ' ' || *s == '\t' || *s == '\r'); 4324887Schin if (*s == '\n') 4334887Schin return b; 4344887Schin } 4354887Schin return s; 4364887Schin } 4374887Schin 4384887Schin /* 4394887Schin * skip to t1 or t2 or t3, whichever first, in s 4404887Schin * n==0 outside [...] 4414887Schin * n==1 inside [...] before ? 4424887Schin * n==2 inside [...] after ? 4434887Schin * b==0 outside {...} 4444887Schin * b==1 inside {...} 4454887Schin * past skips past the terminator to the next token 4464887Schin * otherwise a pointer to the terminator is returned 4474887Schin * 4484887Schin * ]] for ] inside [...] 4494887Schin * ?? for ? inside [...] before ? 4504887Schin * :: for : inside [...] before ? 4514887Schin */ 4524887Schin 4534887Schin static char* 4544887Schin skip(register char* s, register int t1, register int t2, register int t3, register int n, register int b, int past, int version) 4554887Schin { 4564887Schin register int c; 4574887Schin register int on = n; 4584887Schin register int ob = b; 4594887Schin 4604887Schin if (version < 1) 4614887Schin { 4624887Schin n = n >= 1; 4634887Schin for (;;) 4644887Schin { 4654887Schin switch (*s++) 4664887Schin { 4674887Schin case 0: 4684887Schin break; 4694887Schin case '[': 4704887Schin n++; 4714887Schin continue; 4724887Schin case ']': 4734887Schin if (--n <= 0) 4744887Schin break; 4754887Schin continue; 4764887Schin default: 4774887Schin continue; 4784887Schin } 4794887Schin break; 4804887Schin } 4814887Schin } 4824887Schin else while (c = *s++) 4834887Schin { 4844887Schin 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))); 4854887Schin if (c == '[') 4864887Schin { 4874887Schin if (!n) 4884887Schin n = 1; 4894887Schin } 4904887Schin else if (c == ']') 4914887Schin { 4924887Schin if (n) 4934887Schin { 4944887Schin if (*s == ']') 4954887Schin s++; 4964887Schin else if (on == 1) 4974887Schin break; 4984887Schin else 4994887Schin n = 0; 5004887Schin } 5014887Schin } 5024887Schin else if (c == GO) 5034887Schin { 5044887Schin if (n == 0) 5054887Schin b++; 5064887Schin } 5074887Schin else if (c == OG) 5084887Schin { 5094887Schin if (n == 0 && b-- == ob) 5104887Schin break; 5114887Schin } 5124887Schin else if (c == '?') 5134887Schin { 5144887Schin if (n == 1) 5154887Schin { 5164887Schin if (*s == '?') 5174887Schin s++; 5184887Schin else 5194887Schin { 5204887Schin if (n == on && (c == t1 || c == t2 || c == t3)) 5214887Schin break; 5224887Schin n = 2; 5234887Schin } 5244887Schin } 5254887Schin } 5264887Schin else if (n == on && (c == t1 || c == t2 || c == t3)) 5274887Schin { 5284887Schin if (n == 1 && c == ':' && *s == c) 5294887Schin s++; 5304887Schin else 5314887Schin break; 5324887Schin } 5334887Schin } 5344887Schin return past && *(s - 1) ? next(s, version) : s - 1; 5354887Schin } 5364887Schin 5374887Schin /* 5384887Schin * match s with t 5394887Schin * t translated if possible 5404887Schin * imbedded { - _ ' } ignored 5414887Schin * * separates required prefix from optional suffix 5424887Schin * otherwise prefix match 5434887Schin */ 5444887Schin 5454887Schin static int 5464887Schin match(char* s, char* t, int version, const char* catalog) 5474887Schin { 5484887Schin register char* w; 5494887Schin register char* x; 5504887Schin char* xw; 5514887Schin char* ww; 5524887Schin int n; 5534887Schin int v; 5544887Schin int j; 5554887Schin 5564887Schin for (n = 0; n < 2; n++) 5574887Schin { 5584887Schin if (n) 5594887Schin x = t; 5604887Schin else 5614887Schin { 5624887Schin if (catalog) 5634887Schin { 5644887Schin w = skip(t, ':', '?', 0, 1, 0, 0, version); 5654887Schin w = sfprints("%-.*s", w - t, t); 5664887Schin x = T(error_info.id, catalog, w); 5674887Schin if (x == w) 5684887Schin continue; 5694887Schin } 5704887Schin x = T(NiL, ID, t); 5714887Schin if (x == t) 5724887Schin continue; 5734887Schin } 5744887Schin do 5754887Schin { 5764887Schin v = 0; 5774887Schin xw = x; 5784887Schin w = ww = s; 5794887Schin while (*x && *w) 5804887Schin { 5814887Schin if (isupper(*x)) 5824887Schin xw = x; 5834887Schin if (isupper(*w)) 5844887Schin ww = w; 5854887Schin if (*x == '*' && !v++ || *x == '\a') 5864887Schin { 5874887Schin if (*x == '\a') 5884887Schin do 5894887Schin { 5904887Schin if (!*++x) 5914887Schin { 5924887Schin x--; 5934887Schin break; 5944887Schin } 5954887Schin } while (*x != '\a'); 5964887Schin j = *(x + 1); 5974887Schin if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0) 5984887Schin while (*w) 5994887Schin w++; 6004887Schin } 6014887Schin else if (sep(*x)) 6024887Schin xw = ++x; 6034887Schin else if (sep(*w) && w != s) 6044887Schin ww = ++w; 6054887Schin else if (*x == *w) 6064887Schin { 6074887Schin x++; 6084887Schin w++; 6094887Schin } 6104887Schin else if (w == ww && x == xw) 6114887Schin break; 6124887Schin else 6134887Schin { 6144887Schin if (x != xw) 6154887Schin { 6164887Schin while (*x && !sep(*x) && !isupper(*x)) 6174887Schin x++; 6184887Schin if (!*x) 6194887Schin break; 6204887Schin if (sep(*x)) 6214887Schin x++; 6224887Schin xw = x; 6234887Schin } 6244887Schin while (w > ww && *w != *x) 6254887Schin w--; 6264887Schin } 6274887Schin } 6284887Schin if (!*w) 6294887Schin { 6304887Schin if (!v) 6314887Schin { 6324887Schin for (;;) 6334887Schin { 6344887Schin switch (*x++) 6354887Schin { 6364887Schin case 0: 6374887Schin case ':': 6384887Schin case '|': 6394887Schin case '?': 6404887Schin case ']': 6414887Schin return 1; 6424887Schin case '*': 6434887Schin break; 6444887Schin default: 6454887Schin continue; 6464887Schin } 6474887Schin break; 6484887Schin } 6494887Schin break; 6504887Schin } 6514887Schin return 1; 6524887Schin } 6534887Schin } while (*(x = skip(x, '|', 0, 0, 1, 0, 0, version)) == '|' && x++); 6544887Schin } 6554887Schin return 0; 6564887Schin } 6574887Schin 6584887Schin /* 6594887Schin * prefix search for s in tab with num elements of size 6604887Schin * with optional translation 6614887Schin */ 6624887Schin 6634887Schin static void* 6644887Schin search(const void* tab, size_t num, size_t siz, char* s) 6654887Schin { 6664887Schin register char* p; 6674887Schin register char* e; 6684887Schin 6694887Schin for (e = (p = (char*)tab) + num * siz; p < e; p += siz) 6704887Schin if (match(s, *((char**)p), -1, NiL)) 6714887Schin return (void*)p; 6724887Schin return 0; 6734887Schin } 6744887Schin 6754887Schin /* 6764887Schin * save s and return the saved pointer 6774887Schin */ 6784887Schin 6794887Schin static char* 6804887Schin save(const char* s) 6814887Schin { 6824887Schin Save_t* p; 6838462SApril.Chin@Sun.COM Dtdisc_t* d; 6844887Schin 6854887Schin static Dt_t* dict; 6864887Schin 6874887Schin if (!dict) 6884887Schin { 6898462SApril.Chin@Sun.COM if (!(d = newof(0, Dtdisc_t, 1, 0))) 6908462SApril.Chin@Sun.COM return (char*)s; 6918462SApril.Chin@Sun.COM d->key = offsetof(Save_t, text); 6928462SApril.Chin@Sun.COM if (!(dict = dtopen(d, Dthash))) 6934887Schin return (char*)s; 6944887Schin } 6954887Schin if (!(p = (Save_t*)dtmatch(dict, s))) 6964887Schin { 6974887Schin if (!(p = newof(0, Save_t, 1, strlen(s)))) 6984887Schin return (char*)s; 6994887Schin strcpy(p->text, s); 7004887Schin dtinsert(dict, p); 7014887Schin } 7024887Schin return p->text; 7034887Schin } 7044887Schin 7054887Schin /* 7064887Schin * initialize the attributes for pass p from opt string s 7074887Schin */ 7084887Schin 7094887Schin static int 7104887Schin init(register char* s, Optpass_t* p) 7114887Schin { 7124887Schin register char* t; 7134887Schin register int c; 7144887Schin register int a; 7154887Schin register int n; 7164887Schin 7174887Schin if (!opt_info.state->msgdict) 7184887Schin { 7194887Schin #if !_PACKAGE_astsa 7204887Schin if (!ast.locale.serial) 7214887Schin setlocale(LC_ALL, ""); 7224887Schin #endif 7234887Schin opt_info.state->vp = sfstropen(); 7244887Schin opt_info.state->xp = sfstropen(); 7254887Schin opt_info.state->msgdisc.key = offsetof(Msg_t, text); 7264887Schin opt_info.state->msgdisc.size = -1; 7274887Schin opt_info.state->msgdisc.link = offsetof(Msg_t, link); 7284887Schin if (opt_info.state->msgdict = dtopen(&opt_info.state->msgdisc, Dthash)) 7294887Schin for (n = 0; n < elementsof(C_LC_MESSAGES_libast); n++) 7304887Schin dtinsert(opt_info.state->msgdict, C_LC_MESSAGES_libast + n); 7314887Schin if (!map[OPT_FLAGS[0]]) 7324887Schin for (n = 0, t = OPT_FLAGS; *t; t++) 7334887Schin map[*t] = ++n; 7344887Schin } 7354887Schin #if _BLD_DEBUG 7364887Schin error(-1, "optget debug"); 7374887Schin #endif 7384887Schin p->oopts = s; 7394887Schin p->version = 0; 7404887Schin p->prefix = 2; 7414887Schin p->section = 1; 7424887Schin p->flags = 0; 7434887Schin p->catalog = 0; 7444887Schin s = next(s, 0); 7454887Schin if (*s == ':') 7464887Schin s++; 7474887Schin if (*s == '+') 7484887Schin s++; 7494887Schin s = next(s, 0); 7504887Schin if (*s++ == '[') 7514887Schin { 7524887Schin if (*s == '+') 7534887Schin p->version = 1; 7544887Schin else if (*s++ == '-') 7554887Schin { 7564887Schin if (*s == '?' || *s == ']') 7574887Schin p->version = 1; 7584887Schin else 7594887Schin { 7608462SApril.Chin@Sun.COM if (!isdigit(*s)) 7614887Schin p->version = 1; 7624887Schin else 7638462SApril.Chin@Sun.COM while (isdigit(*s)) 7644887Schin p->version = p->version * 10 + (*s++ - '0'); 7654887Schin while (*s && *s != '?' && *s != ']') 7664887Schin { 7674887Schin c = *s++; 7688462SApril.Chin@Sun.COM if (!isdigit(*s)) 7694887Schin n = 1; 7704887Schin else 7714887Schin { 7724887Schin n = 0; 7738462SApril.Chin@Sun.COM while (isdigit(*s)) 7744887Schin n = n * 10 + (*s++ - '0'); 7754887Schin } 7764887Schin switch (c) 7774887Schin { 7788462SApril.Chin@Sun.COM case '+': 7798462SApril.Chin@Sun.COM p->flags |= OPT_plus; 7808462SApril.Chin@Sun.COM break; 7814887Schin case 'c': 7824887Schin p->flags |= OPT_cache; 7834887Schin break; 7844887Schin case 'i': 7854887Schin p->flags |= OPT_ignore; 7864887Schin break; 7874887Schin case 'l': 7884887Schin p->flags |= OPT_long; 7894887Schin break; 7908462SApril.Chin@Sun.COM case 'n': 7918462SApril.Chin@Sun.COM p->flags |= OPT_numeric; 7928462SApril.Chin@Sun.COM break; 7934887Schin case 'o': 7944887Schin p->flags |= OPT_old; 7954887Schin break; 7964887Schin case 'p': 7974887Schin p->prefix = n; 7984887Schin break; 7994887Schin case 's': 8004887Schin p->section = n; 8014887Schin if (n > 1 && n < 6) 8024887Schin { 8034887Schin p->flags |= OPT_functions; 8044887Schin p->prefix = 0; 8054887Schin } 8064887Schin break; 8074887Schin } 8084887Schin } 8094887Schin } 8104887Schin } 8114887Schin while (*s) 8124887Schin if (*s++ == ']' && *s++ == '[') 8134887Schin { 8144887Schin if (*s++ != '-') 8154887Schin { 8164887Schin if (!error_info.id && strneq(s - 1, "+NAME?", 6)) 8174887Schin { 8184887Schin for (t = s += 5; *t && *t != ' ' && *t != ']'; t++); 8194887Schin error_info.id = save(sfprints("%-.*s", t - s, s)); 8204887Schin } 8214887Schin break; 8224887Schin } 8234887Schin if (*s == '-') 8244887Schin s++; 8254887Schin if (strneq(s, "catalog?", 8)) 8264887Schin { 8274887Schin s += 8; 8284887Schin if ((t = strchr(s, ']')) && (!error_info.id || (t - s) != strlen(error_info.id) || !strneq(s, error_info.id, t - s))) 8294887Schin p->catalog = save(sfprints("%-.*s", t - s, s)); 8304887Schin if (error_info.id) 8314887Schin break; 8324887Schin } 8334887Schin } 8344887Schin } 8354887Schin if (!p->catalog) 8364887Schin { 8374887Schin if (opt_info.disc && opt_info.disc->catalog && (!error_info.id || !streq(opt_info.disc->catalog, error_info.id))) 8384887Schin p->catalog = opt_info.disc->catalog; 8394887Schin else 8404887Schin p->catalog = ID; 8414887Schin } 8424887Schin s = p->oopts; 8434887Schin if (*s == ':') 8444887Schin s++; 8454887Schin if (*s == '+') 8464887Schin { 8474887Schin s++; 8484887Schin p->flags |= OPT_plus; 8494887Schin } 8508462SApril.Chin@Sun.COM s = next(s, 0); 8514887Schin if (*s != '[') 8524887Schin for (t = s, a = 0; *t; t++) 8534887Schin if (!a && *t == '-') 8544887Schin { 8554887Schin p->flags |= OPT_minus; 8564887Schin break; 8574887Schin } 8584887Schin else if (*t == '[') 8594887Schin a++; 8604887Schin else if (*t == ']') 8614887Schin a--; 8624887Schin if (!p->version && (t = strchr(s, '(')) && strchr(t, ')') && (opt_info.state->cp || (opt_info.state->cp = sfstropen()))) 8634887Schin { 8644887Schin /* 8654887Schin * solaris long option compatibility 8664887Schin */ 8674887Schin 8684887Schin p->version = 1; 8694887Schin for (t = p->oopts; t < s; t++) 8704887Schin sfputc(opt_info.state->cp, *t); 8714887Schin n = t - p->oopts; 8724887Schin sfputc(opt_info.state->cp, '['); 8734887Schin sfputc(opt_info.state->cp, '-'); 8744887Schin sfputc(opt_info.state->cp, ']'); 8754887Schin while (c = *s++) 8764887Schin { 8774887Schin sfputc(opt_info.state->cp, '['); 8784887Schin sfputc(opt_info.state->cp, c); 8794887Schin if (a = (c = *s++) == ':') 8804887Schin c = *s++; 8814887Schin if (c == '(') 8824887Schin { 8834887Schin sfputc(opt_info.state->cp, ':'); 8844887Schin for (;;) 8854887Schin { 8864887Schin while ((c = *s++) && c != ')') 8874887Schin sfputc(opt_info.state->cp, c); 8884887Schin if (!c || *s != '(') 8894887Schin break; 8904887Schin sfputc(opt_info.state->cp, '|'); 8914887Schin s++; 8924887Schin } 8934887Schin } 8944887Schin sfputc(opt_info.state->cp, ']'); 8954887Schin if (a) 8964887Schin sfputr(opt_info.state->cp, ":[string]", -1); 8974887Schin if (!c) 8984887Schin break; 8994887Schin } 9004887Schin if (!(p->oopts = s = sfstruse(opt_info.state->cp))) 9014887Schin return -1; 9024887Schin s += n; 9034887Schin } 9044887Schin p->opts = s; 905*10898Sroland.mainz@nrubsig.org message((-1, "version=%d prefix=%d section=%d flags=%04x catalog=%s", p->version, p->prefix, p->section, p->flags, p->catalog)); 9064887Schin return 0; 9074887Schin } 9084887Schin 9094887Schin /* 9104887Schin * return the bold set/unset sequence for style 9114887Schin */ 9124887Schin 9134887Schin static const char* 9144887Schin font(int f, int style, int set) 9154887Schin { 9164887Schin switch (style) 9174887Schin { 9184887Schin case STYLE_html: 9194887Schin return fonts[f].html[set]; 9204887Schin case STYLE_nroff: 9214887Schin return fonts[f].nroff[set]; 9224887Schin case STYLE_short: 9234887Schin case STYLE_long: 9244887Schin case STYLE_posix: 9254887Schin case STYLE_api: 9264887Schin break; 9274887Schin default: 9284887Schin if (opt_info.state->emphasis > 0) 9294887Schin return fonts[f].term[set]; 9304887Schin break; 9314887Schin } 9324887Schin return ""; 9334887Schin } 9344887Schin 9354887Schin /* 9364887Schin * expand \f...\f info 9374887Schin * *p set to next char after second \f 9384887Schin * expanded value returned 9394887Schin */ 9404887Schin 9414887Schin static char* 9424887Schin expand(register char* s, register char* e, char** p, Sfio_t* ip) 9434887Schin { 9444887Schin register int c; 9454887Schin register char* b = s; 9464887Schin int n; 9474887Schin 9484887Schin message((-23, "AHA#%d expand(%s)", __LINE__, show(s))); 9494887Schin n = sfstrtell(ip); 9504887Schin c = 1; 9514887Schin while ((!e || s < e) && (c = *s++) && c != '\f'); 9524887Schin sfwrite(ip, b, s - b - 1); 9534887Schin sfputc(ip, 0); 9544887Schin b = sfstrbase(ip) + n; 9554887Schin message((-23, "AHA#%d expand(%s)", __LINE__, b)); 9564887Schin n = sfstrtell(ip); 9574887Schin if (!c) 9584887Schin s--; 9594887Schin if (*b == '?') 9604887Schin { 9614887Schin if (!*++b || streq(b, "NAME")) 9624887Schin { 9634887Schin if (!(b = error_info.id)) 9644887Schin b = "command"; 9654887Schin sfstrseek(ip, 0, SEEK_SET); 9664887Schin sfputr(ip, b, -1); 9674887Schin n = 0; 9684887Schin } 9694887Schin else 9704887Schin n = 1; 9714887Schin } 9724887Schin else if (!opt_info.disc || !opt_info.disc->infof || (*opt_info.disc->infof)(&opt_info, ip, b, opt_info.disc) < 0) 9734887Schin n = 0; 9744887Schin *p = s; 9754887Schin if (s = sfstruse(ip)) 9764887Schin s += n; 9774887Schin else 9784887Schin s = "error"; 9794887Schin return s; 9804887Schin } 9814887Schin 9824887Schin /* 9834887Schin * push \f...\f info 9844887Schin */ 9854887Schin 9864887Schin static Push_t* 9874887Schin info(Push_t* psp, char* s, char* e, Sfio_t* ip) 9884887Schin { 9894887Schin register char* b; 9904887Schin int n; 9914887Schin Push_t* tsp; 9924887Schin 9934887Schin static Push_t push; 9944887Schin 9954887Schin b = expand(s, e, &s, ip); 9964887Schin n = strlen(b); 9974887Schin if (tsp = newof(0, Push_t, 1, n + 1)) 9984887Schin { 9994887Schin tsp->nb = (char*)(tsp + 1); 10004887Schin tsp->ne = tsp->nb + n; 10014887Schin strcpy(tsp->nb, b); 10024887Schin } 10034887Schin else 10044887Schin tsp = &push; 10054887Schin tsp->next = psp; 10064887Schin tsp->ob = s; 10074887Schin tsp->oe = e; 10084887Schin return tsp; 10094887Schin } 10104887Schin 10114887Schin /* 10124887Schin * push translation 10134887Schin */ 10144887Schin 10154887Schin static Push_t* 10164887Schin localize(Push_t* psp, char* s, char* e, int term, int n, char* catalog, int version, Sfio_t* ip) 10174887Schin { 10184887Schin char* t; 10194887Schin char* u; 10204887Schin Push_t* tsp; 10214887Schin int c; 10224887Schin 10234887Schin t = skip(s, term, 0, 0, n, 0, 0, version); 10244887Schin if (e && t > e) 10254887Schin t = e; 10264887Schin while (s < t) 10274887Schin { 10284887Schin switch (c = *s++) 10294887Schin { 10304887Schin case ':': 10314887Schin case '?': 10324887Schin if (term && *s == c) 10334887Schin s++; 10344887Schin break; 10354887Schin case ']': 10364887Schin if (*s == c) 10374887Schin s++; 10384887Schin break; 10394887Schin } 10404887Schin sfputc(ip, c); 10414887Schin } 10424887Schin if (!(s = sfstruse(ip)) || (u = T(error_info.id, catalog, s)) == s) 10434887Schin return 0; 10444887Schin n = strlen(u); 10454887Schin if (tsp = newof(0, Push_t, 1, n + 1)) 10464887Schin { 10474887Schin tsp->nb = (char*)(tsp + 1); 10484887Schin tsp->ne = tsp->nb + n; 10494887Schin strcpy(tsp->nb, u); 10504887Schin tsp->ob = t; 10514887Schin tsp->oe = e; 10524887Schin tsp->ch = 1; 10534887Schin } 10544887Schin tsp->next = psp; 10554887Schin return tsp; 10564887Schin } 10574887Schin 10584887Schin /* 10594887Schin * output label s from [ ...label...[?...] ] to sp 10604887Schin * 1 returned if the label was translated 10614887Schin */ 10624887Schin 10634887Schin static int 10648462SApril.Chin@Sun.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* catalog) 10654887Schin { 10664887Schin register int c; 10674887Schin register char* t; 10684887Schin register char* e; 10694887Schin int ostyle; 10704887Schin int a; 10714887Schin int i; 10724887Schin char* p; 10734887Schin char* w; 10744887Schin char* y; 10754887Schin int va; 10764887Schin Push_t* tsp; 10774887Schin 10784887Schin int r = 0; 10794887Schin int n = 1; 10804887Schin Push_t* psp = 0; 10814887Schin 10824887Schin if ((ostyle = style) > (STYLE_nroff - (sep <= 0)) && f != FONT_LITERAL) 10834887Schin style = 0; 10844887Schin if (z < 0) 10854887Schin e = s + strlen(s); 10864887Schin else 10874887Schin e = s + z; 10884887Schin if (sep > 0) 10894887Schin { 10904887Schin if (sep == ' ' && style == STYLE_nroff) 10914887Schin sfputc(sp, '\\'); 10924887Schin sfputc(sp, sep); 10934887Schin } 10944887Schin sep = !sep || z < 0; 10954887Schin va = 0; 10964887Schin y = 0; 10978462SApril.Chin@Sun.COM if (about) 10988462SApril.Chin@Sun.COM sfputc(sp, '('); 10994887Schin if (version < 1) 11004887Schin { 11014887Schin a = 0; 11024887Schin for (;;) 11034887Schin { 11044887Schin if (s >= e) 11054887Schin return r; 11064887Schin switch (c = *s++) 11074887Schin { 11084887Schin case '[': 11094887Schin a++; 11104887Schin break; 11114887Schin case ']': 11124887Schin if (--a < 0) 11134887Schin return r; 11144887Schin break; 11154887Schin } 11164887Schin sfputc(sp, c); 11174887Schin } 11184887Schin } 11194887Schin else if (level && (*(p = skip(s, 0, 0, 0, 1, level, 1, version)) == ':' || *p == '#')) 11204887Schin { 11214887Schin va = 0; 11224887Schin if (*++p == '?' || *p == *(p - 1)) 11234887Schin { 11244887Schin p++; 11254887Schin va |= OPT_optional; 11264887Schin } 11274887Schin if (*(p = next(p, version)) == '[') 11284887Schin y = p + 1; 11294887Schin } 11304887Schin if (X(catalog) && (!level || *s == '\a' || *(s - 1) != '+') && 11314887Schin (tsp = localize(psp, s, e, (sep || level) ? '?' : 0, sep || level, catalog, version, ip))) 11324887Schin { 11334887Schin psp= tsp; 11344887Schin s = psp->nb; 11354887Schin e = psp->ne; 11364887Schin r = psp->ch > 0; 11374887Schin } 11384887Schin switch (*s) 11394887Schin { 11404887Schin case '\a': 11414887Schin if (f == FONT_ITALIC) 11424887Schin s++; 11434887Schin f = 0; 11444887Schin break; 11454887Schin case '\b': 11464887Schin if (f == FONT_BOLD) 11474887Schin s++; 11484887Schin f = 0; 11494887Schin break; 11504887Schin case '\v': 11514887Schin if (f == FONT_LITERAL) 11524887Schin s++; 11534887Schin f = 0; 11544887Schin break; 11554887Schin default: 11564887Schin if (f) 11574887Schin sfputr(sp, font(f, style, 1), -1); 11584887Schin break; 11594887Schin } 11604887Schin for (;;) 11614887Schin { 11624887Schin if (s >= e) 11634887Schin { 11644887Schin if (!(tsp = psp)) 11654887Schin goto restore; 11664887Schin s = psp->ob; 11674887Schin e = psp->oe; 11684887Schin psp = psp->next; 11694887Schin free(tsp); 11704887Schin continue; 11714887Schin } 11724887Schin switch (c = *s++) 11734887Schin { 11744887Schin case '(': 11754887Schin if (n) 11764887Schin { 11774887Schin n = 0; 11784887Schin if (f) 11794887Schin { 11804887Schin sfputr(sp, font(f, style, 0), -1); 11814887Schin f = 0; 11824887Schin } 11834887Schin } 11844887Schin break; 11854887Schin case '?': 11864887Schin case ':': 11874887Schin case ']': 11884887Schin if (psp && psp->ch) 11894887Schin break; 11904887Schin if (y) 11914887Schin { 11924887Schin if (va & OPT_optional) 11934887Schin sfputc(sp, '['); 11944887Schin sfputc(sp, '='); 11958462SApril.Chin@Sun.COM label(sp, 0, y, 0, -1, 0, style, FONT_ITALIC, ip, version, catalog); 11964887Schin if (va & OPT_optional) 11974887Schin sfputc(sp, ']'); 11984887Schin y = 0; 11994887Schin } 12004887Schin switch (c) 12014887Schin { 12024887Schin case '?': 12034887Schin if (*s == '?') 12044887Schin s++; 12054887Schin else if (*s == ']' && *(s + 1) != ']') 12064887Schin continue; 12074887Schin else if (sep) 12084887Schin goto restore; 12094887Schin else if (X(catalog) && (tsp = localize(psp, s, e, 0, 1, catalog, version, ip))) 12104887Schin { 12114887Schin psp = tsp; 12124887Schin s = psp->nb; 12134887Schin e = psp->ne; 12144887Schin } 12154887Schin break; 12164887Schin case ']': 12174887Schin if (sep && *s++ != ']') 12184887Schin goto restore; 12194887Schin break; 12204887Schin case ':': 12214887Schin if (sep && *s++ != ':') 12224887Schin goto restore; 12234887Schin break; 12244887Schin } 12254887Schin break; 12264887Schin case '\a': 12274887Schin a = FONT_ITALIC; 12284887Schin setfont: 12294887Schin if (f & ~a) 12304887Schin { 12314887Schin sfputr(sp, font(f, style, 0), -1); 12324887Schin f = 0; 12334887Schin } 12344887Schin if (!f && style == STYLE_html) 12354887Schin { 12364887Schin for (t = s; t < e && !isspace(*t) && !iscntrl(*t); t++); 12374887Schin if (*t == c && *++t == '(') 12384887Schin { 12394887Schin w = t; 12404887Schin while (++t < e && isdigit(*t)); 12414887Schin if (t < e && *t == ')' && t > w + 1) 12424887Schin { 12434887Schin sfprintf(sp, "<NOBR><A href=\"../man%-.*s/%-.*s.html\">%s%-.*s%s</A>%-.*s</NOBR>" 12444887Schin , t - w - 1, w + 1 12454887Schin , w - s - 1, s 12464887Schin , font(a, style, 1) 12474887Schin , w - s - 1, s 12484887Schin , font(a, style, 0) 12494887Schin , t - w + 1, w 12504887Schin ); 12514887Schin s = t + 1; 12524887Schin continue; 12534887Schin } 12544887Schin } 12554887Schin } 12564887Schin sfputr(sp, font(a, style, !!(f ^= a)), -1); 12574887Schin continue; 12584887Schin case '\b': 12594887Schin a = FONT_BOLD; 12604887Schin goto setfont; 12614887Schin case '\f': 12624887Schin psp = info(psp, s, e, ip); 12634887Schin if (psp->nb) 12644887Schin { 12654887Schin s = psp->nb; 12664887Schin e = psp->ne; 12674887Schin } 12684887Schin else 12694887Schin { 12704887Schin s = psp->ob; 12714887Schin psp = psp->next; 12724887Schin } 12734887Schin continue; 12744887Schin case '\n': 12754887Schin sfputc(sp, c); 12764887Schin for (i = 0; i < level; i++) 12774887Schin sfputc(sp, '\t'); 12784887Schin continue; 12794887Schin case '\v': 12804887Schin a = FONT_LITERAL; 12814887Schin goto setfont; 12824887Schin case '<': 12834887Schin if (style == STYLE_html) 12844887Schin { 12854887Schin sfputr(sp, "<", -1); 12864887Schin c = 0; 12874887Schin for (t = s; t < e; t++) 12884887Schin if (!isalnum(*t) && *t != '_' && *t != '.' && *t != '-') 12894887Schin { 12904887Schin if (*t == '@') 12914887Schin { 12924887Schin if (c) 12934887Schin break; 12944887Schin c = 1; 12954887Schin } 12964887Schin else if (*t == '>') 12974887Schin { 12984887Schin if (c) 12994887Schin { 13004887Schin sfprintf(sp, "<A href=\"mailto:%-.*s>%-.*s</A>>", t - s, s, t - s, s); 13014887Schin s = t + 1; 13024887Schin } 13034887Schin break; 13044887Schin } 13054887Schin else 13064887Schin break; 13074887Schin } 13084887Schin continue; 13094887Schin } 13104887Schin break; 13114887Schin case '>': 13124887Schin if (style == STYLE_html) 13134887Schin { 13144887Schin sfputr(sp, ">", -1); 13154887Schin continue; 13164887Schin } 13174887Schin break; 13184887Schin case '&': 13194887Schin if (style == STYLE_html) 13204887Schin { 13214887Schin sfputr(sp, "&", -1); 13224887Schin continue; 13234887Schin } 13244887Schin break; 13254887Schin case '-': 13264887Schin if (ostyle == STYLE_nroff) 13274887Schin sfputc(sp, '\\'); 13284887Schin break; 13294887Schin case '.': 13304887Schin if (ostyle == STYLE_nroff) 13314887Schin { 13324887Schin sfputc(sp, '\\'); 13334887Schin sfputc(sp, '&'); 13344887Schin } 13354887Schin break; 13364887Schin case '\\': 13374887Schin if (ostyle == STYLE_nroff) 13384887Schin { 13394887Schin c = 'e'; 13404887Schin sfputc(sp, '\\'); 13414887Schin } 13424887Schin break; 13434887Schin case ' ': 13444887Schin if (ostyle == STYLE_nroff) 13454887Schin sfputc(sp, '\\'); 13464887Schin break; 13474887Schin } 13484887Schin sfputc(sp, c); 13494887Schin } 13504887Schin restore: 13514887Schin if (f) 13524887Schin sfputr(sp, font(f, style, 0), -1); 13538462SApril.Chin@Sun.COM if (about) 13548462SApril.Chin@Sun.COM sfputc(sp, ')'); 13554887Schin if (psp) 13564887Schin pop(psp); 13574887Schin return r; 13584887Schin } 13594887Schin 13604887Schin /* 13614887Schin * output args description to sp from p of length n 13624887Schin */ 13634887Schin 13644887Schin static void 13654887Schin args(register Sfio_t* sp, register char* p, register int n, int flags, int style, Sfio_t* ip, int version, char* catalog) 13664887Schin { 13674887Schin register int i; 13684887Schin register char* t; 13694887Schin register char* o; 13704887Schin register char* a = 0; 13714887Schin char* b; 13724887Schin int sep; 13734887Schin 13744887Schin if (flags & OPT_functions) 13754887Schin sep = '\t'; 13764887Schin else 13774887Schin { 13784887Schin sep = ' '; 13794887Schin o = T(NiL, ID, "options"); 13804887Schin b = style == STYLE_nroff ? "\\ " : " "; 13814887Schin for (;;) 13824887Schin { 13834887Schin t = (char*)memchr(p, '\n', n); 13844887Schin if (style >= STYLE_man) 13854887Schin { 13864887Schin if (!(a = error_info.id)) 13874887Schin a = "..."; 13884887Schin 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); 13894887Schin } 13904887Schin else if (a) 13914887Schin 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); 13924887Schin else 13934887Schin { 13944887Schin if (!(a = error_info.id)) 13954887Schin a = "..."; 13964887Schin if (!sfstrtell(sp)) 13974887Schin sfprintf(sp, "[%s%s%s]", b, o, b); 13984887Schin } 13994887Schin if (!t) 14004887Schin break; 14014887Schin i = ++t - p; 14024887Schin if (i) 14034887Schin { 14044887Schin sfputr(sp, b, -1); 14054887Schin if (X(catalog)) 14064887Schin { 14074887Schin sfwrite(ip, p, i); 14084887Schin if (b = sfstruse(ip)) 14094887Schin sfputr(sp, T(error_info.id, catalog, b), -1); 14104887Schin else 14114887Schin sfwrite(sp, p, i); 14124887Schin } 14134887Schin else 14144887Schin sfwrite(sp, p, i); 14154887Schin } 14164887Schin if (style == STYLE_html) 14174887Schin sfputr(sp, "<BR>", '\n'); 14184887Schin else if (style == STYLE_nroff) 14194887Schin sfputr(sp, ".br", '\n'); 14204887Schin else if (style == STYLE_api) 14214887Schin sfputr(sp, ".BR", '\n'); 14224887Schin p = t; 14234887Schin n -= i; 14244887Schin while (n > 0 && (*p == ' ' || *p == '\t')) 14254887Schin { 14264887Schin p++; 14274887Schin n--; 14284887Schin } 14294887Schin } 14304887Schin } 14314887Schin if (n) 14328462SApril.Chin@Sun.COM label(sp, sep, p, 0, n, 0, style, 0, ip, version, catalog); 14334887Schin } 14344887Schin 14354887Schin /* 14364887Schin * output [+-...label...?...] label s to sp 14374887Schin * according to {...} level and style 14384887Schin * return 0:header 1:paragraph 14394887Schin */ 14404887Schin 14414887Schin static int 14428462SApril.Chin@Sun.COM item(Sfio_t* sp, char* s, int about, int level, int style, Sfio_t* ip, int version, char* catalog) 14434887Schin { 14444887Schin register char* t; 14454887Schin int n; 14464887Schin int par; 14474887Schin 14484887Schin sfputc(sp, '\n'); 14494887Schin if (*s == '\n') 14504887Schin { 14514887Schin par = 0; 14524887Schin if (style >= STYLE_nroff) 14534887Schin sfprintf(sp, ".DS\n"); 14544887Schin else 14554887Schin { 14564887Schin if (style == STYLE_html) 14574887Schin sfprintf(sp, "<PRE>\n"); 14584887Schin else 14594887Schin sfputc(sp, '\n'); 14604887Schin for (n = 0; n < level; n++) 14614887Schin sfputc(sp, '\t'); 14624887Schin } 14638462SApril.Chin@Sun.COM label(sp, 0, s + 1, about, -1, level, style, FONT_LITERAL, ip, version, catalog); 14644887Schin sfputc(sp, '\n'); 14654887Schin if (style >= STYLE_nroff) 14664887Schin sfprintf(sp, ".DE"); 14674887Schin else if (style == STYLE_html) 14684887Schin sfprintf(sp, "</PRE>"); 14694887Schin } 14704887Schin else if (*s != ']' && (*s != '?' || *(s + 1) == '?')) 14714887Schin { 14724887Schin par = 0; 14734887Schin if (level) 14744887Schin { 14754887Schin if (style >= STYLE_nroff) 14768462SApril.Chin@Sun.COM sfprintf(sp, ".H%d ", (level - (level > 2)) / 2); 14774887Schin else 14784887Schin for (n = 0; n < level; n++) 14794887Schin sfputc(sp, '\t'); 14804887Schin } 14814887Schin if (style == STYLE_html) 14824887Schin { 14834887Schin if (!level) 14844887Schin sfputr(sp, "<H4>", -1); 14854887Schin sfputr(sp, "<A name=\"", -1); 14864887Schin 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] == '?') 14874887Schin for (t = s + 8; *t && *t != ']'; t++) 14884887Schin if (t[0] == 'p' && (!strncmp(t, "proprietary", 11) || !strncmp(t, "private", 7)) || t[0] == 'n' && !strncmp(t, "noncommercial", 13)) 14894887Schin { 14904887Schin opt_info.state->flags |= OPT_proprietary; 14914887Schin break; 14924887Schin } 14938462SApril.Chin@Sun.COM label(sp, 0, s, about, -1, level, 0, 0, ip, version, catalog); 14944887Schin sfputr(sp, "\">", -1); 14958462SApril.Chin@Sun.COM label(sp, 0, s, about, -1, level, style, level ? FONT_BOLD : 0, ip, version, catalog); 14964887Schin sfputr(sp, "</A>", -1); 14974887Schin if (!level) 14984887Schin sfputr(sp, "</H4>", -1); 14994887Schin } 15004887Schin else 15014887Schin { 15024887Schin if (!level) 15034887Schin { 15044887Schin if (style >= STYLE_nroff) 15054887Schin sfprintf(sp, ".SH "); 15064887Schin else if (style == STYLE_man) 15074887Schin sfputc(sp, '\n'); 15084887Schin else if (style != STYLE_options && style != STYLE_match || *s == '-' || *s == '+') 15094887Schin sfputc(sp, '\t'); 15104887Schin } 15118462SApril.Chin@Sun.COM label(sp, 0, s, about, -1, level, style, FONT_BOLD, ip, version, catalog); 15124887Schin } 15134887Schin } 15144887Schin else 15154887Schin { 15164887Schin par = 1; 15174887Schin if (style >= STYLE_nroff) 15188462SApril.Chin@Sun.COM sfputr(sp, level ? ".SP" : ".PP", -1); 15194887Schin } 15204887Schin if (style >= STYLE_nroff || !level) 15214887Schin sfputc(sp, '\n'); 15224887Schin if (par && style < STYLE_nroff) 15234887Schin for (n = 0; n < level; n++) 15244887Schin sfputc(sp, '\t'); 15254887Schin return par; 15264887Schin } 15274887Schin 15284887Schin /* 15294887Schin * output text to sp from p according to style 15304887Schin */ 15314887Schin 15324887Schin static char* 15334887Schin textout(Sfio_t* sp, register char* p, int style, int level, int bump, Sfio_t* ip, int version, char* catalog) 15344887Schin { 15354887Schin #if 0 15364887Schin #define textout(a,b,c,d,e,f,g,h) (sfprintf(a,"(%d)",__LINE__),textout(a,b,c,d,e,f,g,h)) 15374887Schin #endif 15384887Schin register char* t; 15394887Schin register int c; 15404887Schin register int n; 15414887Schin char* e; 15424887Schin int a; 15434887Schin int f; 15444887Schin int par; 15458462SApril.Chin@Sun.COM int about; 15464887Schin Push_t* tsp; 15474887Schin 15484887Schin int ident = 0; 15494887Schin int lev = level; 15504887Schin Push_t* psp = 0; 15514887Schin 15524887Schin again: 15538462SApril.Chin@Sun.COM about = 0; 15544887Schin if ((c = *p) == GO) 15554887Schin { 15564887Schin for (;;) 15574887Schin { 15584887Schin while (*(p = next(p + 1, version)) == '\n'); 15594887Schin if (*p == GO) 15604887Schin { 15614887Schin if (level > 1) 15624887Schin level++; 15634887Schin level++; 15644887Schin } 15654887Schin else if (*p != OG) 15664887Schin { 15678462SApril.Chin@Sun.COM if (level <= 1 || *p != '[' || *(p + 1) != '-' || style == STYLE_man && *(p + 2) == '?' || isalpha(*(p + 2))) 15684887Schin break; 15694887Schin p = skip(p, 0, 0, 0, 1, level, 0, version); 15704887Schin } 15714887Schin else if ((level -= 2) <= lev) 15724887Schin return p + 1; 15734887Schin } 15744887Schin if (*p == '\f') 15754887Schin { 15764887Schin psp = info(psp, p + 1, NiL, ip); 15774887Schin if (psp->nb) 15784887Schin p = psp->nb; 15794887Schin else 15804887Schin { 15814887Schin p = psp->ob; 15824887Schin psp = psp->next; 15834887Schin } 15844887Schin } 15854887Schin if (*p != '[') 15864887Schin return p; 15874887Schin c = *++p; 15884887Schin if (level > 1) 15894887Schin level++; 15904887Schin level++; 15914887Schin } 15924887Schin if (c == '-' && level > 1) 15938462SApril.Chin@Sun.COM { 15948462SApril.Chin@Sun.COM if (style == STYLE_man) 15958462SApril.Chin@Sun.COM { 15968462SApril.Chin@Sun.COM about = 1; 15978462SApril.Chin@Sun.COM if (*(p + 1) == '-') 15988462SApril.Chin@Sun.COM p++; 15998462SApril.Chin@Sun.COM } 16008462SApril.Chin@Sun.COM else 16018462SApril.Chin@Sun.COM for (;;) 16028462SApril.Chin@Sun.COM { 16038462SApril.Chin@Sun.COM p = skip(p, 0, 0, 0, 1, level, 0, version); 16048462SApril.Chin@Sun.COM while (*(p = next(p + 1, version)) == '\n'); 16058462SApril.Chin@Sun.COM if (*p == '[') 16068462SApril.Chin@Sun.COM { 16078462SApril.Chin@Sun.COM if ((c = *++p) != '-') 16088462SApril.Chin@Sun.COM break; 16098462SApril.Chin@Sun.COM } 16108462SApril.Chin@Sun.COM else if (*p == GO) 16118462SApril.Chin@Sun.COM goto again; 16128462SApril.Chin@Sun.COM else if (*p == OG) 16138462SApril.Chin@Sun.COM return p + 1; 16148462SApril.Chin@Sun.COM } 16158462SApril.Chin@Sun.COM } 16164887Schin if (c == '+' || c == '-' && (bump = 3) || c != ' ' && level > 1) 16174887Schin { 16184887Schin p = skip(t = p + 1, '?', 0, 0, 1, level, 0, version); 16198462SApril.Chin@Sun.COM if (c == '-' && (*t == '?' || isdigit(*t) || *p == '?' && *(p + 1) == '\n')) 16204887Schin { 16214887Schin if ((c = *p) != '?') 16224887Schin return skip(p, 0, 0, 0, 1, level, 1, version); 16238462SApril.Chin@Sun.COM e = C("version"); 16248462SApril.Chin@Sun.COM par = item(sp, e, about, level, style, ip, version, ID); 16254887Schin for (;;) 16264887Schin { 16274887Schin while (isspace(*(p + 1))) 16284887Schin p++; 16294887Schin e = p; 16304887Schin if (e[1] == '@' && e[2] == '(' && e[3] == '#' && e[4] == ')') 16314887Schin p = e + 4; 16324887Schin else if (e[1] == '$' && e[2] == 'I' && e[3] == 'd' && e[4] == ':' && e[5] == ' ') 16334887Schin { 16344887Schin p = e + 5; 16354887Schin ident = 1; 16364887Schin } 16374887Schin else 16384887Schin break; 16394887Schin } 16404887Schin } 16414887Schin else 16424887Schin { 16434887Schin if (isdigit(c) && isdigit(*t)) 16444887Schin { 16454887Schin while (isdigit(*t)) 16464887Schin t++; 16474887Schin if (*t == ':') 16484887Schin t++; 16494887Schin } 16504887Schin else if (isalnum(c) && *t-- == ':') 16514887Schin { 16524887Schin if (X(catalog) || *t == *(t + 2)) 16534887Schin t += 2; 16544887Schin else 16554887Schin { 16564887Schin sfprintf(ip, "%s", t); 16574887Schin if (e = sfstruse(ip)) 16584887Schin *((t = e) + 1) = '|'; 16594887Schin } 16604887Schin } 16618462SApril.Chin@Sun.COM par = item(sp, t, about, level, style, ip, version, catalog); 16624887Schin c = *p; 16634887Schin } 16648462SApril.Chin@Sun.COM if (!about && level) 16654887Schin par = 0; 16664887Schin } 16674887Schin else 16684887Schin { 16694887Schin if (style >= STYLE_nroff) 16704887Schin sfputc(sp, '\n'); 16714887Schin else if (c == '?') 16724887Schin for (n = 0; n < level; n++) 16734887Schin sfputc(sp, '\t'); 16744887Schin par = 0; 16754887Schin } 16764887Schin if (c == ':') 16774887Schin c = *(p = skip(p, '?', 0, 0, 1, 0, 0, version)); 16784887Schin if ((c == ']' || c == '?' && *(p + 1) == ']' && *(p + 2) != ']' && p++) && (c = *(p = next(p + 1, version))) == GO) 16794887Schin p = textout(sp, p, style, level + bump + par + 1, 0, ip, version, catalog); 16804887Schin else if (c == '?' || c == ' ') 16814887Schin { 16824887Schin p++; 16834887Schin if (c == ' ') 16844887Schin sfputc(sp, c); 16854887Schin else 16864887Schin { 16874887Schin if (X(catalog) && (tsp = localize(psp, p, NiL, 0, 1, catalog, version, ip))) 16884887Schin { 16894887Schin psp = tsp; 16904887Schin p = psp->nb; 16914887Schin } 16924887Schin if (style < STYLE_nroff) 16934887Schin for (n = 0; n < bump + 1; n++) 16944887Schin sfputc(sp, '\t'); 16954887Schin } 16964887Schin f = 0; 16974887Schin for (;;) 16984887Schin { 16994887Schin switch (c = *p++) 17004887Schin { 17014887Schin case 0: 17024887Schin if (!(tsp = psp)) 17034887Schin { 17044887Schin if (f) 17054887Schin sfputr(sp, font(f, style, 0), -1); 17064887Schin return p - 1; 17074887Schin } 17084887Schin p = psp->ob; 17094887Schin psp = psp->next; 17104887Schin free(tsp); 17114887Schin continue; 17124887Schin case ']': 17134887Schin if (psp && psp->ch) 17144887Schin break; 17154887Schin if (*p != ']') 17164887Schin { 17174887Schin if (f) 17184887Schin { 17194887Schin sfputr(sp, font(f, style, 0), -1); 17204887Schin f = 0; 17214887Schin } 17224887Schin for (;;) 17234887Schin { 17244887Schin if ((*p == '#' || *p == ':') && level > lev) 17254887Schin { 17264887Schin char* o; 17274887Schin char* v; 17284887Schin int j; 17294887Schin int m; 17304887Schin int ol; 17314887Schin int vl; 17324887Schin 17334887Schin a = 0; 17344887Schin o = 0; 17354887Schin v = 0; 17364887Schin if (*++p == '?' || *p == *(p - 1)) 17374887Schin { 17384887Schin p++; 17394887Schin a |= OPT_optional; 17404887Schin } 17414887Schin if (*(p = next(p, version)) == '[') 17424887Schin { 17434887Schin p = skip(p + 1, ':', '?', 0, 1, 0, 0, version); 17444887Schin while (*p == ':') 17454887Schin { 17464887Schin p = skip(t = p + 1, ':', '?', 0, 1, 0, 0, version); 17474887Schin m = p - t; 17484887Schin if (*t == '!') 17494887Schin { 17504887Schin o = t + 1; 17514887Schin ol = m - 1; 17524887Schin } 17534887Schin else if (*t == '=') 17544887Schin { 17554887Schin v = t + 1; 17564887Schin vl = m - 1; 17574887Schin } 17584887Schin else 17594887Schin for (j = 0; j < elementsof(attrs); j++) 17604887Schin if (strneq(t, attrs[j].name, m)) 17614887Schin { 17624887Schin a |= attrs[j].flag; 17634887Schin break; 17644887Schin } 17654887Schin } 17664887Schin } 17674887Schin if (a & OPT_optional) 17684887Schin { 17694887Schin if (o) 17704887Schin { 17714887Schin sfprintf(sp, " %s ", T(NiL, ID, "If the option value is omitted then")); 17724887Schin sfputr(sp, font(FONT_BOLD, style, 1), -1); 17734887Schin t = o + ol; 17744887Schin while (o < t) 17754887Schin { 17764887Schin if (((c = *o++) == ':' || c == '?') && *o == c) 17774887Schin o++; 17784887Schin sfputc(sp, c); 17794887Schin } 17804887Schin sfputr(sp, font(FONT_BOLD, style, 0), -1); 17814887Schin sfprintf(sp, " %s.", T(NiL, ID, "is assumed")); 17824887Schin } 17834887Schin else 17844887Schin sfprintf(sp, " %s", T(NiL, ID, "The option value may be omitted.")); 17854887Schin } 17864887Schin if (v) 17874887Schin { 17884887Schin sfprintf(sp, " %s ", T(NiL, ID, "The default value is")); 17894887Schin sfputr(sp, font(FONT_BOLD, style, 1), -1); 17904887Schin t = v + vl; 17914887Schin while (v < t) 17924887Schin { 17934887Schin if (((c = *v++) == ':' || c == '?') && *v == c) 17944887Schin v++; 17954887Schin sfputc(sp, c); 17964887Schin } 17974887Schin sfputr(sp, font(FONT_BOLD, style, 0), -1); 17984887Schin sfputc(sp, '.'); 17994887Schin } 18004887Schin p = skip(p, 0, 0, 0, 1, 0, 1, version); 18014887Schin } 18024887Schin if (*(p = next(p, version)) == GO) 18034887Schin p = textout(sp, p, style, level + bump + !level, 0, ip, version, catalog); 18044887Schin else if (*p == '[' && level > lev) 18054887Schin { 18064887Schin p++; 18074887Schin goto again; 18084887Schin } 18094887Schin else if (*p == '\f') 18104887Schin { 18114887Schin p++; 18124887Schin if (style != STYLE_keys) 18134887Schin { 18144887Schin psp = info(psp, p, NiL, ip); 18154887Schin if (psp->nb) 18164887Schin p = psp->nb; 18174887Schin else 18184887Schin { 18194887Schin p = psp->ob; 18204887Schin psp = psp->next; 18214887Schin } 18224887Schin } 18234887Schin } 18244887Schin else if (!*p) 18254887Schin { 18264887Schin if (!(tsp = psp)) 18274887Schin break; 18284887Schin p = psp->ob; 18294887Schin psp = psp->next; 18304887Schin free(tsp); 18314887Schin } 18324887Schin else if (*p != OG) 18334887Schin break; 18344887Schin else 18354887Schin { 18364887Schin p++; 18374887Schin if ((level -= 2) <= lev) 18384887Schin break; 18394887Schin } 18404887Schin } 18414887Schin return p; 18424887Schin } 18434887Schin p++; 18444887Schin break; 18454887Schin case '\a': 18464887Schin a = FONT_ITALIC; 18474887Schin setfont: 18484887Schin if (f & ~a) 18494887Schin { 18504887Schin sfputr(sp, font(f, style, 0), -1); 18514887Schin f = 0; 18524887Schin } 18534887Schin if (!f && style == STYLE_html) 18544887Schin { 18554887Schin for (t = p; *t && !isspace(*t) && !iscntrl(*t); t++); 18564887Schin if (*t == c && *++t == '(') 18574887Schin { 18584887Schin e = t; 18594887Schin while (isdigit(*++t)); 18604887Schin if (*t == ')' && t > e + 1) 18614887Schin { 18624887Schin sfprintf(sp, "<NOBR><A href=\"../man%-.*s/%-.*s.html\">%s%-.*s%s</A>%-.*s</NOBR>" 18634887Schin , t - e - 1, e + 1 18644887Schin , e - p - 1, p 18654887Schin , font(a, style, 1) 18664887Schin , e - p - 1, p 18674887Schin , font(a, style, 0) 18684887Schin , t - e + 1, e 18694887Schin ); 18704887Schin p = t + 1; 18714887Schin continue; 18724887Schin } 18734887Schin } 18744887Schin } 18754887Schin sfputr(sp, font(a, style, !!(f ^= a)), -1); 18764887Schin continue; 18774887Schin case '\b': 18784887Schin a = FONT_BOLD; 18794887Schin goto setfont; 18804887Schin case '\f': 18814887Schin if (style != STYLE_keys) 18824887Schin { 18834887Schin psp = info(psp, p, NiL, ip); 18844887Schin if (psp->nb) 18854887Schin p = psp->nb; 18864887Schin else 18874887Schin { 18884887Schin p = psp->ob; 18894887Schin psp = psp->next; 18904887Schin } 18914887Schin } 18924887Schin continue; 18934887Schin case '\v': 18944887Schin a = FONT_LITERAL; 18954887Schin goto setfont; 18964887Schin case ' ': 18974887Schin if (ident && *p == '$') 18984887Schin { 18994887Schin while (*++p) 19004887Schin if (*p == ']') 19014887Schin { 19024887Schin if (*(p + 1) != ']') 19034887Schin break; 19044887Schin p++; 19054887Schin } 19064887Schin continue; 19074887Schin } 19084887Schin case '\n': 19094887Schin case '\r': 19104887Schin case '\t': 19114887Schin while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') 19124887Schin p++; 19134887Schin if (*p == ']' && *(p + 1) != ']' && (!psp || !psp->ch)) 19144887Schin continue; 19154887Schin c = ' '; 19164887Schin break; 19174887Schin case '<': 19184887Schin if (style == STYLE_html) 19194887Schin { 19204887Schin sfputr(sp, "<", -1); 19214887Schin c = 0; 19224887Schin for (t = p; *t; t++) 19234887Schin if (!isalnum(*t) && *t != '_' && *t != '.' && *t != '-') 19244887Schin { 19254887Schin if (*t == '@') 19264887Schin { 19274887Schin if (c) 19284887Schin break; 19294887Schin c = 1; 19304887Schin } 19314887Schin else if (*t == '>') 19324887Schin { 19334887Schin if (c) 19344887Schin { 19354887Schin sfprintf(sp, "<A href=\"mailto:%-.*s\">%-.*s</A>>", t - p, p, t - p, p); 19364887Schin p = t + 1; 19374887Schin } 19384887Schin break; 19394887Schin } 19404887Schin else 19414887Schin break; 19424887Schin } 19434887Schin continue; 19444887Schin } 19454887Schin break; 19464887Schin case '>': 19474887Schin if (style == STYLE_html) 19484887Schin { 19494887Schin sfputr(sp, ">", -1); 19504887Schin continue; 19514887Schin } 19524887Schin break; 19534887Schin case '&': 19544887Schin if (style == STYLE_html) 19554887Schin { 19564887Schin sfputr(sp, "&", -1); 19574887Schin continue; 19584887Schin } 19594887Schin break; 19604887Schin case '-': 19614887Schin if (style == STYLE_nroff) 19624887Schin sfputc(sp, '\\'); 19634887Schin break; 19644887Schin case '.': 19654887Schin if (style == STYLE_nroff) 19664887Schin { 19674887Schin sfputc(sp, '\\'); 19684887Schin sfputc(sp, '&'); 19694887Schin } 19704887Schin break; 19714887Schin case '\\': 19724887Schin if (style == STYLE_nroff) 19734887Schin { 19744887Schin sfputc(sp, c); 19754887Schin c = 'e'; 19764887Schin } 19774887Schin break; 19784887Schin } 19794887Schin sfputc(sp, c); 19804887Schin } 19814887Schin } 19824887Schin else if (c == '[' && level > lev) 19834887Schin { 19844887Schin p++; 19854887Schin goto again; 19864887Schin } 19874887Schin return p; 19884887Schin } 19894887Schin 19904887Schin /* 19914887Schin * generate optget() help [...] list from lp 19924887Schin */ 19934887Schin 19944887Schin static void 19954887Schin list(Sfio_t* sp, register const List_t* lp) 19964887Schin { 19974887Schin sfprintf(sp, "[%c", lp->type); 19984887Schin if (lp->name) 19994887Schin { 20004887Schin sfprintf(sp, "%s", lp->name); 20014887Schin if (lp->text) 20024887Schin sfprintf(sp, "?%s", lp->text); 20034887Schin } 20044887Schin sfputc(sp, ']'); 20054887Schin } 20064887Schin 20074887Schin /* 20084887Schin * return pointer to help message sans `Usage: command' 20094887Schin * if oopts is 0 then opt_info.state->pass is used 20104887Schin * what: 20114887Schin * 0 ?short by default, ?long if any long options used 20124887Schin * * otherwise see help_text[] (--???) 20134887Schin * external formatter: 20144887Schin * \a...\a italic 20154887Schin * \b...\b bold 20164887Schin * \f...\f discipline infof callback on ... 20174887Schin * \v...\v literal 20184887Schin * internal formatter: 20194887Schin * \t indent 20204887Schin * \n newline 20214887Schin * margin flush pops to previous indent 20224887Schin */ 20234887Schin 20244887Schin char* 20254887Schin opthelp(const char* oopts, const char* what) 20264887Schin { 20274887Schin register Sfio_t* sp; 20284887Schin register Sfio_t* mp; 20294887Schin register int c; 20304887Schin register char* p; 20314887Schin register Indent_t* ip; 20324887Schin char* t; 20334887Schin char* x; 20344887Schin char* w; 20354887Schin char* u; 20364887Schin char* y; 20374887Schin char* s; 20384887Schin char* d; 20394887Schin char* v; 20404887Schin char* ov; 20414887Schin char* name; 20424887Schin char* pp; 20434887Schin char* rb; 20444887Schin char* re; 20454887Schin int f; 20464887Schin int i; 20474887Schin int j; 20484887Schin int m; 20494887Schin int n; 20504887Schin int a; 20514887Schin int sl; 20524887Schin int vl; 20534887Schin int ol; 20544887Schin int wl; 20554887Schin int xl; 20564887Schin int rm; 20574887Schin int ts; 20584887Schin int co; 20594887Schin int z; 20604887Schin int style; 20614887Schin int head; 20628462SApril.Chin@Sun.COM int margin; 20634887Schin int mode; 20644887Schin int mutex; 20654887Schin int prefix; 20664887Schin int version; 20674887Schin long tp; 20684887Schin char* catalog; 20694887Schin Optpass_t* o; 20704887Schin Optpass_t* q; 20714887Schin Optpass_t* e; 20724887Schin Optpass_t one; 20734887Schin Help_t* hp; 20744887Schin short ptstk[elementsof(indent) + 2]; 20754887Schin short* pt; 20764887Schin Sfio_t* vp; 20774887Schin Push_t* tsp; 20784887Schin 20794887Schin char* opts = (char*)oopts; 20804887Schin int flags = 0; 20814887Schin int matched = 0; 20824887Schin int paragraph = 0; 20834887Schin int section = 1; 20844887Schin Push_t* psp = 0; 20854887Schin Sfio_t* sp_help = 0; 20864887Schin Sfio_t* sp_text = 0; 20874887Schin Sfio_t* sp_plus = 0; 20884887Schin Sfio_t* sp_head = 0; 20894887Schin Sfio_t* sp_body = 0; 20904887Schin Sfio_t* sp_info = 0; 20914887Schin Sfio_t* sp_misc = 0; 20924887Schin 20934887Schin if (!(mp = opt_info.state->mp) && !(mp = opt_info.state->mp = sfstropen())) 20944887Schin goto nospace; 20954887Schin if (!what) 20964887Schin style = opt_info.state->style; 20974887Schin else if (!*what) 20984887Schin style = STYLE_options; 20994887Schin else if (*what != '?') 21004887Schin style = STYLE_match; 21014887Schin else if (!*(what + 1)) 21024887Schin style = STYLE_man; 21034887Schin else if ((hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), (char*)what + 1)) && hp->style >= 0) 21044887Schin { 21054887Schin style = hp->style; 21064887Schin if (*hp->name != '?') 21074887Schin what = hp->name; 21084887Schin } 21094887Schin else 21104887Schin { 21114887Schin if ((style = opt_info.state->force) < STYLE_man) 21124887Schin style = STYLE_man; 21134887Schin if (!(sp_help = sfstropen())) 21144887Schin goto nospace; 21154887Schin for (i = 0; i < elementsof(help_head); i++) 21164887Schin list(sp_help, &help_head[i]); 21174887Schin for (i = 0; i < elementsof(styles); i++) 21184887Schin sfprintf(sp_help, "[:%s?%s]", styles[i].match, styles[i].text); 21194887Schin for (i = 0; i < elementsof(help_tail); i++) 21204887Schin list(sp_help, &help_tail[i]); 21214887Schin if (!(opts = sfstruse(sp_help))) 21224887Schin goto nospace; 21234887Schin } 21244887Schin message((-20, "AHA#%d style=%d", __LINE__, style)); 21254887Schin again: 21264887Schin if (opts) 21274887Schin { 21284887Schin for (i = 0; i < opt_info.state->npass; i++) 21294887Schin if (opt_info.state->pass[i].oopts == opts) 21304887Schin { 21314887Schin o = &opt_info.state->pass[i]; 21324887Schin break; 21334887Schin } 21344887Schin if (i >= opt_info.state->npass) 21354887Schin { 21364887Schin o = &one; 21374887Schin if (init((char*)opts, o)) 21384887Schin goto nospace; 21394887Schin } 21404887Schin e = o + 1; 21414887Schin } 21424887Schin else if (opt_info.state->npass > 0) 21434887Schin { 21444887Schin o = opt_info.state->pass; 21454887Schin e = o + opt_info.state->npass; 21464887Schin } 21474887Schin else if (opt_info.state->npass < 0) 21484887Schin { 21494887Schin o = &opt_info.state->cache->pass; 21504887Schin e = o + 1; 21514887Schin } 21524887Schin else 21534887Schin return T(NiL, ID, "[* call optget() before opthelp() *]"); 2154*10898Sroland.mainz@nrubsig.org if (style <= STYLE_usage) 21554887Schin { 21564887Schin if (!(sp_text = sfstropen()) || !(sp_info = sfstropen())) 21574887Schin goto nospace; 21584887Schin if (style >= STYLE_match && style < STYLE_keys && !(sp_body = sfstropen())) 21594887Schin goto nospace; 21604887Schin } 21614887Schin switch (style) 21624887Schin { 21634887Schin case STYLE_api: 21644887Schin case STYLE_html: 21654887Schin case STYLE_nroff: 21664887Schin opt_info.state->emphasis = 0; 21674887Schin break; 21684887Schin case STYLE_usage: 21694887Schin case STYLE_keys: 21704887Schin for (q = o; q < e; q++) 21714887Schin if (!(q->flags & OPT_ignore) && !streq(q->catalog, o->catalog)) 21724887Schin o = q; 21734887Schin /*FALLTHROUGH*/ 21744887Schin case STYLE_posix: 21754887Schin sfputc(mp, '\f'); 21764887Schin break; 21774887Schin default: 21784887Schin if (!opt_info.state->emphasis) 21794887Schin { 21804887Schin if (x = getenv("ERROR_OPTIONS")) 21814887Schin { 21824887Schin if (strmatch(x, "*noemphasi*")) 21834887Schin break; 21844887Schin if (strmatch(x, "*emphasi*")) 21854887Schin { 21864887Schin opt_info.state->emphasis = 1; 21874887Schin break; 21884887Schin } 21894887Schin } 21904887Schin if ((x = getenv("TERM")) && strmatch(x, "(ansi|vt100|xterm)*") && isatty(sffileno(sfstderr))) 21914887Schin opt_info.state->emphasis = 1; 21924887Schin } 21934887Schin break; 21944887Schin } 21954887Schin x = ""; 21964887Schin xl = 0; 21974887Schin for (q = o; q < e; q++) 21984887Schin { 21994887Schin if (q->flags & OPT_ignore) 22004887Schin continue; 22014887Schin if (section < q->section) 22024887Schin section = q->section; 22034887Schin section = q->section; 22044887Schin flags |= q->flags; 22054887Schin p = q->opts; 22064887Schin prefix = q->prefix; 22074887Schin version = q->version; 22084887Schin catalog = q->catalog; 22094887Schin switch (style) 22104887Schin { 22114887Schin case STYLE_usage: 22124887Schin if (xl) 22134887Schin sfputc(mp, '\n'); 22144887Schin else 22154887Schin xl = 1; 2216*10898Sroland.mainz@nrubsig.org psp = 0; 2217*10898Sroland.mainz@nrubsig.org for (;;) 22184887Schin { 2219*10898Sroland.mainz@nrubsig.org switch (c = *p++) 22204887Schin { 2221*10898Sroland.mainz@nrubsig.org case 0: 2222*10898Sroland.mainz@nrubsig.org if (!(tsp = psp)) 2223*10898Sroland.mainz@nrubsig.org goto style_usage; 2224*10898Sroland.mainz@nrubsig.org p = psp->ob; 2225*10898Sroland.mainz@nrubsig.org psp = psp->next; 2226*10898Sroland.mainz@nrubsig.org free(tsp); 2227*10898Sroland.mainz@nrubsig.org continue; 22284887Schin case '\a': 22294887Schin c = 'a'; 22304887Schin break; 22314887Schin case '\b': 22324887Schin c = 'b'; 22334887Schin break; 22344887Schin case '\f': 2235*10898Sroland.mainz@nrubsig.org psp = info(psp, p, NiL, sp_info); 2236*10898Sroland.mainz@nrubsig.org if (psp->nb) 2237*10898Sroland.mainz@nrubsig.org p = psp->nb; 2238*10898Sroland.mainz@nrubsig.org else 2239*10898Sroland.mainz@nrubsig.org { 2240*10898Sroland.mainz@nrubsig.org p = psp->ob; 2241*10898Sroland.mainz@nrubsig.org psp = psp->next; 2242*10898Sroland.mainz@nrubsig.org } 2243*10898Sroland.mainz@nrubsig.org continue; 22444887Schin case '\n': 22454887Schin c = 'n'; 22464887Schin break; 22474887Schin case '\r': 22484887Schin c = 'r'; 22494887Schin break; 22504887Schin case '\t': 22514887Schin c = 't'; 22524887Schin break; 22534887Schin case '\v': 22544887Schin c = 'v'; 22554887Schin break; 22564887Schin case '"': 22574887Schin c = '"'; 22584887Schin break; 22594887Schin case '\'': 22604887Schin c = '\''; 22614887Schin break; 22624887Schin case '\\': 22634887Schin c = '\\'; 22644887Schin break; 22654887Schin default: 22664887Schin sfputc(mp, c); 22674887Schin continue; 22684887Schin } 22694887Schin sfputc(mp, '\\'); 22704887Schin sfputc(mp, c); 22714887Schin } 2272*10898Sroland.mainz@nrubsig.org style_usage: 22734887Schin continue; 22744887Schin case STYLE_keys: 22754887Schin a = 0; 22764887Schin psp = 0; 22774887Schin vl = 0; 22784887Schin for (;;) 22794887Schin { 22804887Schin if (!(c = *p++)) 22814887Schin { 22824887Schin if (!(tsp = psp)) 22834887Schin break; 22844887Schin p = psp->ob; 22854887Schin psp = psp->next; 22864887Schin free(tsp); 22874887Schin continue; 22884887Schin } 22894887Schin if (c == '\f') 22904887Schin { 22914887Schin psp = info(psp, p, NiL, sp_info); 22924887Schin if (psp->nb) 22934887Schin p = psp->nb; 22944887Schin else 22954887Schin { 22964887Schin p = psp->ob; 22974887Schin psp = psp->next; 22984887Schin } 22994887Schin continue; 23004887Schin } 23014887Schin f = z = 1; 23024887Schin t = 0; 23034887Schin if (a == 0 && (c == ' ' || c == '\n' && *p == '\n')) 23044887Schin { 23054887Schin if (c == ' ' && *p == ']') 23064887Schin { 23074887Schin p++; 23084887Schin continue; 23094887Schin } 23104887Schin if (*p == '\n') 23114887Schin p++; 23124887Schin a = c; 23134887Schin } 23144887Schin else if (c == '\n') 23154887Schin { 23164887Schin if (a == ' ') 23174887Schin a = -1; 23184887Schin else if (a == '\n' || *p == '\n') 23194887Schin { 23204887Schin a = -1; 23214887Schin p++; 23224887Schin } 23234887Schin continue; 23244887Schin } 23254887Schin else if ((c == ':' || c == '#') && (*p == '[' || *p == '?' && *(p + 1) == '[' && p++)) 23264887Schin p++; 23274887Schin else if (c != '[') 23284887Schin { 23298462SApril.Chin@Sun.COM if (c == GO) 23304887Schin vl++; 23318462SApril.Chin@Sun.COM else if (c == OG) 23324887Schin vl--; 23334887Schin continue; 23344887Schin } 23354887Schin else if (*p == ' ') 23364887Schin { 23374887Schin p++; 23384887Schin continue; 23394887Schin } 23404887Schin else if (*p == '-') 23414887Schin { 23424887Schin z = 0; 23434887Schin if (*++p == '-') 23444887Schin { 23454887Schin p = skip(p, 0, 0, 0, 1, 0, 1, version); 23464887Schin continue; 23474887Schin } 23484887Schin } 23494887Schin else if (*p == '+') 23504887Schin { 23514887Schin p++; 23524887Schin if (vl > 0 && *p != '\a') 23534887Schin { 23544887Schin f = 0; 23554887Schin p = skip(p, '?', 0, 0, 1, 0, 0, version); 23564887Schin if (*p == '?') 23574887Schin p++; 23584887Schin } 23594887Schin } 23604887Schin else 23614887Schin { 23624887Schin if (*(p + 1) == '\f' && (vp = opt_info.state->vp)) 23634887Schin p = expand(p + 2, NiL, &t, vp); 23644887Schin p = skip(p, ':', '?', 0, 1, 0, 0, version); 23654887Schin if (*p == ':') 23664887Schin p++; 23674887Schin } 23684887Schin if (f && *p == '?' && *(p + 1) != '?') 23694887Schin { 23704887Schin f = 0; 23714887Schin if (z) 23724887Schin p++; 23734887Schin else 23744887Schin p = skip(p, 0, 0, 0, 1, 0, 0, version); 23754887Schin } 23764887Schin if (*p == ']' && *(p + 1) != ']') 23774887Schin { 23784887Schin p++; 23794887Schin continue; 23804887Schin } 23814887Schin if (!*p) 23824887Schin { 23834887Schin if (!t) 23844887Schin break; 23854887Schin p = t; 23864887Schin t = 0; 23874887Schin } 23884887Schin m = sfstrtell(mp); 23894887Schin sfputc(mp, '"'); 23904887Schin xl = 1; 23914887Schin /*UNDENT...*/ 23924887Schin 23934887Schin for (;;) 23944887Schin { 23954887Schin if (!(c = *p++)) 23964887Schin { 23974887Schin if (t) 23984887Schin { 23994887Schin p = t; 24004887Schin t = 0; 24014887Schin } 24024887Schin if (!(tsp = psp)) 24034887Schin { 24044887Schin p--; 24054887Schin break; 24064887Schin } 24074887Schin p = psp->ob; 24084887Schin psp = psp->next; 24094887Schin free(tsp); 24104887Schin continue; 24114887Schin } 24124887Schin if (a > 0) 24134887Schin { 24144887Schin if (c == '\n') 24154887Schin { 24164887Schin if (a == ' ') 24174887Schin { 24184887Schin a = -1; 24194887Schin break; 24204887Schin } 24214887Schin if (a == '\n' || *p == '\n') 24224887Schin { 24234887Schin a = -1; 24244887Schin p++; 24254887Schin break; 24264887Schin } 24274887Schin } 24284887Schin } 24294887Schin else if (c == ']') 24304887Schin { 24314887Schin if (*p != ']') 24324887Schin { 24334887Schin sfputc(mp, 0); 24344887Schin y = sfstrbase(mp) + m + 1; 24354887Schin if (D(y) || !strmatch(y, KEEP) || strmatch(y, OMIT)) 24364887Schin { 24374887Schin sfstrseek(mp, m, SEEK_SET); 24384887Schin xl = 0; 24394887Schin } 24404887Schin else 24414887Schin sfstrseek(mp, -1, SEEK_CUR); 24424887Schin break; 24434887Schin } 24444887Schin sfputc(mp, *p++); 24454887Schin continue; 24464887Schin } 24474887Schin switch (c) 24484887Schin { 24494887Schin case '?': 24504887Schin if (f) 24514887Schin { 24524887Schin if (*p == '?') 24534887Schin { 24544887Schin p++; 24554887Schin sfputc(mp, c); 24564887Schin } 24574887Schin else 24584887Schin { 24594887Schin f = 0; 24604887Schin sfputc(mp, 0); 24614887Schin y = sfstrbase(mp) + m + 1; 24624887Schin if (D(y) || !strmatch(y, KEEP) || strmatch(y, OMIT)) 24634887Schin { 24644887Schin sfstrseek(mp, m, SEEK_SET); 24654887Schin xl = 0; 24664887Schin } 24674887Schin else 24684887Schin sfstrseek(mp, -1, SEEK_CUR); 24694887Schin if (z && (*p != ']' || *(p + 1) == ']')) 24704887Schin { 24714887Schin if (xl) 24724887Schin { 24734887Schin sfputc(mp, '"'); 24744887Schin sfputc(mp, '\n'); 24754887Schin } 24764887Schin m = sfstrtell(mp); 24774887Schin sfputc(mp, '"'); 24784887Schin xl = 1; 24794887Schin } 24804887Schin else 24814887Schin { 24824887Schin p = skip(p, 0, 0, 0, 1, 0, 0, version); 24834887Schin if (*p == '?') 24844887Schin p++; 24854887Schin } 24864887Schin } 24874887Schin } 24884887Schin else 24894887Schin sfputc(mp, c); 24904887Schin continue; 24914887Schin case ':': 24924887Schin if (f && *p == ':') 24934887Schin p++; 24944887Schin sfputc(mp, c); 24954887Schin continue; 24964887Schin case '\a': 24974887Schin c = 'a'; 24984887Schin break; 24994887Schin case '\b': 25004887Schin c = 'b'; 25014887Schin break; 25024887Schin case '\f': 25034887Schin c = 'f'; 25044887Schin break; 25054887Schin case '\n': 25064887Schin c = 'n'; 25074887Schin break; 25084887Schin case '\r': 25094887Schin c = 'r'; 25104887Schin break; 25114887Schin case '\t': 25124887Schin c = 't'; 25134887Schin break; 25144887Schin case '\v': 25154887Schin c = 'v'; 25164887Schin break; 25174887Schin case '"': 25184887Schin c = '"'; 25194887Schin break; 25204887Schin case '\\': 25214887Schin c = '\\'; 25224887Schin break; 25234887Schin case CC_esc: 25244887Schin c = 'E'; 25254887Schin break; 25264887Schin default: 25274887Schin sfputc(mp, c); 25284887Schin continue; 25294887Schin } 25304887Schin sfputc(mp, '\\'); 25314887Schin sfputc(mp, c); 25324887Schin } 25334887Schin 25344887Schin /*...INDENT*/ 25354887Schin if (xl) 25364887Schin { 25374887Schin sfputc(mp, '"'); 25384887Schin sfputc(mp, '\n'); 25394887Schin } 25404887Schin } 25414887Schin continue; 25424887Schin } 25434887Schin z = 0; 25444887Schin head = 0; 25454887Schin mode = 0; 25464887Schin mutex = 0; 25474887Schin if (style > STYLE_short && style < STYLE_nroff && version < 1) 25484887Schin { 25494887Schin style = STYLE_short; 25504887Schin if (sp_body) 25514887Schin { 25524887Schin sfclose(sp_body); 25534887Schin sp_body = 0; 25544887Schin } 25554887Schin } 25564887Schin else if (style == STYLE_short && prefix < 2) 25574887Schin style = STYLE_long; 25584887Schin if (*p == ':') 25594887Schin p++; 25604887Schin if (*p == '+') 25614887Schin { 25624887Schin p++; 25634887Schin if (!(sp = sp_plus) && !(sp = sp_plus = sfstropen())) 25644887Schin goto nospace; 25654887Schin } 25664887Schin else if (style >= STYLE_match) 25674887Schin sp = sp_body; 25684887Schin else 25694887Schin sp = sp_text; 25704887Schin psp = 0; 25714887Schin for (;;) 25724887Schin { 25734887Schin if (!(*(p = next(p, version)))) 25744887Schin { 25754887Schin if (!(tsp = psp)) 25764887Schin break; 25774887Schin p = psp->ob; 25784887Schin psp = psp->next; 25794887Schin free(tsp); 25804887Schin continue; 25814887Schin } 25824887Schin if (*p == '\f') 25834887Schin { 25844887Schin psp = info(psp, p + 1, NiL, sp_info); 25854887Schin if (psp->nb) 25864887Schin p = psp->nb; 25874887Schin else 25884887Schin { 25894887Schin p = psp->ob; 25904887Schin psp = psp->next; 25914887Schin } 25924887Schin continue; 25934887Schin } 25944887Schin if (*p == '\n' || *p == ' ') 25954887Schin { 25964887Schin if (*(x = p = next(p + 1, version))) 25974887Schin while (*++p) 25984887Schin if (*p == '\n') 25994887Schin { 26004887Schin while (*++p == ' ' || *p == '\t' || *p == '\r'); 26014887Schin if (*p == '\n') 26024887Schin break; 26034887Schin } 26044887Schin xl = p - x; 26054887Schin if (!*p) 26064887Schin break; 26074887Schin continue; 26084887Schin } 26098462SApril.Chin@Sun.COM if (*p == OG) 26104887Schin { 26114887Schin p++; 26124887Schin continue; 26134887Schin } 26144887Schin message((-20, "opthelp: opt %s", show(p))); 26154887Schin if (z < 0) 26164887Schin z = 0; 26174887Schin a = 0; 26184887Schin f = 0; 26194887Schin w = 0; 26204887Schin d = 0; 26214887Schin s = 0; 26228462SApril.Chin@Sun.COM rb = re = 0; 26234887Schin sl = 0; 26248462SApril.Chin@Sun.COM vl = 0; 26254887Schin if (*p == '[') 26264887Schin { 26274887Schin if ((c = *(p = next(p + 1, version))) == '-') 26284887Schin { 26294887Schin if (style >= STYLE_man) 26304887Schin { 26314887Schin if (*(p + 1) != '-') 26324887Schin { 26334887Schin if (!sp_misc && !(sp_misc = sfstropen())) 26344887Schin goto nospace; 26354887Schin else 26364887Schin p = textout(sp_misc, p, style, 1, 3, sp_info, version, catalog); 26374887Schin continue; 26384887Schin } 26394887Schin } 26404887Schin else if (style == STYLE_match && *what == '-') 26414887Schin { 26428462SApril.Chin@Sun.COM if (*(p + 1) == '?' || isdigit(*(p + 1))) 26434887Schin s = C("version"); 26444887Schin else 26454887Schin s = p + 1; 26464887Schin w = (char*)what; 26474887Schin if (*s != '-' || *(w + 1) == '-') 26484887Schin { 26494887Schin if (*s == '-') 26504887Schin s++; 26514887Schin if (*(w + 1) == '-') 26524887Schin w++; 26534887Schin if (match(w + 1, s, version, catalog)) 26544887Schin { 26554887Schin if (*(p + 1) == '-') 26564887Schin p++; 26574887Schin p = textout(sp, p, style, 1, 3, sp_info, version, catalog); 26584887Schin matched = -1; 26594887Schin continue; 26604887Schin } 26614887Schin } 26624887Schin } 26634887Schin if (!z) 26644887Schin z = -1; 26654887Schin } 26664887Schin else if (c == '+') 26674887Schin { 26684887Schin if (style >= STYLE_man) 26694887Schin { 26704887Schin p = textout(sp_body, p, style, 0, 0, sp_info, version, catalog); 26714887Schin if (!sp_head) 26724887Schin { 26734887Schin sp_head = sp_body; 26744887Schin if (!(sp_body = sfstropen())) 26754887Schin goto nospace; 26764887Schin } 26774887Schin continue; 26784887Schin } 26794887Schin else if (style == STYLE_match && *what == '+') 26804887Schin { 26814887Schin if (paragraph) 26824887Schin { 26834887Schin if (p[1] == '?') 26844887Schin { 26854887Schin p = textout(sp, p, style, 1, 3, sp_info, version, catalog); 26864887Schin continue; 26874887Schin } 26884887Schin paragraph = 0; 26894887Schin } 26904887Schin if (match((char*)what + 1, p + 1, version, catalog)) 26914887Schin { 26924887Schin p = textout(sp, p, style, 1, 3, sp_info, version, catalog); 26934887Schin matched = -1; 26944887Schin paragraph = 1; 26954887Schin continue; 26964887Schin } 26974887Schin } 26984887Schin if (!z) 26994887Schin z = -1; 27004887Schin } 27014887Schin else if (c == '[' || version < 1) 27024887Schin { 27034887Schin mutex++; 27044887Schin continue; 27054887Schin } 27064887Schin else 27074887Schin { 27084887Schin if (c == '!') 27094887Schin { 27104887Schin a |= OPT_invert; 27114887Schin p++; 27124887Schin } 27134887Schin rb = p; 27144887Schin if (*p != ':') 27154887Schin { 27164887Schin s = p; 27174887Schin if (*(p + 1) == '|') 27184887Schin { 27194887Schin while (*++p && *p != '=' && *p != '!' && *p != ':' && *p != '?'); 27204887Schin if ((p - s) > 1) 27214887Schin sl = p - s; 27224887Schin if (*p == '!') 27234887Schin a |= OPT_invert; 27244887Schin } 27254887Schin if (*(p + 1) == '\f') 27264887Schin p++; 27274887Schin else 27284887Schin p = skip(p, ':', '?', 0, 1, 0, 0, version); 27294887Schin if (sl || (p - s) == 1 || *(s + 1) == '=' || *(s + 1) == '!' && (a |= OPT_invert) || *(s + 1) == '|') 27304887Schin f = *s; 27314887Schin } 27324887Schin re = p; 27334887Schin if (style <= STYLE_short) 27344887Schin { 27354887Schin if (!z && !f) 27364887Schin z = -1; 27374887Schin } 27384887Schin else 27394887Schin { 27404887Schin if (*p == '\f' && (vp = opt_info.state->vp)) 27414887Schin p = expand(p + 1, NiL, &t, vp); 27424887Schin else 27434887Schin t = 0; 27444887Schin if (*p == ':') 27454887Schin { 27464887Schin p = skip(w = p + 1, ':', '?', 0, 1, 0, 0, version); 27474887Schin if (!(wl = p - w)) 27484887Schin w = 0; 27494887Schin } 27504887Schin else 27514887Schin wl = 0; 27524887Schin if (*p == ':' || *p == '?') 27534887Schin { 27544887Schin d = p; 27554887Schin p = skip(p, 0, 0, 0, 1, 0, 0, version); 27564887Schin } 27574887Schin else 27584887Schin d = 0; 27594887Schin if (style == STYLE_match) 27604887Schin { 27614887Schin if (wl && !match((char*)what, w, version, catalog)) 27624887Schin wl = 0; 27634887Schin if ((!wl || *w == ':' || *w == '?') && (what[1] || sl && !memchr(s, what[0], sl) || !sl && what[0] != f)) 27644887Schin { 27654887Schin w = 0; 27664887Schin if (!z) 27674887Schin z = -1; 27684887Schin } 27694887Schin else 27704887Schin matched = 1; 27714887Schin } 27724887Schin if (t) 27734887Schin { 27744887Schin p = t; 27754887Schin if (*p == ':' || *p == '?') 27764887Schin { 27774887Schin d = p; 27784887Schin p = skip(p, 0, 0, 0, 1, 0, 0, version); 27794887Schin } 27804887Schin } 27814887Schin } 27824887Schin } 27834887Schin p = skip(p, 0, 0, 0, 1, 0, 1, version); 27844887Schin if (*p == GO) 27854887Schin p = skip(p + 1, 0, 0, 0, 0, 1, 1, version); 27864887Schin } 27874887Schin else if (*p == ']') 27884887Schin { 27894887Schin if (mutex) 27904887Schin { 27914887Schin if (style >= STYLE_nroff) 27924887Schin sfputr(sp_body, "\n.OP - - anyof", '\n'); 27934887Schin if (!(mutex & 1)) 27944887Schin { 27954887Schin mutex--; 27964887Schin if (style <= STYLE_long) 27974887Schin { 27984887Schin sfputc(sp_body, ' '); 27994887Schin sfputc(sp_body, ']'); 28004887Schin } 28014887Schin } 28024887Schin mutex--; 28034887Schin } 28044887Schin p++; 28054887Schin continue; 28064887Schin } 28074887Schin else if (*p == '?') 28084887Schin { 28094887Schin if (style < STYLE_match) 28104887Schin z = 1; 28114887Schin mode |= OPT_hidden; 28124887Schin p++; 28134887Schin continue; 28144887Schin } 28154887Schin else if (*p == '\\' && style==STYLE_posix) 28164887Schin { 28174887Schin if (*++p) 28184887Schin p++; 28194887Schin continue; 28204887Schin } 28214887Schin else 28224887Schin { 28234887Schin f = *p++; 28244887Schin s = 0; 28254887Schin if (style == STYLE_match && !z) 28264887Schin z = -1; 28274887Schin } 28284887Schin if (!z) 28294887Schin { 28304887Schin if (style == STYLE_long || prefix < 2 || (q->flags & OPT_long)) 28314887Schin f = 0; 28324887Schin else if (style <= STYLE_short) 28334887Schin w = 0; 28344887Schin if (!f && !w) 28354887Schin z = -1; 28364887Schin } 28378462SApril.Chin@Sun.COM ov = 0; 28388462SApril.Chin@Sun.COM u = v = y = 0; 28394887Schin if (*p == ':' && (a |= OPT_string) || *p == '#' && (a |= OPT_number)) 28404887Schin { 28414887Schin message((-21, "opthelp: arg %s", show(p))); 28424887Schin if (*++p == '?' || *p == *(p - 1)) 28434887Schin { 28444887Schin p++; 28454887Schin a |= OPT_optional; 28464887Schin } 28474887Schin if (*(p = next(p, version)) == '[') 28484887Schin { 28494887Schin if (!z) 28504887Schin { 28514887Schin p = skip(y = p + 1, ':', '?', 0, 1, 0, 0, version); 28524887Schin while (*p == ':') 28534887Schin { 28544887Schin p = skip(t = p + 1, ':', '?', 0, 1, 0, 0, version); 28554887Schin m = p - t; 28564887Schin if (*t == '!') 28574887Schin { 28584887Schin ov = t + 1; 28594887Schin ol = m - 1; 28604887Schin } 28614887Schin else if (*t == '=') 28624887Schin { 28634887Schin v = t + 1; 28644887Schin vl = m - 1; 28654887Schin } 28664887Schin else 28674887Schin for (j = 0; j < elementsof(attrs); j++) 28684887Schin if (strneq(t, attrs[j].name, m)) 28694887Schin { 28704887Schin a |= attrs[j].flag; 28714887Schin break; 28724887Schin } 28734887Schin } 28744887Schin if (*p == '?') 28754887Schin u = p; 28764887Schin p = skip(p, 0, 0, 0, 1, 0, 1, version); 28774887Schin } 28784887Schin else 28794887Schin p = skip(p + 1, 0, 0, 0, 1, 0, 1, version); 28804887Schin } 28814887Schin else 28824887Schin y = (a & OPT_number) ? T(NiL, ID, "#") : T(NiL, ID, "arg"); 28834887Schin } 28844887Schin else 28854887Schin a |= OPT_flag; 28864887Schin if (!z) 28874887Schin { 28884887Schin if (style <= STYLE_short && !y && !mutex || style == STYLE_posix) 28894887Schin { 28904887Schin if (style != STYLE_posix && !sfstrtell(sp)) 28914887Schin { 28924887Schin sfputc(sp, '['); 28934887Schin if (sp == sp_plus) 28944887Schin sfputc(sp, '+'); 28954887Schin sfputc(sp, '-'); 28964887Schin } 28974887Schin if (!sl) 28984887Schin sfputc(sp, f); 28994887Schin else 29004887Schin for (c = 0; c < sl; c++) 29014887Schin if (s[c] != '|') 29024887Schin sfputc(sp, s[c]); 29034887Schin if (style == STYLE_posix && y) 29044887Schin sfputc(sp, ':'); 29054887Schin } 29064887Schin else 29074887Schin { 29084887Schin if (style >= STYLE_match) 29094887Schin { 29104887Schin sfputc(sp_body, '\n'); 29114887Schin if (!head) 29124887Schin { 29134887Schin head = 1; 29148462SApril.Chin@Sun.COM item(sp_body, (flags & OPT_functions) ? C("FUNCTIONS") : C("OPTIONS"), 0, 0, style, sp_info, version, ID); 29154887Schin } 29164887Schin if (style >= STYLE_nroff) 29174887Schin { 29184887Schin if (mutex & 1) 29194887Schin { 29204887Schin mutex++; 29214887Schin sfputr(sp_body, "\n.OP - - oneof", '\n'); 29224887Schin } 29234887Schin } 29244887Schin else 29254887Schin sfputc(sp_body, '\t'); 29264887Schin } 29274887Schin else 29284887Schin { 29294887Schin if (sp_body) 29304887Schin sfputc(sp_body, ' '); 29314887Schin else if (!(sp_body = sfstropen())) 29324887Schin goto nospace; 29334887Schin if (mutex) 29344887Schin { 29354887Schin if (mutex & 1) 29364887Schin { 29374887Schin mutex++; 29384887Schin sfputc(sp_body, '['); 29394887Schin } 29404887Schin else 29414887Schin sfputc(sp_body, '|'); 29424887Schin sfputc(sp_body, ' '); 29434887Schin } 29444887Schin else 29454887Schin sfputc(sp_body, '['); 29464887Schin } 29474887Schin if (style >= STYLE_nroff) 29484887Schin { 29494887Schin if (flags & OPT_functions) 29504887Schin { 29514887Schin sfputr(sp_body, ".FN", ' '); 29524887Schin if (re > rb) 29534887Schin sfwrite(sp_body, rb, re - rb); 29544887Schin else 29554887Schin sfputr(sp, "void", -1); 29564887Schin if (w) 29578462SApril.Chin@Sun.COM label(sp_body, ' ', w, 0, -1, 0, style, FONT_BOLD, sp_info, version, catalog); 29584887Schin } 29594887Schin else 29604887Schin { 29614887Schin sfputr(sp_body, ".OP", ' '); 29624887Schin if (sl) 29634887Schin sfwrite(sp_body, s, sl); 29644887Schin else 29654887Schin sfputc(sp_body, f ? f : '-'); 29664887Schin sfputc(sp_body, ' '); 29674887Schin if (w) 29684887Schin { 29698462SApril.Chin@Sun.COM if (label(sp_body, 0, w, 0, -1, 0, style, 0, sp_info, version, catalog)) 29704887Schin { 29714887Schin sfputc(sp_body, '|'); 29728462SApril.Chin@Sun.COM label(sp_body, 0, w, 0, -1, 0, style, 0, sp_info, version, native); 29734887Schin } 29744887Schin } 29754887Schin else 29764887Schin sfputc(sp_body, '-'); 29774887Schin sfputc(sp_body, ' '); 29784887Schin m = a & OPT_TYPE; 29794887Schin for (j = 0; j < elementsof(attrs); j++) 29804887Schin if (m & attrs[j].flag) 29814887Schin { 29824887Schin sfputr(sp_body, attrs[j].name, -1); 29834887Schin break; 29844887Schin } 29854887Schin if (m = (a & ~m) | mode) 29864887Schin for (j = 0; j < elementsof(attrs); j++) 29874887Schin if (m & attrs[j].flag) 29884887Schin { 29894887Schin sfputc(sp_body, ':'); 29904887Schin sfputr(sp_body, attrs[j].name, -1); 29914887Schin } 29924887Schin sfputc(sp_body, ' '); 29934887Schin if (y) 29948462SApril.Chin@Sun.COM label(sp_body, 0, y, 0, -1, 0, style, 0, sp_info, version, catalog); 29954887Schin else 29964887Schin sfputc(sp_body, '-'); 29974887Schin if (v) 29984887Schin sfprintf(sp_body, " %-.*s", vl, v); 29994887Schin } 30004887Schin } 30014887Schin else 30024887Schin { 30034887Schin if (f) 30044887Schin { 30054887Schin if (sp_body == sp_plus) 30064887Schin sfputc(sp_body, '+'); 30074887Schin sfputc(sp_body, '-'); 30084887Schin sfputr(sp_body, font(FONT_BOLD, style, 1), -1); 30094887Schin if (!sl) 30104887Schin { 30114887Schin sfputc(sp_body, f); 30124887Schin if (f == '-' && y) 30134887Schin { 30144887Schin y = 0; 30154887Schin sfputr(sp_body, C("long-option[=value]"), -1); 30164887Schin } 30174887Schin } 30184887Schin else 30194887Schin sfwrite(sp_body, s, sl); 30204887Schin sfputr(sp_body, font(FONT_BOLD, style, 0), -1); 30214887Schin if (w) 30224887Schin { 30234887Schin sfputc(sp_body, ','); 30244887Schin sfputc(sp_body, ' '); 30254887Schin } 30264887Schin } 30274887Schin else if ((flags & OPT_functions) && re > rb) 30284887Schin { 30294887Schin sfwrite(sp_body, rb, re - rb); 30304887Schin sfputc(sp_body, ' '); 30314887Schin } 30324887Schin if (w) 30334887Schin { 30344887Schin if (prefix > 0) 30354887Schin { 30364887Schin sfputc(sp_body, '-'); 30374887Schin if (prefix > 1) 30384887Schin sfputc(sp_body, '-'); 30394887Schin } 30408462SApril.Chin@Sun.COM if (label(sp_body, 0, w, 0, -1, 0, style, FONT_BOLD, sp_info, version, catalog)) 30414887Schin { 30424887Schin sfputc(sp_body, '|'); 30438462SApril.Chin@Sun.COM label(sp_body, 0, w, 0, -1, 0, style, FONT_BOLD, sp_info, version, native); 30444887Schin } 30454887Schin } 30464887Schin if (y) 30474887Schin { 30484887Schin if (a & OPT_optional) 30494887Schin sfputc(sp_body, '['); 30504887Schin else if (!w) 30514887Schin sfputc(sp_body, ' '); 30524887Schin if (w) 30534887Schin sfputc(sp_body, prefix == 1 ? ' ' : '='); 30548462SApril.Chin@Sun.COM label(sp_body, 0, y, 0, -1, 0, style, FONT_ITALIC, sp_info, version, catalog); 30554887Schin if (a & OPT_optional) 30564887Schin sfputc(sp_body, ']'); 30574887Schin } 30584887Schin } 30594887Schin if (style >= STYLE_match) 30604887Schin { 30614887Schin if (d) 30624887Schin textout(sp_body, d, style, 0, 3, sp_info, version, catalog); 30634887Schin if (u) 30644887Schin textout(sp_body, u, style, 0, 3, sp_info, version, catalog); 30654887Schin if ((a & OPT_invert) && w && (d || u)) 30664887Schin { 30674887Schin u = skip(w, ':', '?', 0, 1, 0, 0, version); 30684887Schin if (f) 30694887Schin 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); 30704887Schin else 30714887Schin 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")); 30724887Schin if (!(t = sfstruse(sp_info))) 30734887Schin goto nospace; 30744887Schin textout(sp_body, t, style, 0, 0, sp_info, version, NiL); 30754887Schin } 30764887Schin if (*p == GO) 30774887Schin { 30784887Schin p = u ? skip(p + 1, 0, 0, 0, 0, 1, 1, version) : textout(sp_body, p, style, 4, 0, sp_info, version, catalog); 30794887Schin y = "+?"; 30804887Schin } 30814887Schin else 30824887Schin y = " "; 30834887Schin if (a & OPT_optional) 30844887Schin { 30854887Schin if (ov) 30864887Schin { 30874887Schin sfprintf(sp_info, "%s%s \b", y, T(NiL, ID, "If the option value is omitted then")); 30884887Schin t = ov + ol; 30894887Schin while (ov < t) 30904887Schin { 30914887Schin if (((c = *ov++) == ':' || c == '?') && *ov == c) 30924887Schin ov++; 30934887Schin sfputc(sp_info, c); 30944887Schin } 30954887Schin sfprintf(sp_info, "\b %s.", T(NiL, ID, "is assumed")); 30964887Schin } 30974887Schin else 30984887Schin sfprintf(sp_info, "%s%s", y, T(NiL, ID, "The option value may be omitted.")); 30994887Schin if (!(t = sfstruse(sp_info))) 31004887Schin goto nospace; 31014887Schin textout(sp_body, t, style, 4, 0, sp_info, version, NiL); 31024887Schin y = " "; 31034887Schin } 31044887Schin if (v) 31054887Schin { 31064887Schin sfprintf(sp_info, "%s%s \b", y, T(NiL, ID, "The default value is")); 31074887Schin t = v + vl; 31084887Schin while (v < t) 31094887Schin { 31104887Schin if (((c = *v++) == ':' || c == '?') && *v == c) 31114887Schin v++; 31124887Schin sfputc(sp_info, c); 31134887Schin } 31144887Schin sfputc(sp_info, '\b'); 31154887Schin sfputc(sp_info, '.'); 31164887Schin if (!(t = sfstruse(sp_info))) 31174887Schin goto nospace; 31184887Schin textout(sp_body, t, style, 4, 0, sp_info, version, NiL); 31194887Schin } 31204887Schin } 31214887Schin else if (!mutex) 31224887Schin sfputc(sp_body, ']'); 31234887Schin } 31244887Schin if (*p == GO) 31254887Schin { 31264887Schin if (style >= STYLE_match) 31274887Schin p = textout(sp_body, p, style, 4, 0, sp_info, version, catalog); 31284887Schin else 31294887Schin p = skip(p + 1, 0, 0, 0, 0, 1, 1, version); 31304887Schin } 31314887Schin } 31324887Schin else if (*p == GO) 31334887Schin p = skip(p + 1, 0, 0, 0, 0, 1, 1, version); 31344887Schin } 31354887Schin psp = pop(psp); 31364887Schin if (sp_misc) 31374887Schin { 31384887Schin if (!(p = sfstruse(sp_misc))) 31394887Schin goto nospace; 31404887Schin for (t = p; *t == '\t' || *t == '\n'; t++); 31414887Schin if (*t) 31424887Schin { 31438462SApril.Chin@Sun.COM item(sp_body, C("IMPLEMENTATION"), 0, 0, style, sp_info, version, ID); 31444887Schin sfputr(sp_body, p, -1); 31454887Schin } 31464887Schin } 31474887Schin } 31484887Schin version = o->version; 31494887Schin catalog = o->catalog; 31504887Schin if (style >= STYLE_keys) 31514887Schin { 31524887Schin if (sp_info) 31534887Schin sfclose(sp_info); 31544887Schin if (style == STYLE_keys && sfstrtell(mp) > 1) 31554887Schin sfstrseek(mp, -1, SEEK_CUR); 31564887Schin if (!(p = sfstruse(mp))) 31574887Schin goto nospace; 31584887Schin return opt_info.msg = p; 31594887Schin } 31604887Schin sp = sp_text; 31614887Schin if (sfstrtell(sp) && style != STYLE_posix) 31624887Schin sfputc(sp, ']'); 31634887Schin if (style == STYLE_nroff) 31644887Schin { 31654887Schin sfprintf(sp, "\ 31664887Schin .\\\" format with nroff|troff|groff -man\n\ 31674887Schin .fp 5 CW\n\ 31688462SApril.Chin@Sun.COM .nr mH 5\n\ 31698462SApril.Chin@Sun.COM .de H0\n\ 31708462SApril.Chin@Sun.COM .nr mH 0\n\ 31718462SApril.Chin@Sun.COM .in 5n\n\ 31728462SApril.Chin@Sun.COM \\fB\\\\$1\\fP\n\ 31738462SApril.Chin@Sun.COM .in 7n\n\ 31744887Schin ..\n\ 31754887Schin .de H1\n\ 31768462SApril.Chin@Sun.COM .nr mH 1\n\ 31778462SApril.Chin@Sun.COM .in 7n\n\ 31784887Schin \\fB\\\\$1\\fP\n\ 31798462SApril.Chin@Sun.COM .in 9n\n\ 31804887Schin ..\n\ 31814887Schin .de H2\n\ 31828462SApril.Chin@Sun.COM .nr mH 2\n\ 31838462SApril.Chin@Sun.COM .in 11n\n\ 31844887Schin \\fB\\\\$1\\fP\n\ 31858462SApril.Chin@Sun.COM .in 13n\n\ 31864887Schin ..\n\ 31874887Schin .de H3\n\ 31888462SApril.Chin@Sun.COM .nr mH 3\n\ 31898462SApril.Chin@Sun.COM .in 15n\n\ 31904887Schin \\fB\\\\$1\\fP\n\ 31918462SApril.Chin@Sun.COM .in 17n\n\ 31924887Schin ..\n\ 31934887Schin .de H4\n\ 31948462SApril.Chin@Sun.COM .nr mH 4\n\ 31958462SApril.Chin@Sun.COM .in 19n\n\ 31964887Schin \\fB\\\\$1\\fP\n\ 31978462SApril.Chin@Sun.COM .in 21n\n\ 31984887Schin ..\n\ 31994887Schin .de OP\n\ 32008462SApril.Chin@Sun.COM .nr mH 0\n\ 32014887Schin .ie !'\\\\$1'-' \\{\n\ 32024887Schin .ds mO \\\\fB\\\\-\\\\$1\\\\fP\n\ 32034887Schin .ds mS ,\\\\0\n\ 32044887Schin .\\}\n\ 32054887Schin .el \\{\n\ 32064887Schin .ds mO \\\\&\n\ 32074887Schin .ds mS \\\\&\n\ 32084887Schin .\\}\n\ 32094887Schin .ie '\\\\$2'-' \\{\n\ 32104887Schin .if !'\\\\$4'-' .as mO \\\\0\\\\fI\\\\$4\\\\fP\n\ 32114887Schin .\\}\n\ 32124887Schin .el \\{\n\ 32134887Schin .as mO \\\\*(mS\\\\fB%s\\\\$2\\\\fP\n\ 32144887Schin .if !'\\\\$4'-' .as mO =\\\\fI\\\\$4\\\\fP\n\ 32154887Schin .\\}\n\ 32168462SApril.Chin@Sun.COM .in 5n\n\ 32174887Schin \\\\*(mO\n\ 32188462SApril.Chin@Sun.COM .in 9n\n\ 32198462SApril.Chin@Sun.COM ..\n\ 32208462SApril.Chin@Sun.COM .de SP\n\ 32218462SApril.Chin@Sun.COM .if \\\\n(mH==2 .in 9n\n\ 32228462SApril.Chin@Sun.COM .if \\\\n(mH==3 .in 13n\n\ 32238462SApril.Chin@Sun.COM .if \\\\n(mH==4 .in 17n\n\ 32244887Schin ..\n\ 32254887Schin .de FN\n\ 32268462SApril.Chin@Sun.COM .nr mH 0\n\ 32278462SApril.Chin@Sun.COM .in 5n\n\ 32284887Schin \\\\$1 \\\\$2\n\ 32298462SApril.Chin@Sun.COM .in 9n\n\ 32308462SApril.Chin@Sun.COM ..\n\ 32318462SApril.Chin@Sun.COM .de DS\n\ 32328462SApril.Chin@Sun.COM .in +3n\n\ 32338462SApril.Chin@Sun.COM .ft 5\n\ 32348462SApril.Chin@Sun.COM .nf\n\ 32358462SApril.Chin@Sun.COM ..\n\ 32368462SApril.Chin@Sun.COM .de DE\n\ 32378462SApril.Chin@Sun.COM .fi\n\ 32388462SApril.Chin@Sun.COM .ft R\n\ 32398462SApril.Chin@Sun.COM .in -3n\n\ 32404887Schin ..\n\ 32414887Schin .TH %s %d\n\ 32424887Schin " 32434887Schin , o->prefix == 2 ? "\\\\-\\\\-" : o->prefix == 1 ? "\\\\-" : "" 32444887Schin , error_info.id 32454887Schin , section 32464887Schin ); 32474887Schin } 32484887Schin if (style == STYLE_match) 32494887Schin { 32504887Schin if (!matched) 32514887Schin { 32524887Schin if (hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), (char*)what)) 32534887Schin { 32544887Schin if (!sp_help && !(sp_help = sfstropen())) 32554887Schin goto nospace; 32564887Schin sfprintf(sp_help, "[-][:%s?%s]", hp->match, hp->text); 32574887Schin if (!(opts = sfstruse(sp_help))) 32584887Schin goto nospace; 32594887Schin goto again; 32604887Schin } 32614887Schin s = (char*)unknown; 32624887Schin goto nope; 32634887Schin } 32644887Schin else if (matched < 0) 32654887Schin x = 0; 32664887Schin } 32674887Schin if (sp_plus) 32684887Schin { 32694887Schin if (sfstrtell(sp_plus)) 32704887Schin { 32714887Schin if (sfstrtell(sp)) 32724887Schin sfputc(sp, ' '); 32734887Schin if (!(t = sfstruse(sp_plus))) 32744887Schin goto nospace; 32754887Schin sfputr(sp, t, ']'); 32764887Schin } 32774887Schin sfclose(sp_plus); 32784887Schin } 32794887Schin if (style >= STYLE_man) 32804887Schin { 32814887Schin if (sp_head) 32824887Schin { 32834887Schin if (!(t = sfstruse(sp_head))) 32844887Schin goto nospace; 32854887Schin for (; *t == '\n'; t++); 32864887Schin sfputr(sp, t, '\n'); 32874887Schin sfclose(sp_head); 32884887Schin sp_head = 0; 32894887Schin } 32908462SApril.Chin@Sun.COM item(sp, C("SYNOPSIS"), 0, 0, style, sp_info, version, ID); 32914887Schin } 32924887Schin if (x) 32934887Schin { 32944887Schin for (t = x + xl; t > x && (*(t - 1) == '\n' || *(t - 1) == '\r'); t--); 32954887Schin xl = t - x; 32964887Schin if (style >= STYLE_match) 32974887Schin { 32984887Schin args(sp, x, xl, flags, style, sp_info, version, catalog); 32994887Schin x = 0; 33004887Schin } 33014887Schin } 33024887Schin if (sp_body) 33034887Schin { 33044887Schin if (sfstrtell(sp_body)) 33054887Schin { 33064887Schin if (style < STYLE_match && sfstrtell(sp)) 33074887Schin sfputc(sp, ' '); 33084887Schin if (!(t = sfstruse(sp_body))) 33094887Schin goto nospace; 33104887Schin sfputr(sp, t, -1); 33114887Schin } 33124887Schin sfclose(sp_body); 33134887Schin sp_body = 0; 33144887Schin } 33154887Schin if (x && style != STYLE_posix) 33164887Schin args(sp, x, xl, flags, style, sp_info, version, catalog); 33174887Schin if (sp_info) 33184887Schin { 33194887Schin sfclose(sp_info); 33204887Schin sp_info = 0; 33214887Schin } 33224887Schin if (sp_misc) 33234887Schin { 33244887Schin sfclose(sp_misc); 33254887Schin sp_misc = 0; 33264887Schin } 33274887Schin if (!(p = sfstruse(sp))) 33284887Schin goto nospace; 33294887Schin name = error_info.id ? error_info.id : "command"; 33304887Schin m = strlen(name) + 1; 33318462SApril.Chin@Sun.COM #if 0 33324887Schin if (!opt_info.state->width) 33338462SApril.Chin@Sun.COM #endif 33344887Schin { 33354887Schin astwinsize(1, NiL, &opt_info.state->width); 33364887Schin if (opt_info.state->width < 20) 33374887Schin opt_info.state->width = OPT_WIDTH; 33384887Schin } 33398462SApril.Chin@Sun.COM margin = style == STYLE_api ? (8 * 1024) : (opt_info.state->width - 1); 33404887Schin if (!(opt_info.state->flags & OPT_preformat)) 33414887Schin { 33424887Schin if (style >= STYLE_man || matched < 0) 33434887Schin { 33444887Schin sfputc(mp, '\f'); 33454887Schin ts = 0; 33464887Schin } 33474887Schin else 33484887Schin ts = OPT_USAGE + m; 33494887Schin if (style == STYLE_html) 33504887Schin { 33514887Schin 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" : "", name); 33524887Schin 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", name, section, T(NiL, ID, heading[section % 10]), name, section); 33534887Schin sfprintf(mp, "<DL compact>\n<DT>"); 33544887Schin co = 2; 33554887Schin *(pt = ptstk) = 0; 33564887Schin } 33574887Schin else 33584887Schin co = 0; 33598462SApril.Chin@Sun.COM if ((rm = margin - ts) < OPT_MARGIN) 33604887Schin rm = OPT_MARGIN; 33614887Schin ip = indent; 33624887Schin ip->stop = (ip+1)->stop = style >= STYLE_html ? 0 : 2; 33634887Schin tp = 0; 33644887Schin n = 0; 33654887Schin head = 1; 33664887Schin while (*p == '\n') 33674887Schin p++; 33684887Schin while (c = *p++) 33694887Schin { 33704887Schin if (c == '\n') 33714887Schin { 33724887Schin ip = indent; 33734887Schin n = 0; 33744887Schin tp = 0; 33754887Schin sfputc(mp, '\n'); 33764887Schin co = 0; 33778462SApril.Chin@Sun.COM rm = margin; 33784887Schin ts = ip->stop; 33794887Schin if (*p == '\n') 33804887Schin { 33814887Schin while (*++p == '\n'); 33824887Schin if ((style == STYLE_man || style == STYLE_html) && (!head || *p != ' ' && *p != '\t')) 33834887Schin { 33844887Schin if (style == STYLE_man) 33854887Schin p--; 33864887Schin else 33874887Schin sfprintf(mp, "<P>\n"); 33884887Schin } 33894887Schin } 33904887Schin head = *p != ' ' && *p != '\t'; 33914887Schin if (style == STYLE_html && (*p != '<' || !strneq(p, "<BR>", 4) && !strneq(p, "<P>", 3))) 33924887Schin { 33934887Schin y = p; 33944887Schin while (*p == '\t') 33954887Schin p++; 33964887Schin if (*p == '\n') 33974887Schin continue; 33984887Schin j = p - y; 33994887Schin if (j > *pt) 34004887Schin { 34014887Schin if (pt > ptstk) 34024887Schin sfprintf(mp, "<DL compact>\n"); 34034887Schin *++pt = j; 34044887Schin sfprintf(mp, "<DL compact>\n"); 34054887Schin } 34064887Schin else while (j < *pt) 34074887Schin { 34084887Schin if (--pt > ptstk) 34094887Schin sfprintf(mp, "</DL>\n"); 34104887Schin sfprintf(mp, "</DL>\n"); 34114887Schin } 34124887Schin co += sfprintf(mp, "<DT>"); 34134887Schin } 34144887Schin } 34154887Schin else if (c == '\t') 34164887Schin { 34174887Schin if (style == STYLE_html) 34184887Schin { 34194887Schin while (*p == '\t') 34204887Schin p++; 34214887Schin if (*p != '\n') 34224887Schin co += sfprintf(mp, "<DD>"); 34234887Schin } 34244887Schin else 34254887Schin { 34264887Schin if ((ip+1)->stop) 34274887Schin { 34284887Schin do 34294887Schin { 34304887Schin ip++; 34314887Schin if (*p != '\t') 34324887Schin break; 34334887Schin p++; 34344887Schin } while ((ip+1)->stop); 34354887Schin if (*p == '\n') 34364887Schin continue; 34374887Schin ts = ip->stop; 34384887Schin if (co >= ts) 34394887Schin { 34404887Schin sfputc(mp, '\n'); 34414887Schin co = 0; 34428462SApril.Chin@Sun.COM rm = margin; 34434887Schin ts = ip->stop; 34444887Schin } 34454887Schin } 34464887Schin while (co < ts) 34474887Schin { 34484887Schin sfputc(mp, ' '); 34494887Schin co++; 34504887Schin } 34514887Schin } 34524887Schin } 34534887Schin else 34544887Schin { 34554887Schin if (c == ' ' && !n) 34564887Schin { 34574887Schin if (co >= rm) 34584887Schin tp = 0; 34594887Schin else 34604887Schin { 34614887Schin tp = sfstrtell(mp); 34624887Schin pp = p; 34634887Schin } 34644887Schin if (style == STYLE_nroff && !co) 34654887Schin continue; 34664887Schin } 34674887Schin else if (style == STYLE_html) 34684887Schin { 34694887Schin if (c == '<') 34704887Schin { 34714887Schin if (strneq(p, "NOBR>", 5)) 34724887Schin n++; 34734887Schin else if (n && strneq(p, "/NOBR>", 6) && !--n) 34744887Schin { 34754887Schin for (y = p += 6; (c = *p) && c != ' ' && c != '\t' && c != '\n' && c != '<'; p++) 34764887Schin if (c == '[') 34774887Schin sfputr(mp, "[", -1); 34784887Schin else if (c == ']') 34794887Schin sfputr(mp, "]", -1); 34804887Schin else 34814887Schin sfputc(mp, c); 34824887Schin sfwrite(mp, "</NOBR", 6); 34834887Schin c = '>'; 34844887Schin tp = 0; 34854887Schin co += p - y + 6; 34864887Schin } 34874887Schin } 34884887Schin else if (c == '>' && !n) 34894887Schin { 34904887Schin for (y = --p; (c = *p) && c != ' ' && c != '\t' && c != '\n' && c != '<'; p++) 34914887Schin if (c == '[') 34924887Schin sfputr(mp, "[", -1); 34934887Schin else if (c == ']') 34944887Schin sfputr(mp, "]", -1); 34954887Schin else 34964887Schin sfputc(mp, c); 34974887Schin c = *sfstrseek(mp, -1, SEEK_CUR); 34984887Schin if (p > y + 1) 34994887Schin { 35004887Schin tp = 0; 35014887Schin co += p - y - 1; 35024887Schin } 35034887Schin if (co >= rm) 35044887Schin tp = 0; 35054887Schin else 35064887Schin { 35074887Schin tp = sfstrtell(mp); 35084887Schin pp = p; 35094887Schin } 35104887Schin } 35114887Schin else if (c == '[') 35124887Schin { 35134887Schin sfputr(mp, "[", -1); 35144887Schin c = ';'; 35154887Schin } 35164887Schin else if (c == ']') 35174887Schin { 35184887Schin sfputr(mp, "]", -1); 35194887Schin c = ';'; 35204887Schin } 35214887Schin else if (c == 'h') 35224887Schin { 35234887Schin y = p; 35244887Schin if (*y++ == 't' && *y++ == 't' && *y++ == 'p' && (*y == ':' || *y++ == 's' && *y == ':') && *y++ == ':' && *y++ == '/' && *y++ == '/') 35254887Schin { 35264887Schin while (isalnum(*y) || *y == '_' || *y == '/' || *y == '-' || *y == '.') 35274887Schin y++; 35284887Schin if (*y == '?') 35294887Schin while (isalnum(*y) || *y == '_' || *y == '/' || *y == '-' || *y == '.' || *y == '?' || *y == '=' || *y == '%' || *y == '&' || *y == ';' || *y == '#') 35304887Schin y++; 35314887Schin if (*(y - 1) == '.') 35324887Schin y--; 35334887Schin p--; 35344887Schin sfprintf(mp, "<A href=\"%-.*s\">%-.*s</A", y - p, p, y - p, p); 35354887Schin p = y; 35364887Schin c = '>'; 35374887Schin } 35384887Schin } 35394887Schin else if (c == 'C') 35404887Schin { 35414887Schin y = p; 35424887Schin 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++ == ')') 35434887Schin { 35444887Schin sfputr(mp, "Copyright ©", -1); 35454887Schin p = y; 35464887Schin c = ';'; 35474887Schin } 35484887Schin } 35494887Schin } 35504887Schin else if (c == ']') 35514887Schin { 35524887Schin if (n) 35534887Schin n--; 35544887Schin } 35554887Schin else if (c == '[') 35564887Schin n++; 35574887Schin if (c == CC_esc) 35584887Schin { 35594887Schin sfputc(mp, c); 35604887Schin do 35614887Schin { 35624887Schin if (!(c = *p++)) 35634887Schin { 35644887Schin p--; 35654887Schin break; 35664887Schin } 35674887Schin sfputc(mp, c); 35684887Schin } while (c < 'a' || c > 'z'); 35694887Schin } 35704887Schin else if (co++ >= rm && !n) 35714887Schin { 35724887Schin if (tp) 35734887Schin { 35744887Schin if (*sfstrseek(mp, tp, SEEK_SET) != ' ') 35754887Schin sfstrseek(mp, 1, SEEK_CUR); 35764887Schin tp = 0; 35774887Schin p = pp; 35784887Schin n = 0; 35794887Schin } 35804887Schin else if (c != ' ' && c != '\n') 35814887Schin sfputc(mp, c); 35824887Schin if (*p == ' ') 35834887Schin p++; 35844887Schin if (*p != '\n') 35854887Schin { 35864887Schin sfputc(mp, '\n'); 35874887Schin for (co = 0; co < ts; co++) 35884887Schin sfputc(mp, ' '); 35898462SApril.Chin@Sun.COM rm = margin; 35904887Schin } 35914887Schin } 35924887Schin else 35934887Schin sfputc(mp, c); 35944887Schin } 35954887Schin } 35964887Schin for (d = sfstrbase(mp), t = sfstrseek(mp, 0, SEEK_CUR); t > d && ((c = *(t - 1)) == '\n' || c == '\r' || c == ' ' || c == '\t'); t--); 35974887Schin sfstrseek(mp, t - d, SEEK_SET); 35984887Schin if (style == STYLE_html) 35994887Schin { 36004887Schin while (pt > ptstk) 36014887Schin { 36024887Schin if (--pt > ptstk) 36034887Schin sfprintf(mp, "\n</DL>"); 36044887Schin sfprintf(mp, "\n</DL>"); 36054887Schin } 36064887Schin sfprintf(mp, "</DL>\n</BODY>\n</HTML>"); 36074887Schin } 36084887Schin } 36094887Schin else 36104887Schin sfputr(mp, p, 0); 36114887Schin if (!(p = sfstruse(mp))) 36124887Schin goto nospace; 36134887Schin if (sp) 36144887Schin sfclose(sp); 36154887Schin return opt_info.msg = p; 36164887Schin nospace: 36174887Schin s = T(NiL, ID, "[* out of space *]"); 36184887Schin nope: 36194887Schin if (psp) 36204887Schin pop(psp); 36214887Schin if (sp_help) 36224887Schin sfclose(sp_help); 36234887Schin if (sp_text) 36244887Schin sfclose(sp_text); 36254887Schin if (sp_plus) 36264887Schin sfclose(sp_plus); 36274887Schin if (sp_info) 36284887Schin sfclose(sp_info); 36294887Schin if (sp_head) 36304887Schin sfclose(sp_head); 36314887Schin if (sp_body) 36324887Schin sfclose(sp_body); 36334887Schin if (sp_misc) 36344887Schin sfclose(sp_misc); 36354887Schin return s; 36364887Schin } 36374887Schin 36384887Schin /* 36394887Schin * compatibility wrapper to opthelp() 36404887Schin */ 36414887Schin 36424887Schin char* 36434887Schin optusage(const char* opts) 36444887Schin { 36454887Schin return opthelp(opts, NiL); 36464887Schin } 36474887Schin 36484887Schin /* 36494887Schin * convert number using strtonll() *except* that 36504887Schin * 0*[[:digit:]].* is treated as [[:digit:]].* 36514887Schin * i.e., it looks octal but isn't, to meet 36524887Schin * posix Utility Argument Syntax -- use 36534887Schin * 0x.* or <base>#* for alternate bases 36544887Schin */ 36554887Schin 36564887Schin static intmax_t 36574887Schin optnumber(const char* s, char** t, int* e) 36584887Schin { 36594887Schin intmax_t n; 36604887Schin int oerrno; 36614887Schin 36624887Schin while (*s == '0' && isdigit(*(s + 1))) 36634887Schin s++; 36644887Schin oerrno = errno; 36654887Schin errno = 0; 36664887Schin n = strtonll(s, t, NiL, 0); 36674887Schin if (e) 36684887Schin *e = errno; 36694887Schin errno = oerrno; 36704887Schin return n; 36714887Schin } 36724887Schin 36734887Schin /* 36744887Schin * point opt_info.arg to an error/info message for opt_info.name 36754887Schin * p points to opts location for opt_info.name 36764887Schin * optget() return value is returned 36774887Schin */ 36784887Schin 36794887Schin static int 36804887Schin opterror(register char* p, int version, char* catalog, int err) 36814887Schin { 36824887Schin register Sfio_t* mp; 36834887Schin register Sfio_t* tp; 36844887Schin register char* s; 36854887Schin register int c; 36864887Schin 36874887Schin if (opt_info.num != LONG_MIN) 3688*10898Sroland.mainz@nrubsig.org opt_info.num = (long)(opt_info.number = 0); 36894887Schin if (!p || !(mp = opt_info.state->mp) && !(mp = opt_info.state->mp = sfstropen())) 36904887Schin goto nospace; 36914887Schin s = *p == '-' ? p : opt_info.name; 36924887Schin if (*p == '!') 36934887Schin { 36944887Schin while (*s == '-') 36954887Schin sfputc(mp, *s++); 36964887Schin sfputc(mp, 'n'); 36974887Schin sfputc(mp, 'o'); 36984887Schin } 36994887Schin sfputr(mp, s, ':'); 37004887Schin sfputc(mp, ' '); 37014887Schin if (*p == '#' || *p == ':') 37024887Schin { 37034887Schin if (*p == '#') 37044887Schin { 37054887Schin s = T(NiL, ID, "numeric"); 37064887Schin sfputr(mp, s, ' '); 37074887Schin } 37084887Schin if (*(p = next(p + 1, version)) == '[') 37094887Schin { 37104887Schin p = skip(s = p + 1, ':', '?', 0, 1, 0, 0, version); 37114887Schin tp = X(catalog) ? opt_info.state->xp : mp; 37124887Schin while (s < p) 37134887Schin { 37144887Schin if ((c = *s++) == '?' || c == ']') 37154887Schin s++; 37164887Schin sfputc(tp, c); 37174887Schin } 37184887Schin if (!X(catalog)) 37194887Schin sfputc(mp, ' '); 37204887Schin else if (p = sfstruse(tp)) 37214887Schin sfputr(mp, T(error_info.id, catalog, p), ' '); 37224887Schin else 37234887Schin goto nospace; 37244887Schin } 37254887Schin p = opt_info.name[2] ? C("value expected") : C("argument expected"); 37264887Schin } 37274887Schin else if (*p == '*' || *p == '&') 37284887Schin { 37294887Schin sfputr(mp, opt_info.arg, ':'); 37304887Schin sfputc(mp, ' '); 37314887Schin p = *p == '&' ? C("ambiguous option argument value") : C("unknown option argument value"); 37324887Schin } 37334887Schin else if (*p == '=' || *p == '!') 37344887Schin p = C("value not expected"); 37354887Schin else if (*p == '?') 37364887Schin p = *(p + 1) == '?' ? C("optget: option not supported") : C("ambiguous option"); 37374887Schin else if (*p == '+') 37384887Schin p = C("section not found"); 37394887Schin else 37404887Schin { 37414887Schin if (opt_info.option[0] != '?' && opt_info.option[0] != '-' || opt_info.option[1] != '?' && opt_info.option[1] != '-') 37424887Schin opt_info.option[0] = 0; 37434887Schin p = C("unknown option"); 37444887Schin } 37454887Schin p = T(NiL, ID, p); 37464887Schin sfputr(mp, p, -1); 37474887Schin if (err) 37484887Schin sfputr(mp, " -- out of range", -1); 37494887Schin if (opt_info.arg = sfstruse(mp)) 37504887Schin return ':'; 37514887Schin nospace: 37524887Schin opt_info.arg = T(NiL, ID, "[* out of space *]"); 37534887Schin return ':'; 37544887Schin } 37554887Schin 37564887Schin /* 37574887Schin * argv: command line argv where argv[0] is command name 37584887Schin * 37594887Schin * opts: option control string 37604887Schin * 37614887Schin * '[' [flag][=][index][:<long-name>[|<alias-name>...]['?'description]] ']' 37624887Schin * long option name, index, description; -index returned 37634887Schin * ':' option takes string arg 37644887Schin * '#' option takes numeric arg (concat option may follow) 37654887Schin * '?' (option) following options not in usage 37664887Schin * (following # or :) optional arg 37674887Schin * '[' '[' ... ] ... '[' ... ']' ']' 37684887Schin * mutually exclusive option grouping 37694887Schin * '[' name [:attr]* [?description] ']' 37704887Schin * (following # or :) optional option arg description 37714887Schin * '\n'[' '|'\t']* ignored for legibility 37724887Schin * ' ' ... optional argument(s) description (to end of string) 37734887Schin * or after blank line 37744887Schin * ']]' literal ']' within '[' ... ']' 37754887Schin * 37764887Schin * return: 37774887Schin * 0 no more options 37784887Schin * '?' usage: opt_info.arg points to message sans 37794887Schin * `Usage: command ' 37804887Schin * ':' error: opt_info.arg points to message sans `command: ' 37814887Schin * 3782*10898Sroland.mainz@nrubsig.org * ':' '#' ' ' '[' ']' 37834887Schin * invalid option chars 37844887Schin * 37854887Schin * -- terminates option list and returns 0 37864887Schin * 37874887Schin * + as first opts char makes + equivalent to - 37884887Schin * 37894887Schin * if any # option is specified then numeric options (e.g., -123) 37904887Schin * are associated with the leftmost # option in opts 37914887Schin * 37924887Schin * usage info in placed opt_info.arg when '?' returned 37934887Schin * see help_text[] (--???) for more info 37944887Schin */ 37954887Schin 37964887Schin int 37974887Schin optget(register char** argv, const char* oopts) 37984887Schin { 37994887Schin register int c; 38004887Schin register char* s; 38014887Schin char* a; 38024887Schin char* b; 38034887Schin char* e; 38044887Schin char* f; 38054887Schin char* g; 38064887Schin char* v; 38074887Schin char* w; 38084887Schin char* p; 38094887Schin char* q; 38104887Schin char* t; 38114887Schin char* y; 38124887Schin char* numopt; 38134887Schin char* opts; 38144887Schin char* catalog; 38154887Schin int n; 38164887Schin int m; 38174887Schin int k; 38184887Schin int j; 38194887Schin int x; 38204887Schin int err; 38214887Schin int no; 38224887Schin int nov; 38234887Schin int num; 38244887Schin int numchr; 38254887Schin int prefix; 38264887Schin int version; 38274887Schin Help_t* hp; 38284887Schin Push_t* psp; 38294887Schin Push_t* tsp; 38304887Schin Sfio_t* vp; 38314887Schin Sfio_t* xp; 38324887Schin Optcache_t* cache; 38334887Schin Optcache_t* pcache; 38344887Schin Optpass_t* pass; 38354887Schin 38368462SApril.Chin@Sun.COM #if !_PACKAGE_astsa && !_YOU_FIGURED_OUT_HOW_TO_GET_ALL_DLLS_TO_DO_THIS_ 38374887Schin /* 38384887Schin * these are not initialized by all dlls! 38394887Schin */ 38404887Schin 38414887Schin extern Error_info_t _error_info_; 38424887Schin extern Opt_t _opt_info_; 38434887Schin 38444887Schin if (!_error_infop_) 38454887Schin _error_infop_ = &_error_info_; 38464887Schin if (!_opt_infop_) 38474887Schin _opt_infop_ = &_opt_info_; 38484887Schin if (!opt_info.state) 38494887Schin opt_info.state = &state; 38504887Schin #endif 38514887Schin if (!oopts) 38524887Schin return 0; 38534887Schin opt_info.state->pindex = opt_info.index; 38544887Schin opt_info.state->poffset = opt_info.offset; 38554887Schin if (!opt_info.index) 38564887Schin { 38574887Schin opt_info.index = 1; 38584887Schin opt_info.offset = 0; 38594887Schin if (opt_info.state->npass) 38604887Schin { 38614887Schin opt_info.state->npass = 0; 38624887Schin opt_info.state->join = 0; 38634887Schin } 38644887Schin } 38654887Schin if (!argv) 38664887Schin cache = 0; 38674887Schin else 38684887Schin for (pcache = 0, cache = opt_info.state->cache; cache; pcache = cache, cache = cache->next) 38694887Schin if (cache->pass.oopts == (char*)oopts) 38704887Schin break; 38714887Schin if (cache) 38724887Schin { 38734887Schin if (pcache) 38744887Schin { 38754887Schin pcache->next = cache->next; 38764887Schin cache->next = opt_info.state->cache; 38774887Schin opt_info.state->cache = cache; 38784887Schin } 38794887Schin pass = &cache->pass; 38804887Schin opt_info.state->npass = -1; 38814887Schin } 38824887Schin else 38834887Schin { 38844887Schin if (!argv) 38854887Schin n = opt_info.state->npass ? opt_info.state->npass : 1; 38864887Schin else if ((n = opt_info.state->join - 1) < 0) 38874887Schin n = 0; 38884887Schin if (n >= opt_info.state->npass || opt_info.state->pass[n].oopts != (char*)oopts) 38894887Schin { 38904887Schin for (m = 0; m < opt_info.state->npass && opt_info.state->pass[m].oopts != (char*)oopts; m++); 38914887Schin if (m < opt_info.state->npass) 38924887Schin n = m; 38934887Schin else 38944887Schin { 38954887Schin if (n >= elementsof(opt_info.state->pass)) 38964887Schin n = elementsof(opt_info.state->pass) - 1; 38974887Schin init((char*)oopts, &opt_info.state->pass[n]); 38984887Schin if (opt_info.state->npass <= n) 38994887Schin opt_info.state->npass = n + 1; 39004887Schin } 39014887Schin } 39024887Schin if (!argv) 39034887Schin return 0; 39044887Schin pass = &opt_info.state->pass[n]; 39054887Schin } 39064887Schin opts = pass->opts; 39074887Schin prefix = pass->prefix; 39084887Schin version = pass->version; 39094887Schin if (!(xp = opt_info.state->xp) || (catalog = pass->catalog) && !X(catalog)) 39104887Schin catalog = 0; 39114887Schin else /* if (!error_info.catalog) */ 39124887Schin error_info.catalog = catalog; 39134887Schin again: 39144887Schin psp = 0; 39154887Schin 39164887Schin /* 39174887Schin * check if any options remain and determine if the 39184887Schin * next option is short or long 39194887Schin */ 39204887Schin 39214887Schin opt_info.assignment = 0; 39224887Schin num = 1; 39234887Schin w = v = 0; 39244887Schin x = 0; 39254887Schin for (;;) 39264887Schin { 39274887Schin if (!opt_info.offset) 39284887Schin { 39294887Schin /* 39304887Schin * finished with the previous arg 39314887Schin */ 39324887Schin 39334887Schin if (opt_info.index == 1 && opt_info.argv != opt_info.state->strv) 39344887Schin { 39354887Schin opt_info.argv = 0; 39364887Schin opt_info.state->argv[0] = 0; 39374887Schin if (argv[0] && (opt_info.state->argv[0] = save(argv[0]))) 39384887Schin opt_info.argv = opt_info.state->argv; 39394887Schin opt_info.state->style = STYLE_short; 39404887Schin } 39414887Schin if (!(s = argv[opt_info.index])) 39424887Schin return 0; 39434887Schin if (!prefix) 39444887Schin { 39454887Schin /* 39464887Schin * long with no prefix (dd style) 39474887Schin */ 39484887Schin 39494887Schin n = 2; 39504887Schin if ((c = *s) != '-' && c != '+') 39514887Schin c = '-'; 39524887Schin else if (*++s == c) 39534887Schin { 39544887Schin if (!*++s) 39554887Schin { 39564887Schin opt_info.index++; 39574887Schin return 0; 39584887Schin } 39598462SApril.Chin@Sun.COM else if (*s == c) 39608462SApril.Chin@Sun.COM return 0; 39614887Schin } 39624887Schin else if (*s == '?') 39634887Schin n = 1; 39644887Schin } 39658462SApril.Chin@Sun.COM else if ((c = *s++) != '-' && (c != '+' || !(pass->flags & OPT_plus) && (!(pass->flags & OPT_numeric) || !isdigit(*s)))) 39664887Schin { 39674887Schin if (!(pass->flags & OPT_old) || !isalpha(c)) 39684887Schin return 0; 39694887Schin s--; 39704887Schin n = 1; 39714887Schin opt_info.offset--; 39724887Schin } 39734887Schin else if (*s == c) 39744887Schin { 39754887Schin if (!*++s) 39764887Schin { 39774887Schin /* 39784887Schin * -- or ++ end of options 39794887Schin */ 39804887Schin 39814887Schin opt_info.index++; 39824887Schin return 0; 39834887Schin } 39848462SApril.Chin@Sun.COM else if (*s == c) 39858462SApril.Chin@Sun.COM { 39868462SApril.Chin@Sun.COM /* 39878462SApril.Chin@Sun.COM * ---* or +++* are operands 39888462SApril.Chin@Sun.COM */ 39898462SApril.Chin@Sun.COM 39908462SApril.Chin@Sun.COM return 0; 39918462SApril.Chin@Sun.COM } 39924887Schin if (version || *s == '?' || !(pass->flags & OPT_minus)) 39934887Schin { 39944887Schin /* 39954887Schin * long with double prefix 39964887Schin */ 39974887Schin 39984887Schin n = 2; 39994887Schin } 40004887Schin else 40014887Schin { 40024887Schin /* 40034887Schin * short option char '-' 40044887Schin */ 40054887Schin 40064887Schin s--; 40074887Schin n = 1; 40084887Schin } 40094887Schin } 40104887Schin else if (prefix == 1 && *s != '?') 40114887Schin { 40124887Schin /* 40134887Schin * long with single prefix (find style) 40144887Schin */ 40154887Schin 40164887Schin n = 2; 40174887Schin } 40184887Schin else 40194887Schin { 40204887Schin /* 40214887Schin * short (always with single prefix) 40224887Schin */ 40234887Schin 40244887Schin n = 1; 40254887Schin } 40264887Schin 40274887Schin /* 40284887Schin * just a prefix is an option (e.g., `-' == stdin) 40294887Schin */ 40304887Schin 40314887Schin if (!*s) 40324887Schin return 0; 40334887Schin if (c == '+') 40344887Schin opt_info.arg = 0; 4035*10898Sroland.mainz@nrubsig.org message((-2, "c='%c' n=%d", c, n)); 40364887Schin if (n == 2) 40374887Schin { 40384887Schin x = 0; 40394887Schin opt_info.state->style = STYLE_long; 40404887Schin opt_info.option[0] = opt_info.name[0] = opt_info.name[1] = c; 40414887Schin w = &opt_info.name[prefix]; 40424887Schin if ((*s == 'n' || *s == 'N') && (*(s + 1) == 'o' || *(s + 1) == 'O') && *(s + 2) && *(s + 2) != '=') 40434887Schin no = *(s + 2) == '-' ? 3 : 2; 40444887Schin else 40454887Schin no = 0; 40464887Schin for (c = *s; *s; s++) 40474887Schin { 40484887Schin if (*s == '=') 40494887Schin { 40504887Schin if (*(s + 1) == '=') 40514887Schin s++; 40524887Schin if (!isalnum(*(s - 1)) && *(w - 1) == (opt_info.assignment = *(s - 1))) 40534887Schin w--; 40544887Schin v = ++s; 40554887Schin break; 40564887Schin } 40574887Schin if (w < &opt_info.name[elementsof(opt_info.name) - 1] && *s != ':' && *s != '|' && *s != '[' && *s != ']') 40584887Schin *w++ = *s; 40594887Schin } 40604887Schin *w = 0; 40614887Schin w = &opt_info.name[prefix]; 40624887Schin c = *w; 40634887Schin opt_info.offset = 0; 40644887Schin opt_info.index++; 40654887Schin break; 40664887Schin } 40674887Schin opt_info.offset++; 40684887Schin } 40694887Schin if (!argv[opt_info.index]) 40704887Schin return 0; 40714887Schin if (c = argv[opt_info.index][opt_info.offset++]) 40724887Schin { 40734887Schin if ((k = argv[opt_info.index][0]) != '-' && k != '+') 40744887Schin k = '-'; 40754887Schin opt_info.option[0] = opt_info.name[0] = k; 40764887Schin opt_info.option[1] = opt_info.name[1] = c; 40774887Schin opt_info.option[2] = opt_info.name[2] = 0; 40784887Schin break; 40794887Schin } 40804887Schin opt_info.offset = 0; 40814887Schin opt_info.index++; 40824887Schin } 40834887Schin 40844887Schin /* 40854887Schin * at this point: 40864887Schin * 40874887Schin * c the first character of the option 40884887Schin * w long option name if != 0, otherwise short 40894887Schin * v long option value (via =) if w != 0 40904887Schin */ 40914887Schin 40924887Schin if (c == '?') 40934887Schin { 40944887Schin /* 40954887Schin * ? always triggers internal help 40964887Schin */ 40974887Schin 40984887Schin if (w && !v && (*(w + 1) || !(v = argv[opt_info.index]) || !++opt_info.index)) 40994887Schin v = w + 1; 41004887Schin opt_info.option[1] = c; 41014887Schin opt_info.option[2] = 0; 41024887Schin if (!w) 41034887Schin { 41044887Schin opt_info.name[1] = c; 41054887Schin opt_info.name[2] = 0; 41064887Schin } 41074887Schin goto help; 41084887Schin } 41094887Schin numopt = 0; 41104887Schin f = 0; 41114887Schin s = opts; 41124887Schin 41134887Schin /* 41144887Schin * no option can start with these characters 41154887Schin */ 41164887Schin 41174887Schin if (c == ':' || c == '#' || c == ' ' || c == '[' || c == ']') 41184887Schin { 41194887Schin if (c != *s) 41204887Schin s = ""; 41214887Schin } 41224887Schin else 41234887Schin { 41244887Schin a = 0; 41254887Schin if (!w && (pass->flags & OPT_cache)) 41264887Schin { 41274887Schin if (cache) 41284887Schin { 41294887Schin if (k = cache->flags[map[c]]) 41304887Schin { 41314887Schin opt_info.arg = 0; 41324887Schin 41334887Schin /* 41344887Schin * this is a ksh getopts workaround 41354887Schin */ 41364887Schin 41374887Schin if (opt_info.num != LONG_MIN) 4138*10898Sroland.mainz@nrubsig.org opt_info.num = (long)(opt_info.number = !(k & OPT_cache_invert)); 41394887Schin if (!(k & (OPT_cache_string|OPT_cache_numeric))) 41404887Schin return c; 41414887Schin if (*(opt_info.arg = &argv[opt_info.index++][opt_info.offset])) 41424887Schin { 41434887Schin if (!(k & OPT_cache_numeric)) 41444887Schin { 41454887Schin opt_info.offset = 0; 41464887Schin return c; 41474887Schin } 41484887Schin opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err)); 41494887Schin if (err || e == opt_info.arg) 41504887Schin { 41514887Schin if (!err && (k & OPT_cache_optional)) 41524887Schin { 41534887Schin opt_info.arg = 0; 41544887Schin opt_info.index--; 41554887Schin return c; 41564887Schin } 41574887Schin } 41584887Schin else if (*e) 41594887Schin { 41604887Schin opt_info.offset += e - opt_info.arg; 41614887Schin opt_info.index--; 41624887Schin return c; 41634887Schin } 41644887Schin else 41654887Schin { 41664887Schin opt_info.offset = 0; 41674887Schin return c; 41684887Schin } 41694887Schin } 41704887Schin else if (opt_info.arg = argv[opt_info.index]) 41714887Schin { 41724887Schin opt_info.index++; 41734887Schin if ((k & OPT_cache_optional) && (*opt_info.arg == '-' || (pass->flags & OPT_plus) && *opt_info.arg == '+') && *(opt_info.arg + 1)) 41744887Schin { 41754887Schin opt_info.arg = 0; 41764887Schin opt_info.index--; 41774887Schin opt_info.offset = 0; 41784887Schin return c; 41794887Schin } 41804887Schin if (k & OPT_cache_string) 41814887Schin { 41824887Schin opt_info.offset = 0; 41834887Schin return c; 41844887Schin } 41854887Schin opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err)); 41864887Schin if (!err) 41874887Schin { 41884887Schin if (!*e) 41894887Schin { 41904887Schin opt_info.offset = 0; 41914887Schin return c; 41924887Schin } 41934887Schin if (k & OPT_cache_optional) 41944887Schin { 41954887Schin opt_info.arg = 0; 41964887Schin opt_info.index--; 41974887Schin opt_info.offset = 0; 41984887Schin return c; 41994887Schin } 42004887Schin } 42014887Schin } 42024887Schin else if (k & OPT_cache_optional) 42034887Schin { 42044887Schin opt_info.offset = 0; 42054887Schin return c; 42064887Schin } 42074887Schin opt_info.index--; 42084887Schin } 42094887Schin cache = 0; 42104887Schin } 42114887Schin else if (cache = newof(0, Optcache_t, 1, 0)) 42124887Schin { 42134887Schin cache->caching = c; 42144887Schin c = 0; 42154887Schin cache->pass = *pass; 42164887Schin cache->next = opt_info.state->cache; 42174887Schin opt_info.state->cache = cache; 42184887Schin } 42194887Schin } 42204887Schin else 42214887Schin cache = 0; 42224887Schin for (;;) 42234887Schin { 42244887Schin if (!(*(s = next(s, version))) || *s == '\n' || *s == ' ') 42254887Schin { 42264887Schin if (!(tsp = psp)) 42274887Schin { 42284887Schin if (cache) 42294887Schin { 42304887Schin /* 42314887Schin * the first loop pass 42324887Schin * initialized the cache 42334887Schin * so one more pass to 42344887Schin * check the cache or 42354887Schin * bail for a full scan 42364887Schin */ 42374887Schin 42384887Schin cache->flags[0] = 0; 42394887Schin c = cache->caching; 42404887Schin cache->caching = 0; 42414887Schin cache = 0; 42424887Schin s = opts; 42434887Schin continue; 42444887Schin } 42454887Schin if (!x && catalog) 42464887Schin { 42474887Schin /* 42484887Schin * the first loop pass 42494887Schin * translated long 42504887Schin * options and there 42514887Schin * were no matches so 42524887Schin * one more pass for C 42534887Schin * locale 42544887Schin */ 42554887Schin 42564887Schin catalog = 0; 42574887Schin s = opts; 42584887Schin continue; 42594887Schin } 42604887Schin s = ""; 42614887Schin break; 42624887Schin } 42634887Schin s = psp->ob; 42644887Schin psp = psp->next; 42654887Schin free(tsp); 42664887Schin continue; 42674887Schin } 42684887Schin if (*s == '\f') 42694887Schin { 42704887Schin psp = info(psp, s + 1, NiL, opt_info.state->xp); 42714887Schin if (psp->nb) 42724887Schin s = psp->nb; 42734887Schin else 42744887Schin { 42754887Schin s = psp->ob; 42764887Schin psp = psp->next; 42774887Schin } 42784887Schin continue; 42794887Schin } 4280*10898Sroland.mainz@nrubsig.org message((-20, "optget: opt %s c %c w %s num %ld", show(s), c, w, num)); 42814887Schin if (*s == c && !w) 42824887Schin break; 42834887Schin else if (*s == '[') 42844887Schin { 42854887Schin f = s = next(s + 1, version); 42864887Schin k = *f; 42874887Schin if (k == '+' || k == '-') 42884887Schin /* ignore */; 42894887Schin else if (k == '[' || version < 1) 42904887Schin continue; 42914887Schin else if (w && !cache) 42924887Schin { 42934887Schin nov = no; 42944887Schin if (*(s + 1) == '\f' && (vp = opt_info.state->vp)) 42954887Schin { 42964887Schin sfputc(vp, k); 42974887Schin s = expand(s + 2, NiL, &t, vp); 42984887Schin if (*s) 42994887Schin *(f = s - 1) = k; 43004887Schin else 43014887Schin { 43024887Schin f = sfstrbase(vp); 43034887Schin if (s = strrchr(f, ':')) 43044887Schin f = s - 1; 43054887Schin else 43064887Schin s = f + 1; 43074887Schin } 43084887Schin } 43094887Schin else 43104887Schin t = 0; 43114887Schin if (*s != ':') 43124887Schin s = skip(s, ':', '?', 0, 1, 0, 0, version); 43134887Schin if (*s == ':') 43144887Schin { 43154887Schin if (catalog) 43164887Schin { 43174887Schin p = skip(s + 1, '?', 0, 0, 1, 0, 0, version); 43184887Schin e = sfprints("%-.*s", p - (s + 1), s + 1); 43194887Schin g = T(error_info.id, catalog, e); 43204887Schin if (g == e) 43214887Schin p = 0; 43224887Schin else 43234887Schin { 43244887Schin sfprintf(xp, ":%s|%s?", g, e); 43254887Schin if (!(s = sfstruse(xp))) 43264887Schin goto nospace; 43274887Schin } 43284887Schin } 43294887Schin else 43304887Schin p = 0; 43314887Schin y = w; 43324887Schin for (;;) 43334887Schin { 43344887Schin n = m = 0; 43354887Schin e = s + 1; 43364887Schin while (*++s) 43374887Schin { 43384887Schin if (*s == '*' || *s == '\a') 43394887Schin { 43404887Schin if (*s == '\a') 43414887Schin do 43424887Schin { 43434887Schin if (!*++s) 43444887Schin { 43454887Schin s--; 43464887Schin break; 43474887Schin } 43484887Schin } while (*s != '\a'); 43494887Schin j = *(s + 1); 43504887Schin if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0) 43514887Schin { 43524887Schin while (*w) 43534887Schin w++; 43544887Schin m = 0; 43554887Schin break; 43564887Schin } 43574887Schin m = 1; 43584887Schin } 43594887Schin else if (*s == *w || sep(*s) && sep(*w)) 43604887Schin w++; 43614887Schin else if (*w == 0) 43624887Schin break; 43634887Schin else if (!sep(*s)) 43644887Schin { 43654887Schin if (sep(*w)) 43664887Schin { 43674887Schin if (*++w == *s) 43684887Schin { 43694887Schin w++; 43704887Schin continue; 43714887Schin } 43724887Schin } 43734887Schin else if (w == y || sep(*(w - 1)) || isupper(*(w - 1)) && islower(*w)) 43744887Schin break; 43754887Schin for (q = s; *q && !sep(*q) && *q != '|' && *q != '?' && *q != ']'; q++); 43764887Schin if (!sep(*q)) 43774887Schin break; 43784887Schin for (s = q; w > y && *w != *(s + 1); w--); 43794887Schin } 43804887Schin else if (*w != *(s + 1)) 43814887Schin break; 43824887Schin } 43834887Schin if (!*w) 43844887Schin { 43854887Schin nov = 0; 43864887Schin break; 43874887Schin } 43884887Schin if (n = no) 43894887Schin { 43904887Schin m = 0; 43914887Schin s = e - 1; 43924887Schin w = y + n; 43934887Schin while (*++s) 43944887Schin { 43954887Schin if (*s == '*' || *s == '\a') 43964887Schin { 43974887Schin if (*s == '\a') 43984887Schin do 43994887Schin { 44004887Schin if (!*++s) 44014887Schin { 44024887Schin s--; 44034887Schin break; 44044887Schin } 44054887Schin } while (*s != '\a'); 44064887Schin j = *(s + 1); 44074887Schin if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0) 44084887Schin { 44094887Schin while (*w) 44104887Schin w++; 44114887Schin m = 0; 44124887Schin break; 44134887Schin } 44144887Schin m = 1; 44154887Schin } 44164887Schin else if (*s == *w || sep(*s) && sep(*w)) 44174887Schin w++; 44184887Schin else if (*w == 0) 44194887Schin break; 44204887Schin else if (!sep(*s)) 44214887Schin { 44224887Schin if (sep(*w)) 44234887Schin { 44244887Schin if (*++w == *s) 44254887Schin { 44264887Schin w++; 44274887Schin continue; 44284887Schin } 44294887Schin } 44304887Schin else if (w == y || sep(*(w - 1)) || isupper(*(w - 1)) && islower(*w)) 44314887Schin break; 44324887Schin for (q = s; *q && !sep(*q) && *q != '|' && *q != '?' && *q != ']'; q++); 44334887Schin if (!sep(*q)) 44344887Schin break; 44354887Schin for (s = q; w > y && *w != *(s + 1); w--); 44364887Schin } 44374887Schin else if (*w != *(s + 1)) 44384887Schin break; 44394887Schin } 44404887Schin if (!*w) 44414887Schin break; 44424887Schin } 44434887Schin if (*(s = skip(s, ':', '|', '?', 1, 0, 0, version)) != '|') 44444887Schin break; 44454887Schin w = y; 44464887Schin } 44474887Schin if (p) 44484887Schin s = p; 44494887Schin if (!*w) 44504887Schin { 44514887Schin if (n) 44524887Schin num = 0; 44534887Schin if (!(n = (m || *s == ':' || *s == '|' || *s == '?' || *s == ']' || *s == 0)) && x) 44544887Schin { 44554887Schin psp = pop(psp); 44564887Schin return opterror("?", version, catalog, 0); 44574887Schin } 44584887Schin for (x = k; *(f + 1) == '|' && (j = *(f + 2)) && j != '!' && j != '=' && j != ':' && j != '?' && j != ']'; f += 2); 44594887Schin if (*f == ':') 44604887Schin { 44614887Schin x = -1; 44624887Schin opt_info.option[1] = '-'; 44634887Schin opt_info.option[2] = 0; 44644887Schin } 44654887Schin else if (*(f + 1) == ':' || *(f + 1) == '!' && *(f + 2) == ':') 44664887Schin { 44674887Schin opt_info.option[1] = x; 44684887Schin opt_info.option[2] = 0; 44694887Schin } 44704887Schin else 44714887Schin { 44724887Schin a = f; 44734887Schin if (*a == '=') 44744887Schin a++; 44754887Schin else 44764887Schin { 44774887Schin if (*(a + 1) == '!') 44784887Schin a++; 44794887Schin if (*(a + 1) == '=') 44804887Schin a += 2; 44814887Schin } 44824887Schin x = -strtol(a, &b, 0); 44834887Schin if ((b - a) > sizeof(opt_info.option) - 2) 44844887Schin b = a + sizeof(opt_info.option) - 2; 44854887Schin memcpy(&opt_info.option[1], a, b - a); 44864887Schin opt_info.option[b - a + 1] = 0; 44874887Schin } 44884887Schin b = e; 44894887Schin if (t) 44904887Schin { 44914887Schin s = t; 44924887Schin t = 0; 44934887Schin } 44944887Schin a = s = skip(s, 0, 0, 0, 1, 0, 0, version); 44954887Schin if (n) 44964887Schin { 44974887Schin w = y; 44984887Schin break; 44994887Schin } 45004887Schin } 45014887Schin w = y; 45024887Schin } 45034887Schin else if (k == c && prefix == 1) 45044887Schin { 45054887Schin w = 0; 45064887Schin opt_info.name[1] = c; 45074887Schin opt_info.name[2] = 0; 45084887Schin opt_info.offset = 2; 45094887Schin opt_info.index--; 45104887Schin break; 45114887Schin } 45124887Schin if (t) 45134887Schin { 45144887Schin s = t; 45154887Schin if (a) 45164887Schin a = t; 45174887Schin } 45184887Schin } 45194887Schin s = skip(s, 0, 0, 0, 1, 0, 1, version); 45204887Schin if (*s == GO) 45214887Schin s = skip(s + 1, 0, 0, 0, 0, 1, 1, version); 45224887Schin if (cache) 45234887Schin { 45244887Schin m = OPT_cache_flag; 45254887Schin v = s; 45264887Schin if (*v == '#') 45274887Schin { 45284887Schin v++; 45294887Schin m |= OPT_cache_numeric; 45304887Schin } 45314887Schin else if (*v == ':') 45324887Schin { 45334887Schin v++; 45344887Schin m |= OPT_cache_string; 45354887Schin } 45364887Schin if (*v == '?') 45374887Schin { 45384887Schin v++; 45394887Schin m |= OPT_cache_optional; 45404887Schin } 45414887Schin else if (*v == *(v - 1)) 45424887Schin v++; 45434887Schin if (*(v = next(v, version)) == '[') 45444887Schin v = skip(v + 1, 0, 0, 0, 1, 0, 1, version); 45454887Schin if (*v != GO) 45464887Schin { 45474887Schin v = f; 45484887Schin for (;;) 45494887Schin { 45504887Schin if (isdigit(*f) && isdigit(*(f + 1))) 45514887Schin while (isdigit(*(f + 1))) 45524887Schin f++; 45534887Schin else if (*(f + 1) == '=') 45544887Schin break; 45554887Schin else 45564887Schin cache->flags[map[*f]] = m; 45574887Schin j = 0; 45584887Schin while (*(f + 1) == '|') 45594887Schin { 45604887Schin f += 2; 45614887Schin if (!(j = *f) || j == '!' || j == '=' || j == ':' || j == '?' || j == ']') 45624887Schin break; 45634887Schin cache->flags[map[j]] = m; 45644887Schin } 45654887Schin if (j != '!' || (m & OPT_cache_invert)) 45664887Schin break; 45674887Schin f = v; 45684887Schin m |= OPT_cache_invert; 45694887Schin } 45704887Schin } 45714887Schin } 45724887Schin else 45734887Schin { 45744887Schin m = 0; 45754887Schin if (!w) 45764887Schin { 45774887Schin if (isdigit(*f) && isdigit(*(f + 1))) 45784887Schin k = -1; 45794887Schin if (c == k) 45804887Schin m = 1; 45814887Schin while (*(f + 1) == '|') 45824887Schin { 45834887Schin f += 2; 45844887Schin if (!(j = *f)) 45854887Schin { 45864887Schin m = 0; 45874887Schin break; 45884887Schin } 45894887Schin else if (j == c) 45904887Schin m = 1; 45914887Schin else if (j == '!' || j == '=' || j == ':' || j == '?' || j == ']') 45924887Schin break; 45934887Schin } 45944887Schin } 45954887Schin if (m) 45964887Schin { 45974887Schin s--; 45984887Schin if (*++f == '!') 45994887Schin { 46004887Schin f++; 46014887Schin num = 0; 46024887Schin } 46034887Schin if (*f == '=') 46044887Schin { 46054887Schin c = -strtol(++f, &b, 0); 46064887Schin if ((b - f) > sizeof(opt_info.option) - 2) 46074887Schin b = f + sizeof(opt_info.option) - 2; 46084887Schin memcpy(&opt_info.option[1], f, b - f); 46094887Schin opt_info.option[b - f + 1] = 0; 46104887Schin } 46114887Schin else 46124887Schin c = k; 46134887Schin break; 46144887Schin } 46154887Schin } 46164887Schin if (*s == '#') 46174887Schin { 46184887Schin if (!numopt && s > opts) 46194887Schin { 46204887Schin numopt = s - 1; 46214887Schin numchr = k; 46224887Schin if (*f == ':') 46234887Schin numchr = -1; 46244887Schin else if (*(f + 1) != ':' && *(f + 1) != '!' && *(f + 1) != ']') 46254887Schin { 46264887Schin a = f; 46274887Schin if (*a == '=') 46284887Schin a++; 46294887Schin else 46304887Schin { 46314887Schin if (*(a + 1) == '!') 46324887Schin a++; 46334887Schin if (*(a + 1) == '=') 46344887Schin a += 2; 46354887Schin } 46364887Schin numchr = -strtol(a, NiL, 0); 46374887Schin } 46384887Schin } 46394887Schin } 46404887Schin else if (*s != ':') 46414887Schin continue; 46424887Schin } 46434887Schin else if (*s == ']') 46444887Schin { 46454887Schin s++; 46464887Schin continue; 46474887Schin } 46484887Schin else if (*s == '#') 46494887Schin { 46504887Schin if (!numopt && s > opts) 46514887Schin numchr = *(numopt = s - 1); 46524887Schin } 46534887Schin else if (*s != ':') 46544887Schin { 46554887Schin if (cache) 46564887Schin { 46574887Schin m = OPT_cache_flag; 46584887Schin if (*(s + 1) == '#') 46594887Schin { 46604887Schin m |= OPT_cache_numeric; 46614887Schin if (*(s + 2) == '?') 46624887Schin m |= OPT_cache_optional; 46634887Schin } 46644887Schin else if (*(s + 1) == ':') 46654887Schin { 46664887Schin m |= OPT_cache_string; 46674887Schin if (*(s + 2) == '?') 46684887Schin m |= OPT_cache_optional; 46694887Schin } 46704887Schin cache->flags[map[*s]] = m; 46714887Schin } 46724887Schin s++; 46734887Schin continue; 46744887Schin } 46754887Schin message((-21, "optget: opt %s", show(s))); 46764887Schin if (*++s == '?' || *s == *(s - 1)) 46774887Schin s++; 46784887Schin if (*(s = next(s, version)) == '[') 46794887Schin { 46804887Schin s = skip(s + 1, 0, 0, 0, 1, 0, 1, version); 46814887Schin if (*s == GO) 46824887Schin s = skip(s + 1, 0, 0, 0, 0, 1, 1, version); 46834887Schin } 4684*10898Sroland.mainz@nrubsig.org message((-21, "optget: opt %s", show(s))); 46854887Schin } 46864887Schin if (w && x) 46874887Schin { 46884887Schin s = skip(b, '|', '?', 0, 1, 0, 0, version); 46894887Schin if (v && (a == 0 || *a == 0 || *(a + 1) != ':' && *(a + 1) != '#') && (*v == '0' || *v == '1') && !*(v + 1)) 46904887Schin { 46914887Schin if (*v == '0') 46924887Schin num = !num; 46934887Schin v = 0; 46944887Schin } 46954887Schin if ((s - b) >= elementsof(opt_info.name)) 46964887Schin s = b + elementsof(opt_info.name) - 1; 46974887Schin for (;;) 46984887Schin { 46994887Schin if (b >= s) 47004887Schin { 47014887Schin *w = 0; 47024887Schin break; 47034887Schin } 47044887Schin if (*b == '*') 47054887Schin break; 47064887Schin *w++ = *b++; 47074887Schin } 47084887Schin if (!num && v) 47094887Schin return opterror(no ? "!" : "=", version, catalog, 0); 47104887Schin w = &opt_info.name[prefix]; 47114887Schin c = x; 47124887Schin s = a; 47134887Schin } 47144887Schin } 47154887Schin if (!*s) 47164887Schin { 47174887Schin if (w) 47184887Schin { 47194887Schin if (hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), w)) 47204887Schin { 47214887Schin if (!v) 47224887Schin v = (char*)hp->name; 47234887Schin goto help; 47244887Schin } 47254887Schin if (!v) 47264887Schin { 47274887Schin v = opt_info.name; 47284887Schin goto help; 47294887Schin } 47304887Schin } 47318462SApril.Chin@Sun.COM if (w || !isdigit(c) || !numopt || !(pass->flags & OPT_numeric)) 47324887Schin { 47334887Schin pop(psp); 47344887Schin return opterror("", version, catalog, 0); 47354887Schin } 47364887Schin s = numopt; 47374887Schin c = opt_info.option[1] = numchr; 47384887Schin opt_info.offset--; 47394887Schin } 47404887Schin opt_info.arg = 0; 47414887Schin 47424887Schin /* 47434887Schin * this is a ksh getopts workaround 47444887Schin */ 47454887Schin 47464887Schin if (opt_info.num != LONG_MIN) 4747*10898Sroland.mainz@nrubsig.org opt_info.num = (long)(opt_info.number = num); 47484887Schin if ((n = *++s == '#') || *s == ':' || w && !nov && v && (optnumber(v, &e, NiL), n = !*e)) 47494887Schin { 47504887Schin if (w) 47514887Schin { 47524887Schin if (nov) 47534887Schin { 47544887Schin if (v) 47554887Schin { 47564887Schin pop(psp); 47574887Schin return opterror("!", version, catalog, 0); 47584887Schin } 4759*10898Sroland.mainz@nrubsig.org opt_info.num = (long)(opt_info.number = 0); 47604887Schin } 47614887Schin else 47624887Schin { 47634887Schin if (!v && *(s + 1) != '?' && (v = argv[opt_info.index])) 47644887Schin { 47654887Schin opt_info.index++; 47664887Schin opt_info.offset = 0; 47674887Schin } 47684887Schin if (!(opt_info.arg = v) || (*v == '0' || *v == '1') && !*(v + 1)) 47694887Schin { 47704887Schin if (*(s + 1) != '?') 47714887Schin { 47724887Schin if (!opt_info.arg) 47734887Schin { 47744887Schin pop(psp); 47754887Schin return opterror(s, version, catalog, 0); 47764887Schin } 47774887Schin } 47784887Schin else if (*(t = next(s + 2, version)) == '[') 47794887Schin while (*(t = skip(t, ':', 0, 0, 1, 0, 0, version)) == ':') 47804887Schin if (*++t == '!') 47814887Schin { 47824887Schin if (!v || *v == '1') 47834887Schin { 47844887Schin e = skip(t, ':', '?', ']', 1, 0, 0, version); 47854887Schin opt_info.arg = sfprints("%-.*s", e - t - 1, t + 1); 47864887Schin } 47874887Schin else 47884887Schin { 47894887Schin opt_info.arg = 0; 4790*10898Sroland.mainz@nrubsig.org opt_info.num = (long)(opt_info.number = 0); 47914887Schin } 47924887Schin break; 47934887Schin } 47944887Schin } 47954887Schin if (opt_info.arg && n) 47964887Schin { 47974887Schin opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err)); 47984887Schin if (err || e == opt_info.arg) 47994887Schin { 48004887Schin pop(psp); 48014887Schin return opterror(s, version, catalog, err); 48024887Schin } 48034887Schin } 48044887Schin } 48054887Schin goto optarg; 48064887Schin } 48074887Schin else if (*(opt_info.arg = &argv[opt_info.index++][opt_info.offset])) 48084887Schin { 48094887Schin if (*s == '#') 48104887Schin { 48114887Schin opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err)); 48124887Schin if (err || e == opt_info.arg) 48134887Schin { 48144887Schin if (!err && *(s + 1) == '?') 48154887Schin { 48164887Schin opt_info.arg = 0; 48174887Schin opt_info.index--; 48184887Schin } 48194887Schin else 48204887Schin { 48214887Schin opt_info.offset = 0; 48224887Schin c = opterror(s, version, catalog, err); 48234887Schin } 48244887Schin pop(psp); 48254887Schin return c; 48264887Schin } 48274887Schin else if (*e) 48284887Schin { 48294887Schin opt_info.offset += e - opt_info.arg; 48304887Schin opt_info.index--; 48314887Schin pop(psp); 48324887Schin return c; 48334887Schin } 48344887Schin } 48354887Schin } 48364887Schin else if (opt_info.arg = argv[opt_info.index]) 48374887Schin { 48384887Schin opt_info.index++; 48394887Schin if (*(s + 1) == '?' && (*opt_info.arg == '-' || (pass->flags & OPT_plus) && *opt_info.arg == '+') && *(opt_info.arg + 1)) 48404887Schin { 48414887Schin opt_info.index--; 48424887Schin opt_info.arg = 0; 48434887Schin } 48444887Schin else if (*s == '#') 48454887Schin { 48464887Schin opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err)); 48474887Schin if (err || *e) 48484887Schin { 48494887Schin if (!err && *(s + 1) == '?') 48504887Schin { 48514887Schin opt_info.arg = 0; 48524887Schin opt_info.index--; 48534887Schin } 48544887Schin else 48554887Schin { 48564887Schin pop(psp); 48574887Schin opt_info.offset = 0; 48584887Schin return opterror(s, version, catalog, err); 48594887Schin } 48604887Schin } 48614887Schin } 48624887Schin } 48634887Schin else if (*(s + 1) != '?') 48644887Schin { 48654887Schin opt_info.index--; 48664887Schin pop(psp); 48674887Schin return opterror(s, version, catalog, 0); 48684887Schin } 48694887Schin opt_info.offset = 0; 48704887Schin optarg: 48714887Schin if (*s == ':' && *(s = skip(s, 0, 0, 0, 1, 0, 1, version)) == GO && *(s = next(s + 1, version)) == '[' && isalnum(*(s + 1))) 48724887Schin { 48734887Schin x = 0; 48744887Schin if (opt_info.arg) 48754887Schin { 48764887Schin do 48774887Schin { 48784887Schin w = y = opt_info.arg; 48794887Schin f = s = next(s + 1, version); 48804887Schin k = *f; 48814887Schin if (k == *w && isalpha(k) && !*(w + 1)) 48824887Schin { 48834887Schin x = k; 48844887Schin break; 48854887Schin } 48864887Schin if (*s == '+' || *s == '-') 48874887Schin continue; 48884887Schin else if (*s == '[' || version < 1) 48894887Schin continue; 48904887Schin else 48914887Schin { 48924887Schin if (*s != ':') 48934887Schin s = skip(s, ':', '?', 0, 1, 0, 0, version); 48944887Schin if (*s == ':') 48954887Schin { 48964887Schin if (catalog) 48974887Schin { 48984887Schin p = skip(s + 1, '?', 0, 0, 1, 0, 0, version); 48994887Schin e = sfprints("%-.*s", p - (s + 1), s + 1); 49004887Schin b = T(error_info.id, catalog, e); 49014887Schin if (b == e) 49024887Schin p = 0; 49034887Schin else 49044887Schin { 49054887Schin sfprintf(xp, ":%s|%s?", b, e); 49064887Schin if (!(s = sfstruse(xp))) 49074887Schin goto nospace; 49084887Schin } 49094887Schin } 49104887Schin else 49114887Schin p = 0; 49124887Schin for (;;) 49134887Schin { 49144887Schin n = m = 0; 49154887Schin e = s + 1; 49164887Schin while (*++s) 49174887Schin { 49184887Schin if (*s == '*' || *s == '\a') 49194887Schin { 49204887Schin if (*s == '\a') 49214887Schin do 49224887Schin { 49234887Schin if (!*++s) 49244887Schin { 49254887Schin s--; 49264887Schin break; 49274887Schin } 49284887Schin } while (*s != '\a'); 49294887Schin j = *(s + 1); 49304887Schin if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0) 49314887Schin { 49324887Schin while (*w) 49334887Schin w++; 49344887Schin m = 0; 49354887Schin break; 49364887Schin } 49374887Schin m = 1; 49384887Schin } 49394887Schin else if (*s == *w || sep(*s) && sep(*w)) 49404887Schin w++; 49414887Schin else if (*w == 0) 49424887Schin break; 49434887Schin else if (!sep(*s)) 49444887Schin { 49454887Schin if (sep(*w)) 49464887Schin { 49474887Schin if (*++w == *s) 49484887Schin { 49494887Schin w++; 49504887Schin continue; 49514887Schin } 49524887Schin } 49534887Schin else if (w == y || sep(*(w - 1)) || isupper(*(w - 1)) && islower(*w)) 49544887Schin break; 49554887Schin for (q = s; *q && !sep(*q) && *q != '|' && *q != '?' && *q != ']'; q++); 49564887Schin if (!sep(*q)) 49574887Schin break; 49584887Schin for (s = q; w > y && *w != *(s + 1); w--); 49594887Schin } 49604887Schin else if (*w != *(s + 1)) 49614887Schin break; 49624887Schin } 49634887Schin if (!*w) 49644887Schin { 49654887Schin nov = 0; 49664887Schin break; 49674887Schin } 49684887Schin if (*(s = skip(s, ':', '|', '?', 1, 0, 0, version)) != '|') 49694887Schin break; 49704887Schin w = y; 49714887Schin } 49724887Schin if (p) 49734887Schin s = p; 49744887Schin if (!*w) 49754887Schin { 49764887Schin if (n) 49774887Schin num = 0; 49784887Schin if (!(n = (m || *s == ':' || *s == '|' || *s == '?' || *s == ']')) && x) 49794887Schin { 49804887Schin pop(psp); 49814887Schin return opterror("&", version, catalog, 0); 49824887Schin } 49834887Schin for (x = k; *(f + 1) == '|' && (j = *(f + 2)) && j != '!' && j != '=' && j != ':' && j != '?' && j != ']'; f += 2); 49844887Schin if (*f == ':') 49854887Schin x = -1; 49864887Schin else if (*(f + 1) == ':' || *(f + 1) == '!' && *(f + 2) == ':') 49874887Schin /* ok */; 49884887Schin else 49894887Schin { 49904887Schin a = f; 49914887Schin if (*a == '=') 49924887Schin a++; 49934887Schin else 49944887Schin { 49954887Schin if (*(a + 1) == '!') 49964887Schin a++; 49974887Schin if (*(a + 1) == '=') 49984887Schin a += 2; 49994887Schin } 50004887Schin x = -strtol(a, &b, 0); 50014887Schin } 50024887Schin b = e; 50034887Schin a = s = skip(s, 0, 0, 0, 1, 0, 0, version); 50044887Schin if (n) 50054887Schin break; 50064887Schin } 50074887Schin } 50084887Schin } 50094887Schin } while (*(s = skip(s, 0, 0, 0, 1, 0, 1, version)) == '['); 5010*10898Sroland.mainz@nrubsig.org if (!(opt_info.num = (long)(opt_info.number = x))) 50114887Schin { 50124887Schin pop(psp); 50134887Schin return opterror("*", version, catalog, 0); 50144887Schin } 50154887Schin } 50164887Schin } 50174887Schin } 50184887Schin else if (w && v) 50194887Schin { 50204887Schin pop(psp); 50214887Schin return opterror("=", version, catalog, 0); 50224887Schin } 50234887Schin else 50244887Schin { 5025*10898Sroland.mainz@nrubsig.org opt_info.num = (long)(opt_info.number = num); 50264887Schin if (!w && !argv[opt_info.index][opt_info.offset]) 50274887Schin { 50284887Schin opt_info.offset = 0; 50294887Schin opt_info.index++; 50304887Schin } 50314887Schin } 50324887Schin pop(psp); 50334887Schin return c; 50344887Schin help: 50354887Schin if (v && *v == '?' && *(v + 1) == '?' && *(v + 2)) 50364887Schin { 50374887Schin s = v + 2; 50384887Schin if ((s[0] == 'n' || s[0] == 'N') && (s[1] == 'o' || s[1] == 'O')) 50394887Schin { 50404887Schin s += 2; 50414887Schin n = -1; 50424887Schin } 50434887Schin else 50444887Schin n = 1; 50454887Schin if (hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), s)) 50464887Schin { 50474887Schin if (hp->style < STYLE_man || !(s = argv[opt_info.index]) || s[0] != '-' || s[1] != '-' || !s[2]) 50484887Schin { 50494887Schin opt_info.arg = sfprints("\fversion=%d", version); 50504887Schin pop(psp); 50514887Schin return '?'; 50524887Schin } 50534887Schin opt_info.state->force = hp->style; 50544887Schin } 50554887Schin else if (match(s, "ESC", -1, NiL) || match(s, "EMPHASIS", -1, NiL)) 50564887Schin opt_info.state->emphasis = n; 50574887Schin else if (match(s, "PREFORMAT", -1, NiL)) 50584887Schin opt_info.state->flags |= OPT_preformat; 50594887Schin else if (match(s, "TEST", -1, NiL)) 50604887Schin { 50614887Schin opt_info.state->width = OPT_WIDTH; 50624887Schin opt_info.state->emphasis = 1; 50634887Schin } 50644887Schin else 50654887Schin { 50664887Schin pop(psp); 50674887Schin return opterror(v, version, catalog, 0); 50684887Schin } 50694887Schin psp = pop(psp); 50704887Schin if (argv == opt_info.state->strv) 50714887Schin return '#'; 50724887Schin goto again; 50734887Schin } 50744887Schin if ((opt_info.arg = opthelp(NiL, v)) == (char*)unknown) 50754887Schin { 50764887Schin pop(psp); 50774887Schin return opterror(v, version, catalog, 0); 50784887Schin } 50794887Schin pop(psp); 50804887Schin return '?'; 50814887Schin nospace: 50824887Schin pop(psp); 50834887Schin return opterror(NiL, 0, NiL, 0); 50844887Schin } 50854887Schin 50864887Schin /* 50874887Schin * parse long options with 0,1,2 leading '-' or '+' from string and pass to optget() 50884887Schin * syntax is the unquoted 50894887Schin * 50904887Schin * <length> [-|+|--|++]<name>[[-+:|&=]=<value>\n (or \0 for the last) 50914887Schin * 50924887Schin * or the quoted 50934887Schin * 50944887Schin * [-|+|--|++][no]name[[-+:|&=]=['"{(]value[)}"']][, ]... 50954887Schin * 50964887Schin * with \x escapes passed to chresc() 50974887Schin * 50984887Schin * return '#' for `label:', with opt_info.name==label 50994887Schin * str[opt_info.offset] next arg 51004887Schin * 51014887Schin * optstr(s, 0) 51024887Schin * return '-' if arg, 0 otherwise 51034887Schin * optstr(0, opts) 51044887Schin * use previous parsed str 51054887Schin */ 51064887Schin 51074887Schin int 51084887Schin optstr(const char* str, const char* opts) 51094887Schin { 51104887Schin register char* s = (char*)str; 51114887Schin register Sfio_t* mp; 51124887Schin register int c; 51134887Schin register int ql; 51144887Schin register int qr; 51154887Schin register int qc; 51164887Schin int v; 51174887Schin char* e; 51184887Schin 51194887Schin again: 51204887Schin if (s) 51214887Schin { 51224887Schin if (!(mp = opt_info.state->strp) && !(mp = opt_info.state->strp = sfstropen())) 51234887Schin return 0; 51244887Schin if (opt_info.state->str != s) 51254887Schin opt_info.state->str = s; 51264887Schin else if (opt_info.index == 1) 51274887Schin s += opt_info.offset; 51284887Schin while (*s == ',' || *s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') 51294887Schin s++; 51304887Schin if (!*s) 51314887Schin { 51324887Schin opt_info.state->str = 0; 51334887Schin return 0; 51344887Schin } 51354887Schin if (*s == '-' || *s == '+') 51364887Schin { 51374887Schin c = *s++; 51384887Schin sfputc(mp, c); 51394887Schin if (*s == c) 51404887Schin { 51414887Schin sfputc(mp, c); 51424887Schin s++; 51434887Schin } 51444887Schin } 51454887Schin else 51464887Schin { 51474887Schin sfputc(mp, '-'); 51484887Schin sfputc(mp, '-'); 51494887Schin } 51504887Schin if (isdigit(*s) && (v = (int)strtol(s, &e, 10)) > 1 && isspace(*e) && --v <= strlen(s) && (s[v] == 0 || s[v] == '\n')) 51514887Schin { 51524887Schin s += v; 51534887Schin while (isspace(*++e)); 51544887Schin sfwrite(mp, e, s - e); 51554887Schin } 51564887Schin else 51574887Schin { 51584887Schin while (*s && *s != ',' && *s != ' ' && *s != '\t' && *s != '\n' && *s != '\r' && *s != '=' && *s != ':') 51594887Schin sfputc(mp, *s++); 51604887Schin if ((c = *s) == ':' && *(s + 1) != '=') 51614887Schin { 51624887Schin opt_info.index = 1; 51634887Schin opt_info.offset = ++s - (char*)str; 51644887Schin if (!(s = sfstruse(mp))) 51654887Schin goto nospace; 51664887Schin s += 2; 51674887Schin e = opt_info.name; 51684887Schin while (e < &opt_info.name[sizeof(opt_info.name)-1] && (*e++ = *s++)); 51694887Schin opt_info.arg = 0; 5170*10898Sroland.mainz@nrubsig.org opt_info.num = (long)(opt_info.number = 0); 51714887Schin opt_info.option[0] = ':'; 51724887Schin opt_info.option[1] = 0; 51734887Schin return '#'; 51744887Schin } 51754887Schin if (c == ':' || c == '=') 51764887Schin { 51774887Schin sfputc(mp, c); 51784887Schin ql = qr = 0; 51794887Schin while (c = *++s) 51804887Schin { 51814887Schin if (c == '\\') 51824887Schin { 51834887Schin sfputc(mp, chresc(s, &e)); 51844887Schin s = e - 1; 51854887Schin } 51864887Schin else if (c == qr) 51874887Schin { 51884887Schin if (qr != ql) 51894887Schin sfputc(mp, c); 51904887Schin if (--qc <= 0) 51914887Schin qr = ql = 0; 51924887Schin } 51934887Schin else if (c == ql) 51944887Schin { 51954887Schin sfputc(mp, c); 51964887Schin qc++; 51974887Schin } 51984887Schin else if (qr) 51994887Schin sfputc(mp, c); 52004887Schin else if (c == ',' || c == ' ' || c == '\t' || c == '\n' || c == '\r') 52014887Schin break; 52024887Schin else if (c == '"' || c == '\'') 52034887Schin { 52044887Schin ql = qr = c; 52054887Schin qc = 1; 52064887Schin } 52074887Schin else 52084887Schin { 52094887Schin sfputc(mp, c); 52104887Schin if (c == GO) 52114887Schin { 52124887Schin ql = c; 52134887Schin qr = OG; 52144887Schin qc = 1; 52154887Schin } 52164887Schin else if (c == '(') 52174887Schin { 52184887Schin ql = c; 52194887Schin qr = ')'; 52204887Schin qc = 1; 52214887Schin } 52224887Schin } 52234887Schin } 52244887Schin } 52254887Schin } 52264887Schin opt_info.argv = opt_info.state->strv; 52274887Schin opt_info.state->strv[0] = T(NiL, ID, "option"); 52284887Schin if (!(opt_info.state->strv[1] = sfstruse(mp))) 52294887Schin goto nospace; 52304887Schin opt_info.state->strv[2] = 0; 52314887Schin opt_info.offset = s - (char*)str; 52324887Schin } 52334887Schin if (opts) 52344887Schin { 52354887Schin if (!opt_info.state->strv[1]) 52364887Schin { 52374887Schin opt_info.state->str = 0; 52384887Schin return 0; 52394887Schin } 52404887Schin opt_info.index = 1; 52414887Schin v = opt_info.offset; 52424887Schin opt_info.offset = 0; 52434887Schin c = optget(opt_info.state->strv, opts); 52444887Schin opt_info.index = 1; 52454887Schin opt_info.offset = v; 52464887Schin if (c == '#') 52474887Schin { 52484887Schin s = opt_info.state->str; 52494887Schin goto again; 52504887Schin } 52514887Schin if ((c == '?' || c == ':') && (opt_info.arg[0] == '-' && opt_info.arg[1] == '-')) 52524887Schin opt_info.arg += 2; 52534887Schin s = opt_info.name; 52544887Schin if (*s++ == '-' && *s++ == '-' && *s) 52554887Schin { 52564887Schin e = opt_info.name; 52574887Schin while (*e++ = *s++); 52584887Schin } 52594887Schin } 52604887Schin else 52614887Schin c = '-'; 52624887Schin return c; 52634887Schin nospace: 52644887Schin return opterror(NiL, 0, NiL, 0); 52654887Schin } 5266