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