#include "y2.h" /* * YSETUP.C -- Modified for use with DECUS LEX * Variable "yylval" resides in yylex(), not in yypars(); * Therefore, is defined "extern" here. * * Also, the command line processing for the Decus version * has been changed. A new switch has been added to allow * specification of the "table" file name(s), and unused * switch processing removed. * * NOTE * This probably won't run on UNIX any more. * * Bob Denny * 27-Aug-81 */ setup(argc,argv) int argc; char *argv[]; { int i,j,lev,t, ty; int c; int tempty; /*01*/ int *p; int defsw, infsw; char actname[8]; char filename[24]; char *cp; defsw = infsw = 0; foutput = NULL; fdefine = NULL; i = 1; while( argc >= 2 && argv[1][0] == '-' ) { while( *++(argv[1]) ) { switch( *argv[1] ) { case 'i': case 'I': infsw++; continue; case 'h': case 'H': defsw++; continue; default: fprintf(stderr, "Illegal option: %c\n", *argv[1]); usage(); } } argv++; argc--; } if(argc < 2) usage(); /* Catch no filename given */ /* * Now open the input file with a default extension of ".Y", * then replace the period in argv[1] with a null, so argv[1] * can be used to form the table, defs and info filenames. */ cp = argv[1]; while(*cp++ != '.' && *cp != '\0'); /* Scan past '.' or to null */ if(*cp == '\0') concat(filename, argv[1], ".Y", 0); else { strcpy(filename, argv[1]); *(argv[1]-1) = '\0'; /* Null the period */ } if((finput=fopen( filename, "r" )) == NULL ) error( "cannot open input file \"%s\"", filename ); /* * Now open the .H and .I files if requested. */ if(defsw) { concat(filename, argv[1], ".H", 0); fdefine = fopen(filename, "w"); if(fdefine == NULL) error("cannot open defs file\"%s\"", filename); } if(infsw) { concat(filename, argv[1], ".I", 0); foutput = fopen(filename, "w"); if(foutput == NULL) error("cannot open info file\"%s\"", filename); } /* * Now the "table" output C file. */ concat(filename, argv[1], ".C", 0); ftable = fopen(filename, "w"); if( ftable == NULL ) error( "cannot open table file\"%s\"", filename); /* * Finally, the temp files. */ ftemp = fopen( TEMPNAME, "w" ); faction = fopen( ACTNAME, "w" ); if( ftemp==NULL || faction==NULL ) error( "cannot open temp file" ); /* * Now put the full filename of the input file into * the "filename" buffer for cpyact(), and point the * global cell "infile" at it. */ iovtoa(finput, filename); infile = filename; /* * Complete initialization. */ cnamp = cnames; defin(0,"$end"); extval = 0400; defin(0,"error"); defin(1,"$accept"); mem=mem0; lev = 0; ty = 0; i=0; /* sorry -- no yacc parser here..... we must bootstrap somehow... */ for( t=gettok(); t!=MARK && t!= ENDFILE; ) { switch( t ) { case ';': t = gettok(); break; case START: if( (t=gettok()) != IDENTIFIER ) { error( "bad %%start construction" ); } start = chfind(1,tokname); t = gettok(); continue; case TYPEDEF: if( (t=gettok()) != TYPENAME ) error( "bad syntax in %%type" ); ty = numbval; for(;;) { t = gettok(); switch( t ) { case IDENTIFIER: if( (t=chfind( 1, tokname ) ) < NTBASE ) { j = TYPE( toklev[t] ); if( j!= 0 && j != ty ) { error( "type redeclaration of token %s", tokset[t].name ); } else SETTYPE( toklev[t],ty); } else { j = nontrst[t-NTBASE].tvalue; if( j != 0 && j != ty ) { error( "type redeclaration of nonterminal %s", nontrst[t-NTBASE].name ); } else nontrst[t-NTBASE].tvalue = ty; } case ',': continue; case ';': t = gettok(); break; default: break; } break; } continue; case UNION: /* copy the union declaration to the output */ cpyunion(); t = gettok(); continue; case LEFT: case BINARY: case RIGHT: ++i; case TERM: lev = t-TERM; /* nonzero means new prec. and assoc. */ ty = 0; /* get identifiers so defined */ t = gettok(); if( t == TYPENAME ) { /* there is a type defined */ ty = numbval; t = gettok(); } for(;;) { switch( t ) { case ',': t = gettok(); continue; case ';': break; case IDENTIFIER: j = chfind(0,tokname); if( lev ) { if( ASSOC(toklev[j]) ) error( "redeclaration of precedence of%s", tokname ); SETASC(toklev[j],lev); SETPLEV(toklev[j],i); } if( ty ) { if( TYPE(toklev[j]) ) error( "redeclaration of type of %s", tokname ); SETTYPE(toklev[j],ty); } if( (t=gettok()) == NUMBER ) { tokset[j].value = numbval; if( j < ndefout && j>2 ) { error( "please define type number of %s earlier", tokset[j].name ); } t=gettok(); } continue; } break; } continue; case LCURLY: defout(); cpycode(); t = gettok(); continue; default: error( "syntax error" ); } } if( t == ENDFILE ) { error( "unexpected EOF before %%" ); } /* t is MARK */ defout(); fprintf( ftable, "#define yyclearin yychar = -1\n" ); fprintf( ftable, "#define yyerrok yyerrflag = 0\n" ); fprintf( ftable, "extern int yychar;\nextern short yyerrflag;\n" ); fprintf( ftable, "#ifndef YYMAXDEPTH\n#define YYMAXDEPTH 150\n#endif\n" ); if( !ntypes ) fprintf( ftable, "#ifndef YYSTYPE\n#define YYSTYPE int\n#endif\n" ); #ifndef decus fprintf( ftable, "YYSTYPE yylval, yyval;\n" ); #else fprintf( ftable, "extern YYSTYPE yylval; /*DECUS LEX */\n"); fprintf( ftable, "YYSTYPE yyval; /*DECUS LEX */\n"); #endif prdptr[0]=mem; /* added production */ *mem++ = NTBASE; *mem++ = start; /* if start is 0, we will overwrite with the lhs of the firstrule */ *mem++ = 1; *mem++ = 0; prdptr[1]=mem; while( (t=gettok()) == LCURLY ) cpycode(); if( t != C_IDENTIFIER ) error( "bad syntax on first rule" ); if( !start ) prdptr[0][1] = chfind(1,tokname); /* read rules */ while( t!=MARK && t!=ENDFILE ) { /* process a rule */ if( t == '|' ) { *mem++ = *prdptr[nprod-1]; } else if( t == C_IDENTIFIER ) { *mem = chfind(1,tokname); if( *mem < NTBASE ) error( "token illegal on LHS of grammar rule" ); ++mem; } else error( "illegal rule: missing semicolon or | ?" ); /* read rule body */ t = gettok(); more_rule: while( t == IDENTIFIER ) { *mem = chfind(1,tokname); if( *mem=NTBASE)error("nonterminal %s illegal after %%prec", nontrst[j-NTBASE].name); levprd[nprod]=toklev[j]; t = gettok(); } if( t == '=' ) { levprd[nprod] |= ACTFLAG; fprintf( faction, "\ncase %d:", nprod ); cpyact( mem-prdptr[nprod]-1 ); fprintf( faction, " break;" ); if( (t=gettok()) == IDENTIFIER ) { /* action within rule... */ sprintf( actname, "$$%d", nprod ); j = chfind(1,actname); /* make it a nonterminal */ /* the current rule will become rule number nprod+1 */ /* move the contents down, and make room for the null */ for( p=mem; p>=prdptr[nprod]; --p ) p[2] = *p; mem += 2; /* enter null production for action */ p = prdptr[nprod]; *p++ = j; *p++ = -nprod; /* update the production information */ levprd[nprod+1] = levprd[nprod] & ~ACTFLAG; levprd[nprod] = ACTFLAG; if( ++nprod >= NPROD ) error( "more than %d rules", NPROD ); prdptr[nprod] = p; /* make the action appear in the original rule */ *mem++ = j; /* get some more of the rule */ goto more_rule; } } while( t == ';' ) t = gettok(); *mem++ = -nprod; /* check that default action is reasonable */ if( ntypes && !(levprd[nprod]&ACTFLAG) && nontrst[*prdptr[nprod]-NTBASE].tvalue ) { /* no explicit action, LHS has value */ /*01*/ tempty = prdptr[nprod][1]; if( tempty < 0 ) error( "must return a value, since LHS has a type" ); else if( tempty >= NTBASE ) tempty = nontrst[tempty-NTBASE].tvalue; else tempty = TYPE( toklev[tempty] ); if( tempty != nontrst[*prdptr[nprod]-NTBASE].tvalue ) { error( "default action causes potential type clash" ); } } if( ++nprod >= NPROD ) error( "more than %d rules", NPROD ); prdptr[nprod] = mem; levprd[nprod]=0; } /* end of all rules */ fputss("/* End of actions */", faction); /* Properly terminate the last line */ finact(); if( t == MARK ) { fprintf( ftable, "\n# line %d \"%s\"\n", lineno, infile ); while( (c=getc(finput)) != EOF ) putc( c, ftable ); } fclose( finput ); } usage() { fprintf(stderr,"Modified YACC:\n"); fprintf(stderr," yacc -hi infile\n\n"); fprintf(stderr,"Switches:\n"); fprintf(stderr," -h Create definitions header file\n"); fprintf(stderr," -i Create parser description file\n\n"); fprintf(stderr,"Default input file extension is \".Y\"\n"); fprintf(stderr,"Defs file same name, \".H\" extension.\n"); fprintf(stderr,"Info file same name, \".I\" extension.\n"); #ifdef decus #ifdef rsx exit(2); /* Exit status "error" */ #endif #ifdef rt11 exit(4); #endif #else exit(0); #endif }