1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1986-2012 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Eclipse Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.eclipse.org/org/documents/epl-v10.html * 11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * * 19 ***********************************************************************/ 20 #pragma prototyped 21 /* 22 * Glenn Fowler 23 * AT&T Research 24 * 25 * convert C prototypes to ANSI, K&R and C++ styles or K&R to ANSI 26 * slips into the pp block read 27 * 28 * define PROTOMAIN for standalone proto 29 * PROTOMAIN is coded for minimal library support 30 */ 31 32 static const char id[] = "\n@(#)$Id: proto (AT&T Research) 2008-05-11 $\0\n"; 33 34 #if PROTOMAIN 35 36 #include "ppfsm.c" 37 38 #include <hashkey.h> 39 40 #if PROTO_STANDALONE 41 #undef O_RDONLY 42 #endif 43 44 #else 45 46 #include "pplib.h" 47 #include "ppfsm.h" 48 49 #endif 50 51 #define GENERATED "/* : : generated by proto : : */\n" 52 53 #define PRAGMADIR "pragma" /* pragma directive */ 54 #define MAGICTOP 80 /* must be in these top lines */ 55 56 #ifndef elementsof 57 #define elementsof(x) (sizeof(x)/sizeof(x[0])) 58 #endif 59 60 typedef struct Key_s 61 { 62 const char* name; 63 size_t size; 64 int hit; 65 int val; 66 } Key_t; 67 68 typedef struct Proto_s /* proto buffer state */ 69 { 70 int brace; /* {..} level */ 71 int call; /* call level */ 72 int fd; /* input file descriptor */ 73 char* file; /* input file name */ 74 long flags; /* coupled flags */ 75 long options; /* uncoupled flags */ 76 char* package; /* header package */ 77 int line; /* input line count */ 78 int test; /* testing */ 79 80 char* tp; /* input token base */ 81 82 int iz; /* input buffer size */ 83 char* ib; /* input buffer base */ 84 char* ip; /* input buffer pointer */ 85 86 int oz; /* output buffer size */ 87 char* ob; /* output buffer base */ 88 char* op; /* output buffer pointer */ 89 char* ox; /* output buffer externalize */ 90 91 char cc[3]; /* beg mid end comment char */ 92 char pushback[4]; /* pushback area for caller */ 93 94 char variadic[256]; /* variadic args buffer */ 95 96 /* output buffer */ 97 /* slide buffer */ 98 /* input buffer */ 99 } Proto_t; 100 101 /* 102 * proto is separate from pp so these undef's are ok 103 */ 104 105 #undef CLASSIC 106 #define CLASSIC (1L<<0) 107 #undef DECLARE 108 #define DECLARE (1L<<1) 109 #undef DEFINE 110 #define DEFINE (1L<<2) 111 #undef DIRECTIVE 112 #define DIRECTIVE (1L<<3) 113 #undef ERROR 114 #define ERROR (1L<<4) 115 #undef EXTERN 116 #define EXTERN (1L<<5) 117 #undef EXTERNALIZE 118 #define EXTERNALIZE (1L<<6) 119 #undef IDID 120 #define IDID (1L<<7) 121 #undef INDIRECT 122 #define INDIRECT (1L<<8) 123 #undef INIT 124 #define INIT (1L<<9) 125 #undef INIT_DEFINE 126 #define INIT_DEFINE (1L<<10) 127 #undef INIT_INCLUDE 128 #define INIT_INCLUDE (1L<<11) 129 #undef JUNK 130 #define JUNK (1L<<12) 131 #undef LINESYNC 132 #define LINESYNC (1L<<13) 133 #undef MANGLE 134 #define MANGLE (1L<<14) 135 #undef MATCH 136 #define MATCH (1L<<15) 137 #undef MORE 138 #define MORE (1L<<16) 139 #undef OTHER 140 #define OTHER (1L<<17) 141 #undef PASS 142 #define PASS (1L<<18) 143 #undef PLUSONLY 144 #define PLUSONLY (1L<<19) 145 #undef PLUSPLUS 146 #define PLUSPLUS (1L<<20) 147 #undef RECURSIVE 148 #define RECURSIVE (1L<<21) 149 #undef SHARP 150 #define SHARP (1L<<22) 151 #undef SKIP 152 #define SKIP (1L<<23) 153 #undef SLIDE 154 #define SLIDE (1L<<24) 155 #undef TOKENS 156 #define TOKENS (1L<<25) 157 #undef TYPEDEF 158 #define TYPEDEF (1L<<26) 159 #undef VARIADIC 160 #define VARIADIC (1L<<27) 161 #undef VARIADIC2 162 #define VARIADIC2 (1L<<28) 163 #undef YACC 164 #define YACC (1L<<29) 165 #undef YACCSPLIT 166 #define YACCSPLIT (1L<<30) 167 #undef YACC2 168 #define YACC2 (1L<<31) 169 170 #undef GLOBAL 171 #define GLOBAL (MORE) 172 173 #undef REGULAR 174 #define REGULAR (1L<<0) 175 176 #ifndef CHUNK 177 #define CHUNK 1024 178 #endif 179 #define BLOCK (16*CHUNK) 180 181 #define T_VA_START (N_TOKEN+1) 182 183 #define RESERVED(b,e,n) ((((long)(b))<<16)|(((long)(e))<<8)|((long)(n))) 184 185 #define KEYENT(s,m,v) {s,sizeof(s)-1,m,v} 186 187 #define HIT_prototyped 0x01 188 #define HIT_noticed 0x02 189 190 static const Key_t pragmas[] = 191 { 192 KEYENT("prototyped", HIT_prototyped, 1), /* NOTE: first entry */ 193 KEYENT("noprototyped", HIT_prototyped, 0), 194 KEYENT("noticed", HIT_noticed, 1), 195 KEYENT("nonoticed", HIT_noticed, 0), 196 }; 197 198 #if PROTOMAIN 199 static const Key_t notices[] = 200 { 201 KEYENT("Copyright", HIT_noticed, 1), 202 KEYENT("COPYRIGHT", HIT_noticed, 1), 203 KEYENT("copyright", HIT_noticed, 1), 204 KEYENT("Public Domain", HIT_noticed, 0), 205 KEYENT("PUBLIC DOMAIN", HIT_noticed, 0), 206 }; 207 #endif 208 209 /* 210 * generate integer 211 * pointer to end returned 212 */ 213 214 static char* 215 number(register char* p, register long n) 216 { 217 register long d; 218 219 for (d = 1000000; d > 1; d /= 10) 220 if (n >= d) *p++ = '0' + (n / d) % 10; 221 *p++ = '0' + n % 10; 222 return p; 223 } 224 225 #if PROTOMAIN 226 227 static int errors; 228 229 #if PROTO_STANDALONE 230 231 /* 232 * namespace pollution forces us to claim parts of libc 233 */ 234 235 #undef memcpy 236 #define memcpy(t,f,n) memcopy(t,f,n) 237 #undef strcpy 238 #define strcpy(t,f) strcopy(t,f) 239 #undef strlen 240 #define strlen(s) sstrlen(s) 241 #undef strncmp 242 #define strncmp(s,t,n) sstrncmp(s,t,n) 243 244 /* 245 * environmentally safe strlen() 246 */ 247 248 static int 249 sstrlen(register const char* s) 250 { 251 register const char* b; 252 253 for (b = s; *s; s++); 254 return s - b; 255 } 256 257 /* 258 * environmentally safe strncmp() 259 */ 260 261 static int 262 sstrncmp(register const char* s, register const char* t, register int n) 263 { 264 register const char* e = s + n; 265 266 while (s < e) 267 { 268 if (*s != *t || !*s) 269 return *s - *t; 270 s++; 271 t++; 272 } 273 return 0; 274 } 275 276 /* 277 * strcpy() except pointer to end returned 278 */ 279 280 static char* 281 strcopy(register char* s, register const char* t) 282 { 283 while (*s++ = *t++); 284 return s - 1; 285 } 286 287 #endif 288 289 static void 290 proto_error(char* iob, int level, char* msg, char* arg) 291 { 292 register char* p; 293 char buf[1024]; 294 295 p = strcopy(buf, "proto: "); 296 if (iob) 297 { 298 register Proto_t* proto = (Proto_t*)(iob - sizeof(Proto_t)); 299 300 if (proto->line) 301 { 302 if (proto->file) 303 { 304 *p++ = '"'; 305 p = strcopy(p, proto->file); 306 *p++ = '"'; 307 *p++ = ','; 308 *p++ = ' '; 309 } 310 p = strcopy(p, "line "); 311 p = number(p, proto->line); 312 } 313 else if (proto->file) 314 p = strcopy(p, proto->file); 315 } 316 else 317 { 318 p = strcopy(p, msg); 319 msg = arg; 320 arg = 0; 321 } 322 if (*(p - 1) != ' ') 323 { 324 *p++ = ':'; 325 *p++ = ' '; 326 } 327 if (level == 1) 328 p = strcopy(p, "warning: "); 329 p = strcopy(p, msg); 330 if (arg) 331 { 332 *p++ = ' '; 333 p = strcopy(p, arg); 334 } 335 *p++ = '\n'; 336 write(2, buf, p - buf); 337 if (level >= 3) 338 exit(level - 2); 339 if (level >= 2) 340 errors++; 341 } 342 343 /* 344 * memcpy() but pointer to end returned 345 */ 346 347 static char* 348 memcopy(register char* s, register char* t, int n) 349 { 350 register char* e = t + n; 351 352 while (t < e) *s++ = *t++; 353 return s; 354 } 355 356 #include "../libast/port/astlicense.c" 357 358 #else 359 360 #define memcopy(s,t,n) (((char*)memcpy(s,t,n))+(n)) 361 362 #endif 363 364 /* 365 * generate line sync 366 * pointer to end returned 367 */ 368 369 static char* 370 linesync(register Proto_t* proto, register char* p, register long n) 371 { 372 #if PROTOMAIN 373 if (proto->flags & LINESYNC) 374 #endif 375 { 376 #if PROTOMAIN 377 p = strcopy(p, "\n#line "); 378 #else 379 p = strcopy(p, "\n# "); 380 #endif 381 p = number(p, n); 382 *p++ = '\n'; 383 } 384 return p; 385 } 386 387 /* 388 * output init header 389 * pointer to end returned 390 */ 391 392 static char* 393 init(Proto_t* proto, char* op, int flags) 394 { 395 register char* s; 396 397 if (flags & INIT_DEFINE) 398 { 399 op = strcopy(op, "\ 400 \n\ 401 #if !defined(__PROTO__)\n\ 402 # if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)\n\ 403 # if defined(__cplusplus)\n\ 404 # define __LINKAGE__ \"C\"\n\ 405 # else\n\ 406 # define __LINKAGE__\n\ 407 # endif\n\ 408 # define __STDARG__\n\ 409 # define __PROTO__(x) x\n\ 410 # define __OTORP__(x)\n\ 411 # define __PARAM__(n,o) n\n\ 412 # if !defined(__STDC__) && !defined(__cplusplus)\n\ 413 # if !defined(c_plusplus)\n\ 414 # define const\n\ 415 # endif\n\ 416 # define signed\n\ 417 # define void int\n\ 418 # define volatile\n\ 419 # define __V_ char\n\ 420 # else\n\ 421 # define __V_ void\n\ 422 # endif\n\ 423 # else\n\ 424 # define __PROTO__(x) ()\n\ 425 # define __OTORP__(x) x\n\ 426 # define __PARAM__(n,o) o\n\ 427 # define __LINKAGE__\n\ 428 # define __V_ char\n\ 429 # define const\n\ 430 # define signed\n\ 431 # define void int\n\ 432 # define volatile\n\ 433 # endif\n\ 434 # define __MANGLE__ __LINKAGE__\n\ 435 # if defined(__cplusplus) || defined(c_plusplus)\n\ 436 # define __VARARG__ ...\n\ 437 # else\n\ 438 # define __VARARG__\n\ 439 # endif\n\ 440 # if defined(__STDARG__)\n\ 441 # define __VA_START__(p,a) va_start(p,a)\n\ 442 # else\n\ 443 # define __VA_START__(p,a) va_start(p)\n\ 444 # endif\n\ 445 # if !defined(__INLINE__)\n\ 446 # if defined(__cplusplus)\n\ 447 # define __INLINE__ extern __MANGLE__ inline\n\ 448 # else\n\ 449 # if defined(_WIN32) && !defined(__GNUC__)\n\ 450 # define __INLINE__ __inline\n\ 451 # endif\n\ 452 # endif\n\ 453 # endif\n\ 454 #endif\n\ 455 #if !defined(__LINKAGE__)\n\ 456 #define __LINKAGE__ /* 2004-08-11 transition */\n\ 457 #endif\n\ 458 "); 459 } 460 else 461 op = strcopy(op, "\ 462 \n\ 463 #if !defined(__PROTO__)\n\ 464 #include <prototyped.h>\n\ 465 #endif\n\ 466 #if !defined(__LINKAGE__)\n\ 467 #define __LINKAGE__ /* 2004-08-11 transition */\n\ 468 #endif\n\ 469 "); 470 if (proto->package) 471 { 472 s = "\ 473 #ifndef __MANGLE_%_DATA__\n\ 474 # ifdef _BLD_%\n\ 475 # ifdef __EXPORT__\n\ 476 # define __MANGLE_%_DATA__ __MANGLE__ __EXPORT__\n\ 477 # else\n\ 478 # define __MANGLE_%_DATA__ __MANGLE__\n\ 479 # endif\n\ 480 # define __MANGLE_%_FUNC__ __MANGLE__\n\ 481 # else\n\ 482 # ifdef __IMPORT__\n\ 483 # define __MANGLE_%_DATA__ __MANGLE__ __IMPORT__\n\ 484 # else\n\ 485 # define __MANGLE_%_DATA__ __MANGLE__\n\ 486 # endif\n\ 487 # define __MANGLE_%_FUNC__ __MANGLE__\n\ 488 # endif\n\ 489 #endif\n\ 490 "; 491 for (;;) 492 { 493 switch (*op++ = *s++) 494 { 495 case 0: 496 op--; 497 break; 498 case '%': 499 op = strcopy(op - 1, proto->package); 500 continue; 501 default: 502 continue; 503 } 504 break; 505 } 506 } 507 return op; 508 } 509 510 #define BACKOUT() (op=ko) 511 #define CACHE() do{CACHEIN();CACHEOUT();call=proto->call;}while(0) 512 #define CACHEIN() (ip=proto->ip) 513 #define CACHEOUT() (op=proto->op) 514 #define GETCHR() (*(unsigned char*)ip++) 515 #define KEEPOUT() (ko=op) 516 #define LASTOUT() (*(op-1)) 517 #define PUTCHR(c) (*op++=(c)) 518 #define SYNC() do{SYNCIN();SYNCOUT();proto->flags&=~(EXTERN|INIT|OTHER|VARIADIC|VARIADIC2);proto->flags|=flags&(EXTERN|INIT|OTHER|VARIADIC|VARIADIC2);proto->call=call;}while(0) 519 #define SYNCIN() (proto->ip=ip) 520 #define SYNCOUT() (proto->op=op) 521 #define UNGETCHR() (ip--) 522 #define UNPUTCHR() (op--) 523 524 /* 525 * advance to the next non-space character 526 */ 527 528 static char* 529 nns(register char* s) 530 { 531 while (*s == ' ' || *s == '\t' || *s == '\n') 532 s++; 533 return s; 534 } 535 536 #define DIR_if 01 537 #define DIR_el 02 538 #define DIR_en 03 539 #define DIR 03 540 541 /* 542 * update directive mask 543 */ 544 545 static int 546 directive(register char* s, int dir) 547 { 548 switch (*(s = nns(s))) 549 { 550 case 'e': 551 case 'i': 552 dir <<= 2; 553 switch (*++s) 554 { 555 case 'f': 556 dir |= DIR_if; 557 break; 558 case 'l': 559 dir |= DIR_el; 560 break; 561 case 'n': 562 dir |= DIR_en; 563 break; 564 } 565 break; 566 } 567 return dir; 568 } 569 570 /* 571 * the tokenizer 572 * top level calls loop until EOB 573 * recursive calls just return the next token 574 */ 575 576 static int 577 lex(register Proto_t* proto, register long flags) 578 { 579 register char* ip; 580 register char* op; 581 register int c; 582 register int state; 583 register short* rp; 584 char* m; 585 char* e; 586 char* t; 587 char* bp; 588 char* v; 589 char* im; 590 char* ko; 591 char* aom; 592 int n; 593 int line; 594 int quot; 595 int brack; 596 int sub; 597 int x; 598 int vc; 599 600 char* ie = 0; 601 char* om = 0; 602 char* aim = 0; 603 char* aie = 0; 604 char* func = 0; 605 int call = 0; 606 int dir = 0; 607 int group = 0; 608 int last = 0; 609 int paren = 0; 610 #if PROTOMAIN 611 char* qe = 0; 612 int qn = 0; 613 int args = 0; 614 #endif 615 616 CACHE(); 617 #if PROTOMAIN 618 if (flags & EXTERN) KEEPOUT(); 619 #endif 620 fsm_start: 621 proto->tp = ip; 622 state = PROTO; 623 bp = ip; 624 do 625 { 626 rp = fsm[state]; 627 fsm_get: 628 while (!(state = rp[c = GETCHR()])); 629 fsm_next: 630 ; 631 } while (state > 0); 632 if ((n = ip - bp - 1) > 0) 633 { 634 ip = bp; 635 MEMCPY(op, ip, n); 636 ip++; 637 } 638 state = ~state; 639 fsm_terminal: 640 switch (TERM(state)) 641 { 642 case S_CHR: 643 if (op > proto->ob && *(op - 1) == '=' && (op == proto->ob + 1 || *(op - 2) != '=')) switch (c) 644 { 645 case '+': 646 case '-': 647 case '*': 648 case '&': 649 PUTCHR(' '); 650 break; 651 } 652 PUTCHR(c); 653 break; 654 655 case S_CHRB: 656 UNGETCHR(); 657 c = LASTOUT(); 658 break; 659 660 case S_COMMENT: 661 switch (c) 662 { 663 case '\n': 664 if (INCOMMENTXX(rp)) goto fsm_newline; 665 PUTCHR(c); 666 proto->line++; 667 rp = fsm[COM2]; 668 break; 669 case '/': 670 #if PROTOMAIN 671 if ((flags & (EXTERN|MATCH)) == EXTERN) BACKOUT(); 672 else 673 #endif 674 PUTCHR(c); 675 if (INCOMMENTXX(rp)) 676 { 677 rp = fsm[COM5]; 678 break; 679 } 680 goto fsm_start; 681 case EOF: 682 break; 683 default: 684 #if PROTOMAIN 685 if ((flags & (EXTERN|MATCH)) == EXTERN) BACKOUT(); 686 else 687 #endif 688 PUTCHR(c); 689 rp = fsm[INCOMMENTXX(rp) ? COM5 : COM3]; 690 break; 691 } 692 bp = ip; 693 goto fsm_get; 694 695 case S_EOB: 696 if (c) 697 { 698 if (state = fsm[TERMINAL][INDEX(rp)+1]) 699 goto fsm_terminal; 700 SYNC(); 701 return 0; 702 } 703 UNGETCHR(); 704 fsm_eob: 705 if ((flags & (DECLARE|GLOBAL|RECURSIVE)) == GLOBAL && (proto->flags & MORE)) 706 { 707 #if PROTOMAIN 708 if (!(flags & EXTERN)) /* XXX */ 709 #endif 710 flags |= SLIDE; 711 c = ip - proto->ib; 712 if (!(flags & MATCH)) 713 im = proto->tp; 714 if (ip > proto->ib) 715 { 716 n = ip - im; 717 if (ip - n < proto->ib) 718 proto->flags |= ERROR; 719 memcopy(proto->ib - n, ip - n, n); 720 ip = proto->ib; 721 } 722 proto->tp -= c; 723 if (flags & MATCH) 724 { 725 im -= c; 726 ie -= c; 727 } 728 if (aim) 729 aim -= c; 730 if (aie) 731 aie -= c; 732 if ((n = read(proto->fd, ip, proto->iz)) > 0) 733 { 734 if ((proto->options & REGULAR) && n < proto->iz) 735 { 736 proto->flags &= ~MORE; 737 close(proto->fd); 738 } 739 *(ip + n) = 0; 740 if (state & SPLICE) 741 goto fsm_splice; 742 bp = ip; 743 goto fsm_get; 744 } 745 *ip = 0; 746 proto->flags &= ~MORE; 747 close(proto->fd); 748 } 749 if (state & SPLICE) 750 goto fsm_splice; 751 /* NOTE: RECURSIVE lex() should really SLIDE too */ 752 if (!(flags & RECURSIVE) && (state = rp[c = EOF])) 753 { 754 bp = ip; 755 goto fsm_next; 756 } 757 SYNC(); 758 return 0; 759 760 case S_LITBEG: 761 quot = c; 762 #if PROTOMAIN 763 if (c == '"' && qe) 764 { 765 for (n = 0, t = qe + 1; t < op && (*t == ' ' || *t == '\t' || *t == '\n' && ++n || *t >= 'A' && *t <= 'Z' || *t == '_'); t++); 766 if (t == op) 767 { 768 op = qe; 769 qe = 0; 770 qn = n; 771 } 772 else PUTCHR(c); 773 } 774 else 775 #endif 776 PUTCHR(c); 777 rp = fsm[LIT1]; 778 bp = ip; 779 goto fsm_get; 780 781 case S_LITEND: 782 if (c == quot) 783 { 784 #if PROTOMAIN 785 if (!(flags & DIRECTIVE)) 786 qe = (c == '"') ? op : (char*)0; 787 #endif 788 PUTCHR(c); 789 #if PROTOMAIN 790 while (qn > 0) 791 { 792 qn--; 793 PUTCHR('\n'); 794 } 795 #endif 796 } 797 else if (c != '\n' && c != EOF) 798 { 799 PUTCHR(c); 800 bp = ip; 801 goto fsm_get; 802 } 803 else 804 { 805 #if PROTOMAIN 806 while (qn > 0) 807 { 808 qn--; 809 PUTCHR('\n'); 810 } 811 #endif 812 UNGETCHR(); 813 } 814 c = T_INVALID; 815 break; 816 817 case S_LITESC: 818 #if PROTOMAIN 819 if (flags & CLASSIC) PUTCHR(c); 820 else 821 #endif 822 switch (c) 823 { 824 case 'a': 825 n = CC_bel; 826 goto fsm_oct; 827 case 'E': 828 n = CC_esc; 829 goto fsm_oct; 830 case 'v': 831 n = CC_vt; 832 goto fsm_oct; 833 case 'x': 834 SYNC(); 835 lex(proto, (flags & GLOBAL) | RECURSIVE); 836 for (n = x = 0; (c = GETCHR()), x < 3; x++) switch (c) 837 { 838 case '0': case '1': case '2': case '3': 839 case '4': case '5': case '6': case '7': 840 case '8': case '9': 841 n = (n << 4) + c - '0'; 842 break; 843 case 'a': case 'b': case 'c': case 'd': 844 case 'e': case 'f': 845 n = (n << 4) + c - 'a' + 10; 846 break; 847 case 'A': case 'B': case 'C': case 'D': 848 case 'E': case 'F': 849 n = (n << 4) + c - 'A' + 10; 850 break; 851 default: 852 goto fsm_hex; 853 } 854 fsm_hex: 855 UNGETCHR(); 856 fsm_oct: 857 PUTCHR(((n >> 6) & 07) + '0'); 858 PUTCHR(((n >> 3) & 07) + '0'); 859 PUTCHR((n & 07) + '0'); 860 break; 861 default: 862 PUTCHR(c); 863 break; 864 } 865 rp = fsm[LIT1]; 866 bp = ip; 867 goto fsm_get; 868 869 case S_MACRO: 870 UNGETCHR(); 871 #if PROTOMAIN 872 if ((flags & EXTERN) && *proto->tp == 's' && !strncmp(proto->tp, "static", 6)) 873 { 874 c = T_EXTERN; 875 break; 876 } 877 #endif 878 if (*proto->tp == '_' && !strncmp(proto->tp, "__STDPP__directive", 6)) c = '#'; 879 else c = T_ID; 880 881 break; 882 883 case S_NL: 884 fsm_newline: 885 proto->line++; 886 #if PROTOMAIN 887 if (flags & EXTERN) 888 { 889 if (op != proto->ob && LASTOUT() != ' ' && LASTOUT() != '\n') 890 PUTCHR(' '); 891 } 892 else 893 #endif 894 PUTCHR(c); 895 if (flags & DIRECTIVE) 896 { 897 #if PROTOMAIN 898 if (flags & CLASSIC) 899 { 900 if (flags & EXTERN) BACKOUT(); 901 if (flags & JUNK) 902 { 903 *(ip - 1) = 0; 904 op = strcopy(om, "/* "); 905 op = strcopy(op, im); 906 op = strcopy(op, " */\n"); 907 } 908 flags &= ~(DEFINE|DIRECTIVE|IDID|INDIRECT|JUNK|MATCH|SHARP|TYPEDEF); 909 } 910 else 911 #endif 912 { 913 if ((flags & (DEFINE|SHARP)) == (DEFINE|SHARP)) 914 { 915 *(ip - 1) = 0; 916 op = strcopy(om, "#if defined(__STDC__) || defined(__STDPP__)\n"); 917 op = strcopy(op, im); 918 op = strcopy(op, "\n#else\n"); 919 bp = ip; 920 ip = im; 921 *op++ = *ip++; 922 while (*op = *ip++) 923 if (*op++ == '#' && *ip != '(') 924 { 925 op--; 926 while (*--op == ' ' || *op == '\t'); 927 if (*ip == '#') 928 { 929 op = strcopy(op + 1, "/**/"); 930 while (*++ip == ' ' || *ip == '\t'); 931 } 932 else 933 { 934 if (*op != '"') *++op = '"'; 935 op++; 936 while (*ip == ' ' || *ip == '\t') ip++; 937 while ((c = *ip) >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c >= '0' && c <= '9' || c == '_') *op++ = *ip++; 938 while (*ip == ' ' || *ip == '\t') ip++; 939 if (*ip == '"') ip++; 940 else *op++ = '"'; 941 } 942 } 943 ip = bp; 944 op = strcopy(op, "\n#endif\n"); 945 op = linesync(proto, op, proto->line); 946 } 947 flags &= ~(DEFINE|DIRECTIVE|IDID|INDIRECT|MATCH|OTHER|SHARP|SKIP|TOKENS|TYPEDEF); 948 } 949 call = 0; 950 group = 0; 951 paren = 0; 952 last = '\n'; 953 } 954 if (paren == 0 && (flags & (MATCH|RECURSIVE|SKIP|SLIDE)) == SLIDE) 955 { 956 #if PROTOMAIN 957 if (flags & EXTERN) BACKOUT(); 958 #endif 959 SYNC(); 960 return 0; 961 } 962 goto fsm_start; 963 964 case S_QUAL: 965 PUTCHR(c); 966 rp = fsm[NEXT(state)]; 967 bp = ip; 968 goto fsm_get; 969 970 case S_TOK: 971 PUTCHR(c); 972 c = TYPE(state); 973 break; 974 975 case S_TOKB: 976 UNGETCHR(); 977 c = TYPE(state); 978 break; 979 980 case S_RESERVED: 981 UNGETCHR(); 982 c = T_ID; 983 if (!(flags & DECLARE)) switch (RESERVED(*proto->tp, *(ip - 1), ip - proto->tp)) 984 { 985 case RESERVED('N', 'N', 3): 986 if (proto->tp[1] == 'o') 987 c = T_DO; 988 break; 989 case RESERVED('d', 'o', 2): 990 c = T_DO; 991 break; 992 case RESERVED('e', 'e', 4): 993 if (!(flags & RECURSIVE) && (flags & (DIRECTIVE|TOKENS)) != DIRECTIVE && !strncmp(proto->tp, "else", 4)) 994 { 995 c = T_ELSE; 996 goto fsm_id; 997 } 998 break; 999 case RESERVED('e', 'n', 6): 1000 if (!strncmp(proto->tp, "extern", 6)) 1001 c = T_EXTERN; 1002 break; 1003 case RESERVED('f', 'r', 3): 1004 if (!(flags & RECURSIVE) && !strncmp(proto->tp, "for", 3)) 1005 { 1006 c = T_FOR; 1007 goto fsm_id; 1008 } 1009 break; 1010 case RESERVED('i', 'f', 2): 1011 c = T_IF; 1012 break; 1013 case RESERVED('i', 'e', 6): 1014 if (!strncmp(proto->tp, "inline", 6) && !(flags & (MATCH|SKIP|TOKENS|TYPEDEF)) && proto->brace == 0 && paren == 0 && group == 0 && (last == ';' || last == '}' || last == '\n' || last == 0)) 1015 { 1016 flags |= SKIP; 1017 SYNC(); 1018 line = proto->line; 1019 op = strcopy(op - 6, "__INLINE__"); 1020 SYNC(); 1021 } 1022 break; 1023 case RESERVED('r', 'n', 6): 1024 if (!(flags & RECURSIVE) && !strncmp(proto->tp, "return", 6)) 1025 { 1026 c = T_RETURN; 1027 goto fsm_id; 1028 } 1029 break; 1030 case RESERVED('s', 'c', 6): 1031 if ((proto->options & EXTERNALIZE) && !strncmp(proto->tp, "static", 6)) 1032 { 1033 proto->ox = op - 6; 1034 flags |= EXTERNALIZE; 1035 } 1036 break; 1037 case RESERVED('t', 'f', 7): 1038 if (!(flags & RECURSIVE) && !strncmp(proto->tp, "typedef", 7)) 1039 { 1040 flags |= TYPEDEF; 1041 c = T_EXTERN; 1042 } 1043 break; 1044 case RESERVED('v', 't', 8): 1045 if (*ip == '(' && !strncmp(proto->tp, "va_start", 8)) c = T_VA_START; 1046 break; 1047 case RESERVED('v', 'd', 4): 1048 if (!strncmp(proto->tp, "void", 4)) 1049 { 1050 if (flags & (CLASSIC|PLUSONLY|INIT_DEFINE|INIT_INCLUDE)) c = T_VOID; 1051 else 1052 { 1053 SYNC(); 1054 line = proto->line; 1055 if (lex(proto, (flags & GLOBAL) | RECURSIVE) == '*') 1056 { 1057 memcopy(op - 4, "__V_", 4); 1058 memcopy(ip - 4, "__V_", 4); 1059 } 1060 else c = T_VOID; 1061 proto->line = line; 1062 SYNC(); 1063 bp = ip; 1064 } 1065 } 1066 break; 1067 case RESERVED('w', 'e', 5): 1068 if (!(flags & RECURSIVE) && !strncmp(proto->tp, "while", 5)) 1069 { 1070 c = T_WHILE; 1071 goto fsm_id; 1072 } 1073 break; 1074 } 1075 #if PROTOMAIN 1076 if ((flags & CLASSIC) && c != T_EXTERN) 1077 c = T_ID; 1078 #endif 1079 break; 1080 1081 case S_VS: 1082 goto fsm_start; 1083 1084 case S_WS: 1085 UNGETCHR(); 1086 #if PROTOMAIN 1087 if ((flags & (EXTERN|MATCH)) == EXTERN) 1088 { 1089 while (op > proto->ob && (*(op - 1) == ' ' || *(op - 1) == '\t')) 1090 op--; 1091 if (op > proto->ob && *(op - 1) != '\n') *op++ = ' '; 1092 } 1093 #endif 1094 goto fsm_start; 1095 1096 default: 1097 if (state & SPLICE) 1098 { 1099 if (c == '\\') 1100 { 1101 if (!(n = GETCHR())) 1102 { 1103 goto fsm_eob; 1104 fsm_splice: 1105 c = '\\'; 1106 n = GETCHR(); 1107 } 1108 if (n == '\n') 1109 { 1110 proto->line++; 1111 PUTCHR('\\'); 1112 PUTCHR('\n'); 1113 bp = ip; 1114 goto fsm_get; 1115 } 1116 UNGETCHR(); 1117 } 1118 state &= ~SPLICE; 1119 if (state >= TERMINAL) 1120 goto fsm_terminal; 1121 rp = fsm[state]; 1122 } 1123 PUTCHR(c); 1124 bp = ip; 1125 goto fsm_get; 1126 } 1127 if (!(flags & (INIT_DEFINE|INIT_INCLUDE|RECURSIVE))) 1128 { 1129 if (!(flags & DIRECTIVE)) switch (c) 1130 { 1131 case '(': 1132 #if PROTOMAIN 1133 if (!(flags & CLASSIC) || proto->brace == 0) 1134 #endif 1135 { 1136 if (paren++ == 0) 1137 { 1138 #if PROTOMAIN 1139 if (!(flags & CLASSIC) || group <= 1) 1140 #endif 1141 { 1142 #if PROTOMAIN 1143 args = 0; 1144 #endif 1145 if (group++ == 0) group++; 1146 else if (flags & INDIRECT) call++; 1147 flags |= MATCH; 1148 im = ip - 1; 1149 om = op - 1; 1150 } 1151 sub = 0; 1152 } 1153 else if (paren == 2 && !aim) 1154 { 1155 sub++; 1156 if (last == '(') 1157 { 1158 flags &= ~MATCH; 1159 om = 0; 1160 } 1161 else if (flags & INDIRECT) 1162 { 1163 aim = ip - 1; 1164 aom = op - 1; 1165 } 1166 else if ((flags & (MATCH|TOKENS)) == MATCH) 1167 { 1168 for (m = ip - 2; m > im && (*m == ' ' || *m == '\t'); m--); 1169 if (m != im && sub == 1) 1170 { 1171 m = im + (*nns(ip) == '*'); 1172 } 1173 if (m == im) 1174 { 1175 flags &= ~MATCH; 1176 om = 0; 1177 } 1178 } 1179 else if ((flags & MATCH) && sub == 1 && *nns(ip) != '*') 1180 { 1181 flags &= ~MATCH; 1182 om = 0; 1183 } 1184 } 1185 flags &= ~TOKENS; 1186 } 1187 break; 1188 case ')': 1189 #if PROTOMAIN 1190 if (!(flags & CLASSIC) || proto->brace == 0) 1191 #endif 1192 if (--paren == 0) 1193 { 1194 #if PROTOMAIN 1195 if (flags & CLASSIC) 1196 { 1197 if (group != 2) 1198 { 1199 c = T_ID; 1200 break; 1201 } 1202 group++; 1203 } 1204 #endif 1205 ie = ip; 1206 } 1207 else if (paren == 1 && (flags & INDIRECT) && !aie) 1208 aie = ip; 1209 break; 1210 case '*': 1211 if (last == '(' && group == 2) 1212 { 1213 group--; 1214 if (paren == 1) 1215 { 1216 flags |= INDIRECT; 1217 aim = aie = 0; 1218 } 1219 } 1220 break; 1221 case '#': 1222 dir = directive(ip, dir); 1223 if (proto->brace == 0 && paren == 0 && last != '=' && (flags & (CLASSIC|DECLARE|DIRECTIVE|MATCH|PLUSONLY|SKIP|TOKENS)) == (MATCH|TOKENS) && ((dir & DIR) != DIR_en || ((dir>>2) & DIR) != DIR_if)) 1224 flags |= DIRECTIVE; 1225 else if (!(flags & (DECLARE|DIRECTIVE))) 1226 { 1227 flags |= DIRECTIVE; 1228 if (!(flags & PLUSONLY)) 1229 { 1230 bp = ip; 1231 while (*ip == ' ' || *ip == '\t') ip++; 1232 if (*ip == 'l' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e') 1233 { 1234 if (*++ip == ' ' || *ip == '\t') 1235 { 1236 proto->line = 0; 1237 while (*++ip >= '0' && *ip <= '9') 1238 proto->line = proto->line * 10 + *ip - '0'; 1239 proto->line--; 1240 } 1241 } 1242 #if PROTOMAIN 1243 else if ((flags & (CLASSIC|EXTERN)) == CLASSIC) 1244 { 1245 n = 0; 1246 t = ip + 6; 1247 while (ip < t && *ip >= 'a' && *ip <= 'z') 1248 n = HASHKEYPART(n, *ip++); 1249 switch (n) 1250 { 1251 case HASHKEY4('e','l','s','e'): 1252 case HASHKEY5('e','n','d','i','f'): 1253 while (*ip == ' ' || *ip == '\t') ip++; 1254 if (*ip != '\n' && *ip != '/' && *(ip + 1) != '*') 1255 { 1256 flags |= JUNK|MATCH; 1257 im = ip; 1258 om = op + (ip - bp); 1259 } 1260 break; 1261 case HASHKEY4('e','l','i','f'): 1262 case HASHKEY5('e','r','r','o','r'): 1263 case HASHKEY2('i','f'): 1264 case HASHKEY5('i','f','d','e','f'): 1265 case HASHKEY6('i','f','n','d','e','f'): 1266 case HASHKEY5('u','n','d','e','f'): 1267 break; 1268 case HASHKEY6('i','n','c','l','u','d'): 1269 if (*ip == 'e') ip++; 1270 /*FALLTHROUGH*/ 1271 case HASHKEY6('d','e','f','i','n','e'): 1272 case HASHKEY6('p','r','a','g','m','a'): 1273 if (*ip < 'a' || *ip > 'z') break; 1274 /*FALLTHROUGH*/ 1275 default: 1276 flags |= JUNK|MATCH; 1277 im = bp - 1; 1278 om = op - 1; 1279 break; 1280 } 1281 } 1282 else 1283 #endif 1284 { 1285 if (*ip == 'i' && *++ip == 'n' && *++ip == 'c' && *++ip == 'l' && *++ip == 'u' && *++ip == 'd' && *++ip == 'e') 1286 { 1287 while (*++ip == ' ' || *ip == '\t'); 1288 if (*ip++ == '<' && *ip++ == 's' && *ip++ == 't' && *ip++ == 'd' && *ip++ == 'a' && *ip++ == 'r' && *ip++ == 'g' && *ip++ == '.' && *ip++ == 'h' && *ip++ == '>') 1289 { 1290 op = strcopy(op, "\ 1291 if !defined(va_start)\n\ 1292 #if defined(__STDARG__)\n\ 1293 #include <stdarg.h>\n\ 1294 #else\n\ 1295 #include <varargs.h>\n\ 1296 #endif\n\ 1297 #endif\n\ 1298 "); 1299 op = linesync(proto, op, proto->line); 1300 break; 1301 } 1302 } 1303 else if (*ip == 'd' && *++ip == 'e' && *++ ip == 'f' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e' && (*++ip == ' ' || *ip == '\t')) 1304 { 1305 while (*++ip == ' ' || *ip == '\t'); 1306 if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t')) 1307 { 1308 t = ip; 1309 while (*++t == ' ' || *t == '\t'); 1310 if (*t == 'e' && *++t == 'x' && *++ t == 't' && *++t == 'e' && *++t == 'r' && *++t == 'n' && (*++t == ' ' || *t == '\t' || *t == '\n' || *t == '\r')) 1311 ip = t; 1312 t = ip; 1313 while (*++t == ' ' || *t == '\t'); 1314 if (*t == '_' && *(t + 1) == '_') 1315 { 1316 op = strcopy(op, "undef __MANGLE__\n"); 1317 op = linesync(proto, op, proto->line); 1318 op = strcopy(op, "#define __MANGLE__ __LINKAGE__"); 1319 break; 1320 } 1321 } 1322 flags |= DEFINE|MATCH; 1323 im = bp - 1; 1324 om = op - 1; 1325 } 1326 else if (*ip == 'u' && *++ip == 'n' && *++ ip == 'd' && *++ip == 'e' && *++ip == 'f' && (*++ip == ' ' || *ip == '\t')) 1327 { 1328 while (*++ip == ' ' || *ip == '\t'); 1329 if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t' || *ip == '\n' || *ip == '\r')) 1330 { 1331 op = strcopy(op, "undef __MANGLE__\n"); 1332 op = linesync(proto, op, proto->line); 1333 op = strcopy(op, "#define __MANGLE__ __LINKAGE__"); 1334 break; 1335 } 1336 flags |= DEFINE|MATCH; 1337 im = bp - 1; 1338 om = op - 1; 1339 } 1340 } 1341 ip = bp; 1342 } 1343 break; 1344 } 1345 else 1346 break; 1347 /*FALLTHROUGH*/ 1348 case '{': 1349 if (proto->brace++ == 0 && paren == 0) 1350 { 1351 if (last == '=') flags |= INIT; 1352 #if PROTOMAIN 1353 else if (flags & CLASSIC) 1354 { 1355 if ((flags & (MATCH|OTHER|SKIP)) == MATCH) 1356 { 1357 if (args) 1358 { 1359 v = number(op, args < 0 ? -args : args); 1360 v = strcopy(v, " argument actual/formal mismatch"); 1361 *v++ = ' '; 1362 v = memcopy(v, im, ie - im); 1363 *v = 0; 1364 proto_error((char*)proto + sizeof(Proto_t), 2, op, NiL); 1365 } 1366 ip--; 1367 /*UNDENT...*/ 1368 v = ie; 1369 while (ie < ip) 1370 if (*ie++ == '/' && *ie == '*') 1371 { 1372 e = ie - 1; 1373 while (++ie < ip) 1374 { 1375 if (*ie == '*') 1376 { 1377 while (ie < ip && *ie == '*') ie++; 1378 if (ie < ip && *ie == '/') 1379 { 1380 while (++ie < ip && (*ie == ' ' || *ie == '\t')); 1381 while (e > v && (*(e - 1) == ' ' || *(e - 1) == '\t')) e--; 1382 if (e > v && *e != '\n') *e++ = ' '; 1383 t = ie; 1384 while (--e >= v) 1385 *--t = *e; 1386 v = t; 1387 break; 1388 } 1389 } 1390 } 1391 } 1392 ie = v; 1393 /*...INDENT*/ 1394 op = om++; 1395 if (flags & EXTERN) 1396 { 1397 v = op; 1398 while (v > ko && *--v != ' '); 1399 if (*v != ' ') 1400 { 1401 om = (v = (op += 4)) + 1; 1402 while (v >= ko + 4) 1403 { 1404 *v = *(v - 4); 1405 v--; 1406 } 1407 memcopy(ko, "int ", 4); 1408 } 1409 if (*v == ' ') 1410 { 1411 while (*(v + 1) == '*') 1412 *v++ = '*'; 1413 *v = '\t'; 1414 if ((v - ko) <= 8) 1415 { 1416 om = (e = ++op) + 1; 1417 while (e > v) 1418 { 1419 *e = *(e - 1); 1420 e--; 1421 } 1422 } 1423 } 1424 om = (v = (op += 7)) + 1; 1425 while (v >= ko + 7) 1426 { 1427 *v = *(v - 7); 1428 v--; 1429 } 1430 memcopy(ko, "extern ", 7); 1431 } 1432 PUTCHR('('); 1433 t = op; 1434 e = 0; 1435 /*UNDENT...*/ 1436 while (ie < ip) 1437 { 1438 if ((c = *ie) == ' ' || c == '\t' || c == '\n') 1439 { 1440 while ((c = *++ie) == ' ' || c == '\t' || c == '\n'); 1441 if (ie >= ip) break; 1442 if (c != '*' && op > om) PUTCHR(' '); 1443 } 1444 if ((n = ((c = *ie) == ',')) || c == ';') 1445 { 1446 if (flags & EXTERN) 1447 { 1448 m = op; 1449 while (op > om && ((c = *(op - 1)) == '(' || c == ')' || c == '[' || c == ']')) 1450 op--; 1451 v = op; 1452 while (op > om && (c = *(op - 1)) != ' ' && c != '*') 1453 op--; 1454 while (*(op - 1) == ' ') 1455 op--; 1456 if (!e) 1457 { 1458 e = op; 1459 while (e > om && *(e - 1) == '*') 1460 e--; 1461 } 1462 #if _s5r4_386_compiler_bug_fixed_ 1463 if (op <= om || *(op - 1) == ',' && (*op++ = ' ')) 1464 op = strcopy(op, "int"); 1465 #else 1466 if (op <= om) 1467 op = strcopy(op, "int"); 1468 else if (*(op - 1) == ',') 1469 op = strcopy(op, " int"); 1470 #endif 1471 while (v < m) 1472 PUTCHR(*v++); 1473 } 1474 PUTCHR(','); 1475 if (n) 1476 { 1477 if (x = !e) e = op - 1; 1478 PUTCHR(' '); 1479 m = t; 1480 while (m < e) 1481 PUTCHR(*m++); 1482 if (x) 1483 { 1484 m = e; 1485 while (*--e != ' '); 1486 while (*(e - 1) == '*') e--; 1487 op -= m - e; 1488 } 1489 } 1490 while ((c = *++ie) == ' ' || c == '\t' || c == '\n'); 1491 if (ie >= ip) UNPUTCHR(); 1492 else PUTCHR(' '); 1493 if (!n) 1494 { 1495 t = op; 1496 e = 0; 1497 } 1498 } 1499 else if (*ie == '*') 1500 { 1501 if (op > om && (c = *(op - 1)) == ' ') op--; 1502 while (*ie == '*') PUTCHR(*ie++); 1503 while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++; 1504 if (c != '(') PUTCHR(' '); 1505 } 1506 else if (*ie == '(') 1507 { 1508 if (op > om && *(op - 1) == ' ') op--; 1509 PUTCHR(*ie++); 1510 while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++; 1511 } 1512 else if (*ie == ')') 1513 { 1514 if (op > om && *(op - 1) == '(') 1515 proto_error((char*)proto + sizeof(Proto_t), 1, "function pointer argument prototype omitted", NiL); 1516 PUTCHR(*ie++); 1517 while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++; 1518 } 1519 else if ((flags & EXTERN) && (op == om || *(op - 1) == ' ') && *ie == 'r' && !strncmp(ie, "register", 8) && (*(ie + 8) == ' ' || *(ie + 8) == '\t' || *(ie + 8) == '\n')) 1520 { 1521 ie += 8; 1522 if (op > om) UNPUTCHR(); 1523 } 1524 else PUTCHR(*ie++); 1525 } 1526 /*...INDENT*/ 1527 if (op <= om) op = strcopy(op, "void"); 1528 PUTCHR(')'); 1529 if (flags & EXTERN) 1530 { 1531 PUTCHR(';'); 1532 PUTCHR('\n'); 1533 SYNCOUT(); 1534 KEEPOUT(); 1535 } 1536 else 1537 { 1538 PUTCHR('\n'); 1539 PUTCHR(*ip); 1540 } 1541 ip++; 1542 flags &= ~(MATCH|SKIP); 1543 } 1544 } 1545 #endif 1546 else if ((flags & (MATCH|PLUSONLY|SKIP|TOKENS)) == (MATCH|TOKENS)) 1547 { 1548 line = proto->line; 1549 op = strcopy(om, " __PARAM__("); 1550 op = memcopy(op, im, ie - im); 1551 PUTCHR(','); 1552 PUTCHR(' '); 1553 PUTCHR('('); 1554 flags &= ~(MATCH|SKIP); 1555 if (flags & VARIADIC) 1556 { 1557 if ((vc = ie - im + 1) > sizeof(proto->variadic)) vc = sizeof(proto->variadic); 1558 memcopy(proto->variadic, im, vc); 1559 op = strcopy(op, "va_alist)) __OTORP__(va_dcl)\n{"); 1560 } 1561 else 1562 { 1563 flags |= SKIP; 1564 proto->ip = im; 1565 proto->op = op; 1566 group = 0; 1567 brack = 0; 1568 for (;;) 1569 { 1570 switch (lex(proto, (flags & GLOBAL) | RECURSIVE)) 1571 { 1572 case '[': 1573 brack++; 1574 continue; 1575 case ']': 1576 brack--; 1577 continue; 1578 case '(': 1579 if (paren++) group++; 1580 continue; 1581 case ')': 1582 if (--paren == 0) 1583 { 1584 group = 0; 1585 if (flags & MATCH) 1586 { 1587 flags &= ~(MATCH|SKIP); 1588 op = memcopy(op, m, e - m); 1589 } 1590 break; 1591 } 1592 continue; 1593 case ',': 1594 if (paren == 1) 1595 { 1596 group = 0; 1597 if (flags & MATCH) 1598 { 1599 flags &= ~(MATCH|SKIP); 1600 op = memcopy(op, m, e - m); 1601 } 1602 PUTCHR(','); 1603 PUTCHR(' '); 1604 proto->op = op; 1605 } 1606 continue; 1607 case T_ID: 1608 if (group <= 1 && !brack) 1609 { 1610 flags |= MATCH; 1611 m = proto->tp; 1612 e = proto->ip; 1613 } 1614 continue; 1615 default: 1616 continue; 1617 } 1618 break; 1619 } 1620 PUTCHR(')'); 1621 PUTCHR(')'); 1622 } 1623 if (!(flags & SKIP)) 1624 { 1625 flags |= SKIP; 1626 proto->op = strcopy(op, " __OTORP__("); 1627 proto->ip = im + 1; 1628 n = *(ie - 1); 1629 *(ie - 1) = ';'; 1630 c = *ie; 1631 *ie = 0; 1632 lex(proto, (flags & GLOBAL) | DECLARE); 1633 *(ie - 1) = n; 1634 *ie = c; 1635 proto->ip = ie; 1636 op = proto->op; 1637 PUTCHR(')'); 1638 } 1639 if (flags & EXTERNALIZE) memcpy(proto->ox, "extern", 6); 1640 op = linesync(proto, op, proto->line = line); 1641 if (flags & DIRECTIVE) 1642 { 1643 proto->brace = 0; 1644 PUTCHR('\n'); 1645 PUTCHR('#'); 1646 } 1647 else if (!(flags & VARIADIC)) PUTCHR('{'); 1648 } 1649 } 1650 flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP); 1651 call = 0; 1652 group = 0; 1653 break; 1654 case '}': 1655 flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP|TOKENS); 1656 if (--proto->brace == 0) 1657 { 1658 flags &= ~(INIT|VARIADIC|VARIADIC2); 1659 #if PROTOMAIN 1660 if (flags & EXTERN) BACKOUT(); 1661 #endif 1662 } 1663 call = 0; 1664 group = 0; 1665 paren = 0; 1666 break; 1667 case '=': 1668 if (last == '?') flags |= DIRECTIVE; 1669 else if (paren == 0 && (flags & (INIT|MATCH|SKIP)) == MATCH) 1670 { 1671 if (last == ')' && proto->brace && (group != 2 || call != 2)) flags |= SKIP; 1672 else goto fsm_statement; 1673 } 1674 goto fsm_other; 1675 case ',': 1676 #if PROTOMAIN 1677 if (flags & CLASSIC) 1678 { 1679 if (paren == 1) args++; 1680 else 1681 { 1682 args--; 1683 flags &= ~MATCH; 1684 } 1685 break; 1686 } 1687 #endif 1688 if (paren == 0 && (flags & DECLARE)) *(op - 1) = c = ';'; 1689 /*FALLTHROUGH*/ 1690 case ';': 1691 fsm_statement: 1692 if (flags & INIT) /* ignore */; 1693 #if PROTOMAIN 1694 else if (flags & CLASSIC) 1695 { 1696 if (paren == 0) 1697 { 1698 if ((flags & MATCH) && last == ')') 1699 flags &= ~MATCH; 1700 if (!(flags & MATCH)) 1701 { 1702 call = 0; 1703 group = 0; 1704 flags &= ~SKIP; 1705 if (flags & EXTERN) BACKOUT(); 1706 if (flags & SLIDE) 1707 { 1708 SYNC(); 1709 return 0; 1710 } 1711 } 1712 else 1713 { 1714 args--; 1715 if ((flags & (EXTERN|SKIP)) == (EXTERN|SKIP)) 1716 BACKOUT(); 1717 } 1718 } 1719 } 1720 #endif 1721 else if (paren == 0) 1722 { 1723 if ((flags & (MATCH|OTHER|SKIP)) == MATCH && call > 1) 1724 { 1725 if ((flags & MANGLE) && func) 1726 { 1727 func[0] = 'F'; 1728 func[1] = 'U'; 1729 func[2] = 'N'; 1730 func[3] = 'C'; 1731 func = 0; 1732 } 1733 if ((flags & (DECLARE|INDIRECT)) == INDIRECT && aim && aie < im) 1734 { 1735 while (aie < ip && (*aie == ' ' || *aie == '\t' || *aie == '\n')) aie++; 1736 v = aim; 1737 while (v < aie) 1738 if (*v++ == ')') break; 1739 while (v < aie && (*v == ' ' || *v == '\t' || *v == '\n')) v++; 1740 if (v == aie || !(flags & PLUSPLUS)) 1741 { 1742 if (flags & PLUSPLUS) n = 3; 1743 else if (v == aie && *v == '(') n = 10; 1744 else n = 11; 1745 ko = op; 1746 om += n; 1747 v = op += n; 1748 while (v >= ko + n) 1749 { 1750 *v = *(v - n); 1751 v--; 1752 } 1753 if (flags & PLUSPLUS) memcopy(aom, "(...))", 6); 1754 else if (n == 10) memcopy(aom, "(__VARARG__))", 13); 1755 else 1756 { 1757 ko = strcopy(aom, " __PROTO__("); 1758 ko = memcopy(ko, aim, aie - aim); 1759 *ko = ')'; 1760 if (++ko >= om) 1761 { 1762 *ko++ = ')'; 1763 om = ko; 1764 } 1765 } 1766 } 1767 } 1768 else if (flags & TYPEDEF) 1769 { 1770 op = om; 1771 while (*--op == ' ' || *op == '\t' || *op == '\n'); 1772 if (*op != ')') 1773 { 1774 op = om += 14; 1775 *--op = ')'; 1776 while ((x = *(op - 14)) >= 'A' && x <= 'Z' || x >= 'a' && x <= 'z' || x >= '0' && x <= '9' || x == '_') 1777 *--op = x; 1778 memcopy(op - 13, "(__OTORP__(*)", 13); 1779 } 1780 } 1781 if (flags & OTHER) 1782 ; 1783 else if (flags & PLUSPLUS) 1784 { 1785 op = om; 1786 if (!(flags & TOKENS)) op = strcopy(op, "(...)"); 1787 else op = memcopy(op, im, ie - im); 1788 PUTCHR(c); 1789 } 1790 else 1791 { 1792 if (flags & DECLARE) op = strcopy(om, "()"); 1793 else if (!(flags & TOKENS)) op = strcopy(om, "(__VARARG__)"); 1794 else 1795 { 1796 op = strcopy(om, " __PROTO__("); 1797 op = memcopy(op, im, ie - im); 1798 PUTCHR(')'); 1799 } 1800 if (flags & EXTERNALIZE) memcpy(proto->ox, "extern", 6); 1801 PUTCHR(c); 1802 } 1803 flags &= ~(MATCH|VARIADIC|VARIADIC2); 1804 if (c == ',' && !(flags & INDIRECT)) 1805 { 1806 call = 1; 1807 group = 0; 1808 break; 1809 } 1810 } 1811 else if (flags & (OTHER|SKIP)) call = 0; 1812 if (c == ';') 1813 { 1814 flags &= ~(EXTERNALIZE|MANGLE|TOKENS|TYPEDEF); 1815 call = 0; 1816 if (flags & SLIDE) 1817 { 1818 SYNC(); 1819 return 0; 1820 } 1821 } 1822 else call = call > 1 && c == ','; 1823 group = 0; 1824 flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP); 1825 } 1826 else if (paren == 1 && group == 1 && !(flags & (IDID|MANGLE))) flags |= TOKENS|OTHER; 1827 break; 1828 case T_DO: 1829 case T_IF: 1830 flags |= TOKENS|SKIP; 1831 break; 1832 case T_EXTERN: 1833 #if PROTOMAIN 1834 if (flags & CLASSIC) 1835 { 1836 if (proto->brace == 0) 1837 flags |= SKIP; 1838 } 1839 else 1840 #endif 1841 if (paren == 0 && !(flags & TYPEDEF)) 1842 { 1843 flags |= MANGLE; 1844 if (!(flags & PLUSONLY) || proto->package) 1845 { 1846 op = strcopy(op, " __MANGLE__"); 1847 if (proto->package) 1848 { 1849 op = strcopy(op - 1, proto->package); 1850 func = op + 1; 1851 op = strcopy(op, "_DATA__"); 1852 } 1853 } 1854 else 1855 func = 0; 1856 } 1857 break; 1858 case T_VARIADIC: 1859 if (paren == 0 && (flags & (DECLARE|VARIADIC)) == DECLARE) 1860 { 1861 op -= 3; 1862 SYNC(); 1863 return c; 1864 } 1865 if (paren == 1 && !(flags & SKIP)) 1866 flags |= VARIADIC; 1867 flags |= TOKENS; 1868 break; 1869 case T_VOID: 1870 goto fsm_id; 1871 case T_VA_START: 1872 if ((flags & (PLUSONLY|VARIADIC)) == VARIADIC) 1873 { 1874 flags &= ~MATCH; 1875 line = proto->line; 1876 op = strcopy(op - 8, "__VA_START__"); 1877 SYNC(); 1878 for (;;) 1879 { 1880 switch (lex(proto, (flags & GLOBAL) | RECURSIVE)) 1881 { 1882 case 0: 1883 case ';': 1884 break; 1885 case T_ID: 1886 if (!(flags & MATCH)) 1887 { 1888 flags |= MATCH; 1889 m = proto->tp; 1890 e = proto->ip; 1891 } 1892 continue; 1893 default: 1894 continue; 1895 } 1896 break; 1897 } 1898 CACHE(); 1899 if (flags & MATCH) 1900 { 1901 v = m; 1902 n = e - m; 1903 } 1904 else 1905 { 1906 v = "ap"; 1907 n = 2; 1908 } 1909 op = strcopy(op, " __OTORP__("); 1910 proto->ip = proto->variadic; 1911 proto->op = op; 1912 flags &= ~MATCH; 1913 group = 0; 1914 bp = proto->ip + 1; 1915 if (*bp == 'r' && !strncmp(bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9; 1916 for (;;) 1917 { 1918 switch (lex(proto, (flags & GLOBAL) | RECURSIVE)) 1919 { 1920 case '(': 1921 if (paren++) group++; 1922 continue; 1923 case ')': 1924 if (--paren == 0) 1925 { 1926 if (flags & MATCH) 1927 { 1928 flags &= ~MATCH; 1929 if (!(flags & VARIADIC2)) 1930 { 1931 op = memcopy(op, m, e - m); 1932 op = strcopy(op, " = "); 1933 } 1934 op = strcopy(op, "va_arg("); 1935 op = memcopy(op, v, n); 1936 PUTCHR(','); 1937 PUTCHR(' '); 1938 if (m > bp) op = memcopy(op, bp, m - bp); 1939 else op = strcopy(op, "int "); 1940 if (group > 1) op = strcopy(op, ")()"); 1941 else op = memcopy(op, e, proto->ip - e - 1); 1942 PUTCHR(')'); 1943 PUTCHR(';'); 1944 } 1945 group = 0; 1946 break; 1947 } 1948 continue; 1949 case ',': 1950 if (paren == 1) 1951 { 1952 if (flags & MATCH) 1953 { 1954 flags &= ~MATCH; 1955 if (!(flags & VARIADIC2)) 1956 { 1957 op = memcopy(op, m, e - m); 1958 op = strcopy(op, " = "); 1959 } 1960 op = strcopy(op, "va_arg("); 1961 op = memcopy(op, v, n); 1962 PUTCHR(','); 1963 PUTCHR(' '); 1964 if (m > bp) op = memcopy(op, bp, m - bp); 1965 else op = strcopy(op, "int "); 1966 if (group > 1) op = strcopy(op, ")()"); 1967 else op = memcopy(op, e, proto->ip - e - 1); 1968 PUTCHR(')'); 1969 PUTCHR(';'); 1970 bp = proto->ip + 1; 1971 if (*bp == 'r' && !strncmp(bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9; 1972 } 1973 group = 0; 1974 proto->op = op; 1975 } 1976 continue; 1977 case T_ID: 1978 if (group <= 1) 1979 { 1980 flags |= MATCH; 1981 m = proto->tp; 1982 e = proto->ip; 1983 } 1984 continue; 1985 default: 1986 continue; 1987 } 1988 break; 1989 } 1990 op = strcopy(op, ")"); 1991 flags |= VARIADIC2; 1992 proto->line = line; 1993 call = 0; 1994 break; 1995 } 1996 /*FALLTHROUGH*/ 1997 case T_ID: 1998 fsm_id: 1999 #if PROTOMAIN 2000 if (flags & CLASSIC) 2001 { 2002 if (!args && paren == 1) args++; 2003 break; 2004 } 2005 #endif 2006 if (paren == 0) 2007 { 2008 if (last == ')') 2009 { 2010 if (proto->brace == 0 && !(flags & DECLARE)) flags |= SKIP; 2011 call = !call; 2012 } 2013 else if ((flags & SKIP) || c == T_ID || c == T_VOID) call++; 2014 else flags |= SKIP; 2015 if (last == T_ID) flags |= IDID; 2016 } 2017 c = T_ID; 2018 flags |= TOKENS; 2019 break; 2020 case T_INVALID: 2021 if (*proto->tp >= '0' && *proto->tp <= '9') 2022 { 2023 n = 0; 2024 for (;; op--) 2025 { 2026 switch (*(op - 1)) 2027 { 2028 case 'f': 2029 case 'F': 2030 t = op; 2031 while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'); 2032 if (*t == '.') 2033 op--; 2034 n = 0; 2035 break; 2036 case 'l': 2037 case 'L': 2038 if (!(n & 01)) 2039 { 2040 n |= 01; 2041 t = op; 2042 while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'); 2043 if (*t == '.') 2044 { 2045 n = 0; 2046 op--; 2047 break; 2048 } 2049 } 2050 continue; 2051 case 'u': 2052 case 'U': 2053 n |= 02; 2054 continue; 2055 } 2056 break; 2057 } 2058 if (n & 01) 2059 *op++ = 'L'; 2060 if (n & 02) 2061 { 2062 m = op; 2063 t = op = m + 10; 2064 while ((c = *--m) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') 2065 *--t = c; 2066 c = *t; 2067 strcopy(m + 1, "(unsigned)"); 2068 *t = c; 2069 break; 2070 } 2071 } 2072 goto fsm_other; 2073 #if PROTOMAIN 2074 case '[': 2075 if ((flags & CLASSIC) && paren == 0 && group <= 2) flags |= SKIP; 2076 /*FALLTHROUGH*/ 2077 #endif 2078 default: 2079 fsm_other: 2080 #if PROTOMAIN 2081 if (flags & CLASSIC) break; 2082 #endif 2083 flags |= TOKENS; 2084 if (paren == 0) flags |= OTHER; 2085 break; 2086 } 2087 else if (c == '#' && *ip != '(') flags |= SHARP; 2088 last = c; 2089 #if PROTOMAIN 2090 if ((flags & (EXTERN|MATCH)) == (EXTERN|MATCH) && ((flags & (DIRECTIVE|SKIP)) || proto->brace || c != '(' && c != ')' && c != '*' && c != T_ID)) 2091 CACHEOUT(); 2092 else 2093 #endif 2094 SYNCOUT(); 2095 goto fsm_start; 2096 } 2097 else if (flags & (INIT_DEFINE|INIT_INCLUDE)) 2098 { 2099 #if PROTOMAIN 2100 if ((flags & YACC) && c == '%' && *ip == '{') 2101 t = 0; 2102 else 2103 #endif 2104 { 2105 if (c == '#') 2106 { 2107 for (t = ip; *t == ' ' || *t == '\t'; t++); 2108 if (*t++ == 'i' && *t++ == 'f' && *t++ == 'n' && *t++ == 'd' && *t++ == 'e' && *t++ == 'f') 2109 { 2110 #if !PROTOMAIN 2111 while (*t == ' ' || *t == '\t') t++; 2112 if (*t != '_') 2113 #endif 2114 t = 0; 2115 } 2116 } 2117 else 2118 t = ""; 2119 } 2120 if (t) 2121 { 2122 #if PROTOMAIN 2123 n = ip - proto->tp; 2124 ip -= n; 2125 op -= n; 2126 #else 2127 ip = bp; 2128 op = proto->op; 2129 #endif 2130 } 2131 else 2132 while (*ip != '\n') 2133 *op++ = *ip++; 2134 op = init(proto, op, flags); 2135 op = linesync(proto, op, proto->line); 2136 flags &= ~(INIT_DEFINE|INIT_INCLUDE); 2137 proto->flags &= ~(INIT_DEFINE|INIT_INCLUDE); 2138 goto fsm_start; 2139 } 2140 SYNC(); 2141 return c; 2142 } 2143 2144 /* 2145 * close a proto buffer stream 2146 */ 2147 2148 void 2149 pppclose(char* iob) 2150 { 2151 register Proto_t* proto = (Proto_t*)(iob - sizeof(Proto_t)); 2152 2153 if (proto->flags & MORE) close(proto->fd); 2154 free((char*)proto); /* some ANSI cc's botch the free() prototype */ 2155 } 2156 2157 /* 2158 * open a new proto buffer stream 2159 * read buffer pointer returned 2160 * 0 returned on error or if no magic 2161 * 2162 * file !=0 file path to open, otherwise use fd 2163 * fd open file fd if file==0 2164 * notice !=0 copyright notice info commented at the top 2165 * options !=0 additional notice name=value pairs, space or ; separated 2166 * package !=0 generate header for this package 2167 */ 2168 2169 char* 2170 pppopen(char* file, int fd, char* notice, char* options, char* package, char* comment, int flags) 2171 { 2172 register Proto_t* proto; 2173 register char* iob; 2174 register long n; 2175 register char* s; 2176 char* t; 2177 int pragma; 2178 int clr; 2179 int hit; 2180 int i; 2181 int z; 2182 char* b; 2183 #if PROTOMAIN 2184 int comlen; 2185 char com[80]; 2186 #endif 2187 int m = 0; 2188 2189 static int retain; 2190 2191 /* 2192 * initialize proto 2193 */ 2194 2195 #if PROTOMAIN 2196 if (flags & PROTO_CLASSIC) flags &= ~PROTO_INCLUDE; 2197 #endif 2198 if (flags & PROTO_RETAIN) flags &= ~retain; 2199 else retain &= PROTO_INITIALIZED; 2200 if (file && (fd = open(file, O_RDONLY)) < 0) return 0; 2201 #if !PROTOMAIN 2202 if ((n = lseek(fd, 0L, 2)) > 0) 2203 { 2204 if (lseek(fd, 0L, 0)) return 0; 2205 if (n < CHUNK) n = CHUNK; 2206 else if (n > 2 * BLOCK) n = 0; 2207 m = 1; 2208 } 2209 if (n > 0) 2210 { 2211 /* 2212 * file read in one chunk 2213 */ 2214 2215 if (!(proto = newof(0, Proto_t, 1, 4 * n + 2))) 2216 return 0; 2217 proto->iz = n; 2218 proto->oz = 3 * n; 2219 n = 0; 2220 } 2221 else 2222 #endif 2223 { 2224 /* 2225 * file read in BLOCK chunks 2226 */ 2227 2228 n = BLOCK; 2229 if (!(proto = newof(0, Proto_t, 1, 5 * n + 2))) 2230 return 0; 2231 proto->iz = n; 2232 proto->oz = 3 * n; 2233 proto->flags |= MORE; 2234 } 2235 proto->fd = fd; 2236 proto->package = package; 2237 iob = (char*)proto + sizeof(Proto_t); 2238 proto->op = proto->ob = iob; 2239 proto->ip = proto->ib = iob + proto->oz + n; 2240 if (m) proto->options |= REGULAR; 2241 if (!comment) 2242 comment = "/*"; 2243 if (!(proto->cc[0] = comment[0])) 2244 notice = options = 0; 2245 else if (comment[1]) 2246 { 2247 proto->cc[1] = comment[1]; 2248 proto->cc[2] = comment[2] ? comment[2] : comment[0]; 2249 } 2250 else 2251 proto->cc[1] = proto->cc[2] = comment[0]; 2252 2253 /* 2254 * read the first chunk 2255 */ 2256 2257 n = read(fd, proto->ip, proto->iz); 2258 if (!(proto->flags & MORE)) 2259 close(fd); 2260 if (n < 0) 2261 { 2262 pppclose(iob); 2263 return 0; 2264 } 2265 *(proto->ip + n) = 0; 2266 2267 /* 2268 * check for proto pragma in first block of lines 2269 * pragma blanked out if found 2270 * 2271 * -1 no pragma 2272 * 0 #pragma noprototyped 2273 * 1 #pragma prototyped 2274 * 2275 * NOTE: matches may occur inside comments and quotes 2276 */ 2277 2278 #if PROTOMAIN 2279 if (!notice && !options || (comlen = astlicense(com, sizeof(com), NiL, "type=check", proto->cc[0], proto->cc[1], proto->cc[2])) <= 0) 2280 *com = 0; 2281 #endif 2282 hit = (notice || options) ? 0 : HIT_noticed; 2283 pragma = -1; 2284 s = proto->ip; 2285 m = MAGICTOP; 2286 while (m-- > 0 && *s && hit != (HIT_prototyped|HIT_noticed)) 2287 { 2288 while (*s == ' ' || *s == '\t') 2289 s++; 2290 if (*s == '#') 2291 { 2292 b = s++; 2293 while (*s == ' ' || *s == '\t') 2294 s++; 2295 if (*s == *PRAGMADIR && !strncmp(s, PRAGMADIR, sizeof(PRAGMADIR) - 1) && (*(s += sizeof(PRAGMADIR) - 1) == ' ' || *s == '\t')) 2296 { 2297 clr = 0; 2298 while (*s && *s != '\r' && *s != '\n') 2299 { 2300 for (; *s == ' ' || *s == '\t'; s++); 2301 for (t = s; *s && *s != ' ' && *s != '\t' && *s != '\r' && *s != '\n'; s++); 2302 z = s - t; 2303 for (i = 0; i < elementsof(pragmas); i++) 2304 if (pragmas[i].size == z && !strncmp(t, pragmas[i].name, z)) 2305 { 2306 clr = 1; 2307 hit |= pragmas[i].hit; 2308 switch (pragmas[i].hit) 2309 { 2310 case HIT_noticed: 2311 notice = options = 0; 2312 break; 2313 case HIT_prototyped: 2314 pragma = pragmas[i].val; 2315 break; 2316 } 2317 } 2318 } 2319 if (clr) 2320 { 2321 #if PROTOMAIN 2322 if (!(flags & PROTO_DISABLE) || (flags & PROTO_NOPRAGMA)) 2323 #endif 2324 for (; b < s; *b++ = ' '); 2325 } 2326 } 2327 } 2328 else if (*s == *GENERATED && !strncmp(s, GENERATED, sizeof(GENERATED) - 1)) 2329 { 2330 pragma = 0; 2331 break; 2332 } 2333 #if PROTOMAIN 2334 else if (*s == '%' && *(s + 1) == '{') 2335 proto->flags |= YACC; 2336 else if (!(hit & HIT_noticed)) 2337 { 2338 if (*s == *com && !strncmp(s, com, comlen)) 2339 { 2340 hit |= HIT_noticed; 2341 notice = options = 0; 2342 } 2343 else 2344 for (; *s && *s != '\n' && !(hit & HIT_noticed); s++) 2345 for (i = 0; i < elementsof(notices); i++) 2346 if (*s == notices[i].name[0] && !strncmp(s, notices[i].name, notices[i].size)) 2347 { 2348 s += notices[i].size; 2349 if (notices[i].val) 2350 { 2351 while (*s == ' ' || *s == '\t') 2352 s++; 2353 if (*s == '(' && (*(s + 1) == 'c' || *(s + 1) == 'C') && *(s + 2) == ')' || *s >= '0' && *s <= '9' && *(s + 1) >= '0' && *(s + 1) <= '9') 2354 { 2355 hit |= notices[i].hit; 2356 notice = options = 0; 2357 } 2358 } 2359 else 2360 { 2361 hit |= notices[i].hit; 2362 notice = options = 0; 2363 } 2364 break; 2365 } 2366 } 2367 #endif 2368 while (*s && *s++ != '\n'); 2369 } 2370 if (flags & PROTO_PLUSPLUS) proto->flags |= PLUSPLUS; 2371 if (flags & PROTO_TEST) proto->test = 1; 2372 if (flags & PROTO_EXTERNALIZE) proto->options |= EXTERNALIZE; 2373 #if PROTOMAIN 2374 if (flags & PROTO_CLASSIC) pragma = -pragma; 2375 if (flags & PROTO_DISABLE) pragma = 0; 2376 if (flags & PROTO_LINESYNC) proto->flags |= LINESYNC; 2377 if (!(proto->flags & YACC) && file && (m = strlen(file)) > 2 && file[--m] == 'y' && file[--m] == '.') 2378 proto->flags |= YACC; 2379 #endif 2380 if (pragma <= 0) 2381 { 2382 if (flags & PROTO_PLUSPLUS) 2383 { 2384 flags &= ~(PROTO_HEADER|PROTO_INCLUDE); 2385 proto->flags |= PLUSONLY; 2386 } 2387 else if (!(flags & (PROTO_FORCE|PROTO_PASS))) 2388 { 2389 pppclose(iob); 2390 return 0; 2391 } 2392 else if ((flags & (PROTO_FORCE|PROTO_PASS)) == PROTO_PASS || !pragma) 2393 { 2394 proto->flags |= PASS; 2395 if (proto->flags & MORE) 2396 proto->oz += proto->iz; 2397 proto->iz = n; 2398 if (notice || options) 2399 { 2400 if (proto->cc[0] == '#' && proto->ip[0] == '#' && proto->ip[1] == '!') 2401 { 2402 s = proto->ip; 2403 while (*s && *s++ != '\n'); 2404 m = s - proto->ip; 2405 proto->op = memcopy(proto->op, proto->ip, m); 2406 proto->ip = s; 2407 proto->iz = n -= m; 2408 } 2409 #if PROTOMAIN 2410 if (proto->cc[0]) 2411 { 2412 if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0) 2413 proto_error((char*)proto + sizeof(Proto_t), 1, proto->op, NiL); 2414 else 2415 proto->op += comlen; 2416 } 2417 if (!(flags & PROTO_CLASSIC) && !(proto->flags & YACC)) 2418 #endif 2419 proto->op = linesync(proto, proto->op, 1); 2420 proto->iz += proto->op - proto->ob; 2421 } 2422 memcopy(proto->op, proto->ip, n); 2423 return iob; 2424 } 2425 } 2426 #if PROTOMAIN 2427 if (!(retain & PROTO_INITIALIZED)) 2428 { 2429 retain |= PROTO_INITIALIZED; 2430 ppfsm(FSM_INIT, NiL); 2431 } 2432 #endif 2433 proto->line = 1; 2434 #if CHUNK >= 512 2435 if (notice || options || (flags & (PROTO_HEADER|PROTO_INCLUDE))) 2436 { 2437 #if PROTOMAIN 2438 if (notice || options) 2439 { 2440 if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0) 2441 proto_error((char*)proto + sizeof(Proto_t), 1, proto->op, NiL); 2442 else 2443 proto->op += comlen; 2444 } 2445 #endif 2446 if (flags & PROTO_INCLUDE) 2447 { 2448 proto->flags |= INIT_INCLUDE; 2449 if (flags & PROTO_RETAIN) 2450 retain |= PROTO_INCLUDE; 2451 } 2452 else if (flags & PROTO_HEADER) 2453 { 2454 if (flags & PROTO_RETAIN) retain |= PROTO_HEADER; 2455 #if PROTOMAIN 2456 if (flags & PROTO_CLASSIC) 2457 { 2458 *proto->op++ = '#'; 2459 proto->op = strcopy(proto->op, PRAGMADIR); 2460 *proto->op++ = ' '; 2461 proto->op = strcopy(proto->op, pragmas[0].name); 2462 *proto->op++ = '\n'; 2463 } 2464 else 2465 #endif 2466 proto->flags |= INIT_DEFINE; 2467 } 2468 #if PROTOMAIN 2469 if (!(flags & PROTO_CLASSIC)) 2470 { 2471 if (proto->flags & YACC) 2472 { 2473 proto->op = strcopy(proto->op, "\n%{\n" + !notice); 2474 proto->op = strcopy(proto->op, GENERATED); 2475 proto->op = strcopy(proto->op, "%}\n"); 2476 } 2477 else 2478 { 2479 if (n || notice || options) 2480 *proto->op++ = '\n'; 2481 proto->op = strcopy(proto->op, GENERATED); 2482 if (n) 2483 proto->op = linesync(proto, proto->op, proto->line); 2484 else if (proto->flags & (INIT_DEFINE|INIT_INCLUDE)) 2485 proto->op = init(proto, proto->op, proto->flags); 2486 } 2487 } 2488 #endif 2489 } 2490 #endif 2491 #if PROTOMAIN 2492 proto->file = file; 2493 if (flags & PROTO_CLASSIC) 2494 { 2495 proto->flags |= CLASSIC; 2496 if (!(flags & PROTO_HEADER)) proto->flags |= EXTERN; 2497 } 2498 #endif 2499 return iob; 2500 } 2501 2502 /* 2503 * read next proto'd chunk into iob 2504 * the chunk is 0 terminated and its size is returned 2505 */ 2506 2507 int 2508 pppread(char* iob) 2509 { 2510 register Proto_t* proto = (Proto_t*)(iob - sizeof(Proto_t)); 2511 register int n; 2512 2513 if (proto->flags & PASS) 2514 { 2515 if (proto->iz) 2516 { 2517 n = proto->iz; 2518 proto->iz = 0; 2519 } 2520 else if (!(proto->flags & MORE)) n = 0; 2521 else if ((n = read(proto->fd, proto->ob, proto->oz)) <= 0 || (proto->options & REGULAR) && n < proto->oz) 2522 { 2523 proto->flags &= ~MORE; 2524 close(proto->fd); 2525 } 2526 } 2527 else 2528 { 2529 if (proto->op == proto->ob) 2530 { 2531 if (proto->flags & ERROR) return -1; 2532 #if PROTOMAIN 2533 if (proto->flags & YACC) 2534 { 2535 register char* ip = proto->ip; 2536 register char* op = proto->ob; 2537 register char* ep = proto->ob + proto->oz - 2; 2538 2539 if (!*ip) 2540 { 2541 ip = proto->ip = proto->ib; 2542 if (!(proto->flags & MORE)) n = 0; 2543 else if ((n = read(proto->fd, ip, proto->iz)) <= 0 || (proto->options & REGULAR) && n < proto->iz) 2544 { 2545 if (n < 0) n = 0; 2546 proto->flags &= ~MORE; 2547 close(proto->fd); 2548 } 2549 ip[n] = 0; 2550 } 2551 if (proto->flags & YACCSPLIT) 2552 { 2553 proto->flags &= ~YACCSPLIT; 2554 if (*ip == '%') 2555 { 2556 *op++ = *ip++; 2557 if (proto->flags & YACC2) proto->flags &= ~YACC; 2558 else proto->flags |= YACC2; 2559 } 2560 } 2561 if (proto->flags & YACC) 2562 while (op < ep && (n = *op++ = *ip)) 2563 { 2564 ip++; 2565 if (n == '%') 2566 { 2567 if (*ip == '%' && (ip == proto->ip + 1 || *(ip - 2) == '\n')) 2568 { 2569 *op++ = *ip++; 2570 if (proto->flags & YACC2) proto->flags &= ~YACC; 2571 else proto->flags |= YACC2; 2572 break; 2573 } 2574 if (!*ip) 2575 { 2576 *op++ = '%'; 2577 proto->flags |= YACCSPLIT; 2578 break; 2579 } 2580 } 2581 else if (n == '\n') proto->line++; 2582 } 2583 proto->op = memcopy(proto->ob, proto->ip, ip - proto->ip); 2584 proto->ip = ip; 2585 } 2586 else 2587 #endif 2588 lex(proto, proto->flags); 2589 if ((proto->flags & (ERROR|MORE)) == ERROR) 2590 proto->op = strcopy(proto->op, "/* NOTE: some constructs may not have been converted */\n"); 2591 } 2592 n = proto->op - proto->ob; 2593 proto->op = proto->ob; 2594 } 2595 return n; 2596 } 2597 2598 #if !PROTOMAIN 2599 2600 /* 2601 * drop control of iob after first pppread() 2602 * return value is input fd 2603 * if fd<0 then all data in iob 2604 */ 2605 2606 int 2607 pppdrop(char* iob) 2608 { 2609 register Proto_t* proto = (Proto_t*)(iob - sizeof(Proto_t)); 2610 2611 if (proto->flags & MORE) 2612 { 2613 proto->flags &= ~MORE; 2614 return proto->fd; 2615 } 2616 return -1; 2617 } 2618 2619 #endif 2620