1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include <stdio.h> 29 #include <ctype.h> 30 #include "cppdef.h" 31 #include "cpp.h" 32 #if HOST == SYS_VMS 33 /* 34 * Include the rms stuff. (We can't just include rms.h as it uses the 35 * VaxC-specific library include syntax that Decus CPP doesn't support. 36 * By including things by hand, we can CPP ourself.) 37 */ 38 #include <nam.h> 39 #include <fab.h> 40 #include <rab.h> 41 #include <rmsdef.h> 42 #endif 43 44 /* 45 * Generate (by hand-inspection) a set of unique values for each control 46 * operator. Note that this is not guaranteed to work for non-Ascii 47 * machines. CPP won't compile if there are hash conflicts. 48 */ 49 50 #define L_assert ('a' + ('s' << 1)) 51 #define L_define ('d' + ('f' << 1)) 52 #define L_elif ('e' + ('i' << 1)) 53 #define L_else ('e' + ('s' << 1)) 54 #define L_endif ('e' + ('d' << 1)) 55 #define L_if ('i' + (EOS << 1)) 56 #define L_ifdef ('i' + ('d' << 1)) 57 #define L_ifndef ('i' + ('n' << 1)) 58 #define L_include ('i' + ('c' << 1)) 59 #define L_line ('l' + ('n' << 1)) 60 #define L_nogood (EOS + (EOS << 1)) /* To catch #i */ 61 #define L_pragma ('p' + ('a' << 1)) 62 #define L_undef ('u' + ('d' << 1)) 63 #define L_error ('e' + ('r' << 1)) /* BP 5.3.92, #error */ 64 #define MAXLINE 80 /* BP 5.3.92, #error */ 65 #if OSL_DEBUG_LEVEL > 1 66 #define L_debug ('d' + ('b' << 1)) /* #debug */ 67 #define L_nodebug ('n' + ('d' << 1)) /* #nodebug */ 68 #endif 69 70 71 void InitCpp2() 72 { 73 74 } 75 76 77 int 78 control(int counter) 79 /* 80 * Process #control lines. Simple commands are processed inline, 81 * while complex commands have their own subroutines. 82 * 83 * The counter is used to force out a newline before #line, and 84 * #pragma commands. This prevents these commands from ending up at 85 * the end of the previous line if cpp is invoked with the -C option. 86 */ 87 { 88 register int c; 89 register char *tp; 90 register int hash; 91 char *ep; 92 93 c = skipws(); 94 if (c == '\n' || c == EOF_CHAR) 95 return (counter + 1); 96 if (!isdigit(c)) 97 scanid(c); /* Get #word to token[] */ 98 else { 99 unget(); /* Hack -- allow #123 as a */ 100 strcpy(token, "line"); /* synonym for #line 123 */ 101 } 102 hash = (token[1] == EOS) ? L_nogood : (token[0] + (token[2] << 1)); 103 switch (hash) { 104 case L_assert: tp = "assert"; break; 105 case L_define: tp = "define"; break; 106 case L_elif: tp = "elif"; break; 107 case L_else: tp = "else"; break; 108 case L_endif: tp = "endif"; break; 109 case L_if: tp = "if"; break; 110 case L_ifdef: tp = "ifdef"; break; 111 case L_ifndef: tp = "ifndef"; break; 112 case L_include: tp = "include"; break; 113 case L_line: tp = "line"; break; 114 case L_pragma: tp = "pragma"; break; 115 case L_undef: tp = "undef"; break; 116 case L_error: tp = "error"; break; 117 #if OSL_DEBUG_LEVEL > 1 118 case L_debug: tp = "debug"; break; 119 case L_nodebug: tp = "nodebug"; break; 120 #endif 121 default: hash = L_nogood; 122 case L_nogood: tp = ""; break; 123 } 124 if (!streq(tp, token)) 125 hash = L_nogood; 126 /* 127 * hash is set to a unique value corresponding to the 128 * control keyword (or L_nogood if we think it's nonsense). 129 */ 130 if (infile->fp == NULL) 131 cwarn("Control line \"%s\" within macro expansion", token); 132 if (!compiling) { /* Not compiling now */ 133 switch (hash) { 134 case L_if: /* These can't turn */ 135 case L_ifdef: /* compilation on, but */ 136 case L_ifndef: /* we must nest #if's */ 137 if (++ifptr >= &ifstack[BLK_NEST]) 138 goto if_nest_err; 139 *ifptr = 0; /* !WAS_COMPILING */ 140 case L_line: /* Many */ 141 /* 142 * Are pragma's always processed? 143 */ 144 case L_pragma: /* options */ 145 case L_include: /* are uninteresting */ 146 case L_define: /* if we */ 147 case L_undef: /* aren't */ 148 case L_assert: /* compiling. */ 149 case L_error: /* BP 5.3.92, #error */ 150 dump_line: skipnl(); /* Ignore rest of line */ 151 return (counter + 1); 152 } 153 } 154 /* 155 * Make sure that #line and #pragma are output on a fresh line. 156 */ 157 if (counter > 0 && (hash == L_line || hash == L_pragma)) { 158 PUTCHAR('\n'); 159 counter--; 160 } 161 switch (hash) { 162 case L_line: 163 /* 164 * Parse the line to update the line number and "progname" 165 * field and line number for the next input line. 166 * Set wrongline to force it out later. 167 */ 168 c = skipws(); 169 workp = work; /* Save name in work */ 170 while (c != '\n' && c != EOF_CHAR) { 171 save(c); 172 c = get(); 173 } 174 unget(); 175 save(EOS); 176 /* 177 * Split #line argument into <line-number> and <name> 178 * We subtract 1 as we want the number of the next line. 179 */ 180 line = atoi(work) - 1; /* Reset line number */ 181 for (tp = work; isdigit(*tp) || type[(int)*tp] == SPA; tp++) 182 ; /* Skip over digits */ 183 if (*tp != EOS) { /* Got a filename, so: */ 184 if (*tp == '"' && (ep = strrchr(tp + 1, '"')) != NULL) { 185 tp++; /* Skip over left quote */ 186 *ep = EOS; /* And ignore right one */ 187 } 188 if (infile->progname != NULL) /* Give up the old name */ 189 free(infile->progname); /* if it's allocated. */ 190 infile->progname = savestring(tp); 191 } 192 wrongline = TRUE; /* Force output later */ 193 break; 194 195 case L_include: 196 doinclude(); 197 break; 198 199 case L_define: 200 dodefine(); 201 break; 202 203 case L_undef: 204 doundef(); 205 break; 206 207 case L_else: 208 if (ifptr == &ifstack[0]) 209 goto nest_err; 210 else if ((*ifptr & ELSE_SEEN) != 0) 211 goto else_seen_err; 212 *ifptr |= ELSE_SEEN; 213 if ((*ifptr & WAS_COMPILING) != 0) { 214 if (compiling || (*ifptr & TRUE_SEEN) != 0) 215 compiling = FALSE; 216 else { 217 compiling = TRUE; 218 } 219 } 220 break; 221 222 case L_elif: 223 if (ifptr == &ifstack[0]) 224 goto nest_err; 225 else if ((*ifptr & ELSE_SEEN) != 0) { 226 else_seen_err: cerror("#%s may not follow #else", token); 227 goto dump_line; 228 } 229 if ((*ifptr & (WAS_COMPILING | TRUE_SEEN)) != WAS_COMPILING) { 230 compiling = FALSE; /* Done compiling stuff */ 231 goto dump_line; /* Skip this clause */ 232 } 233 doif(L_if); 234 break; 235 236 case L_if: 237 case L_ifdef: 238 case L_ifndef: 239 if (++ifptr >= &ifstack[BLK_NEST]) 240 if_nest_err: cfatal("Too many nested #%s statements", token); 241 *ifptr = WAS_COMPILING; 242 doif(hash); 243 break; 244 245 case L_endif: 246 if (ifptr == &ifstack[0]) { 247 nest_err: cerror("#%s must be in an #if", token); 248 goto dump_line; 249 } 250 if (!compiling && (*ifptr & WAS_COMPILING) != 0) 251 wrongline = TRUE; 252 compiling = ((*ifptr & WAS_COMPILING) != 0); 253 --ifptr; 254 break; 255 256 case L_assert: 257 if (eval() == 0) 258 cerror("Preprocessor assertion failure", NULLST); 259 break; 260 261 case L_pragma: 262 /* 263 * #pragma is provided to pass "options" to later 264 * passes of the compiler. cpp doesn't have any yet. 265 */ 266 fprintf( pCppOut, "#pragma "); 267 while ((c = get()) != '\n' && c != EOF_CHAR) 268 cput(c); 269 unget(); 270 break; 271 272 #if OSL_DEBUG_LEVEL > 1 273 case L_debug: 274 if (debug == 0) 275 dumpdef("debug set on"); 276 debug++; 277 break; 278 279 case L_nodebug: 280 debug--; 281 break; 282 #endif 283 case L_error: /* BP 5.3.92, #error */ 284 { 285 fprintf( pCppOut, "cpp: line %u, Error directive: ", line ); 286 while ((c = get()) != '\n' && c != EOF_CHAR) 287 cput(c); 288 fprintf( pCppOut, "\n" ); 289 exit( 1 ); 290 break; 291 } 292 default: 293 /* 294 * Undefined #control keyword. 295 * Note: the correct behavior may be to warn and 296 * pass the line to a subsequent compiler pass. 297 * This would allow #asm or similar extensions. 298 */ 299 cerror("Illegal # command \"%s\"", token); 300 break; 301 } 302 if (hash != L_include) { 303 #if OLD_PREPROCESSOR 304 /* 305 * Ignore the rest of the #control line so you can write 306 * #if foo 307 * #endif foo 308 */ 309 goto dump_line; /* Take common exit */ 310 #else 311 if (skipws() != '\n') { 312 cwarn("Unexpected text in #control line ignored", NULLST); 313 skipnl(); 314 } 315 #endif 316 } 317 return (counter + 1); 318 } 319 320 FILE_LOCAL 321 void doif(int hash) 322 /* 323 * Process an #if, #ifdef, or #ifndef. The latter two are straightforward, 324 * while #if needs a subroutine of its own to evaluate the expression. 325 * 326 * doif() is called only if compiling is TRUE. If false, compilation 327 * is always supressed, so we don't need to evaluate anything. This 328 * supresses unnecessary warnings. 329 */ 330 { 331 register int c; 332 register int found; 333 334 if ((c = skipws()) == '\n' || c == EOF_CHAR) { 335 unget(); 336 goto badif; 337 } 338 if (hash == L_if) { 339 unget(); 340 found = (eval() != 0); /* Evaluate expr, != 0 is TRUE */ 341 hash = L_ifdef; /* #if is now like #ifdef */ 342 } 343 else { 344 if (type[c] != LET) /* Next non-blank isn't letter */ 345 goto badif; /* ... is an error */ 346 found = (lookid(c) != NULL); /* Look for it in symbol table */ 347 } 348 if (found == (hash == L_ifdef)) { 349 compiling = TRUE; 350 *ifptr |= TRUE_SEEN; 351 } 352 else { 353 compiling = FALSE; 354 } 355 return; 356 357 badif: cerror("#if, #ifdef, or #ifndef without an argument", NULLST); 358 #if !OLD_PREPROCESSOR 359 skipnl(); /* Prevent an extra */ 360 unget(); /* Error message */ 361 #endif 362 return; 363 } 364 365 FILE_LOCAL 366 void doinclude() 367 /* 368 * Process the #include control line. 369 * There are three variations: 370 * #include "file" search somewhere relative to the 371 * current source file, if not found, 372 * treat as #include <file>. 373 * #include <file> Search in an implementation-dependent 374 * list of places. 375 * #include token Expand the token, it must be one of 376 * "file" or <file>, process as such. 377 * 378 * Note: the November 12 draft forbids '>' in the #include <file> format. 379 * This restriction is unnecessary and not implemented. 380 */ 381 { 382 register int c; 383 register int delim; 384 #if HOST == SYS_VMS 385 char def_filename[NAM$C_MAXRSS + 1]; 386 #endif 387 388 delim = macroid(skipws()); 389 if (delim != '<' && delim != '"') 390 goto incerr; 391 if (delim == '<') 392 delim = '>'; 393 workp = work; 394 instring = TRUE; /* Accept all characters */ 395 #ifdef CONTROL_COMMENTS_NOT_ALLOWED 396 while ((c = get()) != '\n' && c != EOF_CHAR) 397 save(c); /* Put it away. */ 398 unget(); /* Force nl after includee */ 399 /* 400 * The draft is unclear if the following should be done. 401 */ 402 while (--workp >= work && *workp == ' ') 403 ; /* Trim blanks from filename */ 404 if (*workp != delim) 405 goto incerr; 406 #else 407 while ((c = get()) != delim && c != EOF_CHAR) 408 save(c); 409 #endif 410 *workp = EOS; /* Terminate filename */ 411 instring = FALSE; 412 #if HOST == SYS_VMS 413 /* 414 * Assume the default .h filetype. 415 */ 416 if (!vmsparse(work, ".H", def_filename)) { 417 perror(work); /* Oops. */ 418 goto incerr; 419 } 420 else if (openinclude(def_filename, (delim == '"'))) 421 return; 422 #else 423 if (openinclude(work, (delim == '"'))) 424 return; 425 #endif 426 /* 427 * No sense continuing if #include file isn't there. 428 */ 429 cfatal("Cannot open include file \"%s\"", work); 430 431 incerr: cerror("#include syntax error", NULLST); 432 return; 433 } 434 435 FILE_LOCAL int 436 openinclude(char* filename, int searchlocal) 437 /* 438 * Actually open an include file. This routine is only called from 439 * doinclude() above, but was written as a separate subroutine for 440 * programmer convenience. It searches the list of directories 441 * and actually opens the file, linking it into the list of 442 * active files. Returns TRUE if the file was opened, FALSE 443 * if openinclude() fails. No error message is printed. 444 */ 445 { 446 register char **incptr; 447 #if HOST == SYS_VMS 448 #if NFWORK < (NAM$C_MAXRSS + 1) 449 << error, NFWORK is not greater than NAM$C_MAXRSS >> 450 #endif 451 #endif 452 char tmpname[NFWORK]; /* Filename work area */ 453 454 if (searchlocal) { 455 /* 456 * Look in local directory first 457 */ 458 #if HOST == SYS_UNIX 459 /* 460 * Try to open filename relative to the directory of the current 461 * source file (as opposed to the current directory). (ARF, SCK). 462 */ 463 if (filename[0] != '/' 464 && hasdirectory(infile->filename, tmpname)) 465 strcat(tmpname, filename); 466 else { 467 strcpy(tmpname, filename); 468 } 469 #else 470 if (!hasdirectory(filename, tmpname) 471 && hasdirectory(infile->filename, tmpname)) 472 strcat(tmpname, filename); 473 else { 474 strcpy(tmpname, filename); 475 } 476 #endif 477 if (openfile(tmpname)) 478 return (TRUE); 479 } 480 /* 481 * Look in any directories specified by -I command line 482 * arguments, then in the builtin search list. 483 */ 484 for (incptr = incdir; incptr < incend; incptr++) { 485 if (strlen(*incptr) + strlen(filename) >= (NFWORK - 1)) 486 cfatal("Filename work buffer overflow", NULLST); 487 else { 488 #if HOST == SYS_UNIX 489 if (filename[0] == '/') 490 strcpy(tmpname, filename); 491 else { 492 sprintf(tmpname, "%s/%s", *incptr, filename); 493 } 494 #elif HOST == SYS_UNKNOWN 495 if (filename[0] == '\\') 496 strcpy(tmpname, filename); 497 else { 498 sprintf(tmpname, "%s\\%s", *incptr, filename); 499 } 500 #else 501 if (!hasdirectory(filename, tmpname)) 502 sprintf(tmpname, "%s%s", *incptr, filename); 503 #endif 504 if (openfile(tmpname)) 505 return (TRUE); 506 } 507 } 508 return (FALSE); 509 } 510 511 FILE_LOCAL int 512 hasdirectory(char* source, char* result) 513 /* 514 * If a device or directory is found in the source filename string, the 515 * node/device/directory part of the string is copied to result and 516 * hasdirectory returns TRUE. Else, nothing is copied and it returns FALSE. 517 */ 518 { 519 #if HOST == SYS_UNIX 520 register char *tp; 521 522 if ((tp = strrchr(source, '/')) == NULL) 523 return (FALSE); 524 else { 525 strncpy(result, source, tp - source + 1); 526 result[tp - source + 1] = EOS; 527 return (TRUE); 528 } 529 #else 530 #if HOST == SYS_VMS 531 if (vmsparse(source, NULLST, result) 532 && result[0] != EOS) 533 return (TRUE); 534 else { 535 return (FALSE); 536 } 537 #else 538 /* 539 * Random DEC operating system (RSX, RT11, RSTS/E) 540 */ 541 register char *tp; 542 543 if ((tp = strrchr(source, ']')) == NULL 544 && (tp = strrchr(source, ':')) == NULL) 545 return (FALSE); 546 else { 547 strncpy(result, source, tp - source + 1); 548 result[tp - source + 1] = EOS; 549 return (TRUE); 550 } 551 #endif 552 #endif 553 } 554 555 #if HOST == SYS_VMS 556 557 /* 558 * EXP_DEV is set if a device was specified, EXP_DIR if a directory 559 * is specified. (Both set indicate a file-logical, but EXP_DEV 560 * would be set by itself if you are reading, say, SYS$INPUT:) 561 */ 562 #define DEVDIR (NAM$M_EXP_DEV | NAM$M_EXP_DIR) 563 564 FILE_LOCAL int 565 vmsparse(source, defstring, result) 566 char *source; 567 char *defstring; /* non-NULL -> default string. */ 568 char *result; /* Size is at least NAM$C_MAXRSS + 1 */ 569 /* 570 * Parse the source string, applying the default (properly, using 571 * the system parse routine), storing it in result. 572 * TRUE if it parsed, FALSE on error. 573 * 574 * If defstring is NULL, there are no defaults and result gets 575 * (just) the node::[directory] part of the string (possibly "") 576 */ 577 { 578 struct FAB fab = cc$rms_fab; /* File access block */ 579 struct NAM nam = cc$rms_nam; /* File name block */ 580 char fullname[NAM$C_MAXRSS + 1]; 581 register char *rp; /* Result pointer */ 582 583 fab.fab$l_nam = &nam; /* fab -> nam */ 584 fab.fab$l_fna = source; /* Source filename */ 585 fab.fab$b_fns = strlen(source); /* Size of source */ 586 fab.fab$l_dna = defstring; /* Default string */ 587 if (defstring != NULLST) 588 fab.fab$b_dns = strlen(defstring); /* Size of default */ 589 nam.nam$l_esa = fullname; /* Expanded filename */ 590 nam.nam$b_ess = NAM$C_MAXRSS; /* Expanded name size */ 591 if (sys$parse(&fab) == RMS$_NORMAL) { /* Parse away */ 592 fullname[nam.nam$b_esl] = EOS; /* Terminate string */ 593 result[0] = EOS; /* Just in case */ 594 rp = &result[0]; 595 /* 596 * Remove stuff added implicitly, accepting node names and 597 * dev:[directory] strings (but not process-permanent files). 598 */ 599 if ((nam.nam$l_fnb & NAM$M_PPF) == 0) { 600 if ((nam.nam$l_fnb & NAM$M_NODE) != 0) { 601 strncpy(result, nam.nam$l_node, nam.nam$b_node); 602 rp += nam.nam$b_node; 603 *rp = EOS; 604 } 605 if ((nam.nam$l_fnb & DEVDIR) == DEVDIR) { 606 strncpy(rp, nam.nam$l_dev, nam.nam$b_dev + nam.nam$b_dir); 607 rp += nam.nam$b_dev + nam.nam$b_dir; 608 *rp = EOS; 609 } 610 } 611 if (defstring != NULLST) { 612 strncpy(rp, nam.nam$l_name, nam.nam$b_name + nam.nam$b_type); 613 rp += nam.nam$b_name + nam.nam$b_type; 614 *rp = EOS; 615 if ((nam.nam$l_fnb & NAM$M_EXP_VER) != 0) { 616 strncpy(rp, nam.nam$l_ver, nam.nam$b_ver); 617 rp[nam.nam$b_ver] = EOS; 618 } 619 } 620 return (TRUE); 621 } 622 return (FALSE); 623 } 624 #endif 625 626