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 /* 33 * parm[], parmp, and parlist[] are used to store #define() argument 34 * lists. nargs contains the actual number of parameters stored. 35 */ 36 static char parm[NPARMWORK + 1]; /* define param work buffer */ 37 static char *parmp; /* Free space in parm */ 38 static char *parlist[LASTPARM]; /* -> start of each parameter */ 39 static int nargs; /* Parameters for this macro */ 40 41 void InitCpp4() 42 { 43 int i; 44 for( i = 0; i < NPARMWORK; i++ ) 45 parm[ i ] = 0; 46 for( i = 0; i < LASTPARM; i++ ) 47 parlist[ i ] = NULL; 48 49 nargs = 0; 50 } 51 52 53 void dodefine() 54 /* 55 * Called from control when a #define is scanned. This module 56 * parses formal parameters and the replacement string. When 57 * the formal parameter name is encountered in the replacement 58 * string, it is replaced by a character in the range 128 to 59 * 128+NPARAM (this allows up to 32 parameters within the 60 * Dec Multinational range). If cpp is ported to an EBCDIC 61 * machine, you will have to make other arrangements. 62 * 63 * There is some special case code to distinguish 64 * #define foo bar 65 * from #define foo() bar 66 * 67 * Also, we make sure that 68 * #define foo foo 69 * expands to "foo" but doesn't put cpp into an infinite loop. 70 * 71 * A warning message is printed if you redefine a symbol to a 72 * different text. I.e, 73 * #define foo 123 74 * #define foo 123 75 * is ok, but 76 * #define foo 123 77 * #define foo +123 78 * is not. 79 * 80 * The following subroutines are called from define(): 81 * checkparm called when a token is scanned. It checks through the 82 * array of formal parameters. If a match is found, the 83 * token is replaced by a control byte which will be used 84 * to locate the parameter when the macro is expanded. 85 * textput puts a string in the macro work area (parm[]), updating 86 * parmp to point to the first free byte in parm[]. 87 * textput() tests for work buffer overflow. 88 * charput puts a single character in the macro work area (parm[]) 89 * in a manner analogous to textput(). 90 */ 91 { 92 register int c; 93 register DEFBUF *dp; /* -> new definition */ 94 int isredefine; /* TRUE if redefined */ 95 char *old = 0; /* Remember redefined */ 96 97 if (type[(c = skipws())] != LET) 98 goto bad_define; 99 isredefine = FALSE; /* Set if redefining */ 100 if ((dp = lookid(c)) == NULL) /* If not known now */ 101 dp = defendel(token, FALSE); /* Save the name */ 102 else { /* It's known: */ 103 isredefine = TRUE; /* Remember this fact */ 104 old = dp->repl; /* Remember replacement */ 105 dp->repl = NULL; /* No replacement now */ 106 } 107 parlist[0] = parmp = parm; /* Setup parm buffer */ 108 if ((c = get()) == '(') { /* With arguments? */ 109 nargs = 0; /* Init formals counter */ 110 do { /* Collect formal parms */ 111 if (nargs >= LASTPARM) 112 cfatal("Too many arguments for macro", NULLST); 113 else if ((c = skipws()) == ')') 114 break; /* Got them all */ 115 else if (type[c] != LET) /* Bad formal syntax */ 116 goto bad_define; 117 scanid(c); /* Get the formal param */ 118 parlist[nargs++] = parmp; /* Save its start */ 119 textput(token); /* Save text in parm[] */ 120 } while ((c = skipws()) == ','); /* Get another argument */ 121 if (c != ')') /* Must end at ) */ 122 goto bad_define; 123 c = ' '; /* Will skip to body */ 124 } 125 else { 126 /* 127 * DEF_NOARGS is needed to distinguish between 128 * "#define foo" and "#define foo()". 129 */ 130 nargs = DEF_NOARGS; /* No () parameters */ 131 } 132 if (type[c] == SPA) /* At whitespace? */ 133 c = skipws(); /* Not any more. */ 134 workp = work; /* Replacement put here */ 135 inmacro = TRUE; /* Keep \<newline> now */ 136 while (c != EOF_CHAR && c != '\n') { /* Compile macro body */ 137 #if OK_CONCAT 138 #if COMMENT_INVISIBLE 139 if (c == COM_SEP) { /* Token concatenation? */ 140 save(TOK_SEP); /* Stuff a delimiter */ 141 c = get(); 142 #else 143 if (c == '#') { /* Token concatenation? */ 144 while (workp > work && type[(int)workp[-1]] == SPA) 145 --workp; /* Erase leading spaces */ 146 save(TOK_SEP); /* Stuff a delimiter */ 147 c = skipws(); /* Eat whitespace */ 148 #endif 149 if (type[c] == LET) /* Another token here? */ 150 ; /* Stuff it normally */ 151 else if (type[c] == DIG) { /* Digit string after? */ 152 while (type[c] == DIG) { /* Stuff the digits */ 153 save(c); 154 c = get(); 155 } 156 save(TOK_SEP); /* Delimit 2nd token */ 157 } 158 else { 159 #if ! COMMENT_INVISIBLE 160 ciwarn("Strange character after # (%d.)", c); 161 #endif 162 } 163 continue; 164 } 165 #endif 166 switch (type[c]) { 167 case LET: 168 checkparm(c, dp); /* Might be a formal */ 169 break; 170 171 case DIG: /* Number in mac. body */ 172 case DOT: /* Maybe a float number */ 173 scannumber(c, save); /* Scan it off */ 174 break; 175 176 case QUO: /* String in mac. body */ 177 #if STRING_FORMAL 178 stparmscan(c, dp); /* Do string magic */ 179 #else 180 stparmscan(c); 181 #endif 182 break; 183 184 case BSH: /* Backslash */ 185 save('\\'); 186 if ((c = get()) == '\n') 187 wrongline = TRUE; 188 save(c); 189 break; 190 191 case SPA: /* Absorb whitespace */ 192 /* 193 * Note: the "end of comment" marker is passed on 194 * to allow comments to separate tokens. 195 */ 196 if (workp[-1] == ' ') /* Absorb multiple */ 197 break; /* spaces */ 198 else if (c == '\t') 199 c = ' '; /* Normalize tabs */ 200 /* Fall through to store character */ 201 default: /* Other character */ 202 save(c); 203 break; 204 } 205 c = get(); 206 } 207 inmacro = FALSE; /* Stop newline hack */ 208 unget(); /* For control check */ 209 if (workp > work && workp[-1] == ' ') /* Drop trailing blank */ 210 workp--; 211 *workp = EOS; /* Terminate work */ 212 dp->repl = savestring(work); /* Save the string */ 213 dp->nargs = nargs; /* Save arg count */ 214 #if OSL_DEBUG_LEVEL > 1 215 if (debug) 216 dumpadef("macro definition", dp); 217 else if (bDumpDefs) 218 dumpadef(NULL, dp); 219 #endif 220 if (isredefine) { /* Error if redefined */ 221 if ((old != NULL && dp->repl != NULL && !streq(old, dp->repl)) 222 || (old == NULL && dp->repl != NULL) 223 || (old != NULL && dp->repl == NULL)) { 224 #ifdef STRICT_UNDEF 225 cerror("Redefining defined variable \"%s\"", dp->name); 226 #else 227 cwarn("Redefining defined variable \"%s\"", dp->name); 228 #endif 229 } 230 if (old != NULL) /* We don't need the */ 231 free(old); /* old definition now. */ 232 } 233 return; 234 235 bad_define: 236 cerror("#define syntax error", NULLST); 237 inmacro = FALSE; /* Stop <newline> hack */ 238 } 239 240 void checkparm(int c, DEFBUF* dp) 241 /* 242 * Replace this param if it's defined. Note that the macro name is a 243 * possible replacement token. We stuff DEF_MAGIC in front of the token 244 * which is treated as a LETTER by the token scanner and eaten by 245 * the output routine. This prevents the macro expander from 246 * looping if someone writes "#define foo foo". 247 */ 248 { 249 register int i; 250 register char *cp; 251 252 scanid(c); /* Get parm to token[] */ 253 for (i = 0; i < nargs; i++) { /* For each argument */ 254 if (streq(parlist[i], token)) { /* If it's known */ 255 #ifdef SOLAR 256 save(DEL); 257 #endif 258 save(i + MAC_PARM); /* Save a magic cookie */ 259 return; /* And exit the search */ 260 } 261 } 262 if (streq(dp->name, token)) /* Macro name in body? */ 263 save(DEF_MAGIC); /* Save magic marker */ 264 for (cp = token; *cp != EOS;) /* And save */ 265 save(*cp++); /* The token itself */ 266 } 267 268 #if STRING_FORMAL 269 void stparmscan(delim, dp) 270 int delim; 271 register DEFBUF *dp; 272 /* 273 * Scan the string (starting with the given delimiter). 274 * The token is replaced if it is the only text in this string or 275 * character constant. The algorithm follows checkparm() above. 276 * Note that scanstring() has approved of the string. 277 */ 278 { 279 register int c; 280 281 /* 282 * Warning -- this code hasn't been tested for a while. 283 * It exists only to preserve compatibility with earlier 284 * implementations of cpp. It is not part of the Draft 285 * ANSI Standard C language. 286 */ 287 save(delim); 288 instring = TRUE; 289 while ((c = get()) != delim 290 && c != '\n' 291 && c != EOF_CHAR) { 292 if (type[c] == LET) /* Maybe formal parm */ 293 checkparm(c, dp); 294 else { 295 save(c); 296 if (c == '\\') 297 save(get()); 298 } 299 } 300 instring = FALSE; 301 if (c != delim) 302 cerror("Unterminated string in macro body", NULLST); 303 save(c); 304 } 305 #else 306 void stparmscan(int delim) 307 /* 308 * Normal string parameter scan. 309 */ 310 { 311 register char *wp; 312 register int i; 313 314 wp = workp; /* Here's where it starts */ 315 if (!scanstring(delim, save)) 316 return; /* Exit on scanstring error */ 317 workp[-1] = EOS; /* Erase trailing quote */ 318 wp++; /* -> first string content byte */ 319 for (i = 0; i < nargs; i++) { 320 if (streq(parlist[i], wp)) { 321 #ifdef SOLAR 322 *wp++ = DEL; 323 *wp++ = MAC_PARM + PAR_MAC; /* Stuff a magic marker */ 324 *wp++ = (char)(i + MAC_PARM); /* Make a formal marker */ 325 *wp = wp[-4]; /* Add on closing quote */ 326 workp = wp + 1; /* Reset string end */ 327 #else 328 *wp++ = MAC_PARM + PAR_MAC; /* Stuff a magic marker */ 329 *wp++ = (i + MAC_PARM); /* Make a formal marker */ 330 *wp = wp[-3]; /* Add on closing quote */ 331 workp = wp + 1; /* Reset string end */ 332 #endif 333 return; 334 } 335 } 336 workp[-1] = wp[-1]; /* Nope, reset end quote. */ 337 } 338 #endif 339 340 void doundef() 341 /* 342 * Remove the symbol from the defined list. 343 * Called from the #control processor. 344 */ 345 { 346 register int c; 347 348 if (type[(c = skipws())] != LET) 349 cerror("Illegal #undef argument", NULLST); 350 else { 351 scanid(c); /* Get name to token[] */ 352 if (defendel(token, TRUE) == NULL) { 353 #ifdef STRICT_UNDEF 354 cwarn("Symbol \"%s\" not defined in #undef", token); 355 #endif 356 } 357 } 358 } 359 360 void textput(char* text) 361 /* 362 * Put the string in the parm[] buffer. 363 */ 364 { 365 register int size; 366 367 size = strlen(text) + 1; 368 if ((parmp + size) >= &parm[NPARMWORK]) 369 cfatal("Macro work area overflow", NULLST); 370 else { 371 strcpy(parmp, text); 372 parmp += size; 373 } 374 } 375 376 void charput(int c) 377 /* 378 * Put the byte in the parm[] buffer. 379 */ 380 { 381 if (parmp >= &parm[NPARMWORK]) 382 cfatal("Macro work area overflow", NULLST); 383 else { 384 *parmp++ = (char)c; 385 } 386 } 387 388 /* 389 * M a c r o E x p a n s i o n 390 */ 391 392 static DEFBUF *macro; /* Catches start of infinite macro */ 393 394 void expand(DEFBUF* tokenp) 395 /* 396 * Expand a macro. Called from the cpp mainline routine (via subroutine 397 * macroid()) when a token is found in the symbol table. It calls 398 * expcollect() to parse actual parameters, checking for the correct number. 399 * It then creates a "file" containing a single line containing the 400 * macro with actual parameters inserted appropriately. This is 401 * "pushed back" onto the input stream. (When the get() routine runs 402 * off the end of the macro line, it will dismiss the macro itself.) 403 */ 404 { 405 register int c; 406 register FILEINFO *file; 407 #ifndef ZTC /* BP */ 408 extern FILEINFO *getfile(); 409 #endif 410 411 #if OSL_DEBUG_LEVEL > 1 412 if (debug) 413 dumpadef("expand entry", tokenp); 414 #endif 415 /* 416 * If no macro is pending, save the name of this macro 417 * for an eventual error message. 418 */ 419 if (recursion++ == 0) 420 macro = tokenp; 421 else if (recursion == RECURSION_LIMIT) { 422 cerror("Recursive macro definition of \"%s\"", tokenp->name); 423 fprintf(stderr, "(Defined by \"%s\")\n", macro->name); 424 if (rec_recover) { 425 do { 426 c = get(); 427 } while (infile != NULL && infile->fp == NULL); 428 unget(); 429 recursion = 0; 430 return; 431 } 432 } 433 /* 434 * Here's a macro to expand. 435 */ 436 nargs = 0; /* Formals counter */ 437 parmp = parm; /* Setup parm buffer */ 438 switch (tokenp->nargs) { 439 case (-2): /* __LINE__ */ 440 sprintf(work, "%d", line); 441 ungetstring(work); 442 break; 443 444 case (-3): /* __FILE__ */ 445 for (file = infile; file != NULL; file = file->parent) { 446 if (file->fp != NULL) { 447 sprintf(work, "\"%s\"", (file->progname != NULL) 448 ? file->progname : file->filename); 449 ungetstring(work); 450 break; 451 } 452 } 453 break; 454 455 default: 456 /* 457 * Nothing funny about this macro. 458 */ 459 if (tokenp->nargs < 0) 460 cfatal("Bug: Illegal __ macro \"%s\"", tokenp->name); 461 while ((c = skipws()) == '\n') /* Look for (, skipping */ 462 wrongline = TRUE; /* spaces and newlines */ 463 if (c != '(') { 464 /* 465 * If the programmer writes 466 * #define foo() ... 467 * ... 468 * foo [no ()] 469 * just write foo to the output stream. 470 */ 471 unget(); 472 cwarn("Macro \"%s\" needs arguments", tokenp->name); 473 fputs(tokenp->name, pCppOut ); 474 return; 475 } 476 else if (expcollect()) { /* Collect arguments */ 477 if (tokenp->nargs != nargs) { /* Should be an error? */ 478 cwarn("Wrong number of macro arguments for \"%s\"", 479 tokenp->name); 480 } 481 #if OSL_DEBUG_LEVEL > 1 482 if (debug) 483 dumpparm("expand"); 484 #endif 485 } /* Collect arguments */ 486 case DEF_NOARGS: /* No parameters just stuffs */ 487 expstuff(tokenp); /* Do actual parameters */ 488 } /* nargs switch */ 489 } 490 491 FILE_LOCAL int 492 expcollect() 493 /* 494 * Collect the actual parameters for this macro. TRUE if ok. 495 */ 496 { 497 register int c; 498 register int paren; /* For embedded ()'s */ 499 for (;;) { 500 paren = 0; /* Collect next arg. */ 501 while ((c = skipws()) == '\n') /* Skip over whitespace */ 502 wrongline = TRUE; /* and newlines. */ 503 if (c == ')') { /* At end of all args? */ 504 /* 505 * Note that there is a guard byte in parm[] 506 * so we don't have to check for overflow here. 507 */ 508 *parmp = EOS; /* Make sure terminated */ 509 break; /* Exit collection loop */ 510 } 511 else if (nargs >= LASTPARM) 512 cfatal("Too many arguments in macro expansion", NULLST); 513 parlist[nargs++] = parmp; /* At start of new arg */ 514 for (;; c = cget()) { /* Collect arg's bytes */ 515 if (c == EOF_CHAR) { 516 cerror("end of file within macro argument", NULLST); 517 return (FALSE); /* Sorry. */ 518 } 519 else if (c == '\\') { /* Quote next character */ 520 charput(c); /* Save the \ for later */ 521 charput(cget()); /* Save the next char. */ 522 continue; /* And go get another */ 523 } 524 else if (type[c] == QUO) { /* Start of string? */ 525 scanstring(c, charput); /* Scan it off */ 526 continue; /* Go get next char */ 527 } 528 else if (c == '(') /* Worry about balance */ 529 paren++; /* To know about commas */ 530 else if (c == ')') { /* Other side too */ 531 if (paren == 0) { /* At the end? */ 532 unget(); /* Look at it later */ 533 break; /* Exit arg getter. */ 534 } 535 paren--; /* More to come. */ 536 } 537 else if (c == ',' && paren == 0) /* Comma delimits args */ 538 break; 539 else if (c == '\n') /* Newline inside arg? */ 540 wrongline = TRUE; /* We'll need a #line */ 541 charput(c); /* Store this one */ 542 } /* Collect an argument */ 543 charput(EOS); /* Terminate argument */ 544 #if OSL_DEBUG_LEVEL > 1 545 if (debug) 546 fprintf( pCppOut, "parm[%d] = \"%s\"\n", nargs, parlist[nargs - 1]); 547 #endif 548 } /* Collect all args. */ 549 return (TRUE); /* Normal return */ 550 } 551 552 FILE_LOCAL 553 void expstuff(DEFBUF* tokenp) 554 /* 555 * Stuff the macro body, replacing formal parameters by actual parameters. 556 */ 557 { 558 register int c; /* Current character */ 559 register char *inp; /* -> repl string */ 560 register char *defp; /* -> macro output buff */ 561 int size; /* Actual parm. size */ 562 char *defend; /* -> output buff end */ 563 int string_magic; /* String formal hack */ 564 FILEINFO *file; /* Funny #include */ 565 #ifndef ZTC /* BP */ 566 extern FILEINFO *getfile(); 567 #endif 568 569 file = getfile(NBUFF, tokenp->name); 570 inp = tokenp->repl; /* -> macro replacement */ 571 defp = file->buffer; /* -> output buffer */ 572 defend = defp + (NBUFF - 1); /* Note its end */ 573 if (inp != NULL) { 574 while ((c = (*inp++ & 0xFF)) != EOS) { 575 #ifdef SOLAR 576 if (c == DEL) { 577 c = (*inp++ & 0xFF); 578 #else 579 if (c >= MAC_PARM && c <= (MAC_PARM + PAR_MAC)) { 580 #endif 581 string_magic = (c == (MAC_PARM + PAR_MAC)); 582 if (string_magic) 583 c = (*inp++ & 0xFF); 584 /* 585 * Replace formal parameter by actual parameter string. 586 */ 587 if ((c -= MAC_PARM) < nargs) { 588 size = strlen(parlist[c]); 589 if ((defp + size) >= defend) 590 goto nospace; 591 /* 592 * Erase the extra set of quotes. 593 */ 594 if (string_magic && defp[-1] == parlist[c][0]) { 595 strcpy(defp-1, parlist[c]); 596 defp += (size - 2); 597 } 598 else { 599 strcpy(defp, parlist[c]); 600 defp += size; 601 } 602 } 603 } 604 else if (defp >= defend) { 605 nospace: cfatal("Out of space in macro \"%s\" arg expansion", 606 tokenp->name); 607 } 608 else { 609 *defp++ = (char)c; 610 } 611 } 612 } 613 *defp = EOS; 614 #if OSL_DEBUG_LEVEL > 1 615 if (debug > 1) 616 fprintf( pCppOut, "macroline: \"%s\"\n", file->buffer); 617 #endif 618 } 619 620 #if OSL_DEBUG_LEVEL > 1 621 void dumpparm(char* why) 622 /* 623 * Dump parameter list. 624 */ 625 { 626 register int i; 627 628 fprintf( pCppOut, "dump of %d parameters (%d bytes total) %s\n", 629 nargs, parmp - parm, why); 630 for (i = 0; i < nargs; i++) { 631 fprintf( pCppOut, "parm[%d] (%d) = \"%s\"\n", 632 i + 1, (int)strlen(parlist[i]), parlist[i]); 633 } 634 } 635 #endif 636