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