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