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