1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2012 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
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 
79*b30d1939SAndy Fiddaman #define HELP_head	0x01
80*b30d1939SAndy Fiddaman #define HELP_index	0x02
81*b30d1939SAndy Fiddaman 
82*b30d1939SAndy Fiddaman #define TAG_NONE	0
83*b30d1939SAndy Fiddaman #define TAG_DIV		1
84*b30d1939SAndy Fiddaman #define TAG_DL		2
85*b30d1939SAndy Fiddaman 
86*b30d1939SAndy Fiddaman #define SEP(c)		((c)=='-'||(c)=='_')
87da2e3ebdSchin 
88da2e3ebdSchin typedef struct Attr_s
89da2e3ebdSchin {
90da2e3ebdSchin 	const char*	name;
91da2e3ebdSchin 	int		flag;
92da2e3ebdSchin } Attr_t;
93da2e3ebdSchin 
94da2e3ebdSchin typedef struct Help_s
95da2e3ebdSchin {
96da2e3ebdSchin 	const char*	match;		/* builtin help match name	*/
97da2e3ebdSchin 	const char*	name;		/* builtin help name		*/
98da2e3ebdSchin 	int		style;		/* STYLE_*			*/
99da2e3ebdSchin 	const char*	text;		/* --? text			*/
100da2e3ebdSchin 	unsigned int	size;		/* strlen text			*/
101da2e3ebdSchin } Help_t;
102da2e3ebdSchin 
103da2e3ebdSchin typedef struct Font_s
104da2e3ebdSchin {
105da2e3ebdSchin 	const char*	html[2];
106da2e3ebdSchin 	const char*	nroff[2];
107da2e3ebdSchin 	const char*	term[2];
108da2e3ebdSchin } Font_t;
109da2e3ebdSchin 
110da2e3ebdSchin typedef struct List_s
111da2e3ebdSchin {
112da2e3ebdSchin 	int		type;		/* { - + : }			*/
113da2e3ebdSchin 	const char*	name;		/* list name			*/
114da2e3ebdSchin 	const char*	text;		/* help text			*/
115da2e3ebdSchin } List_t;
116da2e3ebdSchin 
117da2e3ebdSchin typedef struct Msg_s
118da2e3ebdSchin {
119da2e3ebdSchin 	const char*	text;		/* default message text		*/
120da2e3ebdSchin 	Dtlink_t	link;		/* cdt link			*/
121da2e3ebdSchin } Msg_t;
122da2e3ebdSchin 
123da2e3ebdSchin typedef struct Save_s
124da2e3ebdSchin {
125da2e3ebdSchin 	Dtlink_t	link;		/* cdt link			*/
126da2e3ebdSchin 	char		text[1];	/* saved text text		*/
127da2e3ebdSchin } Save_t;
128da2e3ebdSchin 
129da2e3ebdSchin typedef struct Push_s
130da2e3ebdSchin {
131da2e3ebdSchin 	struct Push_s*	next;		/* next string			*/
132da2e3ebdSchin 	char*		ob;		/* next char in old string	*/
133da2e3ebdSchin 	char*		oe;		/* end of old string		*/
134da2e3ebdSchin 	char*		nb;		/* next char in new string	*/
135da2e3ebdSchin 	char*		ne;		/* end of new string		*/
136da2e3ebdSchin 	int		ch;		/* localize() translation	*/
137da2e3ebdSchin } Push_t;
138da2e3ebdSchin 
139*b30d1939SAndy Fiddaman typedef struct Tag_s
140*b30d1939SAndy Fiddaman {
141*b30d1939SAndy Fiddaman 	unsigned char	level;		/* indent level			*/
142*b30d1939SAndy Fiddaman 	unsigned char	id;		/* TAG_* id			*/
143*b30d1939SAndy Fiddaman } Tag_t;
144*b30d1939SAndy Fiddaman 
145da2e3ebdSchin typedef struct Indent_s
146da2e3ebdSchin {
147da2e3ebdSchin 	int		stop;		/* tab column position		*/
148da2e3ebdSchin } Indent_t;
149da2e3ebdSchin 
150da2e3ebdSchin static Indent_t		indent[] =
151da2e3ebdSchin {
152da2e3ebdSchin 	0,2,	4,10,	12,18,	20,26,	28,34,	36,42,	44,50,	0,0
153da2e3ebdSchin };
154da2e3ebdSchin 
155*b30d1939SAndy Fiddaman static const char*	end[] =
156*b30d1939SAndy Fiddaman {
157*b30d1939SAndy Fiddaman 	"", "</DIV>\n", "</DL>\n"
158*b30d1939SAndy Fiddaman };
159*b30d1939SAndy Fiddaman 
160da2e3ebdSchin static const char	term_off[] =	{CC_esc,'[','0','m',0};
161da2e3ebdSchin static const char	term_B_on[] =	{CC_esc,'[','1','m',0};
162da2e3ebdSchin static const char	term_I_on[] =	{CC_esc,'[','1',';','4','m',0};
163da2e3ebdSchin 
164da2e3ebdSchin static const Font_t	fonts[] =
165da2e3ebdSchin {
166da2e3ebdSchin 	"",	"",	"",	"",	"",			"",
167da2e3ebdSchin 	"</B>",	"<B>", "\\fP",	"\\fB",	&term_off[0],	&term_B_on[0],
168da2e3ebdSchin 	"</I>",	"<I>", "\\fP",	"\\fI",	&term_off[0],	&term_I_on[0],
169da2e3ebdSchin 	"",	"",	"",	"",	"",			"",
170da2e3ebdSchin 	"</TT>","<TT>","\\fP",	"\\f5",	"",			"",
171da2e3ebdSchin };
172da2e3ebdSchin 
173da2e3ebdSchin static char		native[] = "";
174da2e3ebdSchin 
175*b30d1939SAndy Fiddaman static unsigned char	map[UCHAR_MAX];
176*b30d1939SAndy Fiddaman 
177*b30d1939SAndy Fiddaman static Optstate_t	state;
178*b30d1939SAndy Fiddaman 
179da2e3ebdSchin #if !_PACKAGE_astsa
180da2e3ebdSchin 
181da2e3ebdSchin #define ID		ast.id
182da2e3ebdSchin 
183da2e3ebdSchin #define C(s)		ERROR_catalog(s)
184*b30d1939SAndy Fiddaman #define D(s)		(state.msgdict && dtmatch(state.msgdict, (s)))
185da2e3ebdSchin #define T(i,c,m)	(X(c)?translate(i,c,C(m)):(m))
186da2e3ebdSchin #define X(c)		(ERROR_translating()&&(c)!=native)
187da2e3ebdSchin #define Z(x)		C(x),sizeof(x)-1
188da2e3ebdSchin 
189da2e3ebdSchin /*
190da2e3ebdSchin  * translate with C_LC_MESSAGES_libast[] check
191da2e3ebdSchin  */
192da2e3ebdSchin 
193da2e3ebdSchin static char*
translate(const char * cmd,const char * cat,const char * msg)194da2e3ebdSchin translate(const char* cmd, const char* cat, const char* msg)
195da2e3ebdSchin {
196da2e3ebdSchin 	if (!X(cat))
197da2e3ebdSchin 		return (char*)msg;
198da2e3ebdSchin 	if (cat != (const char*)ID && D(msg))
199da2e3ebdSchin 		cat = (const char*)ID;
200da2e3ebdSchin 	return errorx(NiL, cmd, cat, msg);
201da2e3ebdSchin }
202da2e3ebdSchin 
203da2e3ebdSchin #else
204da2e3ebdSchin 
205da2e3ebdSchin static char		ID[] = "ast";
206da2e3ebdSchin 
207da2e3ebdSchin #define C(s)		s
208*b30d1939SAndy Fiddaman #define D(s)		(state.msgdict && dtmatch(state.msgdict, (s)))
209da2e3ebdSchin #define T(i,c,m)	m
210da2e3ebdSchin #define X(c)		0
211da2e3ebdSchin #define Z(x)		C(x),sizeof(x)-1
212da2e3ebdSchin 
213da2e3ebdSchin #endif
214da2e3ebdSchin 
215da2e3ebdSchin static const List_t	help_head[] =
216da2e3ebdSchin {
217da2e3ebdSchin 	'-',	0,
218da2e3ebdSchin 		0,
219da2e3ebdSchin 	'+',	C("NAME"),
220da2e3ebdSchin 		C("options available to all \bast\b commands"),
221da2e3ebdSchin 	'+',	C("DESCRIPTION"),
222da2e3ebdSchin 		C("\b-?\b and \b--?\b* options are the same \
223da2e3ebdSchin for all \bast\b commands. For any \aitem\a below, if \b--\b\aitem\a is not \
224da2e3ebdSchin supported by a given command then it is equivalent to \b--\?\?\b\aitem\a. The \
225da2e3ebdSchin \b--\?\?\b form should be used for portability. All output is written to the \
226da2e3ebdSchin standard error."),
227da2e3ebdSchin };
228da2e3ebdSchin 
229da2e3ebdSchin static const Help_t	styles[] =
230da2e3ebdSchin {
231da2e3ebdSchin 	C("about"),	"-",		STYLE_match,
232da2e3ebdSchin 	Z("List all implementation info."),
233da2e3ebdSchin 	C("api"),	"?api",		STYLE_api,
234da2e3ebdSchin 	Z("List detailed info in program readable form."),
235da2e3ebdSchin 	C("help"),	"",		-1,
236da2e3ebdSchin 	Z("List detailed help option info."),
237da2e3ebdSchin 	C("html"),	"?html",	STYLE_html,
238da2e3ebdSchin 	Z("List detailed info in html."),
239da2e3ebdSchin 	C("keys"),	"?keys",	STYLE_keys,
240da2e3ebdSchin 	Z("List the usage translation key strings with C style escapes."),
241da2e3ebdSchin 	C("long"),	"?long",	STYLE_long,
242da2e3ebdSchin 	Z("List long option usage."),
243da2e3ebdSchin 	C("man"),	"?man",		STYLE_man,
244da2e3ebdSchin 	Z("List detailed info in displayed man page form."),
245da2e3ebdSchin 	C("nroff"),	"?nroff",	STYLE_nroff,
246da2e3ebdSchin 	Z("List detailed info in nroff."),
247da2e3ebdSchin 	C("options"),	"?options",	STYLE_options,
248da2e3ebdSchin 	Z("List short and long option details."),
249da2e3ebdSchin 	C("posix"),	"?posix",	STYLE_posix,
250da2e3ebdSchin 	Z("List posix getopt usage."),
251da2e3ebdSchin 	C("short"),	"?short",	STYLE_short,
252da2e3ebdSchin 	Z("List short option usage."),
253da2e3ebdSchin 	C("usage"),	"?usage",	STYLE_usage,
254da2e3ebdSchin 	Z("List the usage string with C style escapes."),
255da2e3ebdSchin };
256da2e3ebdSchin 
257da2e3ebdSchin static const List_t	help_tail[] =
258da2e3ebdSchin {
259da2e3ebdSchin 	':',	C("\?\?-\alabel\a"),
260da2e3ebdSchin 		C("List implementation info matching \alabel\a*."),
261da2e3ebdSchin 	':',	C("\?\?\aname\a"),
262da2e3ebdSchin 		C("Equivalent to \b--help=\b\aname\a."),
263da2e3ebdSchin 	':',	C("\?\?"),
264da2e3ebdSchin 		C("Equivalent to \b--\?\?options\b."),
265da2e3ebdSchin 	':',	C("\?\?\?\?"),
266da2e3ebdSchin 		C("Equivalent to \b--\?\?man\b."),
267da2e3ebdSchin 	':',	C("\?\?\?\?\?\?"),
268da2e3ebdSchin 		C("Equivalent to \b--\?\?help\b."),
269da2e3ebdSchin 	':',	C("\?\?\?\?\?\?\aitem\a"),
270da2e3ebdSchin 		C("If the next argument is \b--\b\aoption\a then list \
271da2e3ebdSchin the \aoption\a output in the \aitem\a style. Otherwise print \
272da2e3ebdSchin \bversion=\b\an\a where \an\a>0 if \b--\?\?\b\aitem\a is supported, \b0\b \
273da2e3ebdSchin if not."),
274da2e3ebdSchin 	':',	C("\?\?\?\?\?\?ESC"),
275da2e3ebdSchin 		C("Emit escape codes even if output is not a terminal."),
276*b30d1939SAndy Fiddaman 	':',	C("\?\?\?\?\?\?MAN[=\asection\a]]"),
277*b30d1939SAndy Fiddaman 		C("List the \bman\b(1) section title for \asection\a [the \
278*b30d1939SAndy Fiddaman current command]]."),
279*b30d1939SAndy Fiddaman 	':',	C("\?\?\?\?\?\?SECTION"),
280*b30d1939SAndy Fiddaman 		C("List the \bman\b(1) section number for the current command."),
281da2e3ebdSchin 	':',	C("\?\?\?\?\?\?TEST"),
282da2e3ebdSchin 		C("Massage the output for regression testing."),
283da2e3ebdSchin };
284da2e3ebdSchin 
285da2e3ebdSchin static const Attr_t	attrs[] =
286da2e3ebdSchin {
287da2e3ebdSchin 	"flag",		OPT_flag,
288da2e3ebdSchin 	"hidden",	OPT_hidden,
289da2e3ebdSchin 	"ignorecase",	OPT_ignorecase,
290da2e3ebdSchin 	"invert",	OPT_invert,
291da2e3ebdSchin 	"listof",	OPT_listof,
292da2e3ebdSchin 	"number",	OPT_number,
293da2e3ebdSchin 	"oneof",	OPT_oneof,
294da2e3ebdSchin 	"optional",	OPT_optional,
295da2e3ebdSchin 	"string",	OPT_string,
296da2e3ebdSchin };
297da2e3ebdSchin 
298da2e3ebdSchin static const char	unknown[] = C("unknown option or attribute");
299da2e3ebdSchin 
300da2e3ebdSchin static const char*	heading[] =
301da2e3ebdSchin {
302da2e3ebdSchin 	C("INDEX"),
303da2e3ebdSchin 	C("USER COMMANDS"),
304da2e3ebdSchin 	C("SYSTEM LIBRARY"),
305da2e3ebdSchin 	C("USER LIBRARY"),
306da2e3ebdSchin 	C("FILE FORMATS"),
307da2e3ebdSchin 	C("MISCELLANEOUS"),
308da2e3ebdSchin 	C("GAMES and DEMOS"),
309da2e3ebdSchin 	C("SPECIAL FILES"),
310da2e3ebdSchin 	C("ADMINISTRATIVE COMMANDS"),
311da2e3ebdSchin 	C("GUIs"),
312da2e3ebdSchin };
313da2e3ebdSchin 
314da2e3ebdSchin /*
315da2e3ebdSchin  * list of common man page strings
316da2e3ebdSchin  * NOTE: add but do not delete from this table
317da2e3ebdSchin  */
318da2e3ebdSchin 
319da2e3ebdSchin static Msg_t		C_LC_MESSAGES_libast[] =
320da2e3ebdSchin {
321da2e3ebdSchin 	{ C("APPLICATION USAGE") },
322da2e3ebdSchin 	{ C("ASYNCHRONOUS EVENTS") },
323da2e3ebdSchin 	{ C("BUGS") },
324da2e3ebdSchin 	{ C("CAVEATS") },
325da2e3ebdSchin 	{ C("CONSEQUENCES OF ERRORS") },
326da2e3ebdSchin 	{ C("DESCRIPTION") },
327da2e3ebdSchin 	{ C("ENVIRONMENT VARIABLES") },
328da2e3ebdSchin 	{ C("EXAMPLES") },
329da2e3ebdSchin 	{ C("EXIT STATUS") },
330da2e3ebdSchin 	{ C("EXTENDED DESCRIPTION") },
331da2e3ebdSchin 	{ C("INPUT FILES") },
332da2e3ebdSchin 	{ C("LIBRARY") },
333da2e3ebdSchin 	{ C("NAME") },
334da2e3ebdSchin 	{ C("OPERANDS") },
335da2e3ebdSchin 	{ C("OPTIONS") },
336da2e3ebdSchin 	{ C("OUTPUT FILES") },
337*b30d1939SAndy Fiddaman 	{ C("PLUGIN") },
338da2e3ebdSchin 	{ C("SEE ALSO") },
339da2e3ebdSchin 	{ C("STDERR") },
340da2e3ebdSchin 	{ C("STDIN") },
341da2e3ebdSchin 	{ C("STDOUT") },
342da2e3ebdSchin 	{ C("SYNOPSIS") },
343da2e3ebdSchin 	{ C("author") },
344da2e3ebdSchin 	{ C("copyright") },
345da2e3ebdSchin 	{ C("license") },
346da2e3ebdSchin 	{ C("name") },
347da2e3ebdSchin 	{ C("path") },
348da2e3ebdSchin 	{ C("version") },
349da2e3ebdSchin };
350da2e3ebdSchin 
351da2e3ebdSchin /*
352da2e3ebdSchin  * 2007-03-19 move opt_info from _opt_info_ to (*_opt_data_)
353da2e3ebdSchin  *	      to allow future Opt_t growth
354da2e3ebdSchin  *            by 2009 _opt_info_ can be static
355da2e3ebdSchin  */
356da2e3ebdSchin 
357da2e3ebdSchin #if _BLD_ast && defined(__EXPORT__)
358da2e3ebdSchin #define extern		extern __EXPORT__
359da2e3ebdSchin #endif
360da2e3ebdSchin 
361da2e3ebdSchin extern Opt_t	_opt_info_;
362da2e3ebdSchin 
363da2e3ebdSchin Opt_t		_opt_info_ = { 0,0,0,0,0,0,0,{0},{0},0,0,0,{0},{0},&state };
364da2e3ebdSchin 
365da2e3ebdSchin #undef	extern
366da2e3ebdSchin 
367da2e3ebdSchin __EXTERN__(Opt_t, _opt_info_);
368da2e3ebdSchin 
369da2e3ebdSchin __EXTERN__(Opt_t*, _opt_infop_);
370da2e3ebdSchin 
371da2e3ebdSchin Opt_t*		_opt_infop_ = &_opt_info_;
372da2e3ebdSchin 
373*b30d1939SAndy Fiddaman Optstate_t*
optstate(Opt_t * p)374*b30d1939SAndy Fiddaman optstate(Opt_t* p)
375*b30d1939SAndy Fiddaman {
376*b30d1939SAndy Fiddaman 	return &state;
377*b30d1939SAndy Fiddaman }
378*b30d1939SAndy Fiddaman 
379*b30d1939SAndy Fiddaman #if DEBUG || _BLD_DEBUG
380da2e3ebdSchin 
381da2e3ebdSchin /*
382da2e3ebdSchin  * debug usage string segment format
383da2e3ebdSchin  */
384da2e3ebdSchin 
385da2e3ebdSchin static char*
show(register char * s)386da2e3ebdSchin show(register char* s)
387da2e3ebdSchin {
388da2e3ebdSchin 	register int	c;
389da2e3ebdSchin 	register char*	t;
390da2e3ebdSchin 	register char*	e;
391da2e3ebdSchin 
392da2e3ebdSchin 	static char	buf[32];
393da2e3ebdSchin 
394da2e3ebdSchin 	if (!s)
395da2e3ebdSchin 		return "(null)";
396da2e3ebdSchin 	t = buf;
397da2e3ebdSchin 	e = buf + sizeof(buf) - 2;
398da2e3ebdSchin 	while (t < e)
399da2e3ebdSchin 	{
400da2e3ebdSchin 		switch (c = *s++)
401da2e3ebdSchin 		{
402da2e3ebdSchin 		case 0:
403da2e3ebdSchin 			goto done;
404da2e3ebdSchin 		case '\a':
405da2e3ebdSchin 			*t++ = '\\';
406da2e3ebdSchin 			c = 'a';
407da2e3ebdSchin 			break;
408da2e3ebdSchin 		case '\b':
409da2e3ebdSchin 			*t++ = '\\';
410da2e3ebdSchin 			c = 'b';
411da2e3ebdSchin 			break;
412da2e3ebdSchin 		case '\f':
413da2e3ebdSchin 			*t++ = '\\';
414da2e3ebdSchin 			c = 'f';
415da2e3ebdSchin 			break;
4163e14f97fSRoger A. Faulkner 		case '\n':
4173e14f97fSRoger A. Faulkner 			*t++ = '\\';
4183e14f97fSRoger A. Faulkner 			c = 'n';
4193e14f97fSRoger A. Faulkner 			break;
4203e14f97fSRoger A. Faulkner 		case '\t':
4213e14f97fSRoger A. Faulkner 			*t++ = '\\';
4223e14f97fSRoger A. Faulkner 			c = 't';
4233e14f97fSRoger A. Faulkner 			break;
424da2e3ebdSchin 		case '\v':
425da2e3ebdSchin 			*t++ = '\\';
426da2e3ebdSchin 			c = 'v';
427da2e3ebdSchin 			break;
428da2e3ebdSchin 		}
429da2e3ebdSchin 		*t++ = c;
430da2e3ebdSchin 	}
431da2e3ebdSchin  done:
432da2e3ebdSchin 	*t = 0;
433da2e3ebdSchin 	return buf;
434da2e3ebdSchin }
435da2e3ebdSchin 
436da2e3ebdSchin #endif
437da2e3ebdSchin 
438*b30d1939SAndy Fiddaman typedef struct Section_s
439*b30d1939SAndy Fiddaman {
440*b30d1939SAndy Fiddaman 	const char	section[4];
441*b30d1939SAndy Fiddaman 	const char*	name;
442*b30d1939SAndy Fiddaman } Section_t;
443*b30d1939SAndy Fiddaman 
444*b30d1939SAndy Fiddaman static const Section_t	sections[] =
445*b30d1939SAndy Fiddaman {
446*b30d1939SAndy Fiddaman 	"1M",	"MAKE ASSERTION OPERATORS AND RULES",
447*b30d1939SAndy Fiddaman 	"1",	"USER COMMANDS",
448*b30d1939SAndy Fiddaman 	"2",	"SYSTEM CALLS",
449*b30d1939SAndy Fiddaman 	"3F",	"FORTRAN LIBRARY ROUTINES",
450*b30d1939SAndy Fiddaman 	"3K",	"KERNEL VM LIBRARY FUNCTIONS",
451*b30d1939SAndy Fiddaman 	"3L",	"LIGHTWEIGHT PROCESSES LIBRARY",
452*b30d1939SAndy Fiddaman 	"3M",	"MATHEMATICAL LIBRARY",
453*b30d1939SAndy Fiddaman 	"3N",	"NETWORK FUNCTIONS",
454*b30d1939SAndy Fiddaman 	"3R",	"RPC SERVICES LIBRARY",
455*b30d1939SAndy Fiddaman 	"3S",	"STANDARD I/O FUNCTIONS",
456*b30d1939SAndy Fiddaman 	"3V",	"SYSTEM V LIBRARY",
457*b30d1939SAndy Fiddaman 	"3",	"C LIBRARY FUNCTIONS",
458*b30d1939SAndy Fiddaman 	"4F",	"PROTOCOL FAMILIES",
459*b30d1939SAndy Fiddaman 	"4P",	"PROTOCOLS",
460*b30d1939SAndy Fiddaman 	"4",	"DEVICES AND NETWORK INTERFACES",
461*b30d1939SAndy Fiddaman 	"5P",	"PLUGINS",
462*b30d1939SAndy Fiddaman 	"5",	"FILE FORMATS",
463*b30d1939SAndy Fiddaman 	"6",	"GAMES AND DEMOS",
464*b30d1939SAndy Fiddaman 	"7",	"PUBLIC FILES AND TABLES",
465*b30d1939SAndy Fiddaman 	"8",	"ADMINISTRATIVE COMMANDS",
466*b30d1939SAndy Fiddaman 	"L",	"LOCAL COMMANDS",
467*b30d1939SAndy Fiddaman };
468*b30d1939SAndy Fiddaman 
469*b30d1939SAndy Fiddaman /*
470*b30d1939SAndy Fiddaman  * return section name given abbreviation
471*b30d1939SAndy Fiddaman  */
472*b30d1939SAndy Fiddaman 
473*b30d1939SAndy Fiddaman static char*
secname(char * section)474*b30d1939SAndy Fiddaman secname(char* section)
475*b30d1939SAndy Fiddaman {
476*b30d1939SAndy Fiddaman 	int		i;
477*b30d1939SAndy Fiddaman 	char*		b;
478*b30d1939SAndy Fiddaman 	char*		t;
479*b30d1939SAndy Fiddaman 	const char*	s;
480*b30d1939SAndy Fiddaman 
481*b30d1939SAndy Fiddaman 	b = t = fmtbuf(64);
482*b30d1939SAndy Fiddaman 	if (section[1])
483*b30d1939SAndy Fiddaman 	{
484*b30d1939SAndy Fiddaman 		switch (section[2] ? section[2] : section[1])
485*b30d1939SAndy Fiddaman 		{
486*b30d1939SAndy Fiddaman 		case 'C':
487*b30d1939SAndy Fiddaman 			s = "COMPATIBILITY ";
488*b30d1939SAndy Fiddaman 			break;
489*b30d1939SAndy Fiddaman 		case 'U':
490*b30d1939SAndy Fiddaman 			s = "UWIN ";
491*b30d1939SAndy Fiddaman 			break;
492*b30d1939SAndy Fiddaman 		case 'X':
493*b30d1939SAndy Fiddaman 			s = "MISCELLANEOUS ";
494*b30d1939SAndy Fiddaman 			break;
495*b30d1939SAndy Fiddaman 		default:
496*b30d1939SAndy Fiddaman 			s = 0;
497*b30d1939SAndy Fiddaman 			break;
498*b30d1939SAndy Fiddaman 		}
499*b30d1939SAndy Fiddaman 		if (s)
500*b30d1939SAndy Fiddaman 			t = strcopy(t, s);
501*b30d1939SAndy Fiddaman 	}
502*b30d1939SAndy Fiddaman 	s = 0;
503*b30d1939SAndy Fiddaman 	for (i = 0; i < elementsof(sections); i++)
504*b30d1939SAndy Fiddaman 		if (section[0] == sections[i].section[0] && (section[1] == sections[i].section[1] || !sections[i].section[1]))
505*b30d1939SAndy Fiddaman 		{
506*b30d1939SAndy Fiddaman 			s = sections[i].name;
507*b30d1939SAndy Fiddaman 			break;
508*b30d1939SAndy Fiddaman 		}
509*b30d1939SAndy Fiddaman 	if (!s)
510*b30d1939SAndy Fiddaman 	{
511*b30d1939SAndy Fiddaman 		t = strcopy(t, "SECTION ");
512*b30d1939SAndy Fiddaman 		s = section;
513*b30d1939SAndy Fiddaman 	}
514*b30d1939SAndy Fiddaman 	strcopy(t, s);
515*b30d1939SAndy Fiddaman 	return b;
516*b30d1939SAndy Fiddaman }
517*b30d1939SAndy Fiddaman 
518da2e3ebdSchin /*
519da2e3ebdSchin  * pop the push stack
520da2e3ebdSchin  */
521da2e3ebdSchin 
522da2e3ebdSchin static Push_t*
pop(register Push_t * psp)523da2e3ebdSchin pop(register Push_t* psp)
524da2e3ebdSchin {
525da2e3ebdSchin 	register Push_t*	tsp;
526da2e3ebdSchin 
527da2e3ebdSchin 	while (tsp = psp)
528da2e3ebdSchin 	{
529da2e3ebdSchin 		psp = psp->next;
530da2e3ebdSchin 		free(tsp);
531da2e3ebdSchin 	}
532da2e3ebdSchin 	return 0;
533da2e3ebdSchin }
534da2e3ebdSchin 
535da2e3ebdSchin /*
536da2e3ebdSchin  * skip over line space to the next token
537da2e3ebdSchin  */
538da2e3ebdSchin 
539da2e3ebdSchin static char*
next(register char * s,int version)540da2e3ebdSchin next(register char* s, int version)
541da2e3ebdSchin {
542da2e3ebdSchin 	register char*	b;
543da2e3ebdSchin 
544da2e3ebdSchin 	while (*s == '\t' || *s == '\r' || version >= 1 && *s == ' ')
545da2e3ebdSchin 		s++;
546da2e3ebdSchin 	if (*s == '\n')
547da2e3ebdSchin 	{
548da2e3ebdSchin 		b = s;
549da2e3ebdSchin 		while (*++s == ' ' || *s == '\t' || *s == '\r');
550da2e3ebdSchin 		if (*s == '\n')
551da2e3ebdSchin 			return b;
552da2e3ebdSchin 	}
553da2e3ebdSchin 	return s;
554da2e3ebdSchin }
555da2e3ebdSchin 
556da2e3ebdSchin /*
557da2e3ebdSchin  * skip to t1 or t2 or t3, whichever first, in s
558da2e3ebdSchin  *	n==0	outside [...]
559da2e3ebdSchin  *	n==1	inside [...] before ?
560da2e3ebdSchin  *	n==2	inside [...] after ?
561da2e3ebdSchin  *	b==0	outside {...}
562da2e3ebdSchin  *	b==1	inside {...}
563da2e3ebdSchin  * past skips past the terminator to the next token
564da2e3ebdSchin  * otherwise a pointer to the terminator is returned
565da2e3ebdSchin  *
566da2e3ebdSchin  * ]] for ] inside [...]
567da2e3ebdSchin  * ?? for ? inside [...] before ?
568da2e3ebdSchin  * :: for : inside [...] before ?
569da2e3ebdSchin  */
570da2e3ebdSchin 
571da2e3ebdSchin 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)572da2e3ebdSchin skip(register char* s, register int t1, register int t2, register int t3, register int n, register int b, int past, int version)
573da2e3ebdSchin {
574da2e3ebdSchin 	register int	c;
575da2e3ebdSchin 	register int	on = n;
576da2e3ebdSchin 	register int	ob = b;
577da2e3ebdSchin 
578da2e3ebdSchin 	if (version < 1)
579da2e3ebdSchin 	{
580da2e3ebdSchin 		n = n >= 1;
581da2e3ebdSchin 		for (;;)
582da2e3ebdSchin 		{
583da2e3ebdSchin 			switch (*s++)
584da2e3ebdSchin 			{
585da2e3ebdSchin 			case 0:
586da2e3ebdSchin 				break;
587da2e3ebdSchin 			case '[':
588da2e3ebdSchin 				n++;
589da2e3ebdSchin 				continue;
590da2e3ebdSchin 			case ']':
591da2e3ebdSchin 				if (--n <= 0)
592da2e3ebdSchin 					break;
593da2e3ebdSchin 				continue;
594da2e3ebdSchin 			default:
595da2e3ebdSchin 				continue;
596da2e3ebdSchin 			}
597da2e3ebdSchin 			break;
598da2e3ebdSchin 		}
599da2e3ebdSchin 	}
600da2e3ebdSchin 	else while (c = *s++)
601da2e3ebdSchin 	{
602da2e3ebdSchin 		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)));
603da2e3ebdSchin 		if (c == '[')
604da2e3ebdSchin 		{
605da2e3ebdSchin 			if (!n)
606da2e3ebdSchin 				n = 1;
607da2e3ebdSchin 		}
608da2e3ebdSchin 		else if (c == ']')
609da2e3ebdSchin 		{
610da2e3ebdSchin 			if (n)
611da2e3ebdSchin 			{
612da2e3ebdSchin 				if (*s == ']')
613da2e3ebdSchin 					s++;
614da2e3ebdSchin 				else if (on == 1)
615da2e3ebdSchin 					break;
616da2e3ebdSchin 				else
617da2e3ebdSchin 					n = 0;
618da2e3ebdSchin 			}
619da2e3ebdSchin 		}
620da2e3ebdSchin 		else if (c == GO)
621da2e3ebdSchin 		{
622da2e3ebdSchin 			if (n == 0)
623da2e3ebdSchin 				b++;
624da2e3ebdSchin 		}
625da2e3ebdSchin 		else if (c == OG)
626da2e3ebdSchin 		{
627da2e3ebdSchin 			if (n == 0 && b-- == ob)
628da2e3ebdSchin 				break;
629da2e3ebdSchin 		}
630da2e3ebdSchin 		else if (c == '?')
631da2e3ebdSchin 		{
632da2e3ebdSchin 			if (n == 1)
633da2e3ebdSchin 			{
634da2e3ebdSchin 				if (*s == '?')
635da2e3ebdSchin 					s++;
636da2e3ebdSchin 				else
637da2e3ebdSchin 				{
638da2e3ebdSchin 					if (n == on && (c == t1 || c == t2 || c == t3))
639da2e3ebdSchin 						break;
640da2e3ebdSchin 					n = 2;
641da2e3ebdSchin 				}
642da2e3ebdSchin 			}
643da2e3ebdSchin 		}
644da2e3ebdSchin 		else if (n == on && (c == t1 || c == t2 || c == t3))
645da2e3ebdSchin 		{
646da2e3ebdSchin 			if (n == 1 && c == ':' && *s == c)
647da2e3ebdSchin 				s++;
648da2e3ebdSchin 			else
649da2e3ebdSchin 				break;
650da2e3ebdSchin 		}
651da2e3ebdSchin 	}
652da2e3ebdSchin 	return past && *(s - 1) ? next(s, version) : s - 1;
653da2e3ebdSchin }
654da2e3ebdSchin 
655*b30d1939SAndy Fiddaman /*
656*b30d1939SAndy Fiddaman  * *s points to '(' on input
657*b30d1939SAndy Fiddaman  * return is one past matching ')'
658*b30d1939SAndy Fiddaman  */
659*b30d1939SAndy Fiddaman 
660*b30d1939SAndy Fiddaman static char*
nest(register char * s)661*b30d1939SAndy Fiddaman nest(register char* s)
662*b30d1939SAndy Fiddaman {
663*b30d1939SAndy Fiddaman 	int	n;
664*b30d1939SAndy Fiddaman 
665*b30d1939SAndy Fiddaman 	n = 0;
666*b30d1939SAndy Fiddaman 	for (;;)
667*b30d1939SAndy Fiddaman 	{
668*b30d1939SAndy Fiddaman 		switch (*s++)
669*b30d1939SAndy Fiddaman 		{
670*b30d1939SAndy Fiddaman 		case '(':
671*b30d1939SAndy Fiddaman 			n++;
672*b30d1939SAndy Fiddaman 			continue;
673*b30d1939SAndy Fiddaman 		case ')':
674*b30d1939SAndy Fiddaman 			if (!--n)
675*b30d1939SAndy Fiddaman 				break;
676*b30d1939SAndy Fiddaman 			continue;
677*b30d1939SAndy Fiddaman 		default:
678*b30d1939SAndy Fiddaman 			continue;
679*b30d1939SAndy Fiddaman 		}
680*b30d1939SAndy Fiddaman 		break;
681*b30d1939SAndy Fiddaman 	}
682*b30d1939SAndy Fiddaman 	return s;
683*b30d1939SAndy Fiddaman }
684*b30d1939SAndy Fiddaman 
685da2e3ebdSchin /*
686da2e3ebdSchin  * match s with t
687da2e3ebdSchin  * t translated if possible
688*b30d1939SAndy Fiddaman  * embedded { - _ ' } ignored
689da2e3ebdSchin  * * separates required prefix from optional suffix
690da2e3ebdSchin  * otherwise prefix match
691da2e3ebdSchin  */
692da2e3ebdSchin 
693da2e3ebdSchin static int
match(char * s,char * t,int version,const char * id,const char * catalog)6943e14f97fSRoger A. Faulkner match(char* s, char* t, int version, const char* id, const char* catalog)
695da2e3ebdSchin {
696da2e3ebdSchin 	register char*	w;
697da2e3ebdSchin 	register char*	x;
698da2e3ebdSchin 	char*		xw;
699da2e3ebdSchin 	char*		ww;
700da2e3ebdSchin 	int		n;
701da2e3ebdSchin 	int		v;
702da2e3ebdSchin 	int		j;
703da2e3ebdSchin 
704da2e3ebdSchin 	for (n = 0; n < 2; n++)
705da2e3ebdSchin 	{
706da2e3ebdSchin 		if (n)
707da2e3ebdSchin 			x = t;
708da2e3ebdSchin 		else
709da2e3ebdSchin 		{
710da2e3ebdSchin 			if (catalog)
711da2e3ebdSchin 			{
712da2e3ebdSchin 				w = skip(t, ':', '?', 0, 1, 0, 0, version);
713da2e3ebdSchin 				w = sfprints("%-.*s", w - t, t);
7143e14f97fSRoger A. Faulkner 				x = T(id, catalog, w);
715da2e3ebdSchin 				if (x == w)
716da2e3ebdSchin 					continue;
717da2e3ebdSchin 			}
718da2e3ebdSchin 			x = T(NiL, ID, t);
719da2e3ebdSchin 			if (x == t)
720da2e3ebdSchin 				continue;
721da2e3ebdSchin 		}
722da2e3ebdSchin 		do
723da2e3ebdSchin 		{
724da2e3ebdSchin 			v = 0;
725da2e3ebdSchin 			xw = x;
726da2e3ebdSchin 			w = ww = s;
727da2e3ebdSchin 			while (*x && *w)
728da2e3ebdSchin 			{
729da2e3ebdSchin 				if (isupper(*x))
730da2e3ebdSchin 					xw = x;
731da2e3ebdSchin 				if (isupper(*w))
732da2e3ebdSchin 					ww = w;
733da2e3ebdSchin 				if (*x == '*' && !v++ || *x == '\a')
734da2e3ebdSchin 				{
735da2e3ebdSchin 					if (*x == '\a')
736da2e3ebdSchin 						do
737da2e3ebdSchin 						{
738da2e3ebdSchin 							if (!*++x)
739da2e3ebdSchin 							{
740da2e3ebdSchin 								x--;
741da2e3ebdSchin 								break;
742da2e3ebdSchin 							}
743da2e3ebdSchin 						} while (*x != '\a');
744da2e3ebdSchin 					j = *(x + 1);
745da2e3ebdSchin 					if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
746da2e3ebdSchin 						while (*w)
747da2e3ebdSchin 							w++;
748da2e3ebdSchin 				}
749*b30d1939SAndy Fiddaman 				else if (SEP(*x))
750da2e3ebdSchin 					xw = ++x;
751*b30d1939SAndy Fiddaman 				else if (SEP(*w) && w != s)
752da2e3ebdSchin 					ww = ++w;
753da2e3ebdSchin 				else if (*x == *w)
754da2e3ebdSchin 				{
755da2e3ebdSchin 					x++;
756da2e3ebdSchin 					w++;
757da2e3ebdSchin 				}
758da2e3ebdSchin 				else if (w == ww && x == xw)
759da2e3ebdSchin 					break;
760da2e3ebdSchin 				else
761da2e3ebdSchin 				{
762da2e3ebdSchin 					if (x != xw)
763da2e3ebdSchin 					{
764*b30d1939SAndy Fiddaman 						while (*x && !SEP(*x) && !isupper(*x))
765da2e3ebdSchin 							x++;
766da2e3ebdSchin 						if (!*x)
767da2e3ebdSchin 							break;
768*b30d1939SAndy Fiddaman 						if (SEP(*x))
769da2e3ebdSchin 							x++;
770da2e3ebdSchin 						xw = x;
771da2e3ebdSchin 					}
772da2e3ebdSchin 					while (w > ww && *w != *x)
773da2e3ebdSchin 						w--;
774da2e3ebdSchin 				}
775da2e3ebdSchin 			}
776da2e3ebdSchin 			if (!*w)
777da2e3ebdSchin 			{
778da2e3ebdSchin 				if (!v)
779da2e3ebdSchin 				{
780da2e3ebdSchin 					for (;;)
781da2e3ebdSchin 					{
782da2e3ebdSchin 						switch (*x++)
783da2e3ebdSchin 						{
784da2e3ebdSchin 						case 0:
785da2e3ebdSchin 						case ':':
786da2e3ebdSchin 						case '|':
787da2e3ebdSchin 						case '?':
788da2e3ebdSchin 						case ']':
789da2e3ebdSchin 							return 1;
790da2e3ebdSchin 						case '*':
791da2e3ebdSchin 							break;
792da2e3ebdSchin 						default:
793da2e3ebdSchin 							continue;
794da2e3ebdSchin 						}
795da2e3ebdSchin 						break;
796da2e3ebdSchin 					}
797da2e3ebdSchin 					break;
798da2e3ebdSchin 				}
799da2e3ebdSchin 				return 1;
800da2e3ebdSchin 			}
801da2e3ebdSchin 		} while (*(x = skip(x, '|', 0, 0, 1, 0, 0, version)) == '|' && x++);
802da2e3ebdSchin 	}
803da2e3ebdSchin 	return 0;
804da2e3ebdSchin }
805da2e3ebdSchin 
806da2e3ebdSchin /*
807da2e3ebdSchin  * prefix search for s in tab with num elements of size
808da2e3ebdSchin  * with optional translation
809da2e3ebdSchin  */
810da2e3ebdSchin 
811da2e3ebdSchin static void*
search(const void * tab,size_t num,size_t siz,char * s)812da2e3ebdSchin search(const void* tab, size_t num, size_t siz, char* s)
813da2e3ebdSchin {
814da2e3ebdSchin 	register char*	p;
815da2e3ebdSchin 	register char*	e;
816da2e3ebdSchin 
817da2e3ebdSchin 	for (e = (p = (char*)tab) + num * siz; p < e; p += siz)
8183e14f97fSRoger A. Faulkner 		if (match(s, *((char**)p), -1, NiL, NiL))
819da2e3ebdSchin 			return (void*)p;
820da2e3ebdSchin 	return 0;
821da2e3ebdSchin }
822da2e3ebdSchin 
823da2e3ebdSchin /*
824*b30d1939SAndy Fiddaman  * save ap+bp+cp and return the saved pointer
825da2e3ebdSchin  */
826da2e3ebdSchin 
827da2e3ebdSchin static char*
save(const char * ap,size_t az,const char * bp,size_t bz,const char * cp,size_t cz)828*b30d1939SAndy Fiddaman save(const char* ap, size_t az, const char* bp, size_t bz, const char* cp, size_t cz)
829da2e3ebdSchin {
830*b30d1939SAndy Fiddaman 	char*		b;
831*b30d1939SAndy Fiddaman 	char*		e;
832*b30d1939SAndy Fiddaman 	const char*	ep;
833da2e3ebdSchin 	Save_t*		p;
8347c2fbfb3SApril Chin 	Dtdisc_t*	d;
835*b30d1939SAndy Fiddaman 	char		buf[1024];
836da2e3ebdSchin 
837da2e3ebdSchin 	static Dt_t*	dict;
838da2e3ebdSchin 
839da2e3ebdSchin 	if (!dict)
840da2e3ebdSchin 	{
8417c2fbfb3SApril Chin 		if (!(d = newof(0, Dtdisc_t, 1, 0)))
842*b30d1939SAndy Fiddaman 			return (char*)ap;
8437c2fbfb3SApril Chin 		d->key = offsetof(Save_t, text);
844*b30d1939SAndy Fiddaman 		if (!(dict = dtopen(d, Dtset)))
845*b30d1939SAndy Fiddaman 			return (char*)ap;
846da2e3ebdSchin 	}
847*b30d1939SAndy Fiddaman 	b = buf;
848*b30d1939SAndy Fiddaman 	e = b + sizeof(buf) - 1;
849*b30d1939SAndy Fiddaman 	for (ep = ap + az; b < e && ap < ep; *b++ = *ap++);
850*b30d1939SAndy Fiddaman 	if (bp)
851da2e3ebdSchin 	{
852*b30d1939SAndy Fiddaman 		for (ep = bp + bz; b < e && bp < ep; *b++ = *bp++);
853*b30d1939SAndy Fiddaman 		if (cp)
854*b30d1939SAndy Fiddaman 			for (ep = cp + cz; b < e && cp < ep; *b++ = *cp++);
855*b30d1939SAndy Fiddaman 	}
856*b30d1939SAndy Fiddaman 	*b = 0;
857*b30d1939SAndy Fiddaman 	if (!(p = (Save_t*)dtmatch(dict, buf)))
858*b30d1939SAndy Fiddaman 	{
859*b30d1939SAndy Fiddaman 		if (!(p = newof(0, Save_t, 1, b - buf)))
860*b30d1939SAndy Fiddaman 			return (char*)ap;
861*b30d1939SAndy Fiddaman 		strcpy(p->text, buf);
862da2e3ebdSchin 		dtinsert(dict, p);
863da2e3ebdSchin 	}
864da2e3ebdSchin 	return p->text;
865da2e3ebdSchin }
866da2e3ebdSchin 
867*b30d1939SAndy Fiddaman /*
868*b30d1939SAndy Fiddaman  * expand \f...\f info
869*b30d1939SAndy Fiddaman  * *p set to next char after second \f
870*b30d1939SAndy Fiddaman  * expanded value returned
871*b30d1939SAndy Fiddaman  */
872*b30d1939SAndy Fiddaman 
873*b30d1939SAndy Fiddaman static char*
expand(register char * s,register char * e,char ** p,Sfio_t * ip,char * id)874*b30d1939SAndy Fiddaman expand(register char* s, register char* e, char** p, Sfio_t* ip, char* id)
875*b30d1939SAndy Fiddaman {
876*b30d1939SAndy Fiddaman 	register int	c;
877*b30d1939SAndy Fiddaman 	register char*	b = s;
878*b30d1939SAndy Fiddaman 	int		n;
879*b30d1939SAndy Fiddaman 
880*b30d1939SAndy Fiddaman 	n = sfstrtell(ip);
881*b30d1939SAndy Fiddaman 	c = 1;
882*b30d1939SAndy Fiddaman 	while ((!e || s < e) && (c = *s++) && c != '\f');
883*b30d1939SAndy Fiddaman 	sfwrite(ip, b, s - b - 1);
884*b30d1939SAndy Fiddaman 	sfputc(ip, 0);
885*b30d1939SAndy Fiddaman 	b = sfstrbase(ip) + n;
886*b30d1939SAndy Fiddaman 	n = sfstrtell(ip);
887*b30d1939SAndy Fiddaman 	if (!c)
888*b30d1939SAndy Fiddaman 		s--;
889*b30d1939SAndy Fiddaman 	if (*b == '?')
890*b30d1939SAndy Fiddaman 	{
891*b30d1939SAndy Fiddaman 		if (!*++b || streq(b, "NAME"))
892*b30d1939SAndy Fiddaman 		{
893*b30d1939SAndy Fiddaman 			if (!(b = id))
894*b30d1939SAndy Fiddaman 				b = "command";
895*b30d1939SAndy Fiddaman 			sfstrseek(ip, 0, SEEK_SET);
896*b30d1939SAndy Fiddaman 			sfputr(ip, b, -1);
897*b30d1939SAndy Fiddaman 			n = 0;
898*b30d1939SAndy Fiddaman 		}
899*b30d1939SAndy Fiddaman 		else
900*b30d1939SAndy Fiddaman 			n = 1;
901*b30d1939SAndy Fiddaman 	}
902*b30d1939SAndy Fiddaman 	else if (!opt_info.disc || !opt_info.disc->infof || (*opt_info.disc->infof)(&opt_info, ip, b, opt_info.disc) < 0)
903*b30d1939SAndy Fiddaman 		n = 0;
904*b30d1939SAndy Fiddaman 	*p = s;
905*b30d1939SAndy Fiddaman 	if (s = sfstruse(ip))
906*b30d1939SAndy Fiddaman 		s += n;
907*b30d1939SAndy Fiddaman 	else
908*b30d1939SAndy Fiddaman 		s = "error";
909*b30d1939SAndy Fiddaman 	return s;
910*b30d1939SAndy Fiddaman }
911*b30d1939SAndy Fiddaman 
912*b30d1939SAndy Fiddaman /*
913*b30d1939SAndy Fiddaman  * initialize the translation dictionary and flag maps
914*b30d1939SAndy Fiddaman  */
915*b30d1939SAndy Fiddaman 
916*b30d1939SAndy Fiddaman static void
initdict(void)917*b30d1939SAndy Fiddaman initdict(void)
918*b30d1939SAndy Fiddaman {
919*b30d1939SAndy Fiddaman 	register int	n;
920*b30d1939SAndy Fiddaman 
921*b30d1939SAndy Fiddaman 	state.vp = sfstropen();
922*b30d1939SAndy Fiddaman 	state.msgdisc.key = offsetof(Msg_t, text);
923*b30d1939SAndy Fiddaman 	state.msgdisc.size = -1;
924*b30d1939SAndy Fiddaman 	state.msgdisc.link = offsetof(Msg_t, link);
925*b30d1939SAndy Fiddaman 	if (state.msgdict = dtopen(&state.msgdisc, Dtset))
926*b30d1939SAndy Fiddaman 		for (n = 0; n < elementsof(C_LC_MESSAGES_libast); n++)
927*b30d1939SAndy Fiddaman 			dtinsert(state.msgdict, C_LC_MESSAGES_libast + n);
928*b30d1939SAndy Fiddaman }
929*b30d1939SAndy Fiddaman 
930da2e3ebdSchin /*
931da2e3ebdSchin  * initialize the attributes for pass p from opt string s
932da2e3ebdSchin  */
933da2e3ebdSchin 
934da2e3ebdSchin static int
init(register char * s,Optpass_t * p)935da2e3ebdSchin init(register char* s, Optpass_t* p)
936da2e3ebdSchin {
937da2e3ebdSchin 	register char*	t;
9383e14f97fSRoger A. Faulkner 	register char*	u;
939da2e3ebdSchin 	register int	c;
940da2e3ebdSchin 	register int	a;
941da2e3ebdSchin 	register int	n;
942*b30d1939SAndy Fiddaman 	char*		e;
943*b30d1939SAndy Fiddaman 	int		l;
944da2e3ebdSchin 
945*b30d1939SAndy Fiddaman 	if (!state.localized)
946da2e3ebdSchin 	{
947*b30d1939SAndy Fiddaman 		state.localized = 1;
948da2e3ebdSchin #if !_PACKAGE_astsa
949da2e3ebdSchin 		if (!ast.locale.serial)
950da2e3ebdSchin 			setlocale(LC_ALL, "");
951da2e3ebdSchin #endif
952*b30d1939SAndy Fiddaman 		state.xp = sfstropen();
953da2e3ebdSchin 		if (!map[OPT_FLAGS[0]])
954da2e3ebdSchin 			for (n = 0, t = OPT_FLAGS; *t; t++)
955da2e3ebdSchin 				map[*t] = ++n;
956da2e3ebdSchin 	}
957da2e3ebdSchin #if _BLD_DEBUG
958*b30d1939SAndy Fiddaman 	error(-2, "optget debug");
959da2e3ebdSchin #endif
960da2e3ebdSchin 	p->oopts = s;
961da2e3ebdSchin 	p->version = 0;
962da2e3ebdSchin 	p->prefix = 2;
963*b30d1939SAndy Fiddaman 	p->section[0] = '1';
964*b30d1939SAndy Fiddaman 	p->section[1] = 0;
965da2e3ebdSchin 	p->flags = 0;
9663e14f97fSRoger A. Faulkner 	p->id = error_info.id;
967da2e3ebdSchin 	p->catalog = 0;
968da2e3ebdSchin 	s = next(s, 0);
969da2e3ebdSchin 	if (*s == ':')
970da2e3ebdSchin 		s++;
971da2e3ebdSchin 	if (*s == '+')
972da2e3ebdSchin 		s++;
973da2e3ebdSchin 	s = next(s, 0);
974da2e3ebdSchin 	if (*s++ == '[')
975da2e3ebdSchin 	{
976da2e3ebdSchin 		if (*s == '+')
977da2e3ebdSchin 			p->version = 1;
978da2e3ebdSchin 		else if (*s++ == '-')
979da2e3ebdSchin 		{
980da2e3ebdSchin 			if (*s == '?' || *s == ']')
981da2e3ebdSchin 				p->version = 1;
982da2e3ebdSchin 			else
983da2e3ebdSchin 			{
9847c2fbfb3SApril Chin 				if (!isdigit(*s))
985da2e3ebdSchin 					p->version = 1;
986da2e3ebdSchin 				else
9877c2fbfb3SApril Chin 					while (isdigit(*s))
988da2e3ebdSchin 						p->version = p->version * 10 + (*s++ - '0');
989*b30d1939SAndy Fiddaman 				while (*s && *s != ']')
990da2e3ebdSchin 				{
991*b30d1939SAndy Fiddaman 					if ((c = *s++) == '?')
992*b30d1939SAndy Fiddaman 					{
993*b30d1939SAndy Fiddaman 						p->release = s;
994*b30d1939SAndy Fiddaman 						while (*s && *s != ']')
995*b30d1939SAndy Fiddaman 							if (isspace(*s++))
996*b30d1939SAndy Fiddaman 								p->release = s;
997*b30d1939SAndy Fiddaman 						break;
998*b30d1939SAndy Fiddaman 					}
999*b30d1939SAndy Fiddaman 					else if (!isdigit(*s))
1000da2e3ebdSchin 						n = 1;
1001da2e3ebdSchin 					else
1002da2e3ebdSchin 					{
1003da2e3ebdSchin 						n = 0;
10047c2fbfb3SApril Chin 						while (isdigit(*s))
1005da2e3ebdSchin 							n = n * 10 + (*s++ - '0');
1006da2e3ebdSchin 					}
1007da2e3ebdSchin 					switch (c)
1008da2e3ebdSchin 					{
10097c2fbfb3SApril Chin 					case '+':
10107c2fbfb3SApril Chin 						p->flags |= OPT_plus;
10117c2fbfb3SApril Chin 						break;
1012*b30d1939SAndy Fiddaman 					case 'a':
1013*b30d1939SAndy Fiddaman 						p->flags |= OPT_append;
1014*b30d1939SAndy Fiddaman 						break;
1015da2e3ebdSchin 					case 'c':
1016da2e3ebdSchin 						p->flags |= OPT_cache;
1017da2e3ebdSchin 						break;
1018da2e3ebdSchin 					case 'i':
1019da2e3ebdSchin 						p->flags |= OPT_ignore;
1020da2e3ebdSchin 						break;
1021da2e3ebdSchin 					case 'l':
1022da2e3ebdSchin 						p->flags |= OPT_long;
1023da2e3ebdSchin 						break;
1024*b30d1939SAndy Fiddaman 					case 'm':
1025*b30d1939SAndy Fiddaman 						p->flags |= OPT_module;
1026*b30d1939SAndy Fiddaman 						break;
10277c2fbfb3SApril Chin 					case 'n':
10287c2fbfb3SApril Chin 						p->flags |= OPT_numeric;
10297c2fbfb3SApril Chin 						break;
1030da2e3ebdSchin 					case 'o':
1031da2e3ebdSchin 						p->flags |= OPT_old;
1032da2e3ebdSchin 						break;
1033da2e3ebdSchin 					case 'p':
1034da2e3ebdSchin 						p->prefix = n;
1035da2e3ebdSchin 						break;
1036da2e3ebdSchin 					case 's':
1037*b30d1939SAndy Fiddaman 						if (n > 1 && n < 5)
1038da2e3ebdSchin 						{
1039da2e3ebdSchin 							p->flags |= OPT_functions;
1040da2e3ebdSchin 							p->prefix = 0;
1041da2e3ebdSchin 						}
1042*b30d1939SAndy Fiddaman 						p->section[0] = '0' + (n % 10);
1043*b30d1939SAndy Fiddaman 						n = 1;
1044*b30d1939SAndy Fiddaman 						if (isupper(*s))
1045*b30d1939SAndy Fiddaman 							p->section[n++] = *s++;
1046*b30d1939SAndy Fiddaman 						if (isupper(*s))
1047*b30d1939SAndy Fiddaman 							p->section[n++] = *s++;
1048*b30d1939SAndy Fiddaman 						p->section[n] = 0;
1049da2e3ebdSchin 						break;
1050da2e3ebdSchin 					}
1051da2e3ebdSchin 				}
1052da2e3ebdSchin 			}
1053da2e3ebdSchin 		}
1054da2e3ebdSchin 		while (*s)
10553e14f97fSRoger A. Faulkner 			if (*s++ == ']')
1056da2e3ebdSchin 			{
10573e14f97fSRoger A. Faulkner 				while (isspace(*s))
1058da2e3ebdSchin 					s++;
10593e14f97fSRoger A. Faulkner 				if (*s++ == '[')
1060da2e3ebdSchin 				{
10613e14f97fSRoger A. Faulkner 					if (*s++ != '-')
10623e14f97fSRoger A. Faulkner 					{
1063*b30d1939SAndy Fiddaman 						l = 0;
1064*b30d1939SAndy Fiddaman 						if (strneq(s - 1, "+NAME?", 6) && (s += 5) || strneq(s - 1, "+LIBRARY?", 9) && (s += 8) && (l = 1) || strneq(s - 1, "+PLUGIN?", 8) && (s += 7) && (l = 1))
10653e14f97fSRoger A. Faulkner 						{
1066*b30d1939SAndy Fiddaman 							for (; *s == '\a' || *s == '\b' || *s == '\v' || *s == ' '; s++);
1067*b30d1939SAndy Fiddaman 							if (*s == '\f')
1068*b30d1939SAndy Fiddaman 							{
1069*b30d1939SAndy Fiddaman 								if (*(s + 1) == '?' && *(s + 2) == '\f')
1070*b30d1939SAndy Fiddaman 									break;
1071*b30d1939SAndy Fiddaman 								s = expand(s + 1, NiL, &e, state.xp, p->id);
1072*b30d1939SAndy Fiddaman 							}
1073*b30d1939SAndy Fiddaman 							for (t = s; *t && *t != ' ' && *t != ']'; t++);
1074*b30d1939SAndy Fiddaman 							if (t > s)
10753e14f97fSRoger A. Faulkner 							{
1076*b30d1939SAndy Fiddaman 								u = t;
1077*b30d1939SAndy Fiddaman 								if (*(t - 1) == '\a' || *(t - 1) == '\b' || *(t - 1) == '\v')
1078*b30d1939SAndy Fiddaman 									t--;
10793e14f97fSRoger A. Faulkner 								if (t > s)
10803e14f97fSRoger A. Faulkner 								{
1081*b30d1939SAndy Fiddaman 									while (*u == ' ' || *u == '\\')
1082*b30d1939SAndy Fiddaman 										u++;
1083*b30d1939SAndy Fiddaman 									if (*u == '-' || *u == ']')
10843e14f97fSRoger A. Faulkner 									{
1085*b30d1939SAndy Fiddaman 										if (!l)
1086*b30d1939SAndy Fiddaman 											p->id = save(s, t - s, 0, 0, 0, 0);
1087*b30d1939SAndy Fiddaman 										else if ((a = strlen(p->id)) <= (n = t - s) || strncmp(p->id + a - n, s, n) || *(p->id + a - n - 1) != ':')
1088*b30d1939SAndy Fiddaman 											p->id = save(p->id, strlen(p->id), "::", 2, s, t - s);
10893e14f97fSRoger A. Faulkner 									}
10903e14f97fSRoger A. Faulkner 								}
10913e14f97fSRoger A. Faulkner 							}
10923e14f97fSRoger A. Faulkner 						}
1093da2e3ebdSchin 						break;
10943e14f97fSRoger A. Faulkner 					}
10953e14f97fSRoger A. Faulkner 					if (*s == '-')
10963e14f97fSRoger A. Faulkner 						s++;
10973e14f97fSRoger A. Faulkner 					if (strneq(s, "catalog?", 8))
10983e14f97fSRoger A. Faulkner 						p->catalog = s += 8;
1099da2e3ebdSchin 				}
1100da2e3ebdSchin 			}
1101da2e3ebdSchin 	}
11023e14f97fSRoger A. Faulkner 	if (!error_info.id)
11033e14f97fSRoger A. Faulkner 	{
11043e14f97fSRoger A. Faulkner 		if (!(error_info.id = p->id))
11053e14f97fSRoger A. Faulkner 			p->id = "command";
11063e14f97fSRoger A. Faulkner 	}
11073e14f97fSRoger A. Faulkner 	else if (p->id == error_info.id)
1108*b30d1939SAndy Fiddaman 		p->id = save(p->id, strlen(p->id), 0, 0, 0, 0);
11093e14f97fSRoger A. Faulkner 	if (s = p->catalog)
1110*b30d1939SAndy Fiddaman 		p->catalog = ((t = strchr(s, ']')) && (!p->id || (t - s) != strlen(p->id) || !strneq(s, p->id, t - s))) ? save(s, t - s, 0, 0, 0, 0) : (char*)0;
1111da2e3ebdSchin 	if (!p->catalog)
1112da2e3ebdSchin 	{
11133e14f97fSRoger A. Faulkner 		if (opt_info.disc && opt_info.disc->catalog && (!p->id || !streq(opt_info.disc->catalog, p->id)))
1114da2e3ebdSchin 			p->catalog = opt_info.disc->catalog;
1115da2e3ebdSchin 		else
1116da2e3ebdSchin 			p->catalog = ID;
1117da2e3ebdSchin 	}
1118da2e3ebdSchin 	s = p->oopts;
1119da2e3ebdSchin 	if (*s == ':')
1120da2e3ebdSchin 		s++;
1121da2e3ebdSchin 	if (*s == '+')
1122da2e3ebdSchin 	{
1123da2e3ebdSchin 		s++;
1124da2e3ebdSchin 		p->flags |= OPT_plus;
1125da2e3ebdSchin 	}
11267c2fbfb3SApril Chin 	s = next(s, 0);
1127da2e3ebdSchin 	if (*s != '[')
1128da2e3ebdSchin 		for (t = s, a = 0; *t; t++)
1129da2e3ebdSchin 			if (!a && *t == '-')
1130da2e3ebdSchin 			{
1131da2e3ebdSchin 				p->flags |= OPT_minus;
1132da2e3ebdSchin 				break;
1133da2e3ebdSchin 			}
1134da2e3ebdSchin 			else if (*t == '[')
1135da2e3ebdSchin 				a++;
1136da2e3ebdSchin 			else if (*t == ']')
1137da2e3ebdSchin 				a--;
1138*b30d1939SAndy Fiddaman 	if (!p->version && (t = strchr(s, '(')) && strchr(t, ')') && (state.cp || (state.cp = sfstropen())))
1139da2e3ebdSchin 	{
1140da2e3ebdSchin 		/*
1141da2e3ebdSchin 		 * solaris long option compatibility
1142da2e3ebdSchin 		 */
1143da2e3ebdSchin 
1144da2e3ebdSchin 		p->version = 1;
1145da2e3ebdSchin 		for (t = p->oopts; t < s; t++)
1146*b30d1939SAndy Fiddaman 			sfputc(state.cp, *t);
1147da2e3ebdSchin 		n = t - p->oopts;
1148*b30d1939SAndy Fiddaman 		sfputc(state.cp, '[');
1149*b30d1939SAndy Fiddaman 		sfputc(state.cp, '-');
1150*b30d1939SAndy Fiddaman 		sfputc(state.cp, ']');
11513e14f97fSRoger A. Faulkner 		c = *s++;
11523e14f97fSRoger A. Faulkner 		while (c)
1153da2e3ebdSchin 		{
1154*b30d1939SAndy Fiddaman 			sfputc(state.cp, '[');
1155*b30d1939SAndy Fiddaman 			sfputc(state.cp, c);
1156da2e3ebdSchin 			if (a = (c = *s++) == ':')
1157da2e3ebdSchin 				c = *s++;
1158da2e3ebdSchin 			if (c == '(')
1159da2e3ebdSchin 			{
1160*b30d1939SAndy Fiddaman 				sfputc(state.cp, ':');
1161da2e3ebdSchin 				for (;;)
1162da2e3ebdSchin 				{
1163da2e3ebdSchin 					while ((c = *s++) && c != ')')
1164*b30d1939SAndy Fiddaman 						sfputc(state.cp, c);
11653e14f97fSRoger A. Faulkner 					if (!c || (c = *s++) != '(')
1166da2e3ebdSchin 						break;
1167*b30d1939SAndy Fiddaman 					sfputc(state.cp, '|');
1168da2e3ebdSchin 				}
1169da2e3ebdSchin 			}
1170*b30d1939SAndy Fiddaman 			sfputc(state.cp, ']');
1171da2e3ebdSchin 			if (a)
1172*b30d1939SAndy Fiddaman 				sfputr(state.cp, ":[string]", -1);
1173da2e3ebdSchin 		}
1174*b30d1939SAndy Fiddaman 		if (!(p->oopts = s = sfstruse(state.cp)))
1175da2e3ebdSchin 			return -1;
1176da2e3ebdSchin 		s += n;
1177da2e3ebdSchin 	}
1178da2e3ebdSchin 	p->opts = s;
1179*b30d1939SAndy Fiddaman 	message((-2, "version=%d prefix=%d section=%s flags=%04x id=%s catalog=%s oopts=%p", p->version, p->prefix, p->section, p->flags, p->id, p->catalog, p->oopts));
1180da2e3ebdSchin 	return 0;
1181da2e3ebdSchin }
1182da2e3ebdSchin 
1183da2e3ebdSchin /*
1184da2e3ebdSchin  * return the bold set/unset sequence for style
1185da2e3ebdSchin  */
1186da2e3ebdSchin 
1187da2e3ebdSchin static const char*
font(int f,int style,int set)1188da2e3ebdSchin font(int f, int style, int set)
1189da2e3ebdSchin {
1190da2e3ebdSchin 	switch (style)
1191da2e3ebdSchin 	{
1192da2e3ebdSchin 	case STYLE_html:
1193da2e3ebdSchin 		return fonts[f].html[set];
1194da2e3ebdSchin 	case STYLE_nroff:
1195da2e3ebdSchin 		return fonts[f].nroff[set];
1196da2e3ebdSchin 	case STYLE_short:
1197da2e3ebdSchin 	case STYLE_long:
1198da2e3ebdSchin 	case STYLE_posix:
1199da2e3ebdSchin 	case STYLE_api:
1200da2e3ebdSchin 		break;
1201da2e3ebdSchin 	default:
1202*b30d1939SAndy Fiddaman 		if (state.emphasis > 0)
1203da2e3ebdSchin 			return fonts[f].term[set];
1204da2e3ebdSchin 		break;
1205da2e3ebdSchin 	}
1206da2e3ebdSchin 	return "";
1207da2e3ebdSchin }
1208da2e3ebdSchin 
1209da2e3ebdSchin /*
1210da2e3ebdSchin  * push \f...\f info
1211da2e3ebdSchin  */
1212da2e3ebdSchin 
1213da2e3ebdSchin static Push_t*
info(Push_t * psp,char * s,char * e,Sfio_t * ip,char * id)12143e14f97fSRoger A. Faulkner info(Push_t* psp, char* s, char* e, Sfio_t* ip, char* id)
1215da2e3ebdSchin {
1216da2e3ebdSchin 	register char*	b;
1217da2e3ebdSchin 	int		n;
1218da2e3ebdSchin 	Push_t*		tsp;
1219da2e3ebdSchin 
1220da2e3ebdSchin 	static Push_t	push;
1221da2e3ebdSchin 
12223e14f97fSRoger A. Faulkner 	b = expand(s, e, &s, ip, id);
1223da2e3ebdSchin 	n = strlen(b);
1224da2e3ebdSchin 	if (tsp = newof(0, Push_t, 1, n + 1))
1225da2e3ebdSchin 	{
1226da2e3ebdSchin 		tsp->nb = (char*)(tsp + 1);
1227da2e3ebdSchin 		tsp->ne = tsp->nb + n;
1228da2e3ebdSchin 		strcpy(tsp->nb, b);
1229da2e3ebdSchin 	}
1230da2e3ebdSchin 	else
1231da2e3ebdSchin 		tsp = &push;
1232da2e3ebdSchin 	tsp->next = psp;
1233da2e3ebdSchin 	tsp->ob = s;
1234da2e3ebdSchin 	tsp->oe = e;
1235da2e3ebdSchin 	return tsp;
1236da2e3ebdSchin }
1237da2e3ebdSchin 
1238da2e3ebdSchin /*
1239da2e3ebdSchin  * push translation
1240da2e3ebdSchin  */
1241da2e3ebdSchin 
1242da2e3ebdSchin static Push_t*
localize(Push_t * psp,char * s,char * e,int term,int n,Sfio_t * ip,int version,char * id,char * catalog)12433e14f97fSRoger A. Faulkner localize(Push_t* psp, char* s, char* e, int term, int n, Sfio_t* ip, int version, char* id, char* catalog)
1244da2e3ebdSchin {
1245da2e3ebdSchin 	char*		t;
1246da2e3ebdSchin 	char*		u;
1247da2e3ebdSchin 	Push_t*		tsp;
1248da2e3ebdSchin 	int		c;
1249da2e3ebdSchin 
1250da2e3ebdSchin 	t = skip(s, term, 0, 0, n, 0, 0, version);
1251da2e3ebdSchin 	if (e && t > e)
1252da2e3ebdSchin 		t = e;
1253da2e3ebdSchin 	while (s < t)
1254da2e3ebdSchin 	{
1255da2e3ebdSchin 		switch (c = *s++)
1256da2e3ebdSchin 		{
1257da2e3ebdSchin 		case ':':
1258da2e3ebdSchin 		case '?':
1259da2e3ebdSchin 			if (term && *s == c)
1260da2e3ebdSchin 				s++;
1261da2e3ebdSchin 			break;
1262da2e3ebdSchin 		case ']':
1263da2e3ebdSchin 			if (*s == c)
1264da2e3ebdSchin 				s++;
1265da2e3ebdSchin 			break;
1266da2e3ebdSchin 		}
1267da2e3ebdSchin 		sfputc(ip, c);
1268da2e3ebdSchin 	}
12693e14f97fSRoger A. Faulkner 	if (!(s = sfstruse(ip)) || (u = T(id, catalog, s)) == s)
1270da2e3ebdSchin 		return 0;
1271da2e3ebdSchin 	n = strlen(u);
1272da2e3ebdSchin 	if (tsp = newof(0, Push_t, 1, n + 1))
1273da2e3ebdSchin 	{
1274da2e3ebdSchin 		tsp->nb = (char*)(tsp + 1);
1275da2e3ebdSchin 		tsp->ne = tsp->nb + n;
1276da2e3ebdSchin 		strcpy(tsp->nb, u);
1277da2e3ebdSchin 		tsp->ob = t;
1278da2e3ebdSchin 		tsp->oe = e;
1279da2e3ebdSchin 		tsp->ch = 1;
1280da2e3ebdSchin 	}
1281da2e3ebdSchin 	tsp->next = psp;
1282da2e3ebdSchin 	return tsp;
1283da2e3ebdSchin }
1284da2e3ebdSchin 
1285da2e3ebdSchin /*
1286da2e3ebdSchin  * output label s from [ ...label...[?...] ] to sp
1287da2e3ebdSchin  * 1 returned if the label was translated
1288da2e3ebdSchin  */
1289da2e3ebdSchin 
1290da2e3ebdSchin 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)12913e14f97fSRoger 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)
1292da2e3ebdSchin {
1293da2e3ebdSchin 	register int	c;
1294da2e3ebdSchin 	register char*	t;
1295da2e3ebdSchin 	register char*	e;
1296da2e3ebdSchin 	int		ostyle;
1297da2e3ebdSchin 	int		a;
1298da2e3ebdSchin 	int		i;
1299da2e3ebdSchin 	char*		p;
1300*b30d1939SAndy Fiddaman 	char*		q;
1301da2e3ebdSchin 	char*		w;
1302da2e3ebdSchin 	char*		y;
1303da2e3ebdSchin 	int		va;
1304da2e3ebdSchin 	Push_t*		tsp;
1305da2e3ebdSchin 
1306da2e3ebdSchin 	int		r = 0;
1307da2e3ebdSchin 	int		n = 1;
1308da2e3ebdSchin 	Push_t*		psp = 0;
1309da2e3ebdSchin 
1310*b30d1939SAndy Fiddaman 	if ((ostyle = style) > (STYLE_nroff - (sep <= 0)) && f != FONT_LITERAL && f >= 0)
1311da2e3ebdSchin 		style = 0;
1312da2e3ebdSchin 	if (z < 0)
1313da2e3ebdSchin 		e = s + strlen(s);
1314da2e3ebdSchin 	else
1315da2e3ebdSchin 		e = s + z;
1316da2e3ebdSchin 	if (sep > 0)
1317da2e3ebdSchin 	{
1318da2e3ebdSchin 		if (sep == ' ' && style == STYLE_nroff)
1319da2e3ebdSchin 			sfputc(sp, '\\');
1320da2e3ebdSchin 		sfputc(sp, sep);
1321da2e3ebdSchin 	}
1322da2e3ebdSchin 	sep = !sep || z < 0;
1323da2e3ebdSchin 	va = 0;
1324da2e3ebdSchin 	y = 0;
13257c2fbfb3SApril Chin 	if (about)
13267c2fbfb3SApril Chin 		sfputc(sp, '(');
1327da2e3ebdSchin 	if (version < 1)
1328da2e3ebdSchin 	{
1329da2e3ebdSchin 		a = 0;
1330da2e3ebdSchin 		for (;;)
1331da2e3ebdSchin 		{
1332da2e3ebdSchin 			if (s >= e)
1333da2e3ebdSchin 				return r;
1334da2e3ebdSchin 			switch (c = *s++)
1335da2e3ebdSchin 			{
1336da2e3ebdSchin 			case '[':
1337da2e3ebdSchin 				a++;
1338da2e3ebdSchin 				break;
1339da2e3ebdSchin 			case ']':
1340da2e3ebdSchin 				if (--a < 0)
1341da2e3ebdSchin 					return r;
1342da2e3ebdSchin 				break;
1343da2e3ebdSchin 			}
1344da2e3ebdSchin 			sfputc(sp, c);
1345da2e3ebdSchin 		}
1346da2e3ebdSchin 	}
1347da2e3ebdSchin 	else if (level && (*(p = skip(s, 0, 0, 0, 1, level, 1, version)) == ':' || *p == '#'))
1348da2e3ebdSchin 	{
1349da2e3ebdSchin 		va = 0;
1350da2e3ebdSchin 		if (*++p == '?' || *p == *(p - 1))
1351da2e3ebdSchin 		{
1352da2e3ebdSchin 			p++;
1353da2e3ebdSchin 			va |= OPT_optional;
1354da2e3ebdSchin 		}
1355da2e3ebdSchin 		if (*(p = next(p, version)) == '[')
1356da2e3ebdSchin 			y = p + 1;
1357da2e3ebdSchin 	}
1358da2e3ebdSchin 	if (X(catalog) && (!level || *s == '\a' || *(s - 1) != '+') &&
13593e14f97fSRoger A. Faulkner 	    (tsp = localize(psp, s, e, (sep || level) ? '?' : 0, sep || level, ip, version, id, catalog)))
1360da2e3ebdSchin 	{
1361*b30d1939SAndy Fiddaman 		psp = tsp;
1362da2e3ebdSchin 		s = psp->nb;
1363da2e3ebdSchin 		e = psp->ne;
1364da2e3ebdSchin 		r = psp->ch > 0;
1365da2e3ebdSchin 	}
1366da2e3ebdSchin 	switch (*s)
1367da2e3ebdSchin 	{
1368da2e3ebdSchin 	case '\a':
1369*b30d1939SAndy Fiddaman 		if (f == FONT_ITALIC || f < 0)
1370da2e3ebdSchin 			s++;
1371*b30d1939SAndy Fiddaman 		if (f > 0)
1372*b30d1939SAndy Fiddaman 			f = 0;
1373da2e3ebdSchin 		break;
1374da2e3ebdSchin 	case '\b':
1375*b30d1939SAndy Fiddaman 		if (f == FONT_BOLD || f < 0)
1376da2e3ebdSchin 			s++;
1377*b30d1939SAndy Fiddaman 		if (f > 0)
1378*b30d1939SAndy Fiddaman 			f = 0;
1379da2e3ebdSchin 		break;
1380da2e3ebdSchin 	case '\v':
1381*b30d1939SAndy Fiddaman 		if (f == FONT_LITERAL || f < 0)
1382da2e3ebdSchin 			s++;
1383*b30d1939SAndy Fiddaman 		if (f > 0)
1384*b30d1939SAndy Fiddaman 			f = 0;
1385da2e3ebdSchin 		break;
1386da2e3ebdSchin 	default:
1387*b30d1939SAndy Fiddaman 		if (f > 0)
1388da2e3ebdSchin 			sfputr(sp, font(f, style, 1), -1);
1389da2e3ebdSchin 		break;
1390da2e3ebdSchin 	}
1391da2e3ebdSchin 	for (;;)
1392da2e3ebdSchin 	{
1393da2e3ebdSchin 		if (s >= e)
1394da2e3ebdSchin 		{
1395da2e3ebdSchin 			if (!(tsp = psp))
1396da2e3ebdSchin 				goto restore;
1397da2e3ebdSchin 			s = psp->ob;
1398da2e3ebdSchin 			e = psp->oe;
1399da2e3ebdSchin 			psp = psp->next;
1400da2e3ebdSchin 			free(tsp);
1401da2e3ebdSchin 			continue;
1402da2e3ebdSchin 		}
1403da2e3ebdSchin 		switch (c = *s++)
1404da2e3ebdSchin 		{
1405da2e3ebdSchin 		case '(':
1406da2e3ebdSchin 			if (n)
1407da2e3ebdSchin 			{
1408da2e3ebdSchin 				n = 0;
1409*b30d1939SAndy Fiddaman 				if (f > 0)
1410da2e3ebdSchin 				{
1411da2e3ebdSchin 					sfputr(sp, font(f, style, 0), -1);
1412da2e3ebdSchin 					f = 0;
1413da2e3ebdSchin 				}
1414da2e3ebdSchin 			}
1415da2e3ebdSchin 			break;
1416da2e3ebdSchin 		case '?':
1417da2e3ebdSchin 		case ':':
1418da2e3ebdSchin 		case ']':
1419da2e3ebdSchin 			if (psp && psp->ch)
1420da2e3ebdSchin 				break;
1421da2e3ebdSchin 			if (y)
1422da2e3ebdSchin 			{
1423da2e3ebdSchin 				if (va & OPT_optional)
1424da2e3ebdSchin 					sfputc(sp, '[');
1425da2e3ebdSchin 				sfputc(sp, '=');
1426*b30d1939SAndy Fiddaman 				label(sp, 0, y, 0, -1, 0, style, f >= 0 ? FONT_ITALIC : f, ip, version, id, catalog);
1427da2e3ebdSchin 				if (va & OPT_optional)
1428da2e3ebdSchin 					sfputc(sp, ']');
1429da2e3ebdSchin 				y = 0;
1430da2e3ebdSchin 			}
1431da2e3ebdSchin 			switch (c)
1432da2e3ebdSchin 			{
1433da2e3ebdSchin 			case '?':
1434da2e3ebdSchin 				if (*s == '?')
1435da2e3ebdSchin 					s++;
1436da2e3ebdSchin 				else if (*s == ']' && *(s + 1) != ']')
1437da2e3ebdSchin 					continue;
1438da2e3ebdSchin 				else if (sep)
1439da2e3ebdSchin 					goto restore;
14403e14f97fSRoger A. Faulkner 				else if (X(catalog) && (tsp = localize(psp, s, e, 0, 1, ip, version, id, catalog)))
1441da2e3ebdSchin 				{
1442da2e3ebdSchin 					psp = tsp;
1443da2e3ebdSchin 					s = psp->nb;
1444da2e3ebdSchin 					e = psp->ne;
1445da2e3ebdSchin 				}
1446da2e3ebdSchin 				break;
1447da2e3ebdSchin 			case ']':
1448da2e3ebdSchin 				if (sep && *s++ != ']')
1449da2e3ebdSchin 					goto restore;
1450da2e3ebdSchin 				break;
1451da2e3ebdSchin 			case ':':
1452da2e3ebdSchin 				if (sep && *s++ != ':')
1453da2e3ebdSchin 					goto restore;
1454da2e3ebdSchin 				break;
1455da2e3ebdSchin 			}
1456da2e3ebdSchin 			break;
1457da2e3ebdSchin 		case '\a':
1458da2e3ebdSchin 			a = FONT_ITALIC;
1459da2e3ebdSchin 		setfont:
1460*b30d1939SAndy Fiddaman 			if (f >= 0)
1461da2e3ebdSchin 			{
1462*b30d1939SAndy Fiddaman 				if (f & ~a)
1463da2e3ebdSchin 				{
1464*b30d1939SAndy Fiddaman 					sfputr(sp, font(f, style, 0), -1);
1465*b30d1939SAndy Fiddaman 					f = 0;
1466*b30d1939SAndy Fiddaman 				}
1467*b30d1939SAndy Fiddaman 				if (!f && style == STYLE_html)
1468*b30d1939SAndy Fiddaman 				{
1469*b30d1939SAndy Fiddaman 					for (t = s; t < e && !isspace(*t) && !iscntrl(*t); t++);
1470*b30d1939SAndy Fiddaman 					if (*t == c && *++t == '(')
1471da2e3ebdSchin 					{
1472*b30d1939SAndy Fiddaman 						w = t;
1473*b30d1939SAndy Fiddaman 						if (++t < e && isdigit(*t))
1474*b30d1939SAndy Fiddaman 							while (++t < e && isupper(*t));
1475*b30d1939SAndy Fiddaman 						if (t < e && *t == ')' && t > w + 1)
1476*b30d1939SAndy Fiddaman 						{
1477*b30d1939SAndy Fiddaman 							sfprintf(sp, "<NOBR><A href=\"../man%-.*s/"
1478*b30d1939SAndy Fiddaman 								, t - w - 1, w + 1
1479*b30d1939SAndy Fiddaman 								);
1480*b30d1939SAndy Fiddaman 							for (q = s; q < w - 1; q++)
1481*b30d1939SAndy Fiddaman 								if (*q == ':' && q < w - 2 && *(q + 1) == ':')
1482*b30d1939SAndy Fiddaman 								{
1483*b30d1939SAndy Fiddaman 									sfputc(sp, '-');
1484*b30d1939SAndy Fiddaman 									q++;
1485*b30d1939SAndy Fiddaman 								}
1486*b30d1939SAndy Fiddaman 								else
1487*b30d1939SAndy Fiddaman 									sfputc(sp, *q);
1488*b30d1939SAndy Fiddaman 							sfprintf(sp, ".html\">%s%-.*s%s</A>%-.*s</NOBR>"
1489*b30d1939SAndy Fiddaman 								, font(a, style, 1)
1490*b30d1939SAndy Fiddaman 								, w - s - 1, s
1491*b30d1939SAndy Fiddaman 								, font(a, style, 0)
1492*b30d1939SAndy Fiddaman 								, t - w + 1, w
1493*b30d1939SAndy Fiddaman 								);
1494*b30d1939SAndy Fiddaman 							s = t + 1;
1495*b30d1939SAndy Fiddaman 							continue;
1496*b30d1939SAndy Fiddaman 						}
1497da2e3ebdSchin 					}
1498da2e3ebdSchin 				}
1499*b30d1939SAndy Fiddaman 				sfputr(sp, font(a, style, !!(f ^= a)), -1);
1500da2e3ebdSchin 			}
1501da2e3ebdSchin 			continue;
1502da2e3ebdSchin 		case '\b':
1503da2e3ebdSchin 			a = FONT_BOLD;
1504da2e3ebdSchin 			goto setfont;
1505da2e3ebdSchin 		case '\f':
15063e14f97fSRoger A. Faulkner 			psp = info(psp, s, e, ip, id);
1507da2e3ebdSchin 			if (psp->nb)
1508da2e3ebdSchin 			{
1509da2e3ebdSchin 				s = psp->nb;
1510da2e3ebdSchin 				e = psp->ne;
1511da2e3ebdSchin 			}
1512da2e3ebdSchin 			else
1513da2e3ebdSchin 			{
1514da2e3ebdSchin 				s = psp->ob;
1515da2e3ebdSchin 				psp = psp->next;
1516da2e3ebdSchin 			}
1517da2e3ebdSchin 			continue;
1518da2e3ebdSchin 		case '\n':
1519da2e3ebdSchin 			sfputc(sp, c);
1520da2e3ebdSchin 			for (i = 0; i < level; i++)
1521da2e3ebdSchin 				sfputc(sp, '\t');
1522da2e3ebdSchin 			continue;
1523da2e3ebdSchin 		case '\v':
1524da2e3ebdSchin 			a = FONT_LITERAL;
1525da2e3ebdSchin 			goto setfont;
1526da2e3ebdSchin 		case '<':
1527da2e3ebdSchin 			if (style == STYLE_html)
1528da2e3ebdSchin 			{
1529da2e3ebdSchin 				sfputr(sp, "&lt;", -1);
1530da2e3ebdSchin 				c = 0;
1531da2e3ebdSchin 				for (t = s; t < e; t++)
1532da2e3ebdSchin 					if (!isalnum(*t) && *t != '_' && *t != '.' && *t != '-')
1533da2e3ebdSchin 					{
1534da2e3ebdSchin 						if (*t == '@')
1535da2e3ebdSchin 						{
1536da2e3ebdSchin 							if (c)
1537da2e3ebdSchin 								break;
1538da2e3ebdSchin 							c = 1;
1539da2e3ebdSchin 						}
1540da2e3ebdSchin 						else if (*t == '>')
1541da2e3ebdSchin 						{
1542da2e3ebdSchin 							if (c)
1543da2e3ebdSchin 							{
1544da2e3ebdSchin 								sfprintf(sp, "<A href=\"mailto:%-.*s>%-.*s</A>&gt;", t - s, s, t - s, s);
1545da2e3ebdSchin 								s = t + 1;
1546da2e3ebdSchin 							}
1547da2e3ebdSchin 							break;
1548da2e3ebdSchin 						}
1549da2e3ebdSchin 						else
1550da2e3ebdSchin 							break;
1551da2e3ebdSchin 					}
1552da2e3ebdSchin 				continue;
1553da2e3ebdSchin 			}
1554da2e3ebdSchin 			break;
1555da2e3ebdSchin 		case '>':
1556da2e3ebdSchin 			if (style == STYLE_html)
1557da2e3ebdSchin 			{
1558da2e3ebdSchin 				sfputr(sp, "&gt;", -1);
1559da2e3ebdSchin 				continue;
1560da2e3ebdSchin 			}
1561da2e3ebdSchin 			break;
1562da2e3ebdSchin 		case '&':
1563da2e3ebdSchin 			if (style == STYLE_html)
1564da2e3ebdSchin 			{
1565da2e3ebdSchin 				sfputr(sp, "&amp;", -1);
1566da2e3ebdSchin 				continue;
1567da2e3ebdSchin 			}
1568da2e3ebdSchin 			break;
1569*b30d1939SAndy Fiddaman 		case '"':
1570*b30d1939SAndy Fiddaman 			if (style == STYLE_html)
1571*b30d1939SAndy Fiddaman 			{
1572*b30d1939SAndy Fiddaman 				sfputr(sp, "&quot;", -1);
1573*b30d1939SAndy Fiddaman 				continue;
1574*b30d1939SAndy Fiddaman 			}
1575*b30d1939SAndy Fiddaman 			break;
1576da2e3ebdSchin 		case '-':
1577da2e3ebdSchin 			if (ostyle == STYLE_nroff)
1578da2e3ebdSchin 				sfputc(sp, '\\');
1579da2e3ebdSchin 			break;
1580da2e3ebdSchin 		case '.':
1581da2e3ebdSchin 			if (ostyle == STYLE_nroff)
1582da2e3ebdSchin 			{
1583da2e3ebdSchin 				sfputc(sp, '\\');
1584da2e3ebdSchin 				sfputc(sp, '&');
1585da2e3ebdSchin 			}
1586da2e3ebdSchin 			break;
1587da2e3ebdSchin 		case '\\':
1588da2e3ebdSchin 			if (ostyle == STYLE_nroff)
1589da2e3ebdSchin 			{
1590da2e3ebdSchin 				c = 'e';
1591da2e3ebdSchin 				sfputc(sp, '\\');
1592da2e3ebdSchin 			}
1593da2e3ebdSchin 			break;
1594da2e3ebdSchin 		case ' ':
1595da2e3ebdSchin 			if (ostyle == STYLE_nroff)
1596da2e3ebdSchin 				sfputc(sp, '\\');
1597da2e3ebdSchin 			break;
1598da2e3ebdSchin 		}
1599da2e3ebdSchin 		sfputc(sp, c);
1600da2e3ebdSchin 	}
1601da2e3ebdSchin  restore:
1602*b30d1939SAndy Fiddaman 	if (f > 0)
1603da2e3ebdSchin 		sfputr(sp, font(f, style, 0), -1);
16047c2fbfb3SApril Chin 	if (about)
16057c2fbfb3SApril Chin 		sfputc(sp, ')');
1606da2e3ebdSchin 	if (psp)
1607da2e3ebdSchin 		pop(psp);
1608da2e3ebdSchin 	return r;
1609da2e3ebdSchin }
1610da2e3ebdSchin 
1611da2e3ebdSchin /*
1612da2e3ebdSchin  * output args description to sp from p of length n
1613da2e3ebdSchin  */
1614da2e3ebdSchin 
1615da2e3ebdSchin 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)16163e14f97fSRoger 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)
1617da2e3ebdSchin {
1618da2e3ebdSchin 	register int	i;
1619da2e3ebdSchin 	register char*	t;
1620da2e3ebdSchin 	register char*	o;
1621da2e3ebdSchin 	register char*	a = 0;
1622da2e3ebdSchin 	char*		b;
1623da2e3ebdSchin 	int		sep;
1624da2e3ebdSchin 
1625da2e3ebdSchin 	if (flags & OPT_functions)
1626da2e3ebdSchin 		sep = '\t';
1627da2e3ebdSchin 	else
1628da2e3ebdSchin 	{
1629da2e3ebdSchin 		sep = ' ';
1630da2e3ebdSchin 		o = T(NiL, ID, "options");
1631da2e3ebdSchin 		b = style == STYLE_nroff ? "\\ " : " ";
1632da2e3ebdSchin 		for (;;)
1633da2e3ebdSchin 		{
1634da2e3ebdSchin 			t = (char*)memchr(p, '\n', n);
1635da2e3ebdSchin 			if (style >= STYLE_man)
1636da2e3ebdSchin 			{
16373e14f97fSRoger A. Faulkner 				if (!(a = id))
1638da2e3ebdSchin 					a = "...";
1639da2e3ebdSchin 				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);
1640da2e3ebdSchin 			}
1641da2e3ebdSchin 			else if (a)
1642da2e3ebdSchin 				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);
1643da2e3ebdSchin 			else
1644da2e3ebdSchin 			{
16453e14f97fSRoger A. Faulkner 				if (!(a = error_info.id) && !(a = id))
1646da2e3ebdSchin 					a = "...";
1647da2e3ebdSchin 				if (!sfstrtell(sp))
1648da2e3ebdSchin 					sfprintf(sp, "[%s%s%s]", b, o, b);
1649da2e3ebdSchin 			}
1650da2e3ebdSchin 			if (!t)
1651da2e3ebdSchin 				break;
1652da2e3ebdSchin 			i = ++t - p;
1653da2e3ebdSchin 			if (i)
1654da2e3ebdSchin 			{
1655da2e3ebdSchin 				sfputr(sp, b, -1);
1656da2e3ebdSchin 				if (X(catalog))
1657da2e3ebdSchin 				{
1658da2e3ebdSchin 					sfwrite(ip, p, i);
1659da2e3ebdSchin 					if (b = sfstruse(ip))
16603e14f97fSRoger A. Faulkner 						sfputr(sp, T(id, catalog, b), -1);
1661da2e3ebdSchin 					else
1662da2e3ebdSchin 						sfwrite(sp, p, i);
1663da2e3ebdSchin 				}
1664da2e3ebdSchin 				else
1665da2e3ebdSchin 					sfwrite(sp, p, i);
1666da2e3ebdSchin 			}
1667da2e3ebdSchin 			if (style == STYLE_html)
1668da2e3ebdSchin 				sfputr(sp, "<BR>", '\n');
1669da2e3ebdSchin 			else if (style == STYLE_nroff)
1670da2e3ebdSchin 				sfputr(sp, ".br", '\n');
1671da2e3ebdSchin 			else if (style == STYLE_api)
1672da2e3ebdSchin 				sfputr(sp, ".BR", '\n');
1673da2e3ebdSchin 			p = t;
1674da2e3ebdSchin 			n -= i;
1675da2e3ebdSchin 			while (n > 0 && (*p == ' ' || *p == '\t'))
1676da2e3ebdSchin 			{
1677da2e3ebdSchin 				p++;
1678da2e3ebdSchin 				n--;
1679da2e3ebdSchin 			}
1680da2e3ebdSchin 		}
1681da2e3ebdSchin 	}
1682da2e3ebdSchin 	if (n)
16833e14f97fSRoger A. Faulkner 		label(sp, sep, p, 0, n, 0, style, 0, ip, version, id, catalog);
1684da2e3ebdSchin }
1685da2e3ebdSchin 
1686da2e3ebdSchin /*
1687da2e3ebdSchin  * output [+-...label...?...] label s to sp
1688da2e3ebdSchin  * according to {...} level and style
1689da2e3ebdSchin  * return 0:header 1:paragraph
1690da2e3ebdSchin  */
1691da2e3ebdSchin 
1692da2e3ebdSchin static int
item(Sfio_t * sp,char * s,int about,int level,int style,Sfio_t * ip,int version,char * id,char * catalog,int * hflags)1693*b30d1939SAndy Fiddaman item(Sfio_t* sp, char* s, int about, int level, int style, Sfio_t* ip, int version, char* id, char* catalog, int* hflags)
1694da2e3ebdSchin {
1695da2e3ebdSchin 	register char*	t;
1696da2e3ebdSchin 	int		n;
1697da2e3ebdSchin 	int		par;
1698da2e3ebdSchin 
1699da2e3ebdSchin 	sfputc(sp, '\n');
1700da2e3ebdSchin 	if (*s == '\n')
1701da2e3ebdSchin 	{
1702da2e3ebdSchin 		par = 0;
1703da2e3ebdSchin 		if (style >= STYLE_nroff)
1704da2e3ebdSchin 			sfprintf(sp, ".DS\n");
1705da2e3ebdSchin 		else
1706da2e3ebdSchin 		{
1707da2e3ebdSchin 			if (style == STYLE_html)
1708da2e3ebdSchin 				sfprintf(sp, "<PRE>\n");
1709da2e3ebdSchin 			else
1710da2e3ebdSchin 				sfputc(sp, '\n');
1711da2e3ebdSchin 			for (n = 0; n < level; n++)
1712da2e3ebdSchin 				sfputc(sp, '\t');
1713da2e3ebdSchin 		}
17143e14f97fSRoger A. Faulkner 		label(sp, 0, s + 1, about, -1, level, style, FONT_LITERAL, ip, version, id, catalog);
1715da2e3ebdSchin 		sfputc(sp, '\n');
1716da2e3ebdSchin 		if (style >= STYLE_nroff)
1717da2e3ebdSchin 			sfprintf(sp, ".DE");
1718da2e3ebdSchin 		else if (style == STYLE_html)
1719da2e3ebdSchin 			sfprintf(sp, "</PRE>");
1720da2e3ebdSchin 	}
1721da2e3ebdSchin 	else if (*s != ']' && (*s != '?' || *(s + 1) == '?'))
1722da2e3ebdSchin 	{
1723da2e3ebdSchin 		par = 0;
1724da2e3ebdSchin 		if (level)
1725da2e3ebdSchin 		{
1726da2e3ebdSchin 			if (style >= STYLE_nroff)
17277c2fbfb3SApril Chin 				sfprintf(sp, ".H%d ", (level - (level > 2)) / 2);
1728da2e3ebdSchin 			else
1729da2e3ebdSchin 				for (n = 0; n < level; n++)
1730da2e3ebdSchin 					sfputc(sp, '\t');
1731da2e3ebdSchin 		}
1732da2e3ebdSchin 		if (style == STYLE_html)
1733da2e3ebdSchin 		{
1734da2e3ebdSchin 			if (!level)
1735*b30d1939SAndy Fiddaman 			{
1736*b30d1939SAndy Fiddaman 				if (*hflags & HELP_head)
1737*b30d1939SAndy Fiddaman 					sfputr(sp, "</DIV>", '\n');
1738*b30d1939SAndy Fiddaman 				else
1739*b30d1939SAndy Fiddaman 					*hflags |= HELP_head;
1740da2e3ebdSchin 				sfputr(sp, "<H4>", -1);
1741*b30d1939SAndy Fiddaman 			}
1742da2e3ebdSchin 			sfputr(sp, "<A name=\"", -1);
1743da2e3ebdSchin 			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] == '?')
1744da2e3ebdSchin 				for (t = s + 8; *t && *t != ']'; t++)
1745da2e3ebdSchin 					if (t[0] == 'p' && (!strncmp(t, "proprietary", 11) || !strncmp(t, "private", 7)) || t[0] == 'n' && !strncmp(t, "noncommercial", 13))
1746da2e3ebdSchin 					{
1747*b30d1939SAndy Fiddaman 						state.flags |= OPT_proprietary;
1748da2e3ebdSchin 						break;
1749da2e3ebdSchin 					}
1750*b30d1939SAndy Fiddaman 			label(sp, 0, s, about, -1, level, style, -1, ip, version, id, catalog);
1751da2e3ebdSchin 			sfputr(sp, "\">", -1);
17523e14f97fSRoger A. Faulkner 			label(sp, 0, s, about, -1, level, style, level ? FONT_BOLD : 0, ip, version, id, catalog);
1753da2e3ebdSchin 			sfputr(sp, "</A>", -1);
1754da2e3ebdSchin 			if (!level)
1755*b30d1939SAndy Fiddaman 			{
1756*b30d1939SAndy Fiddaman 				if (!strncmp(s, C("SYNOPSIS"), strlen(C("SYNOPSIS"))))
1757*b30d1939SAndy Fiddaman 					sfputr(sp, "</H4>\n<DIV class=SY>", -1);
1758*b30d1939SAndy Fiddaman 				else
1759*b30d1939SAndy Fiddaman 				{
1760*b30d1939SAndy Fiddaman 					sfputr(sp, "</H4>\n<DIV class=SH>", -1);
1761*b30d1939SAndy Fiddaman 					if (!strncmp(s, C("NAME"), strlen(C("NAME"))) || !strncmp(s, C("PLUGIN"), strlen(C("PLUGIN"))))
1762*b30d1939SAndy Fiddaman 						*hflags |= HELP_index;
1763*b30d1939SAndy Fiddaman 				}
1764*b30d1939SAndy Fiddaman 			}
1765da2e3ebdSchin 		}
1766da2e3ebdSchin 		else
1767da2e3ebdSchin 		{
1768da2e3ebdSchin 			if (!level)
1769da2e3ebdSchin 			{
1770da2e3ebdSchin 				if (style >= STYLE_nroff)
1771da2e3ebdSchin 					sfprintf(sp, ".SH ");
1772da2e3ebdSchin 				else if (style == STYLE_man)
1773da2e3ebdSchin 					sfputc(sp, '\n');
1774da2e3ebdSchin 				else if (style != STYLE_options && style != STYLE_match || *s == '-' || *s == '+')
1775da2e3ebdSchin 					sfputc(sp, '\t');
1776da2e3ebdSchin 			}
17773e14f97fSRoger A. Faulkner 			label(sp, 0, s, about, -1, level, style, FONT_BOLD, ip, version, id, catalog);
1778da2e3ebdSchin 		}
1779da2e3ebdSchin 	}
1780da2e3ebdSchin 	else
1781da2e3ebdSchin 	{
1782da2e3ebdSchin 		par = 1;
1783da2e3ebdSchin 		if (style >= STYLE_nroff)
17847c2fbfb3SApril Chin 			sfputr(sp, level ? ".SP" : ".PP", -1);
1785da2e3ebdSchin 	}
1786da2e3ebdSchin 	if (style >= STYLE_nroff || !level)
1787da2e3ebdSchin 		sfputc(sp, '\n');
1788da2e3ebdSchin 	if (par && style < STYLE_nroff)
1789da2e3ebdSchin 		for (n = 0; n < level; n++)
1790da2e3ebdSchin 			sfputc(sp, '\t');
1791da2e3ebdSchin 	return par;
1792da2e3ebdSchin }
1793da2e3ebdSchin 
1794da2e3ebdSchin /*
1795da2e3ebdSchin  * output text to sp from p according to style
1796da2e3ebdSchin  */
1797da2e3ebdSchin 
17983e14f97fSRoger A. Faulkner #if _BLD_DEBUG
17993e14f97fSRoger A. Faulkner 
1800*b30d1939SAndy Fiddaman static char*	textout(Sfio_t*, char*, char*, int, int, int, int, Sfio_t*, int, char*, char*, int*);
18013e14f97fSRoger A. Faulkner 
1802da2e3ebdSchin static char*
trace_textout(Sfio_t * sp,register char * p,char * conform,int conformlen,int style,int level,int bump,Sfio_t * ip,int version,char * id,char * catalog,int * hflags,int line)1803*b30d1939SAndy Fiddaman trace_textout(Sfio_t* sp, register char* p, char* conform, int conformlen, int style, int level, int bump, Sfio_t* ip, int version, char* id, char* catalog, int* hflags, int line)
1804da2e3ebdSchin {
18053e14f97fSRoger A. Faulkner 	static int	depth = 0;
18063e14f97fSRoger A. Faulkner 
18073e14f97fSRoger A. Faulkner 	message((-21, "opthelp: txt#%d +++ %2d \"%s\" style=%d level=%d bump=%d", line, ++depth, show(p), style, level, bump));
1808*b30d1939SAndy Fiddaman 	p = textout(sp, p, conform, conformlen, style, level, bump, ip, version, id, catalog, hflags);
18093e14f97fSRoger A. Faulkner 	message((-21, "opthelp: txt#%d --- %2d \"%s\"", line, depth--, show(p)));
18103e14f97fSRoger A. Faulkner 	return p;
18113e14f97fSRoger A. Faulkner }
18123e14f97fSRoger A. Faulkner 
18133e14f97fSRoger A. Faulkner #endif
18143e14f97fSRoger A. Faulkner 
18153e14f97fSRoger A. Faulkner static char*
textout(Sfio_t * sp,register char * s,char * conform,int conformlen,int style,int level,int bump,Sfio_t * ip,int version,char * id,char * catalog,int * hflags)1816*b30d1939SAndy Fiddaman textout(Sfio_t* sp, register char* s, char* conform, int conformlen, int style, int level, int bump, Sfio_t* ip, int version, char* id, char* catalog, int* hflags)
18173e14f97fSRoger A. Faulkner {
18183e14f97fSRoger A. Faulkner #if _BLD_DEBUG
1819*b30d1939SAndy Fiddaman #define textout(sp,s,conform,conformlen,style,level,bump,ip,version,id,catalog,hflags)	trace_textout(sp,s,conform,conformlen,style,level,bump,ip,version,id,catalog,hflags,__LINE__)
1820da2e3ebdSchin #endif
1821da2e3ebdSchin 	register char*	t;
1822da2e3ebdSchin 	register int	c;
1823da2e3ebdSchin 	register int	n;
1824*b30d1939SAndy Fiddaman 	char*		w;
1825*b30d1939SAndy Fiddaman 	char*		q;
1826da2e3ebdSchin 	int		a;
1827da2e3ebdSchin 	int		f;
1828da2e3ebdSchin 	int		par;
18297c2fbfb3SApril Chin 	int		about;
1830da2e3ebdSchin 	Push_t*		tsp;
1831da2e3ebdSchin 
1832da2e3ebdSchin 	int		ident = 0;
1833da2e3ebdSchin 	int		lev = level;
1834da2e3ebdSchin 	Push_t*		psp = 0;
1835da2e3ebdSchin 
1836da2e3ebdSchin  again:
18377c2fbfb3SApril Chin 	about = 0;
1838*b30d1939SAndy Fiddaman 	if ((c = *s) == GO)
1839da2e3ebdSchin 	{
1840da2e3ebdSchin 		for (;;)
1841da2e3ebdSchin 		{
1842*b30d1939SAndy Fiddaman 			while (*(s = next(s + 1, version)) == '\n');
1843*b30d1939SAndy Fiddaman 			if (*s == GO)
1844da2e3ebdSchin 			{
1845da2e3ebdSchin 				if (level > 1)
1846da2e3ebdSchin 					level++;
1847da2e3ebdSchin 				level++;
1848da2e3ebdSchin 			}
1849*b30d1939SAndy Fiddaman 			else if (*s != OG)
1850da2e3ebdSchin 			{
1851*b30d1939SAndy Fiddaman 				if (level <= 1 || *s != '[' || *(s + 1) != '-' || style == STYLE_man && *(s + 2) == '?' || isalpha(*(s + 2)))
1852da2e3ebdSchin 					break;
1853*b30d1939SAndy Fiddaman 				s = skip(s, 0, 0, 0, 1, level, 0, version);
1854da2e3ebdSchin 			}
1855da2e3ebdSchin 			else if ((level -= 2) <= lev)
1856*b30d1939SAndy Fiddaman 				return s + 1;
1857da2e3ebdSchin 		}
1858*b30d1939SAndy Fiddaman 		if (*s == '\f')
1859da2e3ebdSchin 		{
1860*b30d1939SAndy Fiddaman 			psp = info(psp, s + 1, NiL, ip, id);
1861da2e3ebdSchin 			if (psp->nb)
1862*b30d1939SAndy Fiddaman 				s = psp->nb;
1863da2e3ebdSchin 			else
1864da2e3ebdSchin 			{
1865*b30d1939SAndy Fiddaman 				s = psp->ob;
1866da2e3ebdSchin 				psp = psp->next;
1867da2e3ebdSchin 			}
1868da2e3ebdSchin 		}
1869*b30d1939SAndy Fiddaman 		if (*s != '[')
1870*b30d1939SAndy Fiddaman 			return s;
1871*b30d1939SAndy Fiddaman 		c = *++s;
1872da2e3ebdSchin 		if (level > 1)
1873da2e3ebdSchin 			level++;
1874da2e3ebdSchin 		level++;
1875da2e3ebdSchin 	}
1876da2e3ebdSchin 	if (c == '-' && level > 1)
18777c2fbfb3SApril Chin 	{
18787c2fbfb3SApril Chin 		if (style == STYLE_man)
18797c2fbfb3SApril Chin 		{
18807c2fbfb3SApril Chin 			about = 1;
1881*b30d1939SAndy Fiddaman 			if (*(s + 1) == '-')
1882*b30d1939SAndy Fiddaman 				s++;
18837c2fbfb3SApril Chin 		}
18847c2fbfb3SApril Chin 		else
18857c2fbfb3SApril Chin 			for (;;)
18867c2fbfb3SApril Chin 			{
1887*b30d1939SAndy Fiddaman 				s = skip(s, 0, 0, 0, 1, level, 0, version);
1888*b30d1939SAndy Fiddaman 				while (*(s = next(s + 1, version)) == '\n');
1889*b30d1939SAndy Fiddaman 				if (*s == '[')
18907c2fbfb3SApril Chin 				{
1891*b30d1939SAndy Fiddaman 					if ((c = *++s) != '-')
18927c2fbfb3SApril Chin 						break;
18937c2fbfb3SApril Chin 				}
1894*b30d1939SAndy Fiddaman 				else if (*s == GO)
18957c2fbfb3SApril Chin 					goto again;
1896*b30d1939SAndy Fiddaman 				else if (*s == OG)
1897*b30d1939SAndy Fiddaman 					return s + 1;
18987c2fbfb3SApril Chin 			}
18997c2fbfb3SApril Chin 	}
1900da2e3ebdSchin 	if (c == '+' || c == '-' && (bump = 3) || c != ' ' && level > 1)
1901da2e3ebdSchin 	{
1902*b30d1939SAndy Fiddaman 		s = skip(t = s + 1, '?', 0, 0, 1, level, 0, version);
1903*b30d1939SAndy Fiddaman 		if (c == '-' && (*t == '?' || isdigit(*t) || *s == '?' && *(s + 1) == '\n'))
1904da2e3ebdSchin 		{
1905*b30d1939SAndy Fiddaman 			if ((c = *s) != '?')
1906*b30d1939SAndy Fiddaman 				return skip(s, 0, 0, 0, 1, level, 1, version);
1907*b30d1939SAndy Fiddaman 			w = C("version");
1908*b30d1939SAndy Fiddaman 			par = item(sp, w, about, level, style, ip, version, id, ID, hflags);
1909da2e3ebdSchin 			for (;;)
1910da2e3ebdSchin 			{
1911*b30d1939SAndy Fiddaman 				while (isspace(*(s + 1)))
1912*b30d1939SAndy Fiddaman 					s++;
1913*b30d1939SAndy Fiddaman 				w = s;
1914*b30d1939SAndy Fiddaman 				if (w[1] == '@' && w[2] == '(' && w[3] == '#' && w[4] == ')')
1915*b30d1939SAndy Fiddaman 					s = w + 4;
1916*b30d1939SAndy Fiddaman 				else if (w[1] == '$' && w[2] == 'I' && w[3] == 'd' && w[4] == ':' && w[5] == ' ')
1917da2e3ebdSchin 				{
1918*b30d1939SAndy Fiddaman 					s = w + 5;
1919da2e3ebdSchin 					ident = 1;
1920da2e3ebdSchin 				}
1921da2e3ebdSchin 				else
1922da2e3ebdSchin 					break;
1923da2e3ebdSchin 			}
1924da2e3ebdSchin 		}
1925da2e3ebdSchin 		else
1926da2e3ebdSchin 		{
1927da2e3ebdSchin 			if (isdigit(c) && isdigit(*t))
1928da2e3ebdSchin 			{
1929da2e3ebdSchin 				while (isdigit(*t))
1930da2e3ebdSchin 					t++;
1931da2e3ebdSchin 				if (*t == ':')
1932da2e3ebdSchin 					t++;
1933da2e3ebdSchin 			}
1934da2e3ebdSchin 			else if (isalnum(c) && *t-- == ':')
1935da2e3ebdSchin 			{
1936da2e3ebdSchin 				if (X(catalog) || *t == *(t + 2))
1937da2e3ebdSchin 					t += 2;
1938da2e3ebdSchin 				else
1939da2e3ebdSchin 				{
1940da2e3ebdSchin 					sfprintf(ip, "%s", t);
1941*b30d1939SAndy Fiddaman 					if (w = sfstruse(ip))
1942*b30d1939SAndy Fiddaman 						*((t = w) + 1) = '|';
1943da2e3ebdSchin 				}
1944da2e3ebdSchin 			}
1945*b30d1939SAndy Fiddaman 			par = item(sp, t, about, level, style, ip, version, id, catalog, hflags);
1946*b30d1939SAndy Fiddaman 			c = *s;
1947da2e3ebdSchin 		}
19487c2fbfb3SApril Chin 		if (!about && level)
1949da2e3ebdSchin 			par = 0;
1950da2e3ebdSchin 	}
1951da2e3ebdSchin 	else
1952da2e3ebdSchin 	{
1953da2e3ebdSchin 		if (style >= STYLE_nroff)
1954da2e3ebdSchin 			sfputc(sp, '\n');
1955da2e3ebdSchin 		else if (c == '?')
1956da2e3ebdSchin 			for (n = 0; n < level; n++)
1957da2e3ebdSchin 				sfputc(sp, '\t');
1958da2e3ebdSchin 		par = 0;
1959da2e3ebdSchin 	}
1960da2e3ebdSchin 	if (c == ':')
1961*b30d1939SAndy Fiddaman 		c = *(s = skip(s, '?', 0, 0, 1, 0, 0, version));
1962*b30d1939SAndy Fiddaman 	if ((c == ']' || c == '?' && *(s + 1) == ']' && *(s + 2) != ']' && s++) && (c = *(s = next(s + 1, version))) == GO)
19633e14f97fSRoger A. Faulkner 	{
1964*b30d1939SAndy Fiddaman 		s = textout(sp, s, conform, conformlen, style, level + bump + par + 1, 0, ip, version, id, catalog, hflags);
1965*b30d1939SAndy Fiddaman 		if (level > lev && *s && *(s = next(s, version)) == '[')
19663e14f97fSRoger A. Faulkner 		{
1967*b30d1939SAndy Fiddaman 			s++;
1968*b30d1939SAndy Fiddaman 			message((-21, "textout#%d s=%s", __LINE__, show(s)));
19693e14f97fSRoger A. Faulkner 			goto again;
19703e14f97fSRoger A. Faulkner 		}
19713e14f97fSRoger A. Faulkner 	}
1972da2e3ebdSchin 	else if (c == '?' || c == ' ')
1973da2e3ebdSchin 	{
1974*b30d1939SAndy Fiddaman 		s++;
1975da2e3ebdSchin 		if (c == ' ')
1976da2e3ebdSchin 			sfputc(sp, c);
1977da2e3ebdSchin 		else
1978da2e3ebdSchin 		{
1979*b30d1939SAndy Fiddaman 			if (X(catalog) && (tsp = localize(psp, s, NiL, 0, 1, ip, version, id, catalog)))
1980da2e3ebdSchin 			{
1981da2e3ebdSchin 				psp = tsp;
1982*b30d1939SAndy Fiddaman 				s = psp->nb;
1983da2e3ebdSchin 			}
1984da2e3ebdSchin 			if (style < STYLE_nroff)
1985da2e3ebdSchin 				for (n = 0; n < bump + 1; n++)
1986da2e3ebdSchin 					sfputc(sp, '\t');
1987da2e3ebdSchin 		}
1988*b30d1939SAndy Fiddaman 		if (conform)
1989*b30d1939SAndy Fiddaman 		{
1990*b30d1939SAndy Fiddaman 			sfprintf(sp, "[%-.*s %s] ", conformlen, conform, T(NiL, ID, "conformance"));
1991*b30d1939SAndy Fiddaman 			conform = 0;
1992*b30d1939SAndy Fiddaman 		}
1993*b30d1939SAndy Fiddaman 		if (*hflags & HELP_index)
1994*b30d1939SAndy Fiddaman 		{
1995*b30d1939SAndy Fiddaman 			*hflags &= ~HELP_index;
1996*b30d1939SAndy Fiddaman 			sfputr(sp, "<!--MAN-INDEX-->", -1);
1997*b30d1939SAndy Fiddaman 		}
1998da2e3ebdSchin 		f = 0;
1999da2e3ebdSchin 		for (;;)
2000da2e3ebdSchin 		{
2001*b30d1939SAndy Fiddaman 			switch (c = *s++)
2002da2e3ebdSchin 			{
2003da2e3ebdSchin 			case 0:
2004da2e3ebdSchin 				if (!(tsp = psp))
2005da2e3ebdSchin 				{
2006da2e3ebdSchin 					if (f)
2007da2e3ebdSchin 						sfputr(sp, font(f, style, 0), -1);
2008*b30d1939SAndy Fiddaman 					return s - 1;
2009da2e3ebdSchin 				}
2010*b30d1939SAndy Fiddaman 				s = psp->ob;
2011da2e3ebdSchin 				psp = psp->next;
2012da2e3ebdSchin 				free(tsp);
2013da2e3ebdSchin 				continue;
2014da2e3ebdSchin 			case ']':
2015da2e3ebdSchin 				if (psp && psp->ch)
2016da2e3ebdSchin 					break;
2017*b30d1939SAndy Fiddaman 				if (*s != ']')
2018da2e3ebdSchin 				{
2019da2e3ebdSchin 					if (f)
2020da2e3ebdSchin 					{
2021da2e3ebdSchin 						sfputr(sp, font(f, style, 0), -1);
2022da2e3ebdSchin 						f = 0;
2023da2e3ebdSchin 					}
2024da2e3ebdSchin 					for (;;)
2025da2e3ebdSchin 					{
2026*b30d1939SAndy Fiddaman 						if ((*s == '#' || *s == ':') && level > lev)
2027da2e3ebdSchin 						{
2028da2e3ebdSchin 							char*	o;
2029da2e3ebdSchin 							char*	v;
2030da2e3ebdSchin 							int	j;
2031da2e3ebdSchin 							int	m;
2032da2e3ebdSchin 							int	ol;
2033da2e3ebdSchin 							int	vl;
2034da2e3ebdSchin 
2035da2e3ebdSchin 							a = 0;
2036da2e3ebdSchin 							o = 0;
2037da2e3ebdSchin 							v = 0;
2038*b30d1939SAndy Fiddaman 							if (*++s == '?' || *s == *(s - 1))
2039da2e3ebdSchin 							{
2040*b30d1939SAndy Fiddaman 								s++;
2041da2e3ebdSchin 								a |= OPT_optional;
2042da2e3ebdSchin 							}
2043*b30d1939SAndy Fiddaman 							if (*(s = next(s, version)) == '[')
2044da2e3ebdSchin 							{
2045*b30d1939SAndy Fiddaman 								s = skip(s + 1, ':', '?', 0, 1, 0, 0, version);
2046*b30d1939SAndy Fiddaman 								while (*s == ':')
2047da2e3ebdSchin 								{
2048*b30d1939SAndy Fiddaman 									s = skip(t = s + 1, ':', '?', 0, 1, 0, 0, version);
2049*b30d1939SAndy Fiddaman 									m = s - t;
2050da2e3ebdSchin 									if (*t == '!')
2051da2e3ebdSchin 									{
2052da2e3ebdSchin 										o = t + 1;
2053da2e3ebdSchin 										ol = m - 1;
2054da2e3ebdSchin 									}
2055da2e3ebdSchin 									else if (*t == '=')
2056da2e3ebdSchin 									{
2057da2e3ebdSchin 										v = t + 1;
2058da2e3ebdSchin 										vl = m - 1;
2059da2e3ebdSchin 									}
2060da2e3ebdSchin 									else
2061da2e3ebdSchin 										for (j = 0; j < elementsof(attrs); j++)
2062da2e3ebdSchin 											if (strneq(t, attrs[j].name, m))
2063da2e3ebdSchin 											{
2064da2e3ebdSchin 												a |= attrs[j].flag;
2065da2e3ebdSchin 												break;
2066da2e3ebdSchin 											}
2067da2e3ebdSchin 								}
2068da2e3ebdSchin 							}
2069da2e3ebdSchin 							if (a & OPT_optional)
2070da2e3ebdSchin 							{
2071da2e3ebdSchin 								if (o)
2072da2e3ebdSchin 								{
2073da2e3ebdSchin 									sfprintf(sp, " %s ", T(NiL, ID, "If the option value is omitted then"));
2074da2e3ebdSchin 									sfputr(sp, font(FONT_BOLD, style, 1), -1);
2075da2e3ebdSchin 									t = o + ol;
2076da2e3ebdSchin 									while (o < t)
2077da2e3ebdSchin 									{
2078da2e3ebdSchin 										if (((c = *o++) == ':' || c == '?') && *o == c)
2079da2e3ebdSchin 											o++;
2080da2e3ebdSchin 										sfputc(sp, c);
2081da2e3ebdSchin 									}
2082da2e3ebdSchin 									sfputr(sp, font(FONT_BOLD, style, 0), -1);
2083da2e3ebdSchin 									sfprintf(sp, " %s.", T(NiL, ID, "is assumed"));
2084da2e3ebdSchin 								}
2085da2e3ebdSchin 								else
2086da2e3ebdSchin 									sfprintf(sp, " %s", T(NiL, ID, "The option value may be omitted."));
2087da2e3ebdSchin 							}
2088da2e3ebdSchin 							if (v)
2089da2e3ebdSchin 							{
2090da2e3ebdSchin 								sfprintf(sp, " %s ", T(NiL, ID, "The default value is"));
2091da2e3ebdSchin 								sfputr(sp, font(FONT_BOLD, style, 1), -1);
2092da2e3ebdSchin 								t = v + vl;
2093da2e3ebdSchin 								while (v < t)
2094da2e3ebdSchin 								{
2095da2e3ebdSchin 									if (((c = *v++) == ':' || c == '?') && *v == c)
2096da2e3ebdSchin 										v++;
2097da2e3ebdSchin 									sfputc(sp, c);
2098da2e3ebdSchin 								}
2099da2e3ebdSchin 								sfputr(sp, font(FONT_BOLD, style, 0), -1);
2100da2e3ebdSchin 								sfputc(sp, '.');
2101da2e3ebdSchin 							}
2102*b30d1939SAndy Fiddaman 							s = skip(s, 0, 0, 0, 1, 0, 1, version);
2103da2e3ebdSchin 						}
2104*b30d1939SAndy Fiddaman 						if (*(s = next(s, version)) == GO)
21053e14f97fSRoger A. Faulkner 						{
2106*b30d1939SAndy Fiddaman 							s = textout(sp, s, 0, 0, style, level + bump + !level, 0, ip, version, id, catalog, hflags);
2107*b30d1939SAndy Fiddaman 							if (*s && *(s = next(s, version)) == '[' && !isalnum(*(s + 1)))
21083e14f97fSRoger A. Faulkner 							{
2109*b30d1939SAndy Fiddaman 								s++;
2110*b30d1939SAndy Fiddaman 								message((-21, "textout#%d s=%s", __LINE__, show(s)));
21113e14f97fSRoger A. Faulkner 								goto again;
21123e14f97fSRoger A. Faulkner 							}
21133e14f97fSRoger A. Faulkner 						}
2114*b30d1939SAndy Fiddaman 						else if (*s == '[' && level > lev)
2115da2e3ebdSchin 						{
2116*b30d1939SAndy Fiddaman 							s++;
2117da2e3ebdSchin 							goto again;
2118da2e3ebdSchin 						}
2119*b30d1939SAndy Fiddaman 						else if (*s == '\f')
2120da2e3ebdSchin 						{
2121*b30d1939SAndy Fiddaman 							s++;
2122da2e3ebdSchin 							if (style != STYLE_keys)
2123da2e3ebdSchin 							{
2124*b30d1939SAndy Fiddaman 								psp = info(psp, s, NiL, ip, id);
2125da2e3ebdSchin 								if (psp->nb)
2126*b30d1939SAndy Fiddaman 									s = psp->nb;
2127da2e3ebdSchin 								else
2128da2e3ebdSchin 								{
2129*b30d1939SAndy Fiddaman 									s = psp->ob;
2130da2e3ebdSchin 									psp = psp->next;
2131da2e3ebdSchin 								}
2132da2e3ebdSchin 							}
2133da2e3ebdSchin 						}
2134*b30d1939SAndy Fiddaman 						else if (!*s)
2135da2e3ebdSchin 						{
2136da2e3ebdSchin 							if (!(tsp = psp))
2137da2e3ebdSchin 								break;
2138*b30d1939SAndy Fiddaman 							s = psp->ob;
2139da2e3ebdSchin 							psp = psp->next;
2140da2e3ebdSchin 							free(tsp);
2141da2e3ebdSchin 						}
2142*b30d1939SAndy Fiddaman 						else if (*s != OG)
2143da2e3ebdSchin 							break;
2144da2e3ebdSchin 						else
2145da2e3ebdSchin 						{
2146*b30d1939SAndy Fiddaman 							s++;
2147da2e3ebdSchin 							if ((level -= 2) <= lev)
2148da2e3ebdSchin 								break;
2149da2e3ebdSchin 						}
2150da2e3ebdSchin 					}
2151*b30d1939SAndy Fiddaman 					return s;
2152da2e3ebdSchin 				}
2153*b30d1939SAndy Fiddaman 				s++;
2154da2e3ebdSchin 				break;
2155da2e3ebdSchin 			case '\a':
2156da2e3ebdSchin 				a = FONT_ITALIC;
2157da2e3ebdSchin 			setfont:
2158da2e3ebdSchin 				if (f & ~a)
2159da2e3ebdSchin 				{
2160da2e3ebdSchin 					sfputr(sp, font(f, style, 0), -1);
2161da2e3ebdSchin 					f = 0;
2162da2e3ebdSchin 				}
2163da2e3ebdSchin 				if (!f && style == STYLE_html)
2164da2e3ebdSchin 				{
2165*b30d1939SAndy Fiddaman 					for (t = s; *t && !isspace(*t) && !iscntrl(*t); t++);
2166da2e3ebdSchin 					if (*t == c && *++t == '(')
2167da2e3ebdSchin 					{
2168*b30d1939SAndy Fiddaman 						w = t;
2169*b30d1939SAndy Fiddaman 						if (isdigit(*++t))
2170*b30d1939SAndy Fiddaman 							while (isupper(*++t));
2171*b30d1939SAndy Fiddaman 						if (*t == ')' && t > w + 1)
2172da2e3ebdSchin 						{
2173*b30d1939SAndy Fiddaman 							sfprintf(sp, "<NOBR><A href=\"../man%-.*s/"
2174*b30d1939SAndy Fiddaman 								, t - w - 1, w + 1
2175*b30d1939SAndy Fiddaman 								);
2176*b30d1939SAndy Fiddaman 							for (q = s; q < w - 1; q++)
2177*b30d1939SAndy Fiddaman 								if (*q == ':' && q < w - 2 && *(q + 1) == ':')
2178*b30d1939SAndy Fiddaman 								{
2179*b30d1939SAndy Fiddaman 									sfputc(sp, '-');
2180*b30d1939SAndy Fiddaman 									q++;
2181*b30d1939SAndy Fiddaman 								}
2182*b30d1939SAndy Fiddaman 								else
2183*b30d1939SAndy Fiddaman 									sfputc(sp, *q);
2184*b30d1939SAndy Fiddaman 							sfprintf(sp, ".html\">%s%-.*s%s</A>%-.*s</NOBR>"
2185da2e3ebdSchin 								, font(a, style, 1)
2186*b30d1939SAndy Fiddaman 								, w - s - 1, s
2187da2e3ebdSchin 								, font(a, style, 0)
2188*b30d1939SAndy Fiddaman 								, t - w + 1, w
2189da2e3ebdSchin 								);
2190*b30d1939SAndy Fiddaman 							s = t + 1;
2191da2e3ebdSchin 							continue;
2192da2e3ebdSchin 						}
2193da2e3ebdSchin 					}
2194da2e3ebdSchin 				}
2195da2e3ebdSchin 				sfputr(sp, font(a, style, !!(f ^= a)), -1);
2196da2e3ebdSchin 				continue;
2197da2e3ebdSchin 			case '\b':
2198da2e3ebdSchin 				a = FONT_BOLD;
2199da2e3ebdSchin 				goto setfont;
2200da2e3ebdSchin 			case '\f':
2201da2e3ebdSchin 				if (style != STYLE_keys)
2202da2e3ebdSchin 				{
2203*b30d1939SAndy Fiddaman 					psp = info(psp, s, NiL, ip, id);
2204da2e3ebdSchin 					if (psp->nb)
2205*b30d1939SAndy Fiddaman 						s = psp->nb;
2206da2e3ebdSchin 					else
2207da2e3ebdSchin 					{
2208*b30d1939SAndy Fiddaman 						s = psp->ob;
2209da2e3ebdSchin 						psp = psp->next;
2210da2e3ebdSchin 					}
2211da2e3ebdSchin 				}
2212da2e3ebdSchin 				continue;
2213da2e3ebdSchin 			case '\v':
2214da2e3ebdSchin 				a = FONT_LITERAL;
2215da2e3ebdSchin 				goto setfont;
2216da2e3ebdSchin 			case ' ':
2217*b30d1939SAndy Fiddaman 				if (ident && *s == '$')
2218da2e3ebdSchin 				{
2219*b30d1939SAndy Fiddaman 					while (*++s)
2220*b30d1939SAndy Fiddaman 						if (*s == ']')
2221da2e3ebdSchin 						{
2222*b30d1939SAndy Fiddaman 							if (*(s + 1) != ']')
2223da2e3ebdSchin 								break;
2224*b30d1939SAndy Fiddaman 							s++;
2225da2e3ebdSchin 						}
2226da2e3ebdSchin 					continue;
2227da2e3ebdSchin 				}
2228da2e3ebdSchin 			case '\n':
2229da2e3ebdSchin 			case '\r':
2230da2e3ebdSchin 			case '\t':
2231*b30d1939SAndy Fiddaman 				while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n')
2232*b30d1939SAndy Fiddaman 					s++;
2233*b30d1939SAndy Fiddaman 				if (*s == ']' && *(s + 1) != ']' && (!psp || !psp->ch))
2234da2e3ebdSchin 					continue;
2235da2e3ebdSchin 				c = ' ';
2236da2e3ebdSchin 				break;
2237da2e3ebdSchin 			case '<':
2238da2e3ebdSchin 				if (style == STYLE_html)
2239da2e3ebdSchin 				{
2240da2e3ebdSchin 					sfputr(sp, "&lt;", -1);
2241da2e3ebdSchin 					c = 0;
2242*b30d1939SAndy Fiddaman 					for (t = s; *t; t++)
2243da2e3ebdSchin 						if (!isalnum(*t) && *t != '_' && *t != '.' && *t != '-')
2244da2e3ebdSchin 						{
2245da2e3ebdSchin 							if (*t == '@')
2246da2e3ebdSchin 							{
2247da2e3ebdSchin 								if (c)
2248da2e3ebdSchin 									break;
2249da2e3ebdSchin 								c = 1;
2250da2e3ebdSchin 							}
2251da2e3ebdSchin 							else if (*t == '>')
2252da2e3ebdSchin 							{
2253da2e3ebdSchin 								if (c)
2254da2e3ebdSchin 								{
2255*b30d1939SAndy Fiddaman 									sfprintf(sp, "<A href=\"mailto:%-.*s\">%-.*s</A>&gt;", t - s, s, t - s, s);
2256*b30d1939SAndy Fiddaman 									s = t + 1;
2257da2e3ebdSchin 								}
2258da2e3ebdSchin 								break;
2259da2e3ebdSchin 							}
2260da2e3ebdSchin 							else
2261da2e3ebdSchin 								break;
2262da2e3ebdSchin 						}
2263da2e3ebdSchin 					continue;
2264da2e3ebdSchin 				}
2265da2e3ebdSchin 				break;
2266da2e3ebdSchin 			case '>':
2267da2e3ebdSchin 				if (style == STYLE_html)
2268da2e3ebdSchin 				{
2269da2e3ebdSchin 					sfputr(sp, "&gt;", -1);
2270da2e3ebdSchin 					continue;
2271da2e3ebdSchin 				}
2272da2e3ebdSchin 				break;
2273da2e3ebdSchin 			case '&':
2274da2e3ebdSchin 				if (style == STYLE_html)
2275da2e3ebdSchin 				{
2276da2e3ebdSchin 					sfputr(sp, "&amp;", -1);
2277da2e3ebdSchin 					continue;
2278da2e3ebdSchin 				}
2279da2e3ebdSchin 				break;
2280da2e3ebdSchin 			case '-':
2281da2e3ebdSchin 				if (style == STYLE_nroff)
2282da2e3ebdSchin 					sfputc(sp, '\\');
2283da2e3ebdSchin 				break;
2284da2e3ebdSchin 			case '.':
2285da2e3ebdSchin 				if (style == STYLE_nroff)
2286da2e3ebdSchin 				{
2287da2e3ebdSchin 					sfputc(sp, '\\');
2288da2e3ebdSchin 					sfputc(sp, '&');
2289da2e3ebdSchin 				}
2290da2e3ebdSchin 				break;
2291da2e3ebdSchin 			case '\\':
2292da2e3ebdSchin 				if (style == STYLE_nroff)
2293da2e3ebdSchin 				{
2294da2e3ebdSchin 					sfputc(sp, c);
2295da2e3ebdSchin 					c = 'e';
2296da2e3ebdSchin 				}
2297da2e3ebdSchin 				break;
2298da2e3ebdSchin 			}
2299da2e3ebdSchin 			sfputc(sp, c);
2300da2e3ebdSchin 		}
2301da2e3ebdSchin 	}
2302da2e3ebdSchin 	else if (c == '[' && level > lev)
2303da2e3ebdSchin 	{
2304*b30d1939SAndy Fiddaman 		s++;
2305da2e3ebdSchin 		goto again;
2306da2e3ebdSchin 	}
2307*b30d1939SAndy Fiddaman 	return s;
2308da2e3ebdSchin }
2309da2e3ebdSchin 
2310da2e3ebdSchin /*
2311da2e3ebdSchin  * generate optget() help [...] list from lp
2312da2e3ebdSchin  */
2313da2e3ebdSchin 
2314da2e3ebdSchin static void
list(Sfio_t * sp,register const List_t * lp)2315da2e3ebdSchin list(Sfio_t* sp, register const List_t* lp)
2316da2e3ebdSchin {
2317da2e3ebdSchin 	sfprintf(sp, "[%c", lp->type);
2318da2e3ebdSchin 	if (lp->name)
2319da2e3ebdSchin 	{
2320da2e3ebdSchin 		sfprintf(sp, "%s", lp->name);
2321da2e3ebdSchin 		if (lp->text)
2322da2e3ebdSchin 			sfprintf(sp, "?%s", lp->text);
2323da2e3ebdSchin 	}
2324da2e3ebdSchin 	sfputc(sp, ']');
2325da2e3ebdSchin }
2326da2e3ebdSchin 
2327da2e3ebdSchin /*
2328da2e3ebdSchin  * return pointer to help message sans `Usage: command'
2329*b30d1939SAndy Fiddaman  * if oopts is 0 then state.pass is used
2330da2e3ebdSchin  * what:
2331da2e3ebdSchin  *	0	?short by default, ?long if any long options used
2332da2e3ebdSchin  *	*	otherwise see help_text[] (--???)
2333da2e3ebdSchin  * external formatter:
2334da2e3ebdSchin  *	\a...\a	italic
2335da2e3ebdSchin  *	\b...\b	bold
2336da2e3ebdSchin  *	\f...\f	discipline infof callback on ...
2337da2e3ebdSchin  *	\v...\v	literal
2338da2e3ebdSchin  * internal formatter:
2339da2e3ebdSchin  *	\t	indent
2340da2e3ebdSchin  *	\n	newline
2341da2e3ebdSchin  * margin flush pops to previous indent
2342da2e3ebdSchin  */
2343da2e3ebdSchin 
2344da2e3ebdSchin char*
opthelp(const char * oopts,const char * what)2345da2e3ebdSchin opthelp(const char* oopts, const char* what)
2346da2e3ebdSchin {
2347da2e3ebdSchin 	register Sfio_t*	sp;
2348da2e3ebdSchin 	register Sfio_t*	mp;
2349da2e3ebdSchin 	register int		c;
2350da2e3ebdSchin 	register char*		p;
2351da2e3ebdSchin 	register Indent_t*	ip;
2352da2e3ebdSchin 	char*			t;
2353da2e3ebdSchin 	char*			x;
2354da2e3ebdSchin 	char*			w;
2355da2e3ebdSchin 	char*			u;
2356da2e3ebdSchin 	char*			y;
2357da2e3ebdSchin 	char*			s;
2358da2e3ebdSchin 	char*			d;
2359da2e3ebdSchin 	char*			v;
2360*b30d1939SAndy Fiddaman 	char*			cb;
2361*b30d1939SAndy Fiddaman 	char*			dt;
2362da2e3ebdSchin 	char*			ov;
2363da2e3ebdSchin 	char*			pp;
2364da2e3ebdSchin 	char*			rb;
2365da2e3ebdSchin 	char*			re;
2366da2e3ebdSchin 	int			f;
2367da2e3ebdSchin 	int			i;
2368da2e3ebdSchin 	int			j;
2369da2e3ebdSchin 	int			m;
2370da2e3ebdSchin 	int			n;
2371da2e3ebdSchin 	int			a;
2372*b30d1939SAndy Fiddaman 	int			cl;
2373da2e3ebdSchin 	int			sl;
2374da2e3ebdSchin 	int			vl;
2375da2e3ebdSchin 	int			ol;
2376da2e3ebdSchin 	int			wl;
2377da2e3ebdSchin 	int			xl;
2378da2e3ebdSchin 	int			rm;
2379da2e3ebdSchin 	int			ts;
2380da2e3ebdSchin 	int			co;
2381da2e3ebdSchin 	int			z;
2382da2e3ebdSchin 	int			style;
2383da2e3ebdSchin 	int			head;
23847c2fbfb3SApril Chin 	int			margin;
2385da2e3ebdSchin 	int			mode;
2386da2e3ebdSchin 	int			mutex;
2387da2e3ebdSchin 	int			prefix;
2388da2e3ebdSchin 	int			version;
2389da2e3ebdSchin 	long			tp;
23903e14f97fSRoger A. Faulkner 	char*			id;
2391da2e3ebdSchin 	char*			catalog;
2392da2e3ebdSchin 	Optpass_t*		o;
2393da2e3ebdSchin 	Optpass_t*		q;
2394da2e3ebdSchin 	Optpass_t*		e;
2395da2e3ebdSchin 	Optpass_t		one;
2396*b30d1939SAndy Fiddaman 	Optpass_t		top;
2397da2e3ebdSchin 	Help_t*			hp;
2398*b30d1939SAndy Fiddaman 	Tag_t			ptstk[elementsof(indent) + 2];
2399*b30d1939SAndy Fiddaman 	Tag_t*			pt;
2400da2e3ebdSchin 	Sfio_t*			vp;
2401da2e3ebdSchin 	Push_t*			tsp;
2402da2e3ebdSchin 
2403da2e3ebdSchin 	char*			opts = (char*)oopts;
2404*b30d1939SAndy Fiddaman 	char*			section = "1";
2405da2e3ebdSchin 	int			flags = 0;
2406*b30d1939SAndy Fiddaman 	int			bflags = 0;
2407*b30d1939SAndy Fiddaman 	int			dflags = 0;
2408*b30d1939SAndy Fiddaman 	int			hflags = 0;
2409da2e3ebdSchin 	int			matched = 0;
2410da2e3ebdSchin 	int			paragraph = 0;
2411da2e3ebdSchin 	Push_t*			psp = 0;
2412da2e3ebdSchin 	Sfio_t*			sp_help = 0;
2413da2e3ebdSchin 	Sfio_t*			sp_text = 0;
2414da2e3ebdSchin 	Sfio_t*			sp_plus = 0;
2415da2e3ebdSchin 	Sfio_t*			sp_head = 0;
2416da2e3ebdSchin 	Sfio_t*			sp_body = 0;
2417da2e3ebdSchin 	Sfio_t*			sp_info = 0;
2418da2e3ebdSchin 	Sfio_t*			sp_misc = 0;
2419da2e3ebdSchin 
2420*b30d1939SAndy Fiddaman 	if (!(mp = state.mp) && !(mp = state.mp = sfstropen()))
2421da2e3ebdSchin 		goto nospace;
2422da2e3ebdSchin 	if (!what)
2423*b30d1939SAndy Fiddaman 		style = state.style;
2424da2e3ebdSchin 	else if (!*what)
2425da2e3ebdSchin 		style = STYLE_options;
2426da2e3ebdSchin 	else if (*what != '?')
2427da2e3ebdSchin 		style = STYLE_match;
2428da2e3ebdSchin 	else if (!*(what + 1))
2429da2e3ebdSchin 		style = STYLE_man;
2430da2e3ebdSchin 	else if ((hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), (char*)what + 1)) && hp->style >= 0)
2431da2e3ebdSchin 	{
2432da2e3ebdSchin 		style = hp->style;
2433da2e3ebdSchin 		if (*hp->name != '?')
2434da2e3ebdSchin 			what = hp->name;
2435da2e3ebdSchin 	}
2436da2e3ebdSchin 	else
2437da2e3ebdSchin 	{
2438*b30d1939SAndy Fiddaman 		if ((style = state.force) < STYLE_man)
2439da2e3ebdSchin 			style = STYLE_man;
2440da2e3ebdSchin 		if (!(sp_help = sfstropen()))
2441da2e3ebdSchin 			goto nospace;
2442da2e3ebdSchin 		for (i = 0; i < elementsof(help_head); i++)
2443da2e3ebdSchin 			list(sp_help, &help_head[i]);
2444da2e3ebdSchin 		for (i = 0; i < elementsof(styles); i++)
2445da2e3ebdSchin 			sfprintf(sp_help, "[:%s?%s]", styles[i].match, styles[i].text);
2446da2e3ebdSchin 		for (i = 0; i < elementsof(help_tail); i++)
2447da2e3ebdSchin 			list(sp_help, &help_tail[i]);
2448da2e3ebdSchin 		if (!(opts = sfstruse(sp_help)))
2449da2e3ebdSchin 			goto nospace;
2450da2e3ebdSchin 	}
2451*b30d1939SAndy Fiddaman 
2452*b30d1939SAndy Fiddaman 	/*
2453*b30d1939SAndy Fiddaman 	 * this is a workaround for static optjoin() data
2454*b30d1939SAndy Fiddaman 	 * clobbered by plugins/builtins that may be called
2455*b30d1939SAndy Fiddaman 	 * evaluating \f...\f -- it would be good to hide
2456*b30d1939SAndy Fiddaman 	 * optjoin() interactions a bit more ...
2457*b30d1939SAndy Fiddaman 	 */
2458*b30d1939SAndy Fiddaman 
2459*b30d1939SAndy Fiddaman 	top = state.pass[0];
2460da2e3ebdSchin  again:
2461da2e3ebdSchin 	if (opts)
2462da2e3ebdSchin 	{
2463*b30d1939SAndy Fiddaman 		for (i = 0; i < state.npass; i++)
2464*b30d1939SAndy Fiddaman 			if (state.pass[i].oopts == opts)
2465da2e3ebdSchin 			{
2466*b30d1939SAndy Fiddaman 				o = &state.pass[i];
2467da2e3ebdSchin 				break;
2468da2e3ebdSchin 			}
2469*b30d1939SAndy Fiddaman 		if (i >= state.npass)
2470da2e3ebdSchin 		{
2471da2e3ebdSchin 			o = &one;
2472da2e3ebdSchin 			if (init((char*)opts, o))
2473da2e3ebdSchin 				goto nospace;
2474da2e3ebdSchin 		}
2475da2e3ebdSchin 		e = o + 1;
2476da2e3ebdSchin 	}
2477*b30d1939SAndy Fiddaman 	else
2478da2e3ebdSchin 	{
2479*b30d1939SAndy Fiddaman 		if (state.npass > 0)
2480*b30d1939SAndy Fiddaman 		{
2481*b30d1939SAndy Fiddaman 			o = state.pass;
2482*b30d1939SAndy Fiddaman 			e = o + state.npass;
2483*b30d1939SAndy Fiddaman 		}
2484*b30d1939SAndy Fiddaman 		else if (state.npass < 0)
2485*b30d1939SAndy Fiddaman 		{
2486*b30d1939SAndy Fiddaman 			o = &state.cache->pass;
2487*b30d1939SAndy Fiddaman 			e = o + 1;
2488*b30d1939SAndy Fiddaman 		}
2489*b30d1939SAndy Fiddaman 		else
2490*b30d1939SAndy Fiddaman 			return T(NiL, ID, "[* call optget() before opthelp() *]");
2491*b30d1939SAndy Fiddaman 		oopts = (const char*)state.pass[0].oopts;
2492da2e3ebdSchin 	}
249334f9b3eeSRoland Mainz 	if (style <= STYLE_usage)
2494da2e3ebdSchin 	{
2495da2e3ebdSchin 		if (!(sp_text = sfstropen()) || !(sp_info = sfstropen()))
2496da2e3ebdSchin 			goto nospace;
2497da2e3ebdSchin 		if (style >= STYLE_match && style < STYLE_keys && !(sp_body = sfstropen()))
2498da2e3ebdSchin 			goto nospace;
2499da2e3ebdSchin 	}
2500da2e3ebdSchin 	switch (style)
2501da2e3ebdSchin 	{
2502da2e3ebdSchin 	case STYLE_api:
2503da2e3ebdSchin 	case STYLE_html:
2504da2e3ebdSchin 	case STYLE_nroff:
2505*b30d1939SAndy Fiddaman 		state.emphasis = 0;
2506da2e3ebdSchin 		break;
2507da2e3ebdSchin 	case STYLE_usage:
2508da2e3ebdSchin 	case STYLE_keys:
2509da2e3ebdSchin 		for (q = o; q < e; q++)
2510da2e3ebdSchin 			if (!(q->flags & OPT_ignore) && !streq(q->catalog, o->catalog))
2511da2e3ebdSchin 				o = q;
2512da2e3ebdSchin 		/*FALLTHROUGH*/
2513da2e3ebdSchin 	case STYLE_posix:
2514da2e3ebdSchin 		sfputc(mp, '\f');
2515da2e3ebdSchin 		break;
2516da2e3ebdSchin 	default:
2517*b30d1939SAndy Fiddaman 		if (!state.emphasis)
2518da2e3ebdSchin 		{
2519da2e3ebdSchin 			if (x = getenv("ERROR_OPTIONS"))
2520da2e3ebdSchin 			{
2521da2e3ebdSchin 				if (strmatch(x, "*noemphasi*"))
2522da2e3ebdSchin 					break;
2523da2e3ebdSchin 				if (strmatch(x, "*emphasi*"))
2524da2e3ebdSchin 				{
2525*b30d1939SAndy Fiddaman 					state.emphasis = 1;
2526da2e3ebdSchin 					break;
2527da2e3ebdSchin 				}
2528da2e3ebdSchin 			}
2529da2e3ebdSchin 			if ((x = getenv("TERM")) && strmatch(x, "(ansi|vt100|xterm)*") && isatty(sffileno(sfstderr)))
2530*b30d1939SAndy Fiddaman 				state.emphasis = 1;
2531da2e3ebdSchin 		}
2532da2e3ebdSchin 		break;
2533da2e3ebdSchin 	}
2534da2e3ebdSchin 	x = "";
2535da2e3ebdSchin 	xl = 0;
2536da2e3ebdSchin 	for (q = o; q < e; q++)
2537da2e3ebdSchin 	{
2538da2e3ebdSchin 		if (q->flags & OPT_ignore)
2539da2e3ebdSchin 			continue;
2540da2e3ebdSchin 		section = q->section;
2541da2e3ebdSchin 		flags |= q->flags;
2542da2e3ebdSchin 		p = q->opts;
2543da2e3ebdSchin 		prefix = q->prefix;
2544da2e3ebdSchin 		version = q->version;
25453e14f97fSRoger A. Faulkner 		id = q->id;
2546da2e3ebdSchin 		catalog = q->catalog;
2547da2e3ebdSchin 		switch (style)
2548da2e3ebdSchin 		{
2549da2e3ebdSchin 		case STYLE_usage:
2550da2e3ebdSchin 			if (xl)
2551da2e3ebdSchin 				sfputc(mp, '\n');
2552da2e3ebdSchin 			else
2553da2e3ebdSchin 				xl = 1;
255434f9b3eeSRoland Mainz 			psp = 0;
255534f9b3eeSRoland Mainz 			for (;;)
2556da2e3ebdSchin 			{
255734f9b3eeSRoland Mainz 				switch (c = *p++)
2558da2e3ebdSchin 				{
255934f9b3eeSRoland Mainz 				case 0:
256034f9b3eeSRoland Mainz 					if (!(tsp = psp))
256134f9b3eeSRoland Mainz 						goto style_usage;
256234f9b3eeSRoland Mainz 					p = psp->ob;
256334f9b3eeSRoland Mainz 					psp = psp->next;
256434f9b3eeSRoland Mainz 					free(tsp);
256534f9b3eeSRoland Mainz 					continue;
2566da2e3ebdSchin 				case '\a':
2567da2e3ebdSchin 					c = 'a';
2568da2e3ebdSchin 					break;
2569da2e3ebdSchin 				case '\b':
2570da2e3ebdSchin 					c = 'b';
2571da2e3ebdSchin 					break;
2572da2e3ebdSchin 				case '\f':
25733e14f97fSRoger A. Faulkner 					psp = info(psp, p, NiL, sp_info, id);
257434f9b3eeSRoland Mainz 					if (psp->nb)
257534f9b3eeSRoland Mainz 						p = psp->nb;
257634f9b3eeSRoland Mainz 					else
257734f9b3eeSRoland Mainz 					{
257834f9b3eeSRoland Mainz 						p = psp->ob;
257934f9b3eeSRoland Mainz 						psp = psp->next;
258034f9b3eeSRoland Mainz 					}
258134f9b3eeSRoland Mainz 					continue;
2582da2e3ebdSchin 				case '\n':
2583da2e3ebdSchin 					c = 'n';
2584da2e3ebdSchin 					break;
2585da2e3ebdSchin 				case '\r':
2586da2e3ebdSchin 					c = 'r';
2587da2e3ebdSchin 					break;
2588da2e3ebdSchin 				case '\t':
2589da2e3ebdSchin 					c = 't';
2590da2e3ebdSchin 					break;
2591da2e3ebdSchin 				case '\v':
2592da2e3ebdSchin 					c = 'v';
2593da2e3ebdSchin 					break;
2594da2e3ebdSchin 				case '"':
2595da2e3ebdSchin 					c = '"';
2596da2e3ebdSchin 					break;
2597da2e3ebdSchin 				case '\'':
2598da2e3ebdSchin 					c = '\'';
2599da2e3ebdSchin 					break;
2600da2e3ebdSchin 				case '\\':
2601da2e3ebdSchin 					c = '\\';
2602da2e3ebdSchin 					break;
2603da2e3ebdSchin 				default:
2604da2e3ebdSchin 					sfputc(mp, c);
2605da2e3ebdSchin 					continue;
2606da2e3ebdSchin 				}
2607da2e3ebdSchin 				sfputc(mp, '\\');
2608da2e3ebdSchin 				sfputc(mp, c);
2609da2e3ebdSchin 			}
261034f9b3eeSRoland Mainz 		style_usage:
2611da2e3ebdSchin 			continue;
2612da2e3ebdSchin 		case STYLE_keys:
2613da2e3ebdSchin 			a = 0;
2614da2e3ebdSchin 			psp = 0;
2615da2e3ebdSchin 			vl = 0;
2616da2e3ebdSchin 			for (;;)
2617da2e3ebdSchin 			{
2618da2e3ebdSchin 				if (!(c = *p++))
2619da2e3ebdSchin 				{
2620da2e3ebdSchin 					if (!(tsp = psp))
2621da2e3ebdSchin 						break;
2622da2e3ebdSchin 					p = psp->ob;
2623da2e3ebdSchin 					psp = psp->next;
2624da2e3ebdSchin 					free(tsp);
2625da2e3ebdSchin 					continue;
2626da2e3ebdSchin 				}
2627da2e3ebdSchin 				if (c == '\f')
2628da2e3ebdSchin 				{
26293e14f97fSRoger A. Faulkner 					psp = info(psp, p, NiL, sp_info, id);
2630da2e3ebdSchin 					if (psp->nb)
2631da2e3ebdSchin 						p = psp->nb;
2632da2e3ebdSchin 					else
2633da2e3ebdSchin 					{
2634da2e3ebdSchin 						p = psp->ob;
2635da2e3ebdSchin 						psp = psp->next;
2636da2e3ebdSchin 					}
2637da2e3ebdSchin 					continue;
2638da2e3ebdSchin 				}
2639da2e3ebdSchin 				f = z = 1;
2640da2e3ebdSchin 				t = 0;
2641da2e3ebdSchin 				if (a == 0 && (c == ' ' || c == '\n' && *p == '\n'))
2642da2e3ebdSchin 				{
2643da2e3ebdSchin 					if (c == ' ' && *p == ']')
2644da2e3ebdSchin 					{
2645da2e3ebdSchin 						p++;
2646da2e3ebdSchin 						continue;
2647da2e3ebdSchin 					}
2648da2e3ebdSchin 					if (*p == '\n')
2649da2e3ebdSchin 						p++;
2650da2e3ebdSchin 					a = c;
2651da2e3ebdSchin 				}
2652da2e3ebdSchin 				else if (c == '\n')
2653da2e3ebdSchin 				{
2654da2e3ebdSchin 					if (a == ' ')
2655da2e3ebdSchin 						a = -1;
2656da2e3ebdSchin 					else if (a == '\n' || *p == '\n')
2657da2e3ebdSchin 					{
2658da2e3ebdSchin 						a = -1;
2659da2e3ebdSchin 						p++;
2660da2e3ebdSchin 					}
2661da2e3ebdSchin 					continue;
2662da2e3ebdSchin 				}
2663da2e3ebdSchin 				else if ((c == ':' || c == '#') && (*p == '[' || *p == '?' && *(p + 1) == '[' && p++))
2664da2e3ebdSchin 					p++;
2665da2e3ebdSchin 				else if (c != '[')
2666da2e3ebdSchin 				{
26677c2fbfb3SApril Chin 					if (c == GO)
2668da2e3ebdSchin 						vl++;
26697c2fbfb3SApril Chin 					else if (c == OG)
2670da2e3ebdSchin 						vl--;
2671da2e3ebdSchin 					continue;
2672da2e3ebdSchin 				}
2673da2e3ebdSchin 				else if (*p == ' ')
2674da2e3ebdSchin 				{
2675da2e3ebdSchin 					p++;
2676da2e3ebdSchin 					continue;
2677da2e3ebdSchin 				}
2678da2e3ebdSchin 				else if (*p == '-')
2679da2e3ebdSchin 				{
2680da2e3ebdSchin 					z = 0;
2681da2e3ebdSchin 					if (*++p == '-')
2682da2e3ebdSchin 					{
2683da2e3ebdSchin 						p = skip(p, 0, 0, 0, 1, 0, 1, version);
2684da2e3ebdSchin 						continue;
2685da2e3ebdSchin 					}
2686da2e3ebdSchin 				}
2687da2e3ebdSchin 				else if (*p == '+')
2688da2e3ebdSchin 				{
2689da2e3ebdSchin 					p++;
2690da2e3ebdSchin 					if (vl > 0 && *p != '\a')
2691da2e3ebdSchin 					{
2692da2e3ebdSchin 						f = 0;
2693da2e3ebdSchin 						p = skip(p, '?', 0, 0, 1, 0, 0, version);
2694da2e3ebdSchin 						if (*p == '?')
2695da2e3ebdSchin 							p++;
2696da2e3ebdSchin 					}
2697da2e3ebdSchin 				}
2698da2e3ebdSchin 				else
2699da2e3ebdSchin 				{
2700*b30d1939SAndy Fiddaman 					if (*(p + 1) == '\f' && (vp = state.vp))
27013e14f97fSRoger A. Faulkner 						p = expand(p + 2, NiL, &t, vp, id);
2702da2e3ebdSchin 					p = skip(p, ':', '?', 0, 1, 0, 0, version);
2703da2e3ebdSchin 					if (*p == ':')
2704da2e3ebdSchin 						p++;
2705da2e3ebdSchin 				}
2706da2e3ebdSchin 				if (f && *p == '?' && *(p + 1) != '?')
2707da2e3ebdSchin 				{
2708da2e3ebdSchin 					f = 0;
2709da2e3ebdSchin 					if (z)
2710da2e3ebdSchin 						p++;
2711da2e3ebdSchin 					else
2712da2e3ebdSchin 						p = skip(p, 0, 0, 0, 1, 0, 0, version);
2713da2e3ebdSchin 				}
2714da2e3ebdSchin 				if (*p == ']' && *(p + 1) != ']')
2715da2e3ebdSchin 				{
2716da2e3ebdSchin 					p++;
2717da2e3ebdSchin 					continue;
2718da2e3ebdSchin 				}
2719da2e3ebdSchin 				if (!*p)
2720da2e3ebdSchin 				{
2721da2e3ebdSchin 					if (!t)
2722da2e3ebdSchin 						break;
2723da2e3ebdSchin 					p = t;
2724da2e3ebdSchin 					t = 0;
2725da2e3ebdSchin 				}
2726da2e3ebdSchin 				m = sfstrtell(mp);
2727da2e3ebdSchin 				sfputc(mp, '"');
2728da2e3ebdSchin 				xl = 1;
2729da2e3ebdSchin 				/*UNDENT...*/
2730da2e3ebdSchin 
2731da2e3ebdSchin 	for (;;)
2732da2e3ebdSchin 	{
2733da2e3ebdSchin 		if (!(c = *p++))
2734da2e3ebdSchin 		{
2735da2e3ebdSchin 			if (t)
2736da2e3ebdSchin 			{
2737da2e3ebdSchin 				p = t;
2738da2e3ebdSchin 				t = 0;
2739da2e3ebdSchin 			}
2740da2e3ebdSchin 			if (!(tsp = psp))
2741da2e3ebdSchin 			{
2742da2e3ebdSchin 				p--;
2743da2e3ebdSchin 				break;
2744da2e3ebdSchin 			}
2745da2e3ebdSchin 			p = psp->ob;
2746da2e3ebdSchin 			psp = psp->next;
2747da2e3ebdSchin 			free(tsp);
2748da2e3ebdSchin 			continue;
2749da2e3ebdSchin 		}
2750da2e3ebdSchin 		if (a > 0)
2751da2e3ebdSchin 		{
2752da2e3ebdSchin 			if (c == '\n')
2753da2e3ebdSchin 			{
2754da2e3ebdSchin 				if (a == ' ')
2755da2e3ebdSchin 				{
2756da2e3ebdSchin 					a = -1;
2757da2e3ebdSchin 					break;
2758da2e3ebdSchin 				}
2759da2e3ebdSchin 				if (a == '\n' || *p == '\n')
2760da2e3ebdSchin 				{
2761da2e3ebdSchin 					a = -1;
2762da2e3ebdSchin 					p++;
2763da2e3ebdSchin 					break;
2764da2e3ebdSchin 				}
2765da2e3ebdSchin 			}
2766da2e3ebdSchin 		}
2767da2e3ebdSchin 		else if (c == ']')
2768da2e3ebdSchin 		{
2769da2e3ebdSchin 			if (*p != ']')
2770da2e3ebdSchin 			{
2771da2e3ebdSchin 				sfputc(mp, 0);
2772da2e3ebdSchin 				y = sfstrbase(mp) + m + 1;
2773da2e3ebdSchin 				if (D(y) || !strmatch(y, KEEP) || strmatch(y, OMIT))
2774da2e3ebdSchin 				{
2775da2e3ebdSchin 					sfstrseek(mp, m, SEEK_SET);
2776da2e3ebdSchin 					xl = 0;
2777da2e3ebdSchin 				}
2778da2e3ebdSchin 				else
2779da2e3ebdSchin 					sfstrseek(mp, -1, SEEK_CUR);
2780da2e3ebdSchin 				break;
2781da2e3ebdSchin 			}
2782da2e3ebdSchin 			sfputc(mp, *p++);
2783da2e3ebdSchin 			continue;
2784da2e3ebdSchin 		}
2785da2e3ebdSchin 		switch (c)
2786da2e3ebdSchin 		{
2787da2e3ebdSchin 		case '?':
2788da2e3ebdSchin 			if (f)
2789da2e3ebdSchin 			{
2790da2e3ebdSchin 				if (*p == '?')
2791da2e3ebdSchin 				{
2792da2e3ebdSchin 					p++;
2793da2e3ebdSchin 					sfputc(mp, c);
2794da2e3ebdSchin 				}
2795da2e3ebdSchin 				else
2796da2e3ebdSchin 				{
2797da2e3ebdSchin 					f = 0;
2798da2e3ebdSchin 					sfputc(mp, 0);
2799da2e3ebdSchin 					y = sfstrbase(mp) + m + 1;
2800da2e3ebdSchin 					if (D(y) || !strmatch(y, KEEP) || strmatch(y, OMIT))
2801da2e3ebdSchin 					{
2802da2e3ebdSchin 						sfstrseek(mp, m, SEEK_SET);
2803da2e3ebdSchin 						xl = 0;
2804da2e3ebdSchin 					}
2805da2e3ebdSchin 					else
2806da2e3ebdSchin 						sfstrseek(mp, -1, SEEK_CUR);
2807da2e3ebdSchin 					if (z && (*p != ']' || *(p + 1) == ']'))
2808da2e3ebdSchin 					{
2809da2e3ebdSchin 						if (xl)
2810da2e3ebdSchin 						{
2811da2e3ebdSchin 							sfputc(mp, '"');
2812da2e3ebdSchin 							sfputc(mp, '\n');
2813da2e3ebdSchin 						}
2814da2e3ebdSchin 						m = sfstrtell(mp);
2815da2e3ebdSchin 						sfputc(mp, '"');
2816da2e3ebdSchin 						xl = 1;
2817da2e3ebdSchin 					}
2818da2e3ebdSchin 					else
2819da2e3ebdSchin 					{
2820da2e3ebdSchin 						p = skip(p, 0, 0, 0, 1, 0, 0, version);
2821da2e3ebdSchin 						if (*p == '?')
2822da2e3ebdSchin 							p++;
2823da2e3ebdSchin 					}
2824da2e3ebdSchin 				}
2825da2e3ebdSchin 			}
2826da2e3ebdSchin 			else
2827da2e3ebdSchin 				sfputc(mp, c);
2828da2e3ebdSchin 			continue;
2829da2e3ebdSchin 		case ':':
2830da2e3ebdSchin 			if (f && *p == ':')
2831da2e3ebdSchin 				p++;
2832da2e3ebdSchin 			sfputc(mp, c);
2833da2e3ebdSchin 			continue;
2834da2e3ebdSchin 		case '\a':
2835da2e3ebdSchin 			c = 'a';
2836da2e3ebdSchin 			break;
2837da2e3ebdSchin 		case '\b':
2838da2e3ebdSchin 			c = 'b';
2839da2e3ebdSchin 			break;
2840da2e3ebdSchin 		case '\f':
2841da2e3ebdSchin 			c = 'f';
2842da2e3ebdSchin 			break;
2843da2e3ebdSchin 		case '\n':
2844da2e3ebdSchin 			c = 'n';
2845da2e3ebdSchin 			break;
2846da2e3ebdSchin 		case '\r':
2847da2e3ebdSchin 			c = 'r';
2848da2e3ebdSchin 			break;
2849da2e3ebdSchin 		case '\t':
2850da2e3ebdSchin 			c = 't';
2851da2e3ebdSchin 			break;
2852da2e3ebdSchin 		case '\v':
2853da2e3ebdSchin 			c = 'v';
2854da2e3ebdSchin 			break;
2855da2e3ebdSchin 		case '"':
2856da2e3ebdSchin 			c = '"';
2857da2e3ebdSchin 			break;
2858da2e3ebdSchin 		case '\\':
2859da2e3ebdSchin 			c = '\\';
2860da2e3ebdSchin 			break;
2861da2e3ebdSchin 		case CC_esc:
2862da2e3ebdSchin 			c = 'E';
2863da2e3ebdSchin 			break;
2864da2e3ebdSchin 		default:
2865da2e3ebdSchin 			sfputc(mp, c);
2866da2e3ebdSchin 			continue;
2867da2e3ebdSchin 		}
2868da2e3ebdSchin 		sfputc(mp, '\\');
2869da2e3ebdSchin 		sfputc(mp, c);
2870da2e3ebdSchin 	}
2871da2e3ebdSchin 
2872da2e3ebdSchin 				/*...INDENT*/
2873da2e3ebdSchin 				if (xl)
2874da2e3ebdSchin 				{
2875da2e3ebdSchin 					sfputc(mp, '"');
2876da2e3ebdSchin 					sfputc(mp, '\n');
2877da2e3ebdSchin 				}
2878da2e3ebdSchin 			}
2879da2e3ebdSchin 			continue;
2880da2e3ebdSchin 		}
2881da2e3ebdSchin 		z = 0;
2882da2e3ebdSchin 		head = 0;
2883da2e3ebdSchin 		mode = 0;
2884da2e3ebdSchin 		mutex = 0;
2885da2e3ebdSchin 		if (style > STYLE_short && style < STYLE_nroff && version < 1)
2886da2e3ebdSchin 		{
2887da2e3ebdSchin 			style = STYLE_short;
2888da2e3ebdSchin 			if (sp_body)
2889da2e3ebdSchin 			{
2890da2e3ebdSchin 				sfclose(sp_body);
2891da2e3ebdSchin 				sp_body = 0;
2892da2e3ebdSchin 			}
2893da2e3ebdSchin 		}
2894da2e3ebdSchin 		else if (style == STYLE_short && prefix < 2)
2895da2e3ebdSchin 			style = STYLE_long;
2896da2e3ebdSchin 		if (*p == ':')
2897da2e3ebdSchin 			p++;
2898da2e3ebdSchin 		if (*p == '+')
2899da2e3ebdSchin 		{
2900da2e3ebdSchin 			p++;
2901da2e3ebdSchin 			if (!(sp = sp_plus) && !(sp = sp_plus = sfstropen()))
2902da2e3ebdSchin 				goto nospace;
2903da2e3ebdSchin 		}
2904da2e3ebdSchin 		else if (style >= STYLE_match)
2905da2e3ebdSchin 			sp = sp_body;
2906da2e3ebdSchin 		else
2907da2e3ebdSchin 			sp = sp_text;
2908da2e3ebdSchin 		psp = 0;
2909da2e3ebdSchin 		for (;;)
2910da2e3ebdSchin 		{
2911da2e3ebdSchin 			if (!(*(p = next(p, version))))
2912da2e3ebdSchin 			{
2913da2e3ebdSchin 				if (!(tsp = psp))
2914da2e3ebdSchin 					break;
2915da2e3ebdSchin 				p = psp->ob;
2916da2e3ebdSchin 				psp = psp->next;
2917da2e3ebdSchin 				free(tsp);
2918da2e3ebdSchin 				continue;
2919da2e3ebdSchin 			}
2920da2e3ebdSchin 			if (*p == '\f')
2921da2e3ebdSchin 			{
29223e14f97fSRoger A. Faulkner 				psp = info(psp, p + 1, NiL, sp_info, id);
2923da2e3ebdSchin 				if (psp->nb)
2924da2e3ebdSchin 					p = psp->nb;
2925da2e3ebdSchin 				else
2926da2e3ebdSchin 				{
2927da2e3ebdSchin 					p = psp->ob;
2928da2e3ebdSchin 					psp = psp->next;
2929da2e3ebdSchin 				}
2930da2e3ebdSchin 				continue;
2931da2e3ebdSchin 			}
2932da2e3ebdSchin 			if (*p == '\n' || *p == ' ')
2933da2e3ebdSchin 			{
2934da2e3ebdSchin 				if (*(x = p = next(p + 1, version)))
2935da2e3ebdSchin 					while (*++p)
2936da2e3ebdSchin 						if (*p == '\n')
2937da2e3ebdSchin 						{
2938da2e3ebdSchin 							while (*++p == ' ' || *p == '\t' || *p == '\r');
2939da2e3ebdSchin 							if (*p == '\n')
2940da2e3ebdSchin 								break;
2941da2e3ebdSchin 						}
2942da2e3ebdSchin 				xl = p - x;
2943da2e3ebdSchin 				if (!*p)
2944da2e3ebdSchin 					break;
2945da2e3ebdSchin 				continue;
2946da2e3ebdSchin 			}
29477c2fbfb3SApril Chin 			if (*p == OG)
2948da2e3ebdSchin 			{
2949da2e3ebdSchin 				p++;
2950da2e3ebdSchin 				continue;
2951da2e3ebdSchin 			}
2952da2e3ebdSchin 			message((-20, "opthelp: opt %s", show(p)));
2953da2e3ebdSchin 			if (z < 0)
2954da2e3ebdSchin 				z = 0;
2955da2e3ebdSchin 			a = 0;
2956da2e3ebdSchin 			f = 0;
2957da2e3ebdSchin 			w = 0;
2958da2e3ebdSchin 			d = 0;
2959da2e3ebdSchin 			s = 0;
29607c2fbfb3SApril Chin 			rb = re = 0;
2961da2e3ebdSchin 			sl = 0;
29627c2fbfb3SApril Chin 			vl = 0;
2963da2e3ebdSchin 			if (*p == '[')
2964da2e3ebdSchin 			{
2965*b30d1939SAndy Fiddaman 				if ((c = *(p = next(p + 1, version))) == '(')
2966*b30d1939SAndy Fiddaman 				{
2967*b30d1939SAndy Fiddaman 					p = nest(cb = p);
2968*b30d1939SAndy Fiddaman 					cl = p - cb;
2969*b30d1939SAndy Fiddaman 					c = *p;
2970*b30d1939SAndy Fiddaman 				}
2971*b30d1939SAndy Fiddaman 				else
2972*b30d1939SAndy Fiddaman 					cb = 0;
2973*b30d1939SAndy Fiddaman 				if (c == '-')
2974da2e3ebdSchin 				{
2975da2e3ebdSchin 					if (style >= STYLE_man)
2976da2e3ebdSchin 					{
2977da2e3ebdSchin 						if (*(p + 1) != '-')
2978da2e3ebdSchin 						{
2979da2e3ebdSchin 							if (!sp_misc && !(sp_misc = sfstropen()))
2980da2e3ebdSchin 								goto nospace;
2981da2e3ebdSchin 							else
2982*b30d1939SAndy Fiddaman 								p = textout(sp_misc, p, cb, cl, style, 1, 3, sp_info, version, id, catalog, &hflags);
2983da2e3ebdSchin 							continue;
2984da2e3ebdSchin 						}
2985da2e3ebdSchin 					}
2986da2e3ebdSchin 					else if (style == STYLE_match && *what == '-')
2987da2e3ebdSchin 					{
2988*b30d1939SAndy Fiddaman 						if (*(p + 1) == '?' || *(s = skip(p + 1, ':', '?', 0, 1, 0, 0, version)) == '?' && isspace(*(s + 1)))
2989da2e3ebdSchin 							s = C("version");
2990da2e3ebdSchin 						else
2991da2e3ebdSchin 							s = p + 1;
2992da2e3ebdSchin 						w = (char*)what;
2993da2e3ebdSchin 						if (*s != '-' || *(w + 1) == '-')
2994da2e3ebdSchin 						{
2995da2e3ebdSchin 							if (*s == '-')
2996da2e3ebdSchin 								s++;
2997da2e3ebdSchin 							if (*(w + 1) == '-')
2998da2e3ebdSchin 								w++;
29993e14f97fSRoger A. Faulkner 							if (match(w + 1, s, version, id, catalog))
3000da2e3ebdSchin 							{
3001da2e3ebdSchin 								if (*(p + 1) == '-')
3002da2e3ebdSchin 									p++;
3003*b30d1939SAndy Fiddaman 								p = textout(sp, p, cb, cl, style, 1, 3, sp_info, version, id, catalog, &hflags);
3004da2e3ebdSchin 								matched = -1;
3005da2e3ebdSchin 								continue;
3006da2e3ebdSchin 							}
3007da2e3ebdSchin 						}
3008da2e3ebdSchin 					}
3009da2e3ebdSchin 					if (!z)
3010da2e3ebdSchin 						z = -1;
3011da2e3ebdSchin 				}
3012da2e3ebdSchin 				else if (c == '+')
3013da2e3ebdSchin 				{
3014da2e3ebdSchin 					if (style >= STYLE_man)
3015da2e3ebdSchin 					{
3016*b30d1939SAndy Fiddaman 						p = textout(sp_body, p, cb, cl, style, 0, 0, sp_info, version, id, catalog, &bflags);
3017da2e3ebdSchin 						if (!sp_head)
3018da2e3ebdSchin 						{
3019da2e3ebdSchin 							sp_head = sp_body;
3020*b30d1939SAndy Fiddaman 							hflags = dflags = bflags;
3021da2e3ebdSchin 							if (!(sp_body = sfstropen()))
3022da2e3ebdSchin 								goto nospace;
3023da2e3ebdSchin 						}
3024da2e3ebdSchin 						continue;
3025da2e3ebdSchin 					}
3026da2e3ebdSchin 					else if (style == STYLE_match && *what == '+')
3027da2e3ebdSchin 					{
3028da2e3ebdSchin 						if (paragraph)
3029da2e3ebdSchin 						{
3030da2e3ebdSchin 							if (p[1] == '?')
3031da2e3ebdSchin 							{
3032*b30d1939SAndy Fiddaman 								p = textout(sp, p, cb, cl, style, 1, 3, sp_info, version, id, catalog, &hflags);
3033da2e3ebdSchin 								continue;
3034da2e3ebdSchin 							}
3035da2e3ebdSchin 							paragraph = 0;
3036da2e3ebdSchin 						}
30373e14f97fSRoger A. Faulkner 						if (match((char*)what + 1, p + 1, version, id, catalog))
3038da2e3ebdSchin 						{
3039*b30d1939SAndy Fiddaman 							p = textout(sp, p, cb, cl, style, 1, 3, sp_info, version, id, catalog, &hflags);
3040da2e3ebdSchin 							matched = -1;
3041da2e3ebdSchin 							paragraph = 1;
3042da2e3ebdSchin 							continue;
3043da2e3ebdSchin 						}
3044da2e3ebdSchin 					}
3045da2e3ebdSchin 					if (!z)
3046da2e3ebdSchin 						z = -1;
3047da2e3ebdSchin 				}
3048da2e3ebdSchin 				else if (c == '[' || version < 1)
3049da2e3ebdSchin 				{
3050da2e3ebdSchin 					mutex++;
3051da2e3ebdSchin 					continue;
3052da2e3ebdSchin 				}
3053da2e3ebdSchin 				else
3054da2e3ebdSchin 				{
3055da2e3ebdSchin 					if (c == '!')
3056da2e3ebdSchin 					{
3057da2e3ebdSchin 						a |= OPT_invert;
3058da2e3ebdSchin 						p++;
3059da2e3ebdSchin 					}
3060da2e3ebdSchin 					rb = p;
3061da2e3ebdSchin 					if (*p != ':')
3062da2e3ebdSchin 					{
3063da2e3ebdSchin 						s = p;
3064da2e3ebdSchin 						if (*(p + 1) == '|')
3065da2e3ebdSchin 						{
3066da2e3ebdSchin 							while (*++p && *p != '=' && *p != '!' && *p != ':' && *p != '?');
3067da2e3ebdSchin 							if ((p - s) > 1)
3068da2e3ebdSchin 								sl = p - s;
3069da2e3ebdSchin 							if (*p == '!')
3070da2e3ebdSchin 								a |= OPT_invert;
3071da2e3ebdSchin 						}
3072da2e3ebdSchin 						if (*(p + 1) == '\f')
3073da2e3ebdSchin 							p++;
3074da2e3ebdSchin 						else
3075da2e3ebdSchin 							p = skip(p, ':', '?', 0, 1, 0, 0, version);
3076da2e3ebdSchin 						if (sl || (p - s) == 1 || *(s + 1) == '=' || *(s + 1) == '!' && (a |= OPT_invert) || *(s + 1) == '|')
3077da2e3ebdSchin 							f = *s;
3078da2e3ebdSchin 					}
3079da2e3ebdSchin 					re = p;
3080da2e3ebdSchin 					if (style <= STYLE_short)
3081da2e3ebdSchin 					{
3082da2e3ebdSchin 						if (!z && !f)
3083da2e3ebdSchin 							z = -1;
3084da2e3ebdSchin 					}
3085da2e3ebdSchin 					else
3086da2e3ebdSchin 					{
3087*b30d1939SAndy Fiddaman 						if (*p == '\f' && (vp = state.vp))
30883e14f97fSRoger A. Faulkner 							p = expand(p + 1, NiL, &t, vp, id);
3089da2e3ebdSchin 						else
3090da2e3ebdSchin 							t = 0;
3091da2e3ebdSchin 						if (*p == ':')
3092da2e3ebdSchin 						{
3093da2e3ebdSchin 							p = skip(w = p + 1, ':', '?', 0, 1, 0, 0, version);
3094da2e3ebdSchin 							if (!(wl = p - w))
3095da2e3ebdSchin 								w = 0;
3096da2e3ebdSchin 						}
3097da2e3ebdSchin 						else
3098da2e3ebdSchin 							wl = 0;
3099da2e3ebdSchin 						if (*p == ':' || *p == '?')
3100da2e3ebdSchin 						{
3101da2e3ebdSchin 							d = p;
3102da2e3ebdSchin 							p = skip(p, 0, 0, 0, 1, 0, 0, version);
3103da2e3ebdSchin 						}
3104da2e3ebdSchin 						else
3105da2e3ebdSchin 							d = 0;
3106da2e3ebdSchin 						if (style == STYLE_match)
3107da2e3ebdSchin 						{
31083e14f97fSRoger A. Faulkner 							if (wl && !match((char*)what, w, version, id, catalog))
3109da2e3ebdSchin 								wl = 0;
3110da2e3ebdSchin 							if ((!wl || *w == ':' || *w == '?') && (what[1] || sl && !memchr(s, what[0], sl) || !sl && what[0] != f))
3111da2e3ebdSchin 							{
3112da2e3ebdSchin 								w = 0;
3113da2e3ebdSchin 								if (!z)
3114da2e3ebdSchin 									z = -1;
3115da2e3ebdSchin 							}
3116da2e3ebdSchin 							else
3117da2e3ebdSchin 								matched = 1;
3118da2e3ebdSchin 						}
3119da2e3ebdSchin 						if (t)
3120da2e3ebdSchin 						{
3121da2e3ebdSchin 							p = t;
3122da2e3ebdSchin 							if (*p == ':' || *p == '?')
3123da2e3ebdSchin 							{
3124da2e3ebdSchin 								d = p;
3125da2e3ebdSchin 								p = skip(p, 0, 0, 0, 1, 0, 0, version);
3126da2e3ebdSchin 							}
3127da2e3ebdSchin 						}
3128da2e3ebdSchin 					}
3129da2e3ebdSchin 				}
3130da2e3ebdSchin 				p = skip(p, 0, 0, 0, 1, 0, 1, version);
3131da2e3ebdSchin 				if (*p == GO)
3132da2e3ebdSchin 					p = skip(p + 1, 0, 0, 0, 0, 1, 1, version);
3133da2e3ebdSchin 			}
3134da2e3ebdSchin 			else if (*p == ']')
3135da2e3ebdSchin 			{
3136da2e3ebdSchin 				if (mutex)
3137da2e3ebdSchin 				{
3138da2e3ebdSchin 					if (style >= STYLE_nroff)
3139da2e3ebdSchin 						sfputr(sp_body, "\n.OP - - anyof", '\n');
3140da2e3ebdSchin 					if (!(mutex & 1))
3141da2e3ebdSchin 					{
3142da2e3ebdSchin 						mutex--;
3143da2e3ebdSchin 						if (style <= STYLE_long)
3144da2e3ebdSchin 						{
3145da2e3ebdSchin 							sfputc(sp_body, ' ');
3146da2e3ebdSchin 							sfputc(sp_body, ']');
3147da2e3ebdSchin 						}
3148da2e3ebdSchin 					}
3149da2e3ebdSchin 					mutex--;
3150da2e3ebdSchin 				}
3151da2e3ebdSchin 				p++;
3152da2e3ebdSchin 				continue;
3153da2e3ebdSchin 			}
3154da2e3ebdSchin 			else if (*p == '?')
3155da2e3ebdSchin 			{
3156da2e3ebdSchin 				if (style < STYLE_match)
3157da2e3ebdSchin 					z = 1;
3158da2e3ebdSchin 				mode |= OPT_hidden;
3159da2e3ebdSchin 				p++;
3160da2e3ebdSchin 				continue;
3161da2e3ebdSchin 			}
3162da2e3ebdSchin 			else if (*p == '\\' && style==STYLE_posix)
3163da2e3ebdSchin 			{
3164da2e3ebdSchin 				if (*++p)
3165da2e3ebdSchin 					p++;
3166da2e3ebdSchin 				continue;
3167da2e3ebdSchin 			}
3168da2e3ebdSchin 			else
3169da2e3ebdSchin 			{
3170da2e3ebdSchin 				f = *p++;
3171da2e3ebdSchin 				s = 0;
3172da2e3ebdSchin 				if (style == STYLE_match && !z)
3173da2e3ebdSchin 					z = -1;
3174da2e3ebdSchin 			}
3175da2e3ebdSchin 			if (!z)
3176da2e3ebdSchin 			{
3177da2e3ebdSchin 				if (style == STYLE_long || prefix < 2 || (q->flags & OPT_long))
3178da2e3ebdSchin 					f = 0;
3179da2e3ebdSchin 				else if (style <= STYLE_short)
3180da2e3ebdSchin 					w = 0;
3181da2e3ebdSchin 				if (!f && !w)
3182da2e3ebdSchin 					z = -1;
3183da2e3ebdSchin 			}
31847c2fbfb3SApril Chin 			ov = 0;
31857c2fbfb3SApril Chin 			u = v = y = 0;
3186da2e3ebdSchin 			if (*p == ':' && (a |= OPT_string) || *p == '#' && (a |= OPT_number))
3187da2e3ebdSchin 			{
3188da2e3ebdSchin 				message((-21, "opthelp: arg %s", show(p)));
3189da2e3ebdSchin 				if (*++p == '?' || *p == *(p - 1))
3190da2e3ebdSchin 				{
3191da2e3ebdSchin 					p++;
3192da2e3ebdSchin 					a |= OPT_optional;
3193da2e3ebdSchin 				}
3194da2e3ebdSchin 				if (*(p = next(p, version)) == '[')
3195da2e3ebdSchin 				{
3196da2e3ebdSchin 					if (!z)
3197da2e3ebdSchin 					{
3198da2e3ebdSchin 						p = skip(y = p + 1, ':', '?', 0, 1, 0, 0, version);
3199da2e3ebdSchin 						while (*p == ':')
3200da2e3ebdSchin 						{
3201da2e3ebdSchin 							p = skip(t = p + 1, ':', '?', 0, 1, 0, 0, version);
3202da2e3ebdSchin 							m = p - t;
3203da2e3ebdSchin 							if (*t == '!')
3204da2e3ebdSchin 							{
3205da2e3ebdSchin 								ov = t + 1;
3206da2e3ebdSchin 								ol = m - 1;
3207da2e3ebdSchin 							}
3208da2e3ebdSchin 							else if (*t == '=')
3209da2e3ebdSchin 							{
3210da2e3ebdSchin 								v = t + 1;
3211da2e3ebdSchin 								vl = m - 1;
3212da2e3ebdSchin 							}
3213da2e3ebdSchin 							else
3214da2e3ebdSchin 								for (j = 0; j < elementsof(attrs); j++)
3215da2e3ebdSchin 									if (strneq(t, attrs[j].name, m))
3216da2e3ebdSchin 									{
3217da2e3ebdSchin 										a |= attrs[j].flag;
3218da2e3ebdSchin 										break;
3219da2e3ebdSchin 									}
3220da2e3ebdSchin 						}
3221da2e3ebdSchin 						if (*p == '?')
3222da2e3ebdSchin 							u = p;
3223da2e3ebdSchin 						p = skip(p, 0, 0, 0, 1, 0, 1, version);
3224da2e3ebdSchin 					}
3225da2e3ebdSchin 					else
3226da2e3ebdSchin 						p = skip(p + 1, 0, 0, 0, 1, 0, 1, version);
3227da2e3ebdSchin 				}
3228da2e3ebdSchin 				else
3229da2e3ebdSchin 					y = (a & OPT_number) ? T(NiL, ID, "#") : T(NiL, ID, "arg");
3230da2e3ebdSchin 			}
3231da2e3ebdSchin 			else
3232da2e3ebdSchin 				a |= OPT_flag;
3233da2e3ebdSchin 			if (!z)
3234da2e3ebdSchin 			{
3235da2e3ebdSchin 				if (style <= STYLE_short && !y && !mutex || style == STYLE_posix)
3236da2e3ebdSchin 				{
3237da2e3ebdSchin 					if (style != STYLE_posix && !sfstrtell(sp))
3238da2e3ebdSchin 					{
3239da2e3ebdSchin 						sfputc(sp, '[');
3240da2e3ebdSchin 						if (sp == sp_plus)
3241da2e3ebdSchin 							sfputc(sp, '+');
3242da2e3ebdSchin 						sfputc(sp, '-');
3243da2e3ebdSchin 					}
3244da2e3ebdSchin 					if (!sl)
3245da2e3ebdSchin 						sfputc(sp, f);
3246da2e3ebdSchin 					else
3247da2e3ebdSchin 						for (c = 0; c < sl; c++)
3248da2e3ebdSchin 							if (s[c] != '|')
3249da2e3ebdSchin 								sfputc(sp, s[c]);
3250da2e3ebdSchin 					if (style == STYLE_posix && y)
3251da2e3ebdSchin 						sfputc(sp, ':');
3252da2e3ebdSchin 				}
3253da2e3ebdSchin 				else
3254da2e3ebdSchin 				{
3255da2e3ebdSchin 					if (style >= STYLE_match)
3256da2e3ebdSchin 					{
3257da2e3ebdSchin 						sfputc(sp_body, '\n');
3258da2e3ebdSchin 						if (!head)
3259da2e3ebdSchin 						{
3260da2e3ebdSchin 							head = 1;
3261*b30d1939SAndy Fiddaman 							item(sp_body, (flags & OPT_functions) ? C("FUNCTIONS") : C("OPTIONS"), 0, 0, style, sp_info, version, id, ID, &bflags);
3262da2e3ebdSchin 						}
3263da2e3ebdSchin 						if (style >= STYLE_nroff)
3264da2e3ebdSchin 						{
3265da2e3ebdSchin 							if (mutex & 1)
3266da2e3ebdSchin 							{
3267da2e3ebdSchin 								mutex++;
3268da2e3ebdSchin 								sfputr(sp_body, "\n.OP - - oneof", '\n');
3269da2e3ebdSchin 							}
3270da2e3ebdSchin 						}
3271da2e3ebdSchin 						else
3272da2e3ebdSchin 							sfputc(sp_body, '\t');
3273da2e3ebdSchin 					}
3274da2e3ebdSchin 					else
3275da2e3ebdSchin 					{
3276da2e3ebdSchin 						if (sp_body)
3277da2e3ebdSchin 							sfputc(sp_body, ' ');
3278da2e3ebdSchin 						else if (!(sp_body = sfstropen()))
3279da2e3ebdSchin 							goto nospace;
3280da2e3ebdSchin 						if (mutex)
3281da2e3ebdSchin 						{
3282da2e3ebdSchin 							if (mutex & 1)
3283da2e3ebdSchin 							{
3284da2e3ebdSchin 								mutex++;
3285da2e3ebdSchin 								sfputc(sp_body, '[');
3286da2e3ebdSchin 							}
3287da2e3ebdSchin 							else
3288da2e3ebdSchin 								sfputc(sp_body, '|');
3289da2e3ebdSchin 							sfputc(sp_body, ' ');
3290da2e3ebdSchin 						}
3291da2e3ebdSchin 						else
3292da2e3ebdSchin 							sfputc(sp_body, '[');
3293da2e3ebdSchin 					}
3294da2e3ebdSchin 					if (style >= STYLE_nroff)
3295da2e3ebdSchin 					{
3296da2e3ebdSchin 						if (flags & OPT_functions)
3297da2e3ebdSchin 						{
3298da2e3ebdSchin 							sfputr(sp_body, ".FN", ' ');
3299da2e3ebdSchin 							if (re > rb)
3300da2e3ebdSchin 								sfwrite(sp_body, rb, re - rb);
3301da2e3ebdSchin 							else
3302da2e3ebdSchin 								sfputr(sp, "void", -1);
3303da2e3ebdSchin 							if (w)
33043e14f97fSRoger A. Faulkner 								label(sp_body, ' ', w, 0, -1, 0, style, FONT_BOLD, sp_info, version, id, catalog);
3305da2e3ebdSchin 						}
3306da2e3ebdSchin 						else
3307da2e3ebdSchin 						{
3308da2e3ebdSchin 							sfputr(sp_body, ".OP", ' ');
3309da2e3ebdSchin 							if (sl)
3310da2e3ebdSchin 								sfwrite(sp_body, s, sl);
3311da2e3ebdSchin 							else
3312da2e3ebdSchin 								sfputc(sp_body, f ? f : '-');
3313da2e3ebdSchin 							sfputc(sp_body, ' ');
3314da2e3ebdSchin 							if (w)
3315da2e3ebdSchin 							{
33163e14f97fSRoger A. Faulkner 								if (label(sp_body, 0, w, 0, -1, 0, style, 0, sp_info, version, id, catalog))
3317da2e3ebdSchin 								{
3318da2e3ebdSchin 									sfputc(sp_body, '|');
33193e14f97fSRoger A. Faulkner 									label(sp_body, 0, w, 0, -1, 0, style, 0, sp_info, version, id, native);
3320da2e3ebdSchin 								}
3321da2e3ebdSchin 							}
3322da2e3ebdSchin 							else
3323da2e3ebdSchin 								sfputc(sp_body, '-');
3324da2e3ebdSchin 							sfputc(sp_body, ' ');
3325da2e3ebdSchin 							m = a & OPT_TYPE;
3326da2e3ebdSchin 							for (j = 0; j < elementsof(attrs); j++)
3327da2e3ebdSchin 								if (m & attrs[j].flag)
3328da2e3ebdSchin 								{
3329da2e3ebdSchin 									sfputr(sp_body, attrs[j].name, -1);
3330da2e3ebdSchin 									break;
3331da2e3ebdSchin 								}
3332da2e3ebdSchin 							if (m = (a & ~m) | mode)
3333da2e3ebdSchin 								for (j = 0; j < elementsof(attrs); j++)
3334da2e3ebdSchin 									if (m & attrs[j].flag)
3335da2e3ebdSchin 									{
3336da2e3ebdSchin 										sfputc(sp_body, ':');
3337da2e3ebdSchin 										sfputr(sp_body, attrs[j].name, -1);
3338da2e3ebdSchin 									}
3339da2e3ebdSchin 							sfputc(sp_body, ' ');
3340da2e3ebdSchin 							if (y)
33413e14f97fSRoger A. Faulkner 								label(sp_body, 0, y, 0, -1, 0, style, 0, sp_info, version, id, catalog);
3342da2e3ebdSchin 							else
3343da2e3ebdSchin 								sfputc(sp_body, '-');
3344da2e3ebdSchin 							if (v)
3345da2e3ebdSchin 								sfprintf(sp_body, " %-.*s", vl, v);
3346da2e3ebdSchin 						}
3347da2e3ebdSchin 					}
3348da2e3ebdSchin 					else
3349da2e3ebdSchin 					{
3350da2e3ebdSchin 						if (f)
3351da2e3ebdSchin 						{
3352da2e3ebdSchin 							if (sp_body == sp_plus)
3353da2e3ebdSchin 								sfputc(sp_body, '+');
3354da2e3ebdSchin 							sfputc(sp_body, '-');
3355da2e3ebdSchin 							sfputr(sp_body, font(FONT_BOLD, style, 1), -1);
3356da2e3ebdSchin 							if (!sl)
3357da2e3ebdSchin 							{
3358da2e3ebdSchin 								sfputc(sp_body, f);
3359da2e3ebdSchin 								if (f == '-' && y)
3360da2e3ebdSchin 								{
3361da2e3ebdSchin 									y = 0;
3362da2e3ebdSchin 									sfputr(sp_body, C("long-option[=value]"), -1);
3363da2e3ebdSchin 								}
3364da2e3ebdSchin 							}
3365da2e3ebdSchin 							else
3366da2e3ebdSchin 								sfwrite(sp_body, s, sl);
3367da2e3ebdSchin 							sfputr(sp_body, font(FONT_BOLD, style, 0), -1);
3368da2e3ebdSchin 							if (w)
3369da2e3ebdSchin 							{
3370da2e3ebdSchin 								sfputc(sp_body, ',');
3371da2e3ebdSchin 								sfputc(sp_body, ' ');
3372da2e3ebdSchin 							}
3373da2e3ebdSchin 						}
3374da2e3ebdSchin 						else if ((flags & OPT_functions) && re > rb)
3375da2e3ebdSchin 						{
3376da2e3ebdSchin 							sfwrite(sp_body, rb, re - rb);
3377da2e3ebdSchin 							sfputc(sp_body, ' ');
3378da2e3ebdSchin 						}
3379da2e3ebdSchin 						if (w)
3380da2e3ebdSchin 						{
3381da2e3ebdSchin 							if (prefix > 0)
3382da2e3ebdSchin 							{
3383da2e3ebdSchin 								sfputc(sp_body, '-');
3384da2e3ebdSchin 								if (prefix > 1)
3385da2e3ebdSchin 									sfputc(sp_body, '-');
3386da2e3ebdSchin 							}
33873e14f97fSRoger A. Faulkner 							if (label(sp_body, 0, w, 0, -1, 0, style, FONT_BOLD, sp_info, version, id, catalog))
3388da2e3ebdSchin 							{
3389da2e3ebdSchin 								sfputc(sp_body, '|');
33903e14f97fSRoger A. Faulkner 								label(sp_body, 0, w, 0, -1, 0, style, FONT_BOLD, sp_info, version, id, native);
3391da2e3ebdSchin 							}
3392da2e3ebdSchin 						}
3393da2e3ebdSchin 						if (y)
3394da2e3ebdSchin 						{
3395da2e3ebdSchin 							if (a & OPT_optional)
3396da2e3ebdSchin 								sfputc(sp_body, '[');
3397da2e3ebdSchin 							else if (!w)
3398da2e3ebdSchin 								sfputc(sp_body, ' ');
3399da2e3ebdSchin 							if (w)
3400da2e3ebdSchin 								sfputc(sp_body, prefix == 1 ? ' ' : '=');
34013e14f97fSRoger A. Faulkner 							label(sp_body, 0, y, 0, -1, 0, style, FONT_ITALIC, sp_info, version, id, catalog);
3402da2e3ebdSchin 							if (a & OPT_optional)
3403da2e3ebdSchin 								sfputc(sp_body, ']');
3404da2e3ebdSchin 						}
3405da2e3ebdSchin 					}
3406da2e3ebdSchin 					if (style >= STYLE_match)
3407da2e3ebdSchin 					{
3408da2e3ebdSchin 						if (d)
3409*b30d1939SAndy Fiddaman 						{
3410*b30d1939SAndy Fiddaman 							textout(sp_body, d, cb, cl, style, 0, 3, sp_info, version, id, catalog, &bflags);
3411*b30d1939SAndy Fiddaman 							cb = 0;
3412*b30d1939SAndy Fiddaman 						}
3413da2e3ebdSchin 						if (u)
3414*b30d1939SAndy Fiddaman 							textout(sp_body, u, cb, cl, style, 0, 3, sp_info, version, id, catalog, &bflags);
3415da2e3ebdSchin 						if ((a & OPT_invert) && w && (d || u))
3416da2e3ebdSchin 						{
3417da2e3ebdSchin 							u = skip(w, ':', '?', 0, 1, 0, 0, version);
3418da2e3ebdSchin 							if (f)
3419da2e3ebdSchin 								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);
3420da2e3ebdSchin 							else
3421da2e3ebdSchin 								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"));
3422da2e3ebdSchin 							if (!(t = sfstruse(sp_info)))
3423da2e3ebdSchin 								goto nospace;
3424*b30d1939SAndy Fiddaman 							textout(sp_body, t, 0, 0, style, 0, 0, sp_info, version, NiL, NiL, &bflags);
3425da2e3ebdSchin 						}
3426da2e3ebdSchin 						if (*p == GO)
3427da2e3ebdSchin 						{
3428*b30d1939SAndy Fiddaman 							p = u ? skip(p + 1, 0, 0, 0, 0, 1, 1, version) : textout(sp_body, p, 0, 0, style, 4, 0, sp_info, version, id, catalog, &bflags);
3429da2e3ebdSchin 							y = "+?";
3430da2e3ebdSchin 						}
3431da2e3ebdSchin 						else
3432da2e3ebdSchin 							y = " ";
3433da2e3ebdSchin 						if (a & OPT_optional)
3434da2e3ebdSchin 						{
3435da2e3ebdSchin 							if (ov)
3436da2e3ebdSchin 							{
3437da2e3ebdSchin 								sfprintf(sp_info, "%s%s \b", y, T(NiL, ID, "If the option value is omitted then"));
3438da2e3ebdSchin 								t = ov + ol;
3439da2e3ebdSchin 								while (ov < t)
3440da2e3ebdSchin 								{
3441da2e3ebdSchin 									if (((c = *ov++) == ':' || c == '?') && *ov == c)
3442da2e3ebdSchin 										ov++;
3443da2e3ebdSchin 									sfputc(sp_info, c);
3444da2e3ebdSchin 								}
3445da2e3ebdSchin 								sfprintf(sp_info, "\b %s.", T(NiL, ID, "is assumed"));
3446da2e3ebdSchin 							}
3447da2e3ebdSchin 							else
3448da2e3ebdSchin 								sfprintf(sp_info, "%s%s", y, T(NiL, ID, "The option value may be omitted."));
3449da2e3ebdSchin 							if (!(t = sfstruse(sp_info)))
3450da2e3ebdSchin 								goto nospace;
3451*b30d1939SAndy Fiddaman 							textout(sp_body, t, 0, 0, style, 4, 0, sp_info, version, NiL, NiL, &bflags);
3452da2e3ebdSchin 							y = " ";
3453da2e3ebdSchin 						}
3454da2e3ebdSchin 						if (v)
3455da2e3ebdSchin 						{
3456da2e3ebdSchin 							sfprintf(sp_info, "%s%s \b", y, T(NiL, ID, "The default value is"));
3457da2e3ebdSchin 							t = v + vl;
3458da2e3ebdSchin 							while (v < t)
3459da2e3ebdSchin 							{
3460da2e3ebdSchin 								if (((c = *v++) == ':' || c == '?') && *v == c)
3461da2e3ebdSchin 									v++;
3462da2e3ebdSchin 								sfputc(sp_info, c);
3463da2e3ebdSchin 							}
3464da2e3ebdSchin 							sfputc(sp_info, '\b');
3465da2e3ebdSchin 							sfputc(sp_info, '.');
3466da2e3ebdSchin 							if (!(t = sfstruse(sp_info)))
3467da2e3ebdSchin 								goto nospace;
3468*b30d1939SAndy Fiddaman 							textout(sp_body, t, 0, 0, style, 4, 0, sp_info, version, NiL, NiL, &bflags);
3469da2e3ebdSchin 						}
3470da2e3ebdSchin 					}
3471da2e3ebdSchin 					else if (!mutex)
3472da2e3ebdSchin 						sfputc(sp_body, ']');
3473da2e3ebdSchin 				}
3474da2e3ebdSchin 				if (*p == GO)
3475da2e3ebdSchin 				{
3476da2e3ebdSchin 					if (style >= STYLE_match)
3477*b30d1939SAndy Fiddaman 						p = textout(sp_body, p, 0, 0, style, 4, 0, sp_info, version, id, catalog, &bflags);
3478da2e3ebdSchin 					else
3479da2e3ebdSchin 						p = skip(p + 1, 0, 0, 0, 0, 1, 1, version);
3480da2e3ebdSchin 				}
3481da2e3ebdSchin 			}
3482da2e3ebdSchin 			else if (*p == GO)
3483da2e3ebdSchin 				p = skip(p + 1, 0, 0, 0, 0, 1, 1, version);
3484da2e3ebdSchin 		}
3485da2e3ebdSchin 		psp = pop(psp);
3486da2e3ebdSchin 		if (sp_misc)
3487da2e3ebdSchin 		{
3488da2e3ebdSchin 			if (!(p = sfstruse(sp_misc)))
3489da2e3ebdSchin 				goto nospace;
3490da2e3ebdSchin 			for (t = p; *t == '\t' || *t == '\n'; t++);
3491da2e3ebdSchin 			if (*t)
3492da2e3ebdSchin 			{
3493*b30d1939SAndy Fiddaman 				item(sp_body, C("IMPLEMENTATION"), 0, 0, style, sp_info, version, id, ID, &bflags);
3494da2e3ebdSchin 				sfputr(sp_body, p, -1);
3495da2e3ebdSchin 			}
3496da2e3ebdSchin 		}
3497da2e3ebdSchin 	}
3498*b30d1939SAndy Fiddaman 	if (oopts != o->oopts && oopts == top.oopts)
3499*b30d1939SAndy Fiddaman 		state.pass[0] = top;
3500da2e3ebdSchin 	version = o->version;
35013e14f97fSRoger A. Faulkner 	id = o->id;
3502da2e3ebdSchin 	catalog = o->catalog;
3503da2e3ebdSchin 	if (style >= STYLE_keys)
3504da2e3ebdSchin 	{
3505da2e3ebdSchin 		if (sp_info)
3506da2e3ebdSchin 			sfclose(sp_info);
3507da2e3ebdSchin 		if (style == STYLE_keys && sfstrtell(mp) > 1)
3508da2e3ebdSchin 			sfstrseek(mp, -1, SEEK_CUR);
3509da2e3ebdSchin 		if (!(p = sfstruse(mp)))
3510da2e3ebdSchin 			goto nospace;
3511da2e3ebdSchin 		return opt_info.msg = p;
3512da2e3ebdSchin 	}
3513da2e3ebdSchin 	sp = sp_text;
3514da2e3ebdSchin 	if (sfstrtell(sp) && style != STYLE_posix)
3515da2e3ebdSchin 		sfputc(sp, ']');
3516da2e3ebdSchin 	if (style == STYLE_nroff)
3517da2e3ebdSchin 	{
3518*b30d1939SAndy Fiddaman 		char	rd[64];
35193e14f97fSRoger A. Faulkner 		char	ud[64];
35203e14f97fSRoger A. Faulkner 
35213e14f97fSRoger A. Faulkner 		s = o->id;
35223e14f97fSRoger A. Faulkner 		t = ud;
35233e14f97fSRoger A. Faulkner 		while (t < &ud[sizeof(ud)-2] && (c = *s++))
35243e14f97fSRoger A. Faulkner 		{
35253e14f97fSRoger A. Faulkner 			if (islower(c))
35263e14f97fSRoger A. Faulkner 				c = toupper(c);
35273e14f97fSRoger A. Faulkner 			*t++ = c;
35283e14f97fSRoger A. Faulkner 		}
35293e14f97fSRoger A. Faulkner 		*t = 0;
3530*b30d1939SAndy Fiddaman 		t = rd;
3531*b30d1939SAndy Fiddaman 		if (s = o->release)
3532*b30d1939SAndy Fiddaman 		{
3533*b30d1939SAndy Fiddaman 			*t++ = ' ';
3534*b30d1939SAndy Fiddaman 			while (t < &rd[sizeof(rd)-2] && (c = *s++) && c != ']')
3535*b30d1939SAndy Fiddaman 				*t++ = c;
3536*b30d1939SAndy Fiddaman 		}
3537*b30d1939SAndy Fiddaman 		*t = 0;
3538da2e3ebdSchin 		sfprintf(sp, "\
3539da2e3ebdSchin .\\\" format with nroff|troff|groff -man\n\
3540*b30d1939SAndy Fiddaman .TH %s %s%s\n\
3541da2e3ebdSchin .fp 5 CW\n\
35427c2fbfb3SApril Chin .nr mH 5\n\
35437c2fbfb3SApril Chin .de H0\n\
35447c2fbfb3SApril Chin .nr mH 0\n\
35457c2fbfb3SApril Chin .in 5n\n\
35467c2fbfb3SApril Chin \\fB\\\\$1\\fP\n\
35477c2fbfb3SApril Chin .in 7n\n\
3548da2e3ebdSchin ..\n\
3549da2e3ebdSchin .de H1\n\
35507c2fbfb3SApril Chin .nr mH 1\n\
35517c2fbfb3SApril Chin .in 7n\n\
3552da2e3ebdSchin \\fB\\\\$1\\fP\n\
35537c2fbfb3SApril Chin .in 9n\n\
3554da2e3ebdSchin ..\n\
3555da2e3ebdSchin .de H2\n\
35567c2fbfb3SApril Chin .nr mH 2\n\
35577c2fbfb3SApril Chin .in 11n\n\
3558da2e3ebdSchin \\fB\\\\$1\\fP\n\
35597c2fbfb3SApril Chin .in 13n\n\
3560da2e3ebdSchin ..\n\
3561da2e3ebdSchin .de H3\n\
35627c2fbfb3SApril Chin .nr mH 3\n\
35637c2fbfb3SApril Chin .in 15n\n\
3564da2e3ebdSchin \\fB\\\\$1\\fP\n\
35657c2fbfb3SApril Chin .in 17n\n\
3566da2e3ebdSchin ..\n\
3567da2e3ebdSchin .de H4\n\
35687c2fbfb3SApril Chin .nr mH 4\n\
35697c2fbfb3SApril Chin .in 19n\n\
3570da2e3ebdSchin \\fB\\\\$1\\fP\n\
35717c2fbfb3SApril Chin .in 21n\n\
3572da2e3ebdSchin ..\n\
3573da2e3ebdSchin .de OP\n\
35747c2fbfb3SApril Chin .nr mH 0\n\
3575da2e3ebdSchin .ie !'\\\\$1'-' \\{\n\
3576da2e3ebdSchin .ds mO \\\\fB\\\\-\\\\$1\\\\fP\n\
3577da2e3ebdSchin .ds mS ,\\\\0\n\
3578da2e3ebdSchin .\\}\n\
3579da2e3ebdSchin .el \\{\n\
3580da2e3ebdSchin .ds mO \\\\&\n\
3581da2e3ebdSchin .ds mS \\\\&\n\
3582da2e3ebdSchin .\\}\n\
3583da2e3ebdSchin .ie '\\\\$2'-' \\{\n\
3584da2e3ebdSchin .if !'\\\\$4'-' .as mO \\\\0\\\\fI\\\\$4\\\\fP\n\
3585da2e3ebdSchin .\\}\n\
3586da2e3ebdSchin .el \\{\n\
3587da2e3ebdSchin .as mO \\\\*(mS\\\\fB%s\\\\$2\\\\fP\n\
3588da2e3ebdSchin .if !'\\\\$4'-' .as mO =\\\\fI\\\\$4\\\\fP\n\
3589da2e3ebdSchin .\\}\n\
35907c2fbfb3SApril Chin .in 5n\n\
3591da2e3ebdSchin \\\\*(mO\n\
35927c2fbfb3SApril Chin .in 9n\n\
35937c2fbfb3SApril Chin ..\n\
35947c2fbfb3SApril Chin .de SP\n\
35957c2fbfb3SApril Chin .if \\\\n(mH==2 .in 9n\n\
35967c2fbfb3SApril Chin .if \\\\n(mH==3 .in 13n\n\
35977c2fbfb3SApril Chin .if \\\\n(mH==4 .in 17n\n\
3598da2e3ebdSchin ..\n\
3599da2e3ebdSchin .de FN\n\
36007c2fbfb3SApril Chin .nr mH 0\n\
36017c2fbfb3SApril Chin .in 5n\n\
3602da2e3ebdSchin \\\\$1 \\\\$2\n\
36037c2fbfb3SApril Chin .in 9n\n\
36047c2fbfb3SApril Chin ..\n\
36057c2fbfb3SApril Chin .de DS\n\
36067c2fbfb3SApril Chin .in +3n\n\
36077c2fbfb3SApril Chin .ft 5\n\
36087c2fbfb3SApril Chin .nf\n\
36097c2fbfb3SApril Chin ..\n\
36107c2fbfb3SApril Chin .de DE\n\
36117c2fbfb3SApril Chin .fi\n\
36127c2fbfb3SApril Chin .ft R\n\
36137c2fbfb3SApril Chin .in -3n\n\
3614da2e3ebdSchin ..\n\
3615da2e3ebdSchin "
36163e14f97fSRoger A. Faulkner , ud
3617da2e3ebdSchin , section
3618*b30d1939SAndy Fiddaman , rd
3619*b30d1939SAndy Fiddaman , o->prefix == 2 ? "\\\\-\\\\-" : o->prefix == 1 ? "\\\\-" : ""
3620da2e3ebdSchin );
3621da2e3ebdSchin 	}
3622da2e3ebdSchin 	if (style == STYLE_match)
3623da2e3ebdSchin 	{
3624da2e3ebdSchin 		if (!matched)
3625da2e3ebdSchin 		{
3626da2e3ebdSchin 			if (hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), (char*)what))
3627da2e3ebdSchin 			{
3628da2e3ebdSchin 				if (!sp_help && !(sp_help = sfstropen()))
3629da2e3ebdSchin 					goto nospace;
3630da2e3ebdSchin 				sfprintf(sp_help, "[-][:%s?%s]", hp->match, hp->text);
3631da2e3ebdSchin 				if (!(opts = sfstruse(sp_help)))
3632da2e3ebdSchin 					goto nospace;
3633da2e3ebdSchin 				goto again;
3634da2e3ebdSchin 			}
3635da2e3ebdSchin 			s = (char*)unknown;
3636da2e3ebdSchin 			goto nope;
3637da2e3ebdSchin 		}
3638da2e3ebdSchin 		else if (matched < 0)
3639da2e3ebdSchin 			x = 0;
3640da2e3ebdSchin 	}
3641da2e3ebdSchin 	if (sp_plus)
3642da2e3ebdSchin 	{
3643da2e3ebdSchin 		if (sfstrtell(sp_plus))
3644da2e3ebdSchin 		{
3645da2e3ebdSchin 			if (sfstrtell(sp))
3646da2e3ebdSchin 				sfputc(sp, ' ');
3647da2e3ebdSchin 			if (!(t = sfstruse(sp_plus)))
3648da2e3ebdSchin 				goto nospace;
3649da2e3ebdSchin 			sfputr(sp, t, ']');
3650da2e3ebdSchin 		}
3651da2e3ebdSchin 		sfclose(sp_plus);
3652da2e3ebdSchin 	}
3653da2e3ebdSchin 	if (style >= STYLE_man)
3654da2e3ebdSchin 	{
3655da2e3ebdSchin 		if (sp_head)
3656da2e3ebdSchin 		{
3657da2e3ebdSchin 			if (!(t = sfstruse(sp_head)))
3658da2e3ebdSchin 				goto nospace;
3659da2e3ebdSchin 			for (; *t == '\n'; t++);
3660da2e3ebdSchin 			sfputr(sp, t, '\n');
3661da2e3ebdSchin 			sfclose(sp_head);
3662da2e3ebdSchin 			sp_head = 0;
3663da2e3ebdSchin 		}
3664*b30d1939SAndy Fiddaman 		if (x)
3665*b30d1939SAndy Fiddaman 			item(sp, C("SYNOPSIS"), 0, 0, style, sp_info, version, id, ID, &hflags);
3666da2e3ebdSchin 	}
3667da2e3ebdSchin 	if (x)
3668da2e3ebdSchin 	{
3669da2e3ebdSchin 		for (t = x + xl; t > x && (*(t - 1) == '\n' || *(t - 1) == '\r'); t--);
3670da2e3ebdSchin 		xl = t - x;
3671da2e3ebdSchin 		if (style >= STYLE_match)
3672da2e3ebdSchin 		{
3673*b30d1939SAndy Fiddaman 			u = id;
3674*b30d1939SAndy Fiddaman 			if (o->flags & OPT_functions)
3675*b30d1939SAndy Fiddaman 				t = 0;
3676*b30d1939SAndy Fiddaman 			else if (t = strchr(u, ':'))
3677*b30d1939SAndy Fiddaman 			{
3678*b30d1939SAndy Fiddaman 				if ((o->flags & OPT_module) && *(t + 1) == ':' && *(t + 2))
3679*b30d1939SAndy Fiddaman 				{
3680*b30d1939SAndy Fiddaman 					u = t + 2;
3681*b30d1939SAndy Fiddaman 					t = 0;
3682*b30d1939SAndy Fiddaman 				}
3683*b30d1939SAndy Fiddaman 				else
3684*b30d1939SAndy Fiddaman 					*t = 0;
3685*b30d1939SAndy Fiddaman 			}
3686*b30d1939SAndy Fiddaman 			args(sp, x, xl, o->flags, style, sp_info, version, u, catalog);
3687*b30d1939SAndy Fiddaman 			if (t)
3688*b30d1939SAndy Fiddaman 				*t = ':';
3689da2e3ebdSchin 			x = 0;
3690da2e3ebdSchin 		}
3691da2e3ebdSchin 	}
3692da2e3ebdSchin 	if (sp_body)
3693da2e3ebdSchin 	{
3694da2e3ebdSchin 		if (sfstrtell(sp_body))
3695da2e3ebdSchin 		{
3696da2e3ebdSchin 			if (style < STYLE_match && sfstrtell(sp))
3697da2e3ebdSchin 				sfputc(sp, ' ');
3698da2e3ebdSchin 			if (!(t = sfstruse(sp_body)))
3699da2e3ebdSchin 				goto nospace;
3700*b30d1939SAndy Fiddaman 			if (style == STYLE_html && !(dflags & HELP_head) && (bflags & HELP_head))
3701*b30d1939SAndy Fiddaman 				sfputr(sp, "\n</DIV>", '\n');
3702da2e3ebdSchin 			sfputr(sp, t, -1);
3703da2e3ebdSchin 		}
3704da2e3ebdSchin 		sfclose(sp_body);
3705da2e3ebdSchin 		sp_body = 0;
3706da2e3ebdSchin 	}
3707da2e3ebdSchin 	if (x && style != STYLE_posix)
37083e14f97fSRoger A. Faulkner 		args(sp, x, xl, flags, style, sp_info, version, id, catalog);
3709da2e3ebdSchin 	if (sp_info)
3710da2e3ebdSchin 	{
3711da2e3ebdSchin 		sfclose(sp_info);
3712da2e3ebdSchin 		sp_info = 0;
3713da2e3ebdSchin 	}
3714da2e3ebdSchin 	if (sp_misc)
3715da2e3ebdSchin 	{
3716da2e3ebdSchin 		sfclose(sp_misc);
3717da2e3ebdSchin 		sp_misc = 0;
3718da2e3ebdSchin 	}
3719da2e3ebdSchin 	if (!(p = sfstruse(sp)))
3720da2e3ebdSchin 		goto nospace;
3721*b30d1939SAndy Fiddaman 	astwinsize(1, NiL, &state.width);
3722*b30d1939SAndy Fiddaman 	if (state.width < 20)
3723*b30d1939SAndy Fiddaman 		state.width = OPT_WIDTH;
37243e14f97fSRoger A. Faulkner 	m = strlen((style <= STYLE_long && error_info.id && !strchr(error_info.id, '/')) ? error_info.id : id) + 1;
3725*b30d1939SAndy Fiddaman 	margin = style == STYLE_api ? (8 * 1024) : (state.width - 1);
3726*b30d1939SAndy Fiddaman 	if (!(state.flags & OPT_preformat))
3727da2e3ebdSchin 	{
3728da2e3ebdSchin 		if (style >= STYLE_man || matched < 0)
3729da2e3ebdSchin 		{
3730da2e3ebdSchin 			sfputc(mp, '\f');
3731da2e3ebdSchin 			ts = 0;
3732da2e3ebdSchin 		}
3733da2e3ebdSchin 		else
3734da2e3ebdSchin 			ts = OPT_USAGE + m;
3735da2e3ebdSchin 		if (style == STYLE_html)
3736da2e3ebdSchin 		{
37373e14f97fSRoger A. Faulkner 			char	ud[64];
37383e14f97fSRoger A. Faulkner 
37393e14f97fSRoger A. Faulkner 			s = id;
37403e14f97fSRoger A. Faulkner 			t = ud;
37413e14f97fSRoger A. Faulkner 			while (t < &ud[sizeof(ud)-2] && (c = *s++))
37423e14f97fSRoger A. Faulkner 			{
37433e14f97fSRoger A. Faulkner 				if (islower(c))
37443e14f97fSRoger A. Faulkner 					c = toupper(c);
37453e14f97fSRoger A. Faulkner 				*t++ = c;
37463e14f97fSRoger A. Faulkner 			}
37473e14f97fSRoger A. Faulkner 			*t = 0;
3748*b30d1939SAndy Fiddaman 			sfprintf(mp, "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n<HTML>\n<HEAD>\n<META name=\"generator\" content=\"optget (AT&T Research) 2011-11-11\">\n%s<TITLE>%s man document</TITLE>\n<STYLE type=\"text/css\">\ndiv.SH { padding-left:2em; text-indent:0em; }\ndiv.SY { padding-left:4em; text-indent:-2em; }\ndt { float:left; clear:both; }\ndd { margin-left:3em; }\n</STYLE>\n</HEAD>\n<BODY bgcolor=white>\n", (state.flags & OPT_proprietary) ? "<!--INTERNAL-->\n" : "", id);
3749*b30d1939SAndy Fiddaman 			sfprintf(mp, "<H4><TABLE width=100%%><TR><TH align=left>%s&nbsp;(&nbsp;%s&nbsp;)&nbsp;<TH align=center><A href=\".\" title=\"Index\">%s</A><TH align=right>%s&nbsp;(&nbsp;%s&nbsp;)</TR></TABLE></H4>\n<HR>\n", ud, section, T(NiL, ID, secname(section)), ud, section);
3750da2e3ebdSchin 			co = 2;
3751*b30d1939SAndy Fiddaman 			pt = ptstk;
3752*b30d1939SAndy Fiddaman 			pt->level = 0;
3753*b30d1939SAndy Fiddaman 			pt->id = TAG_DIV;
3754da2e3ebdSchin 		}
3755da2e3ebdSchin 		else
3756da2e3ebdSchin 			co = 0;
37577c2fbfb3SApril Chin 		if ((rm = margin - ts) < OPT_MARGIN)
3758da2e3ebdSchin 			rm = OPT_MARGIN;
3759da2e3ebdSchin 		ip = indent;
3760da2e3ebdSchin 		ip->stop = (ip+1)->stop = style >= STYLE_html ? 0 : 2;
3761da2e3ebdSchin 		tp = 0;
3762da2e3ebdSchin 		n = 0;
3763da2e3ebdSchin 		head = 1;
3764da2e3ebdSchin 		while (*p == '\n')
3765da2e3ebdSchin 			p++;
3766da2e3ebdSchin 		while (c = *p++)
3767da2e3ebdSchin 		{
3768da2e3ebdSchin 			if (c == '\n')
3769da2e3ebdSchin 			{
3770da2e3ebdSchin 				ip = indent;
3771da2e3ebdSchin 				n = 0;
3772da2e3ebdSchin 				tp = 0;
3773da2e3ebdSchin 				sfputc(mp, '\n');
3774da2e3ebdSchin 				co = 0;
37757c2fbfb3SApril Chin 				rm = margin;
3776da2e3ebdSchin 				ts = ip->stop;
3777da2e3ebdSchin 				if (*p == '\n')
3778da2e3ebdSchin 				{
3779da2e3ebdSchin 					while (*++p == '\n');
3780da2e3ebdSchin 					if ((style == STYLE_man || style == STYLE_html) && (!head || *p != ' ' && *p != '\t'))
3781da2e3ebdSchin 					{
3782da2e3ebdSchin 						if (style == STYLE_man)
3783da2e3ebdSchin 							p--;
3784da2e3ebdSchin 						else
3785da2e3ebdSchin 							sfprintf(mp, "<P>\n");
3786da2e3ebdSchin 					}
3787da2e3ebdSchin 				}
3788da2e3ebdSchin 				head = *p != ' ' && *p != '\t';
3789da2e3ebdSchin 				if (style == STYLE_html && (*p != '<' || !strneq(p, "<BR>", 4) && !strneq(p, "<P>", 3)))
3790da2e3ebdSchin 				{
3791da2e3ebdSchin 					y = p;
3792da2e3ebdSchin 					while (*p == '\t')
3793da2e3ebdSchin 						p++;
3794da2e3ebdSchin 					if (*p == '\n')
3795da2e3ebdSchin 						continue;
3796da2e3ebdSchin 					j = p - y;
3797*b30d1939SAndy Fiddaman 					if (j > pt->level)
3798da2e3ebdSchin 					{
3799*b30d1939SAndy Fiddaman 						pt++;
3800*b30d1939SAndy Fiddaman 						pt->level = j;
3801*b30d1939SAndy Fiddaman 						pt->id = TAG_NONE;
3802*b30d1939SAndy Fiddaman 						for (y = p; *y && *y != '\n'; y++)
3803*b30d1939SAndy Fiddaman 							if (*y == '\t')
3804*b30d1939SAndy Fiddaman 							{
3805*b30d1939SAndy Fiddaman 								pt->id = TAG_DL;
3806*b30d1939SAndy Fiddaman 								sfprintf(mp, "<DL>\n");
3807*b30d1939SAndy Fiddaman 								break;
3808*b30d1939SAndy Fiddaman 							}
3809da2e3ebdSchin 					}
3810*b30d1939SAndy Fiddaman 					else
3811*b30d1939SAndy Fiddaman 						while (j < pt->level && pt > ptstk)
3812*b30d1939SAndy Fiddaman 						{
3813*b30d1939SAndy Fiddaman 							sfprintf(mp, "%s", end[pt->id]);
3814*b30d1939SAndy Fiddaman 							pt--;
3815*b30d1939SAndy Fiddaman 						}
3816*b30d1939SAndy Fiddaman 					if (pt->id == TAG_DL)
3817da2e3ebdSchin 					{
3818*b30d1939SAndy Fiddaman 						dt = p;
3819*b30d1939SAndy Fiddaman 						sfprintf(mp, "<DT>");
3820da2e3ebdSchin 					}
3821*b30d1939SAndy Fiddaman 					else
3822*b30d1939SAndy Fiddaman 						dt = 0;
3823da2e3ebdSchin 				}
3824da2e3ebdSchin 			}
3825da2e3ebdSchin 			else if (c == '\t')
3826da2e3ebdSchin 			{
3827da2e3ebdSchin 				if (style == STYLE_html)
3828da2e3ebdSchin 				{
3829da2e3ebdSchin 					while (*p == '\t')
3830da2e3ebdSchin 						p++;
3831da2e3ebdSchin 					if (*p != '\n')
3832*b30d1939SAndy Fiddaman 					{
3833da2e3ebdSchin 						co += sfprintf(mp, "<DD>");
3834*b30d1939SAndy Fiddaman 						if (dt)
3835*b30d1939SAndy Fiddaman 						{
3836*b30d1939SAndy Fiddaman 							c = 0;
3837*b30d1939SAndy Fiddaman 							m = 0;
3838*b30d1939SAndy Fiddaman 							for (;;)
3839*b30d1939SAndy Fiddaman 							{
3840*b30d1939SAndy Fiddaman 								switch (*dt++)
3841*b30d1939SAndy Fiddaman 								{
3842*b30d1939SAndy Fiddaman 								case '\t':
3843*b30d1939SAndy Fiddaman 									break;
3844*b30d1939SAndy Fiddaman 								case '<':
3845*b30d1939SAndy Fiddaman 									c = '>';
3846*b30d1939SAndy Fiddaman 									continue;
3847*b30d1939SAndy Fiddaman 								case '>':
3848*b30d1939SAndy Fiddaman 									if (c == '>')
3849*b30d1939SAndy Fiddaman 										c = 0;
3850*b30d1939SAndy Fiddaman 									else
3851*b30d1939SAndy Fiddaman 										m++;
3852*b30d1939SAndy Fiddaman 									continue;
3853*b30d1939SAndy Fiddaman 								case '&':
3854*b30d1939SAndy Fiddaman 									c = ';';
3855*b30d1939SAndy Fiddaman 									continue;
3856*b30d1939SAndy Fiddaman 								case ';':
3857*b30d1939SAndy Fiddaman 									if (c == ';')
3858*b30d1939SAndy Fiddaman 										c = 0;
3859*b30d1939SAndy Fiddaman 									m++;
3860*b30d1939SAndy Fiddaman 									continue;
3861*b30d1939SAndy Fiddaman 								default:
3862*b30d1939SAndy Fiddaman 									if (!c)
3863*b30d1939SAndy Fiddaman 										m++;
3864*b30d1939SAndy Fiddaman 									continue;
3865*b30d1939SAndy Fiddaman 								}
3866*b30d1939SAndy Fiddaman 								break;
3867*b30d1939SAndy Fiddaman 							}
3868*b30d1939SAndy Fiddaman 							if (m >= 5)
3869*b30d1939SAndy Fiddaman 								co += sfprintf(mp, "<BR>");
3870*b30d1939SAndy Fiddaman 						}
3871*b30d1939SAndy Fiddaman 					}
3872da2e3ebdSchin 				}
3873da2e3ebdSchin 				else
3874da2e3ebdSchin 				{
3875da2e3ebdSchin 					if ((ip+1)->stop)
3876da2e3ebdSchin 					{
3877da2e3ebdSchin 						do
3878da2e3ebdSchin 						{
3879da2e3ebdSchin 							ip++;
3880da2e3ebdSchin 							if (*p != '\t')
3881da2e3ebdSchin 								break;
3882da2e3ebdSchin 							p++;
3883da2e3ebdSchin 						} while ((ip+1)->stop);
3884da2e3ebdSchin 						if (*p == '\n')
3885da2e3ebdSchin 							continue;
3886da2e3ebdSchin 						ts = ip->stop;
3887da2e3ebdSchin 						if (co >= ts)
3888da2e3ebdSchin 						{
3889da2e3ebdSchin 							sfputc(mp, '\n');
3890da2e3ebdSchin 							co = 0;
38917c2fbfb3SApril Chin 							rm = margin;
3892da2e3ebdSchin 							ts = ip->stop;
3893da2e3ebdSchin 						}
3894da2e3ebdSchin 					}
3895da2e3ebdSchin 					while (co < ts)
3896da2e3ebdSchin 					{
3897da2e3ebdSchin 						sfputc(mp, ' ');
3898da2e3ebdSchin 						co++;
3899da2e3ebdSchin 					}
3900da2e3ebdSchin 				}
3901da2e3ebdSchin 			}
3902da2e3ebdSchin 			else
3903da2e3ebdSchin 			{
3904da2e3ebdSchin 				if (c == ' ' && !n)
3905da2e3ebdSchin 				{
3906da2e3ebdSchin 					if (co >= rm)
3907da2e3ebdSchin 						tp = 0;
3908da2e3ebdSchin 					else
3909da2e3ebdSchin 					{
3910da2e3ebdSchin 						tp = sfstrtell(mp);
3911da2e3ebdSchin 						pp = p;
3912da2e3ebdSchin 					}
3913da2e3ebdSchin 					if (style == STYLE_nroff && !co)
3914da2e3ebdSchin 						continue;
3915da2e3ebdSchin 				}
3916da2e3ebdSchin 				else if (style == STYLE_html)
3917da2e3ebdSchin 				{
3918da2e3ebdSchin 					if (c == '<')
3919da2e3ebdSchin 					{
3920da2e3ebdSchin 						if (strneq(p, "NOBR>", 5))
3921da2e3ebdSchin 							n++;
3922da2e3ebdSchin 						else if (n && strneq(p, "/NOBR>", 6) && !--n)
3923da2e3ebdSchin 						{
3924da2e3ebdSchin 							for (y = p += 6; (c = *p) && c != ' ' && c != '\t' && c != '\n' && c != '<'; p++)
3925da2e3ebdSchin 								if (c == '[')
3926da2e3ebdSchin 									sfputr(mp, "&#0091;", -1);
3927da2e3ebdSchin 								else if (c == ']')
3928da2e3ebdSchin 									sfputr(mp, "&#0093;", -1);
3929da2e3ebdSchin 								else
3930da2e3ebdSchin 									sfputc(mp, c);
3931da2e3ebdSchin 							sfwrite(mp, "</NOBR", 6);
3932da2e3ebdSchin 							c = '>';
3933da2e3ebdSchin 							co += p - y + 6;
3934da2e3ebdSchin 						}
3935da2e3ebdSchin 					}
3936da2e3ebdSchin 					else if (c == '>' && !n)
3937da2e3ebdSchin 					{
3938da2e3ebdSchin 						for (y = --p; (c = *p) && c != ' ' && c != '\t' && c != '\n' && c != '<'; p++)
3939da2e3ebdSchin 							if (c == '[')
3940da2e3ebdSchin 								sfputr(mp, "&#0091;", -1);
3941da2e3ebdSchin 							else if (c == ']')
3942da2e3ebdSchin 								sfputr(mp, "&#0093;", -1);
3943da2e3ebdSchin 							else
3944da2e3ebdSchin 								sfputc(mp, c);
3945da2e3ebdSchin 						c = *sfstrseek(mp, -1, SEEK_CUR);
3946da2e3ebdSchin 						if (p > y + 1)
3947da2e3ebdSchin 						{
3948da2e3ebdSchin 							tp = 0;
3949da2e3ebdSchin 							co += p - y - 1;
3950da2e3ebdSchin 						}
3951da2e3ebdSchin 						if (co >= rm)
3952da2e3ebdSchin 							tp = 0;
3953da2e3ebdSchin 						else
3954da2e3ebdSchin 						{
3955da2e3ebdSchin 							tp = sfstrtell(mp);
3956da2e3ebdSchin 							pp = p;
3957da2e3ebdSchin 						}
3958da2e3ebdSchin 					}
3959da2e3ebdSchin 					else if (c == '[')
3960da2e3ebdSchin 					{
3961da2e3ebdSchin 						sfputr(mp, "&#0091", -1);
3962da2e3ebdSchin 						c = ';';
3963da2e3ebdSchin 					}
3964da2e3ebdSchin 					else if (c == ']')
3965da2e3ebdSchin 					{
3966da2e3ebdSchin 						sfputr(mp, "&#0093", -1);
3967da2e3ebdSchin 						c = ';';
3968da2e3ebdSchin 					}
3969da2e3ebdSchin 					else if (c == 'h')
3970da2e3ebdSchin 					{
3971da2e3ebdSchin 						y = p;
3972da2e3ebdSchin 						if (*y++ == 't' && *y++ == 't' && *y++ == 'p' && (*y == ':' || *y++ == 's' && *y == ':') && *y++ == ':' && *y++ == '/' && *y++ == '/')
3973da2e3ebdSchin 						{
3974da2e3ebdSchin 							while (isalnum(*y) || *y == '_' || *y == '/' || *y == '-' || *y == '.')
3975da2e3ebdSchin 								y++;
3976da2e3ebdSchin 							if (*y == '?')
3977da2e3ebdSchin 								while (isalnum(*y) || *y == '_' || *y == '/' || *y == '-' || *y == '.' || *y == '?' || *y == '=' || *y == '%' || *y == '&' || *y == ';' || *y == '#')
3978da2e3ebdSchin 									y++;
3979da2e3ebdSchin 							if (*(y - 1) == '.')
3980da2e3ebdSchin 								y--;
3981da2e3ebdSchin 							p--;
3982da2e3ebdSchin 							sfprintf(mp, "<A href=\"%-.*s\">%-.*s</A", y - p, p, y - p, p);
3983da2e3ebdSchin 							p = y;
3984da2e3ebdSchin 							c = '>';
3985da2e3ebdSchin 						}
3986da2e3ebdSchin 					}
3987da2e3ebdSchin 					else if (c == 'C')
3988da2e3ebdSchin 					{
3989da2e3ebdSchin 						y = p;
3990da2e3ebdSchin 						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++ == ')')
3991da2e3ebdSchin 						{
3992da2e3ebdSchin 							sfputr(mp, "Copyright &copy", -1);
3993da2e3ebdSchin 							p = y;
3994da2e3ebdSchin 							c = ';';
3995da2e3ebdSchin 						}
3996da2e3ebdSchin 					}
3997da2e3ebdSchin 				}
3998da2e3ebdSchin 				else if (c == ']')
3999da2e3ebdSchin 				{
4000da2e3ebdSchin 					if (n)
4001da2e3ebdSchin 						n--;
4002da2e3ebdSchin 				}
4003da2e3ebdSchin 				else if (c == '[')
4004da2e3ebdSchin 					n++;
4005da2e3ebdSchin 				if (c == CC_esc)
4006da2e3ebdSchin 				{
4007da2e3ebdSchin 					sfputc(mp, c);
4008da2e3ebdSchin 					do
4009da2e3ebdSchin 					{
4010da2e3ebdSchin 						if (!(c = *p++))
4011da2e3ebdSchin 						{
4012da2e3ebdSchin 							p--;
4013da2e3ebdSchin 							break;
4014da2e3ebdSchin 						}
4015da2e3ebdSchin 						sfputc(mp, c);
4016da2e3ebdSchin 					} while (c < 'a' || c > 'z');
4017da2e3ebdSchin 				}
4018da2e3ebdSchin 				else if (co++ >= rm && !n)
4019da2e3ebdSchin 				{
4020da2e3ebdSchin 					if (tp)
4021da2e3ebdSchin 					{
4022da2e3ebdSchin 						if (*sfstrseek(mp, tp, SEEK_SET) != ' ')
4023da2e3ebdSchin 							sfstrseek(mp, 1, SEEK_CUR);
4024da2e3ebdSchin 						tp = 0;
4025da2e3ebdSchin 						p = pp;
4026da2e3ebdSchin 						n = 0;
4027da2e3ebdSchin 					}
4028da2e3ebdSchin 					else if (c != ' ' && c != '\n')
4029da2e3ebdSchin 						sfputc(mp, c);
4030da2e3ebdSchin 					if (*p == ' ')
4031da2e3ebdSchin 						p++;
4032da2e3ebdSchin 					if (*p != '\n')
4033da2e3ebdSchin 					{
4034da2e3ebdSchin 						sfputc(mp, '\n');
4035da2e3ebdSchin 						for (co = 0; co < ts; co++)
4036da2e3ebdSchin 							sfputc(mp, ' ');
40377c2fbfb3SApril Chin 						rm = margin;
4038da2e3ebdSchin 					}
4039da2e3ebdSchin 				}
4040da2e3ebdSchin 				else
4041da2e3ebdSchin 					sfputc(mp, c);
4042da2e3ebdSchin 			}
4043da2e3ebdSchin 		}
4044da2e3ebdSchin 		for (d = sfstrbase(mp), t = sfstrseek(mp, 0, SEEK_CUR); t > d && ((c = *(t - 1)) == '\n' || c == '\r' || c == ' ' || c == '\t'); t--);
4045da2e3ebdSchin 		sfstrseek(mp, t - d, SEEK_SET);
4046da2e3ebdSchin 		if (style == STYLE_html)
4047da2e3ebdSchin 		{
4048*b30d1939SAndy Fiddaman 			sfprintf(mp, "\n");
4049da2e3ebdSchin 			while (pt > ptstk)
4050da2e3ebdSchin 			{
4051*b30d1939SAndy Fiddaman 				sfprintf(mp, "%s", end[pt->id]);
4052*b30d1939SAndy Fiddaman 				pt--;
4053da2e3ebdSchin 			}
4054*b30d1939SAndy Fiddaman 			sfprintf(mp, "</DIV>\n</BODY>\n</HTML>");
4055da2e3ebdSchin 		}
4056da2e3ebdSchin 	}
4057da2e3ebdSchin 	else
4058da2e3ebdSchin 		sfputr(mp, p, 0);
4059da2e3ebdSchin 	if (!(p = sfstruse(mp)))
4060da2e3ebdSchin 		goto nospace;
4061da2e3ebdSchin 	if (sp)
4062da2e3ebdSchin 		sfclose(sp);
4063da2e3ebdSchin 	return opt_info.msg = p;
4064da2e3ebdSchin  nospace:
4065da2e3ebdSchin 	s = T(NiL, ID, "[* out of space *]");
4066da2e3ebdSchin  nope:
4067da2e3ebdSchin 	if (psp)
4068da2e3ebdSchin 		pop(psp);
4069da2e3ebdSchin 	if (sp_help)
4070da2e3ebdSchin 		sfclose(sp_help);
4071da2e3ebdSchin 	if (sp_text)
4072da2e3ebdSchin 		sfclose(sp_text);
4073da2e3ebdSchin 	if (sp_plus)
4074da2e3ebdSchin 		sfclose(sp_plus);
4075da2e3ebdSchin 	if (sp_info)
4076da2e3ebdSchin 		sfclose(sp_info);
4077da2e3ebdSchin 	if (sp_head)
4078da2e3ebdSchin 		sfclose(sp_head);
4079da2e3ebdSchin 	if (sp_body)
4080da2e3ebdSchin 		sfclose(sp_body);
4081da2e3ebdSchin 	if (sp_misc)
4082da2e3ebdSchin 		sfclose(sp_misc);
4083da2e3ebdSchin 	return s;
4084da2e3ebdSchin }
4085da2e3ebdSchin 
4086da2e3ebdSchin /*
4087da2e3ebdSchin  * compatibility wrapper to opthelp()
4088da2e3ebdSchin  */
4089da2e3ebdSchin 
4090da2e3ebdSchin char*
optusage(const char * opts)4091da2e3ebdSchin optusage(const char* opts)
4092da2e3ebdSchin {
4093da2e3ebdSchin 	return opthelp(opts, NiL);
4094da2e3ebdSchin }
4095da2e3ebdSchin 
4096da2e3ebdSchin /*
4097da2e3ebdSchin  * convert number using strtonll() *except* that
4098da2e3ebdSchin  * 0*[[:digit:]].* is treated as [[:digit:]].*
4099da2e3ebdSchin  * i.e., it looks octal but isn't, to meet
4100da2e3ebdSchin  * posix Utility Argument Syntax -- use
4101da2e3ebdSchin  * 0x.* or <base>#* for alternate bases
4102da2e3ebdSchin  */
4103da2e3ebdSchin 
4104da2e3ebdSchin static intmax_t
optnumber(const char * s,char ** t,int * e)4105da2e3ebdSchin optnumber(const char* s, char** t, int* e)
4106da2e3ebdSchin {
4107da2e3ebdSchin 	intmax_t	n;
4108da2e3ebdSchin 	int		oerrno;
4109da2e3ebdSchin 
4110da2e3ebdSchin 	while (*s == '0' && isdigit(*(s + 1)))
4111da2e3ebdSchin 		s++;
4112da2e3ebdSchin 	oerrno = errno;
4113da2e3ebdSchin 	errno = 0;
4114da2e3ebdSchin 	n = strtonll(s, t, NiL, 0);
4115da2e3ebdSchin 	if (e)
4116da2e3ebdSchin 		*e = errno;
4117da2e3ebdSchin 	errno = oerrno;
4118da2e3ebdSchin 	return n;
4119da2e3ebdSchin }
4120da2e3ebdSchin 
4121da2e3ebdSchin /*
4122da2e3ebdSchin  * point opt_info.arg to an error/info message for opt_info.name
4123da2e3ebdSchin  * p points to opts location for opt_info.name
4124da2e3ebdSchin  * optget() return value is returned
4125da2e3ebdSchin  */
4126da2e3ebdSchin 
4127da2e3ebdSchin static int
opterror(register char * p,int err,int version,char * id,char * catalog)41283e14f97fSRoger A. Faulkner opterror(register char* p, int err, int version, char* id, char* catalog)
4129da2e3ebdSchin {
4130da2e3ebdSchin 	register Sfio_t*	mp;
4131da2e3ebdSchin 	register Sfio_t*	tp;
4132da2e3ebdSchin 	register char*		s;
4133da2e3ebdSchin 	register int		c;
4134da2e3ebdSchin 
4135da2e3ebdSchin 	if (opt_info.num != LONG_MIN)
413634f9b3eeSRoland Mainz 		opt_info.num = (long)(opt_info.number = 0);
4137*b30d1939SAndy Fiddaman 	if (!p || !(mp = state.mp) && !(mp = state.mp = sfstropen()))
4138da2e3ebdSchin 		goto nospace;
4139da2e3ebdSchin 	s = *p == '-' ? p : opt_info.name;
4140da2e3ebdSchin 	if (*p == '!')
4141da2e3ebdSchin 	{
4142da2e3ebdSchin 		while (*s == '-')
4143da2e3ebdSchin 			sfputc(mp, *s++);
4144da2e3ebdSchin 		sfputc(mp, 'n');
4145da2e3ebdSchin 		sfputc(mp, 'o');
4146da2e3ebdSchin 	}
4147da2e3ebdSchin 	sfputr(mp, s, ':');
4148da2e3ebdSchin 	sfputc(mp, ' ');
4149da2e3ebdSchin 	if (*p == '#' || *p == ':')
4150da2e3ebdSchin 	{
4151da2e3ebdSchin 		if (*p == '#')
4152da2e3ebdSchin 		{
4153da2e3ebdSchin 			s = T(NiL, ID, "numeric");
4154da2e3ebdSchin 			sfputr(mp, s, ' ');
4155da2e3ebdSchin 		}
4156da2e3ebdSchin 		if (*(p = next(p + 1, version)) == '[')
4157da2e3ebdSchin 		{
4158da2e3ebdSchin 			p = skip(s = p + 1, ':', '?', 0, 1, 0, 0, version);
4159*b30d1939SAndy Fiddaman 			tp = X(catalog) ? state.xp : mp;
4160da2e3ebdSchin 			while (s < p)
4161da2e3ebdSchin 			{
4162da2e3ebdSchin 				if ((c = *s++) == '?' || c == ']')
4163da2e3ebdSchin 					s++;
4164da2e3ebdSchin 				sfputc(tp, c);
4165da2e3ebdSchin 			}
4166da2e3ebdSchin 			if (!X(catalog))
4167da2e3ebdSchin 				sfputc(mp, ' ');
4168da2e3ebdSchin 			else if (p = sfstruse(tp))
41693e14f97fSRoger A. Faulkner 				sfputr(mp, T(id, catalog, p), ' ');
4170da2e3ebdSchin 			else
4171da2e3ebdSchin 				goto nospace;
4172da2e3ebdSchin 		}
4173da2e3ebdSchin 		p = opt_info.name[2] ? C("value expected") : C("argument expected");
4174da2e3ebdSchin 	}
4175da2e3ebdSchin 	else if (*p == '*' || *p == '&')
4176da2e3ebdSchin 	{
4177da2e3ebdSchin 		sfputr(mp, opt_info.arg, ':');
4178da2e3ebdSchin 		sfputc(mp, ' ');
4179da2e3ebdSchin 		p = *p == '&' ? C("ambiguous option argument value") : C("unknown option argument value");
4180da2e3ebdSchin 	}
4181da2e3ebdSchin 	else if (*p == '=' || *p == '!')
4182da2e3ebdSchin 		p = C("value not expected");
4183da2e3ebdSchin 	else if (*p == '?')
4184da2e3ebdSchin 		p = *(p + 1) == '?' ? C("optget: option not supported") : C("ambiguous option");
4185da2e3ebdSchin 	else if (*p == '+')
4186da2e3ebdSchin 		p = C("section not found");
4187da2e3ebdSchin 	else
4188da2e3ebdSchin 	{
4189da2e3ebdSchin 		if (opt_info.option[0] != '?' && opt_info.option[0] != '-' || opt_info.option[1] != '?' && opt_info.option[1] != '-')
4190da2e3ebdSchin 			opt_info.option[0] = 0;
4191da2e3ebdSchin 		p = C("unknown option");
4192da2e3ebdSchin 	}
4193da2e3ebdSchin 	p = T(NiL, ID, p);
4194da2e3ebdSchin 	sfputr(mp, p, -1);
4195da2e3ebdSchin 	if (err)
4196da2e3ebdSchin 		sfputr(mp, " -- out of range", -1);
4197da2e3ebdSchin 	if (opt_info.arg = sfstruse(mp))
4198da2e3ebdSchin 		return ':';
4199da2e3ebdSchin  nospace:
4200da2e3ebdSchin 	opt_info.arg = T(NiL, ID, "[* out of space *]");
4201da2e3ebdSchin 	return ':';
4202da2e3ebdSchin }
4203da2e3ebdSchin 
4204da2e3ebdSchin /*
4205da2e3ebdSchin  * argv:	command line argv where argv[0] is command name
4206da2e3ebdSchin  *
4207da2e3ebdSchin  * opts:	option control string
4208da2e3ebdSchin  *
4209da2e3ebdSchin  *	'[' [flag][=][index][:<long-name>[|<alias-name>...]['?'description]] ']'
4210da2e3ebdSchin  *			long option name, index, description; -index returned
4211da2e3ebdSchin  *	':'		option takes string arg
4212da2e3ebdSchin  *	'#'		option takes numeric arg (concat option may follow)
4213da2e3ebdSchin  *	'?'		(option) following options not in usage
4214da2e3ebdSchin  *			(following # or :) optional arg
4215da2e3ebdSchin  *	'[' '[' ... ] ... '[' ... ']' ']'
4216da2e3ebdSchin  *			mutually exclusive option grouping
4217da2e3ebdSchin  *	'[' name [:attr]* [?description] ']'
4218da2e3ebdSchin  *			(following # or :) optional option arg description
4219da2e3ebdSchin  *	'\n'[' '|'\t']*	ignored for legibility
4220da2e3ebdSchin  *	' ' ...		optional argument(s) description (to end of string)
4221da2e3ebdSchin  *			or after blank line
4222da2e3ebdSchin  *	']]'		literal ']' within '[' ... ']'
4223da2e3ebdSchin  *
4224da2e3ebdSchin  * return:
4225da2e3ebdSchin  *	0		no more options
4226da2e3ebdSchin  *	'?'		usage: opt_info.arg points to message sans
4227da2e3ebdSchin  *			`Usage: command '
4228da2e3ebdSchin  *	':'		error: opt_info.arg points to message sans `command: '
4229da2e3ebdSchin  *
423034f9b3eeSRoland Mainz  * ':'  '#'  ' '  '['  ']'
4231da2e3ebdSchin  *			invalid option chars
4232da2e3ebdSchin  *
4233da2e3ebdSchin  * -- terminates option list and returns 0
4234da2e3ebdSchin  *
4235da2e3ebdSchin  * + as first opts char makes + equivalent to -
4236da2e3ebdSchin  *
4237da2e3ebdSchin  * if any # option is specified then numeric options (e.g., -123)
4238da2e3ebdSchin  * are associated with the leftmost # option in opts
4239da2e3ebdSchin  *
4240da2e3ebdSchin  * usage info in placed opt_info.arg when '?' returned
4241da2e3ebdSchin  * see help_text[] (--???) for more info
4242da2e3ebdSchin  */
4243da2e3ebdSchin 
4244da2e3ebdSchin int
optget(register char ** argv,const char * oopts)4245da2e3ebdSchin optget(register char** argv, const char* oopts)
4246da2e3ebdSchin {
4247da2e3ebdSchin 	register int	c;
4248da2e3ebdSchin 	register char*	s;
4249da2e3ebdSchin 	char*		a;
4250da2e3ebdSchin 	char*		b;
4251da2e3ebdSchin 	char*		e;
4252da2e3ebdSchin 	char*		f;
4253da2e3ebdSchin 	char*		g;
4254da2e3ebdSchin 	char*		v;
4255da2e3ebdSchin 	char*		w;
4256da2e3ebdSchin 	char*		p;
4257da2e3ebdSchin 	char*		q;
4258da2e3ebdSchin 	char*		t;
4259da2e3ebdSchin 	char*		y;
4260da2e3ebdSchin 	char*		numopt;
4261da2e3ebdSchin 	char*		opts;
42623e14f97fSRoger A. Faulkner 	char*		id;
4263da2e3ebdSchin 	char*		catalog;
4264da2e3ebdSchin 	int		n;
4265da2e3ebdSchin 	int		m;
4266da2e3ebdSchin 	int		k;
4267da2e3ebdSchin 	int		j;
4268da2e3ebdSchin 	int		x;
4269da2e3ebdSchin 	int		err;
4270da2e3ebdSchin 	int		no;
4271da2e3ebdSchin 	int		nov;
4272da2e3ebdSchin 	int		num;
4273da2e3ebdSchin 	int		numchr;
4274da2e3ebdSchin 	int		prefix;
4275da2e3ebdSchin 	int		version;
4276da2e3ebdSchin 	Help_t*		hp;
4277da2e3ebdSchin 	Push_t*		psp;
4278da2e3ebdSchin 	Push_t*		tsp;
4279da2e3ebdSchin 	Sfio_t*		vp;
4280da2e3ebdSchin 	Sfio_t*		xp;
4281da2e3ebdSchin 	Optcache_t*	cache;
4282da2e3ebdSchin 	Optcache_t*	pcache;
4283da2e3ebdSchin 	Optpass_t*	pass;
4284da2e3ebdSchin 
42857c2fbfb3SApril Chin #if !_PACKAGE_astsa && !_YOU_FIGURED_OUT_HOW_TO_GET_ALL_DLLS_TO_DO_THIS_
4286da2e3ebdSchin 	/*
4287da2e3ebdSchin 	 * these are not initialized by all dlls!
4288da2e3ebdSchin 	 */
4289da2e3ebdSchin 
4290da2e3ebdSchin 	extern Error_info_t	_error_info_;
4291da2e3ebdSchin 	extern Opt_t		_opt_info_;
4292da2e3ebdSchin 
4293da2e3ebdSchin 	if (!_error_infop_)
4294da2e3ebdSchin 		_error_infop_ = &_error_info_;
4295da2e3ebdSchin 	if (!_opt_infop_)
4296da2e3ebdSchin 		_opt_infop_ = &_opt_info_;
4297da2e3ebdSchin #endif
4298da2e3ebdSchin 	if (!oopts)
4299da2e3ebdSchin 		return 0;
4300*b30d1939SAndy Fiddaman 	state.pindex = opt_info.index;
4301*b30d1939SAndy Fiddaman 	state.poffset = opt_info.offset;
4302da2e3ebdSchin 	if (!opt_info.index)
4303da2e3ebdSchin 	{
4304da2e3ebdSchin 		opt_info.index = 1;
4305da2e3ebdSchin 		opt_info.offset = 0;
4306*b30d1939SAndy Fiddaman 		if (state.npass)
4307da2e3ebdSchin 		{
4308*b30d1939SAndy Fiddaman 			state.npass = 0;
4309*b30d1939SAndy Fiddaman 			state.join = 0;
4310da2e3ebdSchin 		}
4311da2e3ebdSchin 	}
4312da2e3ebdSchin 	if (!argv)
4313da2e3ebdSchin 		cache = 0;
4314da2e3ebdSchin 	else
4315*b30d1939SAndy Fiddaman 		for (pcache = 0, cache = state.cache; cache; pcache = cache, cache = cache->next)
4316da2e3ebdSchin 			if (cache->pass.oopts == (char*)oopts)
4317da2e3ebdSchin 				break;
4318da2e3ebdSchin 	if (cache)
4319da2e3ebdSchin 	{
4320da2e3ebdSchin 		if (pcache)
4321da2e3ebdSchin 		{
4322da2e3ebdSchin 			pcache->next = cache->next;
4323*b30d1939SAndy Fiddaman 			cache->next = state.cache;
4324*b30d1939SAndy Fiddaman 			state.cache = cache;
4325da2e3ebdSchin 		}
4326da2e3ebdSchin 		pass = &cache->pass;
4327*b30d1939SAndy Fiddaman 		state.npass = -1;
4328da2e3ebdSchin 	}
4329da2e3ebdSchin 	else
4330da2e3ebdSchin 	{
4331da2e3ebdSchin 		if (!argv)
4332*b30d1939SAndy Fiddaman 			n = state.npass ? state.npass : 1;
4333*b30d1939SAndy Fiddaman 		else if ((n = state.join - 1) < 0)
4334da2e3ebdSchin 			n = 0;
4335*b30d1939SAndy Fiddaman 		if (n >= state.npass || state.pass[n].oopts != (char*)oopts)
4336da2e3ebdSchin 		{
4337*b30d1939SAndy Fiddaman 			for (m = 0; m < state.npass && state.pass[m].oopts != (char*)oopts; m++);
4338*b30d1939SAndy Fiddaman 			if (m < state.npass)
4339da2e3ebdSchin 				n = m;
4340da2e3ebdSchin 			else
4341da2e3ebdSchin 			{
4342*b30d1939SAndy Fiddaman 				if (n >= elementsof(state.pass))
4343*b30d1939SAndy Fiddaman 					n = elementsof(state.pass) - 1;
4344*b30d1939SAndy Fiddaman 				init((char*)oopts, &state.pass[n]);
4345*b30d1939SAndy Fiddaman 				if (state.npass <= n)
4346*b30d1939SAndy Fiddaman 					state.npass = n + 1;
4347da2e3ebdSchin 			}
4348da2e3ebdSchin 		}
4349da2e3ebdSchin 		if (!argv)
4350da2e3ebdSchin 			return 0;
4351*b30d1939SAndy Fiddaman 		pass = &state.pass[n];
4352da2e3ebdSchin 	}
4353da2e3ebdSchin 	opts = pass->opts;
4354da2e3ebdSchin 	prefix = pass->prefix;
4355da2e3ebdSchin 	version = pass->version;
43563e14f97fSRoger A. Faulkner 	id = pass->id;
4357*b30d1939SAndy Fiddaman 	if (!(xp = state.xp) || (catalog = pass->catalog) && !X(catalog))
4358da2e3ebdSchin 		catalog = 0;
4359da2e3ebdSchin 	else /* if (!error_info.catalog) */
4360da2e3ebdSchin 		error_info.catalog = catalog;
4361da2e3ebdSchin  again:
4362da2e3ebdSchin 	psp = 0;
4363da2e3ebdSchin 
4364da2e3ebdSchin 	/*
4365da2e3ebdSchin 	 * check if any options remain and determine if the
4366da2e3ebdSchin 	 * next option is short or long
4367da2e3ebdSchin 	 */
4368da2e3ebdSchin 
4369da2e3ebdSchin 	opt_info.assignment = 0;
4370da2e3ebdSchin 	num = 1;
4371da2e3ebdSchin 	w = v = 0;
4372da2e3ebdSchin 	x = 0;
4373da2e3ebdSchin 	for (;;)
4374da2e3ebdSchin 	{
4375da2e3ebdSchin 		if (!opt_info.offset)
4376da2e3ebdSchin 		{
4377da2e3ebdSchin 			/*
4378da2e3ebdSchin 			 * finished with the previous arg
4379da2e3ebdSchin 			 */
4380da2e3ebdSchin 
4381*b30d1939SAndy Fiddaman 			if (opt_info.index == 1 && opt_info.argv != state.strv)
4382da2e3ebdSchin 			{
4383da2e3ebdSchin 				opt_info.argv = 0;
4384*b30d1939SAndy Fiddaman 				state.argv[0] = 0;
4385*b30d1939SAndy Fiddaman 				if (argv[0] && (state.argv[0] = save(argv[0], strlen(argv[0]), 0, 0, 0, 0)))
4386*b30d1939SAndy Fiddaman 					opt_info.argv = state.argv;
4387*b30d1939SAndy Fiddaman 				state.style = STYLE_short;
4388da2e3ebdSchin 			}
4389da2e3ebdSchin 			if (!(s = argv[opt_info.index]))
4390da2e3ebdSchin 				return 0;
4391da2e3ebdSchin 			if (!prefix)
4392da2e3ebdSchin 			{
4393da2e3ebdSchin 				/*
4394da2e3ebdSchin 				 * long with no prefix (dd style)
4395da2e3ebdSchin 				 */
4396da2e3ebdSchin 
4397da2e3ebdSchin 				n = 2;
4398da2e3ebdSchin 				if ((c = *s) != '-' && c != '+')
4399da2e3ebdSchin 					c = '-';
4400da2e3ebdSchin 				else if (*++s == c)
4401da2e3ebdSchin 				{
4402da2e3ebdSchin 					if (!*++s)
4403da2e3ebdSchin 					{
4404da2e3ebdSchin 						opt_info.index++;
4405da2e3ebdSchin 						return 0;
4406da2e3ebdSchin 					}
44077c2fbfb3SApril Chin 					else if (*s == c)
44087c2fbfb3SApril Chin 						return 0;
4409da2e3ebdSchin 				}
4410da2e3ebdSchin 				else if (*s == '?')
4411da2e3ebdSchin 					n = 1;
4412da2e3ebdSchin 			}
44137c2fbfb3SApril Chin 			else if ((c = *s++) != '-' && (c != '+' || !(pass->flags & OPT_plus) && (!(pass->flags & OPT_numeric) || !isdigit(*s))))
4414da2e3ebdSchin 			{
4415da2e3ebdSchin 				if (!(pass->flags & OPT_old) || !isalpha(c))
4416da2e3ebdSchin 					return 0;
4417da2e3ebdSchin 				s--;
4418da2e3ebdSchin 				n = 1;
4419da2e3ebdSchin 				opt_info.offset--;
4420da2e3ebdSchin 			}
4421da2e3ebdSchin 			else if (*s == c)
4422da2e3ebdSchin 			{
4423da2e3ebdSchin 				if (!*++s)
4424da2e3ebdSchin 				{
4425da2e3ebdSchin 					/*
4426da2e3ebdSchin 					 * -- or ++ end of options
4427da2e3ebdSchin 					 */
4428da2e3ebdSchin 
4429da2e3ebdSchin 					opt_info.index++;
4430da2e3ebdSchin 					return 0;
4431da2e3ebdSchin 				}
44327c2fbfb3SApril Chin 				else if (*s == c)
44337c2fbfb3SApril Chin 				{
44347c2fbfb3SApril Chin 					/*
44357c2fbfb3SApril Chin 					 * ---* or +++* are operands
44367c2fbfb3SApril Chin 					 */
44377c2fbfb3SApril Chin 
44387c2fbfb3SApril Chin 					return 0;
44397c2fbfb3SApril Chin 				}
4440da2e3ebdSchin 				if (version || *s == '?' || !(pass->flags & OPT_minus))
4441da2e3ebdSchin 				{
4442da2e3ebdSchin 					/*
4443da2e3ebdSchin 					 * long with double prefix
4444da2e3ebdSchin 					 */
4445da2e3ebdSchin 
4446da2e3ebdSchin 					n = 2;
4447da2e3ebdSchin 				}
4448da2e3ebdSchin 				else
4449da2e3ebdSchin 				{
4450da2e3ebdSchin 					/*
4451da2e3ebdSchin 					 * short option char '-'
4452da2e3ebdSchin 					 */
4453da2e3ebdSchin 
4454da2e3ebdSchin 					s--;
4455da2e3ebdSchin 					n = 1;
4456da2e3ebdSchin 				}
4457da2e3ebdSchin 			}
4458da2e3ebdSchin 			else if (prefix == 1 && *s != '?')
4459da2e3ebdSchin 			{
4460da2e3ebdSchin 				/*
4461da2e3ebdSchin 				 * long with single prefix (find style)
4462da2e3ebdSchin 				 */
4463da2e3ebdSchin 
4464da2e3ebdSchin 				n = 2;
4465da2e3ebdSchin 			}
4466da2e3ebdSchin 			else
4467da2e3ebdSchin 			{
4468da2e3ebdSchin 				/*
4469da2e3ebdSchin 				 * short (always with single prefix)
4470da2e3ebdSchin 				 */
4471da2e3ebdSchin 
4472da2e3ebdSchin 				n = 1;
4473da2e3ebdSchin 			}
4474da2e3ebdSchin 
4475da2e3ebdSchin 			/*
4476da2e3ebdSchin 			 * just a prefix is an option (e.g., `-' == stdin)
4477da2e3ebdSchin 			 */
4478da2e3ebdSchin 
4479da2e3ebdSchin 			if (!*s)
4480da2e3ebdSchin 				return 0;
4481da2e3ebdSchin 			if (c == '+')
4482da2e3ebdSchin 				opt_info.arg = 0;
4483da2e3ebdSchin 			if (n == 2)
4484da2e3ebdSchin 			{
4485da2e3ebdSchin 				x = 0;
4486*b30d1939SAndy Fiddaman 				state.style = STYLE_long;
4487da2e3ebdSchin 				opt_info.option[0] = opt_info.name[0] = opt_info.name[1] = c;
4488da2e3ebdSchin 				w = &opt_info.name[prefix];
4489da2e3ebdSchin 				if ((*s == 'n' || *s == 'N') && (*(s + 1) == 'o' || *(s + 1) == 'O') && *(s + 2) && *(s + 2) != '=')
4490da2e3ebdSchin 					no = *(s + 2) == '-' ? 3 : 2;
4491da2e3ebdSchin 				else
4492da2e3ebdSchin 					no = 0;
4493da2e3ebdSchin 				for (c = *s; *s; s++)
4494da2e3ebdSchin 				{
4495da2e3ebdSchin 					if (*s == '=')
4496da2e3ebdSchin 					{
4497da2e3ebdSchin 						if (*(s + 1) == '=')
4498da2e3ebdSchin 							s++;
4499da2e3ebdSchin 						if (!isalnum(*(s - 1)) && *(w - 1) == (opt_info.assignment = *(s - 1)))
4500da2e3ebdSchin 							w--;
4501da2e3ebdSchin 						v = ++s;
4502da2e3ebdSchin 						break;
4503da2e3ebdSchin 					}
4504da2e3ebdSchin 					if (w < &opt_info.name[elementsof(opt_info.name) - 1] && *s != ':' && *s != '|' && *s != '[' && *s != ']')
4505da2e3ebdSchin 						*w++ = *s;
4506da2e3ebdSchin 				}
4507da2e3ebdSchin 				*w = 0;
4508da2e3ebdSchin 				w = &opt_info.name[prefix];
4509da2e3ebdSchin 				c = *w;
4510da2e3ebdSchin 				opt_info.offset = 0;
4511da2e3ebdSchin 				opt_info.index++;
4512da2e3ebdSchin 				break;
4513da2e3ebdSchin 			}
4514da2e3ebdSchin 			opt_info.offset++;
4515da2e3ebdSchin 		}
4516da2e3ebdSchin 		if (!argv[opt_info.index])
4517da2e3ebdSchin 			return 0;
4518da2e3ebdSchin 		if (c = argv[opt_info.index][opt_info.offset++])
4519da2e3ebdSchin 		{
4520da2e3ebdSchin 			if ((k = argv[opt_info.index][0]) != '-' && k != '+')
4521da2e3ebdSchin 				k = '-';
4522da2e3ebdSchin 			opt_info.option[0] = opt_info.name[0] = k;
4523da2e3ebdSchin 			opt_info.option[1] = opt_info.name[1] = c;
4524da2e3ebdSchin 			opt_info.option[2] = opt_info.name[2] = 0;
4525da2e3ebdSchin 			break;
4526da2e3ebdSchin 		}
4527da2e3ebdSchin 		opt_info.offset = 0;
4528da2e3ebdSchin 		opt_info.index++;
4529da2e3ebdSchin 	}
4530da2e3ebdSchin 
4531da2e3ebdSchin 	/*
4532da2e3ebdSchin 	 * at this point:
4533da2e3ebdSchin 	 *
4534da2e3ebdSchin 	 *	c	the first character of the option
4535da2e3ebdSchin 	 *	w	long option name if != 0, otherwise short
4536da2e3ebdSchin 	 *	v	long option value (via =) if w != 0
4537da2e3ebdSchin 	 */
4538da2e3ebdSchin 
4539da2e3ebdSchin 	if (c == '?')
4540da2e3ebdSchin 	{
4541da2e3ebdSchin 		/*
4542da2e3ebdSchin 		 * ? always triggers internal help
4543da2e3ebdSchin 		 */
4544da2e3ebdSchin 
4545*b30d1939SAndy Fiddaman 		if (!state.msgdict)
4546*b30d1939SAndy Fiddaman 			initdict();
4547*b30d1939SAndy Fiddaman 		if (w)
4548*b30d1939SAndy Fiddaman 		{
4549*b30d1939SAndy Fiddaman 			if (!v && (*(w + 1) || !(v = argv[opt_info.index]) || !++opt_info.index))
4550*b30d1939SAndy Fiddaman 				v = w + 1;
4551*b30d1939SAndy Fiddaman 			else if (w[0] != '?' || w[1])
4552*b30d1939SAndy Fiddaman 			{
4553*b30d1939SAndy Fiddaman 				s = w;
4554*b30d1939SAndy Fiddaman 				w = v;
4555*b30d1939SAndy Fiddaman 				v = s + 1;
4556*b30d1939SAndy Fiddaman 			}
4557*b30d1939SAndy Fiddaman 		}
4558da2e3ebdSchin 		opt_info.option[1] = c;
4559da2e3ebdSchin 		opt_info.option[2] = 0;
4560da2e3ebdSchin 		if (!w)
4561da2e3ebdSchin 		{
4562da2e3ebdSchin 			opt_info.name[1] = c;
4563da2e3ebdSchin 			opt_info.name[2] = 0;
4564da2e3ebdSchin 		}
4565da2e3ebdSchin 		goto help;
4566da2e3ebdSchin 	}
4567*b30d1939SAndy Fiddaman 	else if (w && !state.msgdict)
4568*b30d1939SAndy Fiddaman 		initdict();
4569da2e3ebdSchin 	numopt = 0;
4570da2e3ebdSchin 	f = 0;
4571da2e3ebdSchin 	s = opts;
4572da2e3ebdSchin 
4573da2e3ebdSchin 	/*
4574da2e3ebdSchin 	 * no option can start with these characters
4575da2e3ebdSchin 	 */
4576da2e3ebdSchin 
4577da2e3ebdSchin 	if (c == ':' || c == '#' || c == ' ' || c == '[' || c == ']')
4578da2e3ebdSchin 	{
4579da2e3ebdSchin 		if (c != *s)
4580da2e3ebdSchin 			s = "";
4581da2e3ebdSchin 	}
4582da2e3ebdSchin 	else
4583da2e3ebdSchin 	{
4584da2e3ebdSchin 		a = 0;
4585da2e3ebdSchin 		if (!w && (pass->flags & OPT_cache))
4586da2e3ebdSchin 		{
4587da2e3ebdSchin 			if (cache)
4588da2e3ebdSchin 			{
4589da2e3ebdSchin 				if (k = cache->flags[map[c]])
4590da2e3ebdSchin 				{
4591da2e3ebdSchin 					opt_info.arg = 0;
4592da2e3ebdSchin 
4593da2e3ebdSchin 					/*
4594da2e3ebdSchin 					 * this is a ksh getopts workaround
4595da2e3ebdSchin 					 */
4596da2e3ebdSchin 
4597da2e3ebdSchin 					if (opt_info.num != LONG_MIN)
459834f9b3eeSRoland Mainz 						opt_info.num = (long)(opt_info.number = !(k & OPT_cache_invert));
4599da2e3ebdSchin 					if (!(k & (OPT_cache_string|OPT_cache_numeric)))
4600da2e3ebdSchin 						return c;
4601da2e3ebdSchin 					if (*(opt_info.arg = &argv[opt_info.index++][opt_info.offset]))
4602da2e3ebdSchin 					{
4603da2e3ebdSchin 						if (!(k & OPT_cache_numeric))
4604da2e3ebdSchin 						{
4605da2e3ebdSchin 							opt_info.offset = 0;
4606da2e3ebdSchin 							return c;
4607da2e3ebdSchin 						}
4608da2e3ebdSchin 						opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
4609da2e3ebdSchin 						if (err || e == opt_info.arg)
4610da2e3ebdSchin 						{
4611*b30d1939SAndy Fiddaman 							opt_info.num = (long)(opt_info.number = 0);
4612da2e3ebdSchin 							if (!err && (k & OPT_cache_optional))
4613da2e3ebdSchin 							{
4614da2e3ebdSchin 								opt_info.arg = 0;
4615da2e3ebdSchin 								opt_info.index--;
4616da2e3ebdSchin 								return c;
4617da2e3ebdSchin 							}
4618da2e3ebdSchin 						}
4619da2e3ebdSchin 						else if (*e)
4620da2e3ebdSchin 						{
4621da2e3ebdSchin 							opt_info.offset += e - opt_info.arg;
4622da2e3ebdSchin 							opt_info.index--;
4623da2e3ebdSchin 							return c;
4624da2e3ebdSchin 						}
4625da2e3ebdSchin 						else
4626da2e3ebdSchin 						{
4627da2e3ebdSchin 							opt_info.offset = 0;
4628da2e3ebdSchin 							return c;
4629da2e3ebdSchin 						}
4630da2e3ebdSchin 					}
4631da2e3ebdSchin 					else if (opt_info.arg = argv[opt_info.index])
4632da2e3ebdSchin 					{
4633da2e3ebdSchin 						opt_info.index++;
4634da2e3ebdSchin 						if ((k & OPT_cache_optional) && (*opt_info.arg == '-' || (pass->flags & OPT_plus) && *opt_info.arg == '+') && *(opt_info.arg + 1))
4635da2e3ebdSchin 						{
4636da2e3ebdSchin 							opt_info.arg = 0;
4637da2e3ebdSchin 							opt_info.index--;
4638da2e3ebdSchin 							opt_info.offset = 0;
4639*b30d1939SAndy Fiddaman 							opt_info.num = (long)(opt_info.number = 0);
4640da2e3ebdSchin 							return c;
4641da2e3ebdSchin 						}
4642da2e3ebdSchin 						if (k & OPT_cache_string)
4643da2e3ebdSchin 						{
4644da2e3ebdSchin 							opt_info.offset = 0;
4645da2e3ebdSchin 							return c;
4646da2e3ebdSchin 						}
4647da2e3ebdSchin 						opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
4648da2e3ebdSchin 						if (!err)
4649da2e3ebdSchin 						{
4650da2e3ebdSchin 							if (!*e)
4651da2e3ebdSchin 							{
4652da2e3ebdSchin 								opt_info.offset = 0;
4653da2e3ebdSchin 								return c;
4654da2e3ebdSchin 							}
4655da2e3ebdSchin 							if (k & OPT_cache_optional)
4656da2e3ebdSchin 							{
4657da2e3ebdSchin 								opt_info.arg = 0;
4658da2e3ebdSchin 								opt_info.index--;
4659da2e3ebdSchin 								opt_info.offset = 0;
4660da2e3ebdSchin 								return c;
4661da2e3ebdSchin 							}
4662da2e3ebdSchin 						}
4663da2e3ebdSchin 					}
4664da2e3ebdSchin 					else if (k & OPT_cache_optional)
4665da2e3ebdSchin 					{
4666da2e3ebdSchin 						opt_info.offset = 0;
4667da2e3ebdSchin 						return c;
4668da2e3ebdSchin 					}
4669da2e3ebdSchin 					opt_info.index--;
4670da2e3ebdSchin 				}
4671da2e3ebdSchin 				cache = 0;
4672da2e3ebdSchin 			}
4673da2e3ebdSchin 			else if (cache = newof(0, Optcache_t, 1, 0))
4674da2e3ebdSchin 			{
4675da2e3ebdSchin 				cache->caching = c;
4676da2e3ebdSchin 				c = 0;
4677da2e3ebdSchin 				cache->pass = *pass;
4678*b30d1939SAndy Fiddaman 				cache->next = state.cache;
4679*b30d1939SAndy Fiddaman 				state.cache = cache;
4680da2e3ebdSchin 			}
4681da2e3ebdSchin 		}
4682da2e3ebdSchin 		else
4683da2e3ebdSchin 			cache = 0;
4684da2e3ebdSchin 		for (;;)
4685da2e3ebdSchin 		{
4686da2e3ebdSchin 			if (!(*(s = next(s, version))) || *s == '\n' || *s == ' ')
4687da2e3ebdSchin 			{
4688da2e3ebdSchin 				if (!(tsp = psp))
4689da2e3ebdSchin 				{
4690da2e3ebdSchin 					if (cache)
4691da2e3ebdSchin 					{
4692da2e3ebdSchin 						/*
4693da2e3ebdSchin 						 * the first loop pass
4694da2e3ebdSchin 						 * initialized the cache
4695da2e3ebdSchin 						 * so one more pass to
4696da2e3ebdSchin 						 * check the cache or
4697da2e3ebdSchin 						 * bail for a full scan
4698da2e3ebdSchin 						 */
4699da2e3ebdSchin 
4700da2e3ebdSchin 						cache->flags[0] = 0;
4701da2e3ebdSchin 						c = cache->caching;
4702da2e3ebdSchin 						cache->caching = 0;
4703da2e3ebdSchin 						cache = 0;
4704da2e3ebdSchin 						s = opts;
4705da2e3ebdSchin 						continue;
4706da2e3ebdSchin 					}
4707da2e3ebdSchin 					if (!x && catalog)
4708da2e3ebdSchin 					{
4709da2e3ebdSchin 						/*
4710da2e3ebdSchin 						 * the first loop pass
4711da2e3ebdSchin 						 * translated long
4712da2e3ebdSchin 						 * options and there
4713da2e3ebdSchin 						 * were no matches so
4714da2e3ebdSchin 						 * one more pass for C
4715da2e3ebdSchin 						 * locale
4716da2e3ebdSchin 						 */
4717da2e3ebdSchin 
4718da2e3ebdSchin 						catalog = 0;
4719da2e3ebdSchin 						s = opts;
4720da2e3ebdSchin 						continue;
4721da2e3ebdSchin 					}
4722da2e3ebdSchin 					s = "";
4723da2e3ebdSchin 					break;
4724da2e3ebdSchin 				}
4725da2e3ebdSchin 				s = psp->ob;
4726da2e3ebdSchin 				psp = psp->next;
4727da2e3ebdSchin 				free(tsp);
4728da2e3ebdSchin 				continue;
4729da2e3ebdSchin 			}
4730da2e3ebdSchin 			if (*s == '\f')
4731da2e3ebdSchin 			{
4732*b30d1939SAndy Fiddaman 				psp = info(psp, s + 1, NiL, xp, id);
4733da2e3ebdSchin 				if (psp->nb)
4734da2e3ebdSchin 					s = psp->nb;
4735da2e3ebdSchin 				else
4736da2e3ebdSchin 				{
4737da2e3ebdSchin 					s = psp->ob;
4738da2e3ebdSchin 					psp = psp->next;
4739da2e3ebdSchin 				}
4740da2e3ebdSchin 				continue;
4741da2e3ebdSchin 			}
474234f9b3eeSRoland Mainz 			message((-20, "optget: opt %s  c %c  w %s  num %ld", show(s), c, w, num));
4743da2e3ebdSchin 			if (*s == c && !w)
4744da2e3ebdSchin 				break;
4745da2e3ebdSchin 			else if (*s == '[')
4746da2e3ebdSchin 			{
4747*b30d1939SAndy Fiddaman 				s = next(s + 1, version);
4748*b30d1939SAndy Fiddaman 				if (*s == '(')
4749*b30d1939SAndy Fiddaman 				{
4750*b30d1939SAndy Fiddaman 					s = nest(f = s);
4751*b30d1939SAndy Fiddaman 					if (!conformance(f, s - f))
4752*b30d1939SAndy Fiddaman 						goto disable;
4753*b30d1939SAndy Fiddaman 				}
4754*b30d1939SAndy Fiddaman 				k = *(f = s);
4755da2e3ebdSchin 				if (k == '+' || k == '-')
4756da2e3ebdSchin 					/* ignore */;
4757da2e3ebdSchin 				else if (k == '[' || version < 1)
4758da2e3ebdSchin 					continue;
4759da2e3ebdSchin 				else if (w && !cache)
4760da2e3ebdSchin 				{
4761da2e3ebdSchin 					nov = no;
4762*b30d1939SAndy Fiddaman 					if (*(s + 1) == '\f' && (vp = state.vp))
4763da2e3ebdSchin 					{
4764da2e3ebdSchin 						sfputc(vp, k);
47653e14f97fSRoger A. Faulkner 						s = expand(s + 2, NiL, &t, vp, id);
4766da2e3ebdSchin 						if (*s)
4767da2e3ebdSchin 							*(f = s - 1) = k;
4768da2e3ebdSchin 						else
4769da2e3ebdSchin 						{
4770da2e3ebdSchin 							f = sfstrbase(vp);
4771da2e3ebdSchin 							if (s = strrchr(f, ':'))
4772da2e3ebdSchin 								f = s - 1;
4773da2e3ebdSchin 							else
4774da2e3ebdSchin 								s = f + 1;
4775da2e3ebdSchin 						}
4776da2e3ebdSchin 					}
4777da2e3ebdSchin 					else
4778da2e3ebdSchin 						t = 0;
4779da2e3ebdSchin 					if (*s != ':')
4780da2e3ebdSchin 						s = skip(s, ':', '?', 0, 1, 0, 0, version);
4781da2e3ebdSchin 					if (*s == ':')
4782da2e3ebdSchin 					{
4783da2e3ebdSchin 						if (catalog)
4784da2e3ebdSchin 						{
4785da2e3ebdSchin 							p = skip(s + 1, '?', 0, 0, 1, 0, 0, version);
4786da2e3ebdSchin 							e = sfprints("%-.*s", p - (s + 1), s + 1);
47873e14f97fSRoger A. Faulkner 							g = T(id, catalog, e);
4788da2e3ebdSchin 							if (g == e)
4789da2e3ebdSchin 								p = 0;
4790da2e3ebdSchin 							else
4791da2e3ebdSchin 							{
4792da2e3ebdSchin 								sfprintf(xp, ":%s|%s?", g, e);
4793da2e3ebdSchin 								if (!(s = sfstruse(xp)))
4794da2e3ebdSchin 									goto nospace;
4795da2e3ebdSchin 							}
4796da2e3ebdSchin 						}
4797da2e3ebdSchin 						else
4798da2e3ebdSchin 							p = 0;
4799da2e3ebdSchin 						y = w;
4800da2e3ebdSchin 						for (;;)
4801da2e3ebdSchin 						{
4802da2e3ebdSchin 							n = m = 0;
4803da2e3ebdSchin 							e = s + 1;
4804da2e3ebdSchin 							while (*++s)
4805da2e3ebdSchin 							{
4806da2e3ebdSchin 								if (*s == '*' || *s == '\a')
4807da2e3ebdSchin 								{
4808da2e3ebdSchin 									if (*s == '\a')
4809da2e3ebdSchin 										do
4810da2e3ebdSchin 										{
4811da2e3ebdSchin 											if (!*++s)
4812da2e3ebdSchin 											{
4813da2e3ebdSchin 												s--;
4814da2e3ebdSchin 												break;
4815da2e3ebdSchin 											}
4816da2e3ebdSchin 										} while (*s != '\a');
4817da2e3ebdSchin 									j = *(s + 1);
4818da2e3ebdSchin 									if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
4819da2e3ebdSchin 									{
4820da2e3ebdSchin 										while (*w)
4821da2e3ebdSchin 											w++;
4822da2e3ebdSchin 										m = 0;
4823da2e3ebdSchin 										break;
4824da2e3ebdSchin 									}
4825da2e3ebdSchin 									m = 1;
4826da2e3ebdSchin 								}
4827*b30d1939SAndy Fiddaman 								else if (*s == *w || SEP(*s) && SEP(*w))
4828da2e3ebdSchin 									w++;
4829da2e3ebdSchin 								else if (*w == 0)
4830da2e3ebdSchin 									break;
4831*b30d1939SAndy Fiddaman 								else if (!SEP(*s))
4832da2e3ebdSchin 								{
4833*b30d1939SAndy Fiddaman 									if (SEP(*w))
4834da2e3ebdSchin 									{
4835da2e3ebdSchin 										if (*++w == *s)
4836da2e3ebdSchin 										{
4837da2e3ebdSchin 											w++;
4838da2e3ebdSchin 											continue;
4839da2e3ebdSchin 										}
4840da2e3ebdSchin 									}
4841*b30d1939SAndy Fiddaman 									else if (w == y || SEP(*(w - 1)) || isupper(*(w - 1)) && islower(*w))
4842da2e3ebdSchin 										break;
4843*b30d1939SAndy Fiddaman 									for (q = s; *q && !SEP(*q) && *q != '|' && *q != '?' && *q != ']'; q++);
4844*b30d1939SAndy Fiddaman 									if (!SEP(*q))
4845da2e3ebdSchin 										break;
4846da2e3ebdSchin 									for (s = q; w > y && *w != *(s + 1); w--);
4847da2e3ebdSchin 								}
4848da2e3ebdSchin 								else if (*w != *(s + 1))
4849da2e3ebdSchin 									break;
4850da2e3ebdSchin 							}
4851da2e3ebdSchin 							if (!*w)
4852da2e3ebdSchin 							{
4853da2e3ebdSchin 								nov = 0;
4854da2e3ebdSchin 								break;
4855da2e3ebdSchin 							}
4856da2e3ebdSchin 							if (n = no)
4857da2e3ebdSchin 							{
4858da2e3ebdSchin 								m = 0;
4859da2e3ebdSchin 								s = e - 1;
4860da2e3ebdSchin 								w = y + n;
4861da2e3ebdSchin 								while (*++s)
4862da2e3ebdSchin 								{
4863da2e3ebdSchin 									if (*s == '*' || *s == '\a')
4864da2e3ebdSchin 									{
4865da2e3ebdSchin 										if (*s == '\a')
4866da2e3ebdSchin 											do
4867da2e3ebdSchin 											{
4868da2e3ebdSchin 												if (!*++s)
4869da2e3ebdSchin 												{
4870da2e3ebdSchin 													s--;
4871da2e3ebdSchin 													break;
4872da2e3ebdSchin 												}
4873da2e3ebdSchin 											} while (*s != '\a');
4874da2e3ebdSchin 										j = *(s + 1);
4875da2e3ebdSchin 										if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
4876da2e3ebdSchin 										{
4877da2e3ebdSchin 											while (*w)
4878da2e3ebdSchin 												w++;
4879da2e3ebdSchin 											m = 0;
4880da2e3ebdSchin 											break;
4881da2e3ebdSchin 										}
4882da2e3ebdSchin 										m = 1;
4883da2e3ebdSchin 									}
4884*b30d1939SAndy Fiddaman 									else if (*s == *w || SEP(*s) && SEP(*w))
4885da2e3ebdSchin 										w++;
4886da2e3ebdSchin 									else if (*w == 0)
4887da2e3ebdSchin 										break;
4888*b30d1939SAndy Fiddaman 									else if (!SEP(*s))
4889da2e3ebdSchin 									{
4890*b30d1939SAndy Fiddaman 										if (SEP(*w))
4891da2e3ebdSchin 										{
4892da2e3ebdSchin 											if (*++w == *s)
4893da2e3ebdSchin 											{
4894da2e3ebdSchin 												w++;
4895da2e3ebdSchin 												continue;
4896da2e3ebdSchin 											}
4897da2e3ebdSchin 										}
4898*b30d1939SAndy Fiddaman 										else if (w == y || SEP(*(w - 1)) || isupper(*(w - 1)) && islower(*w))
4899da2e3ebdSchin 											break;
4900*b30d1939SAndy Fiddaman 										for (q = s; *q && !SEP(*q) && *q != '|' && *q != '?' && *q != ']'; q++);
4901*b30d1939SAndy Fiddaman 										if (!SEP(*q))
4902da2e3ebdSchin 											break;
4903da2e3ebdSchin 										for (s = q; w > y && *w != *(s + 1); w--);
4904da2e3ebdSchin 									}
4905da2e3ebdSchin 									else if (*w != *(s + 1))
4906da2e3ebdSchin 										break;
4907da2e3ebdSchin 								}
4908da2e3ebdSchin 								if (!*w)
4909da2e3ebdSchin 									break;
4910da2e3ebdSchin 							}
4911da2e3ebdSchin 							if (*(s = skip(s, ':', '|', '?', 1, 0, 0, version)) != '|')
4912da2e3ebdSchin 								break;
4913da2e3ebdSchin 							w = y;
4914da2e3ebdSchin 						}
4915da2e3ebdSchin 						if (p)
4916da2e3ebdSchin 							s = p;
4917da2e3ebdSchin 						if (!*w)
4918da2e3ebdSchin 						{
4919da2e3ebdSchin 							if (n)
4920da2e3ebdSchin 								num = 0;
4921da2e3ebdSchin 							if (!(n = (m || *s == ':' || *s == '|' || *s == '?' || *s == ']' || *s == 0)) && x)
4922da2e3ebdSchin 							{
4923da2e3ebdSchin 								psp = pop(psp);
49243e14f97fSRoger A. Faulkner 								return opterror("?", 0, version, id, catalog);
4925da2e3ebdSchin 							}
4926da2e3ebdSchin 							for (x = k; *(f + 1) == '|' && (j = *(f + 2)) && j != '!' && j != '=' && j != ':' && j != '?' && j != ']'; f += 2);
4927da2e3ebdSchin 							if (*f == ':')
4928da2e3ebdSchin 							{
4929da2e3ebdSchin 								x = -1;
4930da2e3ebdSchin 								opt_info.option[1] = '-';
4931da2e3ebdSchin 								opt_info.option[2] = 0;
4932da2e3ebdSchin 							}
4933da2e3ebdSchin 							else if (*(f + 1) == ':' || *(f + 1) == '!' && *(f + 2) == ':')
4934da2e3ebdSchin 							{
4935da2e3ebdSchin 								opt_info.option[1] = x;
4936da2e3ebdSchin 								opt_info.option[2] = 0;
4937da2e3ebdSchin 							}
4938da2e3ebdSchin 							else
4939da2e3ebdSchin 							{
4940da2e3ebdSchin 								a = f;
4941da2e3ebdSchin 								if (*a == '=')
4942da2e3ebdSchin 									a++;
4943da2e3ebdSchin 								else
4944da2e3ebdSchin 								{
4945da2e3ebdSchin 									if (*(a + 1) == '!')
4946da2e3ebdSchin 										a++;
4947da2e3ebdSchin 									if (*(a + 1) == '=')
4948da2e3ebdSchin 										a += 2;
4949da2e3ebdSchin 								}
4950da2e3ebdSchin 								x = -strtol(a, &b, 0);
4951da2e3ebdSchin 								if ((b - a) > sizeof(opt_info.option) - 2)
4952da2e3ebdSchin 									b = a + sizeof(opt_info.option) - 2;
4953da2e3ebdSchin 								memcpy(&opt_info.option[1], a, b - a);
4954da2e3ebdSchin 								opt_info.option[b - a + 1] = 0;
4955da2e3ebdSchin 							}
4956da2e3ebdSchin 							b = e;
4957da2e3ebdSchin 							if (t)
4958da2e3ebdSchin 							{
4959da2e3ebdSchin 								s = t;
4960da2e3ebdSchin 								t = 0;
4961da2e3ebdSchin 							}
4962da2e3ebdSchin 							a = s = skip(s, 0, 0, 0, 1, 0, 0, version);
4963da2e3ebdSchin 							if (n)
4964da2e3ebdSchin 							{
4965da2e3ebdSchin 								w = y;
4966da2e3ebdSchin 								break;
4967da2e3ebdSchin 							}
4968da2e3ebdSchin 						}
4969da2e3ebdSchin 						w = y;
4970da2e3ebdSchin 					}
4971da2e3ebdSchin 					else if (k == c && prefix == 1)
4972da2e3ebdSchin 					{
4973da2e3ebdSchin 						w = 0;
4974da2e3ebdSchin 						opt_info.name[1] = c;
4975da2e3ebdSchin 						opt_info.name[2] = 0;
4976da2e3ebdSchin 						opt_info.offset = 2;
4977da2e3ebdSchin 						opt_info.index--;
4978da2e3ebdSchin 						break;
4979da2e3ebdSchin 					}
4980da2e3ebdSchin 					if (t)
4981da2e3ebdSchin 					{
4982da2e3ebdSchin 						s = t;
4983da2e3ebdSchin 						if (a)
4984da2e3ebdSchin 							a = t;
4985da2e3ebdSchin 					}
4986da2e3ebdSchin 				}
4987*b30d1939SAndy Fiddaman 			disable:
4988da2e3ebdSchin 				s = skip(s, 0, 0, 0, 1, 0, 1, version);
4989da2e3ebdSchin 				if (*s == GO)
4990da2e3ebdSchin 					s = skip(s + 1, 0, 0, 0, 0, 1, 1, version);
4991da2e3ebdSchin 				if (cache)
4992da2e3ebdSchin 				{
4993da2e3ebdSchin 					m = OPT_cache_flag;
4994da2e3ebdSchin 					v = s;
4995da2e3ebdSchin 					if (*v == '#')
4996da2e3ebdSchin 					{
4997da2e3ebdSchin 						v++;
4998da2e3ebdSchin 						m |= OPT_cache_numeric;
4999da2e3ebdSchin 					}
5000da2e3ebdSchin 					else if (*v == ':')
5001da2e3ebdSchin 					{
5002da2e3ebdSchin 						v++;
5003da2e3ebdSchin 						m |= OPT_cache_string;
5004da2e3ebdSchin 					}
5005da2e3ebdSchin 					if (*v == '?')
5006da2e3ebdSchin 					{
5007da2e3ebdSchin 						v++;
5008da2e3ebdSchin 						m |= OPT_cache_optional;
5009da2e3ebdSchin 					}
5010da2e3ebdSchin 					else if (*v == *(v - 1))
5011da2e3ebdSchin 						v++;
5012da2e3ebdSchin 					if (*(v = next(v, version)) == '[')
5013da2e3ebdSchin 						v = skip(v + 1, 0, 0, 0, 1, 0, 1, version);
5014da2e3ebdSchin 					if (*v != GO)
5015da2e3ebdSchin 					{
5016da2e3ebdSchin 						v = f;
5017da2e3ebdSchin 						for (;;)
5018da2e3ebdSchin 						{
5019da2e3ebdSchin 							if (isdigit(*f) && isdigit(*(f + 1)))
5020da2e3ebdSchin 								while (isdigit(*(f + 1)))
5021da2e3ebdSchin 									f++;
5022da2e3ebdSchin 							else if (*(f + 1) == '=')
5023da2e3ebdSchin 								break;
5024da2e3ebdSchin 							else
5025da2e3ebdSchin 								cache->flags[map[*f]] = m;
5026da2e3ebdSchin 							j = 0;
5027da2e3ebdSchin 							while (*(f + 1) == '|')
5028da2e3ebdSchin 							{
5029da2e3ebdSchin 								f += 2;
5030da2e3ebdSchin 								if (!(j = *f) || j == '!' || j == '=' || j == ':' || j == '?' || j == ']')
5031da2e3ebdSchin 									break;
5032da2e3ebdSchin 								cache->flags[map[j]] = m;
5033da2e3ebdSchin 							}
5034da2e3ebdSchin 							if (j != '!' || (m & OPT_cache_invert))
5035da2e3ebdSchin 								break;
5036da2e3ebdSchin 							f = v;
5037da2e3ebdSchin 							m |= OPT_cache_invert;
5038da2e3ebdSchin 						}
5039da2e3ebdSchin 					}
5040da2e3ebdSchin 				}
5041da2e3ebdSchin 				else
5042da2e3ebdSchin 				{
5043da2e3ebdSchin 					m = 0;
5044da2e3ebdSchin 					if (!w)
5045da2e3ebdSchin 					{
5046da2e3ebdSchin 						if (isdigit(*f) && isdigit(*(f + 1)))
5047da2e3ebdSchin 							k = -1;
5048da2e3ebdSchin 						if (c == k)
5049da2e3ebdSchin 							m = 1;
5050da2e3ebdSchin 						while (*(f + 1) == '|')
5051da2e3ebdSchin 						{
5052da2e3ebdSchin 							f += 2;
5053da2e3ebdSchin 							if (!(j = *f))
5054da2e3ebdSchin 							{
5055da2e3ebdSchin 								m = 0;
5056da2e3ebdSchin 								break;
5057da2e3ebdSchin 							}
5058da2e3ebdSchin 							else if (j == c)
5059da2e3ebdSchin 								m = 1;
5060da2e3ebdSchin 							else if (j == '!' || j == '=' || j == ':' || j == '?' || j == ']')
5061da2e3ebdSchin 								break;
5062da2e3ebdSchin 						}
5063da2e3ebdSchin 					}
5064da2e3ebdSchin 					if (m)
5065da2e3ebdSchin 					{
5066da2e3ebdSchin 						s--;
5067da2e3ebdSchin 						if (*++f == '!')
5068da2e3ebdSchin 						{
5069da2e3ebdSchin 							f++;
5070da2e3ebdSchin 							num = 0;
5071da2e3ebdSchin 						}
5072da2e3ebdSchin 						if (*f == '=')
5073da2e3ebdSchin 						{
5074da2e3ebdSchin 							c = -strtol(++f, &b, 0);
5075da2e3ebdSchin 							if ((b - f) > sizeof(opt_info.option) - 2)
5076da2e3ebdSchin 								b = f + sizeof(opt_info.option) - 2;
5077da2e3ebdSchin 							memcpy(&opt_info.option[1], f, b - f);
5078da2e3ebdSchin 							opt_info.option[b - f + 1] = 0;
5079da2e3ebdSchin 						}
5080da2e3ebdSchin 						else
5081da2e3ebdSchin 							c = k;
5082da2e3ebdSchin 						break;
5083da2e3ebdSchin 					}
5084da2e3ebdSchin 				}
5085da2e3ebdSchin 				if (*s == '#')
5086da2e3ebdSchin 				{
5087da2e3ebdSchin 					if (!numopt && s > opts)
5088da2e3ebdSchin 					{
5089da2e3ebdSchin 						numopt = s - 1;
5090da2e3ebdSchin 						numchr = k;
5091da2e3ebdSchin 						if (*f == ':')
5092da2e3ebdSchin 							numchr = -1;
5093da2e3ebdSchin 						else if (*(f + 1) != ':' && *(f + 1) != '!' && *(f + 1) != ']')
5094da2e3ebdSchin 						{
5095da2e3ebdSchin 							a = f;
5096da2e3ebdSchin 							if (*a == '=')
5097da2e3ebdSchin 								a++;
5098da2e3ebdSchin 							else
5099da2e3ebdSchin 							{
5100da2e3ebdSchin 								if (*(a + 1) == '!')
5101da2e3ebdSchin 									a++;
5102da2e3ebdSchin 								if (*(a + 1) == '=')
5103da2e3ebdSchin 									a += 2;
5104da2e3ebdSchin 							}
5105da2e3ebdSchin 							numchr = -strtol(a, NiL, 0);
5106da2e3ebdSchin 						}
5107da2e3ebdSchin 					}
5108da2e3ebdSchin 				}
5109da2e3ebdSchin 				else if (*s != ':')
5110da2e3ebdSchin 					continue;
5111da2e3ebdSchin 			}
5112da2e3ebdSchin 			else if (*s == ']')
5113da2e3ebdSchin 			{
5114da2e3ebdSchin 				s++;
5115da2e3ebdSchin 				continue;
5116da2e3ebdSchin 			}
5117da2e3ebdSchin 			else if (*s == '#')
5118da2e3ebdSchin 			{
5119da2e3ebdSchin 				if (!numopt && s > opts)
5120da2e3ebdSchin 					numchr = *(numopt = s - 1);
5121da2e3ebdSchin 			}
5122da2e3ebdSchin 			else if (*s != ':')
5123da2e3ebdSchin 			{
5124da2e3ebdSchin 				if (cache)
5125da2e3ebdSchin 				{
5126da2e3ebdSchin 					m = OPT_cache_flag;
5127da2e3ebdSchin 					if (*(s + 1) == '#')
5128da2e3ebdSchin 					{
5129da2e3ebdSchin 						m |= OPT_cache_numeric;
5130da2e3ebdSchin 						if (*(s + 2) == '?')
5131da2e3ebdSchin 							m |= OPT_cache_optional;
5132da2e3ebdSchin 					}
5133da2e3ebdSchin 					else if (*(s + 1) == ':')
5134da2e3ebdSchin 					{
5135da2e3ebdSchin 						m |= OPT_cache_string;
5136da2e3ebdSchin 						if (*(s + 2) == '?')
5137da2e3ebdSchin 							m |= OPT_cache_optional;
5138da2e3ebdSchin 					}
5139da2e3ebdSchin 					cache->flags[map[*s]] = m;
5140da2e3ebdSchin 				}
5141da2e3ebdSchin 				s++;
5142da2e3ebdSchin 				continue;
5143da2e3ebdSchin 			}
5144da2e3ebdSchin 			message((-21, "optget: opt %s", show(s)));
5145da2e3ebdSchin 			if (*++s == '?' || *s == *(s - 1))
5146da2e3ebdSchin 				s++;
5147da2e3ebdSchin 			if (*(s = next(s, version)) == '[')
5148da2e3ebdSchin 			{
5149da2e3ebdSchin 				s = skip(s + 1, 0, 0, 0, 1, 0, 1, version);
5150da2e3ebdSchin 				if (*s == GO)
5151da2e3ebdSchin 					s = skip(s + 1, 0, 0, 0, 0, 1, 1, version);
5152da2e3ebdSchin 			}
515334f9b3eeSRoland Mainz 			message((-21, "optget: opt %s", show(s)));
5154da2e3ebdSchin 		}
5155da2e3ebdSchin 		if (w && x)
5156da2e3ebdSchin 		{
5157da2e3ebdSchin 			s = skip(b, '|', '?', 0, 1, 0, 0, version);
5158da2e3ebdSchin 			if (v && (a == 0 || *a == 0 || *(a + 1) != ':' && *(a + 1) != '#') && (*v == '0' || *v == '1') && !*(v + 1))
5159da2e3ebdSchin 			{
5160da2e3ebdSchin 				if (*v == '0')
5161da2e3ebdSchin 					num = !num;
5162da2e3ebdSchin 				v = 0;
5163da2e3ebdSchin 			}
5164da2e3ebdSchin 			if ((s - b) >= elementsof(opt_info.name))
5165da2e3ebdSchin 				s = b + elementsof(opt_info.name) - 1;
5166da2e3ebdSchin 			for (;;)
5167da2e3ebdSchin 			{
5168da2e3ebdSchin 				if (b >= s)
5169da2e3ebdSchin 				{
5170da2e3ebdSchin 					*w = 0;
5171da2e3ebdSchin 					break;
5172da2e3ebdSchin 				}
5173da2e3ebdSchin 				if (*b == '*')
5174da2e3ebdSchin 					break;
5175da2e3ebdSchin 				*w++ = *b++;
5176da2e3ebdSchin 			}
5177da2e3ebdSchin 			if (!num && v)
51783e14f97fSRoger A. Faulkner 				return opterror(no ? "!" : "=", 0, version, id, catalog);
5179da2e3ebdSchin 			w = &opt_info.name[prefix];
5180da2e3ebdSchin 			c = x;
5181da2e3ebdSchin 			s = a;
5182da2e3ebdSchin 		}
5183da2e3ebdSchin 	}
5184da2e3ebdSchin 	if (!*s)
5185da2e3ebdSchin 	{
5186da2e3ebdSchin 		if (w)
5187da2e3ebdSchin 		{
5188da2e3ebdSchin 			if (hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), w))
5189da2e3ebdSchin 			{
5190da2e3ebdSchin 				if (!v)
5191da2e3ebdSchin 					v = (char*)hp->name;
5192da2e3ebdSchin 				goto help;
5193da2e3ebdSchin 			}
5194da2e3ebdSchin 			if (!v)
5195da2e3ebdSchin 			{
5196da2e3ebdSchin 				v = opt_info.name;
5197da2e3ebdSchin 				goto help;
5198da2e3ebdSchin 			}
5199da2e3ebdSchin 		}
52007c2fbfb3SApril Chin 		if (w || !isdigit(c) || !numopt || !(pass->flags & OPT_numeric))
5201da2e3ebdSchin 		{
5202da2e3ebdSchin 			pop(psp);
52033e14f97fSRoger A. Faulkner 			return opterror("", 0, version, id, catalog);
5204da2e3ebdSchin 		}
5205da2e3ebdSchin 		s = numopt;
5206da2e3ebdSchin 		c = opt_info.option[1] = numchr;
5207da2e3ebdSchin 		opt_info.offset--;
5208da2e3ebdSchin 	}
5209da2e3ebdSchin 	opt_info.arg = 0;
5210da2e3ebdSchin 
5211da2e3ebdSchin 	/*
5212da2e3ebdSchin 	 * this is a ksh getopts workaround
5213da2e3ebdSchin 	 */
5214da2e3ebdSchin 
5215da2e3ebdSchin 	if (opt_info.num != LONG_MIN)
521634f9b3eeSRoland Mainz 		opt_info.num = (long)(opt_info.number = num);
5217da2e3ebdSchin 	if ((n = *++s == '#') || *s == ':' || w && !nov && v && (optnumber(v, &e, NiL), n = !*e))
5218da2e3ebdSchin 	{
5219da2e3ebdSchin 		if (w)
5220da2e3ebdSchin 		{
5221da2e3ebdSchin 			if (nov)
5222da2e3ebdSchin 			{
5223da2e3ebdSchin 				if (v)
5224da2e3ebdSchin 				{
5225da2e3ebdSchin 					pop(psp);
52263e14f97fSRoger A. Faulkner 					return opterror("!", 0, version, id, catalog);
5227da2e3ebdSchin 				}
522834f9b3eeSRoland Mainz 				opt_info.num = (long)(opt_info.number = 0);
5229da2e3ebdSchin 			}
5230da2e3ebdSchin 			else
5231da2e3ebdSchin 			{
5232da2e3ebdSchin 				if (!v && *(s + 1) != '?' && (v = argv[opt_info.index]))
5233da2e3ebdSchin 				{
5234da2e3ebdSchin 					opt_info.index++;
5235da2e3ebdSchin 					opt_info.offset = 0;
5236da2e3ebdSchin 				}
5237da2e3ebdSchin 				if (!(opt_info.arg = v) || (*v == '0' || *v == '1') && !*(v + 1))
5238da2e3ebdSchin 				{
5239da2e3ebdSchin 					if (*(s + 1) != '?')
5240da2e3ebdSchin 					{
5241da2e3ebdSchin 						if (!opt_info.arg)
5242da2e3ebdSchin 						{
5243da2e3ebdSchin 							pop(psp);
52443e14f97fSRoger A. Faulkner 							return opterror(s, 0, version, id, catalog);
5245da2e3ebdSchin 						}
5246da2e3ebdSchin 					}
5247da2e3ebdSchin 					else if (*(t = next(s + 2, version)) == '[')
5248da2e3ebdSchin 						while (*(t = skip(t, ':', 0, 0, 1, 0, 0, version)) == ':')
5249da2e3ebdSchin 							if (*++t == '!')
5250da2e3ebdSchin 							{
5251da2e3ebdSchin 								if (!v || *v == '1')
5252da2e3ebdSchin 								{
5253da2e3ebdSchin 									e = skip(t, ':', '?', ']', 1, 0, 0, version);
5254da2e3ebdSchin 									opt_info.arg = sfprints("%-.*s", e - t - 1, t + 1);
5255da2e3ebdSchin 								}
5256da2e3ebdSchin 								else
5257da2e3ebdSchin 								{
5258da2e3ebdSchin 									opt_info.arg = 0;
525934f9b3eeSRoland Mainz 									opt_info.num = (long)(opt_info.number = 0);
5260da2e3ebdSchin 								}
5261da2e3ebdSchin 								break;
5262da2e3ebdSchin 							}
5263da2e3ebdSchin 				}
5264da2e3ebdSchin 				if (opt_info.arg && n)
5265da2e3ebdSchin 				{
5266da2e3ebdSchin 					opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
5267da2e3ebdSchin 					if (err || e == opt_info.arg)
5268da2e3ebdSchin 					{
5269da2e3ebdSchin 						pop(psp);
52703e14f97fSRoger A. Faulkner 						return opterror(s, err, version, id, catalog);
5271da2e3ebdSchin 					}
5272da2e3ebdSchin 				}
5273da2e3ebdSchin 			}
5274da2e3ebdSchin 			goto optarg;
5275da2e3ebdSchin 		}
5276da2e3ebdSchin 		else if (*(opt_info.arg = &argv[opt_info.index++][opt_info.offset]))
5277da2e3ebdSchin 		{
5278da2e3ebdSchin 			if (*s == '#')
5279da2e3ebdSchin 			{
5280da2e3ebdSchin 				opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
5281da2e3ebdSchin 				if (err || e == opt_info.arg)
5282da2e3ebdSchin 				{
5283da2e3ebdSchin 					if (!err && *(s + 1) == '?')
5284da2e3ebdSchin 					{
5285da2e3ebdSchin 						opt_info.arg = 0;
5286da2e3ebdSchin 						opt_info.index--;
5287da2e3ebdSchin 					}
5288da2e3ebdSchin 					else
5289da2e3ebdSchin 					{
5290da2e3ebdSchin 						opt_info.offset = 0;
52913e14f97fSRoger A. Faulkner 						c = opterror(s, err, version, id, catalog);
5292da2e3ebdSchin 					}
5293da2e3ebdSchin 					pop(psp);
5294da2e3ebdSchin 					return c;
5295da2e3ebdSchin 				}
5296da2e3ebdSchin 				else if (*e)
5297da2e3ebdSchin 				{
5298da2e3ebdSchin 					opt_info.offset += e - opt_info.arg;
5299da2e3ebdSchin 					opt_info.index--;
5300da2e3ebdSchin 					pop(psp);
5301da2e3ebdSchin 					return c;
5302da2e3ebdSchin 				}
5303da2e3ebdSchin 			}
5304da2e3ebdSchin 		}
5305da2e3ebdSchin 		else if (opt_info.arg = argv[opt_info.index])
5306da2e3ebdSchin 		{
5307da2e3ebdSchin 			opt_info.index++;
5308da2e3ebdSchin 			if (*(s + 1) == '?' && (*opt_info.arg == '-' || (pass->flags & OPT_plus) && *opt_info.arg == '+') && *(opt_info.arg + 1))
5309da2e3ebdSchin 			{
5310*b30d1939SAndy Fiddaman 				opt_info.num = (long)(opt_info.number = 0);
5311da2e3ebdSchin 				opt_info.index--;
5312da2e3ebdSchin 				opt_info.arg = 0;
5313da2e3ebdSchin 			}
5314da2e3ebdSchin 			else if (*s == '#')
5315da2e3ebdSchin 			{
5316da2e3ebdSchin 				opt_info.num = (long)(opt_info.number = optnumber(opt_info.arg, &e, &err));
5317da2e3ebdSchin 				if (err || *e)
5318da2e3ebdSchin 				{
5319da2e3ebdSchin 					if (!err && *(s + 1) == '?')
5320da2e3ebdSchin 					{
5321da2e3ebdSchin 						opt_info.arg = 0;
5322da2e3ebdSchin 						opt_info.index--;
5323da2e3ebdSchin 					}
5324da2e3ebdSchin 					else
5325da2e3ebdSchin 					{
5326da2e3ebdSchin 						pop(psp);
5327da2e3ebdSchin 						opt_info.offset = 0;
53283e14f97fSRoger A. Faulkner 						return opterror(s, err, version, id, catalog);
5329da2e3ebdSchin 					}
5330da2e3ebdSchin 				}
5331da2e3ebdSchin 			}
5332da2e3ebdSchin 		}
5333da2e3ebdSchin 		else if (*(s + 1) != '?')
5334da2e3ebdSchin 		{
5335da2e3ebdSchin 			opt_info.index--;
5336da2e3ebdSchin 			pop(psp);
53373e14f97fSRoger A. Faulkner 			return opterror(s, 0, version, id, catalog);
5338da2e3ebdSchin 		}
5339da2e3ebdSchin 		opt_info.offset = 0;
5340da2e3ebdSchin 	optarg:
5341da2e3ebdSchin 		if (*s == ':' && *(s = skip(s, 0, 0, 0, 1, 0, 1, version)) == GO && *(s = next(s + 1, version)) == '[' && isalnum(*(s + 1)))
5342da2e3ebdSchin 		{
5343da2e3ebdSchin 			x = 0;
5344da2e3ebdSchin 			if (opt_info.arg)
5345da2e3ebdSchin 			{
5346da2e3ebdSchin 				do
5347da2e3ebdSchin 				{
5348da2e3ebdSchin 					w = y = opt_info.arg;
5349da2e3ebdSchin 					f = s = next(s + 1, version);
5350da2e3ebdSchin 					k = *f;
5351da2e3ebdSchin 					if (k == *w && isalpha(k) && !*(w + 1))
5352da2e3ebdSchin 					{
5353da2e3ebdSchin 						x = k;
5354da2e3ebdSchin 						break;
5355da2e3ebdSchin 					}
5356da2e3ebdSchin 					if (*s == '+' || *s == '-')
5357da2e3ebdSchin 						continue;
5358da2e3ebdSchin 					else if (*s == '[' || version < 1)
5359da2e3ebdSchin 						continue;
5360da2e3ebdSchin 					else
5361da2e3ebdSchin 					{
5362da2e3ebdSchin 						if (*s != ':')
5363da2e3ebdSchin 							s = skip(s, ':', '?', 0, 1, 0, 0, version);
5364da2e3ebdSchin 						if (*s == ':')
5365da2e3ebdSchin 						{
5366da2e3ebdSchin 							if (catalog)
5367da2e3ebdSchin 							{
5368da2e3ebdSchin 								p = skip(s + 1, '?', 0, 0, 1, 0, 0, version);
5369da2e3ebdSchin 								e = sfprints("%-.*s", p - (s + 1), s + 1);
53703e14f97fSRoger A. Faulkner 								b = T(id, catalog, e);
5371da2e3ebdSchin 								if (b == e)
5372da2e3ebdSchin 									p = 0;
5373da2e3ebdSchin 								else
5374da2e3ebdSchin 								{
5375da2e3ebdSchin 									sfprintf(xp, ":%s|%s?", b, e);
5376da2e3ebdSchin 									if (!(s = sfstruse(xp)))
5377da2e3ebdSchin 										goto nospace;
5378da2e3ebdSchin 								}
5379da2e3ebdSchin 							}
5380da2e3ebdSchin 							else
5381da2e3ebdSchin 								p = 0;
5382da2e3ebdSchin 							for (;;)
5383da2e3ebdSchin 							{
5384da2e3ebdSchin 								n = m = 0;
5385da2e3ebdSchin 								e = s + 1;
5386da2e3ebdSchin 								while (*++s)
5387da2e3ebdSchin 								{
5388da2e3ebdSchin 									if (*s == '*' || *s == '\a')
5389da2e3ebdSchin 									{
5390da2e3ebdSchin 										if (*s == '\a')
5391da2e3ebdSchin 											do
5392da2e3ebdSchin 											{
5393da2e3ebdSchin 												if (!*++s)
5394da2e3ebdSchin 												{
5395da2e3ebdSchin 													s--;
5396da2e3ebdSchin 													break;
5397da2e3ebdSchin 												}
5398da2e3ebdSchin 											} while (*s != '\a');
5399da2e3ebdSchin 										j = *(s + 1);
5400da2e3ebdSchin 										if (j == ':' || j == '|' || j == '?' || j == ']' || j == 0)
5401da2e3ebdSchin 										{
5402da2e3ebdSchin 											while (*w)
5403da2e3ebdSchin 												w++;
5404da2e3ebdSchin 											m = 0;
5405da2e3ebdSchin 											break;
5406da2e3ebdSchin 										}
5407da2e3ebdSchin 										m = 1;
5408da2e3ebdSchin 									}
5409*b30d1939SAndy Fiddaman 									else if (*s == *w || SEP(*s) && SEP(*w))
5410da2e3ebdSchin 										w++;
5411da2e3ebdSchin 									else if (*w == 0)
5412da2e3ebdSchin 										break;
5413*b30d1939SAndy Fiddaman 									else if (!SEP(*s))
5414da2e3ebdSchin 									{
5415*b30d1939SAndy Fiddaman 										if (SEP(*w))
5416da2e3ebdSchin 										{
5417da2e3ebdSchin 											if (*++w == *s)
5418da2e3ebdSchin 											{
5419da2e3ebdSchin 												w++;
5420da2e3ebdSchin 												continue;
5421da2e3ebdSchin 											}
5422da2e3ebdSchin 										}
5423*b30d1939SAndy Fiddaman 										else if (w == y || SEP(*(w - 1)) || isupper(*(w - 1)) && islower(*w))
5424da2e3ebdSchin 											break;
5425*b30d1939SAndy Fiddaman 										for (q = s; *q && !SEP(*q) && *q != '|' && *q != '?' && *q != ']'; q++);
5426*b30d1939SAndy Fiddaman 										if (!SEP(*q))
5427da2e3ebdSchin 											break;
5428da2e3ebdSchin 										for (s = q; w > y && *w != *(s + 1); w--);
5429da2e3ebdSchin 									}
5430da2e3ebdSchin 									else if (*w != *(s + 1))
5431da2e3ebdSchin 										break;
5432da2e3ebdSchin 								}
5433da2e3ebdSchin 								if (!*w)
5434da2e3ebdSchin 								{
5435da2e3ebdSchin 									nov = 0;
5436da2e3ebdSchin 									break;
5437da2e3ebdSchin 								}
5438da2e3ebdSchin 								if (*(s = skip(s, ':', '|', '?', 1, 0, 0, version)) != '|')
5439da2e3ebdSchin 									break;
5440da2e3ebdSchin 								w = y;
5441da2e3ebdSchin 							}
5442da2e3ebdSchin 							if (p)
5443da2e3ebdSchin 								s = p;
5444da2e3ebdSchin 							if (!*w)
5445da2e3ebdSchin 							{
5446da2e3ebdSchin 								if (n)
5447da2e3ebdSchin 									num = 0;
5448da2e3ebdSchin 								if (!(n = (m || *s == ':' || *s == '|' || *s == '?' || *s == ']')) && x)
5449da2e3ebdSchin 								{
5450da2e3ebdSchin 									pop(psp);
54513e14f97fSRoger A. Faulkner 									return opterror("&", 0, version, id, catalog);
5452da2e3ebdSchin 								}
5453da2e3ebdSchin 								for (x = k; *(f + 1) == '|' && (j = *(f + 2)) && j != '!' && j != '=' && j != ':' && j != '?' && j != ']'; f += 2);
5454da2e3ebdSchin 								if (*f == ':')
5455da2e3ebdSchin 									x = -1;
5456da2e3ebdSchin 								else if (*(f + 1) == ':' || *(f + 1) == '!' && *(f + 2) == ':')
5457da2e3ebdSchin 									/* ok */;
5458da2e3ebdSchin 								else
5459da2e3ebdSchin 								{
5460da2e3ebdSchin 									a = f;
5461da2e3ebdSchin 									if (*a == '=')
5462da2e3ebdSchin 										a++;
5463da2e3ebdSchin 									else
5464da2e3ebdSchin 									{
5465da2e3ebdSchin 										if (*(a + 1) == '!')
5466da2e3ebdSchin 											a++;
5467da2e3ebdSchin 										if (*(a + 1) == '=')
5468da2e3ebdSchin 											a += 2;
5469da2e3ebdSchin 									}
5470da2e3ebdSchin 									x = -strtol(a, &b, 0);
5471da2e3ebdSchin 								}
5472da2e3ebdSchin 								b = e;
5473da2e3ebdSchin 								a = s = skip(s, 0, 0, 0, 1, 0, 0, version);
5474da2e3ebdSchin 								if (n)
5475da2e3ebdSchin 									break;
5476da2e3ebdSchin 							}
5477da2e3ebdSchin 						}
5478da2e3ebdSchin 					}
5479da2e3ebdSchin 				} while (*(s = skip(s, 0, 0, 0, 1, 0, 1, version)) == '[');
548034f9b3eeSRoland Mainz 				if (!(opt_info.num = (long)(opt_info.number = x)))
5481da2e3ebdSchin 				{
5482da2e3ebdSchin 					pop(psp);
54833e14f97fSRoger A. Faulkner 					return opterror("*", 0, version, id, catalog);
5484da2e3ebdSchin 				}
5485da2e3ebdSchin 			}
5486da2e3ebdSchin 		}
5487da2e3ebdSchin 	}
5488da2e3ebdSchin 	else if (w && v)
5489da2e3ebdSchin 	{
5490da2e3ebdSchin 		pop(psp);
54913e14f97fSRoger A. Faulkner 		return opterror("=", 0, version, id, catalog);
5492da2e3ebdSchin 	}
5493da2e3ebdSchin 	else
5494da2e3ebdSchin 	{
549534f9b3eeSRoland Mainz 		opt_info.num = (long)(opt_info.number = num);
5496da2e3ebdSchin 		if (!w && !argv[opt_info.index][opt_info.offset])
5497da2e3ebdSchin 		{
5498da2e3ebdSchin 			opt_info.offset = 0;
5499da2e3ebdSchin 			opt_info.index++;
5500da2e3ebdSchin 		}
5501da2e3ebdSchin 	}
5502da2e3ebdSchin 	pop(psp);
5503da2e3ebdSchin 	return c;
5504da2e3ebdSchin  help:
5505da2e3ebdSchin 	if (v && *v == '?' && *(v + 1) == '?' && *(v + 2))
5506da2e3ebdSchin 	{
5507da2e3ebdSchin 		s = v + 2;
5508da2e3ebdSchin 		if ((s[0] == 'n' || s[0] == 'N') && (s[1] == 'o' || s[1] == 'O'))
5509da2e3ebdSchin 		{
5510da2e3ebdSchin 			s += 2;
5511da2e3ebdSchin 			n = -1;
5512da2e3ebdSchin 		}
5513da2e3ebdSchin 		else
5514da2e3ebdSchin 			n = 1;
5515da2e3ebdSchin 		if (hp = (Help_t*)search(styles, elementsof(styles), sizeof(styles[0]), s))
5516da2e3ebdSchin 		{
5517da2e3ebdSchin 			if (hp->style < STYLE_man || !(s = argv[opt_info.index]) || s[0] != '-' || s[1] != '-' || !s[2])
5518da2e3ebdSchin 			{
5519da2e3ebdSchin 				opt_info.arg = sfprints("\fversion=%d", version);
5520da2e3ebdSchin 				pop(psp);
5521da2e3ebdSchin 				return '?';
5522da2e3ebdSchin 			}
5523*b30d1939SAndy Fiddaman 			state.force = hp->style;
5524*b30d1939SAndy Fiddaman 		}
5525*b30d1939SAndy Fiddaman 		else if (match(s, "CONFORMANCE", -1, ID, NiL))
5526*b30d1939SAndy Fiddaman 		{
5527*b30d1939SAndy Fiddaman 			opt_info.arg = sfprints("\f%s", conformance(w, 0));
5528*b30d1939SAndy Fiddaman 			pop(psp);
5529*b30d1939SAndy Fiddaman 			return '?';
5530da2e3ebdSchin 		}
55313e14f97fSRoger A. Faulkner 		else if (match(s, "ESC", -1, ID, NiL) || match(s, "EMPHASIS", -1, ID, NiL))
5532*b30d1939SAndy Fiddaman 			state.emphasis = n;
5533*b30d1939SAndy Fiddaman 		else if (match(s, "MAN", -1, ID, NiL))
5534*b30d1939SAndy Fiddaman 		{
5535*b30d1939SAndy Fiddaman 			opt_info.arg = sfprints("\f%s", secname(*w != '?' ? w : pass->section));
5536*b30d1939SAndy Fiddaman 			pop(psp);
5537*b30d1939SAndy Fiddaman 			return '?';
5538*b30d1939SAndy Fiddaman 		}
55393e14f97fSRoger A. Faulkner 		else if (match(s, "PREFORMAT", -1, ID, NiL))
5540*b30d1939SAndy Fiddaman 			state.flags |= OPT_preformat;
5541*b30d1939SAndy Fiddaman 		else if (match(s, "SECTION", -1, ID, NiL))
5542*b30d1939SAndy Fiddaman 		{
5543*b30d1939SAndy Fiddaman 			opt_info.arg = sfprints("\f%s", pass->section);
5544*b30d1939SAndy Fiddaman 			pop(psp);
5545*b30d1939SAndy Fiddaman 			return '?';
5546*b30d1939SAndy Fiddaman 		}
55473e14f97fSRoger A. Faulkner 		else if (match(s, "TEST", -1, ID, NiL))
5548da2e3ebdSchin 		{
5549*b30d1939SAndy Fiddaman 			state.width = OPT_WIDTH;
5550*b30d1939SAndy Fiddaman 			state.emphasis = 1;
5551da2e3ebdSchin 		}
5552da2e3ebdSchin 		else
5553da2e3ebdSchin 		{
5554da2e3ebdSchin 			pop(psp);
55553e14f97fSRoger A. Faulkner 			return opterror(v, 0, version, id, catalog);
5556da2e3ebdSchin 		}
5557da2e3ebdSchin 		psp = pop(psp);
5558*b30d1939SAndy Fiddaman 		if (argv == state.strv)
5559da2e3ebdSchin 			return '#';
5560da2e3ebdSchin 		goto again;
5561da2e3ebdSchin 	}
5562da2e3ebdSchin 	if ((opt_info.arg = opthelp(NiL, v)) == (char*)unknown)
5563da2e3ebdSchin 	{
5564da2e3ebdSchin 		pop(psp);
55653e14f97fSRoger A. Faulkner 		return opterror(v, 0, version, id, catalog);
5566da2e3ebdSchin 	}
5567da2e3ebdSchin 	pop(psp);
5568da2e3ebdSchin 	return '?';
5569da2e3ebdSchin  nospace:
5570da2e3ebdSchin 	pop(psp);
55713e14f97fSRoger A. Faulkner 	return opterror(NiL, 0, 0, NiL, NiL);
5572da2e3ebdSchin }
5573da2e3ebdSchin 
5574da2e3ebdSchin /*
5575da2e3ebdSchin  * parse long options with 0,1,2 leading '-' or '+' from string and pass to optget()
5576da2e3ebdSchin  * syntax is the unquoted
5577da2e3ebdSchin  *
5578da2e3ebdSchin  *	<length> [-|+|--|++]<name>[[-+:|&=]=<value>\n (or \0 for the last)
5579da2e3ebdSchin  *
5580da2e3ebdSchin  * or the quoted
5581da2e3ebdSchin  *
5582da2e3ebdSchin  *	[-|+|--|++][no]name[[-+:|&=]=['"{(]value[)}"']][, ]...
5583da2e3ebdSchin  *
5584da2e3ebdSchin  * with \x escapes passed to chresc()
5585da2e3ebdSchin  *
5586da2e3ebdSchin  * return '#' for `label:', with opt_info.name==label
5587da2e3ebdSchin  * str[opt_info.offset]	next arg
5588da2e3ebdSchin  *
5589da2e3ebdSchin  *	optstr(s, 0)
5590da2e3ebdSchin  *		return '-' if arg, 0 otherwise
5591da2e3ebdSchin  *	optstr(0, opts)
5592da2e3ebdSchin  *		use previous parsed str
5593da2e3ebdSchin  */
5594da2e3ebdSchin 
5595da2e3ebdSchin int
optstr(const char * str,const char * opts)5596da2e3ebdSchin optstr(const char* str, const char* opts)
5597da2e3ebdSchin {
5598da2e3ebdSchin 	register char*		s = (char*)str;
5599da2e3ebdSchin 	register Sfio_t*	mp;
5600da2e3ebdSchin 	register int		c;
5601da2e3ebdSchin 	register int		ql;
5602da2e3ebdSchin 	register int		qr;
5603da2e3ebdSchin 	register int		qc;
5604da2e3ebdSchin 	int			v;
5605da2e3ebdSchin 	char*			e;
5606da2e3ebdSchin 
5607da2e3ebdSchin  again:
5608da2e3ebdSchin 	if (s)
5609da2e3ebdSchin 	{
5610*b30d1939SAndy Fiddaman 		if (!(mp = state.strp) && !(mp = state.strp = sfstropen()))
5611da2e3ebdSchin 			return 0;
5612*b30d1939SAndy Fiddaman 		if (state.str != s)
5613*b30d1939SAndy Fiddaman 			state.str = s;
5614da2e3ebdSchin 		else if (opt_info.index == 1)
5615da2e3ebdSchin 			s += opt_info.offset;
5616da2e3ebdSchin 		while (*s == ',' || *s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')
5617da2e3ebdSchin 			s++;
5618da2e3ebdSchin 		if (!*s)
5619da2e3ebdSchin 		{
5620*b30d1939SAndy Fiddaman 			state.str = 0;
5621da2e3ebdSchin 			return 0;
5622da2e3ebdSchin 		}
5623da2e3ebdSchin 		if (*s == '-' || *s == '+')
5624da2e3ebdSchin 		{
5625da2e3ebdSchin 			c = *s++;
5626da2e3ebdSchin 			sfputc(mp, c);
5627da2e3ebdSchin 			if (*s == c)
5628da2e3ebdSchin 			{
5629da2e3ebdSchin 				sfputc(mp, c);
5630da2e3ebdSchin 				s++;
5631da2e3ebdSchin 			}
5632da2e3ebdSchin 		}
5633da2e3ebdSchin 		else
5634da2e3ebdSchin 		{
5635da2e3ebdSchin 			sfputc(mp, '-');
5636da2e3ebdSchin 			sfputc(mp, '-');
5637da2e3ebdSchin 		}
5638da2e3ebdSchin 		if (isdigit(*s) && (v = (int)strtol(s, &e, 10)) > 1 && isspace(*e) && --v <= strlen(s) && (s[v] == 0 || s[v] == '\n'))
5639da2e3ebdSchin 		{
5640da2e3ebdSchin 			s += v;
5641da2e3ebdSchin 			while (isspace(*++e));
5642da2e3ebdSchin 			sfwrite(mp, e, s - e);
5643da2e3ebdSchin 		}
5644da2e3ebdSchin 		else
5645da2e3ebdSchin 		{
5646da2e3ebdSchin 			while (*s && *s != ',' && *s != ' ' && *s != '\t' && *s != '\n' && *s != '\r' && *s != '=' && *s != ':')
5647da2e3ebdSchin 				sfputc(mp, *s++);
5648da2e3ebdSchin 			if ((c = *s) == ':' && *(s + 1) != '=')
5649da2e3ebdSchin 			{
5650da2e3ebdSchin 				opt_info.index = 1;
5651da2e3ebdSchin 				opt_info.offset = ++s - (char*)str;
5652da2e3ebdSchin 				if (!(s = sfstruse(mp)))
5653da2e3ebdSchin 					goto nospace;
5654da2e3ebdSchin 				s += 2;
5655da2e3ebdSchin 				e = opt_info.name;
5656da2e3ebdSchin 				while (e < &opt_info.name[sizeof(opt_info.name)-1] && (*e++ = *s++));
5657da2e3ebdSchin 				opt_info.arg = 0;
565834f9b3eeSRoland Mainz 				opt_info.num = (long)(opt_info.number = 0);
5659da2e3ebdSchin 				opt_info.option[0] = ':';
5660da2e3ebdSchin 				opt_info.option[1] = 0;
5661da2e3ebdSchin 				return '#';
5662da2e3ebdSchin 			}
5663da2e3ebdSchin 			if (c == ':' || c == '=')
5664da2e3ebdSchin 			{
5665da2e3ebdSchin 				sfputc(mp, c);
5666da2e3ebdSchin 				ql = qr = 0;
5667da2e3ebdSchin 				while (c = *++s)
5668da2e3ebdSchin 				{
5669da2e3ebdSchin 					if (c == '\\')
5670da2e3ebdSchin 					{
5671da2e3ebdSchin 						sfputc(mp, chresc(s, &e));
5672da2e3ebdSchin 						s = e - 1;
5673da2e3ebdSchin 					}
5674da2e3ebdSchin 					else if (c == qr)
5675da2e3ebdSchin 					{
5676da2e3ebdSchin 						if (qr != ql)
5677da2e3ebdSchin 							sfputc(mp, c);
5678da2e3ebdSchin 						if (--qc <= 0)
5679da2e3ebdSchin 							qr = ql = 0;
5680da2e3ebdSchin 					}
5681da2e3ebdSchin 					else if (c == ql)
5682da2e3ebdSchin 					{
5683da2e3ebdSchin 						sfputc(mp, c);
5684da2e3ebdSchin 						qc++;
5685da2e3ebdSchin 					}
5686da2e3ebdSchin 					else if (qr)
5687da2e3ebdSchin 						sfputc(mp, c);
5688da2e3ebdSchin 					else if (c == ',' || c == ' ' || c == '\t' || c == '\n' || c == '\r')
5689da2e3ebdSchin 						break;
5690da2e3ebdSchin 					else if (c == '"' || c == '\'')
5691da2e3ebdSchin 					{
5692da2e3ebdSchin 						ql = qr = c;
5693da2e3ebdSchin 						qc = 1;
5694da2e3ebdSchin 					}
5695da2e3ebdSchin 					else
5696da2e3ebdSchin 					{
5697da2e3ebdSchin 						sfputc(mp, c);
5698da2e3ebdSchin 						if (c == GO)
5699da2e3ebdSchin 						{
5700da2e3ebdSchin 							ql = c;
5701da2e3ebdSchin 							qr = OG;
5702da2e3ebdSchin 							qc = 1;
5703da2e3ebdSchin 						}
5704da2e3ebdSchin 						else if (c == '(')
5705da2e3ebdSchin 						{
5706da2e3ebdSchin 							ql = c;
5707da2e3ebdSchin 							qr = ')';
5708da2e3ebdSchin 							qc = 1;
5709da2e3ebdSchin 						}
5710da2e3ebdSchin 					}
5711da2e3ebdSchin 				}
5712da2e3ebdSchin 			}
5713da2e3ebdSchin 		}
5714*b30d1939SAndy Fiddaman 		opt_info.argv = state.strv;
5715*b30d1939SAndy Fiddaman 		state.strv[0] = T(NiL, ID, "option");
5716*b30d1939SAndy Fiddaman 		if (!(state.strv[1] = sfstruse(mp)))
5717da2e3ebdSchin 			goto nospace;
5718*b30d1939SAndy Fiddaman 		state.strv[2] = 0;
5719da2e3ebdSchin 		opt_info.offset = s - (char*)str;
5720da2e3ebdSchin 	}
5721da2e3ebdSchin 	if (opts)
5722da2e3ebdSchin 	{
5723*b30d1939SAndy Fiddaman 		if (!state.strv[1])
5724da2e3ebdSchin 		{
5725*b30d1939SAndy Fiddaman 			state.str = 0;
5726da2e3ebdSchin 			return 0;
5727da2e3ebdSchin 		}
5728da2e3ebdSchin 		opt_info.index = 1;
5729da2e3ebdSchin 		v = opt_info.offset;
5730da2e3ebdSchin 		opt_info.offset = 0;
5731*b30d1939SAndy Fiddaman 		c = optget(state.strv, opts);
5732da2e3ebdSchin 		opt_info.index = 1;
5733da2e3ebdSchin 		opt_info.offset = v;
5734da2e3ebdSchin 		if (c == '#')
5735da2e3ebdSchin 		{
5736*b30d1939SAndy Fiddaman 			s = state.str;
5737da2e3ebdSchin 			goto again;
5738da2e3ebdSchin 		}
5739da2e3ebdSchin 		if ((c == '?' || c == ':') && (opt_info.arg[0] == '-' && opt_info.arg[1] == '-'))
5740da2e3ebdSchin 			opt_info.arg += 2;
5741da2e3ebdSchin 		s = opt_info.name;
5742da2e3ebdSchin 		if (*s++ == '-' && *s++ == '-' && *s)
5743da2e3ebdSchin 		{
5744da2e3ebdSchin 			e = opt_info.name;
5745da2e3ebdSchin 			while (*e++ = *s++);
5746da2e3ebdSchin 		}
5747da2e3ebdSchin 	}
5748da2e3ebdSchin 	else
5749da2e3ebdSchin 		c = '-';
5750da2e3ebdSchin 	return c;
5751da2e3ebdSchin  nospace:
57523e14f97fSRoger A. Faulkner 	return opterror(NiL, 0, 0, NiL, NiL);
5753da2e3ebdSchin }
5754