xref: /titanic_51/usr/src/lib/libpp/common/ppargs.c (revision 34f9b3eef6fdadbda0a846aa4d68691ac40eace5)
1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*34f9b3eeSRoland Mainz *          Copyright (c) 1986-2009 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6da2e3ebdSchin *                  Common Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10da2e3ebdSchin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11da2e3ebdSchin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                                                                      *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin  * Glenn Fowler
23da2e3ebdSchin  * AT&T Research
24da2e3ebdSchin  *
25da2e3ebdSchin  * common preprocessor command line argument parse
26da2e3ebdSchin  * called by optjoin()
27da2e3ebdSchin  */
28da2e3ebdSchin 
29da2e3ebdSchin static const char usage[] =
30*34f9b3eeSRoland Mainz "[-?\n@(#)$Id: cpp (AT&T Research) 2009-02-02 $\n]"
31da2e3ebdSchin USAGE_LICENSE
32da2e3ebdSchin "[+NAME?cpp - C language preprocessor]"
33da2e3ebdSchin "[+DESCRIPTION?\bcpp\b is the preprocessor for all C language dialects. It is"
34da2e3ebdSchin "	a standalone version of the \blibpp\b(3) preprocessor library. The"
35da2e3ebdSchin "	C dialect implemented by \bcpp\b is determined by probing \bcc\b(1)"
36da2e3ebdSchin "	using \bprobe\b(1). The path of the emulated compiler can be changed"
37da2e3ebdSchin "	by the \b-D-X\b command line option.]"
38da2e3ebdSchin "[+?If \aoutput\a is omitted then the standard output is written; if \ainput\a"
39da2e3ebdSchin "	is also omitted then the standard input is read. NOTE: this is an"
40da2e3ebdSchin "	ancient, non-standard, non-intuitiive file operand syntax that is"
41da2e3ebdSchin "	required by \bcc\b(1); use shell file name expansion at your peril.]"
42da2e3ebdSchin "[+?\bcpp\b specific options are set by the \b-D-\b and \b-I-\b options.]"
43da2e3ebdSchin 
44da2e3ebdSchin "[C:comments?Pass comments to the output. By default comments are omitted.]"
45da2e3ebdSchin "[D:define?Define the macro \aname\a to have \avalue\a; \b1\b is assumed if"
46da2e3ebdSchin "	\b=\b\avalue\a is omitted. If \aname\a begins with \b:\b then it is"
47da2e3ebdSchin "	interpreted as a \blibpp\b(3) \b#pragma pp:\b statement; if \aname\a"
48da2e3ebdSchin "	begins with \b%\b then it is interpreted as a \blibpp\b(3) \b#\b"
49da2e3ebdSchin "	directive statement; if \aname\a begins with \b-\b or \b+\b then it is"
50da2e3ebdSchin "	interpreted as a \blibpp\b(3) option; \b-\b turns the option on,"
51da2e3ebdSchin "	\b+\b turns it off. Most options have a \b#pragma\b counterpart that"
52da2e3ebdSchin "	is listed with the option definition. Right, this is ugly, but its the"
53da2e3ebdSchin "	only portable way to pass options through \bcc\b(1) to"
54da2e3ebdSchin "	\bcpp\b:]:[name[=value]]]{"
55da2e3ebdSchin "	[+-D-C, pp::compatibility?Preprocess for K&R compatibility.]"
56da2e3ebdSchin "	[+-D-D\alevel\a, \bpp::debug\b \alevel\a?Set the debug trace level."
57da2e3ebdSchin "		Higher levels produce more output. Levels higher than 3"
58da2e3ebdSchin "		enabled only in \b-g\b compiled versions.]"
59da2e3ebdSchin "	[+-D-F\aname\a?Set the main input file name to \aname\a. This only"
60da2e3ebdSchin "		affects error message and line sync output.]"
61da2e3ebdSchin "	[+-D-H, pp::hosted?All directories are hosted; compatibility"
62da2e3ebdSchin "		warning messages from hosted directory headers are suppressed.]"
63da2e3ebdSchin "	[+-D-I, pp::cdir?All directories contain C headers; used only with"
64da2e3ebdSchin "		\b-D-+\b.]"
65da2e3ebdSchin "	[+-D-K, pp::keyargs?Enable the non-standard \aname=value\a macro"
66da2e3ebdSchin "		argument mode.]"
67da2e3ebdSchin "	[+-D-L\b[\aid\a]], \bpp::lineid\b [\aid\a]]?Set the line sync directive"
68da2e3ebdSchin "		id to \aid\a or null if omitted.]"
69da2e3ebdSchin "	[+-D-M, pp::nomultiple?Disable multiple include detection.]"
70da2e3ebdSchin "	[+-D-P, pp::passthrough?Enable the non-standard passthrough mode; may"
71da2e3ebdSchin "		be useful for processing non-C input.]"
72da2e3ebdSchin "	[+-D-Q, pp::dump?Dump macro definitions to the output so that the"
73da2e3ebdSchin "		output may be passed through \bcpp\b again. Used for"
74da2e3ebdSchin "		generating precompiled headers.]"
75da2e3ebdSchin "	[+-D-R, pp::transition?Enable the transition preprocessing mode. Used"
76da2e3ebdSchin "		for compilers that can't make up their semantics between"
77da2e3ebdSchin "		K&R and ISO.]"
78da2e3ebdSchin "	[+-D-S, pp::strict?Enable strict preprocessing semantics and warnings."
79da2e3ebdSchin "		Works with any mode (compatibiliy, transition,"
80da2e3ebdSchin "		or the default ISO).]"
81da2e3ebdSchin "	[+-D-T\atest\a, \bpp::test\b \atest\a?Enable implementation specific"
82da2e3ebdSchin "		test code according to \atest\a.]"
837c2fbfb3SApril Chin "	[+-D-W, pp::warn?Enable warnings in non-hosted files.]"
84da2e3ebdSchin "	[+-D-X\b[\acc\a]]?Preprocess for the compiler \acc\a which must be"
85da2e3ebdSchin "		an executable path or an executable on \b$PATH\b.]"
867c2fbfb3SApril Chin "	[+-D-Y, pp::pedantic?Enable pedantic \bpp::warn\b warnings in"
877c2fbfb3SApril Chin "		non-hosted files.]"
88da2e3ebdSchin "	[+-D-Z, pp::pool?Enable pool mode. See \blibpp\b(3).]"
89da2e3ebdSchin "	[+-D-d?List canonicalized \b#define\b statements for non-predefined"
90da2e3ebdSchin "		macros in the output. ]"
91da2e3ebdSchin "	[+-D-m?List canonicalized \b#define\b statements for all macros. All"
92da2e3ebdSchin "		other output is disabled.]"
93da2e3ebdSchin "	[+-D-+, pp::plusplus?Preprocess for the C++ dialect.]"
94da2e3ebdSchin "}"
95da2e3ebdSchin "[I:include?Append \adirectory\a to the list of directories searched for"
96da2e3ebdSchin "	\b#include\b files. If \adirectory\a is \b-\b then: (1) \b-I\b"
97da2e3ebdSchin "	directories before \b-I-\b are searched only for \"...\" include"
98da2e3ebdSchin "	files; (2) \b-I\b directories after \b-I-\b are searched for"
99da2e3ebdSchin "	\"...\" and <...> include files; (3) the directory \b.\b is searched"
100da2e3ebdSchin "	only if it is explicitly specified by a \b-I\b option.]:?[directory]{"
101da2e3ebdSchin "	[+-I-C\adirectory\a, \bpp::cdir\b \adirectory\a?Mark \adirectory\a"
102da2e3ebdSchin "		as a C header directory. Used with \bpp:plusplus\b.]"
103da2e3ebdSchin "	[+-I-D[\afile\a]]?Read the default \bprobe\b(1) definitions from"
104da2e3ebdSchin "		\afile\a, or ignore the default definitions if \afile\a"
105da2e3ebdSchin "		is omitted.]"
106da2e3ebdSchin "	[+-I-H\adirectory\a, \bpp::hostdir\b \adirectory\a?Mark \adirectory\a"
107da2e3ebdSchin "		as a hosted directory. Headers from hosted directories have"
108da2e3ebdSchin "		compatibility warnings disabled.]"
109da2e3ebdSchin "	[+-I-I\aheader\a, \bpp::ignore\b \aheader\a?Add \aheader\a to the"
110da2e3ebdSchin "		list of ignored headers.]"
111da2e3ebdSchin "	[+-I-M\afile\a?\afile\a contains a sequence of \aheader\a"
112da2e3ebdSchin "		[= \"\amap\a\" ]] lines, where \aheader\a is either <\aname\a>"
113da2e3ebdSchin "		or \"\aname\a\", and \"\amap\a\" is an explicit binding"
114da2e3ebdSchin "		for \aheader\a. \aheader\a is ignored if = \"\amap\a\" is"
115da2e3ebdSchin "		omitted.]"
116da2e3ebdSchin "	[+-I-R\afile\a?Include \afile\a but do not emit text or line syncs.]"
117da2e3ebdSchin "	[+-I-S\adirectory\a?Add \adirectory\a to the default standard include"
118da2e3ebdSchin "		directory list.]"
119da2e3ebdSchin "	[+-I-T\afile\a?Include \afile\a and emit text to the output file.]"
120da2e3ebdSchin "}"
121da2e3ebdSchin "[M:dependencies?Generate \bmake\b(1) dependencies. Not needed with"
122da2e3ebdSchin "	\bnmake\b(1). \b-M\b may be followed by optional \aflags\a to change"
123da2e3ebdSchin "	dependency output styles:]{"
124da2e3ebdSchin "	[+D?Generate dependencies in a separate \b.d\b file. Preprocessed"
125da2e3ebdSchin "		output is still written to \aoutput\a, or the standard output"
126da2e3ebdSchin "		if \aoutput\a is omitted.]"
127da2e3ebdSchin "	[+G?Generate missing dependencies too.]"
128da2e3ebdSchin "	[+M?Only generate local header dependencies; \ahosted\a headers are"
129da2e3ebdSchin "		omitted. Note that \ahosted\a headers are determined by"
130da2e3ebdSchin "		\b-I-H\b and the \bpp:hosted\b and \bpp:hostdir\b pragmas;"
131da2e3ebdSchin "		no special distiction is made between \"\" and <> \binclude\b"
132da2e3ebdSchin "		styles.]"
133da2e3ebdSchin "}"
134da2e3ebdSchin "[P!:sync?Emit line syncs.]"
135da2e3ebdSchin "[U:undefine?Remove the definition for the macro \aname\a.]:[name]"
136da2e3ebdSchin 
137da2e3ebdSchin "[A:assert?Enter the assertion via \b#assert\b for system V"
138da2e3ebdSchin "	compatibility.]:[assertion]"
139da2e3ebdSchin "[E:preprocess?Ignored for compatibility with ancient compilers.]"
140da2e3ebdSchin "[H:include-reference?Emit \b#include\b file paths on the standard error,"
141da2e3ebdSchin "	one per line, indented to show nesting.]"
142da2e3ebdSchin "[T?If not \bgcc\b(1) then truncate identifiers to \alength\a"
143da2e3ebdSchin "	characters for compatibility with old AT&T (I guess only Lucent needs"
144da2e3ebdSchin "	them now) compilers.]#?[length]"
145da2e3ebdSchin "[V:version?Emit the \blibpp\b(3) version.]"
146da2e3ebdSchin "[X:argmode?Enable \aname\a=\avalue\a macro arguments for \beasel\b(1)"
147da2e3ebdSchin "	compatibility.]"
148da2e3ebdSchin "[Y:standard?Add \adirectory\a to the list searched for"
149da2e3ebdSchin "	\b#include\b \b<...>\b files.]:[directory]"
150da2e3ebdSchin 
151da2e3ebdSchin "\n"
152da2e3ebdSchin "\n[ input [ output ] ]\n"
153da2e3ebdSchin "\n"
154da2e3ebdSchin 
155da2e3ebdSchin "[+SEE ALSO?\bcc\b(1), \bgcc\b(1), \blibpp\b(3)]"
156da2e3ebdSchin ;
157da2e3ebdSchin 
158da2e3ebdSchin #include "pplib.h"
159da2e3ebdSchin 
160da2e3ebdSchin #include <ctype.h>
161da2e3ebdSchin 
162da2e3ebdSchin /*
163da2e3ebdSchin  * convert lint comments to pragmas
164da2e3ebdSchin  */
165da2e3ebdSchin 
166da2e3ebdSchin static void
pplint(char * head,char * comment,char * tail,int line)167da2e3ebdSchin pplint(char* head, char* comment, char* tail, int line)
168da2e3ebdSchin {
169da2e3ebdSchin 	NoP(line);
170da2e3ebdSchin 	if (strmatch(comment, "(ARGSUSED|PRINTFLIKE|PROTOLIB|SCANFLIKE|VARARGS)*([0-9])|CONSTCOND|CONSTANTCOND|CONSTANTCONDITION|EMPTY|FALLTHRU|FALLTHROUGH|LINTLIBRARY|LINTED*|NOTREACHED"))
171da2e3ebdSchin 	{
172da2e3ebdSchin 		strncopy(pp.token, comment, MAXTOKEN);
173da2e3ebdSchin 		ppprintf("\n#%s %s:%s\n", dirname(PRAGMA), pp.pass, pp.token);
174da2e3ebdSchin 		ppline(error_info.line, NiL);
175da2e3ebdSchin 	}
176da2e3ebdSchin }
177da2e3ebdSchin 
178da2e3ebdSchin /*
179da2e3ebdSchin  * if last!=0 then argv[opt_info.index]==0 with return(0)
180da2e3ebdSchin  * else if argv[opt_info.index]==0 then return(0)
181da2e3ebdSchin  * otherwise argv[opt_info.index] is the first unrecognized
182da2e3ebdSchin  * option with return(1)
183da2e3ebdSchin  *
184da2e3ebdSchin  * use last=0 if the preprocessor is combined with other passes
185da2e3ebdSchin  * so that unknown options may be interpreted for those passes
186da2e3ebdSchin  */
187da2e3ebdSchin 
188da2e3ebdSchin int
ppargs(char ** argv,int last)189da2e3ebdSchin ppargs(char** argv, int last)
190da2e3ebdSchin {
191da2e3ebdSchin 	register char*	s;
192da2e3ebdSchin 	register int	c;
193da2e3ebdSchin 	register int	n;
194da2e3ebdSchin 	char*		p;
195da2e3ebdSchin 
196da2e3ebdSchin 	/*
197da2e3ebdSchin 	 * check the args and initialize
198da2e3ebdSchin 	 */
199da2e3ebdSchin 
200da2e3ebdSchin 	if (!error_info.id)
201da2e3ebdSchin 		error_info.id = "cpp";
202da2e3ebdSchin 	for (;;)
203da2e3ebdSchin 	{
204da2e3ebdSchin 		for (; c = optget(argv, usage); last = 0) switch (c)
205da2e3ebdSchin 		{
206da2e3ebdSchin 		case 'C':
207da2e3ebdSchin 			ppop(PP_COMMENT, ppcomment);
208da2e3ebdSchin 			break;
209da2e3ebdSchin 		case 'D':
210da2e3ebdSchin 			/*
211da2e3ebdSchin 			 * this allows single arg pp option extensions
212da2e3ebdSchin 			 * without touching cc
213da2e3ebdSchin 			 * (not all cc wrappers have -W...)
214da2e3ebdSchin 			 */
215da2e3ebdSchin 
216da2e3ebdSchin 			switch (*(s = opt_info.arg))
217da2e3ebdSchin 			{
218da2e3ebdSchin 			case '-':
219da2e3ebdSchin 			case '+':
220da2e3ebdSchin 				n = (*s++ == '-');
221da2e3ebdSchin 				while (c = *s++) switch (c)
222da2e3ebdSchin 				{
223da2e3ebdSchin 				case 'C':
224da2e3ebdSchin 					ppop(PP_COMPATIBILITY, n);
225da2e3ebdSchin 					break;
226da2e3ebdSchin 				case 'D':
227da2e3ebdSchin 					if (n && ((c = strtol(s, &p, 0)) || p != s))
228da2e3ebdSchin 					{
229da2e3ebdSchin 						s = p;
230da2e3ebdSchin 						n = c;
231da2e3ebdSchin 					}
232da2e3ebdSchin 					ppop(PP_DEBUG, -n);
233da2e3ebdSchin 					break;
234da2e3ebdSchin 				case 'F':
235da2e3ebdSchin 					ppop(PP_FILENAME, n ? s : NiL);
236da2e3ebdSchin 					goto hasarg;
237da2e3ebdSchin 				case 'H':
238da2e3ebdSchin 					ppop(PP_HOSTDIR, "-", n);
239da2e3ebdSchin 					break;
240da2e3ebdSchin 				case 'I':
241da2e3ebdSchin 					ppop(PP_CDIR, "-", n);
242da2e3ebdSchin 					break;
243da2e3ebdSchin 				case 'K':
244da2e3ebdSchin 					ppop(PP_KEYARGS, n);
245da2e3ebdSchin 					break;
246da2e3ebdSchin 				case 'L':
247da2e3ebdSchin 					ppop(PP_LINEID, n && *s ? s : "line");
248da2e3ebdSchin 					goto hasarg;
249da2e3ebdSchin 				case 'M':
250da2e3ebdSchin 					ppop(PP_MULTIPLE, !n);
251da2e3ebdSchin 					break;
252da2e3ebdSchin 				case 'P':
253da2e3ebdSchin 					ppop(PP_PASSTHROUGH, n);
254da2e3ebdSchin 					break;
255da2e3ebdSchin 				case 'Q':
256da2e3ebdSchin 					ppop(PP_DUMP, n);
257da2e3ebdSchin 					break;
258da2e3ebdSchin 				case 'R':
259da2e3ebdSchin 					ppop(PP_TRANSITION, n);
260da2e3ebdSchin 					break;
261da2e3ebdSchin 				case 'S':
262da2e3ebdSchin 					ppop(PP_STRICT, n);
263da2e3ebdSchin 					break;
264da2e3ebdSchin 				case 'T':
265da2e3ebdSchin 					ppop(PP_TEST, s);
266da2e3ebdSchin 					goto hasarg;
267da2e3ebdSchin 				case 'V':
268da2e3ebdSchin 					ppop(PP_VENDOR, "-", n);
269da2e3ebdSchin 					break;
270da2e3ebdSchin 				case 'W':
271da2e3ebdSchin 					ppop(PP_WARN, n);
272da2e3ebdSchin 					break;
273da2e3ebdSchin 				case 'X':
274da2e3ebdSchin 					ppop(PP_PROBE, n && *s ? s : 0);
275da2e3ebdSchin 					goto hasarg;
2767c2fbfb3SApril Chin 				case 'Y':
2777c2fbfb3SApril Chin 					ppop(PP_PEDANTIC, n);
2787c2fbfb3SApril Chin 					break;
279da2e3ebdSchin 				case 'Z':
280da2e3ebdSchin 					ppop(PP_POOL, n);
281da2e3ebdSchin 					break;
282da2e3ebdSchin 				case 'd':
283da2e3ebdSchin 					pp.option |= DEFINITIONS;
284da2e3ebdSchin 					break;
285da2e3ebdSchin 				case 'm':
286da2e3ebdSchin 					pp.state |= NOTEXT;
287da2e3ebdSchin 					pp.option |= KEEPNOTEXT|DEFINITIONS|PREDEFINITIONS;
288da2e3ebdSchin 					pp.linesync = 0;
289da2e3ebdSchin 					break;
290da2e3ebdSchin 				case '+':
291da2e3ebdSchin 					ppop(PP_PLUSPLUS, n);
292da2e3ebdSchin 					break;
293da2e3ebdSchin 				default:
294da2e3ebdSchin 					if (pp.optarg)
295da2e3ebdSchin 					{
296da2e3ebdSchin 						if ((c = (*pp.optarg)(n, c, s)) > 0) goto hasarg;
297da2e3ebdSchin 						else if (!c) break;
298da2e3ebdSchin 					}
299da2e3ebdSchin 					error(1, "%c%s: unknown -D option overload", n ? '-' : '+', s - 1);
300da2e3ebdSchin 					goto hasarg;
301da2e3ebdSchin 				}
302da2e3ebdSchin 			hasarg:
303da2e3ebdSchin 				break;
304da2e3ebdSchin 			case ':':
305da2e3ebdSchin 				ppop(PP_OPTION, s + 1);
306da2e3ebdSchin 				break;
307da2e3ebdSchin 			case '%':
308da2e3ebdSchin 				ppop(PP_DIRECTIVE, s + 1);
309da2e3ebdSchin 				break;
310da2e3ebdSchin 			case '_':
311da2e3ebdSchin 				if (strmatch(s, "__GNUC__*"))
312da2e3ebdSchin 					pp.arg_style |= STYLE_gnu;
313da2e3ebdSchin 				else if (strmatch(s, "__(ANSI|STDC|STRICT)__*") || !(pp.arg_style & STYLE_gnu) && strmatch(s, "__STRICT_ANSI__*"))
314da2e3ebdSchin 					ppop(PP_STRICT, 1);
315da2e3ebdSchin 				else if (strmatch(s, "__cplusplus*"))
316da2e3ebdSchin 					ppop(PP_PLUSPLUS, 1);
317da2e3ebdSchin 				/*FALLTHROUGH*/
318da2e3ebdSchin 			default:
319da2e3ebdSchin 				ppop(PP_DEFINE, s);
320da2e3ebdSchin 				break;
321da2e3ebdSchin 			}
322da2e3ebdSchin 			break;
323da2e3ebdSchin 		case 'E':
324da2e3ebdSchin 			/* historically ignored */
325da2e3ebdSchin 			break;
326da2e3ebdSchin 		case 'I':
327da2e3ebdSchin 			if (!(s = opt_info.arg))
328da2e3ebdSchin 			{
329da2e3ebdSchin 				/*
330da2e3ebdSchin 				 * some compilers interpret `-I ...' as
331da2e3ebdSchin 				 * `-I-S' and arg ... while others interpret
332da2e3ebdSchin 				 * it as `-I...'
333da2e3ebdSchin 				 */
334da2e3ebdSchin 
335da2e3ebdSchin 				p = "-S";
336da2e3ebdSchin 				if ((s = argv[opt_info.index]) && ((n = *s++) == '-' || n == '+') && *s++ == 'D')
337da2e3ebdSchin 				{
338da2e3ebdSchin 					if (isalpha(*s) || *s == '_')
339da2e3ebdSchin 						while (isalnum(*++s) || *s == '_');
340da2e3ebdSchin 					if (*s && *s != '=' && *s != '-' && *s != '+')
341da2e3ebdSchin 						p = argv[opt_info.index++];
342da2e3ebdSchin 				}
343da2e3ebdSchin 				s = p;
344da2e3ebdSchin 			}
345da2e3ebdSchin 			switch (*s)
346da2e3ebdSchin 			{
347da2e3ebdSchin 			case '-':
348da2e3ebdSchin 			case '+':
349da2e3ebdSchin 				n = *(p = s++) == '-';
350da2e3ebdSchin 				c = *s++;
351da2e3ebdSchin 				if (!n && !*s) s = 0;
352da2e3ebdSchin 				switch (c)
353da2e3ebdSchin 				{
354da2e3ebdSchin 				case 0:
355da2e3ebdSchin 					ppop(PP_LOCAL);
356da2e3ebdSchin 					break;
357da2e3ebdSchin 				case 'C':
358da2e3ebdSchin 					ppop(PP_CDIR, s, n);
359da2e3ebdSchin 					break;
360da2e3ebdSchin 				case 'D':
361da2e3ebdSchin 					ppop(PP_DEFAULT, s);
362da2e3ebdSchin 					break;
363da2e3ebdSchin 				case 'H':
364da2e3ebdSchin 					ppop(PP_HOSTDIR, s, n);
365da2e3ebdSchin 					break;
366da2e3ebdSchin 				case 'I':
367da2e3ebdSchin 					ppop(PP_IGNORE, s);
368da2e3ebdSchin 					break;
369da2e3ebdSchin 				case 'M':
370da2e3ebdSchin 					ppop(PP_IGNORELIST, s);
371da2e3ebdSchin 					break;
372da2e3ebdSchin 				case 'R':
373da2e3ebdSchin 					ppop(PP_READ, s);
374da2e3ebdSchin 					break;
375da2e3ebdSchin 				case 'S':
376da2e3ebdSchin 					ppop(PP_STANDARD, s);
377da2e3ebdSchin 					break;
378da2e3ebdSchin 				case 'T':
379da2e3ebdSchin 					ppop(PP_TEXT, s);
380da2e3ebdSchin 					break;
381da2e3ebdSchin 				case 'V':
382da2e3ebdSchin 					ppop(PP_VENDOR, s, n);
383da2e3ebdSchin 					break;
384da2e3ebdSchin 				default:
385da2e3ebdSchin 					error(1, "%s: unknown -I option overload", p);
386da2e3ebdSchin 					break;
387da2e3ebdSchin 				}
388da2e3ebdSchin 				break;
389da2e3ebdSchin 			default:
390da2e3ebdSchin 				ppop(PP_INCLUDE, s);
391da2e3ebdSchin 				break;
392da2e3ebdSchin 			}
393da2e3ebdSchin 			break;
394da2e3ebdSchin 		case 'M':
395da2e3ebdSchin 			for (n = PP_deps; argv[opt_info.index]; opt_info.offset++)
396da2e3ebdSchin 			{
397da2e3ebdSchin 				switch (argv[opt_info.index][opt_info.offset])
398da2e3ebdSchin 				{
399da2e3ebdSchin 				case 'D':
400da2e3ebdSchin 					n |= PP_deps_file;
401da2e3ebdSchin 					continue;
402da2e3ebdSchin 				case 'G':
403da2e3ebdSchin 					n |= PP_deps_generated;
404da2e3ebdSchin 					continue;
405da2e3ebdSchin 				case 'M':
406da2e3ebdSchin 					n |= PP_deps_local;
407da2e3ebdSchin 					continue;
408da2e3ebdSchin 				}
409da2e3ebdSchin 				break;
410da2e3ebdSchin 			}
411da2e3ebdSchin 			ppop(PP_FILEDEPS, n);
412da2e3ebdSchin 			break;
413da2e3ebdSchin 		case 'P':
414da2e3ebdSchin 			ppop(PP_LINE, (PPLINESYNC)0);
415da2e3ebdSchin 			break;
416da2e3ebdSchin 		case 'U':
417da2e3ebdSchin 			ppop(PP_UNDEF, opt_info.arg);
418da2e3ebdSchin 			break;
419da2e3ebdSchin 
420da2e3ebdSchin 		/*
421da2e3ebdSchin 		 * System V CCS compatibility
422da2e3ebdSchin 		 */
423da2e3ebdSchin 
424da2e3ebdSchin 		case 'A':
425da2e3ebdSchin 			if (isalpha(opt_info.arg[0]) || opt_info.arg[0] == '_' || opt_info.arg[0] == '$')
426da2e3ebdSchin 				ppop(PP_ASSERT, opt_info.arg);
427da2e3ebdSchin 			break;
428da2e3ebdSchin 		case 'H':
429da2e3ebdSchin 			ppop(PP_INCREF, ppincref);
430da2e3ebdSchin 			break;
431da2e3ebdSchin 		case 'T':
432da2e3ebdSchin 			if (!(pp.arg_style & STYLE_gnu))
433da2e3ebdSchin 				ppop(PP_TRUNCATE, TRUNCLENGTH);
434da2e3ebdSchin 			/* else enable ANSI trigraphs -- default */
435da2e3ebdSchin 			break;
436da2e3ebdSchin 		case 'V':
437da2e3ebdSchin 			error(0, "%s", pp.version);
438da2e3ebdSchin 			break;
439da2e3ebdSchin 		case 'X':
440da2e3ebdSchin 			pp.arg_mode = (*(opt_info.arg + 1) || pp.arg_mode && pp.arg_mode != *opt_info.arg) ? '-' : *opt_info.arg;
441da2e3ebdSchin 			break;
442da2e3ebdSchin 		case 'Y':
443da2e3ebdSchin 			if (*(s = opt_info.arg) && *(s + 1) == ',')
444da2e3ebdSchin 			{
445da2e3ebdSchin 				if (*s != 'I') break;
446da2e3ebdSchin 				s += 2;
447da2e3ebdSchin 			}
448da2e3ebdSchin 			ppop(PP_STANDARD, s);
449da2e3ebdSchin 			break;
450da2e3ebdSchin 
451da2e3ebdSchin 		/*
452da2e3ebdSchin 		 * errors
453da2e3ebdSchin 		 */
454da2e3ebdSchin 
455da2e3ebdSchin 		case '?':
456da2e3ebdSchin 			error(ERROR_USAGE|4, "%s", opt_info.arg);
457da2e3ebdSchin 			break;
458da2e3ebdSchin 		case ':':
459da2e3ebdSchin 			if (!last)
460da2e3ebdSchin 			{
461da2e3ebdSchin 				opt_info.again = 1;
462da2e3ebdSchin 				return(1);
463da2e3ebdSchin 			}
464da2e3ebdSchin 
465da2e3ebdSchin 			/*
466da2e3ebdSchin 			 * cross your fingers
467da2e3ebdSchin 			 */
468da2e3ebdSchin 
469da2e3ebdSchin 			if (!(s = argv[opt_info.index]))
470da2e3ebdSchin 				error(3, "%s", opt_info.arg);
471da2e3ebdSchin 			if (opt_info.offset == 2 && (pp.arg_style & STYLE_gnu))
472da2e3ebdSchin 			{
473da2e3ebdSchin 				p = argv[opt_info.index + 1];
474da2e3ebdSchin 				if (streq(s, "-$"))
475da2e3ebdSchin 				{
476da2e3ebdSchin 					ppop(PP_OPTION, "noid \"$\"");
477da2e3ebdSchin 					goto ignore;
478da2e3ebdSchin 				}
479da2e3ebdSchin 				else if (streq(s, "-dD"))
480da2e3ebdSchin 				{
481da2e3ebdSchin 					pp.option |= DEFINITIONS;
482da2e3ebdSchin 					goto ignore;
483da2e3ebdSchin 				}
484da2e3ebdSchin 				else if (streq(s, "-dM"))
485da2e3ebdSchin 				{
486da2e3ebdSchin 					pp.state |= NOTEXT;
487da2e3ebdSchin 					pp.option |= KEEPNOTEXT|DEFINITIONS|PREDEFINITIONS;
488da2e3ebdSchin 					pp.linesync = 0;
489da2e3ebdSchin 					goto ignore;
490da2e3ebdSchin 				}
491da2e3ebdSchin 				else if (streq(s, "-imacros"))
492da2e3ebdSchin 				{
493da2e3ebdSchin 					if (p)
494da2e3ebdSchin 					{
495da2e3ebdSchin 						ppop(PP_READ, p);
496da2e3ebdSchin 						opt_info.index++;
497da2e3ebdSchin 						opt_info.offset = 0;
498da2e3ebdSchin 					}
499da2e3ebdSchin 					goto ignore;
500da2e3ebdSchin 				}
501da2e3ebdSchin 				else if (streq(s, "-include"))
502da2e3ebdSchin 				{
503da2e3ebdSchin 					if (p)
504da2e3ebdSchin 					{
505da2e3ebdSchin 						ppop(PP_TEXT, p);
506da2e3ebdSchin 						opt_info.index++;
507da2e3ebdSchin 						opt_info.offset = 0;
508da2e3ebdSchin 					}
509da2e3ebdSchin 					opt_info.offset = 0;
510da2e3ebdSchin 					goto ignore;
511da2e3ebdSchin 				}
512da2e3ebdSchin 				else if (strneq(s, "-lang-", 6))
513da2e3ebdSchin 				{
514da2e3ebdSchin 					s += 6;
515da2e3ebdSchin 					if (streq(s, "c"))
516da2e3ebdSchin 						c = 0;
517da2e3ebdSchin 					else if (streq(s, "c++"))
518da2e3ebdSchin 						c = 1;
519da2e3ebdSchin 					else if (streq(s, "objc"))
520da2e3ebdSchin 						c = 2;
521da2e3ebdSchin 					else if (streq(s, "objc++"))
522da2e3ebdSchin 						c = 3;
523da2e3ebdSchin 					ppop(PP_PLUSPLUS, c & 1);
524da2e3ebdSchin 					if (c & 2)
525da2e3ebdSchin 						ppop(PP_DIRECTIVE, "pragma pp:map \"/#(pragma )?import>/\" \"/#(pragma )?import(.*)/__STDPP__IMPORT__(\\2)/\"\n\
526da2e3ebdSchin #macdef __STDPP__IMPORT__(x)\n\
527da2e3ebdSchin #pragma pp:noallmultiple\n\
528da2e3ebdSchin #include x\n\
529da2e3ebdSchin #pragma pp:allmultiple\n\
530da2e3ebdSchin #endmac");
531da2e3ebdSchin 					goto ignore;
532da2e3ebdSchin 				}
533da2e3ebdSchin 				else if (streq(s, "-lint"))
534da2e3ebdSchin 				{
535da2e3ebdSchin 					ppop(PP_COMMENT, pplint);
536da2e3ebdSchin 					goto ignore;
537da2e3ebdSchin 				}
538da2e3ebdSchin 			}
539da2e3ebdSchin 			s += opt_info.offset - 1;
540da2e3ebdSchin 			if (strmatch(s, "i*.h"))
541da2e3ebdSchin 				ppop((pp.arg_style & STYLE_gnu) || s[1] == '/' ? PP_READ : PP_TEXT, s + 1);
542da2e3ebdSchin 			else if (strmatch(s, "*@(nostandard|nostdinc)*"))
543da2e3ebdSchin 				ppop(PP_STANDARD, "");
544da2e3ebdSchin 			else if (strmatch(s, "*@(exten|xansi)*|std"))
545da2e3ebdSchin 			{
546da2e3ebdSchin 				ppop(PP_COMPATIBILITY, 0);
547da2e3ebdSchin 				ppop(PP_TRANSITION, 1);
548da2e3ebdSchin 			}
549da2e3ebdSchin 			else if (strmatch(s, "*@(ansi|conform|pedantic|stand|std1|strict[!-])*"))
550da2e3ebdSchin 			{
551da2e3ebdSchin 				ppop(PP_COMPATIBILITY, 0);
552da2e3ebdSchin 				ppop(PP_STRICT, 1);
553da2e3ebdSchin 				if (strmatch(s, "*pedantic*"))
554da2e3ebdSchin 					ppop(PP_PEDANTIC, 1);
555da2e3ebdSchin 			}
556da2e3ebdSchin 			else if (strmatch(s, "*@(trans)*"))
557da2e3ebdSchin 			{
558da2e3ebdSchin 				ppop(PP_COMPATIBILITY, 1);
559da2e3ebdSchin 				ppop(PP_TRANSITION, 1);
560da2e3ebdSchin 			}
561da2e3ebdSchin 			else if (strmatch(s, "*@(classic|compat|std0|tradition|[kK][n&+][rR])*"))
562da2e3ebdSchin 			{
563da2e3ebdSchin 				ppop(PP_COMPATIBILITY, 1);
564da2e3ebdSchin 				ppop(PP_TRANSITION, 0);
565da2e3ebdSchin 			}
566da2e3ebdSchin 			else if (strmatch(s, "*@(plusplus|++)*"))
567da2e3ebdSchin 				ppop(PP_PLUSPLUS, 1);
568da2e3ebdSchin 			else if (strmatch(s, "*@(warn)*"))
569da2e3ebdSchin 				ppop(PP_WARN, 1);
570da2e3ebdSchin 
571da2e3ebdSchin 			/*
572da2e3ebdSchin 			 * ignore unknown options
573da2e3ebdSchin 			 * the probe info takes care of these
574da2e3ebdSchin 			 * fails if an option value is in the next arg
575da2e3ebdSchin 			 * and this is the last option
576da2e3ebdSchin 			 */
577da2e3ebdSchin 
578da2e3ebdSchin 			if (argv[opt_info.index + 1] && argv[opt_info.index + 1][0] != '-' && argv[opt_info.index + 2] && argv[opt_info.index + 2][0] == '-')
579da2e3ebdSchin 			{
580da2e3ebdSchin 				opt_info.index++;
581da2e3ebdSchin 				opt_info.offset = 0;
582da2e3ebdSchin 			}
583da2e3ebdSchin 		ignore:
584da2e3ebdSchin 			while (argv[opt_info.index][opt_info.offset]) opt_info.offset++;
585da2e3ebdSchin 			break;
586da2e3ebdSchin 		}
587da2e3ebdSchin 		if (!(s = argv[opt_info.index])) return(0);
588da2e3ebdSchin 		switch (pp.arg_file)
589da2e3ebdSchin 		{
590da2e3ebdSchin 		case 0:
591da2e3ebdSchin 			if (*s != '-' || *(s + 1)) ppop(PP_INPUT, s);
592da2e3ebdSchin 			break;
593da2e3ebdSchin 		case 1:
594da2e3ebdSchin 			if (*s != '-' || *(s + 1)) ppop(PP_OUTPUT, s);
595da2e3ebdSchin 			break;
596da2e3ebdSchin 		default:
597da2e3ebdSchin 			if (!last) return(1);
598da2e3ebdSchin 			error(1, "%s: extraneous argument ignored", s);
599da2e3ebdSchin 			break;
600da2e3ebdSchin 		}
601da2e3ebdSchin 		pp.arg_file++;
602da2e3ebdSchin 		if (!argv[++opt_info.index]) return(0);
603da2e3ebdSchin 
604da2e3ebdSchin 		/*
605da2e3ebdSchin 		 * old versions allow options after file args
606da2e3ebdSchin 		 */
607da2e3ebdSchin 	}
608da2e3ebdSchin }
609