1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1986-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 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 * preprocessor lexical analyzer 26 * standalone and tokenizing lexer combined in one source 27 * define CPP=1 for standalone 28 */ 29 30 #include "pplib.h" 31 #include "ppfsm.h" 32 33 #if CPP 34 35 /* 36 * standalone entry point 37 */ 38 39 #define PPCPP_T void 40 41 #define START QUICK 42 #define INMACRO(x) INQMACRO(x) 43 #define DOSTRIP() (st&STRIP) 44 45 #if DEBUG & TRACE_debug 46 static int hit[LAST-TERMINAL+2]; 47 #endif 48 49 #define BACKIN() (ip--) 50 #define BACKOUT() (op=tp) 51 #define CACHE() do{CACHEINX();CACHEOUTX();st=pp.state;if(!pp.hidden)spliced=0;}while(0) 52 #define CACHEIN() do{CACHEINX();st=pp.state;if(!pp.hidden)spliced=0;}while(0) 53 #define CACHEINX() do{ip=pp.in->nextchr;}while(0) 54 #define CACHEOUT() do{CACHEOUTX();st=pp.state;if(!pp.hidden)spliced=0;}while(0) 55 #define CACHEOUTX() do{tp=op=pp.outp;xp=pp.oute;if(sp)sp=op;}while(0) 56 #define GETCHR() (*(unsigned char*)ip++) 57 #define LASTCHR() (*(ip-1)) 58 #define LASTOUT() ((op>pp.outbuf)?*(op-1):pp.lastout) 59 #define SKIPIN() (ip++) 60 #define PUTCHR(c) (*op++=(c)) 61 #define SETCHR(c) (*op=(c)) 62 #define SYNC() do{SYNCINX();SYNCOUTX();pp.state=st;}while(0) 63 #define SYNCIN() do{SYNCINX();pp.state=st;}while(0) 64 #define SYNCINX() do{pp.in->nextchr=ip;}while(0) 65 #define SYNCOUT() do{SYNCOUTX();pp.state=st;}while(0) 66 #define SYNCOUTX() do{if(sp)op=tp=sp;pp.outp=op;}while(0) 67 #define UNGETCHR(c) (*--ip=(c)) 68 69 #define PPCHECKOUT() do{if(op>xp){{PPWRITE(PPBUFSIZ);if(pp.outbuf==pp.outb){pp.outbuf+=PPBUFSIZ;xp=pp.oute+=PPBUFSIZ;}else{pp.outbuf-=PPBUFSIZ;memcpy(pp.outbuf,xp,op-xp);xp=pp.oute-=PPBUFSIZ;op-=2*PPBUFSIZ;}}}}while(0) 70 #define PPCHECKOUTSP() do{if(op>xp){if(sp)op=sp;else{PPWRITE(PPBUFSIZ);if(pp.outbuf==pp.outb){pp.outbuf+=PPBUFSIZ;xp=pp.oute+=PPBUFSIZ;}else{pp.outbuf-=PPBUFSIZ;memcpy(pp.outbuf,xp,op-xp);xp=pp.oute-=PPBUFSIZ;op-=2*PPBUFSIZ;}}}}while(0) 71 #define PPCHECKOUTTP() do{if(op>xp){{PPWRITE(PPBUFSIZ);if(pp.outbuf==pp.outb){pp.outbuf+=PPBUFSIZ;xp=pp.oute+=PPBUFSIZ;}else{pp.outbuf-=PPBUFSIZ;memcpy(pp.outbuf,xp,op-xp);xp=pp.oute-=PPBUFSIZ;op-=2*PPBUFSIZ;}}tp=op;}}while(0) 72 73 #define PPSYNCLINE() do { \ 74 if ((st & (ADD|HIDDEN)) && !(*pp.control & SKIP)) \ 75 { \ 76 if (spliced) \ 77 { \ 78 error_info.line += spliced; \ 79 spliced = 0; \ 80 } \ 81 else \ 82 { \ 83 if (st & ADD) \ 84 { \ 85 st &= ~ADD; \ 86 m = pp.addp - pp.addbuf; \ 87 pp.addp = pp.addbuf; \ 88 memcpy(op, pp.addbuf, m); \ 89 op += m; \ 90 PPCHECKOUT(); \ 91 } \ 92 if (pp.linesync) \ 93 { \ 94 if ((st & SYNCLINE) || pp.hidden >= MAXHIDDEN) \ 95 { \ 96 pp.hidden = 0; \ 97 st &= ~(HIDDEN|SYNCLINE); \ 98 if (error_info.line) \ 99 { \ 100 if (LASTOUT() != '\n') \ 101 PUTCHR('\n'); \ 102 SYNCOUT(); \ 103 (*pp.linesync)(error_info.line, error_info.file); \ 104 CACHEOUT(); \ 105 } \ 106 } \ 107 else \ 108 { \ 109 m = pp.hidden; \ 110 pp.hidden = 0; \ 111 st &= ~HIDDEN; \ 112 while (m-- > 0) \ 113 PUTCHR('\n'); \ 114 } \ 115 } \ 116 else \ 117 { \ 118 pp.hidden = 0; \ 119 st &= ~HIDDEN; \ 120 PUTCHR('\n'); \ 121 } \ 122 } \ 123 } \ 124 } while (0) 125 126 #if POOL 127 128 /* 129 * <wait.h> is poison here so pool moved to the end 130 */ 131 132 static void poolstatus(void); 133 static void pool(void); 134 135 #endif 136 137 #else 138 139 /* 140 * return next pp token 141 * 142 * NOTE: pp.token points to at least MAXTOKEN*2 chars and is 143 * truncated back to MAXTOKEN on EOB 144 */ 145 146 #define PPCPP_T int 147 #define ppcpp pplex 148 149 #define START TOKEN 150 #define INMACRO(x) INTMACRO(x) 151 #define DOSTRIP() ((st&STRIP)||pp.level==1&&(st&(COMPILE|JOINING))==COMPILE&&!(pp.option&PRESERVE)) 152 153 #define st pp.state 154 #define tp pp.token 155 #define xp &pp.token[MAXTOKEN] 156 157 #define BACKIN() (ip--) 158 #define BACKOUT() (op=pp.token) 159 #define CACHE() do{CACHEIN();CACHEOUT();}while(0) 160 #define CACHEIN() (ip=pp.in->nextchr) 161 #define CACHEOUT() (op=pp.token) 162 #define GETCHR() (*(unsigned char*)ip++) 163 #define LASTCHR() (*(ip-1)) 164 #define PUTCHR(c) (*op++=(c)) 165 #define SETCHR(c) (*op=(c)) 166 #define SKIPIN() (ip++) 167 #define SYNC() do{SYNCIN();SYNCOUT();}while(0) 168 #define SYNCIN() (pp.in->nextchr=ip) 169 #define SYNCOUT() (pp.toknxt=op) 170 #define UNGETCHR(c) (*--ip=(c)) 171 172 #endif 173 174 PPCPP_T 175 ppcpp(void) 176 { 177 register short* rp; 178 register char* ip; 179 register int state; 180 register int c; 181 register char* op; 182 char* bp; 183 int n; 184 int m; 185 int quot; 186 int quotquot; 187 int comdelim = 0; 188 int comstart = 0; 189 int comwarn = 0; 190 char* s; 191 struct ppsymbol* sym; 192 #if CPP 193 register long st; 194 char* tp; 195 char* xp; 196 char* sp = 0; 197 int qual = 0; 198 int spliced = 0; 199 #else 200 int qual; 201 #endif 202 203 #if CPP 204 #if POOL 205 fsm_pool: 206 #endif 207 #else 208 count(pplex); 209 #endif 210 error_info.indent++; 211 pp.level++; 212 CACHE(); 213 #if !CPP 214 fsm_top: 215 qual = 0; 216 #endif 217 fsm_start: 218 #if CPP 219 PPCHECKOUTSP(); 220 tp = op; 221 #endif 222 state = START; 223 fsm_begin: 224 bp = ip; 225 do 226 { 227 rp = fsm[state]; 228 fsm_get: 229 while (!(state = rp[c = GETCHR()])); 230 fsm_next: 231 ; 232 } while (state > 0); 233 if (((state = ~state) != S_COMMENT || pp.comment || c == '/' && !INCOMMENT(rp)) && (n = ip - bp - 1) > 0) 234 { 235 ip = bp; 236 #if CPP 237 if (op == tp && (st & (ADD|HIDDEN)) && !(st & PASSTHROUGH)) 238 switch (TERM(state)) 239 { 240 case S_SHARP: 241 break; 242 case S_CHRB: 243 case S_NL: 244 if (*ip == '\n') 245 break; 246 /*FALLTHROUGH*/ 247 default: 248 PPSYNCLINE(); 249 tp = op; 250 break; 251 } 252 #endif 253 MEMCPY(op, ip, n); 254 ip++; 255 } 256 count(terminal); 257 #if CPP && (DEBUG & TRACE_debug) 258 hit[(state & SPLICE) ? (elementsof(hit) - 1) : (TERM(state) - TERMINAL)]++; 259 #endif 260 fsm_terminal: 261 debug((-9, "TERM %s > %s%s%s |%-*.*s|%s|", pplexstr(INDEX(rp)), pplexstr(state), (st & NEWLINE) ? "|NEWLINE" : "", (st & SKIPCONTROL) ? "|SKIP" : "", op - tp, op - tp, tp, pptokchr(c))); 262 switch (TERM(state)) 263 { 264 265 #if !CPP 266 case S_CHR: 267 PUTCHR(c); 268 break; 269 #endif 270 271 case S_CHRB: 272 BACKIN(); 273 #if CPP 274 st &= ~NEWLINE; 275 pp.in->flags |= IN_tokens; 276 count(token); 277 goto fsm_start; 278 #else 279 c = *tp; 280 break; 281 #endif 282 283 case S_COMMENT: 284 switch (c) 285 { 286 case '\n': 287 if (!INCOMMENTXX(rp)) 288 { 289 qual = 0; 290 if (!comstart) comstart = comdelim = error_info.line; 291 error_info.line++; 292 if (pp.comment) PUTCHR(c); 293 else BACKOUT(); 294 #if CPP 295 rp = fsm[COM2]; 296 bp = ip; 297 goto fsm_get; 298 #else 299 state = COM2; 300 goto fsm_begin; 301 #endif 302 } 303 else if (comwarn < 0 && !(pp.mode & HOSTED)) 304 error(1, "/* appears in // comment"); 305 break; 306 case '*': 307 if (!comwarn && !(pp.mode & HOSTED)) 308 { 309 if (INCOMMENTXX(rp)) comwarn = -1; 310 else if (comstart && comstart != error_info.line) 311 { 312 if (qual || comdelim < error_info.line - 1) 313 { 314 error(1, "/* appears in /* ... */ comment starting at line %d", comstart); 315 comwarn = 1; 316 } 317 else comdelim = error_info.line; 318 } 319 } 320 fsm_comment: 321 PUTCHR(c); 322 #if CPP 323 rp = fsm[INCOMMENTXX(rp) ? COM5 : COM3]; 324 bp = ip; 325 goto fsm_get; 326 #else 327 state = INCOMMENTXX(rp) ? COM5 : COM3; 328 goto fsm_begin; 329 #endif 330 case '/': 331 if (!INCOMMENT(rp)) 332 { 333 if (!(pp.mode & HOSTED)) 334 error(1, "*/ appears outside of comment"); 335 BACKIN(); 336 #if CPP 337 st &= ~NEWLINE; 338 pp.in->flags |= IN_tokens; 339 count(token); 340 goto fsm_start; 341 #else 342 c = '*'; 343 if (!pp.comment) PUTCHR(c); 344 goto fsm_token; 345 #endif 346 } 347 else if (INCOMMENTXX(rp)) 348 { 349 if (!(pp.mode & HOSTED)) 350 { 351 if (comwarn < 0) comwarn = 0; 352 else if (!comwarn) 353 { 354 comwarn = 1; 355 error(1, "*/ appears in // comment"); 356 } 357 } 358 goto fsm_comment; 359 } 360 break; 361 case EOF: 362 BACKIN(); 363 if (!(pp.mode & HOSTED)) 364 { 365 if (comstart) error(2, "unterminated /* ... */ comment starting at line %d", comstart); 366 else if (INCOMMENTXX(rp)) error(2, "unterminated // ... comment"); 367 else error(2, "unterminated /* ... */ comment"); 368 } 369 break; 370 } 371 #if CPP 372 if (!pp.comment || sp) 373 { 374 #if COMPATIBLE 375 if (!(pp.state & COMPATIBILITY) || *bp == ' ' || *bp == '\t') 376 #endif 377 { 378 BACKOUT(); 379 PUTCHR(' '); 380 tp = op; 381 } 382 } 383 else if (pp.in->type & IN_TOP) 384 #else 385 if (pp.comment && !(st & (COLLECTING|DIRECTIVE|JOINING)) && !(*pp.control & SKIP) && (pp.in->type & IN_TOP)) 386 #endif 387 { 388 st &= ~HIDDEN; 389 pp.hidden = 0; 390 *(op - (c != '\n')) = 0; 391 m = (op - (c != '\n') - tp > MAXTOKEN - 6) ? (error_info.line - MAXHIDDEN) : 0; 392 BACKOUT(); 393 SYNC(); 394 while (*tp != '/') tp++; 395 (*pp.comment)(c == '\n' ? "//" : "/*", tp + 2, c == '\n' ? "" : (st & HEADER) ? "*/\n" : "*/", comstart ? comstart : error_info.line); 396 CACHE(); 397 comstart = m; 398 } 399 if (comstart) 400 { 401 st |= HIDDEN; 402 pp.hidden += error_info.line - comstart; 403 comstart = 0; 404 } 405 qual = comwarn = comdelim = 0; 406 BACKOUT(); 407 if (c == '\n') goto fsm_newline; 408 if ((st & PASSTHROUGH) && ((st & (HIDDEN|NEWLINE)) || *ip == '\n')) 409 { 410 if (*ip == '\n') 411 ip++; 412 goto fsm_newline; 413 } 414 #if COMPATIBLE 415 if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) st &= ~NEWLINE; 416 #endif 417 #if !CPP 418 if (pp.level > 1 && !(st & (NOSPACE|SKIPCONTROL))) 419 { 420 #if COMPATIBLE 421 c = ((st & (COMPATIBILITY|DEFINITION)) == ((COMPATIBILITY|DEFINITION))) ? '\t' : ' '; 422 #else 423 c = ' '; 424 #endif 425 goto fsm_return; 426 } 427 #endif 428 goto fsm_start; 429 430 case S_EOB: 431 if (c) 432 { 433 if (state = fsm[TERMINAL][INDEX(rp)+1]) 434 goto fsm_terminal; 435 #if CPP 436 #if POOL 437 if (pp.pool.input) 438 { 439 BACKIN(); 440 SYNC(); 441 pool(); 442 CACHE(); 443 goto fsm_pool; 444 } 445 #endif 446 SYNCOUT(); 447 return; 448 #else 449 BACKIN(); 450 c = 0; 451 goto fsm_return; 452 #endif 453 } 454 { 455 register struct ppinstk* cur = pp.in; 456 register struct ppinstk* prv = pp.in->prev; 457 458 #if CPP 459 if (sp) op = sp; 460 #endif 461 switch (cur->type) 462 { 463 case IN_BUFFER: 464 case IN_INIT: 465 case IN_RESCAN: 466 #if CPP 467 if (prv) 468 #else 469 if (!(st & PASSEOF) && prv) 470 #endif 471 { 472 if (cur->type == IN_RESCAN || cur->type == IN_BUFFER) 473 { 474 fsm_pop: 475 #if PROTOTYPE 476 if (cur->flags & IN_prototype) 477 pppclose(cur->buffer + PPBAKSIZ); 478 else 479 #endif 480 if (!(cur->flags & IN_static)) 481 free(cur->buffer); 482 } 483 while (pp.control-- != cur->control) 484 error(2, "#%s on line %d has no #%s", dirname(IF), GETIFLINE(pp.control+1), dirname(ENDIF)); 485 st |= NEWLINE; 486 error_info.file = cur->file; 487 error_info.line = cur->line; 488 pp.hidden = 0; 489 #if CPP 490 spliced = 0; 491 #endif 492 if (cur->flags & IN_hosted) 493 { 494 pp.mode |= HOSTED; 495 pp.flags |= PP_hosted; 496 } 497 else 498 { 499 pp.mode &= ~HOSTED; 500 pp.flags &= ~PP_hosted; 501 } 502 #if !CPP && CATSTRINGS 503 if (st & JOINING) st |= HIDDEN|SYNCLINE; 504 else 505 #endif 506 { 507 st &= ~(HIDDEN|SYNCLINE); 508 switch (cur->type) 509 { 510 case IN_BUFFER: 511 case IN_INIT: 512 if (!prv->prev) break; 513 /*FALLTHROUGH*/ 514 case IN_FILE: 515 case IN_RESCAN: 516 if (prv->type == IN_FILE || cur->type == IN_FILE && (prv->type == IN_RESCAN || prv->type == IN_MULTILINE)) 517 { 518 if (pp.linesync && (cur->type != IN_RESCAN || (cur->flags & IN_sync))) 519 { 520 POP(); 521 SYNCOUT(); 522 (*pp.linesync)(error_info.line, error_info.file); 523 CACHEOUT(); 524 prv = pp.in; 525 } 526 } 527 #if DEBUG 528 else if (!prv->prev) 529 { 530 /*UNDENT*/ 531 c = 0; 532 #if DEBUG & TRACE_count 533 if (pp.test & TEST_count) 534 { 535 c = 1; 536 sfprintf(sfstderr, "\n"); 537 sfprintf(sfstderr, "%7d: pplex calls\n", pp.counter.pplex); 538 sfprintf(sfstderr, "%7d: terminal states\n", pp.counter.terminal); 539 sfprintf(sfstderr, "%7d: emitted tokens\n", pp.counter.token); 540 sfprintf(sfstderr, "%7d: input stream pushes\n", pp.counter.push); 541 sfprintf(sfstderr, "%7d: macro candidates\n", pp.counter.candidate); 542 sfprintf(sfstderr, "%7d: macro expansions\n", pp.counter.macro); 543 sfprintf(sfstderr, "%7d: function macros\n", pp.counter.function); 544 } 545 #endif 546 #if CPP && (DEBUG & TRACE_debug) 547 if (pp.test & TEST_hit) 548 { 549 c = 1; 550 sfprintf(sfstderr, "\n"); 551 if (hit[elementsof(hit) - 1]) 552 sfprintf(sfstderr, "%7d: SPLICE\n", hit[elementsof(hit) - 1]); 553 for (n = 0; n < elementsof(hit) - 1; n++) 554 if (hit[n]) 555 sfprintf(sfstderr, "%7d: %s\n", hit[n], pplexstr(TERMINAL + n)); 556 } 557 #endif 558 if (pp.test & (TEST_hashcount|TEST_hashdump)) 559 { 560 c = 1; 561 sfprintf(sfstderr, "\n"); 562 hashdump(NiL, (pp.test & TEST_hashdump) ? HASH_BUCKET : 0); 563 } 564 if (c) sfprintf(sfstderr, "\n"); 565 /*INDENT*/ 566 } 567 #endif 568 break; 569 } 570 } 571 #if CHECKPOINT 572 if (cur->index) 573 { 574 SYNCOUT(); 575 cur->index->end = ppoffset(); 576 cur->index = 0; 577 CACHEOUT(); 578 } 579 #endif 580 POP(); 581 bp = ip; 582 tp = op; 583 goto fsm_get; 584 } 585 c = EOF; 586 break; 587 case IN_COPY: 588 if (prv) 589 { 590 error_info.line = cur->line; 591 if (!(prv->symbol->flags & SYM_MULTILINE)) 592 prv->symbol->flags |= SYM_DISABLED; 593 POP(); 594 bp = ip; 595 goto fsm_get; 596 } 597 c = EOF; 598 break; 599 case IN_EXPAND: 600 if (prv) 601 { 602 error_info.line = cur->line; 603 free(cur->buffer); 604 POP(); 605 bp = ip; 606 goto fsm_get; 607 } 608 c = EOF; 609 break; 610 case IN_FILE: 611 FGET(c, c, tp, xp); 612 if (c == EOB) 613 { 614 #if CPP 615 if ((st & (NOTEXT|HIDDEN)) == HIDDEN && LASTOUT() != '\n') 616 PUTCHR('\n'); 617 if (prv) 618 #else 619 if (st & EOF2NL) 620 { 621 st &= ~EOF2NL; 622 *(ip - 1) = c = '\n'; 623 } 624 else if (!(st & (FILEPOP|PASSEOF)) && prv) 625 #endif 626 { 627 if (!(cur->flags & IN_newline)) 628 { 629 cur->flags |= IN_newline; 630 if ((pp.mode & (HOSTED|PEDANTIC)) == PEDANTIC && LASTCHR() != '\f' && LASTCHR() != CC_sub) 631 error(1, "file does not end with %s", pptokchr('\n')); 632 *(ip - 1) = c = '\n'; 633 } 634 else 635 { 636 if (!(cur->flags & (IN_noguard|IN_tokens)) && cur->symbol) 637 ppmultiple(ppsetfile(error_info.file), cur->symbol); 638 if (cur->fd >= 0) 639 close(cur->fd); 640 if (pp.incref && !(pp.mode & INIT)) 641 { 642 SYNCOUT(); 643 (*pp.incref)(error_info.file, cur->file, error_info.line - 1, PP_SYNC_POP); 644 CACHEOUT(); 645 } 646 goto fsm_pop; 647 } 648 } 649 else 650 c = EOF; 651 } 652 break; 653 case IN_MACRO: 654 case IN_MULTILINE: 655 #if !CPP 656 if (!(st & PASSEOF)) 657 #endif 658 #if COMPATIBLE 659 if (prv && (!INMACRO(rp) || (st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && ppismac(*prv->nextchr))) 660 #else 661 if (prv && !INMACRO(rp)) 662 #endif 663 { 664 if (cur->type == IN_MULTILINE) 665 { 666 while (pp.control-- != cur->control) 667 error(2, "#%s on line %d has no #%s", dirname(IF), GETIFLINE(pp.control+1), dirname(ENDIF)); 668 free(cur->buffer); 669 error_info.file = cur->file; 670 error_info.line = cur->line; 671 if (pp.linesync) 672 { 673 SYNCOUT(); 674 (*pp.linesync)(error_info.line, error_info.file); 675 CACHEOUT(); 676 } 677 } 678 cur->symbol->flags &= ~SYM_DISABLED; 679 if (cur->symbol->flags & SYM_FUNCTION) 680 popframe(pp.macp); 681 POP(); 682 #if CPP 683 if (!(st & COMPATIBILITY) && ppisidig(*(op - 1)) && ppisidig(*ip)) UNGETCHR(' '); 684 #endif 685 bp = ip; 686 goto fsm_get; 687 } 688 c = EOF; 689 break; 690 case IN_QUOTE: 691 if (prv) 692 { 693 error_info.line = cur->line; 694 st &= ~(ESCAPE|QUOTE); 695 POP(); 696 c = '"'; 697 } 698 else c = EOF; 699 break; 700 case IN_SQUOTE: 701 if (prv) 702 { 703 error_info.line = cur->line; 704 st &= ~(ESCAPE|SQUOTE); 705 POP(); 706 c = '\''; 707 } 708 else c = EOF; 709 break; 710 case IN_STRING: 711 #if CPP 712 if (prv) 713 #else 714 if (!(st & PASSEOF) && !(cur->flags & IN_expand) && prv) 715 #endif 716 { 717 if (cur->flags & IN_disable) st |= DISABLE; 718 else st &= ~DISABLE; 719 POP(); 720 bp = ip; 721 goto fsm_get; 722 } 723 c = EOF; 724 break; 725 default: 726 c = EOF; 727 break; 728 } 729 } 730 bp = ip - 1; 731 if (state = rp[c]) goto fsm_next; 732 goto fsm_get; 733 734 #if !CPP 735 case S_HUH: 736 if (INOPSPACE(rp)) 737 { 738 if (c == '=') 739 { 740 #if PROTOTYPE 741 if (pp.in->flags & IN_prototype) PUTCHR(c); 742 else 743 { 744 #endif 745 while (*(op - 1) == ' ' || *(op - 1) == '\t') op--; 746 PUTCHR(c); 747 if (st & (STRICT|WARN)) error(1, "%-*.*s: space ignored in operator", op - tp, op - tp, tp); 748 #if PROTOTYPE 749 } 750 #endif 751 switch (*tp) 752 { 753 case '/': 754 c = T_DIVEQ; 755 break; 756 case '%': 757 c = T_MODEQ; 758 break; 759 case '&': 760 c = T_ANDEQ; 761 break; 762 case '*': 763 c = T_MPYEQ; 764 break; 765 case '+': 766 c = T_ADDEQ; 767 break; 768 case '-': 769 c = T_SUBEQ; 770 break; 771 case '^': 772 c = T_XOREQ; 773 break; 774 case '|': 775 c = T_OREQ; 776 break; 777 case '<': 778 c = T_LSHIFTEQ; 779 break; 780 case '>': 781 c = T_RSHIFTEQ; 782 break; 783 } 784 } 785 else 786 { 787 BACKIN(); 788 switch (c = *tp) 789 { 790 case '<': 791 c = T_LSHIFT; 792 break; 793 case '>': 794 c = T_RSHIFT; 795 break; 796 } 797 } 798 } 799 else if (pp.level > 1 || (pp.option & PRESERVE)) PUTCHR(c); 800 else if (tp == op) 801 { 802 if (pp.in->type != IN_BUFFER) 803 { 804 if (!(pp.option & ALLPOSSIBLE)) 805 error(1, "%s: invalid character ignored", pptokchr(c)); 806 goto fsm_top; 807 } 808 PUTCHR(c); 809 } 810 else if (*tp == ':') 811 { 812 PUTCHR(c); 813 if (c == '=') error(2, "real programmers use ="); 814 else c = '+'; 815 } 816 else 817 { 818 BACKIN(); 819 c = *tp; 820 } 821 break; 822 #endif 823 824 case S_QUAL: 825 if ((state = NEXT(state)) != LIT1) 826 { 827 rp = fsm[state]; 828 bp = ip; 829 #if CPP 830 qual = 1; 831 #if COMPATIBLE 832 if (!(st & COMPATIBILITY) || c != 'u' && c != 'U') 833 #endif 834 PUTCHR(c); 835 #else 836 switch (c) 837 { 838 case 'f': 839 case 'F': 840 qual |= N_FLOAT; 841 #if COMPATIBLE 842 if (!(st & COMPATIBILITY)) 843 #endif 844 PUTCHR(c); 845 break; 846 case 'l': 847 case 'L': 848 qual |= N_LONG; 849 PUTCHR(c); 850 break; 851 case 'u': 852 case 'U': 853 qual |= N_UNSIGNED; 854 #if COMPATIBLE 855 if (!(st & COMPATIBILITY)) 856 #endif 857 PUTCHR(c); 858 break; 859 default: 860 PUTCHR(c); 861 break; 862 } 863 #endif 864 goto fsm_get; 865 } 866 #if !CPP 867 qual |= N_WIDE; 868 if (DOSTRIP()) BACKOUT(); 869 #endif 870 /*FALLTHROUGH*/ 871 872 case S_LITBEG: 873 #if CPP 874 quot = c; 875 rp = fsm[LIT1]; 876 if (op == tp) 877 { 878 PPSYNCLINE(); 879 tp = op; 880 } 881 #else 882 if ((quot = c) == '<') 883 { 884 if (!(st & HEADER) || (pp.option & (HEADEREXPAND|HEADEREXPANDALL)) && pp.in->type != IN_FILE && pp.in->type != IN_BUFFER && pp.in->type != IN_INIT && pp.in->type != IN_RESCAN) 885 { 886 PUTCHR(c); 887 bp = ip; 888 rp = fsm[LT1]; 889 goto fsm_get; 890 } 891 quot = '>'; 892 rp = fsm[HDR1]; 893 } 894 else rp = fsm[LIT1]; 895 if (!DOSTRIP()) 896 #endif 897 PUTCHR(c); 898 bp = ip; 899 goto fsm_get; 900 901 case S_LITEND: 902 n = 1; 903 if (c != quot) 904 { 905 if (c != '\n' && c != EOF) 906 { 907 if (st & (QUOTE|SQUOTE)) 908 { 909 if (!(st & ESCAPE)) 910 { 911 st |= ESCAPE; 912 quotquot = c; 913 } 914 else if (c == quotquot) st &= ~ESCAPE; 915 } 916 PUTCHR(c); 917 bp = ip; 918 goto fsm_get; 919 } 920 #if CPP 921 if (st & PASSTHROUGH) 922 { 923 if (c == '\n') goto fsm_newline; 924 bp = ip; 925 goto fsm_start; 926 } 927 #endif 928 m = (st & SKIPCONTROL) && (pp.mode & HOSTED) ? -1 : 1; 929 if (c == '\n' && quot == '\'' && (pp.option & STRINGSPAN)) n = 0; 930 else 931 #if COMPATIBLE && !CPP 932 if ((st & (COMPATIBILITY|DEFINITION)) != (COMPATIBILITY|DEFINITION)) 933 #endif 934 { 935 switch (quot) 936 { 937 case '"': 938 if (c == '\n') 939 { 940 if (!(pp.option & STRINGSPAN) || (st & (COMPATIBILITY|STRICT)) == STRICT) 941 error(m, "%s in string", pptokchr(c)); 942 error_info.line++; 943 if (!(pp.option & STRINGSPAN)) 944 { 945 PUTCHR('\\'); 946 c = 'n'; 947 } 948 else if (pp.option & STRINGSPLIT) 949 { 950 PUTCHR('\\'); 951 PUTCHR('n'); 952 PUTCHR('"'); 953 PUTCHR('\n'); 954 c = '"'; 955 } 956 PUTCHR(c); 957 bp = ip; 958 goto fsm_get; 959 } 960 error(m, "%s in string", pptokchr(c)); 961 c = '\n'; 962 break; 963 case '\'': 964 if (!(st & DIRECTIVE) || !(pp.mode & (HOSTED|RELAX))) 965 error(m, "%s in character constant", pptokchr(c)); 966 break; 967 case '>': 968 error(m, "%s in header constant", pptokchr(c)); 969 break; 970 default: 971 error(m, "%s in %c quote", pptokchr(c), quot); 972 break; 973 } 974 #if !CPP 975 if (!DOSTRIP()) 976 #endif 977 PUTCHR(quot); 978 } 979 if (c == '\n') 980 { 981 UNGETCHR(c); 982 c = quot; 983 } 984 } 985 else if (st & (SQUOTE|QUOTE)) 986 { 987 if (!(st & ESCAPE)) 988 { 989 st |= ESCAPE; 990 quotquot = c; 991 } 992 else if (c == quotquot) st &= ~ESCAPE; 993 PUTCHR('\\'); 994 PUTCHR(c); 995 bp = ip; 996 goto fsm_get; 997 } 998 #if CPP 999 else PUTCHR(c); 1000 #else 1001 else if (!DOSTRIP()) PUTCHR(c); 1002 #endif 1003 #if CATSTRINGS 1004 #if CPP 1005 if (c == '"' && !(st & (COLLECTING|NOTEXT|PASSTHROUGH|SKIPCONTROL)) && (pp.mode & CATLITERAL)) 1006 #else 1007 if (c == '"' && pp.level == 1 && !(st & (COLLECTING|JOINING|NOTEXT|SKIPCONTROL)) && (pp.mode & CATLITERAL)) 1008 #endif 1009 { 1010 char* pptoken; 1011 long ppstate; 1012 1013 pptoken = pp.token; 1014 pp.token = pp.catbuf; 1015 *pp.token++ = 0; 1016 ppstate = (st & STRIP); 1017 if (DOSTRIP()) 1018 ppstate |= ADD|QUOTE; 1019 st |= JOINING; 1020 st &= ~(NEWLINE|STRIP); 1021 1022 /* 1023 * revert to the top level since string 1024 * concatenation crosses file boundaries 1025 * (allowing intervening directives) 1026 */ 1027 1028 pp.level = 0; 1029 SYNCIN(); 1030 m = n = 0; 1031 for (;;) 1032 { 1033 switch (c = pplex()) 1034 { 1035 case '\n': 1036 m++; 1037 continue; 1038 case ' ': 1039 *pp.catbuf = ' '; 1040 continue; 1041 case T_WSTRING: 1042 #if !CPP 1043 qual = N_WIDE; 1044 #endif 1045 if (ppstate & ADD) 1046 ppstate &= ~ADD; 1047 else if (m == n || !(st & SPACEOUT)) 1048 op--; 1049 else 1050 { 1051 n = m; 1052 *(op - 1) = '\\'; 1053 *op++ = '\n'; 1054 } 1055 STRCOPY(op, pp.token + 2 + (*pp.token == ' '), s); 1056 continue; 1057 case T_STRING: 1058 if (ppstate & ADD) 1059 ppstate &= ~ADD; 1060 else if (m == n || !(st & SPACEOUT)) 1061 op--; 1062 else 1063 { 1064 n = m; 1065 *(op - 1) = '\\'; 1066 *op++ = '\n'; 1067 } 1068 STRCOPY(op, pp.token + 1 + (*pp.token == ' '), s); 1069 continue; 1070 case 0: 1071 m = error_info.line ? (error_info.line - 1) : 0; 1072 *pp.token = 0; 1073 /*FALLTHROUGH*/ 1074 default: 1075 if (m) 1076 { 1077 if (--m) 1078 { 1079 pp.state |= HIDDEN|SYNCLINE; 1080 pp.hidden += m; 1081 } 1082 #if COMPATIBLE 1083 if ((st & COMPATIBILITY) && c == '#' && *(pp.token - 1)) 1084 { 1085 *(pp.token + 3) = *(pp.token + 2); 1086 *(pp.token + 2) = *(pp.token + 1); 1087 *(pp.token + 1) = *pp.token; 1088 *pp.token = *(pp.token - 1); 1089 } 1090 error_info.line--; 1091 *--pp.token = '\n'; 1092 #endif 1093 } 1094 else if (*(pp.token - 1)) 1095 pp.token--; 1096 if (ppisidig(*pp.token)) 1097 *op++ = ' '; 1098 if (pp.in->type == IN_MACRO && (s = strchr(pp.token, MARK)) && !*(s + 1)) 1099 { 1100 *(s + 1) = MARK; 1101 *(s + 2) = 0; 1102 } 1103 PUSH_STRING(pp.token); 1104 pp.state &= ~(JOINING|NEWLINE); 1105 pp.state |= ppstate & ~(ADD|QUOTE); 1106 if ((ppstate & (ADD|QUOTE)) == QUOTE) 1107 op--; 1108 break; 1109 } 1110 break; 1111 } 1112 pp.token = pptoken; 1113 CACHEIN(); 1114 pp.level = 1; 1115 #if !CPP 1116 c = T_STRING | qual; 1117 break; 1118 #endif 1119 } 1120 #endif 1121 #if CPP 1122 if (n && !(st & (PASSTHROUGH|SKIPCONTROL|NOTEXT)) && c == '\'' && (op - tp) <= 2 && !(pp.mode & (HOSTED|RELAX))) 1123 error(1, "empty character constant"); 1124 st &= ~(ESCAPE|NEWLINE); 1125 pp.in->flags |= IN_tokens; 1126 count(token); 1127 goto fsm_start; 1128 #else 1129 st &= ~ESCAPE; 1130 switch (quot) 1131 { 1132 case '\'': 1133 if (n && !(st & NOTEXT) && (op - tp) <= (DOSTRIP() ? 0 : 2) && !(pp.mode & (HOSTED|RELAX))) 1134 error(1, "empty character constant"); 1135 c = T_CHARCONST | qual; 1136 break; 1137 case '>': 1138 c = T_HEADER; 1139 break; 1140 default: 1141 if (c == quot) 1142 c = T_STRING | qual; 1143 break; 1144 } 1145 break; 1146 #endif 1147 1148 case S_LITESC: 1149 if (st & (COLLECTING|DIRECTIVE|QUOTE|SQUOTE)) 1150 { 1151 if (st & ESCAPE) 1152 { 1153 PUTCHR('\\'); 1154 if (c == quot) PUTCHR('\\'); 1155 } 1156 PUTCHR(c); 1157 } 1158 #if CPP 1159 else if (st & PASSTHROUGH) PUTCHR(c); 1160 #endif 1161 else if (pp.option & PRESERVE) PUTCHR(c); 1162 else switch (c) 1163 { 1164 case 'b': 1165 case 'f': 1166 case 'n': 1167 case 'r': 1168 case 't': 1169 case '\\': 1170 case '\'': 1171 case '"': 1172 case '?': 1173 PUTCHR(c); 1174 break; 1175 #if COMPATIBLE 1176 case '8': 1177 case '9': 1178 if (!(st & COMPATIBILITY)) goto unknown; 1179 if (st & STRICT) error(1, "%c: invalid character in octal character escape", c); 1180 /*FALLTHROUGH*/ 1181 #endif 1182 case '0': 1183 case '1': 1184 case '2': 1185 case '3': 1186 case '4': 1187 case '5': 1188 case '6': 1189 case '7': 1190 n = c - '0'; 1191 for (m = 0; m < 2; m++) 1192 { 1193 GET(c, c, tp, xp); 1194 switch (c) 1195 { 1196 #if COMPATIBLE 1197 case '8': 1198 case '9': 1199 if (!(st & COMPATIBILITY)) 1200 { 1201 UNGETCHR(c); 1202 break; 1203 } 1204 if (st & STRICT) error(1, "%c: invalid character in octal character escape", c); 1205 /*FALLTHROUGH*/ 1206 #endif 1207 case '0': 1208 case '1': 1209 case '2': 1210 case '3': 1211 case '4': 1212 case '5': 1213 case '6': 1214 case '7': 1215 n = (n << 3) + c - '0'; 1216 continue; 1217 default: 1218 UNGETCHR(c); 1219 break; 1220 } 1221 break; 1222 } 1223 if (n & ~0777) error(1, "octal character constant too large"); 1224 goto octal; 1225 case 'a': 1226 if (pp.option & MODERN) 1227 { 1228 PUTCHR(c); 1229 break; 1230 } 1231 #if COMPATIBLE 1232 if (st & COMPATIBILITY) goto unknown; 1233 #endif 1234 n = CC_bel; 1235 goto octal; 1236 case 'v': 1237 if (pp.option & MODERN) 1238 { 1239 PUTCHR(c); 1240 break; 1241 } 1242 n = CC_vt; 1243 goto octal; 1244 case 'E': 1245 if (st & (COMPATIBILITY|STRICT)) goto unknown; 1246 n = CC_esc; 1247 goto octal; 1248 case 'x': 1249 #if COMPATIBLE 1250 if (st & COMPATIBILITY) goto unknown; 1251 #endif 1252 n = 0; 1253 for (m = 0; m < 3; m++) 1254 { 1255 GET(c, c, tp, xp); 1256 switch (c) 1257 { 1258 case '0': 1259 case '1': 1260 case '2': 1261 case '3': 1262 case '4': 1263 case '5': 1264 case '6': 1265 case '7': 1266 case '8': 1267 case '9': 1268 n = (n << 4) + c - '0'; 1269 continue; 1270 case 'a': 1271 case 'b': 1272 case 'c': 1273 case 'd': 1274 case 'e': 1275 case 'f': 1276 n = (n << 4) + c - 'a' + 10; 1277 continue; 1278 case 'A': 1279 case 'B': 1280 case 'C': 1281 case 'D': 1282 case 'E': 1283 case 'F': 1284 n = (n << 4) + c - 'A' + 10; 1285 continue; 1286 default: 1287 if (!m) error(1, "\\x%c: invalid character in hexadecimal character constant", c); 1288 UNGETCHR(c); 1289 break; 1290 } 1291 break; 1292 } 1293 if (n & ~0777) error(1, "hexadecimal character constant too large"); 1294 octal: 1295 PUTCHR(((n >> 6) & 07) + '0'); 1296 PUTCHR(((n >> 3) & 07) + '0'); 1297 PUTCHR((n & 07) + '0'); 1298 break; 1299 default: 1300 unknown: 1301 if (st & (STRICT|WARN)) error(1, "\\%c: non-standard character constant", c); 1302 PUTCHR(c); 1303 break; 1304 } 1305 state = LIT1; 1306 goto fsm_begin; 1307 1308 case S_MACRO: 1309 BACKIN(); 1310 #if CPP 1311 if (st & (DISABLE|SKIPCONTROL|SKIPMACRO)) 1312 { 1313 if (st & SKIPMACRO) 1314 pp.mode |= MARKMACRO; 1315 st &= ~(NEWLINE|SKIPMACRO); 1316 pp.in->flags |= IN_tokens; 1317 count(token); 1318 goto fsm_start; 1319 } 1320 count(candidate); 1321 SETCHR(0); 1322 switch (state = INDEX(rp)) 1323 { 1324 case HIT0: 1325 tp = op - 1; 1326 break; 1327 case HITN: 1328 bp = tp; 1329 tp = op - ((pp.truncate && pp.truncate < (HITN - HIT0)) ? (pp.truncate - 1) : (HITN - HIT0)); 1330 while (tp > bp && ppisidig(*(tp - 1))) tp--; 1331 break; 1332 default: 1333 bp = tp; 1334 if ((tp = op - (state - HIT0)) > bp && *(tp - 1) == 'L') tp--; 1335 break; 1336 } 1337 if (sym = ppsymref(pp.symtab, tp)) 1338 { 1339 SYNCIN(); 1340 n = ppcall(sym, 0); 1341 CACHEIN(); 1342 if (n >= 0) 1343 { 1344 BACKOUT(); 1345 if (!n) 1346 { 1347 if (sp) op = sp; 1348 else 1349 { 1350 s = ip; 1351 ip = sym->macro->value; 1352 c = sym->macro->size; 1353 while (c > 0) 1354 { 1355 if (op + c < xp + PPBUFSIZ) n = c; 1356 else n = xp + PPBUFSIZ - op; 1357 MEMCPY(op, ip, n); 1358 c -= n; 1359 PPCHECKOUT(); 1360 } 1361 ip = s; 1362 } 1363 } 1364 else if ((sym->flags & SYM_MULTILINE) && pp.linesync) 1365 { 1366 SYNCOUT(); 1367 if (!(state & NEWLINE)) 1368 ppputchar('\n'); 1369 (*pp.linesync)(error_info.line, error_info.file); 1370 CACHEOUT(); 1371 } 1372 } 1373 } 1374 pp.in->flags |= IN_tokens; 1375 goto fsm_start; 1376 #else 1377 if (st & (COLLECTING|DEFINITION|DISABLE|SKIPCONTROL|SKIPMACRO)) 1378 { 1379 if (st & SKIPMACRO) 1380 pp.mode |= MARKMACRO; 1381 st &= ~(NEWLINE|NOEXPAND|SKIPMACRO); 1382 c = T_ID; 1383 if (pp.level == 1) 1384 { 1385 pp.in->flags |= IN_tokens; 1386 if (st & NOTEXT) 1387 { 1388 BACKOUT(); 1389 goto fsm_top; 1390 } 1391 if (st & COMPILE) 1392 { 1393 SETCHR(0); 1394 if (pp.truncate && (op - tp) > pp.truncate) tp[pp.truncate] = 0; 1395 sym = (pp.option & NOHASH) ? ppsymref(pp.symtab, tp) : ppsymset(pp.symtab, tp); 1396 fsm_noise: 1397 if (pp.symbol = sym) 1398 { 1399 if ((sym->flags & SYM_KEYWORD) && (!pp.truncate || (op - tp) <= pp.truncate || (tp[pp.truncate] = '_', tp[pp.truncate + 1] = 0, pp.symbol = sym = (pp.option & NOHASH) ? ppsymref(pp.symtab, tp) : ppsymset(pp.symtab, tp), 0))) 1400 { 1401 c = ((struct ppsymkey*)sym)->lex; 1402 /*UNDENT*/ 1403 1404 #define ADVANCE() do{if(pp.toknxt<op)pp.token=pp.toknxt;}while(0) 1405 1406 #define NOISE_BRACE 01 1407 #define NOISE_NOSPACEOUT 02 1408 #define NOISE_PAREN 04 1409 1410 if ((pp.option & NOISE) && ppisnoise(c)) 1411 { 1412 if (c != T_NOISE) 1413 { 1414 int p; 1415 int f; 1416 char* pptoken; 1417 PPCOMMENT ppcomment; 1418 1419 SYNCIN(); 1420 pp.toknxt = op; 1421 f = 0; 1422 if (!(pp.state & SPACEOUT)) 1423 { 1424 pp.state |= SPACEOUT; 1425 f |= NOISE_NOSPACEOUT; 1426 } 1427 ppcomment = pp.comment; 1428 pp.comment = 0; 1429 op = (pptoken = tp) + MAXTOKEN; 1430 switch (c) 1431 { 1432 case T_X_GROUP: 1433 m = p = 0; 1434 quot = 1; 1435 for (;;) 1436 { 1437 ADVANCE(); 1438 switch (c = pplex()) 1439 { 1440 case '(': 1441 case '{': 1442 if (!p) 1443 { 1444 if (c == '(') 1445 { 1446 if (f & NOISE_PAREN) 1447 { 1448 ungetchr(c); 1449 *--pp.toknxt = 0; 1450 break; 1451 } 1452 f |= NOISE_PAREN; 1453 p = ')'; 1454 } 1455 else 1456 { 1457 f |= NOISE_BRACE|NOISE_PAREN; 1458 p = '}'; 1459 } 1460 n = 1; 1461 m = c; 1462 } 1463 else if (c == m) n++; 1464 quot = 0; 1465 continue; 1466 case ')': 1467 case '}': 1468 if (c == p && --n <= 0) 1469 { 1470 if (c == '}') break; 1471 m = '\n'; 1472 p = 0; 1473 } 1474 quot = 0; 1475 continue; 1476 case ' ': 1477 continue; 1478 case '\n': 1479 error_info.line++; 1480 if (!m) m = '\n'; 1481 continue; 1482 case 0: 1483 break; 1484 case T_ID: 1485 if (quot) continue; 1486 /*FALLTHROUGH*/ 1487 default: 1488 if (m == '\n') 1489 { 1490 /* 1491 * NOTE: token expanded again 1492 */ 1493 1494 s = pp.toknxt; 1495 while (s > pp.token) ungetchr(*--s); 1496 *(pp.toknxt = s) = 0; 1497 break; 1498 } 1499 continue; 1500 } 1501 break; 1502 } 1503 break; 1504 case T_X_LINE: 1505 for (;;) 1506 { 1507 ADVANCE(); 1508 switch (pplex()) 1509 { 1510 case 0: 1511 break; 1512 case '\n': 1513 error_info.line++; 1514 break; 1515 default: 1516 continue; 1517 } 1518 break; 1519 } 1520 break; 1521 case T_X_STATEMENT: 1522 for (;;) 1523 { 1524 ADVANCE(); 1525 switch (pplex()) 1526 { 1527 case 0: 1528 break; 1529 case ';': 1530 ungetchr(';'); 1531 *(pp.toknxt = pp.token) = 0; 1532 break; 1533 default: 1534 continue; 1535 } 1536 break; 1537 } 1538 break; 1539 } 1540 pp.comment = ppcomment; 1541 if (f & NOISE_NOSPACEOUT) 1542 pp.state &= ~SPACEOUT; 1543 CACHEIN(); 1544 tp = pptoken; 1545 op = pp.toknxt; 1546 c = T_NOISES; 1547 } 1548 if (pp.option & NOISEFILTER) 1549 { 1550 BACKOUT(); 1551 goto fsm_top; 1552 } 1553 } 1554 1555 /*INDENT*/ 1556 } 1557 else if ((pp.option & NOISE) && c == T_ID && strneq(tp, "__builtin_", 10)) 1558 { 1559 hashlook(pp.symtab, tp, HASH_DELETE, NiL); 1560 pp.symbol = sym = (struct ppsymbol*)ppkeyset(pp.symtab, tp); 1561 sym->flags |= SYM_KEYWORD; 1562 c = ((struct ppsymkey*)sym)->lex = T_BUILTIN; 1563 } 1564 } 1565 } 1566 goto fsm_symbol; 1567 } 1568 goto fsm_check; 1569 } 1570 if (pp.level == 1) 1571 { 1572 st &= ~(NEWLINE|PASSEOF); 1573 pp.in->flags |= IN_tokens; 1574 } 1575 else st &= ~PASSEOF; 1576 count(candidate); 1577 SETCHR(0); 1578 if (sym = ppsymref(pp.symtab, tp)) 1579 { 1580 SYNCIN(); 1581 c = ppcall(sym, 1); 1582 CACHEIN(); 1583 if (c >= 0) 1584 { 1585 BACKOUT(); 1586 if ((sym->flags & SYM_MULTILINE) && pp.linesync) 1587 { 1588 SYNCOUT(); 1589 (*pp.linesync)(error_info.line, error_info.file); 1590 CACHEOUT(); 1591 } 1592 goto fsm_top; 1593 } 1594 } 1595 c = T_ID; 1596 if (pp.level == 1) 1597 { 1598 if (st & NOTEXT) 1599 { 1600 BACKOUT(); 1601 goto fsm_top; 1602 } 1603 if (st & COMPILE) 1604 { 1605 if (pp.truncate && (op - tp) > pp.truncate) 1606 { 1607 tp[pp.truncate] = 0; 1608 sym = 0; 1609 } 1610 if (!sym) 1611 { 1612 if (!(pp.option & NOHASH)) sym = ppsymset(pp.symtab, tp); 1613 else if (!(sym = ppsymref(pp.symtab, tp))) goto fsm_symbol; 1614 } 1615 goto fsm_noise; 1616 } 1617 goto fsm_symbol; 1618 } 1619 goto fsm_check; 1620 #endif 1621 1622 case S_SHARP: 1623 if (c == '(') 1624 { 1625 pp.in->flags |= IN_tokens; 1626 if ((st & STRICT) && pp.in->type != IN_MACRO && pp.in->type != IN_MULTILINE) 1627 { 1628 if (!(pp.mode & HOSTED)) error(1, "non-standard reference to #(...)"); 1629 if (st & STRICT) 1630 { 1631 PUTCHR(c); 1632 #if CPP 1633 st &= ~NEWLINE; 1634 count(token); 1635 goto fsm_start; 1636 #else 1637 break; 1638 #endif 1639 } 1640 } 1641 if (st & (COLLECTING|DEFINITION|DISABLE|SKIPCONTROL)) 1642 { 1643 PUTCHR(c); 1644 #if CPP 1645 st &= ~NEWLINE; 1646 count(token); 1647 goto fsm_start; 1648 #else 1649 st &= ~NOEXPAND; 1650 break; 1651 #endif 1652 } 1653 op--; 1654 SYNC(); 1655 ppbuiltin(); 1656 CACHE(); 1657 #if CPP 1658 count(token); 1659 goto fsm_start; 1660 #else 1661 goto fsm_top; 1662 #endif 1663 } 1664 BACKIN(); 1665 #if CPP 1666 if (!(st & NEWLINE) || !(pp.in->type & IN_TOP)) 1667 { 1668 fsm_nondirective: 1669 st &= ~NEWLINE; 1670 pp.in->flags |= IN_tokens; 1671 count(token); 1672 goto fsm_start; 1673 } 1674 if (*(s = tp) != '#') 1675 { 1676 #if COMPATIBLE 1677 if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) goto fsm_nondirective; 1678 #endif 1679 while (*s == ' ' || *s == '\t') s++; 1680 if (*s != '#') goto fsm_nondirective; 1681 } 1682 BACKOUT(); 1683 #else 1684 if (!(st & NEWLINE) || (st & DEFINITION) || !(pp.in->type & IN_TOP)) 1685 { 1686 if (c == '#') 1687 { 1688 SKIPIN(); 1689 if (!(st & DEFINITION)) 1690 PUTCHR(c); 1691 c = T_TOKCAT; 1692 } 1693 else if (pp.level == 1 && !(st & (JOINING|SPACEOUT)) && !(pp.option & PRESERVE)) 1694 { 1695 char* pptoken; 1696 char* oop; 1697 PPCOMMENT ppcomment; 1698 1699 SYNCIN(); 1700 pp.toknxt = oop = op; 1701 pp.state |= SPACEOUT; 1702 ppcomment = pp.comment; 1703 pp.comment = 0; 1704 op = (pptoken = tp) + MAXTOKEN; 1705 for (;;) 1706 { 1707 ADVANCE(); 1708 switch (pplex()) 1709 { 1710 case 0: 1711 break; 1712 case '\n': 1713 error_info.line++; 1714 break; 1715 default: 1716 continue; 1717 } 1718 break; 1719 } 1720 pp.comment = ppcomment; 1721 pp.state &= ~SPACEOUT; 1722 CACHEIN(); 1723 tp = pptoken; 1724 *--op = 0; 1725 op = oop; 1726 if (pp.pragma && !(st & NOTEXT)) 1727 { 1728 *s = 0; 1729 SYNC(); 1730 (*pp.pragma)(NiL, NiL, NiL, tp, 1); 1731 CACHE(); 1732 } 1733 if (!c) BACKIN(); 1734 goto fsm_top; 1735 } 1736 else c = '#'; 1737 break; 1738 } 1739 if ((st & (COLLECTING|STRICT)) == (COLLECTING|STRICT)) 1740 error(1, "directives in macro call arguments are not portable"); 1741 #endif 1742 if (c == '#' && pp.in->type == IN_RESCAN) 1743 { 1744 /* 1745 * pass line to pp.pragma VERBATIM 1746 */ 1747 1748 SKIPIN(); 1749 s = pp.valbuf; 1750 while ((c = GETCHR()) && c != '\n') 1751 if ((*s++ = c) == MARK) SKIPIN(); 1752 if (pp.pragma && !(st & NOTEXT)) 1753 { 1754 *s = 0; 1755 SYNC(); 1756 (*pp.pragma)(NiL, NiL, NiL, pp.valbuf, 1); 1757 CACHE(); 1758 } 1759 if (!c) BACKIN(); 1760 #if CPP 1761 goto fsm_start; 1762 #else 1763 goto fsm_top; 1764 #endif 1765 } 1766 SYNC(); 1767 ppcontrol(); 1768 CACHE(); 1769 #if CPP 1770 if (st & (NOTEXT|SKIPCONTROL)) 1771 { 1772 if (!sp) 1773 { 1774 PPCHECKOUTTP(); 1775 sp = tp; 1776 } 1777 } 1778 else if (sp) 1779 { 1780 tp = op = sp; 1781 sp = 0; 1782 } 1783 goto fsm_start; 1784 #else 1785 goto fsm_top; 1786 #endif 1787 1788 case S_NL: 1789 #if CPP 1790 if (op == tp && !(st & JOINING) && pp.in->type == IN_FILE) 1791 { 1792 st |= NEWLINE|HIDDEN; 1793 pp.hidden++; 1794 error_info.line++; 1795 goto fsm_start; 1796 } 1797 #endif 1798 fsm_newline: 1799 #if CPP 1800 if (sp) 1801 op = sp; 1802 else if (!(pp.in->flags & IN_noguard)) 1803 { 1804 while (tp < op) 1805 if ((c = *tp++) != ' ' && c != '\t') 1806 { 1807 pp.in->flags |= IN_tokens; 1808 break; 1809 } 1810 c = '\n'; 1811 } 1812 st |= NEWLINE; 1813 error_info.line++; 1814 if (*ip == '\n' && *(ip + 1) != '\n' && !pp.macref && !(st & (ADD|HIDDEN))) 1815 { 1816 ip++; 1817 PUTCHR('\n'); 1818 error_info.line++; 1819 } 1820 if ((st & NOTEXT) && ((pp.mode & FILEDEPS) || (pp.option & (DEFINITIONS|PREDEFINITIONS)))) 1821 BACKOUT(); 1822 else 1823 { 1824 debug((-5, "token[%d] %03o = %s [line=%d]", pp.level, c, pptokchr(c), error_info.line)); 1825 PUTCHR('\n'); 1826 PPSYNCLINE(); 1827 if (sp) 1828 { 1829 PPCHECKOUT(); 1830 sp = op; 1831 } 1832 } 1833 goto fsm_start; 1834 #else 1835 st |= NEWLINE; 1836 if (pp.level == 1) 1837 { 1838 error_info.line++; 1839 if (!(st & (JOINING|SPACEOUT))) 1840 { 1841 debug((-5, "token[%d] %03o = %s [line=%d]", pp.level, c, pptokchr(c), error_info.line)); 1842 BACKOUT(); 1843 goto fsm_top; 1844 } 1845 } 1846 BACKOUT(); 1847 if (st & SKIPCONTROL) 1848 { 1849 error_info.line++; 1850 st |= HIDDEN; 1851 pp.hidden++; 1852 goto fsm_start; 1853 } 1854 PUTCHR(c = '\n'); 1855 goto fsm_return; 1856 #endif 1857 1858 #if !CPP 1859 case S_TOK: 1860 PUTCHR(c); 1861 c = TYPE(state) | qual; 1862 break; 1863 1864 case S_TOKB: 1865 BACKIN(); 1866 c = TYPE(state) | qual; 1867 break; 1868 #endif 1869 1870 case S_VS: 1871 PUTCHR(c); 1872 #if !CPP 1873 if (st & NOVERTICAL) 1874 { 1875 error(1, "%s invalid in directives", pptokchr(c)); 1876 st &= ~NOVERTICAL; 1877 } 1878 #endif 1879 #if COMPATIBLE 1880 if (st & COMPATIBILITY) st |= NEWLINE; 1881 #endif 1882 #if CPP 1883 if (!(pp.in->flags & IN_noguard)) 1884 while (tp < op) 1885 if ((c = *tp++) != ' ' && c != '\t') 1886 { 1887 pp.in->flags |= IN_tokens; 1888 break; 1889 } 1890 goto fsm_start; 1891 #else 1892 bp = ip; 1893 rp = fsm[WS1]; 1894 goto fsm_get; 1895 #endif 1896 1897 #if !CPP 1898 case S_WS: 1899 #if COMPATIBLE 1900 if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) st &= ~NEWLINE; 1901 #endif 1902 if (pp.level == 1) 1903 { 1904 if ((st & (COMPATIBILITY|SPACEOUT)) && !(st & TRANSITION)) 1905 { 1906 if (st & (COMPILE|NOTEXT)) 1907 { 1908 #if CATSTRINGS 1909 if ((st & (JOINING|NOTEXT|SPACEOUT)) != SPACEOUT) 1910 #else 1911 if ((st & (NOTEXT|SPACEOUT)) != SPACEOUT) 1912 #endif 1913 { 1914 BACKOUT(); 1915 bp = ip - 1; 1916 rp = fsm[START]; 1917 if (state = rp[c]) goto fsm_next; 1918 goto fsm_get; 1919 } 1920 } 1921 else 1922 #if CATSTRINGS 1923 if (!(st & JOINING)) 1924 #endif 1925 { 1926 tp = op; 1927 bp = ip - 1; 1928 rp = fsm[START]; 1929 if (state = rp[c]) goto fsm_next; 1930 goto fsm_get; 1931 } 1932 BACKIN(); 1933 c = ' '; 1934 goto fsm_return; 1935 } 1936 BACKOUT(); 1937 bp = ip - 1; 1938 rp = fsm[START]; 1939 if (state = rp[c]) goto fsm_next; 1940 goto fsm_get; 1941 } 1942 if (st & (NOSPACE|SKIPCONTROL)) 1943 { 1944 BACKOUT(); 1945 bp = ip - 1; 1946 rp = fsm[START]; 1947 if (state = rp[c]) goto fsm_next; 1948 goto fsm_get; 1949 } 1950 if (c != '\n') 1951 { 1952 BACKIN(); 1953 c = ' '; 1954 } 1955 if (!(pp.option & PRESERVE)) 1956 { 1957 BACKOUT(); 1958 PUTCHR(c); 1959 } 1960 goto fsm_return; 1961 #endif 1962 1963 default: 1964 if (state & SPLICE) 1965 { 1966 switch (c) 1967 { 1968 case MARK: 1969 /* 1970 * internal mark 1971 */ 1972 1973 switch (pp.in->type) 1974 { 1975 case IN_BUFFER: 1976 case IN_FILE: 1977 #if !CPP 1978 case IN_INIT: 1979 #if CATSTRINGS 1980 if ((st & JOINING) && (!INQUOTE(rp) || quot != '"') || pp.level > 1 && (rp == fsm[START] || INQUOTE(rp))) 1981 #else 1982 if (pp.level > 1 && (rp == fsm[START] || INQUOTE(rp))) 1983 #endif 1984 PUTCHR(c); 1985 #endif 1986 break; 1987 default: 1988 switch (GETCHR()) 1989 { 1990 case 'A': 1991 if (!(st & (DEFINITION|DISABLE))) 1992 { 1993 c = GETCHR(); 1994 SYNCIN(); 1995 if (pp.macp->arg[c - ARGOFFSET][-1]) 1996 PUSH_EXPAND(pp.macp->arg[c - ARGOFFSET], pp.macp->line); 1997 else 1998 PUSH_COPY(pp.macp->arg[c - ARGOFFSET], pp.macp->line); 1999 CACHEIN(); 2000 bp = ip; 2001 goto fsm_get; 2002 } 2003 /*FALLTHROUGH*/ 2004 case 'C': 2005 c = GETCHR() - ARGOFFSET; 2006 if (!*(s = pp.macp->arg[c]) && (pp.in->symbol->flags & SYM_VARIADIC) && pp.in->symbol->macro->arity == (c + 1)) 2007 { 2008 s = ip - 3; 2009 while (--op > tp && --s > bp && ppisidig(*s)); 2010 } 2011 else 2012 { 2013 SYNCIN(); 2014 PUSH_COPY(s, pp.macp->line); 2015 CACHEIN(); 2016 } 2017 bp = ip; 2018 goto fsm_get; 2019 case 'F': 2020 error_info.file = (char*)strtoul(ip, &s, 16); 2021 debug((-6, "actual sync: file = \"%s\"", error_info.file)); 2022 bp = ip = s + 1; 2023 goto fsm_get; 2024 case 'L': 2025 error_info.line = strtoul(ip, &s, 16); 2026 debug((-6, "actual sync: line = %d", error_info.line)); 2027 bp = ip = s + 1; 2028 goto fsm_get; 2029 case 'Q': 2030 c = GETCHR(); 2031 SYNCIN(); 2032 PUSH_QUOTE(pp.macp->arg[c - ARGOFFSET], pp.macp->line); 2033 CACHEIN(); 2034 bp = ip - 1; 2035 if (st & (COLLECTING|EOF2NL|JOINING)) rp = fsm[START]; 2036 if (state = rp[c = '"']) goto fsm_next; 2037 goto fsm_get; 2038 case 'S': 2039 c = GETCHR(); 2040 SYNCIN(); 2041 PUSH_SQUOTE(pp.macp->arg[c - ARGOFFSET], pp.macp->line); 2042 CACHEIN(); 2043 bp = ip - 1; 2044 if (st & COLLECTING) rp = fsm[START]; 2045 if (state = rp[c = '\'']) goto fsm_next; 2046 goto fsm_get; 2047 case 'X': 2048 if (pp.in->type != IN_COPY) 2049 st |= SKIPMACRO; 2050 if (pp.level <= 1) 2051 { 2052 bp = ip; 2053 goto fsm_get; 2054 } 2055 if (pp.in->type == IN_EXPAND) 2056 { 2057 st &= ~SKIPMACRO; 2058 PUTCHR(c); 2059 PUTCHR('X'); 2060 } 2061 c = GETCHR(); 2062 break; 2063 case 0: 2064 if ((state &= ~SPLICE) >= TERMINAL) goto fsm_terminal; 2065 goto fsm_begin; 2066 default: 2067 #if DEBUG 2068 error(PANIC, "invalid mark op `%c'", LASTCHR()); 2069 /*FALLTHROUGH*/ 2070 case MARK: 2071 #endif 2072 #if CATSTRINGS 2073 if ((st & (JOINING|QUOTE)) == JOINING) 2074 { 2075 if (!INQUOTE(rp)) 2076 PUTCHR(c); 2077 } 2078 else 2079 #endif 2080 #if CPP 2081 if (rp != fsm[START] && !INQUOTE(rp)) 2082 UNGETCHR(c); 2083 #else 2084 if (rp != fsm[START] && !INQUOTE(rp)) 2085 UNGETCHR(c); 2086 else if (pp.level > 1) 2087 PUTCHR(c); 2088 #endif 2089 break; 2090 } 2091 break; 2092 } 2093 break; 2094 case '?': 2095 /* 2096 * trigraph 2097 */ 2098 2099 if (pp.in->type == IN_FILE) 2100 { 2101 GET(c, n, tp, xp); 2102 if (n == '?') 2103 { 2104 GET(c, n, tp, xp); 2105 if (c = trigraph[n]) 2106 { 2107 if ((st & WARN) && (st & (COMPATIBILITY|TRANSITION)) && !(pp.mode & HOSTED) && !INCOMMENT(rp)) 2108 error(1, "trigraph conversion %c%c%c -> %c%s", '?', '?', n, c, (st & TRANSITION) ? "" : " inhibited"); 2109 #if COMPATIBLE 2110 if ((st & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY) 2111 { 2112 #endif 2113 *(bp = ip - 1) = c; 2114 if (state = rp[c]) goto fsm_next; 2115 goto fsm_get; 2116 #if COMPATIBLE 2117 } 2118 #endif 2119 } 2120 if (n != EOB) BACKIN(); 2121 UNGETCHR(c = '?'); 2122 } 2123 else if (n != EOB) BACKIN(); 2124 } 2125 break; 2126 case '%': 2127 case '<': 2128 case ':': 2129 /* 2130 * digraph = --trigraph 2131 */ 2132 2133 if (pp.in->type == IN_FILE && (pp.option & PLUSPLUS)) 2134 { 2135 m = 0; 2136 GET(c, n, tp, xp); 2137 switch (n) 2138 { 2139 case '%': 2140 if (c == '<') m = '{'; 2141 break; 2142 case '>': 2143 if (c == '%') m = '}'; 2144 else if (c == ':') m = ']'; 2145 break; 2146 case ':': 2147 if (c == '%') m = '#'; 2148 else if (c == '<') m = '['; 2149 break; 2150 } 2151 if (m) 2152 { 2153 if ((st & WARN) && (st & (COMPATIBILITY|TRANSITION)) && !(pp.mode & HOSTED) && !INCOMMENT(rp)) 2154 error(1, "digraph conversion %c%c -> %c%s", c, n, m, (st & TRANSITION) ? "" : " inhibited"); 2155 #if COMPATIBLE 2156 if ((st & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY) 2157 { 2158 #endif 2159 *(bp = ip - 1) = c = m; 2160 if (state = rp[c]) goto fsm_next; 2161 goto fsm_get; 2162 #if COMPATIBLE 2163 } 2164 #endif 2165 } 2166 if (n != EOB) BACKIN(); 2167 } 2168 break; 2169 case '\\': 2170 /* 2171 * line splice 2172 */ 2173 2174 if (pp.in->type == IN_FILE && (!(pp.option & PLUSSPLICE) || !INCOMMENTXX(rp))) 2175 { 2176 m = 0; 2177 GET(c, n, tp, xp); 2178 if ((pp.option & SPLICESPACE) && !INQUOTE(rp)) 2179 while (n == ' ') 2180 { 2181 GET(c, n, tp, xp); 2182 m = 1; 2183 } 2184 if (n == '\r') 2185 { 2186 GET(c, n, tp, xp); 2187 if (n != '\n' && n != EOB) 2188 BACKIN(); 2189 } 2190 if (n == '\n') 2191 { 2192 #if CPP 2193 if (INQUOTE(rp)) 2194 { 2195 if ((pp.option & STRINGSPLIT) && quot == '"') 2196 { 2197 PUTCHR(quot); 2198 PUTCHR(n); 2199 PUTCHR(quot); 2200 } 2201 else if (*pp.lineid) 2202 { 2203 PUTCHR(c); 2204 PUTCHR(n); 2205 } 2206 else 2207 { 2208 st |= HIDDEN; 2209 pp.hidden++; 2210 } 2211 } 2212 else 2213 #else 2214 #if COMPATIBLE 2215 if (!INQUOTE(rp) && (st & (COMPATIBILITY|DEFINITION|TRANSITION)) == (COMPATIBILITY|DEFINITION)) 2216 { 2217 if (op == tp) 2218 { 2219 st |= HIDDEN; 2220 pp.hidden++; 2221 error_info.line++; 2222 if (st & SPACEOUT) 2223 goto fsm_start; 2224 c = (pp.option & SPLICECAT) ? '\t' : ' '; 2225 PUTCHR(c); 2226 goto fsm_check; 2227 } 2228 UNGETCHR(n); 2229 state &= ~SPLICE; 2230 goto fsm_terminal; 2231 } 2232 #endif 2233 #endif 2234 { 2235 st |= HIDDEN; 2236 pp.hidden++; 2237 } 2238 #if CPP 2239 spliced++; 2240 #else 2241 error_info.line++; 2242 #endif 2243 bp = ip; 2244 goto fsm_get; 2245 } 2246 else if ((n == 'u' || n == 'U') && !INQUOTE(rp)) 2247 { 2248 PUTCHR(c); 2249 PUTCHR(n); 2250 bp = ip; 2251 goto fsm_get; 2252 } 2253 #if COMPATIBLE 2254 else if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && (n == '"' || n == '\'') && !INQUOTE(rp)) 2255 { 2256 PUTCHR(c); 2257 PUTCHR(n); 2258 bp = ip; 2259 goto fsm_get; 2260 } 2261 #endif 2262 else if (n != EOB) 2263 BACKIN(); 2264 if (m && INSPACE(rp)) 2265 UNGETCHR(c); 2266 } 2267 #if COMPATIBLE 2268 else if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && !INQUOTE(rp)) 2269 { 2270 GET(c, n, tp, xp); 2271 if (n == '"' || n == '\'') 2272 { 2273 PUTCHR(c); 2274 PUTCHR(n); 2275 bp = ip; 2276 goto fsm_get; 2277 } 2278 if (n != EOB) 2279 BACKIN(); 2280 } 2281 #endif 2282 break; 2283 case '\r': 2284 /* 2285 * barf 2286 */ 2287 2288 if (pp.in->type == IN_FILE) 2289 { 2290 GET(c, n, tp, xp); 2291 if (n == '\n') 2292 { 2293 *(bp = ip - 1) = c = n; 2294 if (state = rp[c]) goto fsm_next; 2295 goto fsm_get; 2296 } 2297 if (n != EOB) BACKIN(); 2298 } 2299 break; 2300 case CC_sub: 2301 /* 2302 * barf & puke 2303 */ 2304 2305 if ((pp.option & ZEOF) && pp.in->type == IN_FILE) 2306 { 2307 pp.in->flags |= IN_eof; 2308 c = 0; 2309 state = S_EOB; 2310 goto fsm_terminal; 2311 } 2312 break; 2313 } 2314 if ((state &= ~SPLICE) >= TERMINAL) 2315 goto fsm_terminal; 2316 PUTCHR(c); 2317 goto fsm_begin; 2318 } 2319 #if CPP 2320 if (INOPSPACE(rp)) 2321 { 2322 BACKIN(); 2323 goto fsm_start; 2324 } 2325 #endif 2326 PUTCHR(c); 2327 bp = ip; 2328 goto fsm_get; 2329 } 2330 #if !CPP 2331 fsm_token: 2332 st &= ~NEWLINE; 2333 if (pp.level == 1) 2334 { 2335 pp.in->flags |= IN_tokens; 2336 if (st & NOTEXT) 2337 { 2338 BACKOUT(); 2339 goto fsm_top; 2340 } 2341 fsm_symbol: 2342 count(token); 2343 } 2344 fsm_check: 2345 if (st & SKIPCONTROL) 2346 { 2347 BACKOUT(); 2348 goto fsm_start; 2349 } 2350 fsm_return: 2351 #if CPP 2352 error_info.line += spliced; 2353 #endif 2354 SETCHR(0); 2355 debug((-5, "token[%d] %03o = %s", pp.level, c, pptokstr(tp, 0))); 2356 SYNC(); 2357 pp.level--; 2358 error_info.indent--; 2359 return c; 2360 #endif 2361 } 2362 2363 #if CPP && POOL 2364 2365 #include <ls.h> 2366 #include <wait.h> 2367 2368 /* 2369 * output pool status on exit 2370 */ 2371 2372 static void 2373 poolstatus(void) 2374 { 2375 error(ERROR_OUTPUT|0, pp.pool.output, "%d", error_info.errors != 0); 2376 } 2377 2378 /* 2379 * loop on < input output > 2380 */ 2381 2382 static void 2383 pool(void) 2384 { 2385 char* ifile; 2386 char* ofile; 2387 2388 ppflushout(); 2389 if (!sfnew(sfstdin, NiL, SF_UNBOUND, pp.pool.input, SF_READ)) 2390 error(ERROR_SYSTEM|3, "cannot dup pool input"); 2391 2392 /* 2393 * kick the -I cache 2394 */ 2395 2396 ppsearch(".", T_STRING, SEARCH_EXISTS); 2397 2398 /* 2399 * loop on < input output > 2400 */ 2401 2402 pp.pool.input = 0; 2403 while (ifile = sfgetr(sfstdin, '\n', 1)) 2404 { 2405 if (!(ofile = strchr(ifile, ' '))) 2406 error(3, "%s: pool output file expected", ifile); 2407 *ofile++ = 0; 2408 waitpid(0, NiL, WNOHANG); 2409 switch (fork()) 2410 { 2411 case -1: 2412 error(ERROR_SYSTEM|3, "cannot fork pool"); 2413 case 0: 2414 atexit(poolstatus); 2415 error_info.errors = 0; 2416 error_info.warnings = 0; 2417 close(0); 2418 if (open(ifile, O_RDONLY)) 2419 error(ERROR_SYSTEM|3, "%s: cannot read", ifile); 2420 close(1); 2421 if (open(ofile, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) != 1) 2422 error(ERROR_SYSTEM|3, "%s: cannot create", ofile); 2423 pp.outfile = ofile; 2424 pathcanon(ifile, 0); 2425 ifile = ppsetfile(ifile)->name; 2426 #if CHECKPOINT 2427 if (pp.mode & DUMP) 2428 { 2429 if (!pp.pragma) 2430 error(3, "#%s must be enabled for checkpoints", dirname(PRAGMA)); 2431 (*pp.pragma)(dirname(PRAGMA), pp.pass, keyname(X_CHECKPOINT), pp.checkpoint, 1); 2432 } 2433 #endif 2434 PUSH_FILE(ifile, 0); 2435 return; 2436 } 2437 } 2438 while (wait(NiL) != -1); 2439 } 2440 2441 #endif 2442