1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1986-2011 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Eclipse Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.eclipse.org/org/documents/epl-v10.html * 11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * * 19 ***********************************************************************/ 20 #pragma prototyped 21 /* 22 * Glenn Fowler 23 * AT&T Research 24 * 25 * common preprocessor command line argument parse 26 * called by optjoin() 27 */ 28 29 static const char usage[] = 30 "[-?\n@(#)$Id: cpp (AT&T Research) 2009-02-02 $\n]" 31 USAGE_LICENSE 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.]" 43 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" 64 " \b-D-+\b.]" 65 " [+-D-K, pp::keyargs?Enable the non-standard \aname=value\a macro" 66 " argument mode.]" 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" 77 " K&R and ISO.]" 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" 87 " non-hosted files.]" 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.]" 94 "}" 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" 105 " is omitted.]" 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" 115 " omitted.]" 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" 118 " directory list.]" 119 " [+-I-T\afile\a?Include \afile\a and emit text to the output file.]" 120 "}" 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" 132 " styles.]" 133 "}" 134 "[P!:sync?Emit line syncs.]" 135 "[U:undefine?Remove the definition for the macro \aname\a.]:[name]" 136 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. If the optional \asize\a" 142 " argument is specified then the entire \b-H\b option is" 143 " ignored.]#?[size]" 144 "[T?If not \bgcc\b(1) then truncate identifiers to \alength\a" 145 " characters for compatibility with old AT&T (I guess only Lucent needs" 146 " them now) compilers.]#?[length]" 147 "[V:version?Emit the \blibpp\b(3) version.]" 148 "[X:argmode?Enable \aname\a=\avalue\a macro arguments for \beasel\b(1)" 149 " compatibility.]" 150 "[Y:standard?Add \adirectory\a to the list searched for" 151 " \b#include\b \b<...>\b files.]:[directory]" 152 153 "\n" 154 "\n[ input [ output ] ]\n" 155 "\n" 156 157 "[+SEE ALSO?\bcc\b(1), \bgcc\b(1), \blibpp\b(3)]" 158 ; 159 160 #include "pplib.h" 161 162 #include <ctype.h> 163 164 /* 165 * convert lint comments to pragmas 166 */ 167 168 static void 169 pplint(char* head, char* comment, char* tail, int line) 170 { 171 NoP(line); 172 if (strmatch(comment, "(ARGSUSED|PRINTFLIKE|PROTOLIB|SCANFLIKE|VARARGS)*([0-9])|CONSTCOND|CONSTANTCOND|CONSTANTCONDITION|EMPTY|FALLTHRU|FALLTHROUGH|LINTLIBRARY|LINTED*|NOTREACHED")) 173 { 174 strncopy(pp.token, comment, MAXTOKEN); 175 ppprintf("\n#%s %s:%s\n", dirname(PRAGMA), pp.pass, pp.token); 176 ppline(error_info.line, NiL); 177 } 178 } 179 180 /* 181 * if last!=0 then argv[opt_info.index]==0 with return(0) 182 * else if argv[opt_info.index]==0 then return(0) 183 * otherwise argv[opt_info.index] is the first unrecognized 184 * option with return(1) 185 * 186 * use last=0 if the preprocessor is combined with other passes 187 * so that unknown options may be interpreted for those passes 188 */ 189 190 int 191 ppargs(char** argv, int last) 192 { 193 register char* s; 194 register int c; 195 register int n; 196 char* p; 197 198 /* 199 * check the args and initialize 200 */ 201 202 if (!error_info.id) 203 error_info.id = "cpp"; 204 for (;;) 205 { 206 for (; c = optget(argv, usage); last = 0) switch (c) 207 { 208 case 'C': 209 ppop(PP_COMMENT, ppcomment); 210 break; 211 case 'D': 212 /* 213 * this allows single arg pp option extensions 214 * without touching cc 215 * (not all cc wrappers have -W...) 216 */ 217 218 switch (*(s = opt_info.arg)) 219 { 220 case '-': 221 case '+': 222 n = (*s++ == '-'); 223 while (c = *s++) switch (c) 224 { 225 case 'C': 226 ppop(PP_COMPATIBILITY, n); 227 break; 228 case 'D': 229 if (n && ((c = strtol(s, &p, 0)) || p != s)) 230 { 231 s = p; 232 n = c; 233 } 234 ppop(PP_DEBUG, -n); 235 break; 236 case 'F': 237 ppop(PP_FILENAME, n ? s : NiL); 238 goto hasarg; 239 case 'H': 240 ppop(PP_HOSTDIR, "-", n); 241 break; 242 case 'I': 243 ppop(PP_CDIR, "-", n); 244 break; 245 case 'K': 246 ppop(PP_KEYARGS, n); 247 break; 248 case 'L': 249 ppop(PP_LINEID, n && *s ? s : "line"); 250 goto hasarg; 251 case 'M': 252 ppop(PP_MULTIPLE, !n); 253 break; 254 case 'P': 255 ppop(PP_PASSTHROUGH, n); 256 break; 257 case 'Q': 258 ppop(PP_DUMP, n); 259 break; 260 case 'R': 261 ppop(PP_TRANSITION, n); 262 break; 263 case 'S': 264 ppop(PP_STRICT, n); 265 break; 266 case 'T': 267 ppop(PP_TEST, s); 268 goto hasarg; 269 case 'V': 270 ppop(PP_VENDOR, "-", n); 271 break; 272 case 'W': 273 ppop(PP_WARN, n); 274 break; 275 case 'X': 276 ppop(PP_PROBE, n && *s ? s : 0); 277 goto hasarg; 278 case 'Y': 279 ppop(PP_PEDANTIC, n); 280 break; 281 case 'Z': 282 ppop(PP_POOL, n); 283 break; 284 case 'd': 285 pp.option |= DEFINITIONS; 286 break; 287 case 'm': 288 pp.state |= NOTEXT; 289 pp.option |= KEEPNOTEXT|DEFINITIONS|PREDEFINITIONS; 290 pp.linesync = 0; 291 break; 292 case '+': 293 ppop(PP_PLUSPLUS, n); 294 break; 295 default: 296 if (pp.optarg) 297 { 298 if ((c = (*pp.optarg)(n, c, s)) > 0) goto hasarg; 299 else if (!c) break; 300 } 301 error(1, "%c%s: unknown -D option overload", n ? '-' : '+', s - 1); 302 goto hasarg; 303 } 304 hasarg: 305 break; 306 case ':': 307 ppop(PP_OPTION, s + 1); 308 break; 309 case '%': 310 ppop(PP_DIRECTIVE, s + 1); 311 break; 312 case '_': 313 if (strmatch(s, "__GNUC__*")) 314 pp.arg_style |= STYLE_gnu; 315 else if (strmatch(s, "__(ANSI|STDC|STRICT)__*") || !(pp.arg_style & STYLE_gnu) && strmatch(s, "__STRICT_ANSI__*")) 316 ppop(PP_STRICT, 1); 317 else if (strmatch(s, "__cplusplus*")) 318 ppop(PP_PLUSPLUS, 1); 319 /*FALLTHROUGH*/ 320 default: 321 ppop(PP_DEFINE, s); 322 break; 323 } 324 break; 325 case 'E': 326 /* historically ignored */ 327 break; 328 case 'I': 329 if (!(s = opt_info.arg)) 330 { 331 /* 332 * some compilers interpret `-I ...' as 333 * `-I-S' and arg ... while others interpret 334 * it as `-I...' 335 */ 336 337 p = "-S"; 338 if ((s = argv[opt_info.index]) && ((n = *s++) == '-' || n == '+') && *s++ == 'D') 339 { 340 if (isalpha(*s) || *s == '_') 341 while (isalnum(*++s) || *s == '_'); 342 if (*s && *s != '=' && *s != '-' && *s != '+') 343 p = argv[opt_info.index++]; 344 } 345 s = p; 346 } 347 switch (*s) 348 { 349 case '-': 350 case '+': 351 n = *(p = s++) == '-'; 352 c = *s++; 353 if (!n && !*s) s = 0; 354 switch (c) 355 { 356 case 0: 357 ppop(PP_LOCAL); 358 break; 359 case 'C': 360 ppop(PP_CDIR, s, n); 361 break; 362 case 'D': 363 ppop(PP_DEFAULT, s); 364 break; 365 case 'H': 366 ppop(PP_HOSTDIR, s, n); 367 break; 368 case 'I': 369 ppop(PP_IGNORE, s); 370 break; 371 case 'M': 372 ppop(PP_IGNORELIST, s); 373 break; 374 case 'R': 375 ppop(PP_READ, s); 376 break; 377 case 'S': 378 ppop(PP_STANDARD, s); 379 break; 380 case 'T': 381 ppop(PP_TEXT, s); 382 break; 383 case 'V': 384 ppop(PP_VENDOR, s, n); 385 break; 386 default: 387 error(1, "%s: unknown -I option overload", p); 388 break; 389 } 390 break; 391 default: 392 ppop(PP_INCLUDE, s); 393 break; 394 } 395 break; 396 case 'M': 397 for (n = PP_deps; argv[opt_info.index]; opt_info.offset++) 398 { 399 switch (argv[opt_info.index][opt_info.offset]) 400 { 401 case 'D': 402 n |= PP_deps_file; 403 continue; 404 case 'G': 405 n |= PP_deps_generated; 406 continue; 407 case 'M': 408 n |= PP_deps_local; 409 continue; 410 } 411 break; 412 } 413 ppop(PP_FILEDEPS, n); 414 break; 415 case 'P': 416 ppop(PP_LINE, (PPLINESYNC)0); 417 break; 418 case 'U': 419 ppop(PP_UNDEF, opt_info.arg); 420 break; 421 422 /* 423 * System V CCS compatibility 424 */ 425 426 case 'A': 427 if (isalpha(opt_info.arg[0]) || opt_info.arg[0] == '_' || opt_info.arg[0] == '$') 428 ppop(PP_ASSERT, opt_info.arg); 429 break; 430 case 'H': 431 if (!opt_info.arg) 432 ppop(PP_INCREF, ppincref); 433 break; 434 case 'T': 435 if (!(pp.arg_style & STYLE_gnu)) 436 ppop(PP_TRUNCATE, TRUNCLENGTH); 437 /* else enable ANSI trigraphs -- default */ 438 break; 439 case 'V': 440 error(0, "%s", pp.version); 441 break; 442 case 'X': 443 pp.arg_mode = (*(opt_info.arg + 1) || pp.arg_mode && pp.arg_mode != *opt_info.arg) ? '-' : *opt_info.arg; 444 break; 445 case 'Y': 446 if (*(s = opt_info.arg) && *(s + 1) == ',') 447 { 448 if (*s != 'I') break; 449 s += 2; 450 } 451 ppop(PP_STANDARD, s); 452 break; 453 454 /* 455 * errors 456 */ 457 458 case '?': 459 error(ERROR_USAGE|4, "%s", opt_info.arg); 460 break; 461 case ':': 462 if (!last) 463 { 464 opt_info.again = 1; 465 return(1); 466 } 467 468 /* 469 * cross your fingers 470 */ 471 472 if (!(s = argv[opt_info.index])) 473 error(3, "%s", opt_info.arg); 474 if (opt_info.offset == 2 && (pp.arg_style & STYLE_gnu)) 475 { 476 p = argv[opt_info.index + 1]; 477 if (streq(s, "-$")) 478 { 479 ppop(PP_OPTION, "noid \"$\""); 480 goto ignore; 481 } 482 else if (streq(s, "-dD")) 483 { 484 pp.option |= DEFINITIONS; 485 goto ignore; 486 } 487 else if (streq(s, "-dM")) 488 { 489 pp.state |= NOTEXT; 490 pp.option |= KEEPNOTEXT|DEFINITIONS|PREDEFINITIONS; 491 pp.linesync = 0; 492 goto ignore; 493 } 494 else if (streq(s, "-imacros")) 495 { 496 if (p) 497 { 498 ppop(PP_READ, p); 499 opt_info.index++; 500 opt_info.offset = 0; 501 } 502 goto ignore; 503 } 504 else if (streq(s, "-include")) 505 { 506 if (p) 507 { 508 ppop(PP_TEXT, p); 509 opt_info.index++; 510 opt_info.offset = 0; 511 } 512 opt_info.offset = 0; 513 goto ignore; 514 } 515 else if (strneq(s, "-lang-", 6)) 516 { 517 s += 6; 518 if (streq(s, "c")) 519 c = 0; 520 else if (streq(s, "c++")) 521 c = 1; 522 else if (streq(s, "objc")) 523 c = 2; 524 else if (streq(s, "objc++")) 525 c = 3; 526 ppop(PP_PLUSPLUS, c & 1); 527 if (c & 2) 528 ppop(PP_DIRECTIVE, "pragma pp:map \"/#(pragma )?import>/\" \"/#(pragma )?import(.*)/__STDPP__IMPORT__(\\2)/\"\n\ 529 #macdef __STDPP__IMPORT__(x)\n\ 530 #pragma pp:noallmultiple\n\ 531 #include x\n\ 532 #pragma pp:allmultiple\n\ 533 #endmac"); 534 goto ignore; 535 } 536 else if (streq(s, "-lint")) 537 { 538 ppop(PP_COMMENT, pplint); 539 goto ignore; 540 } 541 } 542 s += opt_info.offset - 1; 543 if (strmatch(s, "i*.h")) 544 ppop((pp.arg_style & STYLE_gnu) || s[1] == '/' ? PP_READ : PP_TEXT, s + 1); 545 else if (strmatch(s, "*@(nostandard|nostdinc)*")) 546 ppop(PP_STANDARD, ""); 547 else if (strmatch(s, "*@(exten|xansi)*|std")) 548 { 549 ppop(PP_COMPATIBILITY, 0); 550 ppop(PP_TRANSITION, 1); 551 } 552 else if (strmatch(s, "*@(ansi|conform|pedantic|stand|std1|strict[!-])*")) 553 { 554 ppop(PP_COMPATIBILITY, 0); 555 ppop(PP_STRICT, 1); 556 if (strmatch(s, "*pedantic*")) 557 ppop(PP_PEDANTIC, 1); 558 } 559 else if (strmatch(s, "*@(trans)*")) 560 { 561 ppop(PP_COMPATIBILITY, 1); 562 ppop(PP_TRANSITION, 1); 563 } 564 else if (strmatch(s, "*@(classic|compat|std0|tradition|[kK][n&+][rR])*")) 565 { 566 ppop(PP_COMPATIBILITY, 1); 567 ppop(PP_TRANSITION, 0); 568 } 569 else if (strmatch(s, "*@(plusplus|++)*")) 570 ppop(PP_PLUSPLUS, 1); 571 else if (strmatch(s, "*@(warn)*")) 572 ppop(PP_WARN, 1); 573 574 /* 575 * ignore unknown options 576 * the probe info takes care of these 577 * fails if an option value is in the next arg 578 * and this is the last option 579 */ 580 581 if (argv[opt_info.index + 1] && argv[opt_info.index + 1][0] != '-' && argv[opt_info.index + 2] && argv[opt_info.index + 2][0] == '-') 582 { 583 opt_info.index++; 584 opt_info.offset = 0; 585 } 586 ignore: 587 while (argv[opt_info.index][opt_info.offset]) opt_info.offset++; 588 break; 589 } 590 if (!(s = argv[opt_info.index])) return(0); 591 switch (pp.arg_file) 592 { 593 case 0: 594 if (*s != '-' || *(s + 1)) ppop(PP_INPUT, s); 595 break; 596 case 1: 597 if (*s != '-' || *(s + 1)) ppop(PP_OUTPUT, s); 598 break; 599 default: 600 if (!last) return(1); 601 error(1, "%s: extraneous argument ignored", s); 602 break; 603 } 604 pp.arg_file++; 605 if (!argv[++opt_info.index]) return(0); 606 607 /* 608 * old versions allow options after file args 609 */ 610 } 611 } 612