1: #ifndef lint 2: static char sccsid[] = "@(#)y2.c 4.1 (Berkeley) 2/11/83"; 3: #endif not lint 4: 5: # include "dextern" 6: # define IDENTIFIER 257 7: # define MARK 258 8: # define TERM 259 9: # define LEFT 260 10: # define RIGHT 261 11: # define BINARY 262 12: # define PREC 263 13: # define LCURLY 264 14: # define C_IDENTIFIER 265 /* name followed by colon */ 15: # define NUMBER 266 16: # define START 267 17: # define TYPEDEF 268 18: # define TYPENAME 269 19: # define UNION 270 20: # define ENDFILE 0 21: 22: /* communication variables between various I/O routines */ 23: 24: char *infile; /* input file name */ 25: int numbval; /* value of an input number */ 26: char tokname[NAMESIZE]; /* input token name */ 27: 28: /* storage of names */ 29: 30: char cnames[CNAMSZ]; /* place where token and nonterminal names are stored */ 31: int cnamsz = CNAMSZ; /* size of cnames */ 32: char * cnamp = cnames; /* place where next name is to be put in */ 33: int ndefout = 3; /* number of defined symbols output */ 34: 35: /* storage of types */ 36: int ntypes; /* number of types defined */ 37: char * typeset[NTYPES]; /* pointers to type tags */ 38: 39: /* symbol tables for tokens and nonterminals */ 40: 41: int ntokens = 0; 42: struct toksymb tokset[NTERMS]; 43: int toklev[NTERMS]; 44: int nnonter = -1; 45: struct ntsymb nontrst[NNONTERM]; 46: int start; /* start symbol */ 47: 48: /* assigned token type values */ 49: int extval = 0; 50: 51: /* input and output file descriptors */ 52: 53: FILE * finput; /* yacc input file */ 54: FILE * faction; /* file for saving actions */ 55: FILE * fdefine; /* file for # defines */ 56: FILE * ftable; /* y.tab.c file */ 57: FILE * ftemp; /* tempfile to pass 2 */ 58: FILE * foutput; /* y.output file */ 59: 60: /* storage for grammar rules */ 61: 62: int mem0[MEMSIZE] ; /* production storage */ 63: int *mem = mem0; 64: int nprod= 1; /* number of productions */ 65: int *prdptr[NPROD]; /* pointers to descriptions of productions */ 66: int levprd[NPROD] ; /* precedence levels for the productions */ 67: 68: 69: setup(argc,argv) int argc; char *argv[]; 70: { int i,j,lev,t, ty; 71: int c; 72: int *p; 73: char actname[8]; 74: 75: foutput = NULL; 76: fdefine = NULL; 77: i = 1; 78: while( argc >= 2 && argv[1][0] == '-' ) { 79: while( *++(argv[1]) ){ 80: switch( *argv[1] ){ 81: case 'v': 82: case 'V': 83: foutput = fopen(FILEU, "w" ); 84: if( foutput == NULL ) error( "cannot open y.output" ); 85: continue; 86: case 'D': 87: case 'd': 88: fdefine = fopen( FILED, "w" ); 89: continue; 90: case 'o': 91: case 'O': 92: fprintf( stderr, "`o' flag now default in yacc\n" ); 93: continue; 94: 95: case 'r': 96: case 'R': 97: error( "Ratfor Yacc is dead: sorry...\n" ); 98: 99: default: 100: error( "illegal option: %c", *argv[1]); 101: } 102: } 103: argv++; 104: argc--; 105: } 106: 107: ftable = fopen( OFILE, "w" ); 108: if( ftable == NULL ) error( "cannot open table file" ); 109: 110: ftemp = fopen( TEMPNAME, "w" ); 111: faction = fopen( ACTNAME, "w" ); 112: if( ftemp==NULL || faction==NULL ) error( "cannot open temp file" ); 113: 114: if( argc < 2 || ((finput=fopen( infile=argv[1], "r" )) == NULL ) ){ 115: error( "cannot open input file" ); 116: } 117: 118: cnamp = cnames; 119: defin(0,"$end"); 120: extval = 0400; 121: defin(0,"error"); 122: defin(1,"$accept"); 123: mem=mem0; 124: lev = 0; 125: ty = 0; 126: i=0; 127: 128: /* sorry -- no yacc parser here..... 129: we must bootstrap somehow... */ 130: 131: for( t=gettok(); t!=MARK && t!= ENDFILE; ){ 132: switch( t ){ 133: 134: case ';': 135: t = gettok(); 136: break; 137: 138: case START: 139: if( (t=gettok()) != IDENTIFIER ){ 140: error( "bad %%start construction" ); 141: } 142: start = chfind(1,tokname); 143: t = gettok(); 144: continue; 145: 146: case TYPEDEF: 147: if( (t=gettok()) != TYPENAME ) error( "bad syntax in %%type" ); 148: ty = numbval; 149: for(;;){ 150: t = gettok(); 151: switch( t ){ 152: 153: case IDENTIFIER: 154: if( (t=chfind( 1, tokname ) ) < NTBASE ) { 155: j = TYPE( toklev[t] ); 156: if( j!= 0 && j != ty ){ 157: error( "type redeclaration of token %s", 158: tokset[t].name ); 159: } 160: else SETTYPE( toklev[t],ty); 161: } 162: else { 163: j = nontrst[t-NTBASE].tvalue; 164: if( j != 0 && j != ty ){ 165: error( "type redeclaration of nonterminal %s", 166: nontrst[t-NTBASE].name ); 167: } 168: else nontrst[t-NTBASE].tvalue = ty; 169: } 170: case ',': 171: continue; 172: 173: case ';': 174: t = gettok(); 175: break; 176: default: 177: break; 178: } 179: break; 180: } 181: continue; 182: 183: case UNION: 184: /* copy the union declaration to the output */ 185: cpyunion(); 186: t = gettok(); 187: continue; 188: 189: case LEFT: 190: case BINARY: 191: case RIGHT: 192: ++i; 193: case TERM: 194: lev = t-TERM; /* nonzero means new prec. and assoc. */ 195: ty = 0; 196: 197: /* get identifiers so defined */ 198: 199: t = gettok(); 200: if( t == TYPENAME ){ /* there is a type defined */ 201: ty = numbval; 202: t = gettok(); 203: } 204: 205: for(;;) { 206: switch( t ){ 207: 208: case ',': 209: t = gettok(); 210: continue; 211: 212: case ';': 213: break; 214: 215: case IDENTIFIER: 216: j = chfind(0,tokname); 217: if( lev ){ 218: if( ASSOC(toklev[j]) ) error( "redeclaration of precedence of %s", tokname ); 219: SETASC(toklev[j],lev); 220: SETPLEV(toklev[j],i); 221: } 222: if( ty ){ 223: if( TYPE(toklev[j]) ) error( "redeclaration of type of %s", tokname ); 224: SETTYPE(toklev[j],ty); 225: } 226: if( (t=gettok()) == NUMBER ){ 227: tokset[j].value = numbval; 228: if( j < ndefout && j>2 ){ 229: error( "please define type number of %s earlier", 230: tokset[j].name ); 231: } 232: t=gettok(); 233: } 234: continue; 235: 236: } 237: 238: break; 239: } 240: 241: continue; 242: 243: case LCURLY: 244: defout(); 245: cpycode(); 246: t = gettok(); 247: continue; 248: 249: default: 250: error( "syntax error" ); 251: 252: } 253: 254: } 255: 256: if( t == ENDFILE ){ 257: error( "unexpected EOF before %%" ); 258: } 259: 260: /* t is MARK */ 261: 262: defout(); 263: 264: fprintf( ftable, "#define yyclearin yychar = -1\n" ); 265: fprintf( ftable, "#define yyerrok yyerrflag = 0\n" ); 266: fprintf( ftable, "extern int yychar;\nextern short yyerrflag;\n" ); 267: fprintf( ftable, "#ifndef YYMAXDEPTH\n#define YYMAXDEPTH 150\n#endif\n" ); 268: if( !ntypes ) fprintf( ftable, "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n" ); 269: fprintf( ftable, "YYSTYPE yylval, yyval;\n" ); 270: 271: prdptr[0]=mem; 272: /* added production */ 273: *mem++ = NTBASE; 274: *mem++ = start; /* if start is 0, we will overwrite with the lhs of the first rule */ 275: *mem++ = 1; 276: *mem++ = 0; 277: prdptr[1]=mem; 278: 279: while( (t=gettok()) == LCURLY ) cpycode(); 280: 281: if( t != C_IDENTIFIER ) error( "bad syntax on first rule" ); 282: 283: if( !start ) prdptr[0][1] = chfind(1,tokname); 284: 285: /* read rules */ 286: 287: while( t!=MARK && t!=ENDFILE ){ 288: 289: /* process a rule */ 290: 291: if( t == '|' ){ 292: *mem++ = *prdptr[nprod-1]; 293: } 294: else if( t == C_IDENTIFIER ){ 295: *mem = chfind(1,tokname); 296: if( *mem < NTBASE ) error( "token illegal on LHS of grammar rule" ); 297: ++mem; 298: } 299: else error( "illegal rule: missing semicolon or | ?" ); 300: 301: /* read rule body */ 302: 303: 304: t = gettok(); 305: more_rule: 306: while( t == IDENTIFIER ) { 307: *mem = chfind(1,tokname); 308: if( *mem<NTBASE ) levprd[nprod] = toklev[*mem]; 309: ++mem; 310: t = gettok(); 311: } 312: 313: 314: if( t == PREC ){ 315: if( gettok()!=IDENTIFIER) error( "illegal %%prec syntax" ); 316: j = chfind(2,tokname); 317: if( j>=NTBASE)error("nonterminal %s illegal after %%prec", nontrst[j-NTBASE].name); 318: levprd[nprod]=toklev[j]; 319: t = gettok(); 320: } 321: 322: if( t == '=' ){ 323: levprd[nprod] |= ACTFLAG; 324: fprintf( faction, "\ncase %d:", nprod ); 325: cpyact( mem-prdptr[nprod]-1 ); 326: fprintf( faction, " break;" ); 327: if( (t=gettok()) == IDENTIFIER ){ 328: /* action within rule... */ 329: 330: sprintf( actname, "$$%d", nprod ); 331: j = chfind(1,actname); /* make it a nonterminal */ 332: 333: /* the current rule will become rule number nprod+1 */ 334: /* move the contents down, and make room for the null */ 335: 336: for( p=mem; p>=prdptr[nprod]; --p ) p[2] = *p; 337: mem += 2; 338: 339: /* enter null production for action */ 340: 341: p = prdptr[nprod]; 342: 343: *p++ = j; 344: *p++ = -nprod; 345: 346: /* update the production information */ 347: 348: levprd[nprod+1] = levprd[nprod] & ~ACTFLAG; 349: levprd[nprod] = ACTFLAG; 350: 351: if( ++nprod >= NPROD ) error( "more than %d rules", NPROD ); 352: prdptr[nprod] = p; 353: 354: /* make the action appear in the original rule */ 355: *mem++ = j; 356: 357: /* get some more of the rule */ 358: 359: goto more_rule; 360: } 361: 362: } 363: 364: while( t == ';' ) t = gettok(); 365: 366: *mem++ = -nprod; 367: 368: /* check that default action is reasonable */ 369: 370: if( ntypes && !(levprd[nprod]&ACTFLAG) && nontrst[*prdptr[nprod]-NTBASE].tvalue ){ 371: /* no explicit action, LHS has value */ 372: register tempty; 373: tempty = prdptr[nprod][1]; 374: if( tempty < 0 ) error( "must return a value, since LHS has a type" ); 375: else if( tempty >= NTBASE ) tempty = nontrst[tempty-NTBASE].tvalue; 376: else tempty = TYPE( toklev[tempty] ); 377: if( tempty != nontrst[*prdptr[nprod]-NTBASE].tvalue ){ 378: error( "default action causes potential type clash" ); 379: } 380: } 381: 382: if( ++nprod >= NPROD ) error( "more than %d rules", NPROD ); 383: prdptr[nprod] = mem; 384: levprd[nprod]=0; 385: 386: } 387: 388: /* end of all rules */ 389: 390: finact(); 391: if( t == MARK ){ 392: fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile ); 393: while( (c=getc(finput)) != EOF ) putc( c, ftable ); 394: } 395: fclose( finput ); 396: } 397: 398: finact(){ 399: /* finish action routine */ 400: 401: fclose(faction); 402: 403: fprintf( ftable, "# define YYERRCODE %d\n", tokset[2].value ); 404: 405: } 406: 407: defin( t, s ) register char *s; { 408: /* define s to be a terminal if t=0 409: or a nonterminal if t=1 */ 410: 411: register val; 412: 413: if (t) { 414: if( ++nnonter >= NNONTERM ) error("too many nonterminals, limit %d",NNONTERM); 415: nontrst[nnonter].name = cstash(s); 416: return( NTBASE + nnonter ); 417: } 418: /* must be a token */ 419: if( ++ntokens >= NTERMS ) error("too many terminals, limit %d",NTERMS ); 420: tokset[ntokens].name = cstash(s); 421: 422: /* establish value for token */ 423: 424: if( s[0]==' ' && s[2]=='\0' ) /* single character literal */ 425: val = s[1]; 426: else if ( s[0]==' ' && s[1]=='\\' ) { /* escape sequence */ 427: if( s[3] == '\0' ){ /* single character escape sequence */ 428: switch ( s[2] ){ 429: /* character which is escaped */ 430: case 'n': val = '\n'; break; 431: case 'r': val = '\r'; break; 432: case 'b': val = '\b'; break; 433: case 't': val = '\t'; break; 434: case 'f': val = '\f'; break; 435: case '\'': val = '\''; break; 436: case '"': val = '"'; break; 437: case '\\': val = '\\'; break; 438: default: error( "invalid escape" ); 439: } 440: } 441: else if( s[2] <= '7' && s[2]>='0' ){ /* \nnn sequence */ 442: if( s[3]<'0' || s[3] > '7' || s[4]<'0' || 443: s[4]>'7' || s[5] != '\0' ) error("illegal \\nnn construction" ); 444: val = 64*s[2] + 8*s[3] + s[4] - 73*'0'; 445: if( val == 0 ) error( "'\\000' is illegal" ); 446: } 447: } 448: else { 449: val = extval++; 450: } 451: tokset[ntokens].value = val; 452: toklev[ntokens] = 0; 453: return( ntokens ); 454: } 455: 456: defout(){ /* write out the defines (at the end of the declaration section) */ 457: 458: register int i, c; 459: register char *cp; 460: 461: for( i=ndefout; i<=ntokens; ++i ){ 462: 463: cp = tokset[i].name; 464: if( *cp == ' ' ) ++cp; /* literals */ 465: 466: for( ; (c= *cp)!='\0'; ++cp ){ 467: 468: if( islower(c) || isupper(c) || isdigit(c) || c=='_' ); /* VOID */ 469: else goto nodef; 470: } 471: 472: fprintf( ftable, "# define %s %d\n", tokset[i].name, tokset[i].value ); 473: if( fdefine != NULL ) fprintf( fdefine, "# define %s %d\n", tokset[i].name, tokset[i].value ); 474: 475: nodef: ; 476: } 477: 478: ndefout = ntokens+1; 479: 480: } 481: 482: char * 483: cstash( s ) register char *s; { 484: char *temp; 485: 486: temp = cnamp; 487: do { 488: if( cnamp >= &cnames[cnamsz] ) error("too many characters in id's and literals" ); 489: else *cnamp++ = *s; 490: } while ( *s++ ); 491: return( temp ); 492: } 493: 494: gettok() { 495: register i, base; 496: static int peekline; /* number of '\n' seen in lookahead */ 497: register c, match, reserve; 498: 499: begin: 500: reserve = 0; 501: lineno += peekline; 502: peekline = 0; 503: c = getc(finput); 504: while( c==' ' || c=='\n' || c=='\t' || c=='\f' ){ 505: if( c == '\n' ) ++lineno; 506: c=getc(finput); 507: } 508: if( c == '/' ){ /* skip comment */ 509: lineno += skipcom(); 510: goto begin; 511: } 512: 513: switch(c){ 514: 515: case EOF: 516: return(ENDFILE); 517: case '{': 518: ungetc( c, finput ); 519: return( '=' ); /* action ... */ 520: case '<': /* get, and look up, a type name (union member name) */ 521: i = 0; 522: while( (c=getc(finput)) != '>' && c>=0 && c!= '\n' ){ 523: tokname[i] = c; 524: if( ++i >= NAMESIZE ) --i; 525: } 526: if( c != '>' ) error( "unterminated < ... > clause" ); 527: tokname[i] = '\0'; 528: for( i=1; i<=ntypes; ++i ){ 529: if( !strcmp( typeset[i], tokname ) ){ 530: numbval = i; 531: return( TYPENAME ); 532: } 533: } 534: typeset[numbval = ++ntypes] = cstash( tokname ); 535: return( TYPENAME ); 536: 537: case '"': 538: case '\'': 539: match = c; 540: tokname[0] = ' '; 541: i = 1; 542: for(;;){ 543: c = getc(finput); 544: if( c == '\n' || c == EOF ) 545: error("illegal or missing ' or \"" ); 546: if( c == '\\' ){ 547: c = getc(finput); 548: tokname[i] = '\\'; 549: if( ++i >= NAMESIZE ) --i; 550: } 551: else if( c == match ) break; 552: tokname[i] = c; 553: if( ++i >= NAMESIZE ) --i; 554: } 555: break; 556: 557: case '%': 558: case '\\': 559: 560: switch(c=getc(finput)) { 561: 562: case '0': return(TERM); 563: case '<': return(LEFT); 564: case '2': return(BINARY); 565: case '>': return(RIGHT); 566: case '%': 567: case '\\': return(MARK); 568: case '=': return(PREC); 569: case '{': return(LCURLY); 570: default: reserve = 1; 571: } 572: 573: default: 574: 575: if( isdigit(c) ){ /* number */ 576: numbval = c-'0' ; 577: base = (c=='0') ? 8 : 10 ; 578: for( c=getc(finput); isdigit(c) ; c=getc(finput) ){ 579: numbval = numbval*base + c - '0'; 580: } 581: ungetc( c, finput ); 582: return(NUMBER); 583: } 584: else if( islower(c) || isupper(c) || c=='_' || c=='.' || c=='$' ){ 585: i = 0; 586: while( islower(c) || isupper(c) || isdigit(c) || c=='_' || c=='.' || c=='$' ){ 587: tokname[i] = c; 588: if( reserve && isupper(c) ) tokname[i] += 'a'-'A'; 589: if( ++i >= NAMESIZE ) --i; 590: c = getc(finput); 591: } 592: } 593: else return(c); 594: 595: ungetc( c, finput ); 596: } 597: 598: tokname[i] = '\0'; 599: 600: if( reserve ){ /* find a reserved word */ 601: if( !strcmp(tokname,"term")) return( TERM ); 602: if( !strcmp(tokname,"token")) return( TERM ); 603: if( !strcmp(tokname,"left")) return( LEFT ); 604: if( !strcmp(tokname,"nonassoc")) return( BINARY ); 605: if( !strcmp(tokname,"binary")) return( BINARY ); 606: if( !strcmp(tokname,"right")) return( RIGHT ); 607: if( !strcmp(tokname,"prec")) return( PREC ); 608: if( !strcmp(tokname,"start")) return( START ); 609: if( !strcmp(tokname,"type")) return( TYPEDEF ); 610: if( !strcmp(tokname,"union")) return( UNION ); 611: error("invalid escape, or illegal reserved word: %s", tokname ); 612: } 613: 614: /* look ahead to distinguish IDENTIFIER from C_IDENTIFIER */ 615: 616: c = getc(finput); 617: while( c==' ' || c=='\t'|| c=='\n' || c=='\f' || c== '/' ) { 618: if( c == '\n' ) ++peekline; 619: else if( c == '/' ){ /* look for comments */ 620: peekline += skipcom(); 621: } 622: c = getc(finput); 623: } 624: if( c == ':' ) return( C_IDENTIFIER ); 625: ungetc( c, finput ); 626: return( IDENTIFIER ); 627: } 628: 629: fdtype( t ){ /* determine the type of a symbol */ 630: register v; 631: if( t >= NTBASE ) v = nontrst[t-NTBASE].tvalue; 632: else v = TYPE( toklev[t] ); 633: if( v <= 0 ) error( "must specify type for %s", (t>=NTBASE)?nontrst[t-NTBASE].name: 634: tokset[t].name ); 635: return( v ); 636: } 637: 638: chfind( t, s ) register char *s; { 639: int i; 640: 641: if (s[0]==' ')t=0; 642: TLOOP(i){ 643: if(!strcmp(s,tokset[i].name)){ 644: return( i ); 645: } 646: } 647: NTLOOP(i){ 648: if(!strcmp(s,nontrst[i].name)) { 649: return( i+NTBASE ); 650: } 651: } 652: /* cannot find name */ 653: if( t>1 ) 654: error( "%s should have been defined earlier", s ); 655: return( defin( t, s ) ); 656: } 657: 658: cpyunion(){ 659: /* copy the union declaration to the output, and the define file if present */ 660: 661: int level, c; 662: fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile ); 663: fprintf( ftable, "typedef union " ); 664: if( fdefine ) fprintf( fdefine, "\ntypedef union " ); 665: 666: level = 0; 667: for(;;){ 668: if( (c=getc(finput)) < 0 ) error( "EOF encountered while processing %%union" ); 669: putc( c, ftable ); 670: if( fdefine ) putc( c, fdefine ); 671: 672: switch( c ){ 673: 674: case '\n': 675: ++lineno; 676: break; 677: 678: case '{': 679: ++level; 680: break; 681: 682: case '}': 683: --level; 684: if( level == 0 ) { /* we are finished copying */ 685: fprintf( ftable, " YYSTYPE;\n" ); 686: if( fdefine ) fprintf( fdefine, " YYSTYPE;\nextern YYSTYPE yylval;\n" ); 687: return; 688: } 689: } 690: } 691: } 692: 693: cpycode(){ /* copies code between \{ and \} */ 694: 695: int c; 696: c = getc(finput); 697: if( c == '\n' ) { 698: c = getc(finput); 699: lineno++; 700: } 701: fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile ); 702: while( c>=0 ){ 703: if( c=='\\' ) 704: if( (c=getc(finput)) == '}' ) return; 705: else putc('\\', ftable ); 706: if( c=='%' ) 707: if( (c=getc(finput)) == '}' ) return; 708: else putc('%', ftable ); 709: putc( c , ftable ); 710: if( c == '\n' ) ++lineno; 711: c = getc(finput); 712: } 713: error("eof before %%}" ); 714: } 715: 716: skipcom(){ /* skip over comments */ 717: register c, i=0; /* i is the number of lines skipped */ 718: 719: /* skipcom is called after reading a / */ 720: 721: if( getc(finput) != '*' ) error( "illegal comment" ); 722: c = getc(finput); 723: while( c != EOF ){ 724: while( c == '*' ){ 725: if( (c=getc(finput)) == '/' ) return( i ); 726: } 727: if( c == '\n' ) ++i; 728: c = getc(finput); 729: } 730: error( "EOF inside comment" ); 731: /* NOTREACHED */ 732: } 733: 734: cpyact(offset){ /* copy C action to the next ; or closing } */ 735: int brac, c, match, j, s, tok; 736: 737: fprintf( faction, "\n# line %d \"%s\"\n", lineno, infile ); 738: 739: brac = 0; 740: 741: loop: 742: c = getc(finput); 743: swt: 744: switch( c ){ 745: 746: case ';': 747: if( brac == 0 ){ 748: putc( c , faction ); 749: return; 750: } 751: goto lcopy; 752: 753: case '{': 754: brac++; 755: goto lcopy; 756: 757: case '$': 758: s = 1; 759: tok = -1; 760: c = getc(finput); 761: if( c == '<' ){ /* type description */ 762: ungetc( c, finput ); 763: if( gettok() != TYPENAME ) error( "bad syntax on $<ident> clause" ); 764: tok = numbval; 765: c = getc(finput); 766: } 767: if( c == '$' ){ 768: fprintf( faction, "yyval"); 769: if( ntypes ){ /* put out the proper tag... */ 770: if( tok < 0 ) tok = fdtype( *prdptr[nprod] ); 771: fprintf( faction, ".%s", typeset[tok] ); 772: } 773: goto loop; 774: } 775: if( c == '-' ){ 776: s = -s; 777: c = getc(finput); 778: } 779: if( isdigit(c) ){ 780: j=0; 781: while( isdigit(c) ){ 782: j= j*10+c-'0'; 783: c = getc(finput); 784: } 785: 786: j = j*s - offset; 787: if( j > 0 ){ 788: error( "Illegal use of $%d", j+offset ); 789: } 790: 791: fprintf( faction, "yypvt[-%d]", -j ); 792: if( ntypes ){ /* put out the proper tag */ 793: if( j+offset <= 0 && tok < 0 ) error( "must specify type of $%d", j+offset ); 794: if( tok < 0 ) tok = fdtype( prdptr[nprod][j+offset] ); 795: fprintf( faction, ".%s", typeset[tok] ); 796: } 797: goto swt; 798: } 799: putc( '$' , faction ); 800: if( s<0 ) putc('-', faction ); 801: goto swt; 802: 803: case '}': 804: if( --brac ) goto lcopy; 805: putc( c, faction ); 806: return; 807: 808: 809: case '/': /* look for comments */ 810: putc( c , faction ); 811: c = getc(finput); 812: if( c != '*' ) goto swt; 813: 814: /* it really is a comment */ 815: 816: putc( c , faction ); 817: c = getc(finput); 818: while( c != EOF ){ 819: while( c=='*' ){ 820: putc( c , faction ); 821: if( (c=getc(finput)) == '/' ) goto lcopy; 822: } 823: putc( c , faction ); 824: if( c == '\n' )++lineno; 825: c = getc(finput); 826: } 827: error( "EOF inside comment" ); 828: 829: case '\'': /* character constant */ 830: match = '\''; 831: goto string; 832: 833: case '"': /* character string */ 834: match = '"'; 835: 836: string: 837: 838: putc( c , faction ); 839: while( c=getc(finput) ){ 840: 841: if( c=='\\' ){ 842: putc( c , faction ); 843: c=getc(finput); 844: if( c == '\n' ) ++lineno; 845: } 846: else if( c==match ) goto lcopy; 847: else if( c=='\n' ) error( "newline in string or char. const." ); 848: putc( c , faction ); 849: } 850: error( "EOF in string or character constant" ); 851: 852: case EOF: 853: error("action does not terminate" ); 854: 855: case '\n': ++lineno; 856: goto lcopy; 857: 858: } 859: 860: lcopy: 861: putc( c , faction ); 862: goto loop; 863: }