1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1986-2009 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
19 ***********************************************************************/
25 * common preprocessor command line argument parse
29 static const char usage
[] =
30 "[-?\n@(#)$Id: cpp (AT&T Research) 2009-02-02 $\n]"
32 "[+NAME?cpp - C language preprocessor]"
33 "[+DESCRIPTION?\bcpp\b is the preprocessor for all C language dialects. It is"
34 " a standalone version of the \blibpp\b(3) preprocessor library. The"
35 " C dialect implemented by \bcpp\b is determined by probing \bcc\b(1)"
36 " using \bprobe\b(1). The path of the emulated compiler can be changed"
37 " by the \b-D-X\b command line option.]"
38 "[+?If \aoutput\a is omitted then the standard output is written; if \ainput\a"
39 " is also omitted then the standard input is read. NOTE: this is an"
40 " ancient, non-standard, non-intuitiive file operand syntax that is"
41 " required by \bcc\b(1); use shell file name expansion at your peril.]"
42 "[+?\bcpp\b specific options are set by the \b-D-\b and \b-I-\b options.]"
44 "[C:comments?Pass comments to the output. By default comments are omitted.]"
45 "[D:define?Define the macro \aname\a to have \avalue\a; \b1\b is assumed if"
46 " \b=\b\avalue\a is omitted. If \aname\a begins with \b:\b then it is"
47 " interpreted as a \blibpp\b(3) \b#pragma pp:\b statement; if \aname\a"
48 " begins with \b%\b then it is interpreted as a \blibpp\b(3) \b#\b"
49 " directive statement; if \aname\a begins with \b-\b or \b+\b then it is"
50 " interpreted as a \blibpp\b(3) option; \b-\b turns the option on,"
51 " \b+\b turns it off. Most options have a \b#pragma\b counterpart that"
52 " is listed with the option definition. Right, this is ugly, but its the"
53 " only portable way to pass options through \bcc\b(1) to"
54 " \bcpp\b:]:[name[=value]]]{"
55 " [+-D-C, pp::compatibility?Preprocess for K&R compatibility.]"
56 " [+-D-D\alevel\a, \bpp::debug\b \alevel\a?Set the debug trace level."
57 " Higher levels produce more output. Levels higher than 3"
58 " enabled only in \b-g\b compiled versions.]"
59 " [+-D-F\aname\a?Set the main input file name to \aname\a. This only"
60 " affects error message and line sync output.]"
61 " [+-D-H, pp::hosted?All directories are hosted; compatibility"
62 " warning messages from hosted directory headers are suppressed.]"
63 " [+-D-I, pp::cdir?All directories contain C headers; used only with"
65 " [+-D-K, pp::keyargs?Enable the non-standard \aname=value\a macro"
67 " [+-D-L\b[\aid\a]], \bpp::lineid\b [\aid\a]]?Set the line sync directive"
68 " id to \aid\a or null if omitted.]"
69 " [+-D-M, pp::nomultiple?Disable multiple include detection.]"
70 " [+-D-P, pp::passthrough?Enable the non-standard passthrough mode; may"
71 " be useful for processing non-C input.]"
72 " [+-D-Q, pp::dump?Dump macro definitions to the output so that the"
73 " output may be passed through \bcpp\b again. Used for"
74 " generating precompiled headers.]"
75 " [+-D-R, pp::transition?Enable the transition preprocessing mode. Used"
76 " for compilers that can't make up their semantics between"
78 " [+-D-S, pp::strict?Enable strict preprocessing semantics and warnings."
79 " Works with any mode (compatibiliy, transition,"
80 " or the default ISO).]"
81 " [+-D-T\atest\a, \bpp::test\b \atest\a?Enable implementation specific"
82 " test code according to \atest\a.]"
83 " [+-D-W, pp::warn?Enable warnings in non-hosted files.]"
84 " [+-D-X\b[\acc\a]]?Preprocess for the compiler \acc\a which must be"
85 " an executable path or an executable on \b$PATH\b.]"
86 " [+-D-Y, pp::pedantic?Enable pedantic \bpp::warn\b warnings in"
88 " [+-D-Z, pp::pool?Enable pool mode. See \blibpp\b(3).]"
89 " [+-D-d?List canonicalized \b#define\b statements for non-predefined"
90 " macros in the output. ]"
91 " [+-D-m?List canonicalized \b#define\b statements for all macros. All"
92 " other output is disabled.]"
93 " [+-D-+, pp::plusplus?Preprocess for the C++ dialect.]"
95 "[I:include?Append \adirectory\a to the list of directories searched for"
96 " \b#include\b files. If \adirectory\a is \b-\b then: (1) \b-I\b"
97 " directories before \b-I-\b are searched only for \"...\" include"
98 " files; (2) \b-I\b directories after \b-I-\b are searched for"
99 " \"...\" and <...> include files; (3) the directory \b.\b is searched"
100 " only if it is explicitly specified by a \b-I\b option.]:?[directory]{"
101 " [+-I-C\adirectory\a, \bpp::cdir\b \adirectory\a?Mark \adirectory\a"
102 " as a C header directory. Used with \bpp:plusplus\b.]"
103 " [+-I-D[\afile\a]]?Read the default \bprobe\b(1) definitions from"
104 " \afile\a, or ignore the default definitions if \afile\a"
106 " [+-I-H\adirectory\a, \bpp::hostdir\b \adirectory\a?Mark \adirectory\a"
107 " as a hosted directory. Headers from hosted directories have"
108 " compatibility warnings disabled.]"
109 " [+-I-I\aheader\a, \bpp::ignore\b \aheader\a?Add \aheader\a to the"
110 " list of ignored headers.]"
111 " [+-I-M\afile\a?\afile\a contains a sequence of \aheader\a"
112 " [= \"\amap\a\" ]] lines, where \aheader\a is either <\aname\a>"
113 " or \"\aname\a\", and \"\amap\a\" is an explicit binding"
114 " for \aheader\a. \aheader\a is ignored if = \"\amap\a\" is"
116 " [+-I-R\afile\a?Include \afile\a but do not emit text or line syncs.]"
117 " [+-I-S\adirectory\a?Add \adirectory\a to the default standard include"
119 " [+-I-T\afile\a?Include \afile\a and emit text to the output file.]"
121 "[M:dependencies?Generate \bmake\b(1) dependencies. Not needed with"
122 " \bnmake\b(1). \b-M\b may be followed by optional \aflags\a to change"
123 " dependency output styles:]{"
124 " [+D?Generate dependencies in a separate \b.d\b file. Preprocessed"
125 " output is still written to \aoutput\a, or the standard output"
126 " if \aoutput\a is omitted.]"
127 " [+G?Generate missing dependencies too.]"
128 " [+M?Only generate local header dependencies; \ahosted\a headers are"
129 " omitted. Note that \ahosted\a headers are determined by"
130 " \b-I-H\b and the \bpp:hosted\b and \bpp:hostdir\b pragmas;"
131 " no special distiction is made between \"\" and <> \binclude\b"
134 "[P!:sync?Emit line syncs.]"
135 "[U:undefine?Remove the definition for the macro \aname\a.]:[name]"
137 "[A:assert?Enter the assertion via \b#assert\b for system V"
138 " compatibility.]:[assertion]"
139 "[E:preprocess?Ignored for compatibility with ancient compilers.]"
140 "[H:include-reference?Emit \b#include\b file paths on the standard error,"
141 " one per line, indented to show nesting.]"
142 "[T?If not \bgcc\b(1) then truncate identifiers to \alength\a"
143 " characters for compatibility with old AT&T (I guess only Lucent needs"
144 " them now) compilers.]#?[length]"
145 "[V:version?Emit the \blibpp\b(3) version.]"
146 "[X:argmode?Enable \aname\a=\avalue\a macro arguments for \beasel\b(1)"
148 "[Y:standard?Add \adirectory\a to the list searched for"
149 " \b#include\b \b<...>\b files.]:[directory]"
152 "\n[ input [ output ] ]\n"
155 "[+SEE ALSO?\bcc\b(1), \bgcc\b(1), \blibpp\b(3)]"
163 * convert lint comments to pragmas
167 pplint(char* head
, char* comment
, char* tail
, int line
)
170 if (strmatch(comment
, "(ARGSUSED|PRINTFLIKE|PROTOLIB|SCANFLIKE|VARARGS)*([0-9])|CONSTCOND|CONSTANTCOND|CONSTANTCONDITION|EMPTY|FALLTHRU|FALLTHROUGH|LINTLIBRARY|LINTED*|NOTREACHED"))
172 strncopy(pp
.token
, comment
, MAXTOKEN
);
173 ppprintf("\n#%s %s:%s\n", dirname(PRAGMA
), pp
.pass
, pp
.token
);
174 ppline(error_info
.line
, NiL
);
179 * if last!=0 then argv[opt_info.index]==0 with return(0)
180 * else if argv[opt_info.index]==0 then return(0)
181 * otherwise argv[opt_info.index] is the first unrecognized
182 * option with return(1)
184 * use last=0 if the preprocessor is combined with other passes
185 * so that unknown options may be interpreted for those passes
189 ppargs(char** argv
, int last
)
197 * check the args and initialize
201 error_info
.id
= "cpp";
204 for (; c
= optget(argv
, usage
); last
= 0) switch (c
)
207 ppop(PP_COMMENT
, ppcomment
);
211 * this allows single arg pp option extensions
212 * without touching cc
213 * (not all cc wrappers have -W...)
216 switch (*(s
= opt_info
.arg
))
221 while (c
= *s
++) switch (c
)
224 ppop(PP_COMPATIBILITY
, n
);
227 if (n
&& ((c
= strtol(s
, &p
, 0)) || p
!= s
))
235 ppop(PP_FILENAME
, n
? s
: NiL
);
238 ppop(PP_HOSTDIR
, "-", n
);
241 ppop(PP_CDIR
, "-", n
);
247 ppop(PP_LINEID
, n
&& *s
? s
: "line");
250 ppop(PP_MULTIPLE
, !n
);
253 ppop(PP_PASSTHROUGH
, n
);
259 ppop(PP_TRANSITION
, n
);
268 ppop(PP_VENDOR
, "-", n
);
274 ppop(PP_PROBE
, n
&& *s
? s
: 0);
277 ppop(PP_PEDANTIC
, n
);
283 pp
.option
|= DEFINITIONS
;
287 pp
.option
|= KEEPNOTEXT
|DEFINITIONS
|PREDEFINITIONS
;
291 ppop(PP_PLUSPLUS
, n
);
296 if ((c
= (*pp
.optarg
)(n
, c
, s
)) > 0) goto hasarg
;
299 error(1, "%c%s: unknown -D option overload", n
? '-' : '+', s
- 1);
305 ppop(PP_OPTION
, s
+ 1);
308 ppop(PP_DIRECTIVE
, s
+ 1);
311 if (strmatch(s
, "__GNUC__*"))
312 pp
.arg_style
|= STYLE_gnu
;
313 else if (strmatch(s
, "__(ANSI|STDC|STRICT)__*") || !(pp
.arg_style
& STYLE_gnu
) && strmatch(s
, "__STRICT_ANSI__*"))
315 else if (strmatch(s
, "__cplusplus*"))
316 ppop(PP_PLUSPLUS
, 1);
324 /* historically ignored */
327 if (!(s
= opt_info
.arg
))
330 * some compilers interpret `-I ...' as
331 * `-I-S' and arg ... while others interpret
336 if ((s
= argv
[opt_info
.index
]) && ((n
= *s
++) == '-' || n
== '+') && *s
++ == 'D')
338 if (isalpha(*s
) || *s
== '_')
339 while (isalnum(*++s
) || *s
== '_');
340 if (*s
&& *s
!= '=' && *s
!= '-' && *s
!= '+')
341 p
= argv
[opt_info
.index
++];
349 n
= *(p
= s
++) == '-';
351 if (!n
&& !*s
) s
= 0;
364 ppop(PP_HOSTDIR
, s
, n
);
370 ppop(PP_IGNORELIST
, s
);
376 ppop(PP_STANDARD
, s
);
382 ppop(PP_VENDOR
, s
, n
);
385 error(1, "%s: unknown -I option overload", p
);
395 for (n
= PP_deps
; argv
[opt_info
.index
]; opt_info
.offset
++)
397 switch (argv
[opt_info
.index
][opt_info
.offset
])
403 n
|= PP_deps_generated
;
411 ppop(PP_FILEDEPS
, n
);
414 ppop(PP_LINE
, (PPLINESYNC
)0);
417 ppop(PP_UNDEF
, opt_info
.arg
);
421 * System V CCS compatibility
425 if (isalpha(opt_info
.arg
[0]) || opt_info
.arg
[0] == '_' || opt_info
.arg
[0] == '$')
426 ppop(PP_ASSERT
, opt_info
.arg
);
429 ppop(PP_INCREF
, ppincref
);
432 if (!(pp
.arg_style
& STYLE_gnu
))
433 ppop(PP_TRUNCATE
, TRUNCLENGTH
);
434 /* else enable ANSI trigraphs -- default */
437 error(0, "%s", pp
.version
);
440 pp
.arg_mode
= (*(opt_info
.arg
+ 1) || pp
.arg_mode
&& pp
.arg_mode
!= *opt_info
.arg
) ? '-' : *opt_info
.arg
;
443 if (*(s
= opt_info
.arg
) && *(s
+ 1) == ',')
445 if (*s
!= 'I') break;
448 ppop(PP_STANDARD
, s
);
456 error(ERROR_USAGE
|4, "%s", opt_info
.arg
);
469 if (!(s
= argv
[opt_info
.index
]))
470 error(3, "%s", opt_info
.arg
);
471 if (opt_info
.offset
== 2 && (pp
.arg_style
& STYLE_gnu
))
473 p
= argv
[opt_info
.index
+ 1];
476 ppop(PP_OPTION
, "noid \"$\"");
479 else if (streq(s
, "-dD"))
481 pp
.option
|= DEFINITIONS
;
484 else if (streq(s
, "-dM"))
487 pp
.option
|= KEEPNOTEXT
|DEFINITIONS
|PREDEFINITIONS
;
491 else if (streq(s
, "-imacros"))
501 else if (streq(s
, "-include"))
512 else if (strneq(s
, "-lang-", 6))
517 else if (streq(s
, "c++"))
519 else if (streq(s
, "objc"))
521 else if (streq(s
, "objc++"))
523 ppop(PP_PLUSPLUS
, c
& 1);
525 ppop(PP_DIRECTIVE
, "pragma pp:map \"/#(pragma )?import>/\" \"/#(pragma )?import(.*)/__STDPP__IMPORT__(\\2)/\"\n\
526 #macdef __STDPP__IMPORT__(x)\n\
527 #pragma pp:noallmultiple\n\
529 #pragma pp:allmultiple\n\
533 else if (streq(s
, "-lint"))
535 ppop(PP_COMMENT
, pplint
);
539 s
+= opt_info
.offset
- 1;
540 if (strmatch(s
, "i*.h"))
541 ppop((pp
.arg_style
& STYLE_gnu
) || s
[1] == '/' ? PP_READ
: PP_TEXT
, s
+ 1);
542 else if (strmatch(s
, "*@(nostandard|nostdinc)*"))
543 ppop(PP_STANDARD
, "");
544 else if (strmatch(s
, "*@(exten|xansi)*|std"))
546 ppop(PP_COMPATIBILITY
, 0);
547 ppop(PP_TRANSITION
, 1);
549 else if (strmatch(s
, "*@(ansi|conform|pedantic|stand|std1|strict[!-])*"))
551 ppop(PP_COMPATIBILITY
, 0);
553 if (strmatch(s
, "*pedantic*"))
554 ppop(PP_PEDANTIC
, 1);
556 else if (strmatch(s
, "*@(trans)*"))
558 ppop(PP_COMPATIBILITY
, 1);
559 ppop(PP_TRANSITION
, 1);
561 else if (strmatch(s
, "*@(classic|compat|std0|tradition|[kK][n&+][rR])*"))
563 ppop(PP_COMPATIBILITY
, 1);
564 ppop(PP_TRANSITION
, 0);
566 else if (strmatch(s
, "*@(plusplus|++)*"))
567 ppop(PP_PLUSPLUS
, 1);
568 else if (strmatch(s
, "*@(warn)*"))
572 * ignore unknown options
573 * the probe info takes care of these
574 * fails if an option value is in the next arg
575 * and this is the last option
578 if (argv
[opt_info
.index
+ 1] && argv
[opt_info
.index
+ 1][0] != '-' && argv
[opt_info
.index
+ 2] && argv
[opt_info
.index
+ 2][0] == '-')
584 while (argv
[opt_info
.index
][opt_info
.offset
]) opt_info
.offset
++;
587 if (!(s
= argv
[opt_info
.index
])) return(0);
591 if (*s
!= '-' || *(s
+ 1)) ppop(PP_INPUT
, s
);
594 if (*s
!= '-' || *(s
+ 1)) ppop(PP_OUTPUT
, s
);
597 if (!last
) return(1);
598 error(1, "%s: extraneous argument ignored", s
);
602 if (!argv
[++opt_info
.index
]) return(0);
605 * old versions allow options after file args