1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1985-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> *
18da2e3ebdSchin * David Korn <dgk@research.att.com> *
19da2e3ebdSchin * Phong Vo <kpv@research.att.com> *
20da2e3ebdSchin * *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #pragma prototyped
23da2e3ebdSchin /*
24da2e3ebdSchin * Glenn Fowler
25da2e3ebdSchin * AT&T Research
26da2e3ebdSchin *
27da2e3ebdSchin * command line option parser and usage formatter
28da2e3ebdSchin * its a monster but its all in one place
29da2e3ebdSchin * widen your window while you're at it
30da2e3ebdSchin */
31da2e3ebdSchin
32da2e3ebdSchin #include <optlib.h>
33da2e3ebdSchin #include <debug.h>
34da2e3ebdSchin #include <ccode.h>
35da2e3ebdSchin #include <ctype.h>
36da2e3ebdSchin #include <errno.h>
37da2e3ebdSchin
38da2e3ebdSchin #define KEEP "*[A-Za-z][A-Za-z]*"
39da2e3ebdSchin #define OMIT "*@(\\[[-+]*\\?*\\]|\\@\\(#\\)|Copyright \\(c\\)|\\$\\I\\d\\: )*"
40da2e3ebdSchin
41da2e3ebdSchin #define GO '{' /* group nest open */
42da2e3ebdSchin #define OG '}' /* group nest close */
43da2e3ebdSchin
44da2e3ebdSchin #define OPT_WIDTH 80 /* default help text width */
45da2e3ebdSchin #define OPT_MARGIN 10 /* default help text margin */
46da2e3ebdSchin #define OPT_USAGE 7 /* usage continuation indent */
47da2e3ebdSchin
48da2e3ebdSchin #define OPT_flag 0x001 /* flag ( 0 or 1 ) */
49da2e3ebdSchin #define OPT_hidden 0x002 /* remaining are hidden */
50da2e3ebdSchin #define OPT_ignorecase 0x004 /* arg match ignores case */
51da2e3ebdSchin #define OPT_invert 0x008 /* flag inverts long sense */
52da2e3ebdSchin #define OPT_listof 0x010 /* arg is ' ' or ',' list */
5334f9b3eeSRoland Mainz #define OPT_number 0x020 /* arg is strtonll() number */
5434f9b3eeSRoland Mainz #define OPT_oneof 0x040 /* arg may be set once */
5534f9b3eeSRoland Mainz #define OPT_optional 0x080 /* arg is optional */
5634f9b3eeSRoland Mainz #define OPT_string 0x100 /* arg is string */
57da2e3ebdSchin
58da2e3ebdSchin #define OPT_preformat 0001 /* output preformat string */
5934f9b3eeSRoland Mainz #define OPT_proprietary 0002 /* proprietary docs */
60da2e3ebdSchin
61da2e3ebdSchin #define OPT_TYPE (OPT_flag|OPT_number|OPT_string)
62da2e3ebdSchin
63da2e3ebdSchin #define STYLE_posix 0 /* posix getopt usage */
64da2e3ebdSchin #define STYLE_short 1 /* [default] short usage */
65da2e3ebdSchin #define STYLE_long 2 /* long usage */
66da2e3ebdSchin #define STYLE_match 3 /* long description of matches */
67da2e3ebdSchin #define STYLE_options 4 /* short and long descriptions */
68da2e3ebdSchin #define STYLE_man 5 /* pretty details */
69da2e3ebdSchin #define STYLE_html 6 /* html details */
70da2e3ebdSchin #define STYLE_nroff 7 /* nroff details */
71da2e3ebdSchin #define STYLE_api 8 /* program details */
72da2e3ebdSchin #define STYLE_keys 9 /* translation key strings */
73da2e3ebdSchin #define STYLE_usage 10 /* escaped usage string */
74da2e3ebdSchin
75da2e3ebdSchin #define FONT_BOLD 1
76da2e3ebdSchin #define FONT_ITALIC 2
77da2e3ebdSchin #define FONT_LITERAL 4
78da2e3ebdSchin
79da2e3ebdSchin #define sep(c) ((c)=='-'||(c)=='_')
80da2e3ebdSchin
81da2e3ebdSchin typedef struct Attr_s
82da2e3ebdSchin {
83da2e3ebdSchin const char* name;
84da2e3ebdSchin int flag;
85da2e3ebdSchin } Attr_t;
86da2e3ebdSchin
87da2e3ebdSchin typedef struct Help_s
88da2e3ebdSchin {
89da2e3ebdSchin const char* match; /* builtin help match name */
90da2e3ebdSchin const char* name; /* builtin help name */
91da2e3ebdSchin int style; /* STYLE_* */
92da2e3ebdSchin const char* text; /* --? text */
93da2e3ebdSchin unsigned int size; /* strlen text */
94da2e3ebdSchin } Help_t;
95da2e3ebdSchin
96da2e3ebdSchin typedef struct Font_s
97da2e3ebdSchin {
98da2e3ebdSchin const char* html[2];
99da2e3ebdSchin const char* nroff[2];
100da2e3ebdSchin const char* term[2];
101da2e3ebdSchin } Font_t;
102da2e3ebdSchin
103da2e3ebdSchin typedef struct List_s
104da2e3ebdSchin {
105da2e3ebdSchin int type; /* { - + : } */
106da2e3ebdSchin const char* name; /* list name */
107da2e3ebdSchin const char* text; /* help text */
108da2e3ebdSchin } List_t;
109da2e3ebdSchin
110da2e3ebdSchin typedef struct Msg_s
111da2e3ebdSchin {
112da2e3ebdSchin const char* text; /* default message text */
113da2e3ebdSchin Dtlink_t link; /* cdt link */
114da2e3ebdSchin } Msg_t;
115da2e3ebdSchin
116da2e3ebdSchin typedef struct Save_s
117da2e3ebdSchin {
118da2e3ebdSchin Dtlink_t link; /* cdt link */
119da2e3ebdSchin char text[1]; /* saved text text */
120da2e3ebdSchin } Save_t;
121da2e3ebdSchin
122da2e3ebdSchin typedef struct Push_s
123da2e3ebdSchin {
124da2e3ebdSchin struct Push_s* next; /* next string */
125da2e3ebdSchin char* ob; /* next char in old string */
126da2e3ebdSchin char* oe; /* end of old string */
127da2e3ebdSchin char* nb; /* next char in new string */
128da2e3ebdSchin char* ne; /* end of new string */
129da2e3ebdSchin int ch; /* localize() translation */
130da2e3ebdSchin } Push_t;
131da2e3ebdSchin
132da2e3ebdSchin typedef struct Indent_s
133da2e3ebdSchin {
134da2e3ebdSchin int stop; /* tab column position */
135da2e3ebdSchin } Indent_t;
136da2e3ebdSchin
137da2e3ebdSchin static Indent_t indent[] =
138da2e3ebdSchin {
139da2e3ebdSchin 0,2, 4,10, 12,18, 20,26, 28,34, 36,42, 44,50, 0,0
140da2e3ebdSchin };
141da2e3ebdSchin
142da2e3ebdSchin static const char term_off[] = {CC_esc,'[','0','m',0};
143da2e3ebdSchin static const char term_B_on[] = {CC_esc,'[','1','m',0};
144da2e3ebdSchin static const char term_I_on[] = {CC_esc,'[','1',';','4','m',0};
145da2e3ebdSchin
146da2e3ebdSchin static const Font_t fonts[] =
147da2e3ebdSchin {
148da2e3ebdSchin "", "", "", "", "", "",
149da2e3ebdSchin "</B>", "<B>", "\\fP", "\\fB", &term_off[0], &term_B_on[0],
150da2e3ebdSchin "</I>", "<I>", "\\fP", "\\fI", &term_off[0], &term_I_on[0],
151da2e3ebdSchin "", "", "", "", "", "",
152da2e3ebdSchin "</TT>","<TT>","\\fP", "\\f5", "", "",
153da2e3ebdSchin };
154da2e3ebdSchin
155da2e3ebdSchin static char native[] = "";
156da2e3ebdSchin
157da2e3ebdSchin #if !_PACKAGE_astsa
158da2e3ebdSchin
159da2e3ebdSchin #define ID ast.id
160da2e3ebdSchin
161da2e3ebdSchin #define C(s) ERROR_catalog(s)
162da2e3ebdSchin #define D(s) (opt_info.state->msgdict && dtmatch(opt_info.state->msgdict, (s)))
163da2e3ebdSchin #define T(i,c,m) (X(c)?translate(i,c,C(m)):(m))
164da2e3ebdSchin #define X(c) (ERROR_translating()&&(c)!=native)
165da2e3ebdSchin #define Z(x) C(x),sizeof(x)-1
166da2e3ebdSchin
167da2e3ebdSchin /*
168da2e3ebdSchin * translate with C_LC_MESSAGES_libast[] check
169da2e3ebdSchin */
170da2e3ebdSchin
171da2e3ebdSchin static char*
translate(const char * cmd,const char * cat,const char * msg)172da2e3ebdSchin translate(const char* cmd, const char* cat, const char* msg)
173da2e3ebdSchin {
174da2e3ebdSchin if (!X(cat))
175da2e3ebdSchin return (char*)msg;
176da2e3ebdSchin if (cat != (const char*)ID && D(msg))
177da2e3ebdSchin cat = (const char*)ID;
178da2e3ebdSchin return errorx(NiL, cmd, cat, msg);
179da2e3ebdSchin }
180da2e3ebdSchin
181da2e3ebdSchin #else
182da2e3ebdSchin
183da2e3ebdSchin static char ID[] = "ast";
184da2e3ebdSchin
185da2e3ebdSchin #define C(s) s
186da2e3ebdSchin #define D(s) (opt_info.state->msgdict && dtmatch(opt_info.state->msgdict, (s)))
187da2e3ebdSchin #define T(i,c,m) m
188da2e3ebdSchin #define X(c) 0
189da2e3ebdSchin #define Z(x) C(x),sizeof(x)-1
190da2e3ebdSchin
191da2e3ebdSchin #endif
192da2e3ebdSchin
193da2e3ebdSchin static const List_t help_head[] =
194da2e3ebdSchin {
195da2e3ebdSchin '-', 0,
196da2e3ebdSchin 0,
197da2e3ebdSchin '+', C("NAME"),
198da2e3ebdSchin C("options available to all \bast\b commands"),
199da2e3ebdSchin '+', C("DESCRIPTION"),
200da2e3ebdSchin C("\b-?\b and \b--?\b* options are the same \
201da2e3ebdSchin for all \bast\b commands. For any \aitem\a below, if \b--\b\aitem\a is not \
202da2e3ebdSchin supported by a given command then it is equivalent to \b--\?\?\b\aitem\a. The \
203da2e3ebdSchin \b--\?\?\b form should be used for portability. All output is written to the \
204da2e3ebdSchin standard error."),
205da2e3ebdSchin };
206da2e3ebdSchin
207da2e3ebdSchin static const Help_t styles[] =
208da2e3ebdSchin {
209da2e3ebdSchin C("about"), "-", STYLE_match,
210da2e3ebdSchin Z("List all implementation info."),
211da2e3ebdSchin C("api"), "?api", STYLE_api,
212da2e3ebdSchin Z("List detailed info in program readable form."),
213da2e3ebdSchin C("help"), "", -1,
214da2e3ebdSchin Z("List detailed help option info."),
215da2e3ebdSchin C("html"), "?html", STYLE_html,
216da2e3ebdSchin Z("List detailed info in html."),
217da2e3ebdSchin C("keys"), "?keys", STYLE_keys,
218da2e3ebdSchin Z("List the usage translation key strings with C style escapes."),
219da2e3ebdSchin C("long"), "?long", STYLE_long,
220da2e3ebdSchin Z("List long option usage."),
221da2e3ebdSchin C("man"), "?man", STYLE_man,
222da2e3ebdSchin Z("List detailed info in displayed man page form."),
223da2e3ebdSchin C("nroff"), "?nroff", STYLE_nroff,
224da2e3ebdSchin Z("List detailed info in nroff."),
225da2e3ebdSchin C("options"), "?options", STYLE_options,
226da2e3ebdSchin Z("List short and long option details."),
227da2e3ebdSchin C("posix"), "?posix", STYLE_posix,
228da2e3ebdSchin Z("List posix getopt usage."),
229da2e3ebdSchin C("short"), "?short", STYLE_short,
230da2e3ebdSchin Z("List short option usage."),
231da2e3ebdSchin C("usage"), "?usage", STYLE_usage,
232da2e3ebdSchin Z("List the usage string with C style escapes."),
233da2e3ebdSchin };
234da2e3ebdSchin
235da2e3ebdSchin static const List_t help_tail[] =
236da2e3ebdSchin {
237da2e3ebdSchin ':', C("\?\?-\alabel\a"),
238da2e3ebdSchin C("List implementation info matching \alabel\a*."),
239da2e3ebdSchin ':', C("\?\?\aname\a"),
240da2e3ebdSchin C("Equivalent to \b--help=\b\aname\a."),
241da2e3ebdSchin ':', C("\?\?"),
242da2e3ebdSchin C("Equivalent to \b--\?\?options\b."),
243da2e3ebdSchin ':', C("\?\?\?\?"),
244da2e3ebdSchin C("Equivalent to \b--\?\?man\b."),
245da2e3ebdSchin ':', C("\?\?\?\?\?\?"),
246da2e3ebdSchin C("Equivalent to \b--\?\?help\b."),
247da2e3ebdSchin ':', C("\?\?\?\?\?\?\aitem\a"),
248da2e3ebdSchin C("If the next argument is \b--\b\aoption\a then list \
249da2e3ebdSchin the \aoption\a output in the \aitem\a style. Otherwise print \
250da2e3ebdSchin \bversion=\b\an\a where \an\a>0 if \b--\?\?\b\aitem\a is supported, \b0\b \
251da2e3ebdSchin if not."),
252da2e3ebdSchin ':', C("\?\?\?\?\?\?ESC"),
253da2e3ebdSchin C("Emit escape codes even if output is not a terminal."),
254da2e3ebdSchin ':', C("\?\?\?\?\?\?TEST"),
255da2e3ebdSchin C("Massage the output for regression testing."),
256da2e3ebdSchin };
257da2e3ebdSchin
258da2e3ebdSchin static const Attr_t attrs[] =
259da2e3ebdSchin {
260da2e3ebdSchin "flag", OPT_flag,
261da2e3ebdSchin "hidden", OPT_hidden,
262da2e3ebdSchin "ignorecase", OPT_ignorecase,
263da2e3ebdSchin "invert", OPT_invert,
264da2e3ebdSchin "listof", OPT_listof,
265da2e3ebdSchin "number", OPT_number,
266da2e3ebdSchin "oneof", OPT_oneof,
267da2e3ebdSchin "optional", OPT_optional,
268da2e3ebdSchin "string", OPT_string,
269da2e3ebdSchin };
270da2e3ebdSchin
271da2e3ebdSchin static const char unknown[] = C("unknown option or attribute");
272da2e3ebdSchin
273da2e3ebdSchin static const char* heading[] =
274da2e3ebdSchin {
275da2e3ebdSchin C("INDEX"),
276da2e3ebdSchin C("USER COMMANDS"),
277da2e3ebdSchin C("SYSTEM LIBRARY"),
278da2e3ebdSchin C("USER LIBRARY"),
279da2e3ebdSchin C("FILE FORMATS"),
280da2e3ebdSchin C("MISCELLANEOUS"),
281da2e3ebdSchin C("GAMES and DEMOS"),
282da2e3ebdSchin C("SPECIAL FILES"),
283da2e3ebdSchin C("ADMINISTRATIVE COMMANDS"),
284da2e3ebdSchin C("GUIs"),
285da2e3ebdSchin };
286da2e3ebdSchin
287da2e3ebdSchin /*
288da2e3ebdSchin * list of common man page strings
289da2e3ebdSchin * NOTE: add but do not delete from this table
290da2e3ebdSchin */
291da2e3ebdSchin
292da2e3ebdSchin static Msg_t C_LC_MESSAGES_libast[] =
293da2e3ebdSchin {
294da2e3ebdSchin { C("APPLICATION USAGE") },
295da2e3ebdSchin { C("ASYNCHRONOUS EVENTS") },
296da2e3ebdSchin { C("BUGS") },
297da2e3ebdSchin { C("CAVEATS") },
298da2e3ebdSchin { C("CONSEQUENCES OF ERRORS") },
299da2e3ebdSchin { C("DESCRIPTION") },
300da2e3ebdSchin { C("ENVIRONMENT VARIABLES") },
301da2e3ebdSchin { C("EXAMPLES") },
302da2e3ebdSchin { C("EXIT STATUS") },
303da2e3ebdSchin { C("EXTENDED DESCRIPTION") },
304da2e3ebdSchin { C("INPUT FILES") },
305da2e3ebdSchin { C("LIBRARY") },
306da2e3ebdSchin { C("NAME") },
307da2e3ebdSchin { C("OPERANDS") },
308da2e3ebdSchin { C("OPTIONS") },
309da2e3ebdSchin { C("OUTPUT FILES") },
310da2e3ebdSchin { C("SEE ALSO") },
311da2e3ebdSchin { C("STDERR") },
312da2e3ebdSchin { C("STDIN") },
313da2e3ebdSchin { C("STDOUT") },
314da2e3ebdSchin { C("SYNOPSIS") },
315da2e3ebdSchin { C("author") },
316da2e3ebdSchin { C("copyright") },
317da2e3ebdSchin { C("license") },
318da2e3ebdSchin { C("name") },
319da2e3ebdSchin { C("path") },
320da2e3ebdSchin { C("version") },
321da2e3ebdSchin };
322da2e3ebdSchin
323da2e3ebdSchin static unsigned char map[UCHAR_MAX];
324da2e3ebdSchin
325da2e3ebdSchin static Optstate_t state;
326da2e3ebdSchin
327da2e3ebdSchin /*
328da2e3ebdSchin * 2007-03-19 move opt_info from _opt_info_ to (*_opt_data_)
329da2e3ebdSchin * to allow future Opt_t growth
330da2e3ebdSchin * by 2009 _opt_info_ can be static
331da2e3ebdSchin */
332da2e3ebdSchin
333da2e3ebdSchin #if _BLD_ast && defined(__EXPORT__)
334da2e3ebdSchin #define extern extern __EXPORT__
335da2e3ebdSchin #endif
336da2e3ebdSchin
337da2e3ebdSchin extern Opt_t _opt_info_;
338da2e3ebdSchin
339da2e3ebdSchin Opt_t _opt_info_ = { 0,0,0,0,0,0,0,{0},{0},0,0,0,{0},{0},&state };
340da2e3ebdSchin
341da2e3ebdSchin #undef extern
342da2e3ebdSchin
343da2e3ebdSchin __EXTERN__(Opt_t, _opt_info_);
344da2e3ebdSchin
345da2e3ebdSchin __EXTERN__(Opt_t*, _opt_infop_);
346da2e3ebdSchin
347da2e3ebdSchin Opt_t* _opt_infop_ = &_opt_info_;
348da2e3ebdSchin
349da2e3ebdSchin #if _BLD_DEBUG
350da2e3ebdSchin
351da2e3ebdSchin /*
352da2e3ebdSchin * debug usage string segment format
353da2e3ebdSchin */
354da2e3ebdSchin
355da2e3ebdSchin static char*
show(register char * s)356da2e3ebdSchin show(register char* s)
357da2e3ebdSchin {
358da2e3ebdSchin register int c;
359da2e3ebdSchin register char* t;
360da2e3ebdSchin register char* e;
361da2e3ebdSchin
362da2e3ebdSchin static char buf[32];
363da2e3ebdSchin
364da2e3ebdSchin if (!s)
365da2e3ebdSchin return "(null)";
366da2e3ebdSchin t = buf;
367da2e3ebdSchin e = buf + sizeof(buf) - 2;
368da2e3ebdSchin while (t < e)
369da2e3ebdSchin {
370da2e3ebdSchin switch (c = *s++)
371da2e3ebdSchin {
372da2e3ebdSchin case 0:
373da2e3ebdSchin goto done;
374da2e3ebdSchin case '\a':
375da2e3ebdSchin *t++ = '\\';
376da2e3ebdSchin c = 'a';
377da2e3ebdSchin break;
378da2e3ebdSchin case '\b':
379da2e3ebdSchin *t++ = '\\';
380da2e3ebdSchin c = 'b';
381da2e3ebdSchin break;
382da2e3ebdSchin case '\f':
383da2e3ebdSchin *t++ = '\\';
384da2e3ebdSchin c = 'f';
385da2e3ebdSchin break;
386*3e14f97fSRoger A. Faulkner case '\n':
387*3e14f97fSRoger A. Faulkner *t++ = '\\';
388*3e14f97fSRoger A. Faulkner c = 'n';
389*3e14f97fSRoger A. Faulkner break;
390*3e14f97fSRoger A. Faulkner case '\t':
391*3e14f97fSRoger A. Faulkner *t++ = '\\';
392*3e14f97fSRoger A. Faulkner c = 't';
393*3e14f97fSRoger A. Faulkner break;
394da2e3ebdSchin case '\v':
395da2e3ebdSchin *t++ = '\\';
396da2e3ebdSchin c = 'v';
397da2e3ebdSchin break;
398da2e3ebdSchin }
399da2e3ebdSchin *t++ = c;
400da2e3ebdSchin }
401da2e3ebdSchin done:
402da2e3ebdSchin *t = 0;
403da2e3ebdSchin return buf;
404da2e3ebdSchin }
405da2e3ebdSchin
406da2e3ebdSchin #endif
407da2e3ebdSchin
408da2e3ebdSchin /*
409da2e3ebdSchin * pop the push stack
410da2e3ebdSchin */
411da2e3ebdSchin
412da2e3ebdSchin static Push_t*
pop(register Push_t * psp)413da2e3ebdSchin pop(register Push_t* psp)
414da2e3ebdSchin {
415da2e3ebdSchin register Push_t* tsp;
416da2e3ebdSchin
417da2e3ebdSchin while (tsp = psp)
418da2e3ebdSchin {
419da2e3ebdSchin psp = psp->next;
420da2e3ebdSchin free(tsp);
421da2e3ebdSchin }
422da2e3ebdSchin return 0;
423da2e3ebdSchin }
424da2e3ebdSchin
425da2e3ebdSchin /*
426da2e3ebdSchin * skip over line space to the next token
427da2e3ebdSchin */
428da2e3ebdSchin
429da2e3ebdSchin static char*
next(register char * s,int version)430da2e3ebdSchin next(register char* s, int version)
431da2e3ebdSchin {
432da2e3ebdSchin register char* b;
433da2e3ebdSchin
434da2e3ebdSchin while (*s == '\t' || *s == '\r' || version >= 1 && *s == ' ')
435da2e3ebdSchin s++;
436da2e3ebdSchin if (*s == '\n')
437da2e3ebdSchin {
438da2e3ebdSchin b = s;
439da2e3ebdSchin while (*++s == ' ' || *s == '\t' || *s == '\r');
440da2e3ebdSchin if (*s == '\n')
441da2e3ebdSchin return b;
442da2e3ebdSchin }
443da2e3ebdSchin return s;
444da2e3ebdSchin }
445da2e3ebdSchin
446da2e3ebdSchin /*
447da2e3ebdSchin * skip to t1 or t2 or t3, whichever first, in s
448da2e3ebdSchin * n==0 outside [...]
449da2e3ebdSchin * n==1 inside [...] before ?
450da2e3ebdSchin * n==2 inside [...] after ?
451da2e3ebdSchin * b==0 outside {...}
452da2e3ebdSchin * b==1 inside {...}
453da2e3ebdSchin * past skips past the terminator to the next token
454da2e3ebdSchin * otherwise a pointer to the terminator is returned
455da2e3ebdSchin *
456da2e3ebdSchin * ]] for ] inside [...]
457da2e3ebdSchin * ?? for ? inside [...] before ?
458da2e3ebdSchin * :: for : inside [...] before ?
459da2e3ebdSchin */
460da2e3ebdSchin
461da2e3ebdSchin static char*
skip(register char * s,register int t1,register int t2,register int t3,register int n,register int b,int past,int version)462da2e3ebdSchin skip(register char* s, register int t1, register int t2, register int t3, register int n, register int b, int past, int version)
463da2e3ebdSchin {
464da2e3ebdSchin register int c;
465da2e3ebdSchin register int on = n;
466da2e3ebdSchin register int ob = b;
467da2e3ebdSchin
468da2e3ebdSchin if (version < 1)
469da2e3ebdSchin {
470da2e3ebdSchin n = n >= 1;
471da2e3ebdSchin for (;;)
472da2e3ebdSchin {
473da2e3ebdSchin switch (*s++)
474da2e3ebdSchin {
475da2e3ebdSchin case 0:
476da2e3ebdSchin break;
477da2e3ebdSchin case '[':
478da2e3ebdSchin n++;
479da2e3ebdSchin continue;
480da2e3ebdSchin case ']':
481da2e3ebdSchin if (--n <= 0)
482da2e3ebdSchin break;
483da2e3ebdSchin continue;
484da2e3ebdSchin default:
485da2e3ebdSchin continue;
486da2e3ebdSchin }
487da2e3ebdSchin break;
488da2e3ebdSchin }
489da2e3ebdSchin }
490da2e3ebdSchin else while (c = *s++)
491da2e3ebdSchin {
492da2e3ebdSchin 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)));
493da2e3ebdSchin if (c == '[')
494da2e3ebdSchin {
495da2e3ebdSchin if (!n)
496da2e3ebdSchin n = 1;
497da2e3ebdSchin }
498da2e3ebdSchin else if (c == ']')
499da2e3ebdSchin {
500da2e3ebdSchin if (n)
501da2e3ebdSchin {
502da2e3ebdSchin if (*s == ']')
503da2e3ebdSchin s++;
504da2e3ebdSchin else if (on == 1)
505da2e3ebdSchin break;
506da2e3ebdSchin else
507da2e3ebdSchin n = 0;
508da2e3ebdSchin }
509da2e3ebdSchin }
510da2e3ebdSchin else if (c == GO)
511da2e3ebdSchin {
512da2e3ebdSchin if (n == 0)
513da2e3ebdSchin b++;
514da2e3ebdSchin }
515da2e3ebdSchin else if (c == OG)
516da2e3ebdSchin {
517da2e3ebdSchin if (n == 0 && b-- == ob)
518da2e3ebdSchin break;
519da2e3ebdSchin }
520da2e3ebdSchin else if (c == '?')
521da2e3ebdSchin {
522da2e3ebdSchin if (n == 1)
523da2e3ebdSchin {
524da2e3ebdSchin if (*s == '?')
525da2e3ebdSchin s++;
526da2e3ebdSchin else
527da2e3ebdSchin {
528da2e3ebdSchin if (n == on && (c == t1 || c == t2 || c == t3))
529da2e3ebdSchin break;
530da2e3ebdSchin n = 2;
531da2e3ebdSchin }
532da2e3ebdSchin }
533da2e3ebdSchin }
534da2e3ebdSchin else if (n == on && (c == t1 || c == t2 || c == t3))
535da2e3ebdSchin {
536da2e3ebdSchin if (n == 1 && c == ':' && *s == c)
537da2e3ebdSchin s++;
538da2e3ebdSchin else
539da2e3ebdSchin break;
540da2e3ebdSchin }
541da2e3ebdSchin }
542da2e3ebdSchin return past && *(s - 1) ? next(s, version) : s - 1;
543da2e3ebdSchin }
544da2e3ebdSchin
545da2e3ebdSchin /*
546da2e3ebdSchin * match s with t
547da2e3ebdSchin * t translated if possible
548da2e3ebdSchin * imbedded { - _ ' } ignored
549da2e3ebdSchin * * separates required prefix from optional suffix
550da2e3ebdSchin * otherwise prefix match
551da2e3ebdSchin */
552da2e3ebdSchin
553da2e3ebdSchin static int
match(char * s,char * t,int version,const char * id,const char * catalog)554*3e14f97fSRoger A. Faulkner match(char* s, char* t, int version, const char* id, const char* catalog)
555da2e3ebdSchin {
556da2e3ebdSchin register char* w;
557da2e3ebdSchin register char* x;
558da2e3ebdSchin char* xw;
559da2e3ebdSchin char* ww;
560da2e3ebdSchin int n;
561da2e3ebdSchin int v;
562da2e3ebdSchin int j;
563da2e3ebdSchin
564da2e3ebdSchin for (n = 0; n < 2; n++)
565da2e3ebdSchin {
566da2e3ebdSchin if (n)
567da2e3ebdSchin x = t;
568da2e3ebdSchin else
569da2e3ebdSchin {
570da2e3ebdSchin if (catalog)
571da2e3ebdSchin {
572da2e3ebdSchin w = skip(t, ':', '?', 0, 1, 0, 0, version);
573da2e3ebdSchin w = sfprints("%-.*s", w - t, t);
574*3e14f97fSRoger A. Faulkner x = T(id, catalog, w);
575da2e3ebdSchin if (x == w)
576da2e3ebdSchin continue;
577da2e3ebdSchin }
578da2e3ebdSchin x = T(NiL, ID, t);
579da2e3ebdSchin if (x == t)
580da2e3ebdSchin continue;
581da2e3ebdSchin }
582da2e3ebdSchin do
583da2e3ebdSchin {
584da2e3ebdSchin v = 0;
585da2e3ebdSchin xw = x;
586da2e3ebdSchin w = ww = s;
587da2e3ebdSchin while (*x && *w)
588da2e3ebdSchin {
589da2e3ebdSchin if (isupper(*x))
590da2e3ebdSchin xw = x;
591da2e3ebdSchin if (isupper(*w))
592da2e3ebdSchin ww = w;
593da2e3ebdSchin if (*x == '*' && !v++ || *x == '\a')
594da2e3ebdSchin {
595da2e3ebdSchin if (*x == '\a')
596da2e3ebdSchin do
597da2e3ebdSchin {
598da2e3ebdSchin if (!*++x)
599da2e3ebdSchin {
600da2e3ebdSchin x--;
601da2e3ebdSchin break;
602da2e3ebdSchin }
603da2e3ebdSchin } while (*x != '\a');
604da2e3ebdSchin j = *(x + 1);
605da2e3ebdSchin if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
606da2e3ebdSchin while (*w)
607da2e3ebdSchin w++;
608da2e3ebdSchin }
609da2e3ebdSchin else if (sep(*x))
610da2e3ebdSchin xw = ++x;
611da2e3ebdSchin else if (sep(*w) && w != s)
612da2e3ebdSchin ww = ++w;
613da2e3ebdSchin else if (*x == *w)
614da2e3ebdSchin {
615da2e3ebdSchin x++;
616da2e3ebdSchin w++;
617da2e3ebdSchin }
618da2e3ebdSchin else if (w == ww && x == xw)
619da2e3ebdSchin break;
620da2e3ebdSchin else
621da2e3ebdSchin {
622da2e3ebdSchin if (x != xw)
623da2e3ebdSchin {
624da2e3ebdSchin while (*x && !sep(*x) && !isupper(*x))
625da2e3ebdSchin x++;
626da2e3ebdSchin if (!*x)
627da2e3ebdSchin break;
628da2e3ebdSchin if (sep(*x))
629da2e3ebdSchin x++;
630da2e3ebdSchin xw = x;
631da2e3ebdSchin }
632da2e3ebdSchin while (w > ww && *w != *x)
633da2e3ebdSchin w--;
634da2e3ebdSchin }
635da2e3ebdSchin }
636da2e3ebdSchin if (!*w)
637da2e3ebdSchin {
638da2e3ebdSchin if (!v)
639da2e3ebdSchin {
640da2e3ebdSchin for (;;)
641da2e3ebdSchin {
642da2e3ebdSchin switch (*x++)
643da2e3ebdSchin {
644da2e3ebdSchin case 0:
645da2e3ebdSchin case ':':
646da2e3ebdSchin case '|':
647da2e3ebdSchin case '?':
648da2e3ebdSchin case ']':
649da2e3ebdSchin return 1;
650da2e3ebdSchin case '*':
651da2e3ebdSchin break;
652da2e3ebdSchin default:
653da2e3ebdSchin continue;
654da2e3ebdSchin }
655da2e3ebdSchin break;
656da2e3ebdSchin }
657da2e3ebdSchin break;
658da2e3ebdSchin }
659da2e3ebdSchin return 1;
660da2e3ebdSchin }
661da2e3ebdSchin } while (*(x = skip(x, '|', 0, 0, 1, 0, 0, version)) == '|' && x++);
662da2e3ebdSchin }
663da2e3ebdSchin return 0;
664da2e3ebdSchin }
665da2e3ebdSchin
666da2e3ebdSchin /*
667da2e3ebdSchin * prefix search for s in tab with num elements of size
668da2e3ebdSchin * with optional translation
669da2e3ebdSchin */
670da2e3ebdSchin
671da2e3ebdSchin static void*
search(const void * tab,size_t num,size_t siz,char * s)672da2e3ebdSchin search(const void* tab, size_t num, size_t siz, char* s)
673da2e3ebdSchin {
674da2e3ebdSchin register char* p;
675da2e3ebdSchin register char* e;
676da2e3ebdSchin
677da2e3ebdSchin for (e = (p = (char*)tab) + num * siz; p < e; p += siz)
678*3e14f97fSRoger A. Faulkner if (match(s, *((char**)p), -1, NiL, NiL))
679da2e3ebdSchin return (void*)p;
680da2e3ebdSchin return 0;
681da2e3ebdSchin }
682da2e3ebdSchin
683da2e3ebdSchin /*
684da2e3ebdSchin * save s and return the saved pointer
685da2e3ebdSchin */
686da2e3ebdSchin
687da2e3ebdSchin static char*
save(const char * s)688da2e3ebdSchin save(const char* s)
689da2e3ebdSchin {
690da2e3ebdSchin Save_t* p;
6917c2fbfb3SApril Chin Dtdisc_t* d;
692da2e3ebdSchin
693da2e3ebdSchin static Dt_t* dict;
694da2e3ebdSchin
695da2e3ebdSchin if (!dict)
696da2e3ebdSchin {
6977c2fbfb3SApril Chin if (!(d = newof(0, Dtdisc_t, 1, 0)))
6987c2fbfb3SApril Chin return (char*)s;
6997c2fbfb3SApril Chin d->key = offsetof(Save_t, text);
7007c2fbfb3SApril Chin if (!(dict = dtopen(d, Dthash)))
701da2e3ebdSchin return (char*)s;
702da2e3ebdSchin }
703da2e3ebdSchin if (!(p = (Save_t*)dtmatch(dict, s)))
704da2e3ebdSchin {
705da2e3ebdSchin if (!(p = newof(0, Save_t, 1, strlen(s))))
706da2e3ebdSchin return (char*)s;
707da2e3ebdSchin strcpy(p->text, s);
708da2e3ebdSchin dtinsert(dict, p);
709da2e3ebdSchin }
710da2e3ebdSchin return p->text;
711da2e3ebdSchin }
712da2e3ebdSchin
713da2e3ebdSchin /*
714da2e3ebdSchin * initialize the attributes for pass p from opt string s
715da2e3ebdSchin */
716da2e3ebdSchin
717da2e3ebdSchin static int
init(register char * s,Optpass_t * p)718da2e3ebdSchin init(register char* s, Optpass_t* p)
719da2e3ebdSchin {
720da2e3ebdSchin register char* t;
721*3e14f97fSRoger A. Faulkner register char* u;
722da2e3ebdSchin register int c;
723da2e3ebdSchin register int a;
724da2e3ebdSchin register int n;
725da2e3ebdSchin
726da2e3ebdSchin if (!opt_info.state->msgdict)
727da2e3ebdSchin {
728da2e3ebdSchin #if !_PACKAGE_astsa
729da2e3ebdSchin if (!ast.locale.serial)
730da2e3ebdSchin setlocale(LC_ALL, "");
731da2e3ebdSchin #endif
732da2e3ebdSchin opt_info.state->vp = sfstropen();
733da2e3ebdSchin opt_info.state->xp = sfstropen();
734da2e3ebdSchin opt_info.state->msgdisc.key = offsetof(Msg_t, text);
735da2e3ebdSchin opt_info.state->msgdisc.size = -1;
736da2e3ebdSchin opt_info.state->msgdisc.link = offsetof(Msg_t, link);
737da2e3ebdSchin if (opt_info.state->msgdict = dtopen(&opt_info.state->msgdisc, Dthash))
738da2e3ebdSchin for (n = 0; n < elementsof(C_LC_MESSAGES_libast); n++)
739da2e3ebdSchin dtinsert(opt_info.state->msgdict, C_LC_MESSAGES_libast + n);
740da2e3ebdSchin if (!map[OPT_FLAGS[0]])
741da2e3ebdSchin for (n = 0, t = OPT_FLAGS; *t; t++)
742da2e3ebdSchin map[*t] = ++n;
743da2e3ebdSchin }
744da2e3ebdSchin #if _BLD_DEBUG
745da2e3ebdSchin error(-1, "optget debug");
746da2e3ebdSchin #endif
747da2e3ebdSchin p->oopts = s;
748da2e3ebdSchin p->version = 0;
749da2e3ebdSchin p->prefix = 2;
750da2e3ebdSchin p->section = 1;
751da2e3ebdSchin p->flags = 0;
752*3e14f97fSRoger A. Faulkner p->id = error_info.id;
753da2e3ebdSchin p->catalog = 0;
754da2e3ebdSchin s = next(s, 0);
755da2e3ebdSchin if (*s == ':')
756da2e3ebdSchin s++;
757da2e3ebdSchin if (*s == '+')
758da2e3ebdSchin s++;
759da2e3ebdSchin s = next(s, 0);
760da2e3ebdSchin if (*s++ == '[')
761da2e3ebdSchin {
762da2e3ebdSchin if (*s == '+')
763da2e3ebdSchin p->version = 1;
764da2e3ebdSchin else if (*s++ == '-')
765da2e3ebdSchin {
766da2e3ebdSchin if (*s == '?' || *s == ']')
767da2e3ebdSchin p->version = 1;
768da2e3ebdSchin else
769da2e3ebdSchin {
7707c2fbfb3SApril Chin if (!isdigit(*s))
771da2e3ebdSchin p->version = 1;
772da2e3ebdSchin else
7737c2fbfb3SApril Chin while (isdigit(*s))
774da2e3ebdSchin p->version = p->version * 10 + (*s++ - '0');
775da2e3ebdSchin while (*s && *s != '?' && *s != ']')
776da2e3ebdSchin {
777da2e3ebdSchin c = *s++;
7787c2fbfb3SApril Chin if (!isdigit(*s))
779da2e3ebdSchin n = 1;
780da2e3ebdSchin else
781da2e3ebdSchin {
782da2e3ebdSchin n = 0;
7837c2fbfb3SApril Chin while (isdigit(*s))
784da2e3ebdSchin n = n * 10 + (*s++ - '0');
785da2e3ebdSchin }
786da2e3ebdSchin switch (c)
787da2e3ebdSchin {
7887c2fbfb3SApril Chin case '+':
7897c2fbfb3SApril Chin p->flags |= OPT_plus;
7907c2fbfb3SApril Chin break;
791da2e3ebdSchin case 'c':
792da2e3ebdSchin p->flags |= OPT_cache;
793da2e3ebdSchin break;
794da2e3ebdSchin case 'i':
795da2e3ebdSchin p->flags |= OPT_ignore;
796da2e3ebdSchin break;
797da2e3ebdSchin case 'l':
798da2e3ebdSchin p->flags |= OPT_long;
799da2e3ebdSchin break;
8007c2fbfb3SApril Chin case 'n':
8017c2fbfb3SApril Chin p->flags |= OPT_numeric;
8027c2fbfb3SApril Chin break;
803da2e3ebdSchin case 'o':
804da2e3ebdSchin p->flags |= OPT_old;
805da2e3ebdSchin break;
806da2e3ebdSchin case 'p':
807da2e3ebdSchin p->prefix = n;
808da2e3ebdSchin break;
809da2e3ebdSchin case 's':
810da2e3ebdSchin p->section = n;
811da2e3ebdSchin if (n > 1 && n < 6)
812da2e3ebdSchin {
813da2e3ebdSchin p->flags |= OPT_functions;
814da2e3ebdSchin p->prefix = 0;
815da2e3ebdSchin }
816da2e3ebdSchin break;
817da2e3ebdSchin }
818da2e3ebdSchin }
819da2e3ebdSchin }
820da2e3ebdSchin }
821da2e3ebdSchin while (*s)
822*3e14f97fSRoger A. Faulkner if (*s++ == ']')
823*3e14f97fSRoger A. Faulkner {
824*3e14f97fSRoger A. Faulkner while (isspace(*s))
825*3e14f97fSRoger A. Faulkner s++;
826*3e14f97fSRoger A. Faulkner if (*s++ == '[')
827da2e3ebdSchin {
828da2e3ebdSchin if (*s++ != '-')
829da2e3ebdSchin {
830*3e14f97fSRoger A. Faulkner if (strneq(s - 1, "+NAME?", 6))
831da2e3ebdSchin {
832*3e14f97fSRoger A. Faulkner for (s += 5; *s == '\a' || *s == '\b' || *s == '\v' || *s == ' '; s++);
833*3e14f97fSRoger A. Faulkner if (*s != '\f')
834*3e14f97fSRoger A. Faulkner {
835*3e14f97fSRoger A. Faulkner for (t = s; *t && *t != ' ' && *t != ']'; t++);
836*3e14f97fSRoger A. Faulkner if (t > s)
837*3e14f97fSRoger A. Faulkner {
838*3e14f97fSRoger A. Faulkner u = t;
839*3e14f97fSRoger A. Faulkner if (*(t - 1) == '\a' || *(t - 1) == '\b' || *(t - 1) == '\v')
840*3e14f97fSRoger A. Faulkner t--;
841*3e14f97fSRoger A. Faulkner if (t > s)
842*3e14f97fSRoger A. Faulkner {
843*3e14f97fSRoger A. Faulkner while (*u == ' ' || *u == '\\')
844*3e14f97fSRoger A. Faulkner u++;
845*3e14f97fSRoger A. Faulkner if (*u == '-' || *u == ']')
846*3e14f97fSRoger A. Faulkner p->id = save(sfprints("%-.*s", t - s, s));
847*3e14f97fSRoger A. Faulkner }
848*3e14f97fSRoger A. Faulkner }
849*3e14f97fSRoger A. Faulkner }
850da2e3ebdSchin }
851da2e3ebdSchin break;
852da2e3ebdSchin }
853da2e3ebdSchin if (*s == '-')
854da2e3ebdSchin s++;
855da2e3ebdSchin if (strneq(s, "catalog?", 8))
856*3e14f97fSRoger A. Faulkner p->catalog = s += 8;
857*3e14f97fSRoger A. Faulkner }
858*3e14f97fSRoger A. Faulkner }
859*3e14f97fSRoger A. Faulkner }
860*3e14f97fSRoger A. Faulkner if (!error_info.id)
861da2e3ebdSchin {
862*3e14f97fSRoger A. Faulkner if (!(error_info.id = p->id))
863*3e14f97fSRoger A. Faulkner p->id = "command";
864da2e3ebdSchin }
865*3e14f97fSRoger A. Faulkner else if (p->id == error_info.id)
866*3e14f97fSRoger A. Faulkner p->id = save(p->id);
867*3e14f97fSRoger A. Faulkner if (s = p->catalog)
868*3e14f97fSRoger A. Faulkner p->catalog = ((t = strchr(s, ']')) && (!p->id || (t - s) != strlen(p->id) || !strneq(s, p->id, t - s))) ? save(sfprints("%-.*s", t - s, s)) : (char*)0;
869da2e3ebdSchin if (!p->catalog)
870da2e3ebdSchin {
871*3e14f97fSRoger A. Faulkner if (opt_info.disc && opt_info.disc->catalog && (!p->id || !streq(opt_info.disc->catalog, p->id)))
872da2e3ebdSchin p->catalog = opt_info.disc->catalog;
873da2e3ebdSchin else
874da2e3ebdSchin p->catalog = ID;
875da2e3ebdSchin }
876da2e3ebdSchin s = p->oopts;
877da2e3ebdSchin if (*s == ':')
878da2e3ebdSchin s++;
879da2e3ebdSchin if (*s == '+')
880da2e3ebdSchin {
881da2e3ebdSchin s++;
882da2e3ebdSchin p->flags |= OPT_plus;
883da2e3ebdSchin }
8847c2fbfb3SApril Chin s = next(s, 0);
885da2e3ebdSchin if (*s != '[')
886da2e3ebdSchin for (t = s, a = 0; *t; t++)
887da2e3ebdSchin if (!a && *t == '-')
888da2e3ebdSchin {
889da2e3ebdSchin p->flags |= OPT_minus;
890da2e3ebdSchin break;
891da2e3ebdSchin }
892da2e3ebdSchin else if (*t == '[')
893da2e3ebdSchin a++;
894da2e3ebdSchin else if (*t == ']')
895da2e3ebdSchin a--;
896da2e3ebdSchin if (!p->version && (t = strchr(s, '(')) && strchr(t, ')') && (opt_info.state->cp || (opt_info.state->cp = sfstropen())))
897da2e3ebdSchin {
898da2e3ebdSchin /*
899da2e3ebdSchin * solaris long option compatibility
900da2e3ebdSchin */
901da2e3ebdSchin
902da2e3ebdSchin p->version = 1;
903da2e3ebdSchin for (t = p->oopts; t < s; t++)
904da2e3ebdSchin sfputc(opt_info.state->cp, *t);
905da2e3ebdSchin n = t - p->oopts;
906da2e3ebdSchin sfputc(opt_info.state->cp, '[');
907da2e3ebdSchin sfputc(opt_info.state->cp, '-');
908da2e3ebdSchin sfputc(opt_info.state->cp, ']');
909*3e14f97fSRoger A. Faulkner c = *s++;
910*3e14f97fSRoger A. Faulkner while (c)
911da2e3ebdSchin {
912da2e3ebdSchin sfputc(opt_info.state->cp, '[');
913da2e3ebdSchin sfputc(opt_info.state->cp, c);
914da2e3ebdSchin if (a = (c = *s++) == ':')
915da2e3ebdSchin c = *s++;
916da2e3ebdSchin if (c == '(')
917da2e3ebdSchin {
918da2e3ebdSchin sfputc(opt_info.state->cp, ':');
919da2e3ebdSchin for (;;)
920da2e3ebdSchin {
921da2e3ebdSchin while ((c = *s++) && c != ')')
922da2e3ebdSchin sfputc(opt_info.state->cp, c);
923*3e14f97fSRoger A. Faulkner if (!c || (c = *s++) != '(')
924da2e3ebdSchin break;
925da2e3ebdSchin sfputc(opt_info.state->cp, '|');
926da2e3ebdSchin }
927da2e3ebdSchin }
928da2e3ebdSchin sfputc(opt_info.state->cp, ']');
929da2e3ebdSchin if (a)
930da2e3ebdSchin sfputr(opt_info.state->cp, ":[string]", -1);
931da2e3ebdSchin }
932da2e3ebdSchin if (!(p->oopts = s = sfstruse(opt_info.state->cp)))
933da2e3ebdSchin return -1;
934da2e3ebdSchin s += n;
935da2e3ebdSchin }
936da2e3ebdSchin p->opts = s;
937*3e14f97fSRoger A. Faulkner message((-1, "version=%d prefix=%d section=%d flags=%04x id=%s catalog=%s", p->version, p->prefix, p->section, p->flags, p->id, p->catalog));
938da2e3ebdSchin return 0;
939da2e3ebdSchin }
940da2e3ebdSchin
941da2e3ebdSchin /*
942da2e3ebdSchin * return the bold set/unset sequence for style
943da2e3ebdSchin */
944da2e3ebdSchin
945da2e3ebdSchin static const char*
font(int f,int style,int set)946da2e3ebdSchin font(int f, int style, int set)
947da2e3ebdSchin {
948da2e3ebdSchin switch (style)
949da2e3ebdSchin {
950da2e3ebdSchin case STYLE_html:
951da2e3ebdSchin return fonts[f].html[set];
952da2e3ebdSchin case STYLE_nroff:
953da2e3ebdSchin return fonts[f].nroff[set];
954da2e3ebdSchin case STYLE_short:
955da2e3ebdSchin case STYLE_long:
956da2e3ebdSchin case STYLE_posix:
957da2e3ebdSchin case STYLE_api:
958da2e3ebdSchin break;
959da2e3ebdSchin default:
960da2e3ebdSchin if (opt_info.state->emphasis > 0)
961da2e3ebdSchin return fonts[f].term[set];
962da2e3ebdSchin break;
963da2e3ebdSchin }
964da2e3ebdSchin return "";
965da2e3ebdSchin }
966da2e3ebdSchin
967da2e3ebdSchin /*
968da2e3ebdSchin * expand \f...\f info
969da2e3ebdSchin * *p set to next char after second \f
970da2e3ebdSchin * expanded value returned
971da2e3ebdSchin */
972da2e3ebdSchin
973da2e3ebdSchin static char*
expand(register char * s,register char * e,char ** p,Sfio_t * ip,char * id)974*3e14f97fSRoger A. Faulkner expand(register char* s, register char* e, char** p, Sfio_t* ip, char* id)
975da2e3ebdSchin {
976da2e3ebdSchin register int c;
977da2e3ebdSchin register char* b = s;
978da2e3ebdSchin int n;
979da2e3ebdSchin
980da2e3ebdSchin n = sfstrtell(ip);
981da2e3ebdSchin c = 1;
982da2e3ebdSchin while ((!e || s < e) && (c = *s++) && c != '\f');
983da2e3ebdSchin sfwrite(ip, b, s - b - 1);
984da2e3ebdSchin sfputc(ip, 0);
985da2e3ebdSchin b = sfstrbase(ip) + n;
986da2e3ebdSchin n = sfstrtell(ip);
987da2e3ebdSchin if (!c)
988da2e3ebdSchin s--;
989da2e3ebdSchin if (*b == '?')
990da2e3ebdSchin {
991da2e3ebdSchin if (!*++b || streq(b, "NAME"))
992da2e3ebdSchin {
993*3e14f97fSRoger A. Faulkner if (!(b = id))
994da2e3ebdSchin b = "command";
995da2e3ebdSchin sfstrseek(ip, 0, SEEK_SET);
996da2e3ebdSchin sfputr(ip, b, -1);
997da2e3ebdSchin n = 0;
998da2e3ebdSchin }
999da2e3ebdSchin else
1000da2e3ebdSchin n = 1;
1001da2e3ebdSchin }
1002da2e3ebdSchin else if (!opt_info.disc || !opt_info.disc->infof || (*opt_info.disc->infof)(&opt_info, ip, b, opt_info.disc) < 0)
1003da2e3ebdSchin n = 0;
1004da2e3ebdSchin *p = s;
1005da2e3ebdSchin if (s = sfstruse(ip))
1006da2e3ebdSchin s += n;
1007da2e3ebdSchin else
1008da2e3ebdSchin s = "error";
1009da2e3ebdSchin return s;
1010da2e3ebdSchin }
1011da2e3ebdSchin
1012da2e3ebdSchin /*
1013da2e3ebdSchin * push \f...\f info
1014da2e3ebdSchin */
1015da2e3ebdSchin
1016da2e3ebdSchin static Push_t*
info(Push_t * psp,char * s,char * e,Sfio_t * ip,char * id)1017*3e14f97fSRoger A. Faulkner info(Push_t* psp, char* s, char* e, Sfio_t* ip, char* id)
1018da2e3ebdSchin {
1019da2e3ebdSchin register char* b;
1020da2e3ebdSchin int n;
1021da2e3ebdSchin Push_t* tsp;
1022da2e3ebdSchin
1023da2e3ebdSchin static Push_t push;
1024da2e3ebdSchin
1025*3e14f97fSRoger A. Faulkner b = expand(s, e, &s, ip, id);
1026da2e3ebdSchin n = strlen(b);
1027da2e3ebdSchin if (tsp = newof(0, Push_t, 1, n + 1))
1028da2e3ebdSchin {
1029da2e3ebdSchin tsp->nb = (char*)(tsp + 1);
1030da2e3ebdSchin tsp->ne = tsp->nb + n;
1031da2e3ebdSchin strcpy(tsp->nb, b);
1032da2e3ebdSchin }
1033da2e3ebdSchin else
1034da2e3ebdSchin tsp = &push;
1035da2e3ebdSchin tsp->next = psp;
1036da2e3ebdSchin tsp->ob = s;
1037da2e3ebdSchin tsp->oe = e;
1038da2e3ebdSchin return tsp;
1039da2e3ebdSchin }
1040da2e3ebdSchin
1041da2e3ebdSchin /*
1042da2e3ebdSchin * push translation
1043da2e3ebdSchin */
1044da2e3ebdSchin
1045da2e3ebdSchin static Push_t*
localize(Push_t * psp,char * s,char * e,int term,int n,Sfio_t * ip,int version,char * id,char * catalog)1046*3e14f97fSRoger A. Faulkner localize(Push_t* psp, char* s, char* e, int term, int n, Sfio_t* ip, int version, char* id, char* catalog)
1047da2e3ebdSchin {
1048da2e3ebdSchin char* t;
1049da2e3ebdSchin char* u;
1050da2e3ebdSchin Push_t* tsp;
1051da2e3ebdSchin int c;
1052da2e3ebdSchin
1053da2e3ebdSchin t = skip(s, term, 0, 0, n, 0, 0, version);
1054da2e3ebdSchin if (e && t > e)
1055da2e3ebdSchin t = e;
1056da2e3ebdSchin while (s < t)
1057da2e3ebdSchin {
1058da2e3ebdSchin switch (c = *s++)
1059da2e3ebdSchin {
1060da2e3ebdSchin case ':':
1061da2e3ebdSchin case '?':
1062da2e3ebdSchin if (term && *s == c)
1063da2e3ebdSchin s++;
1064da2e3ebdSchin break;
1065da2e3ebdSchin case ']':
1066da2e3ebdSchin if (*s == c)
1067da2e3ebdSchin s++;
1068da2e3ebdSchin break;
1069da2e3ebdSchin }
1070da2e3ebdSchin sfputc(ip, c);
1071da2e3ebdSchin }
1072*3e14f97fSRoger A. Faulkner if (!(s = sfstruse(ip)) || (u = T(id, catalog, s)) == s)
1073da2e3ebdSchin return 0;
1074da2e3ebdSchin n = strlen(u);
1075da2e3ebdSchin if (tsp = newof(0, Push_t, 1, n + 1))
1076da2e3ebdSchin {
1077da2e3ebdSchin tsp->nb = (char*)(tsp + 1);
1078da2e3ebdSchin tsp->ne = tsp->nb + n;
1079da2e3ebdSchin strcpy(tsp->nb, u);
1080da2e3ebdSchin tsp->ob = t;
1081da2e3ebdSchin tsp->oe = e;
1082da2e3ebdSchin tsp->ch = 1;
1083da2e3ebdSchin }
1084da2e3ebdSchin tsp->next = psp;
1085da2e3ebdSchin return tsp;
1086da2e3ebdSchin }
1087da2e3ebdSchin
1088da2e3ebdSchin /*
1089da2e3ebdSchin * output label s from [ ...label...[?...] ] to sp
1090da2e3ebdSchin * 1 returned if the label was translated
1091da2e3ebdSchin */
1092da2e3ebdSchin
1093da2e3ebdSchin static int
label(register Sfio_t * sp,int sep,register char * s,int about,int z,int level,int style,int f,Sfio_t * ip,int version,char * id,char * catalog)1094*3e14f97fSRoger A. Faulkner label(register Sfio_t* sp, int sep, register char* s, int about, int z, int level, int style, int f, Sfio_t* ip, int version, char* id, char* catalog)
1095da2e3ebdSchin {
1096da2e3ebdSchin register int c;
1097da2e3ebdSchin register char* t;
1098da2e3ebdSchin register char* e;
1099da2e3ebdSchin int ostyle;
1100da2e3ebdSchin int a;
1101da2e3ebdSchin int i;
1102da2e3ebdSchin char* p;
1103da2e3ebdSchin char* w;
1104da2e3ebdSchin char* y;
1105da2e3ebdSchin int va;
1106da2e3ebdSchin Push_t* tsp;
1107da2e3ebdSchin
1108da2e3ebdSchin int r = 0;
1109da2e3ebdSchin int n = 1;
1110da2e3ebdSchin Push_t* psp = 0;
1111da2e3ebdSchin
1112da2e3ebdSchin if ((ostyle = style) > (STYLE_nroff - (sep <= 0)) && f != FONT_LITERAL)
1113da2e3ebdSchin style = 0;
1114da2e3ebdSchin if (z < 0)
1115da2e3ebdSchin e = s + strlen(s);
1116da2e3ebdSchin else
1117da2e3ebdSchin e = s + z;
1118da2e3ebdSchin if (sep > 0)
1119da2e3ebdSchin {
1120da2e3ebdSchin if (sep == ' ' && style == STYLE_nroff)
1121da2e3ebdSchin sfputc(sp, '\\');
1122da2e3ebdSchin sfputc(sp, sep);
1123da2e3ebdSchin }
1124da2e3ebdSchin sep = !sep || z < 0;
1125da2e3ebdSchin va = 0;
1126da2e3ebdSchin y = 0;
11277c2fbfb3SApril Chin if (about)
11287c2fbfb3SApril Chin sfputc(sp, '(');
1129da2e3ebdSchin if (version < 1)
1130da2e3ebdSchin {
1131da2e3ebdSchin a = 0;
1132da2e3ebdSchin for (;;)
1133da2e3ebdSchin {
1134da2e3ebdSchin if (s >= e)
1135da2e3ebdSchin return r;
1136da2e3ebdSchin switch (c = *s++)
1137da2e3ebdSchin {
1138da2e3ebdSchin case '[':
1139da2e3ebdSchin a++;
1140da2e3ebdSchin break;
1141da2e3ebdSchin case ']':
1142da2e3ebdSchin if (--a < 0)
1143da2e3ebdSchin return r;
1144da2e3ebdSchin break;
1145da2e3ebdSchin }
1146da2e3ebdSchin sfputc(sp, c);
1147da2e3ebdSchin }
1148da2e3ebdSchin }
1149da2e3ebdSchin else if (level && (*(p = skip(s, 0, 0, 0, 1, level, 1, version)) == ':' || *p == '#'))
1150da2e3ebdSchin {
1151da2e3ebdSchin va = 0;
1152da2e3ebdSchin if (*++p == '?' || *p == *(p - 1))
1153da2e3ebdSchin {
1154da2e3ebdSchin p++;
1155da2e3ebdSchin va |= OPT_optional;
1156da2e3ebdSchin }
1157da2e3ebdSchin if (*(p = next(p, version)) == '[')
1158da2e3ebdSchin y = p + 1;
1159da2e3ebdSchin }
1160da2e3ebdSchin if (X(catalog) && (!level || *s == '\a' || *(s - 1) != '+') &&
1161*3e14f97fSRoger A. Faulkner (tsp = localize(psp, s, e, (sep || level) ? '?' : 0, sep || level, ip, version, id, catalog)))
1162da2e3ebdSchin {
1163da2e3ebdSchin psp= tsp;
1164da2e3ebdSchin s = psp->nb;
1165da2e3ebdSchin e = psp->ne;
1166da2e3ebdSchin r = psp->ch > 0;
1167da2e3ebdSchin }
1168da2e3ebdSchin switch (*s)
1169da2e3ebdSchin {
1170da2e3ebdSchin case '\a':
1171da2e3ebdSchin if (f == FONT_ITALIC)
1172da2e3ebdSchin s++;
1173da2e3ebdSchin f = 0;
1174da2e3ebdSchin break;
1175da2e3ebdSchin case '\b':
1176da2e3ebdSchin if (f == FONT_BOLD)
1177da2e3ebdSchin s++;
1178da2e3ebdSchin f = 0;
1179da2e3ebdSchin break;
1180da2e3ebdSchin case '\v':
1181da2e3ebdSchin if (f == FONT_LITERAL)
1182da2e3ebdSchin s++;
1183da2e3ebdSchin f = 0;
1184da2e3ebdSchin break;
1185da2e3ebdSchin default:
1186da2e3ebdSchin if (f)
1187da2e3ebdSchin sfputr(sp, font(f, style, 1), -1);
1188da2e3ebdSchin break;
1189da2e3ebdSchin }
1190da2e3ebdSchin for (;;)
1191da2e3ebdSchin {
1192da2e3ebdSchin if (s >= e)
1193da2e3ebdSchin {
1194da2e3ebdSchin if (!(tsp = psp))
1195da2e3ebdSchin goto restore;
1196da2e3ebdSchin s = psp->ob;
1197da2e3ebdSchin e = psp->oe;
1198da2e3ebdSchin psp = psp->next;
1199da2e3ebdSchin free(tsp);
1200da2e3ebdSchin continue;
1201da2e3ebdSchin }
1202da2e3ebdSchin switch (c = *s++)
1203da2e3ebdSchin {
1204da2e3ebdSchin case '(':
1205da2e3ebdSchin if (n)
1206da2e3ebdSchin {
1207da2e3ebdSchin n = 0;
1208da2e3ebdSchin if (f)
1209da2e3ebdSchin {
1210da2e3ebdSchin sfputr(sp, font(f, style, 0), -1);
1211da2e3ebdSchin f = 0;
1212da2e3ebdSchin }
1213da2e3ebdSchin }
1214da2e3ebdSchin break;
1215da2e3ebdSchin case '?':
1216da2e3ebdSchin case ':':
1217da2e3ebdSchin case ']':
1218da2e3ebdSchin if (psp && psp->ch)
1219da2e3ebdSchin break;
1220da2e3ebdSchin if (y)
1221da2e3ebdSchin {
1222da2e3ebdSchin if (va & OPT_optional)
1223da2e3ebdSchin sfputc(sp, '[');
1224da2e3ebdSchin sfputc(sp, '=');
1225*3e14f97fSRoger A. Faulkner label(sp, 0, y, 0, -1, 0, style, FONT_ITALIC, ip, version, id, catalog);
1226da2e3ebdSchin if (va & OPT_optional)
1227da2e3ebdSchin sfputc(sp, ']');
1228da2e3ebdSchin y = 0;
1229da2e3ebdSchin }
1230da2e3ebdSchin switch (c)
1231da2e3ebdSchin {
1232da2e3ebdSchin case '?':
1233da2e3ebdSchin if (*s == '?')
1234da2e3ebdSchin s++;
1235da2e3ebdSchin else if (*s == ']' && *(s + 1) != ']')
1236da2e3ebdSchin continue;
1237da2e3ebdSchin else if (sep)
1238da2e3ebdSchin goto restore;
1239*3e14f97fSRoger A. Faulkner else if (X(catalog) && (tsp = localize(psp, s, e, 0, 1, ip, version, id, catalog)))
1240da2e3ebdSchin {
1241da2e3ebdSchin psp = tsp;
1242da2e3ebdSchin s = psp->nb;
1243da2e3ebdSchin e = psp->ne;
1244da2e3ebdSchin }
1245da2e3ebdSchin break;
1246da2e3ebdSchin case ']':
1247da2e3ebdSchin if (sep && *s++ != ']')
1248da2e3ebdSchin goto restore;
1249da2e3ebdSchin break;
1250da2e3ebdSchin case ':':
1251da2e3ebdSchin if (sep && *s++ != ':')
1252da2e3ebdSchin goto restore;
1253da2e3ebdSchin break;
1254da2e3ebdSchin }
1255da2e3ebdSchin break;
1256da2e3ebdSchin case '\a':
1257da2e3ebdSchin a = FONT_ITALIC;
1258da2e3ebdSchin setfont:
1259da2e3ebdSchin if (f & ~a)
1260da2e3ebdSchin {
1261da2e3ebdSchin sfputr(sp, font(f, style, 0), -1);
1262da2e3ebdSchin f = 0;
1263da2e3ebdSchin }
1264da2e3ebdSchin if (!f && style == STYLE_html)
1265da2e3ebdSchin {
1266da2e3ebdSchin for (t = s; t < e && !isspace(*t) && !iscntrl(*t); t++);
1267da2e3ebdSchin if (*t == c && *++t == '(')
1268da2e3ebdSchin {
1269da2e3ebdSchin w = t;
1270da2e3ebdSchin while (++t < e && isdigit(*t));
1271da2e3ebdSchin if (t < e && *t == ')' && t > w + 1)
1272da2e3ebdSchin {
1273da2e3ebdSchin sfprintf(sp, "<NOBR><A href=\"../man%-.*s/%-.*s.html\">%s%-.*s%s</A>%-.*s</NOBR>"
1274da2e3ebdSchin , t - w - 1, w + 1
1275da2e3ebdSchin , w - s - 1, s
1276da2e3ebdSchin , font(a, style, 1)
1277da2e3ebdSchin , w - s - 1, s
1278da2e3ebdSchin , font(a, style, 0)
1279da2e3ebdSchin , t - w + 1, w
1280da2e3ebdSchin );
1281da2e3ebdSchin s = t + 1;
1282da2e3ebdSchin continue;
1283da2e3ebdSchin }
1284da2e3ebdSchin }
1285da2e3ebdSchin }
1286da2e3ebdSchin sfputr(sp, font(a, style, !!(f ^= a)), -1);
1287da2e3ebdSchin continue;
1288da2e3ebdSchin case '\b':
1289da2e3ebdSchin a = FONT_BOLD;
1290da2e3ebdSchin goto setfont;
1291da2e3ebdSchin case '\f':
1292*3e14f97fSRoger A. Faulkner psp = info(psp, s, e, ip, id);
1293da2e3ebdSchin if (psp->nb)
1294da2e3ebdSchin {
1295da2e3ebdSchin s = psp->nb;
1296da2e3ebdSchin e = psp->ne;
1297da2e3ebdSchin }
1298da2e3ebdSchin else
1299da2e3ebdSchin {
1300da2e3ebdSchin s = psp->ob;
1301da2e3ebdSchin psp = psp->next;
1302da2e3ebdSchin }
1303da2e3ebdSchin continue;
1304da2e3ebdSchin case '\n':
1305da2e3ebdSchin sfputc(sp, c);
1306da2e3ebdSchin for (i = 0; i < level; i++)
1307da2e3ebdSchin sfputc(sp, '\t');
1308da2e3ebdSchin continue;
1309da2e3ebdSchin case '\v':
1310da2e3ebdSchin a = FONT_LITERAL;
1311da2e3ebdSchin goto setfont;
1312da2e3ebdSchin case '<':
1313da2e3ebdSchin if (style == STYLE_html)
1314da2e3ebdSchin {
1315da2e3ebdSchin sfputr(sp, "<", -1);
1316da2e3ebdSchin c = 0;
1317da2e3ebdSchin for (t = s; t < e; t++)
1318da2e3ebdSchin if (!isalnum(*t) && *t != '_' && *t != '.' && *t != '-')
1319da2e3ebdSchin {
1320da2e3ebdSchin if (*t == '@')
1321da2e3ebdSchin {
1322da2e3ebdSchin if (c)
1323da2e3ebdSchin break;
1324da2e3ebdSchin c = 1;
1325da2e3ebdSchin }
1326da2e3ebdSchin else if (*t == '>')
1327da2e3ebdSchin {
1328da2e3ebdSchin if (c)
1329da2e3ebdSchin {
1330da2e3ebdSchin sfprintf(sp, "<A href=\"mailto:%-.*s>%-.*s</A>>", t - s, s, t - s, s);
1331da2e3ebdSchin s = t + 1;
1332da2e3ebdSchin }
1333da2e3ebdSchin break;
1334da2e3ebdSchin }
1335da2e3ebdSchin else
1336da2e3ebdSchin break;
1337da2e3ebdSchin }
1338da2e3ebdSchin continue;
1339da2e3ebdSchin }
1340da2e3ebdSchin break;
1341da2e3ebdSchin case '>':
1342da2e3ebdSchin if (style == STYLE_html)
1343da2e3ebdSchin {
1344da2e3ebdSchin sfputr(sp, ">", -1);
1345da2e3ebdSchin continue;
1346da2e3ebdSchin }
1347da2e3ebdSchin break;
1348da2e3ebdSchin case '&':
1349da2e3ebdSchin if (style == STYLE_html)
1350da2e3ebdSchin {
1351da2e3ebdSchin sfputr(sp, "&", -1);
1352da2e3ebdSchin continue;
1353da2e3ebdSchin }
1354da2e3ebdSchin break;
1355da2e3ebdSchin case '-':
1356da2e3ebdSchin if (ostyle == STYLE_nroff)
1357da2e3ebdSchin sfputc(sp, '\\');
1358da2e3ebdSchin break;
1359da2e3ebdSchin case '.':
1360da2e3ebdSchin if (ostyle == STYLE_nroff)
1361da2e3ebdSchin {
1362da2e3ebdSchin sfputc(sp, '\\');
1363da2e3ebdSchin sfputc(sp, '&');
1364da2e3ebdSchin }
1365da2e3ebdSchin break;
1366da2e3ebdSchin case '\\':
1367da2e3ebdSchin if (ostyle == STYLE_nroff)
1368da2e3ebdSchin {
1369da2e3ebdSchin c = 'e';
1370da2e3ebdSchin sfputc(sp, '\\');
1371da2e3ebdSchin }
1372da2e3ebdSchin break;
1373da2e3ebdSchin case ' ':
1374da2e3ebdSchin if (ostyle == STYLE_nroff)
1375da2e3ebdSchin sfputc(sp, '\\');
1376da2e3ebdSchin break;
1377da2e3ebdSchin }
1378da2e3ebdSchin sfputc(sp, c);
1379da2e3ebdSchin }
1380da2e3ebdSchin restore:
1381da2e3ebdSchin if (f)
1382da2e3ebdSchin sfputr(sp, font(f, style, 0), -1);
13837c2fbfb3SApril Chin if (about)
13847c2fbfb3SApril Chin sfputc(sp, ')');
1385da2e3ebdSchin if (psp)
1386da2e3ebdSchin pop(psp);
1387da2e3ebdSchin return r;
1388da2e3ebdSchin }
1389da2e3ebdSchin
1390da2e3ebdSchin /*
1391da2e3ebdSchin * output args description to sp from p of length n
1392da2e3ebdSchin */
1393da2e3ebdSchin
1394da2e3ebdSchin static void
args(register Sfio_t * sp,register char * p,register int n,int flags,int style,Sfio_t * ip,int version,char * id,char * catalog)1395*3e14f97fSRoger A. Faulkner args(register Sfio_t* sp, register char* p, register int n, int flags, int style, Sfio_t* ip, int version, char* id, char* catalog)
1396da2e3ebdSchin {
1397da2e3ebdSchin register int i;
1398da2e3ebdSchin register char* t;
1399da2e3ebdSchin register char* o;
1400da2e3ebdSchin register char* a = 0;
1401da2e3ebdSchin char* b;
1402da2e3ebdSchin int sep;
1403da2e3ebdSchin
1404da2e3ebdSchin if (flags & OPT_functions)
1405da2e3ebdSchin sep = '\t';
1406da2e3ebdSchin else
1407da2e3ebdSchin {
1408da2e3ebdSchin sep = ' ';
1409da2e3ebdSchin o = T(NiL, ID, "options");
1410da2e3ebdSchin b = style == STYLE_nroff ? "\\ " : " ";
1411da2e3ebdSchin for (;;)
1412da2e3ebdSchin {
1413da2e3ebdSchin t = (char*)memchr(p, '\n', n);
1414da2e3ebdSchin if (style >= STYLE_man)
1415da2e3ebdSchin {
1416*3e14f97fSRoger A. Faulkner if (!(a = id))
1417da2e3ebdSchin a = "...";
1418da2e3ebdSchin 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);
1419da2e3ebdSchin }
1420da2e3ebdSchin else if (a)
1421da2e3ebdSchin 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);
1422da2e3ebdSchin else
1423da2e3ebdSchin {
1424*3e14f97fSRoger A. Faulkner if (!(a = error_info.id) && !(a = id))
1425da2e3ebdSchin a = "...";
1426da2e3ebdSchin if (!sfstrtell(sp))
1427da2e3ebdSchin sfprintf(sp, "[%s%s%s]", b, o, b);
1428da2e3ebdSchin }
1429da2e3ebdSchin if (!t)
1430da2e3ebdSchin break;
1431da2e3ebdSchin i = ++t - p;
1432da2e3ebdSchin if (i)
1433da2e3ebdSchin {
1434da2e3ebdSchin sfputr(sp, b, -1);
1435da2e3ebdSchin if (X(catalog))
1436da2e3ebdSchin {
1437da2e3ebdSchin sfwrite(ip, p, i);
1438da2e3ebdSchin if (b = sfstruse(ip))
1439*3e14f97fSRoger A. Faulkner sfputr(sp, T(id, catalog, b), -1);
1440da2e3ebdSchin else
1441da2e3ebdSchin sfwrite(sp, p, i);
1442da2e3ebdSchin }
1443da2e3ebdSchin else
1444da2e3ebdSchin sfwrite(sp, p, i);
1445da2e3ebdSchin }
1446da2e3ebdSchin if (style == STYLE_html)
1447da2e3ebdSchin sfputr(sp, "<BR>", '\n');
1448da2e3ebdSchin else if (style == STYLE_nroff)
1449da2e3ebdSchin sfputr(sp, ".br", '\n');
1450da2e3ebdSchin else if (style == STYLE_api)
1451da2e3ebdSchin sfputr(sp, ".BR", '\n');
1452da2e3ebdSchin p = t;
1453da2e3ebdSchin n -= i;
1454da2e3ebdSchin while (n > 0 && (*p == ' ' || *p == '\t'))
1455da2e3ebdSchin {
1456da2e3ebdSchin p++;
1457da2e3ebdSchin n--;
1458da2e3ebdSchin }
1459da2e3ebdSchin }
1460da2e3ebdSchin }
1461da2e3ebdSchin if (n)
1462*3e14f97fSRoger A. Faulkner label(sp, sep, p, 0, n, 0, style, 0, ip, version, id, catalog);
1463da2e3ebdSchin }
1464da2e3ebdSchin
1465da2e3ebdSchin /*
1466da2e3ebdSchin * output [+-...label...?...] label s to sp
1467da2e3ebdSchin * according to {...} level and style
1468da2e3ebdSchin * return 0:header 1:paragraph
1469da2e3ebdSchin */
1470da2e3ebdSchin
1471da2e3ebdSchin static int
item(Sfio_t * sp,char * s,int about,int level,int style,Sfio_t * ip,int version,char * id,char * catalog)1472*3e14f97fSRoger A. Faulkner item(Sfio_t* sp, char* s, int about, int level, int style, Sfio_t* ip, int version, char* id, char* catalog)
1473da2e3ebdSchin {
1474da2e3ebdSchin register char* t;
1475da2e3ebdSchin int n;
1476da2e3ebdSchin int par;
1477da2e3ebdSchin
1478da2e3ebdSchin sfputc(sp, '\n');
1479da2e3ebdSchin if (*s == '\n')
1480da2e3ebdSchin {
1481da2e3ebdSchin par = 0;
1482da2e3ebdSchin if (style >= STYLE_nroff)
1483da2e3ebdSchin sfprintf(sp, ".DS\n");
1484da2e3ebdSchin else
1485da2e3ebdSchin {
1486da2e3ebdSchin if (style == STYLE_html)
1487da2e3ebdSchin sfprintf(sp, "<PRE>\n");
1488da2e3ebdSchin else
1489da2e3ebdSchin sfputc(sp, '\n');
1490da2e3ebdSchin for (n = 0; n < level; n++)
1491da2e3ebdSchin sfputc(sp, '\t');
1492da2e3ebdSchin }
1493*3e14f97fSRoger A. Faulkner label(sp, 0, s + 1, about, -1, level, style, FONT_LITERAL, ip, version, id, catalog);
1494da2e3ebdSchin sfputc(sp, '\n');
1495da2e3ebdSchin if (style >= STYLE_nroff)
1496da2e3ebdSchin sfprintf(sp, ".DE");
1497da2e3ebdSchin else if (style == STYLE_html)
1498da2e3ebdSchin sfprintf(sp, "</PRE>");
1499da2e3ebdSchin }
1500da2e3ebdSchin else if (*s != ']' && (*s != '?' || *(s + 1) == '?'))
1501da2e3ebdSchin {
1502da2e3ebdSchin par = 0;
1503da2e3ebdSchin if (level)
1504da2e3ebdSchin {
1505da2e3ebdSchin if (style >= STYLE_nroff)
15067c2fbfb3SApril Chin sfprintf(sp, ".H%d ", (level - (level > 2)) / 2);
1507da2e3ebdSchin else
1508da2e3ebdSchin for (n = 0; n < level; n++)
1509da2e3ebdSchin sfputc(sp, '\t');
1510da2e3ebdSchin }
1511da2e3ebdSchin if (style == STYLE_html)
1512da2e3ebdSchin {
1513da2e3ebdSchin if (!level)
1514da2e3ebdSchin sfputr(sp, "<H4>", -1);
1515da2e3ebdSchin sfputr(sp, "<A name=\"", -1);
1516da2e3ebdSchin 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] == '?')
1517da2e3ebdSchin for (t = s + 8; *t && *t != ']'; t++)
1518da2e3ebdSchin if (t[0] == 'p' && (!strncmp(t, "proprietary", 11) || !strncmp(t, "private", 7)) || t[0] == 'n' && !strncmp(t, "noncommercial", 13))
1519da2e3ebdSchin {
1520da2e3ebdSchin opt_info.state->flags |= OPT_proprietary;
1521da2e3ebdSchin break;
1522da2e3ebdSchin }
1523*3e14f97fSRoger A. Faulkner label(sp, 0, s, about, -1, level, 0, 0, ip, version, id, catalog);
1524da2e3ebdSchin sfputr(sp, "\">", -1);
1525*3e14f97fSRoger A. Faulkner label(sp, 0, s, about, -1, level, style, level ? FONT_BOLD : 0, ip, version, id, catalog);
1526da2e3ebdSchin sfputr(sp, "</A>", -1);
1527da2e3ebdSchin if (!level)
1528da2e3ebdSchin sfputr(sp, "</H4>", -1);
1529da2e3ebdSchin }
1530da2e3ebdSchin else
1531da2e3ebdSchin {
1532da2e3ebdSchin if (!level)
1533da2e3ebdSchin {
1534da2e3ebdSchin if (style >= STYLE_nroff)
1535da2e3ebdSchin sfprintf(sp, ".SH ");
1536da2e3ebdSchin else if (style == STYLE_man)
1537da2e3ebdSchin sfputc(sp, '\n');
1538da2e3ebdSchin else if (style != STYLE_options && style != STYLE_match || *s == '-' || *s == '+')
1539da2e3ebdSchin sfputc(sp, '\t');
1540da2e3ebdSchin }
1541*3e14f97fSRoger A. Faulkner label(sp, 0, s, about, -1, level, style, FONT_BOLD, ip, version, id, catalog);
1542da2e3ebdSchin }
1543da2e3ebdSchin }
1544da2e3ebdSchin else
1545da2e3ebdSchin {
1546da2e3ebdSchin par = 1;
1547da2e3ebdSchin if (style >= STYLE_nroff)
15487c2fbfb3SApril Chin sfputr(sp, level ? ".SP" : ".PP", -1);
1549da2e3ebdSchin }
1550da2e3ebdSchin if (style >= STYLE_nroff || !level)
1551da2e3ebdSchin sfputc(sp, '\n');
1552da2e3ebdSchin if (par && style < STYLE_nroff)
1553da2e3ebdSchin for (n = 0; n < level; n++)
1554da2e3ebdSchin sfputc(sp, '\t');
1555da2e3ebdSchin return par;
1556da2e3ebdSchin }
1557da2e3ebdSchin
1558da2e3ebdSchin /*
1559da2e3ebdSchin * output text to sp from p according to style
1560da2e3ebdSchin */
1561da2e3ebdSchin
1562*3e14f97fSRoger A. Faulkner #if _BLD_DEBUG
1563*3e14f97fSRoger A. Faulkner
1564*3e14f97fSRoger A. Faulkner static char* textout(Sfio_t*, char*, int, int, int, Sfio_t*, int, char*, char*);
1565*3e14f97fSRoger A. Faulkner
1566da2e3ebdSchin static char*
trace_textout(Sfio_t * sp,register char * p,int style,int level,int bump,Sfio_t * ip,int version,char * id,char * catalog,int line)1567*3e14f97fSRoger A. Faulkner trace_textout(Sfio_t* sp, register char* p, int style, int level, int bump, Sfio_t* ip, int version, char* id, char* catalog, int line)
1568da2e3ebdSchin {
1569*3e14f97fSRoger A. Faulkner static int depth = 0;
1570*3e14f97fSRoger A. Faulkner
1571*3e14f97fSRoger A. Faulkner message((-21, "opthelp: txt#%d +++ %2d \"%s\" style=%d level=%d bump=%d", line, ++depth, show(p), style, level, bump));
1572*3e14f97fSRoger A. Faulkner p = textout(sp, p, style, level, bump, ip, version, id, catalog);
1573*3e14f97fSRoger A. Faulkner message((-21, "opthelp: txt#%d --- %2d \"%s\"", line, depth--, show(p)));
1574*3e14f97fSRoger A. Faulkner return p;
1575*3e14f97fSRoger A. Faulkner }
1576*3e14f97fSRoger A. Faulkner
1577*3e14f97fSRoger A. Faulkner #endif
1578*3e14f97fSRoger A. Faulkner
1579*3e14f97fSRoger A. Faulkner static char*
textout(Sfio_t * sp,register char * p,int style,int level,int bump,Sfio_t * ip,int version,char * id,char * catalog)1580*3e14f97fSRoger A. Faulkner textout(Sfio_t* sp, register char* p, int style, int level, int bump, Sfio_t* ip, int version, char* id, char* catalog)
1581*3e14f97fSRoger A. Faulkner {
1582*3e14f97fSRoger A. Faulkner #if _BLD_DEBUG
1583*3e14f97fSRoger A. Faulkner #define textout(sp,p,style,level,bump,ip,version,id,catalog) trace_textout(sp,p,style,level,bump,ip,version,id,catalog,__LINE__)
1584da2e3ebdSchin #endif
1585da2e3ebdSchin register char* t;
1586da2e3ebdSchin register int c;
1587da2e3ebdSchin register int n;
1588da2e3ebdSchin char* e;
1589da2e3ebdSchin int a;
1590da2e3ebdSchin int f;
1591da2e3ebdSchin int par;
15927c2fbfb3SApril Chin int about;
1593da2e3ebdSchin Push_t* tsp;
1594da2e3ebdSchin
1595da2e3ebdSchin int ident = 0;
1596da2e3ebdSchin int lev = level;
1597da2e3ebdSchin Push_t* psp = 0;
1598da2e3ebdSchin
1599da2e3ebdSchin again:
16007c2fbfb3SApril Chin about = 0;
1601da2e3ebdSchin if ((c = *p) == GO)
1602da2e3ebdSchin {
1603da2e3ebdSchin for (;;)
1604da2e3ebdSchin {
1605da2e3ebdSchin while (*(p = next(p + 1, version)) == '\n');
1606da2e3ebdSchin if (*p == GO)
1607da2e3ebdSchin {
1608da2e3ebdSchin if (level > 1)
1609da2e3ebdSchin level++;
1610da2e3ebdSchin level++;
1611da2e3ebdSchin }
1612da2e3ebdSchin else if (*p != OG)
1613da2e3ebdSchin {
16147c2fbfb3SApril Chin if (level <= 1 || *p != '[' || *(p + 1) != '-' || style == STYLE_man && *(p + 2) == '?' || isalpha(*(p + 2)))
1615da2e3ebdSchin break;
1616da2e3ebdSchin p = skip(p, 0, 0, 0, 1, level, 0, version);
1617da2e3ebdSchin }
1618da2e3ebdSchin else if ((level -= 2) <= lev)
1619da2e3ebdSchin return p + 1;
1620da2e3ebdSchin }
1621da2e3ebdSchin if (*p == '\f')
1622da2e3ebdSchin {
1623*3e14f97fSRoger A. Faulkner psp = info(psp, p + 1, NiL, ip, id);
1624da2e3ebdSchin if (psp->nb)
1625da2e3ebdSchin p = psp->nb;
1626da2e3ebdSchin else
1627da2e3ebdSchin {
1628da2e3ebdSchin p = psp->ob;
1629da2e3ebdSchin psp = psp->next;
1630da2e3ebdSchin }
1631da2e3ebdSchin }
1632da2e3ebdSchin if (*p != '[')
1633da2e3ebdSchin return p;
1634da2e3ebdSchin c = *++p;
1635da2e3ebdSchin if (level > 1)
1636da2e3ebdSchin level++;
1637da2e3ebdSchin level++;
1638da2e3ebdSchin }
1639da2e3ebdSchin if (c == '-' && level > 1)
16407c2fbfb3SApril Chin {
16417c2fbfb3SApril Chin if (style == STYLE_man)
16427c2fbfb3SApril Chin {
16437c2fbfb3SApril Chin about = 1;
16447c2fbfb3SApril Chin if (*(p + 1) == '-')
16457c2fbfb3SApril Chin p++;
16467c2fbfb3SApril Chin }
16477c2fbfb3SApril Chin else
16487c2fbfb3SApril Chin for (;;)
16497c2fbfb3SApril Chin {
16507c2fbfb3SApril Chin p = skip(p, 0, 0, 0, 1, level, 0, version);
16517c2fbfb3SApril Chin while (*(p = next(p + 1, version)) == '\n');
16527c2fbfb3SApril Chin if (*p == '[')
16537c2fbfb3SApril Chin {
16547c2fbfb3SApril Chin if ((c = *++p) != '-')
16557c2fbfb3SApril Chin break;
16567c2fbfb3SApril Chin }
16577c2fbfb3SApril Chin else if (*p == GO)
16587c2fbfb3SApril Chin goto again;
16597c2fbfb3SApril Chin else if (*p == OG)
16607c2fbfb3SApril Chin return p + 1;
16617c2fbfb3SApril Chin }
16627c2fbfb3SApril Chin }
1663da2e3ebdSchin if (c == '+' || c == '-' && (bump = 3) || c != ' ' && level > 1)
1664da2e3ebdSchin {
1665da2e3ebdSchin p = skip(t = p + 1, '?', 0, 0, 1, level, 0, version);
16667c2fbfb3SApril Chin if (c == '-' && (*t == '?' || isdigit(*t) || *p == '?' && *(p + 1) == '\n'))
1667da2e3ebdSchin {
1668da2e3ebdSchin if ((c = *p) != '?')
1669da2e3ebdSchin return skip(p, 0, 0, 0, 1, level, 1, version);
16707c2fbfb3SApril Chin e = C("version");
1671*3e14f97fSRoger A. Faulkner par = item(sp, e, about, level, style, ip, version, id, ID);
1672da2e3ebdSchin for (;;)
1673da2e3ebdSchin {
1674da2e3ebdSchin while (isspace(*(p + 1)))
1675da2e3ebdSchin p++;
1676da2e3ebdSchin e = p;
1677da2e3ebdSchin if (e[1] == '@' && e[2] == '(' && e[3] == '#' && e[4] == ')')
1678da2e3ebdSchin p = e + 4;
1679da2e3ebdSchin else if (e[1] == '$' && e[2] == 'I' && e[3] == 'd' && e[4] == ':' && e[5] == ' ')
1680da2e3ebdSchin {
1681da2e3ebdSchin p = e + 5;
1682da2e3ebdSchin ident = 1;
1683da2e3ebdSchin }
1684da2e3ebdSchin else
1685da2e3ebdSchin break;
1686da2e3ebdSchin }
1687da2e3ebdSchin }
1688da2e3ebdSchin else
1689da2e3ebdSchin {
1690da2e3ebdSchin if (isdigit(c) && isdigit(*t))
1691da2e3ebdSchin {
1692da2e3ebdSchin while (isdigit(*t))
1693da2e3ebdSchin t++;
1694da2e3ebdSchin if (*t == ':')
1695da2e3ebdSchin t++;
1696da2e3ebdSchin }
1697da2e3ebdSchin else if (isalnum(c) && *t-- == ':')
1698da2e3ebdSchin {
1699da2e3ebdSchin if (X(catalog) || *t == *(t + 2))
1700da2e3ebdSchin t += 2;
1701da2e3ebdSchin else
1702da2e3ebdSchin {
1703da2e3ebdSchin sfprintf(ip, "%s", t);
1704da2e3ebdSchin if (e = sfstruse(ip))
1705da2e3ebdSchin *((t = e) + 1) = '|';
1706da2e3ebdSchin }
1707da2e3ebdSchin }
1708*3e14f97fSRoger A. Faulkner par = item(sp, t, about, level, style, ip, version, id, catalog);
1709da2e3ebdSchin c = *p;
1710da2e3ebdSchin }
17117c2fbfb3SApril Chin if (!about && level)
1712da2e3ebdSchin par = 0;
1713da2e3ebdSchin }
1714da2e3ebdSchin else
1715da2e3ebdSchin {
1716da2e3ebdSchin if (style >= STYLE_nroff)
1717da2e3ebdSchin sfputc(sp, '\n');
1718da2e3ebdSchin else if (c == '?')
1719da2e3ebdSchin for (n = 0; n < level; n++)
1720da2e3ebdSchin sfputc(sp, '\t');
1721da2e3ebdSchin par = 0;
1722da2e3ebdSchin }
1723da2e3ebdSchin if (c == ':')
1724da2e3ebdSchin c = *(p = skip(p, '?', 0, 0, 1, 0, 0, version));
1725da2e3ebdSchin if ((c == ']' || c == '?' && *(p + 1) == ']' && *(p + 2) != ']' && p++) && (c = *(p = next(p + 1, version))) == GO)
1726*3e14f97fSRoger A. Faulkner {
1727*3e14f97fSRoger A. Faulkner p = textout(sp, p, style, level + bump + par + 1, 0, ip, version, id, catalog);
1728*3e14f97fSRoger A. Faulkner if (level > lev && *p && *(p = next(p, version)) == '[')
1729*3e14f97fSRoger A. Faulkner {
1730*3e14f97fSRoger A. Faulkner p++;
1731*3e14f97fSRoger A. Faulkner message((-21, "textout#%d p=%s", __LINE__, show(p)));
1732*3e14f97fSRoger A. Faulkner goto again;
1733*3e14f97fSRoger A. Faulkner }
1734*3e14f97fSRoger A. Faulkner }
1735da2e3ebdSchin else if (c == '?' || c == ' ')
1736da2e3ebdSchin {
1737da2e3ebdSchin p++;
1738da2e3ebdSchin if (c == ' ')
1739da2e3ebdSchin sfputc(sp, c);
1740da2e3ebdSchin else
1741da2e3ebdSchin {
1742*3e14f97fSRoger A. Faulkner if (X(catalog) && (tsp = localize(psp, p, NiL, 0, 1, ip, version, id, catalog)))
1743da2e3ebdSchin {
1744da2e3ebdSchin psp = tsp;
1745da2e3ebdSchin p = psp->nb;
1746da2e3ebdSchin }
1747da2e3ebdSchin if (style < STYLE_nroff)
1748da2e3ebdSchin for (n = 0; n < bump + 1; n++)
1749da2e3ebdSchin sfputc(sp, '\t');
1750da2e3ebdSchin }
1751da2e3ebdSchin f = 0;
1752da2e3ebdSchin for (;;)
1753da2e3ebdSchin {
1754da2e3ebdSchin switch (c = *p++)
1755da2e3ebdSchin {
1756da2e3ebdSchin case 0:
1757da2e3ebdSchin if (!(tsp = psp))
1758da2e3ebdSchin {
1759da2e3ebdSchin if (f)
1760da2e3ebdSchin sfputr(sp, font(f, style, 0), -1);
1761da2e3ebdSchin return p - 1;
1762da2e3ebdSchin }
1763da2e3ebdSchin p = psp->ob;
1764da2e3ebdSchin psp = psp->next;
1765da2e3ebdSchin free(tsp);
1766da2e3ebdSchin continue;
1767da2e3ebdSchin case ']':
1768da2e3ebdSchin if (psp && psp->ch)
1769da2e3ebdSchin break;
1770da2e3ebdSchin if (*p != ']')
1771da2e3ebdSchin {
1772da2e3ebdSchin if (f)
1773da2e3ebdSchin {
1774da2e3ebdSchin sfputr(sp, font(f, style, 0), -1);
1775da2e3ebdSchin f = 0;
1776da2e3ebdSchin }
1777da2e3ebdSchin for (;;)
1778da2e3ebdSchin {
1779da2e3ebdSchin if ((*p == '#' || *p == ':') && level > lev)
1780da2e3ebdSchin {
1781da2e3ebdSchin char* o;
1782da2e3ebdSchin char* v;
1783da2e3ebdSchin int j;
1784da2e3ebdSchin int m;
1785da2e3ebdSchin int ol;
1786da2e3ebdSchin int vl;
1787da2e3ebdSchin
1788da2e3ebdSchin a = 0;
1789da2e3ebdSchin o = 0;
1790da2e3ebdSchin v = 0;
1791da2e3ebdSchin if (*++p == '?' || *p == *(p - 1))
1792da2e3ebdSchin {
1793da2e3ebdSchin p++;
1794da2e3ebdSchin a |= OPT_optional;
1795da2e3ebdSchin }
1796da2e3ebdSchin if (*(p = next(p, version)) == '[')
1797da2e3ebdSchin {
1798da2e3ebdSchin p = skip(p + 1, ':', '?', 0, 1, 0, 0, version);
1799da2e3ebdSchin while (*p == ':')
1800da2e3ebdSchin {
1801da2e3ebdSchin p = skip(t = p + 1, ':', '?', 0, 1, 0, 0, version);
1802da2e3ebdSchin m = p - t;
1803da2e3ebdSchin if (*t == '!')
1804da2e3ebdSchin {
1805da2e3ebdSchin o = t + 1;
1806da2e3ebdSchin ol = m - 1;
1807da2e3ebdSchin }
1808da2e3ebdSchin else if (*t == '=')
1809da2e3ebdSchin {
1810da2e3ebdSchin v = t + 1;
1811da2e3ebdSchin vl = m - 1;
1812da2e3ebdSchin }
1813da2e3ebdSchin else
1814da2e3ebdSchin for (j = 0; j < elementsof(attrs); j++)
1815da2e3ebdSchin if (strneq(t, attrs[j].name, m))
1816da2e3ebdSchin {
1817da2e3ebdSchin a |= attrs[j].flag;
1818da2e3ebdSchin break;
1819da2e3ebdSchin }
1820da2e3ebdSchin }
1821da2e3ebdSchin }
1822da2e3ebdSchin if (a & OPT_optional)
1823da2e3ebdSchin {
1824da2e3ebdSchin if (o)
1825da2e3ebdSchin {
1826da2e3ebdSchin sfprintf(sp, " %s ", T(NiL, ID, "If the option value is omitted then"));
1827da2e3ebdSchin sfputr(sp, font(FONT_BOLD, style, 1), -1);
1828da2e3ebdSchin t = o + ol;
1829da2e3ebdSchin while (o < t)
1830da2e3ebdSchin {
1831da2e3ebdSchin if (((c = *o++) == ':' || c == '?') && *o == c)
1832da2e3ebdSchin o++;
1833da2e3ebdSchin sfputc(sp, c);
1834da2e3ebdSchin }
1835da2e3ebdSchin sfputr(sp, font(FONT_BOLD, style, 0), -1);
1836da2e3ebdSchin sfprintf(sp, " %s.", T(NiL, ID, "is assumed"));
1837da2e3ebdSchin }
1838da2e3ebdSchin else
1839da2e3ebdSchin sfprintf(sp, " %s", T(NiL, ID, "The option value may be omitted."));
1840da2e3ebdSchin }
1841da2e3ebdSchin if (v)
1842da2e3ebdSchin {
1843da2e3ebdSchin sfprintf(sp, " %s ", T(NiL, ID, "The default value is"));
1844da2e3ebdSchin sfputr(sp, font(FONT_BOLD, style, 1), -1);
1845da2e3ebdSchin t = v + vl;
1846da2e3ebdSchin while (v < t)
1847da2e3ebdSchin {
1848da2e3ebdSchin if (((c = *v++) == ':' || c == '?') && *v == c)
1849da2e3ebdSchin v++;
1850da2e3ebdSchin sfputc(sp, c);
1851da2e3ebdSchin }
1852da2e3ebdSchin sfputr(sp, font(FONT_BOLD, style, 0), -1);
1853da2e3ebdSchin sfputc(sp, '.');
1854da2e3ebdSchin }
1855da2e3ebdSchin p = skip(p, 0, 0, 0, 1, 0, 1, version);
1856da2e3ebdSchin }
1857da2e3ebdSchin if (*(p = next(p, version)) == GO)
1858*3e14f97fSRoger A. Faulkner {
1859*3e14f97fSRoger A. Faulkner p = textout(sp, p, style, level + bump + !level, 0, ip, version, id, catalog);
1860*3e14f97fSRoger A. Faulkner if (*p && *(p = next(p, version)) == '[' && !isalnum(*(p + 1)))
1861*3e14f97fSRoger A. Faulkner {
1862*3e14f97fSRoger A. Faulkner p++;
1863*3e14f97fSRoger A. Faulkner message((-21, "textout#%d p=%s", __LINE__, show(p)));
1864*3e14f97fSRoger A. Faulkner goto again;
1865*3e14f97fSRoger A. Faulkner }
1866*3e14f97fSRoger A. Faulkner }
1867da2e3ebdSchin else if (*p == '[' && level > lev)
1868da2e3ebdSchin {
1869da2e3ebdSchin p++;
1870da2e3ebdSchin goto again;
1871da2e3ebdSchin }
1872da2e3ebdSchin else if (*p == '\f')
1873da2e3ebdSchin {
1874da2e3ebdSchin p++;
1875da2e3ebdSchin if (style != STYLE_keys)
1876da2e3ebdSchin {
1877*3e14f97fSRoger A. Faulkner psp = info(psp, p, NiL, ip, id);
1878da2e3ebdSchin if (psp->nb)
1879da2e3ebdSchin p = psp->nb;
1880da2e3ebdSchin else
1881da2e3ebdSchin {
1882da2e3ebdSchin p = psp->ob;
1883da2e3ebdSchin psp = psp->next;
1884da2e3ebdSchin }
1885da2e3ebdSchin }
1886da2e3ebdSchin }
1887da2e3ebdSchin else if (!*p)
1888da2e3ebdSchin {
1889da2e3ebdSchin if (!(tsp = psp))
1890da2e3ebdSchin break;
1891da2e3ebdSchin p = psp->ob;
1892da2e3ebdSchin psp = psp->next;
1893da2e3ebdSchin free(tsp);
1894da2e3ebdSchin }
1895da2e3ebdSchin else if (*p != OG)
1896da2e3ebdSchin break;
1897da2e3ebdSchin else
1898da2e3ebdSchin {
1899da2e3ebdSchin p++;
1900da2e3ebdSchin if ((level -= 2) <= lev)
1901da2e3ebdSchin break;
1902da2e3ebdSchin }
1903da2e3ebdSchin }
1904da2e3ebdSchin return p;
1905da2e3ebdSchin }
1906da2e3ebdSchin p++;
1907da2e3ebdSchin break;
1908da2e3ebdSchin case '\a':
1909da2e3ebdSchin a = FONT_ITALIC;
1910da2e3ebdSchin setfont:
1911da2e3ebdSchin if (f & ~a)
1912da2e3ebdSchin {
1913da2e3ebdSchin sfputr(sp, font(f, style, 0), -1);
1914da2e3ebdSchin f = 0;
1915da2e3ebdSchin }
1916da2e3ebdSchin if (!f && style == STYLE_html)
1917da2e3ebdSchin {
1918da2e3ebdSchin for (t = p; *t && !isspace(*t) && !iscntrl(*t); t++);
1919da2e3ebdSchin if (*t == c && *++t == '(')
1920da2e3ebdSchin {
1921da2e3ebdSchin e = t;
1922da2e3ebdSchin while (isdigit(*++t));
1923da2e3ebdSchin if (*t == ')' && t > e + 1)
1924da2e3ebdSchin {
1925da2e3ebdSchin sfprintf(sp, "<NOBR><A href=\"../man%-.*s/%-.*s.html\">%s%-.*s%s</A>%-.*s</NOBR>"
1926da2e3ebdSchin , t - e - 1, e + 1
1927da2e3ebdSchin , e - p - 1, p
1928da2e3ebdSchin , font(a, style, 1)
1929da2e3ebdSchin , e - p - 1, p
1930da2e3ebdSchin , font(a, style, 0)
1931da2e3ebdSchin , t - e + 1, e
1932da2e3ebdSchin );
1933da2e3ebdSchin p = t + 1;
1934da2e3ebdSchin continue;
1935da2e3ebdSchin }
1936da2e3ebdSchin }
1937da2e3ebdSchin }
1938da2e3ebdSchin sfputr(sp, font(a, style, !!(f ^= a)), -1);
1939da2e3ebdSchin continue;
1940da2e3ebdSchin case '\b':
1941da2e3ebdSchin a = FONT_BOLD;
1942da2e3ebdSchin goto setfont;
1943da2e3ebdSchin case '\f':
1944da2e3ebdSchin if (style != STYLE_keys)
1945da2e3ebdSchin {
1946*3e14f97fSRoger A. Faulkner psp = info(psp, p, NiL, ip, id);
1947da2e3ebdSchin if (psp->nb)
1948da2e3ebdSchin p = psp->nb;
1949da2e3ebdSchin else
1950da2e3ebdSchin {
1951da2e3ebdSchin p = psp->ob;
1952da2e3ebdSchin psp = psp->next;
1953da2e3ebdSchin }
1954da2e3ebdSchin }
1955da2e3ebdSchin continue;
1956da2e3ebdSchin case '\v':
1957da2e3ebdSchin a = FONT_LITERAL;
1958da2e3ebdSchin goto setfont;
1959da2e3ebdSchin case ' ':
1960da2e3ebdSchin if (ident && *p == '$')
1961da2e3ebdSchin {
1962da2e3ebdSchin while (*++p)
1963da2e3ebdSchin if (*p == ']')
1964da2e3ebdSchin {
1965da2e3ebdSchin if (*(p + 1) != ']')
1966da2e3ebdSchin break;
1967da2e3ebdSchin p++;
1968da2e3ebdSchin }
1969da2e3ebdSchin continue;
1970da2e3ebdSchin }
1971da2e3ebdSchin case '\n':
1972da2e3ebdSchin case '\r':
1973da2e3ebdSchin case '\t':
1974da2e3ebdSchin while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
1975da2e3ebdSchin p++;
1976da2e3ebdSchin if (*p == ']' && *(p + 1) != ']' && (!psp || !psp->ch))
1977da2e3ebdSchin continue;
1978da2e3ebdSchin c = ' ';
1979da2e3ebdSchin break;
1980da2e3ebdSchin case '<':
1981da2e3ebdSchin if (style == STYLE_html)
1982da2e3ebdSchin {
1983da2e3ebdSchin sfputr(sp, "<", -1);
1984da2e3ebdSchin c = 0;
1985da2e3ebdSchin for (t = p; *t; t++)
1986da2e3ebdSchin if (!isalnum(*t) && *t != '_' && *t != '.' && *t != '-')
1987da2e3ebdSchin {
1988da2e3ebdSchin if (*t == '@')
1989da2e3ebdSchin {
1990da2e3ebdSchin if (c)
1991da2e3ebdSchin break;
1992da2e3ebdSchin c = 1;
1993da2e3ebdSchin }
1994da2e3ebdSchin else if (*t == '>')
1995da2e3ebdSchin {
1996da2e3ebdSchin if (c)
1997da2e3ebdSchin {
1998da2e3ebdSchin sfprintf(sp, "<A href=\"mailto:%-.*s\">%-.*s</A>>", t - p, p, t - p, p);
1999da2e3ebdSchin p = t + 1;
2000da2e3ebdSchin }
2001da2e3ebdSchin break;
2002da2e3ebdSchin }
2003da2e3ebdSchin else
2004da2e3ebdSchin break;
2005da2e3ebdSchin }
2006da2e3ebdSchin continue;
2007da2e3ebdSchin }
2008da2e3ebdSchin break;
2009da2e3ebdSchin case '>':
2010da2e3ebdSchin if (style == STYLE_html)
2011da2e3ebdSchin {
2012da2e3ebdSchin sfputr(sp, ">", -1);
2013da2e3ebdSchin continue;
2014da2e3ebdSchin }
2015da2e3ebdSchin break;
2016da2e3ebdSchin case '&':
2017da2e3ebdSchin if (style == STYLE_html)
2018da2e3ebdSchin {
2019da2e3ebdSchin sfputr(sp, "&", -1);
2020da2e3ebdSchin continue;
2021da2e3ebdSchin }
2022da2e3ebdSchin break;
2023da2e3ebdSchin case '-':
2024da2e3ebdSchin if (style == STYLE_nroff)
2025da2e3ebdSchin sfputc(sp, '\\');
2026da2e3ebdSchin break;
2027da2e3ebdSchin case '.':
2028da2e3ebdSchin if (style == STYLE_nroff)
2029da2e3ebdSchin {
2030da2e3ebdSchin sfputc(sp, '\\');
2031da2e3ebdSchin sfputc(sp, '&');
2032da2e3ebdSchin }
2033da2e3ebdSchin break;
2034da2e3ebdSchin case '\\':
2035da2e3ebdSchin if (style == STYLE_nroff)
2036da2e3ebdSchin {
2037da2e3ebdSchin sfputc(sp, c);
2038da2e3ebdSchin c = 'e';
2039da2e3ebdSchin }
2040da2e3ebdSchin break;
2041da2e3ebdSchin }
2042da2e3ebdSchin sfputc(sp, c);
2043da2e3ebdSchin }
2044da2e3ebdSchin }
2045da2e3ebdSchin else if (c == '[' && level > lev)
2046da2e3ebdSchin {
2047da2e3ebdSchin p++;
2048da2e3ebdSchin goto again;
2049da2e3ebdSchin }
2050da2e3ebdSchin return p;
2051da2e3ebdSchin }
2052da2e3ebdSchin
2053da2e3ebdSchin /*
2054da2e3ebdSchin * generate optget() help [...] list from lp
2055da2e3ebdSchin */
2056da2e3ebdSchin
2057da2e3ebdSchin static void
list(Sfio_t * sp,register const List_t * lp)2058da2e3ebdSchin list(Sfio_t* sp, register const List_t* lp)
2059da2e3ebdSchin {
2060da2e3ebdSchin sfprintf(sp, "[%c", lp->type);
2061da2e3ebdSchin if (lp->name)
2062da2e3ebdSchin {
2063da2e3ebdSchin sfprintf(sp, "%s", lp->name);
2064da2e3ebdSchin if (lp->text)
2065da2e3ebdSchin sfprintf(sp, "?%s", lp->text);
2066da2e3ebdSchin }
2067da2e3ebdSchin sfputc(sp, ']');
2068da2e3ebdSchin }
2069da2e3ebdSchin
2070da2e3ebdSchin /*
2071da2e3ebdSchin * return pointer to help message sans `Usage: command'
2072da2e3ebdSchin * if oopts is 0 then opt_info.state->pass is used
2073da2e3ebdSchin * what:
2074da2e3ebdSchin * 0 ?short by default, ?long if any long options used
2075da2e3ebdSchin * * otherwise see help_text[] (--???)
2076da2e3ebdSchin * external formatter:
2077da2e3ebdSchin * \a...\a italic
2078da2e3ebdSchin * \b...\b bold
2079da2e3ebdSchin * \f...\f discipline infof callback on ...
2080da2e3ebdSchin * \v...\v literal
2081da2e3ebdSchin * internal formatter:
2082da2e3ebdSchin * \t indent
2083da2e3ebdSchin * \n newline
2084da2e3ebdSchin * margin flush pops to previous indent
2085da2e3ebdSchin */
2086da2e3ebdSchin
2087da2e3ebdSchin char*
opthelp(const char * oopts,const char * what)2088da2e3ebdSchin opthelp(const char* oopts, const char* what)
2089da2e3ebdSchin {
2090da2e3ebdSchin register Sfio_t* sp;
2091da2e3ebdSchin register Sfio_t* mp;
2092da2e3ebdSchin register int c;
2093da2e3ebdSchin register char* p;
2094da2e3ebdSchin register Indent_t* ip;
2095da2e3ebdSchin char* t;
2096da2e3ebdSchin char* x;
2097da2e3ebdSchin char* w;
2098da2e3ebdSchin char* u;
2099da2e3ebdSchin char* y;
2100da2e3ebdSchin char* s;
2101da2e3ebdSchin char* d;
2102da2e3ebdSchin char* v;
2103da2e3ebdSchin char* ov;
2104da2e3ebdSchin char* pp;
2105da2e3ebdSchin char* rb;
2106da2e3ebdSchin char* re;
2107da2e3ebdSchin int f;
2108da2e3ebdSchin int i;
2109da2e3ebdSchin int j;
2110da2e3ebdSchin int m;
2111da2e3ebdSchin int n;
2112da2e3ebdSchin int a;
2113da2e3ebdSchin int sl;
2114da2e3ebdSchin int vl;
2115da2e3ebdSchin int ol;
2116da2e3ebdSchin int wl;
2117da2e3ebdSchin int xl;
2118da2e3ebdSchin int rm;
2119da2e3ebdSchin int ts;
2120da2e3ebdSchin int co;
2121da2e3ebdSchin int z;
2122da2e3ebdSchin int style;
2123da2e3ebdSchin int head;
21247c2fbfb3SApril Chin int margin;
2125da2e3ebdSchin int mode;
2126da2e3ebdSchin int mutex;
2127da2e3ebdSchin int prefix;
2128da2e3ebdSchin int version;
2129da2e3ebdSchin long tp;
2130*3e14f97fSRoger A. Faulkner char* id;
2131da2e3ebdSchin char* catalog;
2132da2e3ebdSchin Optpass_t* o;
2133da2e3ebdSchin Optpass_t* q;
2134da2e3ebdSchin Optpass_t* e;
2135da2e3ebdSchin Optpass_t one;
2136da2e3ebdSchin Help_t* hp;
2137da2e3ebdSchin short ptstk[elementsof(indent) + 2];
2138da2e3ebdSchin short* pt;
2139da2e3ebdSchin Sfio_t* vp;
2140da2e3ebdSchin Push_t* tsp;
2141da2e3ebdSchin
2142da2e3ebdSchin char* opts = (char*)oopts;
2143da2e3ebdSchin int flags = 0;
2144da2e3ebdSchin int matched = 0;
2145da2e3ebdSchin int paragraph = 0;
2146da2e3ebdSchin int section = 1;
2147da2e3ebdSchin Push_t* psp = 0;
2148da2e3ebdSchin Sfio_t* sp_help = 0;
2149da2e3ebdSchin Sfio_t* sp_text = 0;
2150da2e3ebdSchin Sfio_t* sp_plus = 0;
2151da2e3ebdSchin Sfio_t* sp_head = 0;
2152da2e3ebdSchin Sfio_t* sp_body = 0;
2153da2e3ebdSchin Sfio_t* sp_info = 0;
2154da2e3ebdSchin Sfio_t* sp_misc = 0;
2155da2e3ebdSchin
2156da2e3ebdSchin if (!(mp = opt_info.state->mp) && !(mp = opt_info.state->mp = sfstropen()))
2157da2e3ebdSchin goto nospace;
2158da2e3ebdSchin if (!what)
2159da2e3ebdSchin style = opt_info.state->style;
2160da2e3ebdSchin else if (!*what)
2161da2e3ebdSchin style = STYLE_options;
2162da2e3ebdSchin else if (*what != '?')
2163da2e3ebdSchin style = STYLE_match;
2164da2e3ebdSchin else if (!*(what + 1))
2165da2e3ebdSchin style = STYLE_man;
2166da2e3ebdSchin else if ((hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), (char*)what + 1)) && hp->style >= 0)
2167da2e3ebdSchin {
2168da2e3ebdSchin style = hp->style;
2169da2e3ebdSchin if (*hp->name != '?')
2170da2e3ebdSchin what = hp->name;
2171da2e3ebdSchin }
2172da2e3ebdSchin else
2173da2e3ebdSchin {
2174da2e3ebdSchin if ((style = opt_info.state->force) < STYLE_man)
2175da2e3ebdSchin style = STYLE_man;
2176da2e3ebdSchin if (!(sp_help = sfstropen()))
2177da2e3ebdSchin goto nospace;
2178da2e3ebdSchin for (i = 0; i < elementsof(help_head); i++)
2179da2e3ebdSchin list(sp_help, &help_head[i]);
2180da2e3ebdSchin for (i = 0; i < elementsof(styles); i++)
2181da2e3ebdSchin sfprintf(sp_help, "[:%s?%s]", styles[i].match, styles[i].text);
2182da2e3ebdSchin for (i = 0; i < elementsof(help_tail); i++)
2183da2e3ebdSchin list(sp_help, &help_tail[i]);
2184da2e3ebdSchin if (!(opts = sfstruse(sp_help)))
2185da2e3ebdSchin goto nospace;
2186da2e3ebdSchin }
2187da2e3ebdSchin again:
2188da2e3ebdSchin if (opts)
2189da2e3ebdSchin {
2190da2e3ebdSchin for (i = 0; i < opt_info.state->npass; i++)
2191da2e3ebdSchin if (opt_info.state->pass[i].oopts == opts)
2192da2e3ebdSchin {
2193da2e3ebdSchin o = &opt_info.state->pass[i];
2194da2e3ebdSchin break;
2195da2e3ebdSchin }
2196da2e3ebdSchin if (i >= opt_info.state->npass)
2197da2e3ebdSchin {
2198da2e3ebdSchin o = &one;
2199da2e3ebdSchin if (init((char*)opts, o))
2200da2e3ebdSchin goto nospace;
2201da2e3ebdSchin }
2202da2e3ebdSchin e = o + 1;
2203da2e3ebdSchin }
2204da2e3ebdSchin else if (opt_info.state->npass > 0)
2205da2e3ebdSchin {
2206da2e3ebdSchin o = opt_info.state->pass;
2207da2e3ebdSchin e = o + opt_info.state->npass;
2208da2e3ebdSchin }
2209da2e3ebdSchin else if (opt_info.state->npass < 0)
2210da2e3ebdSchin {
2211da2e3ebdSchin o = &opt_info.state->cache->pass;
2212da2e3ebdSchin e = o + 1;
2213da2e3ebdSchin }
2214da2e3ebdSchin else
2215da2e3ebdSchin return T(NiL, ID, "[* call optget() before opthelp() *]");
221634f9b3eeSRoland Mainz if (style <= STYLE_usage)
2217da2e3ebdSchin {
2218da2e3ebdSchin if (!(sp_text = sfstropen()) || !(sp_info = sfstropen()))
2219da2e3ebdSchin goto nospace;
2220da2e3ebdSchin if (style >= STYLE_match && style < STYLE_keys && !(sp_body = sfstropen()))
2221da2e3ebdSchin goto nospace;
2222da2e3ebdSchin }
2223da2e3ebdSchin switch (style)
2224da2e3ebdSchin {
2225da2e3ebdSchin case STYLE_api:
2226da2e3ebdSchin case STYLE_html:
2227da2e3ebdSchin case STYLE_nroff:
2228da2e3ebdSchin opt_info.state->emphasis = 0;
2229da2e3ebdSchin break;
2230da2e3ebdSchin case STYLE_usage:
2231da2e3ebdSchin case STYLE_keys:
2232da2e3ebdSchin for (q = o; q < e; q++)
2233da2e3ebdSchin if (!(q->flags & OPT_ignore) && !streq(q->catalog, o->catalog))
2234da2e3ebdSchin o = q;
2235da2e3ebdSchin /*FALLTHROUGH*/
2236da2e3ebdSchin case STYLE_posix:
2237da2e3ebdSchin sfputc(mp, '\f');
2238da2e3ebdSchin break;
2239da2e3ebdSchin default:
2240da2e3ebdSchin if (!opt_info.state->emphasis)
2241da2e3ebdSchin {
2242da2e3ebdSchin if (x = getenv("ERROR_OPTIONS"))
2243da2e3ebdSchin {
2244da2e3ebdSchin if (strmatch(x, "*noemphasi*"))
2245da2e3ebdSchin break;
2246da2e3ebdSchin if (strmatch(x, "*emphasi*"))
2247da2e3ebdSchin {
2248da2e3ebdSchin opt_info.state->emphasis = 1;
2249da2e3ebdSchin break;
2250da2e3ebdSchin }
2251da2e3ebdSchin }
2252da2e3ebdSchin if ((x = getenv("TERM")) && strmatch(x, "(ansi|vt100|xterm)*") && isatty(sffileno(sfstderr)))
2253da2e3ebdSchin opt_info.state->emphasis = 1;
2254da2e3ebdSchin }
2255da2e3ebdSchin break;
2256da2e3ebdSchin }
2257da2e3ebdSchin x = "";
2258da2e3ebdSchin xl = 0;
2259da2e3ebdSchin for (q = o; q < e; q++)
2260da2e3ebdSchin {
2261da2e3ebdSchin if (q->flags & OPT_ignore)
2262da2e3ebdSchin continue;
2263da2e3ebdSchin if (section < q->section)
2264da2e3ebdSchin section = q->section;
2265da2e3ebdSchin section = q->section;
2266da2e3ebdSchin flags |= q->flags;
2267da2e3ebdSchin p = q->opts;
2268da2e3ebdSchin prefix = q->prefix;
2269da2e3ebdSchin version = q->version;
2270*3e14f97fSRoger A. Faulkner id = q->id;
2271da2e3ebdSchin catalog = q->catalog;
2272da2e3ebdSchin switch (style)
2273da2e3ebdSchin {
2274da2e3ebdSchin case STYLE_usage:
2275da2e3ebdSchin if (xl)
2276da2e3ebdSchin sfputc(mp, '\n');
2277da2e3ebdSchin else
2278da2e3ebdSchin xl = 1;
227934f9b3eeSRoland Mainz psp = 0;
228034f9b3eeSRoland Mainz for (;;)
2281da2e3ebdSchin {
228234f9b3eeSRoland Mainz switch (c = *p++)
2283da2e3ebdSchin {
228434f9b3eeSRoland Mainz case 0:
228534f9b3eeSRoland Mainz if (!(tsp = psp))
228634f9b3eeSRoland Mainz goto style_usage;
228734f9b3eeSRoland Mainz p = psp->ob;
228834f9b3eeSRoland Mainz psp = psp->next;
228934f9b3eeSRoland Mainz free(tsp);
229034f9b3eeSRoland Mainz continue;
2291da2e3ebdSchin case '\a':
2292da2e3ebdSchin c = 'a';
2293da2e3ebdSchin break;
2294da2e3ebdSchin case '\b':
2295da2e3ebdSchin c = 'b';
2296da2e3ebdSchin break;
2297da2e3ebdSchin case '\f':
2298*3e14f97fSRoger A. Faulkner psp = info(psp, p, NiL, sp_info, id);
229934f9b3eeSRoland Mainz if (psp->nb)
230034f9b3eeSRoland Mainz p = psp->nb;
230134f9b3eeSRoland Mainz else
230234f9b3eeSRoland Mainz {
230334f9b3eeSRoland Mainz p = psp->ob;
230434f9b3eeSRoland Mainz psp = psp->next;
230534f9b3eeSRoland Mainz }
230634f9b3eeSRoland Mainz continue;
2307da2e3ebdSchin case '\n':
2308da2e3ebdSchin c = 'n';
2309da2e3ebdSchin break;
2310da2e3ebdSchin case '\r':
2311da2e3ebdSchin c = 'r';
2312da2e3ebdSchin break;
2313da2e3ebdSchin case '\t':
2314da2e3ebdSchin c = 't';
2315da2e3ebdSchin break;
2316da2e3ebdSchin case '\v':
2317da2e3ebdSchin c = 'v';
2318da2e3ebdSchin break;
2319da2e3ebdSchin case '"':
2320da2e3ebdSchin c = '"';
2321da2e3ebdSchin break;
2322da2e3ebdSchin case '\'':
2323da2e3ebdSchin c = '\'';
2324da2e3ebdSchin break;
2325da2e3ebdSchin case '\\':
2326da2e3ebdSchin c = '\\';
2327da2e3ebdSchin break;
2328da2e3ebdSchin default:
2329da2e3ebdSchin sfputc(mp, c);
2330da2e3ebdSchin continue;
2331da2e3ebdSchin }
2332da2e3ebdSchin sfputc(mp, '\\');
2333da2e3ebdSchin sfputc(mp, c);
2334da2e3ebdSchin }
233534f9b3eeSRoland Mainz style_usage:
2336da2e3ebdSchin continue;
2337da2e3ebdSchin case STYLE_keys:
2338da2e3ebdSchin a = 0;
2339da2e3ebdSchin psp = 0;
2340da2e3ebdSchin vl = 0;
2341da2e3ebdSchin for (;;)
2342da2e3ebdSchin {
2343da2e3ebdSchin if (!(c = *p++))
2344da2e3ebdSchin {
2345da2e3ebdSchin if (!(tsp = psp))
2346da2e3ebdSchin break;
2347da2e3ebdSchin p = psp->ob;
2348da2e3ebdSchin psp = psp->next;
2349da2e3ebdSchin free(tsp);
2350da2e3ebdSchin continue;
2351da2e3ebdSchin }
2352da2e3ebdSchin if (c == '\f')
2353da2e3ebdSchin {
2354*3e14f97fSRoger A. Faulkner psp = info(psp, p, NiL, sp_info, id);
2355da2e3ebdSchin if (psp->nb)
2356da2e3ebdSchin p = psp->nb;
2357da2e3ebdSchin else
2358da2e3ebdSchin {
2359da2e3ebdSchin p = psp->ob;
2360da2e3ebdSchin psp = psp->next;
2361da2e3ebdSchin }
2362da2e3ebdSchin continue;
2363da2e3ebdSchin }
2364da2e3ebdSchin f = z = 1;
2365da2e3ebdSchin t = 0;
2366da2e3ebdSchin if (a == 0 && (c == ' ' || c == '\n' && *p == '\n'))
2367da2e3ebdSchin {
2368da2e3ebdSchin if (c == ' ' && *p == ']')
2369da2e3ebdSchin {
2370da2e3ebdSchin p++;
2371da2e3ebdSchin continue;
2372da2e3ebdSchin }
2373da2e3ebdSchin if (*p == '\n')
2374da2e3ebdSchin p++;
2375da2e3ebdSchin a = c;
2376da2e3ebdSchin }
2377da2e3ebdSchin else if (c == '\n')
2378da2e3ebdSchin {
2379da2e3ebdSchin if (a == ' ')
2380da2e3ebdSchin a = -1;
2381da2e3ebdSchin else if (a == '\n' || *p == '\n')
2382da2e3ebdSchin {
2383da2e3ebdSchin a = -1;
2384da2e3ebdSchin p++;
2385da2e3ebdSchin }
2386da2e3ebdSchin continue;
2387da2e3ebdSchin }
2388da2e3ebdSchin else if ((c == ':' || c == '#') && (*p == '[' || *p == '?' && *(p + 1) == '[' && p++))
2389da2e3ebdSchin p++;
2390da2e3ebdSchin else if (c != '[')
2391da2e3ebdSchin {
23927c2fbfb3SApril Chin if (c == GO)
2393da2e3ebdSchin vl++;
23947c2fbfb3SApril Chin else if (c == OG)
2395da2e3ebdSchin vl--;
2396da2e3ebdSchin continue;
2397da2e3ebdSchin }
2398da2e3ebdSchin else if (*p == ' ')
2399da2e3ebdSchin {
2400da2e3ebdSchin p++;
2401da2e3ebdSchin continue;
2402da2e3ebdSchin }
2403da2e3ebdSchin else if (*p == '-')
2404da2e3ebdSchin {
2405da2e3ebdSchin z = 0;
2406da2e3ebdSchin if (*++p == '-')
2407da2e3ebdSchin {
2408da2e3ebdSchin p = skip(p, 0, 0, 0, 1, 0, 1, version);
2409da2e3ebdSchin continue;
2410da2e3ebdSchin }
2411da2e3ebdSchin }
2412da2e3ebdSchin else if (*p == '+')
2413da2e3ebdSchin {
2414da2e3ebdSchin p++;
2415da2e3ebdSchin if (vl > 0 && *p != '\a')
2416da2e3ebdSchin {
2417da2e3ebdSchin f = 0;
2418da2e3ebdSchin p = skip(p, '?', 0, 0, 1, 0, 0, version);
2419da2e3ebdSchin if (*p == '?')
2420da2e3ebdSchin p++;
2421da2e3ebdSchin }
2422da2e3ebdSchin }
2423da2e3ebdSchin else
2424da2e3ebdSchin {
2425da2e3ebdSchin if (*(p + 1) == '\f' && (vp = opt_info.state->vp))
2426*3e14f97fSRoger A. Faulkner p = expand(p + 2, NiL, &t, vp, id);
2427da2e3ebdSchin p = skip(p, ':', '?', 0, 1, 0, 0, version);
2428da2e3ebdSchin if (*p == ':')
2429da2e3ebdSchin p++;
2430da2e3ebdSchin }
2431da2e3ebdSchin if (f && *p == '?' && *(p + 1) != '?')
2432da2e3ebdSchin {
2433da2e3ebdSchin f = 0;
2434da2e3ebdSchin if (z)
2435da2e3ebdSchin p++;
2436da2e3ebdSchin else
2437da2e3ebdSchin p = skip(p, 0, 0, 0, 1, 0, 0, version);
2438da2e3ebdSchin }
2439da2e3ebdSchin if (*p == ']' && *(p + 1) != ']')
2440da2e3ebdSchin {
2441da2e3ebdSchin p++;
2442da2e3ebdSchin continue;
2443da2e3ebdSchin }
2444da2e3ebdSchin if (!*p)
2445da2e3ebdSchin {
2446da2e3ebdSchin if (!t)
2447da2e3ebdSchin break;
2448da2e3ebdSchin p = t;
2449da2e3ebdSchin t = 0;
2450da2e3ebdSchin }
2451da2e3ebdSchin m = sfstrtell(mp);
2452da2e3ebdSchin sfputc(mp, '"');
2453da2e3ebdSchin xl = 1;
2454da2e3ebdSchin /*UNDENT...*/
2455da2e3ebdSchin
2456da2e3ebdSchin for (;;)
2457da2e3ebdSchin {
2458da2e3ebdSchin if (!(c = *p++))
2459da2e3ebdSchin {
2460da2e3ebdSchin if (t)
2461da2e3ebdSchin {
2462da2e3ebdSchin p = t;
2463da2e3ebdSchin t = 0;
2464da2e3ebdSchin }
2465da2e3ebdSchin if (!(tsp = psp))
2466da2e3ebdSchin {
2467da2e3ebdSchin p--;
2468da2e3ebdSchin break;
2469da2e3ebdSchin }
2470da2e3ebdSchin p = psp->ob;
2471da2e3ebdSchin psp = psp->next;
2472da2e3ebdSchin free(tsp);
2473da2e3ebdSchin continue;
2474da2e3ebdSchin }
2475da2e3ebdSchin if (a > 0)
2476da2e3ebdSchin {
2477da2e3ebdSchin if (c == '\n')
2478da2e3ebdSchin {
2479da2e3ebdSchin if (a == ' ')
2480da2e3ebdSchin {
2481da2e3ebdSchin a = -1;
2482da2e3ebdSchin break;
2483da2e3ebdSchin }
2484da2e3ebdSchin if (a == '\n' || *p == '\n')
2485da2e3ebdSchin {
2486da2e3ebdSchin a = -1;
2487da2e3ebdSchin p++;
2488da2e3ebdSchin break;
2489da2e3ebdSchin }
2490da2e3ebdSchin }
2491da2e3ebdSchin }
2492da2e3ebdSchin else if (c == ']')
2493da2e3ebdSchin {
2494da2e3ebdSchin if (*p != ']')
2495da2e3ebdSchin {
2496da2e3ebdSchin sfputc(mp, 0);
2497da2e3ebdSchin y = sfstrbase(mp) + m + 1;
2498da2e3ebdSchin if (D(y) || !strmatch(y, KEEP) || strmatch(y, OMIT))
2499da2e3ebdSchin {
2500da2e3ebdSchin sfstrseek(mp, m, SEEK_SET);
2501da2e3ebdSchin xl = 0;
2502da2e3ebdSchin }
2503da2e3ebdSchin else
2504da2e3ebdSchin sfstrseek(mp, -1, SEEK_CUR);
2505da2e3ebdSchin break;
2506da2e3ebdSchin }
2507da2e3ebdSchin sfputc(mp, *p++);
2508da2e3ebdSchin continue;
2509da2e3ebdSchin }
2510da2e3ebdSchin switch (c)
2511da2e3ebdSchin {
2512da2e3ebdSchin case '?':
2513da2e3ebdSchin if (f)
2514da2e3ebdSchin {
2515da2e3ebdSchin if (*p == '?')
2516da2e3ebdSchin {
2517da2e3ebdSchin p++;
2518da2e3ebdSchin sfputc(mp, c);
2519da2e3ebdSchin }
2520da2e3ebdSchin else
2521da2e3ebdSchin {
2522da2e3ebdSchin f = 0;
2523da2e3ebdSchin sfputc(mp, 0);
2524da2e3ebdSchin y = sfstrbase(mp) + m + 1;
2525da2e3ebdSchin if (D(y) || !strmatch(y, KEEP) || strmatch(y, OMIT))
2526da2e3ebdSchin {
2527da2e3ebdSchin sfstrseek(mp, m, SEEK_SET);
2528da2e3ebdSchin xl = 0;
2529da2e3ebdSchin }
2530da2e3ebdSchin else
2531da2e3ebdSchin sfstrseek(mp, -1, SEEK_CUR);
2532da2e3ebdSchin if (z && (*p != ']' || *(p + 1) == ']'))
2533da2e3ebdSchin {
2534da2e3ebdSchin if (xl)
2535da2e3ebdSchin {
2536da2e3ebdSchin sfputc(mp, '"');
2537da2e3ebdSchin sfputc(mp, '\n');
2538da2e3ebdSchin }
2539da2e3ebdSchin m = sfstrtell(mp);
2540da2e3ebdSchin sfputc(mp, '"');
2541da2e3ebdSchin xl = 1;
2542da2e3ebdSchin }
2543da2e3ebdSchin else
2544da2e3ebdSchin {
2545da2e3ebdSchin p = skip(p, 0, 0, 0, 1, 0, 0, version);
2546da2e3ebdSchin if (*p == '?')
2547da2e3ebdSchin p++;
2548da2e3ebdSchin }
2549da2e3ebdSchin }
2550da2e3ebdSchin }
2551da2e3ebdSchin else
2552da2e3ebdSchin sfputc(mp, c);
2553da2e3ebdSchin continue;
2554da2e3ebdSchin case ':':
2555da2e3ebdSchin if (f && *p == ':')
2556da2e3ebdSchin p++;
2557da2e3ebdSchin sfputc(mp, c);
2558da2e3ebdSchin continue;
2559da2e3ebdSchin case '\a':
2560da2e3ebdSchin c = 'a';
2561da2e3ebdSchin break;
2562da2e3ebdSchin case '\b':
2563da2e3ebdSchin c = 'b';
2564da2e3ebdSchin break;
2565da2e3ebdSchin case '\f':
2566da2e3ebdSchin c = 'f';
2567da2e3ebdSchin break;
2568da2e3ebdSchin case '\n':
2569da2e3ebdSchin c = 'n';
2570da2e3ebdSchin break;
2571da2e3ebdSchin case '\r':
2572da2e3ebdSchin c = 'r';
2573da2e3ebdSchin break;
2574da2e3ebdSchin case '\t':
2575da2e3ebdSchin c = 't';
2576da2e3ebdSchin break;
2577da2e3ebdSchin case '\v':
2578da2e3ebdSchin c = 'v';
2579da2e3ebdSchin break;
2580da2e3ebdSchin case '"':
2581da2e3ebdSchin c = '"';
2582da2e3ebdSchin break;
2583da2e3ebdSchin case '\\':
2584da2e3ebdSchin c = '\\';
2585da2e3ebdSchin break;
2586da2e3ebdSchin case CC_esc:
2587da2e3ebdSchin c = 'E';
2588da2e3ebdSchin break;
2589da2e3ebdSchin default:
2590da2e3ebdSchin sfputc(mp, c);
2591da2e3ebdSchin continue;
2592da2e3ebdSchin }
2593da2e3ebdSchin sfputc(mp, '\\');
2594da2e3ebdSchin sfputc(mp, c);
2595da2e3ebdSchin }
2596da2e3ebdSchin
2597da2e3ebdSchin /*...INDENT*/
2598da2e3ebdSchin if (xl)
2599da2e3ebdSchin {
2600da2e3ebdSchin sfputc(mp, '"');
2601da2e3ebdSchin sfputc(mp, '\n');
2602da2e3ebdSchin }
2603da2e3ebdSchin }
2604da2e3ebdSchin continue;
2605da2e3ebdSchin }
2606da2e3ebdSchin z = 0;
2607da2e3ebdSchin head = 0;
2608da2e3ebdSchin mode = 0;
2609da2e3ebdSchin mutex = 0;
2610da2e3ebdSchin if (style > STYLE_short && style < STYLE_nroff && version < 1)
2611da2e3ebdSchin {
2612da2e3ebdSchin style = STYLE_short;
2613da2e3ebdSchin if (sp_body)
2614da2e3ebdSchin {
2615da2e3ebdSchin sfclose(sp_body);
2616da2e3ebdSchin sp_body = 0;
2617da2e3ebdSchin }
2618da2e3ebdSchin }
2619da2e3ebdSchin else if (style == STYLE_short && prefix < 2)
2620da2e3ebdSchin style = STYLE_long;
2621da2e3ebdSchin if (*p == ':')
2622da2e3ebdSchin p++;
2623da2e3ebdSchin if (*p == '+')
2624da2e3ebdSchin {
2625da2e3ebdSchin p++;
2626da2e3ebdSchin if (!(sp = sp_plus) && !(sp = sp_plus = sfstropen()))
2627da2e3ebdSchin goto nospace;
2628da2e3ebdSchin }
2629da2e3ebdSchin else if (style >= STYLE_match)
2630da2e3ebdSchin sp = sp_body;
2631da2e3ebdSchin else
2632da2e3ebdSchin sp = sp_text;
2633da2e3ebdSchin psp = 0;
2634da2e3ebdSchin for (;;)
2635da2e3ebdSchin {
2636da2e3ebdSchin if (!(*(p = next(p, version))))
2637da2e3ebdSchin {
2638da2e3ebdSchin if (!(tsp = psp))
2639da2e3ebdSchin break;
2640da2e3ebdSchin p = psp->ob;
2641da2e3ebdSchin psp = psp->next;
2642da2e3ebdSchin free(tsp);
2643da2e3ebdSchin continue;
2644da2e3ebdSchin }
2645da2e3ebdSchin if (*p == '\f')
2646da2e3ebdSchin {
2647*3e14f97fSRoger A. Faulkner psp = info(psp, p + 1, NiL, sp_info, id);
2648da2e3ebdSchin if (psp->nb)
2649da2e3ebdSchin p = psp->nb;
2650da2e3ebdSchin else
2651da2e3ebdSchin {
2652da2e3ebdSchin p = psp->ob;
2653da2e3ebdSchin psp = psp->next;
2654da2e3ebdSchin }
2655da2e3ebdSchin continue;
2656da2e3ebdSchin }
2657da2e3ebdSchin if (*p == '\n' || *p == ' ')
2658da2e3ebdSchin {
2659da2e3ebdSchin if (*(x = p = next(p + 1, version)))
2660da2e3ebdSchin while (*++p)
2661da2e3ebdSchin if (*p == '\n')
2662da2e3ebdSchin {
2663da2e3ebdSchin while (*++p == ' ' || *p == '\t' || *p == '\r');
2664da2e3ebdSchin if (*p == '\n')
2665da2e3ebdSchin break;
2666da2e3ebdSchin }
2667da2e3ebdSchin xl = p - x;
2668da2e3ebdSchin if (!*p)
2669da2e3ebdSchin break;
2670da2e3ebdSchin continue;
2671da2e3ebdSchin }
26727c2fbfb3SApril Chin if (*p == OG)
2673da2e3ebdSchin {
2674da2e3ebdSchin p++;
2675da2e3ebdSchin continue;
2676da2e3ebdSchin }
2677da2e3ebdSchin message((-20, "opthelp: opt %s", show(p)));
2678da2e3ebdSchin if (z < 0)
2679da2e3ebdSchin z = 0;
2680da2e3ebdSchin a = 0;
2681da2e3ebdSchin f = 0;
2682da2e3ebdSchin w = 0;
2683da2e3ebdSchin d = 0;
2684da2e3ebdSchin s = 0;
26857c2fbfb3SApril Chin rb = re = 0;
2686da2e3ebdSchin sl = 0;
26877c2fbfb3SApril Chin vl = 0;
2688da2e3ebdSchin if (*p == '[')
2689da2e3ebdSchin {
2690da2e3ebdSchin if ((c = *(p = next(p + 1, version))) == '-')
2691da2e3ebdSchin {
2692da2e3ebdSchin if (style >= STYLE_man)
2693da2e3ebdSchin {
2694da2e3ebdSchin if (*(p + 1) != '-')
2695da2e3ebdSchin {
2696da2e3ebdSchin if (!sp_misc && !(sp_misc = sfstropen()))
2697da2e3ebdSchin goto nospace;
2698da2e3ebdSchin else
2699*3e14f97fSRoger A. Faulkner p = textout(sp_misc, p, style, 1, 3, sp_info, version, id, catalog);
2700da2e3ebdSchin continue;
2701da2e3ebdSchin }
2702da2e3ebdSchin }
2703da2e3ebdSchin else if (style == STYLE_match && *what == '-')
2704da2e3ebdSchin {
27057c2fbfb3SApril Chin if (*(p + 1) == '?' || isdigit(*(p + 1)))
2706da2e3ebdSchin s = C("version");
2707da2e3ebdSchin else
2708da2e3ebdSchin s = p + 1;
2709da2e3ebdSchin w = (char*)what;
2710da2e3ebdSchin if (*s != '-' || *(w + 1) == '-')
2711da2e3ebdSchin {
2712da2e3ebdSchin if (*s == '-')
2713da2e3ebdSchin s++;
2714da2e3ebdSchin if (*(w + 1) == '-')
2715da2e3ebdSchin w++;
2716*3e14f97fSRoger A. Faulkner if (match(w + 1, s, version, id, catalog))
2717da2e3ebdSchin {
2718da2e3ebdSchin if (*(p + 1) == '-')
2719da2e3ebdSchin p++;
2720*3e14f97fSRoger A. Faulkner p = textout(sp, p, style, 1, 3, sp_info, version, id, catalog);
2721da2e3ebdSchin matched = -1;
2722da2e3ebdSchin continue;
2723da2e3ebdSchin }
2724da2e3ebdSchin }
2725da2e3ebdSchin }
2726da2e3ebdSchin if (!z)
2727da2e3ebdSchin z = -1;
2728da2e3ebdSchin }
2729da2e3ebdSchin else if (c == '+')
2730da2e3ebdSchin {
2731da2e3ebdSchin if (style >= STYLE_man)
2732da2e3ebdSchin {
2733*3e14f97fSRoger A. Faulkner p = textout(sp_body, p, style, 0, 0, sp_info, version, id, catalog);
2734da2e3ebdSchin if (!sp_head)
2735da2e3ebdSchin {
2736da2e3ebdSchin sp_head = sp_body;
2737da2e3ebdSchin if (!(sp_body = sfstropen()))
2738da2e3ebdSchin goto nospace;
2739da2e3ebdSchin }
2740da2e3ebdSchin continue;
2741da2e3ebdSchin }
2742da2e3ebdSchin else if (style == STYLE_match && *what == '+')
2743da2e3ebdSchin {
2744da2e3ebdSchin if (paragraph)
2745da2e3ebdSchin {
2746da2e3ebdSchin if (p[1] == '?')
2747da2e3ebdSchin {
2748*3e14f97fSRoger A. Faulkner p = textout(sp, p, style, 1, 3, sp_info, version, id, catalog);
2749da2e3ebdSchin continue;
2750da2e3ebdSchin }
2751da2e3ebdSchin paragraph = 0;
2752da2e3ebdSchin }
2753*3e14f97fSRoger A. Faulkner if (match((char*)what + 1, p + 1, version, id, catalog))
2754da2e3ebdSchin {
2755*3e14f97fSRoger A. Faulkner p = textout(sp, p, style, 1, 3, sp_info, version, id, catalog);
2756da2e3ebdSchin matched = -1;
2757da2e3ebdSchin paragraph = 1;
2758da2e3ebdSchin continue;
2759da2e3ebdSchin }
2760da2e3ebdSchin }
2761da2e3ebdSchin if (!z)
2762da2e3ebdSchin z = -1;
2763da2e3ebdSchin }
2764da2e3ebdSchin else if (c == '[' || version < 1)
2765da2e3ebdSchin {
2766da2e3ebdSchin mutex++;
2767da2e3ebdSchin continue;
2768da2e3ebdSchin }
2769da2e3ebdSchin else
2770da2e3ebdSchin {
2771da2e3ebdSchin if (c == '!')
2772da2e3ebdSchin {
2773da2e3ebdSchin a |= OPT_invert;
2774da2e3ebdSchin p++;
2775da2e3ebdSchin }
2776da2e3ebdSchin rb = p;
2777da2e3ebdSchin if (*p != ':')
2778da2e3ebdSchin {
2779da2e3ebdSchin s = p;
2780da2e3ebdSchin if (*(p + 1) == '|')
2781da2e3ebdSchin {
2782da2e3ebdSchin while (*++p && *p != '=' && *p != '!' && *p != ':' && *p != '?');
2783da2e3ebdSchin if ((p - s) > 1)
2784da2e3ebdSchin sl = p - s;
2785da2e3ebdSchin if (*p == '!')
2786da2e3ebdSchin a |= OPT_invert;
2787da2e3ebdSchin }
2788da2e3ebdSchin if (*(p + 1) == '\f')
2789da2e3ebdSchin p++;
2790da2e3ebdSchin else
2791da2e3ebdSchin p = skip(p, ':', '?', 0, 1, 0, 0, version);
2792da2e3ebdSchin if (sl || (p - s) == 1 || *(s + 1) == '=' || *(s + 1) == '!' && (a |= OPT_invert) || *(s + 1) == '|')
2793da2e3ebdSchin f = *s;
2794da2e3ebdSchin }
2795da2e3ebdSchin re = p;
2796da2e3ebdSchin if (style <= STYLE_short)
2797da2e3ebdSchin {
2798da2e3ebdSchin if (!z && !f)
2799da2e3ebdSchin z = -1;
2800da2e3ebdSchin }
2801da2e3ebdSchin else
2802da2e3ebdSchin {
2803da2e3ebdSchin if (*p == '\f' && (vp = opt_info.state->vp))
2804*3e14f97fSRoger A. Faulkner p = expand(p + 1, NiL, &t, vp, id);
2805da2e3ebdSchin else
2806da2e3ebdSchin t = 0;
2807da2e3ebdSchin if (*p == ':')
2808da2e3ebdSchin {
2809da2e3ebdSchin p = skip(w = p + 1, ':', '?', 0, 1, 0, 0, version);
2810da2e3ebdSchin if (!(wl = p - w))
2811da2e3ebdSchin w = 0;
2812da2e3ebdSchin }
2813da2e3ebdSchin else
2814da2e3ebdSchin wl = 0;
2815da2e3ebdSchin if (*p == ':' || *p == '?')
2816da2e3ebdSchin {
2817da2e3ebdSchin d = p;
2818da2e3ebdSchin p = skip(p, 0, 0, 0, 1, 0, 0, version);
2819da2e3ebdSchin }
2820da2e3ebdSchin else
2821da2e3ebdSchin d = 0;
2822da2e3ebdSchin if (style == STYLE_match)
2823da2e3ebdSchin {
2824*3e14f97fSRoger A. Faulkner if (wl && !match((char*)what, w, version, id, catalog))
2825da2e3ebdSchin wl = 0;
2826da2e3ebdSchin if ((!wl || *w == ':' || *w == '?') && (what[1] || sl && !memchr(s, what[0], sl) || !sl && what[0] != f))
2827da2e3ebdSchin {
2828da2e3ebdSchin w = 0;
2829da2e3ebdSchin if (!z)
2830da2e3ebdSchin z = -1;
2831da2e3ebdSchin }
2832da2e3ebdSchin else
2833da2e3ebdSchin matched = 1;
2834da2e3ebdSchin }
2835da2e3ebdSchin if (t)
2836da2e3ebdSchin {
2837da2e3ebdSchin p = t;
2838da2e3ebdSchin if (*p == ':' || *p == '?')
2839da2e3ebdSchin {
2840da2e3ebdSchin d = p;
2841da2e3ebdSchin p = skip(p, 0, 0, 0, 1, 0, 0, version);
2842da2e3ebdSchin }
2843da2e3ebdSchin }
2844da2e3ebdSchin }
2845da2e3ebdSchin }
2846da2e3ebdSchin p = skip(p, 0, 0, 0, 1, 0, 1, version);
2847da2e3ebdSchin if (*p == GO)
2848da2e3ebdSchin p = skip(p + 1, 0, 0, 0, 0, 1, 1, version);
2849da2e3ebdSchin }
2850da2e3ebdSchin else if (*p == ']')
2851da2e3ebdSchin {
2852da2e3ebdSchin if (mutex)
2853da2e3ebdSchin {
2854da2e3ebdSchin if (style >= STYLE_nroff)
2855da2e3ebdSchin sfputr(sp_body, "\n.OP - - anyof", '\n');
2856da2e3ebdSchin if (!(mutex & 1))
2857da2e3ebdSchin {
2858da2e3ebdSchin mutex--;
2859da2e3ebdSchin if (style <= STYLE_long)
2860da2e3ebdSchin {
2861da2e3ebdSchin sfputc(sp_body, ' ');
2862da2e3ebdSchin sfputc(sp_body, ']');
2863da2e3ebdSchin }
2864da2e3ebdSchin }
2865da2e3ebdSchin mutex--;
2866da2e3ebdSchin }
2867da2e3ebdSchin p++;
2868da2e3ebdSchin continue;
2869da2e3ebdSchin }
2870da2e3ebdSchin else if (*p == '?')
2871da2e3ebdSchin {
2872da2e3ebdSchin if (style < STYLE_match)
2873da2e3ebdSchin z = 1;
2874da2e3ebdSchin mode |= OPT_hidden;
2875da2e3ebdSchin p++;
2876da2e3ebdSchin continue;
2877da2e3ebdSchin }
2878da2e3ebdSchin else if (*p == '\\' && style==STYLE_posix)
2879da2e3ebdSchin {
2880da2e3ebdSchin if (*++p)
2881da2e3ebdSchin p++;
2882da2e3ebdSchin continue;
2883da2e3ebdSchin }
2884da2e3ebdSchin else
2885da2e3ebdSchin {
2886da2e3ebdSchin f = *p++;
2887da2e3ebdSchin s = 0;
2888da2e3ebdSchin if (style == STYLE_match && !z)
2889da2e3ebdSchin z = -1;
2890da2e3ebdSchin }
2891da2e3ebdSchin if (!z)
2892da2e3ebdSchin {
2893da2e3ebdSchin if (style == STYLE_long || prefix < 2 || (q->flags & OPT_long))
2894da2e3ebdSchin f = 0;
2895da2e3ebdSchin else if (style <= STYLE_short)
2896da2e3ebdSchin w = 0;
2897da2e3ebdSchin if (!f && !w)
2898da2e3ebdSchin z = -1;
2899da2e3ebdSchin }
29007c2fbfb3SApril Chin ov = 0;
29017c2fbfb3SApril Chin u = v = y = 0;
2902da2e3ebdSchin if (*p == ':' && (a |= OPT_string) || *p == '#' && (a |= OPT_number))
2903da2e3ebdSchin {
2904da2e3ebdSchin message((-21, "opthelp: arg %s", show(p)));
2905da2e3ebdSchin if (*++p == '?' || *p == *(p - 1))
2906da2e3ebdSchin {
2907da2e3ebdSchin p++;
2908da2e3ebdSchin a |= OPT_optional;
2909da2e3ebdSchin }
2910da2e3ebdSchin if (*(p = next(p, version)) == '[')
2911da2e3ebdSchin {
2912da2e3ebdSchin if (!z)
2913da2e3ebdSchin {
2914da2e3ebdSchin p = skip(y = p + 1, ':', '?', 0, 1, 0, 0, version);
2915da2e3ebdSchin while (*p == ':')
2916da2e3ebdSchin {
2917da2e3ebdSchin p = skip(t = p + 1, ':', '?', 0, 1, 0, 0, version);
2918da2e3ebdSchin m = p - t;
2919da2e3ebdSchin if (*t == '!')
2920da2e3ebdSchin {
2921da2e3ebdSchin ov = t + 1;
2922da2e3ebdSchin ol = m - 1;
2923da2e3ebdSchin }
2924da2e3ebdSchin else if (*t == '=')
2925da2e3ebdSchin {
2926da2e3ebdSchin v = t + 1;
2927da2e3ebdSchin vl = m - 1;
2928da2e3ebdSchin }
2929da2e3ebdSchin else
2930da2e3ebdSchin for (j = 0; j < elementsof(attrs); j++)
2931da2e3ebdSchin if (strneq(t, attrs[j].name, m))
2932da2e3ebdSchin {
2933da2e3ebdSchin a |= attrs[j].flag;
2934da2e3ebdSchin break;
2935da2e3ebdSchin }
2936da2e3ebdSchin }
2937da2e3ebdSchin if (*p == '?')
2938da2e3ebdSchin u = p;
2939da2e3ebdSchin p = skip(p, 0, 0, 0, 1, 0, 1, version);
2940da2e3ebdSchin }
2941da2e3ebdSchin else
2942da2e3ebdSchin p = skip(p + 1, 0, 0, 0, 1, 0, 1, version);
2943da2e3ebdSchin }
2944da2e3ebdSchin else
2945da2e3ebdSchin y = (a & OPT_number) ? T(NiL, ID, "#") : T(NiL, ID, "arg");
2946da2e3ebdSchin }
2947da2e3ebdSchin else
2948da2e3ebdSchin a |= OPT_flag;
2949da2e3ebdSchin if (!z)
2950da2e3ebdSchin {
2951da2e3ebdSchin if (style <= STYLE_short && !y && !mutex || style == STYLE_posix)
2952da2e3ebdSchin {
2953da2e3ebdSchin if (style != STYLE_posix && !sfstrtell(sp))
2954da2e3ebdSchin {
2955da2e3ebdSchin sfputc(sp, '[');
2956da2e3ebdSchin if (sp == sp_plus)
2957da2e3ebdSchin sfputc(sp, '+');
2958da2e3ebdSchin sfputc(sp, '-');
2959da2e3ebdSchin }
2960da2e3ebdSchin if (!sl)
2961da2e3ebdSchin sfputc(sp, f);
2962da2e3ebdSchin else
2963da2e3ebdSchin for (c = 0; c < sl; c++)
2964da2e3ebdSchin if (s[c] != '|')
2965da2e3ebdSchin sfputc(sp, s[c]);
2966da2e3ebdSchin if (style == STYLE_posix && y)
2967da2e3ebdSchin sfputc(sp, ':');
2968da2e3ebdSchin }
2969da2e3ebdSchin else
2970da2e3ebdSchin {
2971da2e3ebdSchin if (style >= STYLE_match)
2972da2e3ebdSchin {
2973da2e3ebdSchin sfputc(sp_body, '\n');
2974da2e3ebdSchin if (!head)
2975da2e3ebdSchin {
2976da2e3ebdSchin head = 1;
2977*3e14f97fSRoger A. Faulkner item(sp_body, (flags & OPT_functions) ? C("FUNCTIONS") : C("OPTIONS"), 0, 0, style, sp_info, version, id, ID);
2978da2e3ebdSchin }
2979da2e3ebdSchin if (style >= STYLE_nroff)
2980da2e3ebdSchin {
2981da2e3ebdSchin if (mutex & 1)
2982da2e3ebdSchin {
2983da2e3ebdSchin mutex++;
2984da2e3ebdSchin sfputr(sp_body, "\n.OP - - oneof", '\n');
2985da2e3ebdSchin }
2986da2e3ebdSchin }
2987da2e3ebdSchin else
2988da2e3ebdSchin sfputc(sp_body, '\t');
2989da2e3ebdSchin }
2990da2e3ebdSchin else
2991da2e3ebdSchin {
2992da2e3ebdSchin if (sp_body)
2993da2e3ebdSchin sfputc(sp_body, ' ');
2994da2e3ebdSchin else if (!(sp_body = sfstropen()))
2995da2e3ebdSchin goto nospace;
2996da2e3ebdSchin if (mutex)
2997da2e3ebdSchin {
2998da2e3ebdSchin if (mutex & 1)
2999da2e3ebdSchin {
3000da2e3ebdSchin mutex++;
3001da2e3ebdSchin sfputc(sp_body, '[');
3002da2e3ebdSchin }
3003da2e3ebdSchin else
3004da2e3ebdSchin sfputc(sp_body, '|');
3005da2e3ebdSchin sfputc(sp_body, ' ');
3006da2e3ebdSchin }
3007da2e3ebdSchin else
3008da2e3ebdSchin sfputc(sp_body, '[');
3009da2e3ebdSchin }
3010da2e3ebdSchin if (style >= STYLE_nroff)
3011da2e3ebdSchin {
3012da2e3ebdSchin if (flags & OPT_functions)
3013da2e3ebdSchin {
3014da2e3ebdSchin sfputr(sp_body, ".FN", ' ');
3015da2e3ebdSchin if (re > rb)
3016da2e3ebdSchin sfwrite(sp_body, rb, re - rb);
3017da2e3ebdSchin else
3018da2e3ebdSchin sfputr(sp, "void", -1);
3019da2e3ebdSchin if (w)
3020*3e14f97fSRoger A. Faulkner label(sp_body, ' ', w, 0, -1, 0, style, FONT_BOLD, sp_info, version, id, catalog);
3021da2e3ebdSchin }
3022da2e3ebdSchin else
3023da2e3ebdSchin {
3024da2e3ebdSchin sfputr(sp_body, ".OP", ' ');
3025da2e3ebdSchin if (sl)
3026da2e3ebdSchin sfwrite(sp_body, s, sl);
3027da2e3ebdSchin else
3028da2e3ebdSchin sfputc(sp_body, f ? f : '-');
3029da2e3ebdSchin sfputc(sp_body, ' ');
3030da2e3ebdSchin if (w)
3031da2e3ebdSchin {
3032*3e14f97fSRoger A. Faulkner if (label(sp_body, 0, w, 0, -1, 0, style, 0, sp_info, version, id, catalog))
3033da2e3ebdSchin {
3034da2e3ebdSchin sfputc(sp_body, '|');
3035*3e14f97fSRoger A. Faulkner label(sp_body, 0, w, 0, -1, 0, style, 0, sp_info, version, id, native);
3036da2e3ebdSchin }
3037da2e3ebdSchin }
3038da2e3ebdSchin else
3039da2e3ebdSchin sfputc(sp_body, '-');
3040da2e3ebdSchin sfputc(sp_body, ' ');
3041da2e3ebdSchin m = a & OPT_TYPE;
3042da2e3ebdSchin for (j = 0; j < elementsof(attrs); j++)
3043da2e3ebdSchin if (m & attrs[j].flag)
3044da2e3ebdSchin {
3045da2e3ebdSchin sfputr(sp_body, attrs[j].name, -1);
3046da2e3ebdSchin break;
3047da2e3ebdSchin }
3048da2e3ebdSchin if (m = (a & ~m) | mode)
3049da2e3ebdSchin for (j = 0; j < elementsof(attrs); j++)
3050da2e3ebdSchin if (m & attrs[j].flag)
3051da2e3ebdSchin {
3052da2e3ebdSchin sfputc(sp_body, ':');
3053da2e3ebdSchin sfputr(sp_body, attrs[j].name, -1);
3054da2e3ebdSchin }
3055da2e3ebdSchin sfputc(sp_body, ' ');
3056da2e3ebdSchin if (y)
3057*3e14f97fSRoger A. Faulkner label(sp_body, 0, y, 0, -1, 0, style, 0, sp_info, version, id, catalog);
3058da2e3ebdSchin else
3059da2e3ebdSchin sfputc(sp_body, '-');
3060da2e3ebdSchin if (v)
3061da2e3ebdSchin sfprintf(sp_body, " %-.*s", vl, v);
3062da2e3ebdSchin }
3063da2e3ebdSchin }
3064da2e3ebdSchin else
3065da2e3ebdSchin {
3066da2e3ebdSchin if (f)
3067da2e3ebdSchin {
3068da2e3ebdSchin if (sp_body == sp_plus)
3069da2e3ebdSchin sfputc(sp_body, '+');
3070da2e3ebdSchin sfputc(sp_body, '-');
3071da2e3ebdSchin sfputr(sp_body, font(FONT_BOLD, style, 1), -1);
3072da2e3ebdSchin if (!sl)
3073da2e3ebdSchin {
3074da2e3ebdSchin sfputc(sp_body, f);
3075da2e3ebdSchin if (f == '-' && y)
3076da2e3ebdSchin {
3077da2e3ebdSchin y = 0;
3078da2e3ebdSchin sfputr(sp_body, C("long-option[=value]"), -1);
3079da2e3ebdSchin }
3080da2e3ebdSchin }
3081da2e3ebdSchin else
3082da2e3ebdSchin sfwrite(sp_body, s, sl);
3083da2e3ebdSchin sfputr(sp_body, font(FONT_BOLD, style, 0), -1);
3084da2e3ebdSchin if (w)
3085da2e3ebdSchin {
3086da2e3ebdSchin sfputc(sp_body, ',');
3087da2e3ebdSchin sfputc(sp_body, ' ');
3088da2e3ebdSchin }
3089da2e3ebdSchin }
3090da2e3ebdSchin else if ((flags & OPT_functions) && re > rb)
3091da2e3ebdSchin {
3092da2e3ebdSchin sfwrite(sp_body, rb, re - rb);
3093da2e3ebdSchin sfputc(sp_body, ' ');
3094da2e3ebdSchin }
3095da2e3ebdSchin if (w)
3096da2e3ebdSchin {
3097da2e3ebdSchin if (prefix > 0)
3098da2e3ebdSchin {
3099da2e3ebdSchin sfputc(sp_body, '-');
3100da2e3ebdSchin if (prefix > 1)
3101da2e3ebdSchin sfputc(sp_body, '-');
3102da2e3ebdSchin }
3103*3e14f97fSRoger A. Faulkner if (label(sp_body, 0, w, 0, -1, 0, style, FONT_BOLD, sp_info, version, id, catalog))
3104da2e3ebdSchin {
3105da2e3ebdSchin sfputc(sp_body, '|');
3106*3e14f97fSRoger A. Faulkner label(sp_body, 0, w, 0, -1, 0, style, FONT_BOLD, sp_info, version, id, native);
3107da2e3ebdSchin }
3108da2e3ebdSchin }
3109da2e3ebdSchin if (y)
3110da2e3ebdSchin {
3111da2e3ebdSchin if (a & OPT_optional)
3112da2e3ebdSchin sfputc(sp_body, '[');
3113da2e3ebdSchin else if (!w)
3114da2e3ebdSchin sfputc(sp_body, ' ');
3115da2e3ebdSchin if (w)
3116da2e3ebdSchin sfputc(sp_body, prefix == 1 ? ' ' : '=');
3117*3e14f97fSRoger A. Faulkner label(sp_body, 0, y, 0, -1, 0, style, FONT_ITALIC, sp_info, version, id, catalog);
3118da2e3ebdSchin if (a & OPT_optional)
3119da2e3ebdSchin sfputc(sp_body, ']');
3120da2e3ebdSchin }
3121da2e3ebdSchin }
3122da2e3ebdSchin if (style >= STYLE_match)
3123da2e3ebdSchin {
3124da2e3ebdSchin if (d)
3125*3e14f97fSRoger A. Faulkner textout(sp_body, d, style, 0, 3, sp_info, version, id, catalog);
3126da2e3ebdSchin if (u)
3127*3e14f97fSRoger A. Faulkner textout(sp_body, u, style, 0, 3, sp_info, version, id, catalog);
3128da2e3ebdSchin if ((a & OPT_invert) && w && (d || u))
3129da2e3ebdSchin {
3130da2e3ebdSchin u = skip(w, ':', '?', 0, 1, 0, 0, version);
3131da2e3ebdSchin if (f)
3132da2e3ebdSchin 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);
3133da2e3ebdSchin else
3134da2e3ebdSchin 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"));
3135da2e3ebdSchin if (!(t = sfstruse(sp_info)))
3136da2e3ebdSchin goto nospace;
3137*3e14f97fSRoger A. Faulkner textout(sp_body, t, style, 0, 0, sp_info, version, NiL, NiL);
3138da2e3ebdSchin }
3139da2e3ebdSchin if (*p == GO)
3140da2e3ebdSchin {
3141*3e14f97fSRoger A. Faulkner p = u ? skip(p + 1, 0, 0, 0, 0, 1, 1, version) : textout(sp_body, p, style, 4, 0, sp_info, version, id, catalog);
3142da2e3ebdSchin y = "+?";
3143da2e3ebdSchin }
3144da2e3ebdSchin else
3145da2e3ebdSchin y = " ";
3146da2e3ebdSchin if (a & OPT_optional)
3147da2e3ebdSchin {
3148da2e3ebdSchin if (ov)
3149da2e3ebdSchin {
3150da2e3ebdSchin sfprintf(sp_info, "%s%s \b", y, T(NiL, ID, "If the option value is omitted then"));
3151da2e3ebdSchin t = ov + ol;
3152da2e3ebdSchin while (ov < t)
3153da2e3ebdSchin {
3154da2e3ebdSchin if (((c = *ov++) == ':' || c == '?') && *ov == c)
3155da2e3ebdSchin ov++;
3156da2e3ebdSchin sfputc(sp_info, c);
3157da2e3ebdSchin }
3158da2e3ebdSchin sfprintf(sp_info, "\b %s.", T(NiL, ID, "is assumed"));
3159da2e3ebdSchin }
3160da2e3ebdSchin else
3161da2e3ebdSchin sfprintf(sp_info, "%s%s", y, T(NiL, ID, "The option value may be omitted."));
3162da2e3ebdSchin if (!(t = sfstruse(sp_info)))
3163da2e3ebdSchin goto nospace;
3164*3e14f97fSRoger A. Faulkner textout(sp_body, t, style, 4, 0, sp_info, version, NiL, NiL);
3165da2e3ebdSchin y = " ";
3166da2e3ebdSchin }
3167da2e3ebdSchin if (v)
3168da2e3ebdSchin {
3169da2e3ebdSchin sfprintf(sp_info, "%s%s \b", y, T(NiL, ID, "The default value is"));
3170da2e3ebdSchin t = v + vl;
3171da2e3ebdSchin while (v < t)
3172da2e3ebdSchin {
3173da2e3ebdSchin if (((c = *v++) == ':' || c == '?') && *v == c)
3174da2e3ebdSchin v++;
3175da2e3ebdSchin sfputc(sp_info, c);
3176da2e3ebdSchin }
3177da2e3ebdSchin sfputc(sp_info, '\b');
3178da2e3ebdSchin sfputc(sp_info, '.');
3179da2e3ebdSchin if (!(t = sfstruse(sp_info)))
3180da2e3ebdSchin goto nospace;
3181*3e14f97fSRoger A. Faulkner textout(sp_body, t, style, 4, 0, sp_info, version, NiL, NiL);
3182da2e3ebdSchin }
3183da2e3ebdSchin }
3184da2e3ebdSchin else if (!mutex)
3185da2e3ebdSchin sfputc(sp_body, ']');
3186da2e3ebdSchin }
3187da2e3ebdSchin if (*p == GO)
3188da2e3ebdSchin {
3189da2e3ebdSchin if (style >= STYLE_match)
3190*3e14f97fSRoger A. Faulkner p = textout(sp_body, p, style, 4, 0, sp_info, version, id, catalog);
3191da2e3ebdSchin else
3192da2e3ebdSchin p = skip(p + 1, 0, 0, 0, 0, 1, 1, version);
3193da2e3ebdSchin }
3194da2e3ebdSchin }
3195da2e3ebdSchin else if (*p == GO)
3196da2e3ebdSchin p = skip(p + 1, 0, 0, 0, 0, 1, 1, version);
3197da2e3ebdSchin }
3198da2e3ebdSchin psp = pop(psp);
3199da2e3ebdSchin if (sp_misc)
3200da2e3ebdSchin {
3201da2e3ebdSchin if (!(p = sfstruse(sp_misc)))
3202da2e3ebdSchin goto nospace;
3203da2e3ebdSchin for (t = p; *t == '\t' || *t == '\n'; t++);
3204da2e3ebdSchin if (*t)
3205da2e3ebdSchin {
3206*3e14f97fSRoger A. Faulkner item(sp_body, C("IMPLEMENTATION"), 0, 0, style, sp_info, version, id, ID);
3207da2e3ebdSchin sfputr(sp_body, p, -1);
3208da2e3ebdSchin }
3209da2e3ebdSchin }
3210da2e3ebdSchin }
3211da2e3ebdSchin version = o->version;
3212*3e14f97fSRoger A. Faulkner id = o->id;
3213da2e3ebdSchin catalog = o->catalog;
3214da2e3ebdSchin if (style >= STYLE_keys)
3215da2e3ebdSchin {
3216da2e3ebdSchin if (sp_info)
3217da2e3ebdSchin sfclose(sp_info);
3218da2e3ebdSchin if (style == STYLE_keys && sfstrtell(mp) > 1)
3219da2e3ebdSchin sfstrseek(mp, -1, SEEK_CUR);
3220da2e3ebdSchin if (!(p = sfstruse(mp)))
3221da2e3ebdSchin goto nospace;
3222da2e3ebdSchin return opt_info.msg = p;
3223da2e3ebdSchin }
3224da2e3ebdSchin sp = sp_text;
3225da2e3ebdSchin if (sfstrtell(sp) && style != STYLE_posix)
3226da2e3ebdSchin sfputc(sp, ']');
3227da2e3ebdSchin if (style == STYLE_nroff)
3228da2e3ebdSchin {
3229*3e14f97fSRoger A. Faulkner char ud[64];
3230*3e14f97fSRoger A. Faulkner
3231*3e14f97fSRoger A. Faulkner s = o->id;
3232*3e14f97fSRoger A. Faulkner t = ud;
3233*3e14f97fSRoger A. Faulkner while (t < &ud[sizeof(ud)-2] && (c = *s++))
3234*3e14f97fSRoger A. Faulkner {
3235*3e14f97fSRoger A. Faulkner if (islower(c))
3236*3e14f97fSRoger A. Faulkner c = toupper(c);
3237*3e14f97fSRoger A. Faulkner *t++ = c;
3238*3e14f97fSRoger A. Faulkner }
3239*3e14f97fSRoger A. Faulkner *t = 0;
3240da2e3ebdSchin sfprintf(sp, "\
3241da2e3ebdSchin .\\\" format with nroff|troff|groff -man\n\
3242da2e3ebdSchin .fp 5 CW\n\
32437c2fbfb3SApril Chin .nr mH 5\n\
32447c2fbfb3SApril Chin .de H0\n\
32457c2fbfb3SApril Chin .nr mH 0\n\
32467c2fbfb3SApril Chin .in 5n\n\
32477c2fbfb3SApril Chin \\fB\\\\$1\\fP\n\
32487c2fbfb3SApril Chin .in 7n\n\
3249da2e3ebdSchin ..\n\
3250da2e3ebdSchin .de H1\n\
32517c2fbfb3SApril Chin .nr mH 1\n\
32527c2fbfb3SApril Chin .in 7n\n\
3253da2e3ebdSchin \\fB\\\\$1\\fP\n\
32547c2fbfb3SApril Chin .in 9n\n\
3255da2e3ebdSchin ..\n\
3256da2e3ebdSchin .de H2\n\
32577c2fbfb3SApril Chin .nr mH 2\n\
32587c2fbfb3SApril Chin .in 11n\n\
3259da2e3ebdSchin \\fB\\\\$1\\fP\n\
32607c2fbfb3SApril Chin .in 13n\n\
3261da2e3ebdSchin ..\n\
3262da2e3ebdSchin .de H3\n\
32637c2fbfb3SApril Chin .nr mH 3\n\
32647c2fbfb3SApril Chin .in 15n\n\
3265da2e3ebdSchin \\fB\\\\$1\\fP\n\
32667c2fbfb3SApril Chin .in 17n\n\
3267da2e3ebdSchin ..\n\
3268da2e3ebdSchin .de H4\n\
32697c2fbfb3SApril Chin .nr mH 4\n\
32707c2fbfb3SApril Chin .in 19n\n\
3271da2e3ebdSchin \\fB\\\\$1\\fP\n\
32727c2fbfb3SApril Chin .in 21n\n\
3273da2e3ebdSchin ..\n\
3274da2e3ebdSchin .de OP\n\
32757c2fbfb3SApril Chin .nr mH 0\n\
3276da2e3ebdSchin .ie !'\\\\$1'-' \\{\n\
3277da2e3ebdSchin .ds mO \\\\fB\\\\-\\\\$1\\\\fP\n\
3278da2e3ebdSchin .ds mS ,\\\\0\n\
3279da2e3ebdSchin .\\}\n\
3280da2e3ebdSchin .el \\{\n\
3281da2e3ebdSchin .ds mO \\\\&\n\
3282da2e3ebdSchin .ds mS \\\\&\n\
3283da2e3ebdSchin .\\}\n\
3284da2e3ebdSchin .ie '\\\\$2'-' \\{\n\
3285da2e3ebdSchin .if !'\\\\$4'-' .as mO \\\\0\\\\fI\\\\$4\\\\fP\n\
3286da2e3ebdSchin .\\}\n\
3287da2e3ebdSchin .el \\{\n\
3288da2e3ebdSchin .as mO \\\\*(mS\\\\fB%s\\\\$2\\\\fP\n\
3289da2e3ebdSchin .if !'\\\\$4'-' .as mO =\\\\fI\\\\$4\\\\fP\n\
3290da2e3ebdSchin .\\}\n\
32917c2fbfb3SApril Chin .in 5n\n\
3292da2e3ebdSchin \\\\*(mO\n\
32937c2fbfb3SApril Chin .in 9n\n\
32947c2fbfb3SApril Chin ..\n\
32957c2fbfb3SApril Chin .de SP\n\
32967c2fbfb3SApril Chin .if \\\\n(mH==2 .in 9n\n\
32977c2fbfb3SApril Chin .if \\\\n(mH==3 .in 13n\n\
32987c2fbfb3SApril Chin .if \\\\n(mH==4 .in 17n\n\
3299da2e3ebdSchin ..\n\
3300da2e3ebdSchin .de FN\n\
33017c2fbfb3SApril Chin .nr mH 0\n\
33027c2fbfb3SApril Chin .in 5n\n\
3303da2e3ebdSchin \\\\$1 \\\\$2\n\
33047c2fbfb3SApril Chin .in 9n\n\
33057c2fbfb3SApril Chin ..\n\
33067c2fbfb3SApril Chin .de DS\n\
33077c2fbfb3SApril Chin .in +3n\n\
33087c2fbfb3SApril Chin .ft 5\n\
33097c2fbfb3SApril Chin .nf\n\
33107c2fbfb3SApril Chin ..\n\
33117c2fbfb3SApril Chin .de DE\n\
33127c2fbfb3SApril Chin .fi\n\
33137c2fbfb3SApril Chin .ft R\n\
33147c2fbfb3SApril Chin .in -3n\n\
3315da2e3ebdSchin ..\n\
3316da2e3ebdSchin .TH %s %d\n\
3317da2e3ebdSchin "
3318da2e3ebdSchin , o->prefix == 2 ? "\\\\-\\\\-" : o->prefix == 1 ? "\\\\-" : ""
3319*3e14f97fSRoger A. Faulkner , ud
3320da2e3ebdSchin , section
3321da2e3ebdSchin );
3322da2e3ebdSchin }
3323da2e3ebdSchin if (style == STYLE_match)
3324da2e3ebdSchin {
3325da2e3ebdSchin if (!matched)
3326da2e3ebdSchin {
3327da2e3ebdSchin if (hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), (char*)what))
3328da2e3ebdSchin {
3329da2e3ebdSchin if (!sp_help && !(sp_help = sfstropen()))
3330da2e3ebdSchin goto nospace;
3331da2e3ebdSchin sfprintf(sp_help, "[-][:%s?%s]", hp->match, hp->text);
3332da2e3ebdSchin if (!(opts = sfstruse(sp_help)))
3333da2e3ebdSchin goto nospace;
3334da2e3ebdSchin goto again;
3335da2e3ebdSchin }
3336da2e3ebdSchin s = (char*)unknown;
3337da2e3ebdSchin goto nope;
3338da2e3ebdSchin }
3339da2e3ebdSchin else if (matched < 0)
3340da2e3ebdSchin x = 0;
3341da2e3ebdSchin }
3342da2e3ebdSchin if (sp_plus)
3343da2e3ebdSchin {
3344da2e3ebdSchin if (sfstrtell(sp_plus))
3345da2e3ebdSchin {
3346da2e3ebdSchin if (sfstrtell(sp))
3347da2e3ebdSchin sfputc(sp, ' ');
3348da2e3ebdSchin if (!(t = sfstruse(sp_plus)))
3349da2e3ebdSchin goto nospace;
3350da2e3ebdSchin sfputr(sp, t, ']');
3351da2e3ebdSchin }
3352da2e3ebdSchin sfclose(sp_plus);
3353da2e3ebdSchin }
3354da2e3ebdSchin if (style >= STYLE_man)
3355da2e3ebdSchin {
3356da2e3ebdSchin if (sp_head)
3357da2e3ebdSchin {
3358da2e3ebdSchin if (!(t = sfstruse(sp_head)))
3359da2e3ebdSchin goto nospace;
3360da2e3ebdSchin for (; *t == '\n'; t++);
3361da2e3ebdSchin sfputr(sp, t, '\n');
3362da2e3ebdSchin sfclose(sp_head);
3363da2e3ebdSchin sp_head = 0;
3364da2e3ebdSchin }
3365*3e14f97fSRoger A. Faulkner item(sp, C("SYNOPSIS"), 0, 0, style, sp_info, version, id, ID);
3366da2e3ebdSchin }
3367da2e3ebdSchin if (x)
3368da2e3ebdSchin {
3369da2e3ebdSchin for (t = x + xl; t > x && (*(t - 1) == '\n' || *(t - 1) == '\r'); t--);
3370da2e3ebdSchin xl = t - x;
3371da2e3ebdSchin if (style >= STYLE_match)
3372da2e3ebdSchin {
3373*3e14f97fSRoger A. Faulkner args(sp, x, xl, flags, style, sp_info, version, id, catalog);
3374da2e3ebdSchin x = 0;
3375da2e3ebdSchin }
3376da2e3ebdSchin }
3377da2e3ebdSchin if (sp_body)
3378da2e3ebdSchin {
3379da2e3ebdSchin if (sfstrtell(sp_body))
3380da2e3ebdSchin {
3381da2e3ebdSchin if (style < STYLE_match && sfstrtell(sp))
3382da2e3ebdSchin sfputc(sp, ' ');
3383da2e3ebdSchin if (!(t = sfstruse(sp_body)))
3384da2e3ebdSchin goto nospace;
3385da2e3ebdSchin sfputr(sp, t, -1);
3386da2e3ebdSchin }
3387da2e3ebdSchin sfclose(sp_body);
3388da2e3ebdSchin sp_body = 0;
3389da2e3ebdSchin }
3390da2e3ebdSchin if (x && style != STYLE_posix)
3391*3e14f97fSRoger A. Faulkner args(sp, x, xl, flags, style, sp_info, version, id, catalog);
3392da2e3ebdSchin if (sp_info)
3393da2e3ebdSchin {
3394da2e3ebdSchin sfclose(sp_info);
3395da2e3ebdSchin sp_info = 0;
3396da2e3ebdSchin }
3397da2e3ebdSchin if (sp_misc)
3398da2e3ebdSchin {
3399da2e3ebdSchin sfclose(sp_misc);
3400da2e3ebdSchin sp_misc = 0;
3401da2e3ebdSchin }
3402da2e3ebdSchin if (!(p = sfstruse(sp)))
3403da2e3ebdSchin goto nospace;
3404da2e3ebdSchin astwinsize(1, NiL, &opt_info.state->width);
3405da2e3ebdSchin if (opt_info.state->width < 20)
3406da2e3ebdSchin opt_info.state->width = OPT_WIDTH;
3407*3e14f97fSRoger A. Faulkner m = strlen((style <= STYLE_long && error_info.id && !strchr(error_info.id, '/')) ? error_info.id : id) + 1;
34087c2fbfb3SApril Chin margin = style == STYLE_api ? (8 * 1024) : (opt_info.state->width - 1);
3409da2e3ebdSchin if (!(opt_info.state->flags & OPT_preformat))
3410da2e3ebdSchin {
3411da2e3ebdSchin if (style >= STYLE_man || matched < 0)
3412da2e3ebdSchin {
3413da2e3ebdSchin sfputc(mp, '\f');
3414da2e3ebdSchin ts = 0;
3415da2e3ebdSchin }
3416da2e3ebdSchin else
3417da2e3ebdSchin ts = OPT_USAGE + m;
3418da2e3ebdSchin if (style == STYLE_html)
3419da2e3ebdSchin {
3420*3e14f97fSRoger A. Faulkner char ud[64];
3421*3e14f97fSRoger A. Faulkner
3422*3e14f97fSRoger A. Faulkner s = id;
3423*3e14f97fSRoger A. Faulkner t = ud;
3424*3e14f97fSRoger A. Faulkner while (t < &ud[sizeof(ud)-2] && (c = *s++))
3425*3e14f97fSRoger A. Faulkner {
3426*3e14f97fSRoger A. Faulkner if (islower(c))
3427*3e14f97fSRoger A. Faulkner c = toupper(c);
3428*3e14f97fSRoger A. Faulkner *t++ = c;
3429*3e14f97fSRoger A. Faulkner }
3430*3e14f97fSRoger A. Faulkner *t = 0;
3431*3e14f97fSRoger A. Faulkner sfprintf(mp, "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n<HTML>\n<HEAD>\n<META name=\"generator\" content=\"optget (AT&T Research) 2000-04-01\">\n%s<TITLE>%s man document</TITLE>\n</HEAD>\n<BODY bgcolor=white>\n", (opt_info.state->flags & OPT_proprietary) ? "<!--INTERNAL-->\n" : "", id);
3432*3e14f97fSRoger A. Faulkner sfprintf(mp, "<H4><TABLE width=100%%><TR><TH align=left> %s ( %d ) <TH align=center><A href=\".\" title=\"Index\">%s</A><TH align=right>%s ( %d )</TR></TABLE></H4>\n<HR>\n", ud, section, T(NiL, ID, heading[section % 10]), ud, section);
3433da2e3ebdSchin sfprintf(mp, "<DL compact>\n<DT>");
3434da2e3ebdSchin co = 2;
3435da2e3ebdSchin *(pt = ptstk) = 0;
3436da2e3ebdSchin }
3437da2e3ebdSchin else
3438da2e3ebdSchin co = 0;
34397c2fbfb3SApril Chin if ((rm = margin - ts) < OPT_MARGIN)
3440da2e3ebdSchin rm = OPT_MARGIN;
3441da2e3ebdSchin ip = indent;
3442da2e3ebdSchin ip->stop = (ip+1)->stop = style >= STYLE_html ? 0 : 2;
3443da2e3ebdSchin tp = 0;
3444da2e3ebdSchin n = 0;
3445da2e3ebdSchin head = 1;
3446da2e3ebdSchin while (*p == '\n')
3447da2e3ebdSchin p++;
3448da2e3ebdSchin while (c = *p++)
3449da2e3ebdSchin {
3450da2e3ebdSchin if (c == '\n')
3451da2e3ebdSchin {
3452da2e3ebdSchin ip = indent;
3453da2e3ebdSchin n = 0;
3454da2e3ebdSchin tp = 0;
3455da2e3ebdSchin sfputc(mp, '\n');
3456da2e3ebdSchin co = 0;
34577c2fbfb3SApril Chin rm = margin;
3458da2e3ebdSchin ts = ip->stop;
3459da2e3ebdSchin if (*p == '\n')
3460da2e3ebdSchin {
3461da2e3ebdSchin while (*++p == '\n');
3462da2e3ebdSchin if ((style == STYLE_man || style == STYLE_html) && (!head || *p != ' ' && *p != '\t'))
3463da2e3ebdSchin {
3464da2e3ebdSchin if (style == STYLE_man)
3465da2e3ebdSchin p--;
3466da2e3ebdSchin else
3467da2e3ebdSchin sfprintf(mp, "<P>\n");
3468da2e3ebdSchin }
3469da2e3ebdSchin }
3470da2e3ebdSchin head = *p != ' ' && *p != '\t';
3471da2e3ebdSchin if (style == STYLE_html && (*p != '<' || !strneq(p, "<BR>", 4) && !strneq(p, "<P>", 3)))
3472da2e3ebdSchin {
3473da2e3ebdSchin y = p;
3474da2e3ebdSchin while (*p == '\t')
3475da2e3ebdSchin p++;
3476da2e3ebdSchin if (*p == '\n')
3477da2e3ebdSchin continue;
3478da2e3ebdSchin j = p - y;
3479da2e3ebdSchin if (j > *pt)
3480da2e3ebdSchin {
3481da2e3ebdSchin if (pt > ptstk)
3482da2e3ebdSchin sfprintf(mp, "<DL compact>\n");
3483da2e3ebdSchin *++pt = j;
3484da2e3ebdSchin sfprintf(mp, "<DL compact>\n");
3485da2e3ebdSchin }
3486da2e3ebdSchin else while (j < *pt)
3487da2e3ebdSchin {
3488da2e3ebdSchin if (--pt > ptstk)
3489da2e3ebdSchin sfprintf(mp, "</DL>\n");
3490da2e3ebdSchin sfprintf(mp, "</DL>\n");
3491da2e3ebdSchin }
3492da2e3ebdSchin co += sfprintf(mp, "<DT>");
3493da2e3ebdSchin }
3494da2e3ebdSchin }
3495da2e3ebdSchin else if (c == '\t')
3496da2e3ebdSchin {
3497da2e3ebdSchin if (style == STYLE_html)
3498da2e3ebdSchin {
3499da2e3ebdSchin while (*p == '\t')
3500da2e3ebdSchin p++;
3501da2e3ebdSchin if (*p != '\n')
3502da2e3ebdSchin co += sfprintf(mp, "<DD>");
3503da2e3ebdSchin }
3504da2e3ebdSchin else
3505da2e3ebdSchin {
3506da2e3ebdSchin if ((ip+1)->stop)
3507da2e3ebdSchin {
3508da2e3ebdSchin do
3509da2e3ebdSchin {
3510da2e3ebdSchin ip++;
3511da2e3ebdSchin if (*p != '\t')
3512da2e3ebdSchin break;
3513da2e3ebdSchin p++;
3514da2e3ebdSchin } while ((ip+1)->stop);
3515da2e3ebdSchin if (*p == '\n')
3516da2e3ebdSchin continue;
3517da2e3ebdSchin ts = ip->stop;
3518da2e3ebdSchin if (co >= ts)
3519da2e3ebdSchin {
3520da2e3ebdSchin sfputc(mp, '\n');
3521da2e3ebdSchin co = 0;
35227c2fbfb3SApril Chin rm = margin;
3523da2e3ebdSchin ts = ip->stop;
3524da2e3ebdSchin }
3525da2e3ebdSchin }
3526da2e3ebdSchin while (co < ts)
3527da2e3ebdSchin {
3528da2e3ebdSchin sfputc(mp, ' ');
3529da2e3ebdSchin co++;
3530da2e3ebdSchin }
3531da2e3ebdSchin }
3532da2e3ebdSchin }
3533da2e3ebdSchin else
3534da2e3ebdSchin {
3535da2e3ebdSchin if (c == ' ' && !n)
3536da2e3ebdSchin {
3537da2e3ebdSchin if (co >= rm)
3538da2e3ebdSchin tp = 0;
3539da2e3ebdSchin else
3540da2e3ebdSchin {
3541da2e3ebdSchin tp = sfstrtell(mp);
3542da2e3ebdSchin pp = p;
3543da2e3ebdSchin }
3544da2e3ebdSchin if (style == STYLE_nroff && !co)
3545da2e3ebdSchin continue;
3546da2e3ebdSchin }
3547da2e3ebdSchin else if (style == STYLE_html)
3548da2e3ebdSchin {
3549da2e3ebdSchin if (c == '<')
3550da2e3ebdSchin {
3551da2e3ebdSchin if (strneq(p, "NOBR>", 5))
3552da2e3ebdSchin n++;
3553da2e3ebdSchin else if (n && strneq(p, "/NOBR>", 6) && !--n)
3554da2e3ebdSchin {
3555da2e3ebdSchin for (y = p += 6; (c = *p) && c != ' ' && c != '\t' && c != '\n' && c != '<'; p++)
3556da2e3ebdSchin if (c == '[')
3557da2e3ebdSchin sfputr(mp, "[", -1);
3558da2e3ebdSchin else if (c == ']')
3559da2e3ebdSchin sfputr(mp, "]", -1);
3560da2e3ebdSchin else
3561da2e3ebdSchin sfputc(mp, c);
3562da2e3ebdSchin sfwrite(mp, "</NOBR", 6);
3563da2e3ebdSchin c = '>';
3564da2e3ebdSchin tp = 0;
3565da2e3ebdSchin co += p - y + 6;
3566da2e3ebdSchin }
3567da2e3ebdSchin }
3568da2e3ebdSchin else if (c == '>' && !n)
3569da2e3ebdSchin {
3570da2e3ebdSchin for (y = --p; (c = *p) && c != ' ' && c != '\t' && c != '\n' && c != '<'; p++)
3571da2e3ebdSchin if (c == '[')
3572da2e3ebdSchin sfputr(mp, "[", -1);
3573da2e3ebdSchin else if (c == ']')
3574da2e3ebdSchin sfputr(mp, "]", -1);
3575da2e3ebdSchin else
3576da2e3ebdSchin sfputc(mp, c);
3577da2e3ebdSchin c = *sfstrseek(mp, -1, SEEK_CUR);
3578da2e3ebdSchin if (p > y + 1)
3579da2e3ebdSchin {
3580da2e3ebdSchin tp = 0;
3581da2e3ebdSchin co += p - y - 1;
3582da2e3ebdSchin }
3583da2e3ebdSchin if (co >= rm)
3584da2e3ebdSchin tp = 0;
3585da2e3ebdSchin else
3586da2e3ebdSchin {
3587da2e3ebdSchin tp = sfstrtell(mp);
3588da2e3ebdSchin pp = p;
3589da2e3ebdSchin }
3590da2e3ebdSchin }
3591da2e3ebdSchin else if (c == '[')
3592da2e3ebdSchin {
3593da2e3ebdSchin sfputr(mp, "[", -1);
3594da2e3ebdSchin c = ';';
3595da2e3ebdSchin }
3596da2e3ebdSchin else if (c == ']')
3597da2e3ebdSchin {
3598da2e3ebdSchin sfputr(mp, "]", -1);
3599da2e3ebdSchin c = ';';
3600da2e3ebdSchin }
3601da2e3ebdSchin else if (c == 'h')
3602da2e3ebdSchin {
3603da2e3ebdSchin y = p;
3604da2e3ebdSchin if (*y++ == 't' && *y++ == 't' && *y++ == 'p' && (*y == ':' || *y++ == 's' && *y == ':') && *y++ == ':' && *y++ == '/' && *y++ == '/')
3605da2e3ebdSchin {
3606da2e3ebdSchin while (isalnum(*y) || *y == '_' || *y == '/' || *y == '-' || *y == '.')
3607da2e3ebdSchin y++;
3608da2e3ebdSchin if (*y == '?')
3609da2e3ebdSchin while (isalnum(*y) || *y == '_' || *y == '/' || *y == '-' || *y == '.' || *y == '?' || *y == '=' || *y == '%' || *y == '&' || *y == ';' || *y == '#')
3610da2e3ebdSchin y++;
3611da2e3ebdSchin if (*(y - 1) == '.')
3612da2e3ebdSchin y--;
3613da2e3ebdSchin p--;
3614da2e3ebdSchin sfprintf(mp, "<A href=\"%-.*s\">%-.*s</A", y - p, p, y - p, p);
3615da2e3ebdSchin p = y;
3616da2e3ebdSchin c = '>';
3617da2e3ebdSchin }
3618da2e3ebdSchin }
3619da2e3ebdSchin else if (c == 'C')
3620da2e3ebdSchin {
3621da2e3ebdSchin y = p;
3622da2e3ebdSchin 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++ == ')')
3623da2e3ebdSchin {
3624da2e3ebdSchin sfputr(mp, "Copyright ©", -1);
3625da2e3ebdSchin p = y;
3626da2e3ebdSchin c = ';';
3627da2e3ebdSchin }
3628da2e3ebdSchin }
3629da2e3ebdSchin }
3630da2e3ebdSchin else if (c == ']')
3631da2e3ebdSchin {
3632da2e3ebdSchin if (n)
3633da2e3ebdSchin n--;
3634da2e3ebdSchin }
3635da2e3ebdSchin else if (c == '[')
3636da2e3ebdSchin n++;
3637da2e3ebdSchin if (c == CC_esc)
3638da2e3ebdSchin {
3639da2e3ebdSchin sfputc(mp, c);
3640da2e3ebdSchin do
3641da2e3ebdSchin {
3642da2e3ebdSchin if (!(c = *p++))
3643da2e3ebdSchin {
3644da2e3ebdSchin p--;
3645da2e3ebdSchin break;
3646da2e3ebdSchin }
3647da2e3ebdSchin sfputc(mp, c);
3648da2e3ebdSchin } while (c < 'a' || c > 'z');
3649da2e3ebdSchin }
3650da2e3ebdSchin else if (co++ >= rm && !n)
3651da2e3ebdSchin {
3652da2e3ebdSchin if (tp)
3653da2e3ebdSchin {
3654da2e3ebdSchin if (*sfstrseek(mp, tp, SEEK_SET) != ' ')
3655da2e3ebdSchin sfstrseek(mp, 1, SEEK_CUR);
3656da2e3ebdSchin tp = 0;
3657da2e3ebdSchin p = pp;
3658da2e3ebdSchin n = 0;
3659da2e3ebdSchin }
3660da2e3ebdSchin else if (c != ' ' && c != '\n')
3661da2e3ebdSchin sfputc(mp, c);
3662da2e3ebdSchin if (*p == ' ')
3663da2e3ebdSchin p++;
3664da2e3ebdSchin if (*p != '\n')
3665da2e3ebdSchin {
3666da2e3ebdSchin sfputc(mp, '\n');
3667da2e3ebdSchin for (co = 0; co < ts; co++)
3668da2e3ebdSchin sfputc(mp, ' ');
36697c2fbfb3SApril Chin rm = margin;
3670da2e3ebdSchin }
3671da2e3ebdSchin }
3672da2e3ebdSchin else
3673da2e3ebdSchin sfputc(mp, c);
3674da2e3ebdSchin }
3675da2e3ebdSchin }
3676da2e3ebdSchin for (d = sfstrbase(mp), t = sfstrseek(mp, 0, SEEK_CUR); t > d && ((c = *(t - 1)) == '\n' || c == '\r' || c == ' ' || c == '\t'); t--);
3677da2e3ebdSchin sfstrseek(mp, t - d, SEEK_SET);
3678da2e3ebdSchin if (style == STYLE_html)
3679da2e3ebdSchin {
3680da2e3ebdSchin while (pt > ptstk)
3681da2e3ebdSchin {
3682da2e3ebdSchin if (--pt > ptstk)
3683da2e3ebdSchin sfprintf(mp, "\n</DL>");
3684da2e3ebdSchin sfprintf(mp, "\n</DL>");
3685da2e3ebdSchin }
3686da2e3ebdSchin sfprintf(mp, "</DL>\n</BODY>\n</HTML>");
3687da2e3ebdSchin }
3688da2e3ebdSchin }
3689da2e3ebdSchin else
3690da2e3ebdSchin sfputr(mp, p, 0);
3691da2e3ebdSchin if (!(p = sfstruse(mp)))
3692da2e3ebdSchin goto nospace;
3693da2e3ebdSchin if (sp)
3694da2e3ebdSchin sfclose(sp);
3695da2e3ebdSchin return opt_info.msg = p;
3696da2e3ebdSchin nospace:
3697da2e3ebdSchin s = T(NiL, ID, "[* out of space *]");
3698da2e3ebdSchin nope:
3699da2e3ebdSchin if (psp)
3700da2e3ebdSchin pop(psp);
3701da2e3ebdSchin if (sp_help)
3702da2e3ebdSchin sfclose(sp_help);
3703da2e3ebdSchin if (sp_text)
3704da2e3ebdSchin sfclose(sp_text);
3705da2e3ebdSchin if (sp_plus)
3706da2e3ebdSchin sfclose(sp_plus);
3707da2e3ebdSchin if (sp_info)
3708da2e3ebdSchin sfclose(sp_info);
3709da2e3ebdSchin if (sp_head)
3710da2e3ebdSchin sfclose(sp_head);
3711da2e3ebdSchin if (sp_body)
3712da2e3ebdSchin sfclose(sp_body);
3713da2e3ebdSchin if (sp_misc)
3714da2e3ebdSchin sfclose(sp_misc);
3715da2e3ebdSchin return s;
3716da2e3ebdSchin }
3717da2e3ebdSchin
3718da2e3ebdSchin /*
3719da2e3ebdSchin * compatibility wrapper to opthelp()
3720da2e3ebdSchin */
3721da2e3ebdSchin
3722da2e3ebdSchin char*
optusage(const char * opts)3723da2e3ebdSchin optusage(const char* opts)
3724da2e3ebdSchin {
3725da2e3ebdSchin return opthelp(opts, NiL);
3726da2e3ebdSchin }
3727da2e3ebdSchin
3728da2e3ebdSchin /*
3729da2e3ebdSchin * convert number using strtonll() *except* that
3730da2e3ebdSchin * 0*[[:digit:]].* is treated as [[:digit:]].*
3731da2e3ebdSchin * i.e., it looks octal but isn't, to meet
3732da2e3ebdSchin * posix Utility Argument Syntax -- use
3733da2e3ebdSchin * 0x.* or <base>#* for alternate bases
3734da2e3ebdSchin */
3735da2e3ebdSchin
3736da2e3ebdSchin static intmax_t
optnumber(const char * s,char ** t,int * e)3737da2e3ebdSchin optnumber(const char* s, char** t, int* e)
3738da2e3ebdSchin {
3739da2e3ebdSchin intmax_t n;
3740da2e3ebdSchin int oerrno;
3741da2e3ebdSchin
3742da2e3ebdSchin while (*s == '0' && isdigit(*(s + 1)))
3743da2e3ebdSchin s++;
3744da2e3ebdSchin oerrno = errno;
3745da2e3ebdSchin errno = 0;
3746da2e3ebdSchin n = strtonll(s, t, NiL, 0);
3747da2e3ebdSchin if (e)
3748da2e3ebdSchin *e = errno;
3749da2e3ebdSchin errno = oerrno;
3750da2e3ebdSchin return n;
3751da2e3ebdSchin }
3752da2e3ebdSchin
3753da2e3ebdSchin /*
3754da2e3ebdSchin * point opt_info.arg to an error/info message for opt_info.name
3755da2e3ebdSchin * p points to opts location for opt_info.name
3756da2e3ebdSchin * optget() return value is returned
3757da2e3ebdSchin */
3758da2e3ebdSchin
3759da2e3ebdSchin static int
opterror(register char * p,int err,int version,char * id,char * catalog)3760*3e14f97fSRoger A. Faulkner opterror(register char* p, int err, int version, char* id, char* catalog)
3761da2e3ebdSchin {
3762da2e3ebdSchin register Sfio_t* mp;
3763da2e3ebdSchin register Sfio_t* tp;
3764da2e3ebdSchin register char* s;
3765da2e3ebdSchin register int c;
3766da2e3ebdSchin
3767da2e3ebdSchin if (opt_info.num != LONG_MIN)
376834f9b3eeSRoland Mainz opt_info.num = (long)(opt_info.number = 0);
3769da2e3ebdSchin if (!p || !(mp = opt_info.state->mp) && !(mp = opt_info.state->mp = sfstropen()))
3770da2e3ebdSchin goto nospace;
3771da2e3ebdSchin s = *p == '-' ? p : opt_info.name;
3772da2e3ebdSchin if (*p == '!')
3773da2e3ebdSchin {
3774da2e3ebdSchin while (*s == '-')
3775da2e3ebdSchin sfputc(mp, *s++);
3776da2e3ebdSchin sfputc(mp, 'n');
3777da2e3ebdSchin sfputc(mp, 'o');
3778da2e3ebdSchin }
3779da2e3ebdSchin sfputr(mp, s, ':');
3780da2e3ebdSchin sfputc(mp, ' ');
3781da2e3ebdSchin if (*p == '#' || *p == ':')
3782da2e3ebdSchin {
3783da2e3ebdSchin if (*p == '#')
3784da2e3ebdSchin {
3785da2e3ebdSchin s = T(NiL, ID, "numeric");
3786da2e3ebdSchin sfputr(mp, s, ' ');
3787da2e3ebdSchin }
3788da2e3ebdSchin if (*(p = next(p + 1, version)) == '[')
3789da2e3ebdSchin {
3790da2e3ebdSchin p = skip(s = p + 1, ':', '?', 0, 1, 0, 0, version);
3791da2e3ebdSchin tp = X(catalog) ? opt_info.state->xp : mp;
3792da2e3ebdSchin while (s < p)
3793da2e3ebdSchin {
3794da2e3ebdSchin if ((c = *s++) == '?' || c == ']')
3795da2e3ebdSchin s++;
3796da2e3ebdSchin sfputc(tp, c);
3797da2e3ebdSchin }
3798da2e3ebdSchin if (!X(catalog))
3799da2e3ebdSchin sfputc(mp, ' ');
3800da2e3ebdSchin else if (p = sfstruse(tp))
3801*3e14f97fSRoger A. Faulkner sfputr(mp, T(id, catalog, p), ' ');
3802da2e3ebdSchin else
3803da2e3ebdSchin goto nospace;
3804da2e3ebdSchin }
3805da2e3ebdSchin p = opt_info.name[2] ? C("value expected") : C("argument expected");
3806da2e3ebdSchin }
3807da2e3ebdSchin else if (*p == '*' || *p == '&')
3808da2e3ebdSchin {
3809da2e3ebdSchin sfputr(mp, opt_info.arg, ':');
3810da2e3ebdSchin sfputc(mp, ' ');
3811da2e3ebdSchin p = *p == '&' ? C("ambiguous option argument value") : C("unknown option argument value");
3812da2e3ebdSchin }
3813da2e3ebdSchin else if (*p == '=' || *p == '!')
3814da2e3ebdSchin p = C("value not expected");
3815da2e3ebdSchin else if (*p == '?')
3816da2e3ebdSchin p = *(p + 1) == '?' ? C("optget: option not supported") : C("ambiguous option");
3817da2e3ebdSchin else if (*p == '+')
3818da2e3ebdSchin p = C("section not found");
3819da2e3ebdSchin else
3820da2e3ebdSchin {
3821da2e3ebdSchin if (opt_info.option[0] != '?' && opt_info.option[0] != '-' || opt_info.option[1] != '?' && opt_info.option[1] != '-')
3822da2e3ebdSchin opt_info.option[0] = 0;
3823da2e3ebdSchin p = C("unknown option");
3824da2e3ebdSchin }
3825da2e3ebdSchin p = T(NiL, ID, p);
3826da2e3ebdSchin sfputr(mp, p, -1);
3827da2e3ebdSchin if (err)
3828da2e3ebdSchin sfputr(mp, " -- out of range", -1);
3829da2e3ebdSchin if (opt_info.arg = sfstruse(mp))
3830da2e3ebdSchin return ':';
3831da2e3ebdSchin nospace:
3832da2e3ebdSchin opt_info.arg = T(NiL, ID, "[* out of space *]");
3833da2e3ebdSchin return ':';
3834da2e3ebdSchin }
3835da2e3ebdSchin
3836da2e3ebdSchin /*
3837da2e3ebdSchin * argv: command line argv where argv[0] is command name
3838da2e3ebdSchin *
3839da2e3ebdSchin * opts: option control string
3840da2e3ebdSchin *
3841da2e3ebdSchin * '[' [flag][=][index][:<long-name>[|<alias-name>...]['?'description]] ']'
3842da2e3ebdSchin * long option name, index, description; -index returned
3843da2e3ebdSchin * ':' option takes string arg
3844da2e3ebdSchin * '#' option takes numeric arg (concat option may follow)
3845da2e3ebdSchin * '?' (option) following options not in usage
3846da2e3ebdSchin * (following # or :) optional arg
3847da2e3ebdSchin * '[' '[' ... ] ... '[' ... ']' ']'
3848da2e3ebdSchin * mutually exclusive option grouping
3849da2e3ebdSchin * '[' name [:attr]* [?description] ']'
3850da2e3ebdSchin * (following # or :) optional option arg description
3851da2e3ebdSchin * '\n'[' '|'\t']* ignored for legibility
3852da2e3ebdSchin * ' ' ... optional argument(s) description (to end of string)
3853da2e3ebdSchin * or after blank line
3854da2e3ebdSchin * ']]' literal ']' within '[' ... ']'
3855da2e3ebdSchin *
3856da2e3ebdSchin * return:
3857da2e3ebdSchin * 0 no more options
3858da2e3ebdSchin * '?' usage: opt_info.arg points to message sans
3859da2e3ebdSchin * `Usage: command '
3860da2e3ebdSchin * ':' error: opt_info.arg points to message sans `command: '
3861da2e3ebdSchin *
386234f9b3eeSRoland Mainz * ':' '#' ' ' '[' ']'
3863da2e3ebdSchin * invalid option chars
3864da2e3ebdSchin *
3865da2e3ebdSchin * -- terminates option list and returns 0
3866da2e3ebdSchin *
3867da2e3ebdSchin * + as first opts char makes + equivalent to -
3868da2e3ebdSchin *
3869da2e3ebdSchin * if any # option is specified then numeric options (e.g., -123)
3870da2e3ebdSchin * are associated with the leftmost # option in opts
3871da2e3ebdSchin *
3872da2e3ebdSchin * usage info in placed opt_info.arg when '?' returned
3873da2e3ebdSchin * see help_text[] (--???) for more info
3874da2e3ebdSchin */
3875da2e3ebdSchin
3876da2e3ebdSchin int
optget(register char ** argv,const char * oopts)3877da2e3ebdSchin optget(register char** argv, const char* oopts)
3878da2e3ebdSchin {
3879da2e3ebdSchin register int c;
3880da2e3ebdSchin register char* s;
3881da2e3ebdSchin char* a;
3882da2e3ebdSchin char* b;
3883da2e3ebdSchin char* e;
3884da2e3ebdSchin char* f;
3885da2e3ebdSchin char* g;
3886da2e3ebdSchin char* v;
3887da2e3ebdSchin char* w;
3888da2e3ebdSchin char* p;
3889da2e3ebdSchin char* q;
3890da2e3ebdSchin char* t;
3891da2e3ebdSchin char* y;
3892da2e3ebdSchin char* numopt;
3893da2e3ebdSchin char* opts;
3894*3e14f97fSRoger A. Faulkner char* id;
3895da2e3ebdSchin char* catalog;
3896da2e3ebdSchin int n;
3897da2e3ebdSchin int m;
3898da2e3ebdSchin int k;
3899da2e3ebdSchin int j;
3900da2e3ebdSchin int x;
3901da2e3ebdSchin int err;
3902da2e3ebdSchin int no;
3903da2e3ebdSchin int nov;
3904da2e3ebdSchin int num;
3905da2e3ebdSchin int numchr;
3906da2e3ebdSchin int prefix;
3907da2e3ebdSchin int version;
3908da2e3ebdSchin Help_t* hp;
3909da2e3ebdSchin Push_t* psp;
3910da2e3ebdSchin Push_t* tsp;
3911da2e3ebdSchin Sfio_t* vp;
3912da2e3ebdSchin Sfio_t* xp;
3913da2e3ebdSchin Optcache_t* cache;
3914da2e3ebdSchin Optcache_t* pcache;
3915da2e3ebdSchin Optpass_t* pass;
3916da2e3ebdSchin
39177c2fbfb3SApril Chin #if !_PACKAGE_astsa && !_YOU_FIGURED_OUT_HOW_TO_GET_ALL_DLLS_TO_DO_THIS_
3918da2e3ebdSchin /*
3919da2e3ebdSchin * these are not initialized by all dlls!
3920da2e3ebdSchin */
3921da2e3ebdSchin
3922da2e3ebdSchin extern Error_info_t _error_info_;
3923da2e3ebdSchin extern Opt_t _opt_info_;
3924da2e3ebdSchin
3925da2e3ebdSchin if (!_error_infop_)
3926da2e3ebdSchin _error_infop_ = &_error_info_;
3927da2e3ebdSchin if (!_opt_infop_)
3928da2e3ebdSchin _opt_infop_ = &_opt_info_;
3929da2e3ebdSchin if (!opt_info.state)
3930da2e3ebdSchin opt_info.state = &state;
3931da2e3ebdSchin #endif
3932da2e3ebdSchin if (!oopts)
3933da2e3ebdSchin return 0;
3934da2e3ebdSchin opt_info.state->pindex = opt_info.index;
3935da2e3ebdSchin opt_info.state->poffset = opt_info.offset;
3936da2e3ebdSchin if (!opt_info.index)
3937da2e3ebdSchin {
3938da2e3ebdSchin opt_info.index = 1;
3939da2e3ebdSchin opt_info.offset = 0;
3940da2e3ebdSchin if (opt_info.state->npass)
3941da2e3ebdSchin {
3942da2e3ebdSchin opt_info.state->npass = 0;
3943da2e3ebdSchin opt_info.state->join = 0;
3944da2e3ebdSchin }
3945da2e3ebdSchin }
3946da2e3ebdSchin if (!argv)
3947da2e3ebdSchin cache = 0;
3948da2e3ebdSchin else
3949da2e3ebdSchin for (pcache = 0, cache = opt_info.state->cache; cache; pcache = cache, cache = cache->next)
3950da2e3ebdSchin if (cache->pass.oopts == (char*)oopts)
3951da2e3ebdSchin break;
3952da2e3ebdSchin if (cache)
3953da2e3ebdSchin {
3954da2e3ebdSchin if (pcache)
3955da2e3ebdSchin {
3956da2e3ebdSchin pcache->next = cache->next;
3957da2e3ebdSchin cache->next = opt_info.state->cache;
3958da2e3ebdSchin opt_info.state->cache = cache;
3959da2e3ebdSchin }
3960da2e3ebdSchin pass = &cache->pass;
3961da2e3ebdSchin opt_info.state->npass = -1;
3962da2e3ebdSchin }
3963da2e3ebdSchin else
3964da2e3ebdSchin {
3965da2e3ebdSchin if (!argv)
3966da2e3ebdSchin n = opt_info.state->npass ? opt_info.state->npass : 1;
3967da2e3ebdSchin else if ((n = opt_info.state->join - 1) < 0)
3968da2e3ebdSchin n = 0;
3969da2e3ebdSchin if (n >= opt_info.state->npass || opt_info.state->pass[n].oopts != (char*)oopts)
3970da2e3ebdSchin {
3971da2e3ebdSchin for (m = 0; m < opt_info.state->npass && opt_info.state->pass[m].oopts != (char*)oopts; m++);
3972da2e3ebdSchin if (m < opt_info.state->npass)
3973da2e3ebdSchin n = m;
3974da2e3ebdSchin else
3975da2e3ebdSchin {
3976da2e3ebdSchin if (n >= elementsof(opt_info.state->pass))
3977da2e3ebdSchin n = elementsof(opt_info.state->pass) - 1;
3978da2e3ebdSchin init((char*)oopts, &opt_info.state->pass[n]);
3979da2e3ebdSchin if (opt_info.state->npass <= n)
3980da2e3ebdSchin opt_info.state->npass = n + 1;
3981da2e3ebdSchin }
3982da2e3ebdSchin }
3983da2e3ebdSchin if (!argv)
3984da2e3ebdSchin return 0;
3985da2e3ebdSchin pass = &opt_info.state->pass[n];
3986da2e3ebdSchin }
3987da2e3ebdSchin opts = pass->opts;
3988da2e3ebdSchin prefix = pass->prefix;
3989da2e3ebdSchin version = pass->version;
3990*3e14f97fSRoger A. Faulkner id = pass->id;
3991da2e3ebdSchin if (!(xp = opt_info.state->xp) || (catalog = pass->catalog) && !X(catalog))
3992da2e3ebdSchin catalog = 0;
3993da2e3ebdSchin else /* if (!error_info.catalog) */
3994da2e3ebdSchin error_info.catalog = catalog;
3995da2e3ebdSchin again:
3996da2e3ebdSchin psp = 0;
3997da2e3ebdSchin
3998da2e3ebdSchin /*
3999da2e3ebdSchin * check if any options remain and determine if the
4000da2e3ebdSchin * next option is short or long
4001da2e3ebdSchin */
4002da2e3ebdSchin
4003da2e3ebdSchin opt_info.assignment = 0;
4004da2e3ebdSchin num = 1;
4005da2e3ebdSchin w = v = 0;
4006da2e3ebdSchin x = 0;
4007da2e3ebdSchin for (;;)
4008da2e3ebdSchin {
4009da2e3ebdSchin if (!opt_info.offset)
4010da2e3ebdSchin {
4011da2e3ebdSchin /*
4012da2e3ebdSchin * finished with the previous arg
4013da2e3ebdSchin */
4014da2e3ebdSchin
4015da2e3ebdSchin if (opt_info.index == 1 && opt_info.argv != opt_info.state->strv)
4016da2e3ebdSchin {
4017da2e3ebdSchin opt_info.argv = 0;
4018da2e3ebdSchin opt_info.state->argv[0] = 0;
4019da2e3ebdSchin if (argv[0] && (opt_info.state->argv[0] = save(argv[0])))
4020da2e3ebdSchin opt_info.argv = opt_info.state->argv;
4021da2e3ebdSchin opt_info.state->style = STYLE_short;
4022da2e3ebdSchin }
4023da2e3ebdSchin if (!(s = argv[opt_info.index]))
4024da2e3ebdSchin return 0;
4025da2e3ebdSchin if (!prefix)
4026da2e3ebdSchin {
4027da2e3ebdSchin /*
4028da2e3ebdSchin * long with no prefix (dd style)
4029da2e3ebdSchin */
4030da2e3ebdSchin
4031da2e3ebdSchin n = 2;
4032da2e3ebdSchin if ((c = *s) != '-' && c != '+')
4033da2e3ebdSchin c = '-';
4034da2e3ebdSchin else if (*++s == c)
4035da2e3ebdSchin {
4036da2e3ebdSchin if (!*++s)
4037da2e3ebdSchin {
4038da2e3ebdSchin opt_info.index++;
4039da2e3ebdSchin return 0;
4040da2e3ebdSchin }
40417c2fbfb3SApril Chin else if (*s == c)
40427c2fbfb3SApril Chin return 0;
4043da2e3ebdSchin }
4044da2e3ebdSchin else if (*s == '?')
4045da2e3ebdSchin n = 1;
4046da2e3ebdSchin }
40477c2fbfb3SApril Chin else if ((c = *s++) != '-' && (c != '+' || !(pass->flags & OPT_plus) && (!(pass->flags & OPT_numeric) || !isdigit(*s))))
4048da2e3ebdSchin {
4049da2e3ebdSchin if (!(pass->flags & OPT_old) || !isalpha(c))
4050da2e3ebdSchin return 0;
4051da2e3ebdSchin s--;
4052da2e3ebdSchin n = 1;
4053da2e3ebdSchin opt_info.offset--;
4054da2e3ebdSchin }
4055da2e3ebdSchin else if (*s == c)
4056da2e3ebdSchin {
4057da2e3ebdSchin if (!*++s)
4058da2e3ebdSchin {
4059da2e3ebdSchin /*
4060da2e3ebdSchin * -- or ++ end of options
4061da2e3ebdSchin */
4062da2e3ebdSchin
4063da2e3ebdSchin opt_info.index++;
4064da2e3ebdSchin return 0;
4065da2e3ebdSchin }
40667c2fbfb3SApril Chin else if (*s == c)
40677c2fbfb3SApril Chin {
40687c2fbfb3SApril Chin /*
40697c2fbfb3SApril Chin * ---* or +++* are operands
40707c2fbfb3SApril Chin */
40717c2fbfb3SApril Chin
40727c2fbfb3SApril Chin return 0;
40737c2fbfb3SApril Chin }
4074da2e3ebdSchin if (version || *s == '?' || !(pass->flags & OPT_minus))
4075da2e3ebdSchin {
4076da2e3ebdSchin /*
4077da2e3ebdSchin * long with double prefix
4078da2e3ebdSchin */
4079da2e3ebdSchin
4080da2e3ebdSchin n = 2;
4081da2e3ebdSchin }
4082da2e3ebdSchin else
4083da2e3ebdSchin {
4084da2e3ebdSchin /*
4085da2e3ebdSchin * short option char '-'
4086da2e3ebdSchin */
4087da2e3ebdSchin
4088da2e3ebdSchin s--;
4089da2e3ebdSchin n = 1;
4090da2e3ebdSchin }
4091da2e3ebdSchin }
4092da2e3ebdSchin else if (prefix == 1 && *s != '?')
4093da2e3ebdSchin {
4094da2e3ebdSchin /*
4095da2e3ebdSchin * long with single prefix (find style)
4096da2e3ebdSchin */
4097da2e3ebdSchin
4098da2e3ebdSchin n = 2;
4099da2e3ebdSchin }
4100da2e3ebdSchin else
4101da2e3ebdSchin {
4102da2e3ebdSchin /*
4103da2e3ebdSchin * short (always with single prefix)
4104da2e3ebdSchin */
4105da2e3ebdSchin
4106da2e3ebdSchin n = 1;
4107da2e3ebdSchin }
4108da2e3ebdSchin
4109da2e3ebdSchin /*
4110da2e3ebdSchin * just a prefix is an option (e.g., `-' == stdin)
4111da2e3ebdSchin */
4112da2e3ebdSchin
4113da2e3ebdSchin if (!*s)
4114da2e3ebdSchin return 0;
4115da2e3ebdSchin if (c == '+')
4116da2e3ebdSchin opt_info.arg = 0;
411734f9b3eeSRoland Mainz message((-2, "c='%c' n=%d", c, n));
4118da2e3ebdSchin if (n == 2)
4119da2e3ebdSchin {
4120da2e3ebdSchin x = 0;
4121da2e3ebdSchin opt_info.state->style = STYLE_long;
4122da2e3ebdSchin opt_info.option[0] = opt_info.name[0] = opt_info.name[1] = c;
4123da2e3ebdSchin w = &opt_info.name[prefix];
4124da2e3ebdSchin if ((*s == 'n' || *s == 'N') && (*(s + 1) == 'o' || *(s + 1) == 'O') && *(s + 2) && *(s + 2) != '=')
4125da2e3ebdSchin no = *(s + 2) == '-' ? 3 : 2;
4126da2e3ebdSchin else
4127da2e3ebdSchin no = 0;
4128da2e3ebdSchin for (c = *s; *s; s++)
4129da2e3ebdSchin {
4130da2e3ebdSchin if (*s == '=')
4131da2e3ebdSchin {
4132da2e3ebdSchin if (*(s + 1) == '=')
4133da2e3ebdSchin s++;
4134da2e3ebdSchin if (!isalnum(*(s - 1)) && *(w - 1) == (opt_info.assignment = *(s - 1)))
4135da2e3ebdSchin w--;
4136da2e3ebdSchin v = ++s;
4137da2e3ebdSchin break;
4138da2e3ebdSchin }
4139da2e3ebdSchin if (w < &opt_info.name[elementsof(opt_info.name) - 1] && *s != ':' && *s != '|' && *s != '[' && *s != ']')
4140da2e3ebdSchin *w++ = *s;
4141da2e3ebdSchin }
4142da2e3ebdSchin *w = 0;
4143da2e3ebdSchin w = &opt_info.name[prefix];
4144da2e3ebdSchin c = *w;
4145da2e3ebdSchin opt_info.offset = 0;
4146da2e3ebdSchin opt_info.index++;
4147da2e3ebdSchin break;
4148da2e3ebdSchin }
4149da2e3ebdSchin opt_info.offset++;
4150da2e3ebdSchin }
4151da2e3ebdSchin if (!argv[opt_info.index])
4152da2e3ebdSchin return 0;
4153da2e3ebdSchin if (c = argv[opt_info.index][opt_info.offset++])
4154da2e3ebdSchin {
4155da2e3ebdSchin if ((k = argv[opt_info.index][0]) != '-' && k != '+')
4156da2e3ebdSchin k = '-';
4157da2e3ebdSchin opt_info.option[0] = opt_info.name[0] = k;
4158da2e3ebdSchin opt_info.option[1] = opt_info.name[1] = c;
4159da2e3ebdSchin opt_info.option[2] = opt_info.name[2] = 0;
4160da2e3ebdSchin break;
4161da2e3ebdSchin }
4162da2e3ebdSchin opt_info.offset = 0;
4163da2e3ebdSchin opt_info.index++;
4164da2e3ebdSchin }
4165da2e3ebdSchin
4166da2e3ebdSchin /*
4167da2e3ebdSchin * at this point:
4168da2e3ebdSchin *
4169da2e3ebdSchin * c the first character of the option
4170da2e3ebdSchin * w long option name if != 0, otherwise short
4171da2e3ebdSchin * v long option value (via =) if w != 0
4172da2e3ebdSchin */
4173da2e3ebdSchin
4174da2e3ebdSchin if (c == '?')
4175da2e3ebdSchin {
4176da2e3ebdSchin /*
4177da2e3ebdSchin * ? always triggers internal help
4178da2e3ebdSchin */
4179da2e3ebdSchin
4180da2e3ebdSchin if (w && !v && (*(w + 1) || !(v = argv[opt_info.index]) || !++opt_info.index))
4181da2e3ebdSchin v = w + 1;
4182da2e3ebdSchin opt_info.option[1] = c;
4183da2e3ebdSchin opt_info.option[2] = 0;
4184da2e3ebdSchin if (!w)
4185da2e3ebdSchin {
4186da2e3ebdSchin opt_info.name[1] = c;
4187da2e3ebdSchin opt_info.name[2] = 0;
4188da2e3ebdSchin }
4189da2e3ebdSchin goto help;
4190da2e3ebdSchin }
4191da2e3ebdSchin numopt = 0;
4192da2e3ebdSchin f = 0;
4193da2e3ebdSchin s = opts;
4194da2e3ebdSchin
4195da2e3ebdSchin /*
4196da2e3ebdSchin * no option can start with these characters
4197da2e3ebdSchin */
4198da2e3ebdSchin
4199da2e3ebdSchin if (c == ':' || c == '#' || c == ' ' || c == '[' || c == ']')
4200da2e3ebdSchin {
4201da2e3ebdSchin if (c != *s)
4202da2e3ebdSchin s = "";
4203da2e3ebdSchin }
4204da2e3ebdSchin else
4205da2e3ebdSchin {
4206da2e3ebdSchin a = 0;
4207da2e3ebdSchin if (!w && (pass->flags & OPT_cache))
4208da2e3ebdSchin {
4209da2e3ebdSchin if (cache)
4210da2e3ebdSchin {
4211da2e3ebdSchin if (k = cache->flags[map[c]])
4212da2e3ebdSchin {
4213da2e3ebdSchin opt_info.arg = 0;
4214da2e3ebdSchin
4215da2e3ebdSchin /*
4216da2e3ebdSchin * this is a ksh getopts workaround
4217da2e3ebdSchin */
4218da2e3ebdSchin
4219da2e3ebdSchin if (opt_info.num != LONG_MIN)
422034f9b3eeSRoland Mainz opt_info.num = (long)(opt_info.number = !(k & OPT_cache_invert));
4221da2e3ebdSchin if (!(k & (OPT_cache_string|OPT_cache_numeric)))
4222da2e3ebdSchin return c;
4223da2e3ebdSchin if (*(opt_info.arg = &argv[opt_info.index++][opt_info.offset]))
4224da2e3ebdSchin {
4225da2e3ebdSchin if (!(k & OPT_cache_numeric))
4226da2e3ebdSchin {
4227da2e3ebdSchin opt_info.offset = 0;
4228da2e3ebdSchin return c;
4229da2e3ebdSchin }
4230da2e3ebdSchin opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
4231da2e3ebdSchin if (err || e == opt_info.arg)
4232da2e3ebdSchin {
4233da2e3ebdSchin if (!err && (k & OPT_cache_optional))
4234da2e3ebdSchin {
4235da2e3ebdSchin opt_info.arg = 0;
4236da2e3ebdSchin opt_info.index--;
4237da2e3ebdSchin return c;
4238da2e3ebdSchin }
4239da2e3ebdSchin }
4240da2e3ebdSchin else if (*e)
4241da2e3ebdSchin {
4242da2e3ebdSchin opt_info.offset += e - opt_info.arg;
4243da2e3ebdSchin opt_info.index--;
4244da2e3ebdSchin return c;
4245da2e3ebdSchin }
4246da2e3ebdSchin else
4247da2e3ebdSchin {
4248da2e3ebdSchin opt_info.offset = 0;
4249da2e3ebdSchin return c;
4250da2e3ebdSchin }
4251da2e3ebdSchin }
4252da2e3ebdSchin else if (opt_info.arg = argv[opt_info.index])
4253da2e3ebdSchin {
4254da2e3ebdSchin opt_info.index++;
4255da2e3ebdSchin if ((k & OPT_cache_optional) && (*opt_info.arg == '-' || (pass->flags & OPT_plus) && *opt_info.arg == '+') && *(opt_info.arg + 1))
4256da2e3ebdSchin {
4257da2e3ebdSchin opt_info.arg = 0;
4258da2e3ebdSchin opt_info.index--;
4259da2e3ebdSchin opt_info.offset = 0;
4260da2e3ebdSchin return c;
4261da2e3ebdSchin }
4262da2e3ebdSchin if (k & OPT_cache_string)
4263da2e3ebdSchin {
4264da2e3ebdSchin opt_info.offset = 0;
4265da2e3ebdSchin return c;
4266da2e3ebdSchin }
4267da2e3ebdSchin opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
4268da2e3ebdSchin if (!err)
4269da2e3ebdSchin {
4270da2e3ebdSchin if (!*e)
4271da2e3ebdSchin {
4272da2e3ebdSchin opt_info.offset = 0;
4273da2e3ebdSchin return c;
4274da2e3ebdSchin }
4275da2e3ebdSchin if (k & OPT_cache_optional)
4276da2e3ebdSchin {
4277da2e3ebdSchin opt_info.arg = 0;
4278da2e3ebdSchin opt_info.index--;
4279da2e3ebdSchin opt_info.offset = 0;
4280da2e3ebdSchin return c;
4281da2e3ebdSchin }
4282da2e3ebdSchin }
4283da2e3ebdSchin }
4284da2e3ebdSchin else if (k & OPT_cache_optional)
4285da2e3ebdSchin {
4286da2e3ebdSchin opt_info.offset = 0;
4287da2e3ebdSchin return c;
4288da2e3ebdSchin }
4289da2e3ebdSchin opt_info.index--;
4290da2e3ebdSchin }
4291da2e3ebdSchin cache = 0;
4292da2e3ebdSchin }
4293da2e3ebdSchin else if (cache = newof(0, Optcache_t, 1, 0))
4294da2e3ebdSchin {
4295da2e3ebdSchin cache->caching = c;
4296da2e3ebdSchin c = 0;
4297da2e3ebdSchin cache->pass = *pass;
4298da2e3ebdSchin cache->next = opt_info.state->cache;
4299da2e3ebdSchin opt_info.state->cache = cache;
4300da2e3ebdSchin }
4301da2e3ebdSchin }
4302da2e3ebdSchin else
4303da2e3ebdSchin cache = 0;
4304da2e3ebdSchin for (;;)
4305da2e3ebdSchin {
4306da2e3ebdSchin if (!(*(s = next(s, version))) || *s == '\n' || *s == ' ')
4307da2e3ebdSchin {
4308da2e3ebdSchin if (!(tsp = psp))
4309da2e3ebdSchin {
4310da2e3ebdSchin if (cache)
4311da2e3ebdSchin {
4312da2e3ebdSchin /*
4313da2e3ebdSchin * the first loop pass
4314da2e3ebdSchin * initialized the cache
4315da2e3ebdSchin * so one more pass to
4316da2e3ebdSchin * check the cache or
4317da2e3ebdSchin * bail for a full scan
4318da2e3ebdSchin */
4319da2e3ebdSchin
4320da2e3ebdSchin cache->flags[0] = 0;
4321da2e3ebdSchin c = cache->caching;
4322da2e3ebdSchin cache->caching = 0;
4323da2e3ebdSchin cache = 0;
4324da2e3ebdSchin s = opts;
4325da2e3ebdSchin continue;
4326da2e3ebdSchin }
4327da2e3ebdSchin if (!x && catalog)
4328da2e3ebdSchin {
4329da2e3ebdSchin /*
4330da2e3ebdSchin * the first loop pass
4331da2e3ebdSchin * translated long
4332da2e3ebdSchin * options and there
4333da2e3ebdSchin * were no matches so
4334da2e3ebdSchin * one more pass for C
4335da2e3ebdSchin * locale
4336da2e3ebdSchin */
4337da2e3ebdSchin
4338da2e3ebdSchin catalog = 0;
4339da2e3ebdSchin s = opts;
4340da2e3ebdSchin continue;
4341da2e3ebdSchin }
4342da2e3ebdSchin s = "";
4343da2e3ebdSchin break;
4344da2e3ebdSchin }
4345da2e3ebdSchin s = psp->ob;
4346da2e3ebdSchin psp = psp->next;
4347da2e3ebdSchin free(tsp);
4348da2e3ebdSchin continue;
4349da2e3ebdSchin }
4350da2e3ebdSchin if (*s == '\f')
4351da2e3ebdSchin {
4352*3e14f97fSRoger A. Faulkner psp = info(psp, s + 1, NiL, opt_info.state->xp, id);
4353da2e3ebdSchin if (psp->nb)
4354da2e3ebdSchin s = psp->nb;
4355da2e3ebdSchin else
4356da2e3ebdSchin {
4357da2e3ebdSchin s = psp->ob;
4358da2e3ebdSchin psp = psp->next;
4359da2e3ebdSchin }
4360da2e3ebdSchin continue;
4361da2e3ebdSchin }
436234f9b3eeSRoland Mainz message((-20, "optget: opt %s c %c w %s num %ld", show(s), c, w, num));
4363da2e3ebdSchin if (*s == c && !w)
4364da2e3ebdSchin break;
4365da2e3ebdSchin else if (*s == '[')
4366da2e3ebdSchin {
4367da2e3ebdSchin f = s = next(s + 1, version);
4368da2e3ebdSchin k = *f;
4369da2e3ebdSchin if (k == '+' || k == '-')
4370da2e3ebdSchin /* ignore */;
4371da2e3ebdSchin else if (k == '[' || version < 1)
4372da2e3ebdSchin continue;
4373da2e3ebdSchin else if (w && !cache)
4374da2e3ebdSchin {
4375da2e3ebdSchin nov = no;
4376da2e3ebdSchin if (*(s + 1) == '\f' && (vp = opt_info.state->vp))
4377da2e3ebdSchin {
4378da2e3ebdSchin sfputc(vp, k);
4379*3e14f97fSRoger A. Faulkner s = expand(s + 2, NiL, &t, vp, id);
4380da2e3ebdSchin if (*s)
4381da2e3ebdSchin *(f = s - 1) = k;
4382da2e3ebdSchin else
4383da2e3ebdSchin {
4384da2e3ebdSchin f = sfstrbase(vp);
4385da2e3ebdSchin if (s = strrchr(f, ':'))
4386da2e3ebdSchin f = s - 1;
4387da2e3ebdSchin else
4388da2e3ebdSchin s = f + 1;
4389da2e3ebdSchin }
4390da2e3ebdSchin }
4391da2e3ebdSchin else
4392da2e3ebdSchin t = 0;
4393da2e3ebdSchin if (*s != ':')
4394da2e3ebdSchin s = skip(s, ':', '?', 0, 1, 0, 0, version);
4395da2e3ebdSchin if (*s == ':')
4396da2e3ebdSchin {
4397da2e3ebdSchin if (catalog)
4398da2e3ebdSchin {
4399da2e3ebdSchin p = skip(s + 1, '?', 0, 0, 1, 0, 0, version);
4400da2e3ebdSchin e = sfprints("%-.*s", p - (s + 1), s + 1);
4401*3e14f97fSRoger A. Faulkner g = T(id, catalog, e);
4402da2e3ebdSchin if (g == e)
4403da2e3ebdSchin p = 0;
4404da2e3ebdSchin else
4405da2e3ebdSchin {
4406da2e3ebdSchin sfprintf(xp, ":%s|%s?", g, e);
4407da2e3ebdSchin if (!(s = sfstruse(xp)))
4408da2e3ebdSchin goto nospace;
4409da2e3ebdSchin }
4410da2e3ebdSchin }
4411da2e3ebdSchin else
4412da2e3ebdSchin p = 0;
4413da2e3ebdSchin y = w;
4414da2e3ebdSchin for (;;)
4415da2e3ebdSchin {
4416da2e3ebdSchin n = m = 0;
4417da2e3ebdSchin e = s + 1;
4418da2e3ebdSchin while (*++s)
4419da2e3ebdSchin {
4420da2e3ebdSchin if (*s == '*' || *s == '\a')
4421da2e3ebdSchin {
4422da2e3ebdSchin if (*s == '\a')
4423da2e3ebdSchin do
4424da2e3ebdSchin {
4425da2e3ebdSchin if (!*++s)
4426da2e3ebdSchin {
4427da2e3ebdSchin s--;
4428da2e3ebdSchin break;
4429da2e3ebdSchin }
4430da2e3ebdSchin } while (*s != '\a');
4431da2e3ebdSchin j = *(s + 1);
4432da2e3ebdSchin if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
4433da2e3ebdSchin {
4434da2e3ebdSchin while (*w)
4435da2e3ebdSchin w++;
4436da2e3ebdSchin m = 0;
4437da2e3ebdSchin break;
4438da2e3ebdSchin }
4439da2e3ebdSchin m = 1;
4440da2e3ebdSchin }
4441da2e3ebdSchin else if (*s == *w || sep(*s) && sep(*w))
4442da2e3ebdSchin w++;
4443da2e3ebdSchin else if (*w == 0)
4444da2e3ebdSchin break;
4445da2e3ebdSchin else if (!sep(*s))
4446da2e3ebdSchin {
4447da2e3ebdSchin if (sep(*w))
4448da2e3ebdSchin {
4449da2e3ebdSchin if (*++w == *s)
4450da2e3ebdSchin {
4451da2e3ebdSchin w++;
4452da2e3ebdSchin continue;
4453da2e3ebdSchin }
4454da2e3ebdSchin }
4455da2e3ebdSchin else if (w == y || sep(*(w - 1)) || isupper(*(w - 1)) && islower(*w))
4456da2e3ebdSchin break;
4457da2e3ebdSchin for (q = s; *q && !sep(*q) && *q != '|' && *q != '?' && *q != ']'; q++);
4458da2e3ebdSchin if (!sep(*q))
4459da2e3ebdSchin break;
4460da2e3ebdSchin for (s = q; w > y && *w != *(s + 1); w--);
4461da2e3ebdSchin }
4462da2e3ebdSchin else if (*w != *(s + 1))
4463da2e3ebdSchin break;
4464da2e3ebdSchin }
4465da2e3ebdSchin if (!*w)
4466da2e3ebdSchin {
4467da2e3ebdSchin nov = 0;
4468da2e3ebdSchin break;
4469da2e3ebdSchin }
4470da2e3ebdSchin if (n = no)
4471da2e3ebdSchin {
4472da2e3ebdSchin m = 0;
4473da2e3ebdSchin s = e - 1;
4474da2e3ebdSchin w = y + n;
4475da2e3ebdSchin while (*++s)
4476da2e3ebdSchin {
4477da2e3ebdSchin if (*s == '*' || *s == '\a')
4478da2e3ebdSchin {
4479da2e3ebdSchin if (*s == '\a')
4480da2e3ebdSchin do
4481da2e3ebdSchin {
4482da2e3ebdSchin if (!*++s)
4483da2e3ebdSchin {
4484da2e3ebdSchin s--;
4485da2e3ebdSchin break;
4486da2e3ebdSchin }
4487da2e3ebdSchin } while (*s != '\a');
4488da2e3ebdSchin j = *(s + 1);
4489da2e3ebdSchin if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
4490da2e3ebdSchin {
4491da2e3ebdSchin while (*w)
4492da2e3ebdSchin w++;
4493da2e3ebdSchin m = 0;
4494da2e3ebdSchin break;
4495da2e3ebdSchin }
4496da2e3ebdSchin m = 1;
4497da2e3ebdSchin }
4498da2e3ebdSchin else if (*s == *w || sep(*s) && sep(*w))
4499da2e3ebdSchin w++;
4500da2e3ebdSchin else if (*w == 0)
4501da2e3ebdSchin break;
4502da2e3ebdSchin else if (!sep(*s))
4503da2e3ebdSchin {
4504da2e3ebdSchin if (sep(*w))
4505da2e3ebdSchin {
4506da2e3ebdSchin if (*++w == *s)
4507da2e3ebdSchin {
4508da2e3ebdSchin w++;
4509da2e3ebdSchin continue;
4510da2e3ebdSchin }
4511da2e3ebdSchin }
4512da2e3ebdSchin else if (w == y || sep(*(w - 1)) || isupper(*(w - 1)) && islower(*w))
4513da2e3ebdSchin break;
4514da2e3ebdSchin for (q = s; *q && !sep(*q) && *q != '|' && *q != '?' && *q != ']'; q++);
4515da2e3ebdSchin if (!sep(*q))
4516da2e3ebdSchin break;
4517da2e3ebdSchin for (s = q; w > y && *w != *(s + 1); w--);
4518da2e3ebdSchin }
4519da2e3ebdSchin else if (*w != *(s + 1))
4520da2e3ebdSchin break;
4521da2e3ebdSchin }
4522da2e3ebdSchin if (!*w)
4523da2e3ebdSchin break;
4524da2e3ebdSchin }
4525da2e3ebdSchin if (*(s = skip(s, ':', '|', '?', 1, 0, 0, version)) != '|')
4526da2e3ebdSchin break;
4527da2e3ebdSchin w = y;
4528da2e3ebdSchin }
4529da2e3ebdSchin if (p)
4530da2e3ebdSchin s = p;
4531da2e3ebdSchin if (!*w)
4532da2e3ebdSchin {
4533da2e3ebdSchin if (n)
4534da2e3ebdSchin num = 0;
4535da2e3ebdSchin if (!(n = (m || *s == ':' || *s == '|' || *s == '?' || *s == ']' || *s == 0)) && x)
4536da2e3ebdSchin {
4537da2e3ebdSchin psp = pop(psp);
4538*3e14f97fSRoger A. Faulkner return opterror("?", 0, version, id, catalog);
4539da2e3ebdSchin }
4540da2e3ebdSchin for (x = k; *(f + 1) == '|' && (j = *(f + 2)) && j != '!' && j != '=' && j != ':' && j != '?' && j != ']'; f += 2);
4541da2e3ebdSchin if (*f == ':')
4542da2e3ebdSchin {
4543da2e3ebdSchin x = -1;
4544da2e3ebdSchin opt_info.option[1] = '-';
4545da2e3ebdSchin opt_info.option[2] = 0;
4546da2e3ebdSchin }
4547da2e3ebdSchin else if (*(f + 1) == ':' || *(f + 1) == '!' && *(f + 2) == ':')
4548da2e3ebdSchin {
4549da2e3ebdSchin opt_info.option[1] = x;
4550da2e3ebdSchin opt_info.option[2] = 0;
4551da2e3ebdSchin }
4552da2e3ebdSchin else
4553da2e3ebdSchin {
4554da2e3ebdSchin a = f;
4555da2e3ebdSchin if (*a == '=')
4556da2e3ebdSchin a++;
4557da2e3ebdSchin else
4558da2e3ebdSchin {
4559da2e3ebdSchin if (*(a + 1) == '!')
4560da2e3ebdSchin a++;
4561da2e3ebdSchin if (*(a + 1) == '=')
4562da2e3ebdSchin a += 2;
4563da2e3ebdSchin }
4564da2e3ebdSchin x = -strtol(a, &b, 0);
4565da2e3ebdSchin if ((b - a) > sizeof(opt_info.option) - 2)
4566da2e3ebdSchin b = a + sizeof(opt_info.option) - 2;
4567da2e3ebdSchin memcpy(&opt_info.option[1], a, b - a);
4568da2e3ebdSchin opt_info.option[b - a + 1] = 0;
4569da2e3ebdSchin }
4570da2e3ebdSchin b = e;
4571da2e3ebdSchin if (t)
4572da2e3ebdSchin {
4573da2e3ebdSchin s = t;
4574da2e3ebdSchin t = 0;
4575da2e3ebdSchin }
4576da2e3ebdSchin a = s = skip(s, 0, 0, 0, 1, 0, 0, version);
4577da2e3ebdSchin if (n)
4578da2e3ebdSchin {
4579da2e3ebdSchin w = y;
4580da2e3ebdSchin break;
4581da2e3ebdSchin }
4582da2e3ebdSchin }
4583da2e3ebdSchin w = y;
4584da2e3ebdSchin }
4585da2e3ebdSchin else if (k == c && prefix == 1)
4586da2e3ebdSchin {
4587da2e3ebdSchin w = 0;
4588da2e3ebdSchin opt_info.name[1] = c;
4589da2e3ebdSchin opt_info.name[2] = 0;
4590da2e3ebdSchin opt_info.offset = 2;
4591da2e3ebdSchin opt_info.index--;
4592da2e3ebdSchin break;
4593da2e3ebdSchin }
4594da2e3ebdSchin if (t)
4595da2e3ebdSchin {
4596da2e3ebdSchin s = t;
4597da2e3ebdSchin if (a)
4598da2e3ebdSchin a = t;
4599da2e3ebdSchin }
4600da2e3ebdSchin }
4601da2e3ebdSchin s = skip(s, 0, 0, 0, 1, 0, 1, version);
4602da2e3ebdSchin if (*s == GO)
4603da2e3ebdSchin s = skip(s + 1, 0, 0, 0, 0, 1, 1, version);
4604da2e3ebdSchin if (cache)
4605da2e3ebdSchin {
4606da2e3ebdSchin m = OPT_cache_flag;
4607da2e3ebdSchin v = s;
4608da2e3ebdSchin if (*v == '#')
4609da2e3ebdSchin {
4610da2e3ebdSchin v++;
4611da2e3ebdSchin m |= OPT_cache_numeric;
4612da2e3ebdSchin }
4613da2e3ebdSchin else if (*v == ':')
4614da2e3ebdSchin {
4615da2e3ebdSchin v++;
4616da2e3ebdSchin m |= OPT_cache_string;
4617da2e3ebdSchin }
4618da2e3ebdSchin if (*v == '?')
4619da2e3ebdSchin {
4620da2e3ebdSchin v++;
4621da2e3ebdSchin m |= OPT_cache_optional;
4622da2e3ebdSchin }
4623da2e3ebdSchin else if (*v == *(v - 1))
4624da2e3ebdSchin v++;
4625da2e3ebdSchin if (*(v = next(v, version)) == '[')
4626da2e3ebdSchin v = skip(v + 1, 0, 0, 0, 1, 0, 1, version);
4627da2e3ebdSchin if (*v != GO)
4628da2e3ebdSchin {
4629da2e3ebdSchin v = f;
4630da2e3ebdSchin for (;;)
4631da2e3ebdSchin {
4632da2e3ebdSchin if (isdigit(*f) && isdigit(*(f + 1)))
4633da2e3ebdSchin while (isdigit(*(f + 1)))
4634da2e3ebdSchin f++;
4635da2e3ebdSchin else if (*(f + 1) == '=')
4636da2e3ebdSchin break;
4637da2e3ebdSchin else
4638da2e3ebdSchin cache->flags[map[*f]] = m;
4639da2e3ebdSchin j = 0;
4640da2e3ebdSchin while (*(f + 1) == '|')
4641da2e3ebdSchin {
4642da2e3ebdSchin f += 2;
4643da2e3ebdSchin if (!(j = *f) || j == '!' || j == '=' || j == ':' || j == '?' || j == ']')
4644da2e3ebdSchin break;
4645da2e3ebdSchin cache->flags[map[j]] = m;
4646da2e3ebdSchin }
4647da2e3ebdSchin if (j != '!' || (m & OPT_cache_invert))
4648da2e3ebdSchin break;
4649da2e3ebdSchin f = v;
4650da2e3ebdSchin m |= OPT_cache_invert;
4651da2e3ebdSchin }
4652da2e3ebdSchin }
4653da2e3ebdSchin }
4654da2e3ebdSchin else
4655da2e3ebdSchin {
4656da2e3ebdSchin m = 0;
4657da2e3ebdSchin if (!w)
4658da2e3ebdSchin {
4659da2e3ebdSchin if (isdigit(*f) && isdigit(*(f + 1)))
4660da2e3ebdSchin k = -1;
4661da2e3ebdSchin if (c == k)
4662da2e3ebdSchin m = 1;
4663da2e3ebdSchin while (*(f + 1) == '|')
4664da2e3ebdSchin {
4665da2e3ebdSchin f += 2;
4666da2e3ebdSchin if (!(j = *f))
4667da2e3ebdSchin {
4668da2e3ebdSchin m = 0;
4669da2e3ebdSchin break;
4670da2e3ebdSchin }
4671da2e3ebdSchin else if (j == c)
4672da2e3ebdSchin m = 1;
4673da2e3ebdSchin else if (j == '!' || j == '=' || j == ':' || j == '?' || j == ']')
4674da2e3ebdSchin break;
4675da2e3ebdSchin }
4676da2e3ebdSchin }
4677da2e3ebdSchin if (m)
4678da2e3ebdSchin {
4679da2e3ebdSchin s--;
4680da2e3ebdSchin if (*++f == '!')
4681da2e3ebdSchin {
4682da2e3ebdSchin f++;
4683da2e3ebdSchin num = 0;
4684da2e3ebdSchin }
4685da2e3ebdSchin if (*f == '=')
4686da2e3ebdSchin {
4687da2e3ebdSchin c = -strtol(++f, &b, 0);
4688da2e3ebdSchin if ((b - f) > sizeof(opt_info.option) - 2)
4689da2e3ebdSchin b = f + sizeof(opt_info.option) - 2;
4690da2e3ebdSchin memcpy(&opt_info.option[1], f, b - f);
4691da2e3ebdSchin opt_info.option[b - f + 1] = 0;
4692da2e3ebdSchin }
4693da2e3ebdSchin else
4694da2e3ebdSchin c = k;
4695da2e3ebdSchin break;
4696da2e3ebdSchin }
4697da2e3ebdSchin }
4698da2e3ebdSchin if (*s == '#')
4699da2e3ebdSchin {
4700da2e3ebdSchin if (!numopt && s > opts)
4701da2e3ebdSchin {
4702da2e3ebdSchin numopt = s - 1;
4703da2e3ebdSchin numchr = k;
4704da2e3ebdSchin if (*f == ':')
4705da2e3ebdSchin numchr = -1;
4706da2e3ebdSchin else if (*(f + 1) != ':' && *(f + 1) != '!' && *(f + 1) != ']')
4707da2e3ebdSchin {
4708da2e3ebdSchin a = f;
4709da2e3ebdSchin if (*a == '=')
4710da2e3ebdSchin a++;
4711da2e3ebdSchin else
4712da2e3ebdSchin {
4713da2e3ebdSchin if (*(a + 1) == '!')
4714da2e3ebdSchin a++;
4715da2e3ebdSchin if (*(a + 1) == '=')
4716da2e3ebdSchin a += 2;
4717da2e3ebdSchin }
4718da2e3ebdSchin numchr = -strtol(a, NiL, 0);
4719da2e3ebdSchin }
4720da2e3ebdSchin }
4721da2e3ebdSchin }
4722da2e3ebdSchin else if (*s != ':')
4723da2e3ebdSchin continue;
4724da2e3ebdSchin }
4725da2e3ebdSchin else if (*s == ']')
4726da2e3ebdSchin {
4727da2e3ebdSchin s++;
4728da2e3ebdSchin continue;
4729da2e3ebdSchin }
4730da2e3ebdSchin else if (*s == '#')
4731da2e3ebdSchin {
4732da2e3ebdSchin if (!numopt && s > opts)
4733da2e3ebdSchin numchr = *(numopt = s - 1);
4734da2e3ebdSchin }
4735da2e3ebdSchin else if (*s != ':')
4736da2e3ebdSchin {
4737da2e3ebdSchin if (cache)
4738da2e3ebdSchin {
4739da2e3ebdSchin m = OPT_cache_flag;
4740da2e3ebdSchin if (*(s + 1) == '#')
4741da2e3ebdSchin {
4742da2e3ebdSchin m |= OPT_cache_numeric;
4743da2e3ebdSchin if (*(s + 2) == '?')
4744da2e3ebdSchin m |= OPT_cache_optional;
4745da2e3ebdSchin }
4746da2e3ebdSchin else if (*(s + 1) == ':')
4747da2e3ebdSchin {
4748da2e3ebdSchin m |= OPT_cache_string;
4749da2e3ebdSchin if (*(s + 2) == '?')
4750da2e3ebdSchin m |= OPT_cache_optional;
4751da2e3ebdSchin }
4752da2e3ebdSchin cache->flags[map[*s]] = m;
4753da2e3ebdSchin }
4754da2e3ebdSchin s++;
4755da2e3ebdSchin continue;
4756da2e3ebdSchin }
4757da2e3ebdSchin message((-21, "optget: opt %s", show(s)));
4758da2e3ebdSchin if (*++s == '?' || *s == *(s - 1))
4759da2e3ebdSchin s++;
4760da2e3ebdSchin if (*(s = next(s, version)) == '[')
4761da2e3ebdSchin {
4762da2e3ebdSchin s = skip(s + 1, 0, 0, 0, 1, 0, 1, version);
4763da2e3ebdSchin if (*s == GO)
4764da2e3ebdSchin s = skip(s + 1, 0, 0, 0, 0, 1, 1, version);
4765da2e3ebdSchin }
476634f9b3eeSRoland Mainz message((-21, "optget: opt %s", show(s)));
4767da2e3ebdSchin }
4768da2e3ebdSchin if (w && x)
4769da2e3ebdSchin {
4770da2e3ebdSchin s = skip(b, '|', '?', 0, 1, 0, 0, version);
4771da2e3ebdSchin if (v && (a == 0 || *a == 0 || *(a + 1) != ':' && *(a + 1) != '#') && (*v == '0' || *v == '1') && !*(v + 1))
4772da2e3ebdSchin {
4773da2e3ebdSchin if (*v == '0')
4774da2e3ebdSchin num = !num;
4775da2e3ebdSchin v = 0;
4776da2e3ebdSchin }
4777da2e3ebdSchin if ((s - b) >= elementsof(opt_info.name))
4778da2e3ebdSchin s = b + elementsof(opt_info.name) - 1;
4779da2e3ebdSchin for (;;)
4780da2e3ebdSchin {
4781da2e3ebdSchin if (b >= s)
4782da2e3ebdSchin {
4783da2e3ebdSchin *w = 0;
4784da2e3ebdSchin break;
4785da2e3ebdSchin }
4786da2e3ebdSchin if (*b == '*')
4787da2e3ebdSchin break;
4788da2e3ebdSchin *w++ = *b++;
4789da2e3ebdSchin }
4790da2e3ebdSchin if (!num && v)
4791*3e14f97fSRoger A. Faulkner return opterror(no ? "!" : "=", 0, version, id, catalog);
4792da2e3ebdSchin w = &opt_info.name[prefix];
4793da2e3ebdSchin c = x;
4794da2e3ebdSchin s = a;
4795da2e3ebdSchin }
4796da2e3ebdSchin }
4797da2e3ebdSchin if (!*s)
4798da2e3ebdSchin {
4799da2e3ebdSchin if (w)
4800da2e3ebdSchin {
4801da2e3ebdSchin if (hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), w))
4802da2e3ebdSchin {
4803da2e3ebdSchin if (!v)
4804da2e3ebdSchin v = (char*)hp->name;
4805da2e3ebdSchin goto help;
4806da2e3ebdSchin }
4807da2e3ebdSchin if (!v)
4808da2e3ebdSchin {
4809da2e3ebdSchin v = opt_info.name;
4810da2e3ebdSchin goto help;
4811da2e3ebdSchin }
4812da2e3ebdSchin }
48137c2fbfb3SApril Chin if (w || !isdigit(c) || !numopt || !(pass->flags & OPT_numeric))
4814da2e3ebdSchin {
4815da2e3ebdSchin pop(psp);
4816*3e14f97fSRoger A. Faulkner return opterror("", 0, version, id, catalog);
4817da2e3ebdSchin }
4818da2e3ebdSchin s = numopt;
4819da2e3ebdSchin c = opt_info.option[1] = numchr;
4820da2e3ebdSchin opt_info.offset--;
4821da2e3ebdSchin }
4822da2e3ebdSchin opt_info.arg = 0;
4823da2e3ebdSchin
4824da2e3ebdSchin /*
4825da2e3ebdSchin * this is a ksh getopts workaround
4826da2e3ebdSchin */
4827da2e3ebdSchin
4828da2e3ebdSchin if (opt_info.num != LONG_MIN)
482934f9b3eeSRoland Mainz opt_info.num = (long)(opt_info.number = num);
4830da2e3ebdSchin if ((n = *++s == '#') || *s == ':' || w && !nov && v && (optnumber(v, &e, NiL), n = !*e))
4831da2e3ebdSchin {
4832da2e3ebdSchin if (w)
4833da2e3ebdSchin {
4834da2e3ebdSchin if (nov)
4835da2e3ebdSchin {
4836da2e3ebdSchin if (v)
4837da2e3ebdSchin {
4838da2e3ebdSchin pop(psp);
4839*3e14f97fSRoger A. Faulkner return opterror("!", 0, version, id, catalog);
4840da2e3ebdSchin }
484134f9b3eeSRoland Mainz opt_info.num = (long)(opt_info.number = 0);
4842da2e3ebdSchin }
4843da2e3ebdSchin else
4844da2e3ebdSchin {
4845da2e3ebdSchin if (!v && *(s + 1) != '?' && (v = argv[opt_info.index]))
4846da2e3ebdSchin {
4847da2e3ebdSchin opt_info.index++;
4848da2e3ebdSchin opt_info.offset = 0;
4849da2e3ebdSchin }
4850da2e3ebdSchin if (!(opt_info.arg = v) || (*v == '0' || *v == '1') && !*(v + 1))
4851da2e3ebdSchin {
4852da2e3ebdSchin if (*(s + 1) != '?')
4853da2e3ebdSchin {
4854da2e3ebdSchin if (!opt_info.arg)
4855da2e3ebdSchin {
4856da2e3ebdSchin pop(psp);
4857*3e14f97fSRoger A. Faulkner return opterror(s, 0, version, id, catalog);
4858da2e3ebdSchin }
4859da2e3ebdSchin }
4860da2e3ebdSchin else if (*(t = next(s + 2, version)) == '[')
4861da2e3ebdSchin while (*(t = skip(t, ':', 0, 0, 1, 0, 0, version)) == ':')
4862da2e3ebdSchin if (*++t == '!')
4863da2e3ebdSchin {
4864da2e3ebdSchin if (!v || *v == '1')
4865da2e3ebdSchin {
4866da2e3ebdSchin e = skip(t, ':', '?', ']', 1, 0, 0, version);
4867da2e3ebdSchin opt_info.arg = sfprints("%-.*s", e - t - 1, t + 1);
4868da2e3ebdSchin }
4869da2e3ebdSchin else
4870da2e3ebdSchin {
4871da2e3ebdSchin opt_info.arg = 0;
487234f9b3eeSRoland Mainz opt_info.num = (long)(opt_info.number = 0);
4873da2e3ebdSchin }
4874da2e3ebdSchin break;
4875da2e3ebdSchin }
4876da2e3ebdSchin }
4877da2e3ebdSchin if (opt_info.arg && n)
4878da2e3ebdSchin {
4879da2e3ebdSchin opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
4880da2e3ebdSchin if (err || e == opt_info.arg)
4881da2e3ebdSchin {
4882da2e3ebdSchin pop(psp);
4883*3e14f97fSRoger A. Faulkner return opterror(s, err, version, id, catalog);
4884da2e3ebdSchin }
4885da2e3ebdSchin }
4886da2e3ebdSchin }
4887da2e3ebdSchin goto optarg;
4888da2e3ebdSchin }
4889da2e3ebdSchin else if (*(opt_info.arg = &argv[opt_info.index++][opt_info.offset]))
4890da2e3ebdSchin {
4891da2e3ebdSchin if (*s == '#')
4892da2e3ebdSchin {
4893da2e3ebdSchin opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
4894da2e3ebdSchin if (err || e == opt_info.arg)
4895da2e3ebdSchin {
4896da2e3ebdSchin if (!err && *(s + 1) == '?')
4897da2e3ebdSchin {
4898da2e3ebdSchin opt_info.arg = 0;
4899da2e3ebdSchin opt_info.index--;
4900da2e3ebdSchin }
4901da2e3ebdSchin else
4902da2e3ebdSchin {
4903da2e3ebdSchin opt_info.offset = 0;
4904*3e14f97fSRoger A. Faulkner c = opterror(s, err, version, id, catalog);
4905da2e3ebdSchin }
4906da2e3ebdSchin pop(psp);
4907da2e3ebdSchin return c;
4908da2e3ebdSchin }
4909da2e3ebdSchin else if (*e)
4910da2e3ebdSchin {
4911da2e3ebdSchin opt_info.offset += e - opt_info.arg;
4912da2e3ebdSchin opt_info.index--;
4913da2e3ebdSchin pop(psp);
4914da2e3ebdSchin return c;
4915da2e3ebdSchin }
4916da2e3ebdSchin }
4917da2e3ebdSchin }
4918da2e3ebdSchin else if (opt_info.arg = argv[opt_info.index])
4919da2e3ebdSchin {
4920da2e3ebdSchin opt_info.index++;
4921da2e3ebdSchin if (*(s + 1) == '?' && (*opt_info.arg == '-' || (pass->flags & OPT_plus) && *opt_info.arg == '+') && *(opt_info.arg + 1))
4922da2e3ebdSchin {
4923da2e3ebdSchin opt_info.index--;
4924da2e3ebdSchin opt_info.arg = 0;
4925da2e3ebdSchin }
4926da2e3ebdSchin else if (*s == '#')
4927da2e3ebdSchin {
4928da2e3ebdSchin opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
4929da2e3ebdSchin if (err || *e)
4930da2e3ebdSchin {
4931da2e3ebdSchin if (!err && *(s + 1) == '?')
4932da2e3ebdSchin {
4933da2e3ebdSchin opt_info.arg = 0;
4934da2e3ebdSchin opt_info.index--;
4935da2e3ebdSchin }
4936da2e3ebdSchin else
4937da2e3ebdSchin {
4938da2e3ebdSchin pop(psp);
4939da2e3ebdSchin opt_info.offset = 0;
4940*3e14f97fSRoger A. Faulkner return opterror(s, err, version, id, catalog);
4941da2e3ebdSchin }
4942da2e3ebdSchin }
4943da2e3ebdSchin }
4944da2e3ebdSchin }
4945da2e3ebdSchin else if (*(s + 1) != '?')
4946da2e3ebdSchin {
4947da2e3ebdSchin opt_info.index--;
4948da2e3ebdSchin pop(psp);
4949*3e14f97fSRoger A. Faulkner return opterror(s, 0, version, id, catalog);
4950da2e3ebdSchin }
4951da2e3ebdSchin opt_info.offset = 0;
4952da2e3ebdSchin optarg:
4953da2e3ebdSchin if (*s == ':' && *(s = skip(s, 0, 0, 0, 1, 0, 1, version)) == GO && *(s = next(s + 1, version)) == '[' && isalnum(*(s + 1)))
4954da2e3ebdSchin {
4955da2e3ebdSchin x = 0;
4956da2e3ebdSchin if (opt_info.arg)
4957da2e3ebdSchin {
4958da2e3ebdSchin do
4959da2e3ebdSchin {
4960da2e3ebdSchin w = y = opt_info.arg;
4961da2e3ebdSchin f = s = next(s + 1, version);
4962da2e3ebdSchin k = *f;
4963da2e3ebdSchin if (k == *w && isalpha(k) && !*(w + 1))
4964da2e3ebdSchin {
4965da2e3ebdSchin x = k;
4966da2e3ebdSchin break;
4967da2e3ebdSchin }
4968da2e3ebdSchin if (*s == '+' || *s == '-')
4969da2e3ebdSchin continue;
4970da2e3ebdSchin else if (*s == '[' || version < 1)
4971da2e3ebdSchin continue;
4972da2e3ebdSchin else
4973da2e3ebdSchin {
4974da2e3ebdSchin if (*s != ':')
4975da2e3ebdSchin s = skip(s, ':', '?', 0, 1, 0, 0, version);
4976da2e3ebdSchin if (*s == ':')
4977da2e3ebdSchin {
4978da2e3ebdSchin if (catalog)
4979da2e3ebdSchin {
4980da2e3ebdSchin p = skip(s + 1, '?', 0, 0, 1, 0, 0, version);
4981da2e3ebdSchin e = sfprints("%-.*s", p - (s + 1), s + 1);
4982*3e14f97fSRoger A. Faulkner b = T(id, catalog, e);
4983da2e3ebdSchin if (b == e)
4984da2e3ebdSchin p = 0;
4985da2e3ebdSchin else
4986da2e3ebdSchin {
4987da2e3ebdSchin sfprintf(xp, ":%s|%s?", b, e);
4988da2e3ebdSchin if (!(s = sfstruse(xp)))
4989da2e3ebdSchin goto nospace;
4990da2e3ebdSchin }
4991da2e3ebdSchin }
4992da2e3ebdSchin else
4993da2e3ebdSchin p = 0;
4994da2e3ebdSchin for (;;)
4995da2e3ebdSchin {
4996da2e3ebdSchin n = m = 0;
4997da2e3ebdSchin e = s + 1;
4998da2e3ebdSchin while (*++s)
4999da2e3ebdSchin {
5000da2e3ebdSchin if (*s == '*' || *s == '\a')
5001da2e3ebdSchin {
5002da2e3ebdSchin if (*s == '\a')
5003da2e3ebdSchin do
5004da2e3ebdSchin {
5005da2e3ebdSchin if (!*++s)
5006da2e3ebdSchin {
5007da2e3ebdSchin s--;
5008da2e3ebdSchin break;
5009da2e3ebdSchin }
5010da2e3ebdSchin } while (*s != '\a');
5011da2e3ebdSchin j = *(s + 1);
5012da2e3ebdSchin if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
5013da2e3ebdSchin {
5014da2e3ebdSchin while (*w)
5015da2e3ebdSchin w++;
5016da2e3ebdSchin m = 0;
5017da2e3ebdSchin break;
5018da2e3ebdSchin }
5019da2e3ebdSchin m = 1;
5020da2e3ebdSchin }
5021da2e3ebdSchin else if (*s == *w || sep(*s) && sep(*w))
5022da2e3ebdSchin w++;
5023da2e3ebdSchin else if (*w == 0)
5024da2e3ebdSchin break;
5025da2e3ebdSchin else if (!sep(*s))
5026da2e3ebdSchin {
5027da2e3ebdSchin if (sep(*w))
5028da2e3ebdSchin {
5029da2e3ebdSchin if (*++w == *s)
5030da2e3ebdSchin {
5031da2e3ebdSchin w++;
5032da2e3ebdSchin continue;
5033da2e3ebdSchin }
5034da2e3ebdSchin }
5035da2e3ebdSchin else if (w == y || sep(*(w - 1)) || isupper(*(w - 1)) && islower(*w))
5036da2e3ebdSchin break;
5037da2e3ebdSchin for (q = s; *q && !sep(*q) && *q != '|' && *q != '?' && *q != ']'; q++);
5038da2e3ebdSchin if (!sep(*q))
5039da2e3ebdSchin break;
5040da2e3ebdSchin for (s = q; w > y && *w != *(s + 1); w--);
5041da2e3ebdSchin }
5042da2e3ebdSchin else if (*w != *(s + 1))
5043da2e3ebdSchin break;
5044da2e3ebdSchin }
5045da2e3ebdSchin if (!*w)
5046da2e3ebdSchin {
5047da2e3ebdSchin nov = 0;
5048da2e3ebdSchin break;
5049da2e3ebdSchin }
5050da2e3ebdSchin if (*(s = skip(s, ':', '|', '?', 1, 0, 0, version)) != '|')
5051da2e3ebdSchin break;
5052da2e3ebdSchin w = y;
5053da2e3ebdSchin }
5054da2e3ebdSchin if (p)
5055da2e3ebdSchin s = p;
5056da2e3ebdSchin if (!*w)
5057da2e3ebdSchin {
5058da2e3ebdSchin if (n)
5059da2e3ebdSchin num = 0;
5060da2e3ebdSchin if (!(n = (m || *s == ':' || *s == '|' || *s == '?' || *s == ']')) && x)
5061da2e3ebdSchin {
5062da2e3ebdSchin pop(psp);
5063*3e14f97fSRoger A. Faulkner return opterror("&", 0, version, id, catalog);
5064da2e3ebdSchin }
5065da2e3ebdSchin for (x = k; *(f + 1) == '|' && (j = *(f + 2)) && j != '!' && j != '=' && j != ':' && j != '?' && j != ']'; f += 2);
5066da2e3ebdSchin if (*f == ':')
5067da2e3ebdSchin x = -1;
5068da2e3ebdSchin else if (*(f + 1) == ':' || *(f + 1) == '!' && *(f + 2) == ':')
5069da2e3ebdSchin /* ok */;
5070da2e3ebdSchin else
5071da2e3ebdSchin {
5072da2e3ebdSchin a = f;
5073da2e3ebdSchin if (*a == '=')
5074da2e3ebdSchin a++;
5075da2e3ebdSchin else
5076da2e3ebdSchin {
5077da2e3ebdSchin if (*(a + 1) == '!')
5078da2e3ebdSchin a++;
5079da2e3ebdSchin if (*(a + 1) == '=')
5080da2e3ebdSchin a += 2;
5081da2e3ebdSchin }
5082da2e3ebdSchin x = -strtol(a, &b, 0);
5083da2e3ebdSchin }
5084da2e3ebdSchin b = e;
5085da2e3ebdSchin a = s = skip(s, 0, 0, 0, 1, 0, 0, version);
5086da2e3ebdSchin if (n)
5087da2e3ebdSchin break;
5088da2e3ebdSchin }
5089da2e3ebdSchin }
5090da2e3ebdSchin }
5091da2e3ebdSchin } while (*(s = skip(s, 0, 0, 0, 1, 0, 1, version)) == '[');
509234f9b3eeSRoland Mainz if (!(opt_info.num = (long)(opt_info.number = x)))
5093da2e3ebdSchin {
5094da2e3ebdSchin pop(psp);
5095*3e14f97fSRoger A. Faulkner return opterror("*", 0, version, id, catalog);
5096da2e3ebdSchin }
5097da2e3ebdSchin }
5098da2e3ebdSchin }
5099da2e3ebdSchin }
5100da2e3ebdSchin else if (w && v)
5101da2e3ebdSchin {
5102da2e3ebdSchin pop(psp);
5103*3e14f97fSRoger A. Faulkner return opterror("=", 0, version, id, catalog);
5104da2e3ebdSchin }
5105da2e3ebdSchin else
5106da2e3ebdSchin {
510734f9b3eeSRoland Mainz opt_info.num = (long)(opt_info.number = num);
5108da2e3ebdSchin if (!w && !argv[opt_info.index][opt_info.offset])
5109da2e3ebdSchin {
5110da2e3ebdSchin opt_info.offset = 0;
5111da2e3ebdSchin opt_info.index++;
5112da2e3ebdSchin }
5113da2e3ebdSchin }
5114da2e3ebdSchin pop(psp);
5115da2e3ebdSchin return c;
5116da2e3ebdSchin help:
5117da2e3ebdSchin if (v && *v == '?' && *(v + 1) == '?' && *(v + 2))
5118da2e3ebdSchin {
5119da2e3ebdSchin s = v + 2;
5120da2e3ebdSchin if ((s[0] == 'n' || s[0] == 'N') && (s[1] == 'o' || s[1] == 'O'))
5121da2e3ebdSchin {
5122da2e3ebdSchin s += 2;
5123da2e3ebdSchin n = -1;
5124da2e3ebdSchin }
5125da2e3ebdSchin else
5126da2e3ebdSchin n = 1;
5127da2e3ebdSchin if (hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), s))
5128da2e3ebdSchin {
5129da2e3ebdSchin if (hp->style < STYLE_man || !(s = argv[opt_info.index]) || s[0] != '-' || s[1] != '-' || !s[2])
5130da2e3ebdSchin {
5131da2e3ebdSchin opt_info.arg = sfprints("\fversion=%d", version);
5132da2e3ebdSchin pop(psp);
5133da2e3ebdSchin return '?';
5134da2e3ebdSchin }
5135da2e3ebdSchin opt_info.state->force = hp->style;
5136da2e3ebdSchin }
5137*3e14f97fSRoger A. Faulkner else if (match(s, "ESC", -1, ID, NiL) || match(s, "EMPHASIS", -1, ID, NiL))
5138da2e3ebdSchin opt_info.state->emphasis = n;
5139*3e14f97fSRoger A. Faulkner else if (match(s, "PREFORMAT", -1, ID, NiL))
5140da2e3ebdSchin opt_info.state->flags |= OPT_preformat;
5141*3e14f97fSRoger A. Faulkner else if (match(s, "TEST", -1, ID, NiL))
5142da2e3ebdSchin {
5143da2e3ebdSchin opt_info.state->width = OPT_WIDTH;
5144da2e3ebdSchin opt_info.state->emphasis = 1;
5145da2e3ebdSchin }
5146da2e3ebdSchin else
5147da2e3ebdSchin {
5148da2e3ebdSchin pop(psp);
5149*3e14f97fSRoger A. Faulkner return opterror(v, 0, version, id, catalog);
5150da2e3ebdSchin }
5151da2e3ebdSchin psp = pop(psp);
5152da2e3ebdSchin if (argv == opt_info.state->strv)
5153da2e3ebdSchin return '#';
5154da2e3ebdSchin goto again;
5155da2e3ebdSchin }
5156da2e3ebdSchin if ((opt_info.arg = opthelp(NiL, v)) == (char*)unknown)
5157da2e3ebdSchin {
5158da2e3ebdSchin pop(psp);
5159*3e14f97fSRoger A. Faulkner return opterror(v, 0, version, id, catalog);
5160da2e3ebdSchin }
5161da2e3ebdSchin pop(psp);
5162da2e3ebdSchin return '?';
5163da2e3ebdSchin nospace:
5164da2e3ebdSchin pop(psp);
5165*3e14f97fSRoger A. Faulkner return opterror(NiL, 0, 0, NiL, NiL);
5166da2e3ebdSchin }
5167da2e3ebdSchin
5168da2e3ebdSchin /*
5169da2e3ebdSchin * parse long options with 0,1,2 leading '-' or '+' from string and pass to optget()
5170da2e3ebdSchin * syntax is the unquoted
5171da2e3ebdSchin *
5172da2e3ebdSchin * <length> [-|+|--|++]<name>[[-+:|&=]=<value>\n (or \0 for the last)
5173da2e3ebdSchin *
5174da2e3ebdSchin * or the quoted
5175da2e3ebdSchin *
5176da2e3ebdSchin * [-|+|--|++][no]name[[-+:|&=]=['"{(]value[)}"']][, ]...
5177da2e3ebdSchin *
5178da2e3ebdSchin * with \x escapes passed to chresc()
5179da2e3ebdSchin *
5180da2e3ebdSchin * return '#' for `label:', with opt_info.name==label
5181da2e3ebdSchin * str[opt_info.offset] next arg
5182da2e3ebdSchin *
5183da2e3ebdSchin * optstr(s, 0)
5184da2e3ebdSchin * return '-' if arg, 0 otherwise
5185da2e3ebdSchin * optstr(0, opts)
5186da2e3ebdSchin * use previous parsed str
5187da2e3ebdSchin */
5188da2e3ebdSchin
5189da2e3ebdSchin int
optstr(const char * str,const char * opts)5190da2e3ebdSchin optstr(const char* str, const char* opts)
5191da2e3ebdSchin {
5192da2e3ebdSchin register char* s = (char*)str;
5193da2e3ebdSchin register Sfio_t* mp;
5194da2e3ebdSchin register int c;
5195da2e3ebdSchin register int ql;
5196da2e3ebdSchin register int qr;
5197da2e3ebdSchin register int qc;
5198da2e3ebdSchin int v;
5199da2e3ebdSchin char* e;
5200da2e3ebdSchin
5201da2e3ebdSchin again:
5202da2e3ebdSchin if (s)
5203da2e3ebdSchin {
5204da2e3ebdSchin if (!(mp = opt_info.state->strp) && !(mp = opt_info.state->strp = sfstropen()))
5205da2e3ebdSchin return 0;
5206da2e3ebdSchin if (opt_info.state->str != s)
5207da2e3ebdSchin opt_info.state->str = s;
5208da2e3ebdSchin else if (opt_info.index == 1)
5209da2e3ebdSchin s += opt_info.offset;
5210da2e3ebdSchin while (*s == ',' || *s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')
5211da2e3ebdSchin s++;
5212da2e3ebdSchin if (!*s)
5213da2e3ebdSchin {
5214da2e3ebdSchin opt_info.state->str = 0;
5215da2e3ebdSchin return 0;
5216da2e3ebdSchin }
5217da2e3ebdSchin if (*s == '-' || *s == '+')
5218da2e3ebdSchin {
5219da2e3ebdSchin c = *s++;
5220da2e3ebdSchin sfputc(mp, c);
5221da2e3ebdSchin if (*s == c)
5222da2e3ebdSchin {
5223da2e3ebdSchin sfputc(mp, c);
5224da2e3ebdSchin s++;
5225da2e3ebdSchin }
5226da2e3ebdSchin }
5227da2e3ebdSchin else
5228da2e3ebdSchin {
5229da2e3ebdSchin sfputc(mp, '-');
5230da2e3ebdSchin sfputc(mp, '-');
5231da2e3ebdSchin }
5232da2e3ebdSchin if (isdigit(*s) && (v = (int)strtol(s, &e, 10)) > 1 && isspace(*e) && --v <= strlen(s) && (s[v] == 0 || s[v] == '\n'))
5233da2e3ebdSchin {
5234da2e3ebdSchin s += v;
5235da2e3ebdSchin while (isspace(*++e));
5236da2e3ebdSchin sfwrite(mp, e, s - e);
5237da2e3ebdSchin }
5238da2e3ebdSchin else
5239da2e3ebdSchin {
5240da2e3ebdSchin while (*s && *s != ',' && *s != ' ' && *s != '\t' && *s != '\n' && *s != '\r' && *s != '=' && *s != ':')
5241da2e3ebdSchin sfputc(mp, *s++);
5242da2e3ebdSchin if ((c = *s) == ':' && *(s + 1) != '=')
5243da2e3ebdSchin {
5244da2e3ebdSchin opt_info.index = 1;
5245da2e3ebdSchin opt_info.offset = ++s - (char*)str;
5246da2e3ebdSchin if (!(s = sfstruse(mp)))
5247da2e3ebdSchin goto nospace;
5248da2e3ebdSchin s += 2;
5249da2e3ebdSchin e = opt_info.name;
5250da2e3ebdSchin while (e < &opt_info.name[sizeof(opt_info.name)-1] && (*e++ = *s++));
5251da2e3ebdSchin opt_info.arg = 0;
525234f9b3eeSRoland Mainz opt_info.num = (long)(opt_info.number = 0);
5253da2e3ebdSchin opt_info.option[0] = ':';
5254da2e3ebdSchin opt_info.option[1] = 0;
5255da2e3ebdSchin return '#';
5256da2e3ebdSchin }
5257da2e3ebdSchin if (c == ':' || c == '=')
5258da2e3ebdSchin {
5259da2e3ebdSchin sfputc(mp, c);
5260da2e3ebdSchin ql = qr = 0;
5261da2e3ebdSchin while (c = *++s)
5262da2e3ebdSchin {
5263da2e3ebdSchin if (c == '\\')
5264da2e3ebdSchin {
5265da2e3ebdSchin sfputc(mp, chresc(s, &e));
5266da2e3ebdSchin s = e - 1;
5267da2e3ebdSchin }
5268da2e3ebdSchin else if (c == qr)
5269da2e3ebdSchin {
5270da2e3ebdSchin if (qr != ql)
5271da2e3ebdSchin sfputc(mp, c);
5272da2e3ebdSchin if (--qc <= 0)
5273da2e3ebdSchin qr = ql = 0;
5274da2e3ebdSchin }
5275da2e3ebdSchin else if (c == ql)
5276da2e3ebdSchin {
5277da2e3ebdSchin sfputc(mp, c);
5278da2e3ebdSchin qc++;
5279da2e3ebdSchin }
5280da2e3ebdSchin else if (qr)
5281da2e3ebdSchin sfputc(mp, c);
5282da2e3ebdSchin else if (c == ',' || c == ' ' || c == '\t' || c == '\n' || c == '\r')
5283da2e3ebdSchin break;
5284da2e3ebdSchin else if (c == '"' || c == '\'')
5285da2e3ebdSchin {
5286da2e3ebdSchin ql = qr = c;
5287da2e3ebdSchin qc = 1;
5288da2e3ebdSchin }
5289da2e3ebdSchin else
5290da2e3ebdSchin {
5291da2e3ebdSchin sfputc(mp, c);
5292da2e3ebdSchin if (c == GO)
5293da2e3ebdSchin {
5294da2e3ebdSchin ql = c;
5295da2e3ebdSchin qr = OG;
5296da2e3ebdSchin qc = 1;
5297da2e3ebdSchin }
5298da2e3ebdSchin else if (c == '(')
5299da2e3ebdSchin {
5300da2e3ebdSchin ql = c;
5301da2e3ebdSchin qr = ')';
5302da2e3ebdSchin qc = 1;
5303da2e3ebdSchin }
5304da2e3ebdSchin }
5305da2e3ebdSchin }
5306da2e3ebdSchin }
5307da2e3ebdSchin }
5308da2e3ebdSchin opt_info.argv = opt_info.state->strv;
5309da2e3ebdSchin opt_info.state->strv[0] = T(NiL, ID, "option");
5310da2e3ebdSchin if (!(opt_info.state->strv[1] = sfstruse(mp)))
5311da2e3ebdSchin goto nospace;
5312da2e3ebdSchin opt_info.state->strv[2] = 0;
5313da2e3ebdSchin opt_info.offset = s - (char*)str;
5314da2e3ebdSchin }
5315da2e3ebdSchin if (opts)
5316da2e3ebdSchin {
5317da2e3ebdSchin if (!opt_info.state->strv[1])
5318da2e3ebdSchin {
5319da2e3ebdSchin opt_info.state->str = 0;
5320da2e3ebdSchin return 0;
5321da2e3ebdSchin }
5322da2e3ebdSchin opt_info.index = 1;
5323da2e3ebdSchin v = opt_info.offset;
5324da2e3ebdSchin opt_info.offset = 0;
5325da2e3ebdSchin c = optget(opt_info.state->strv, opts);
5326da2e3ebdSchin opt_info.index = 1;
5327da2e3ebdSchin opt_info.offset = v;
5328da2e3ebdSchin if (c == '#')
5329da2e3ebdSchin {
5330da2e3ebdSchin s = opt_info.state->str;
5331da2e3ebdSchin goto again;
5332da2e3ebdSchin }
5333da2e3ebdSchin if ((c == '?' || c == ':') && (opt_info.arg[0] == '-' && opt_info.arg[1] == '-'))
5334da2e3ebdSchin opt_info.arg += 2;
5335da2e3ebdSchin s = opt_info.name;
5336da2e3ebdSchin if (*s++ == '-' && *s++ == '-' && *s)
5337da2e3ebdSchin {
5338da2e3ebdSchin e = opt_info.name;
5339da2e3ebdSchin while (*e++ = *s++);
5340da2e3ebdSchin }
5341da2e3ebdSchin }
5342da2e3ebdSchin else
5343da2e3ebdSchin c = '-';
5344da2e3ebdSchin return c;
5345da2e3ebdSchin nospace:
5346*3e14f97fSRoger A. Faulkner return opterror(NiL, 0, 0, NiL, NiL);
5347da2e3ebdSchin }
5348