ref: b0377e84cf31c48afed765c433abe7eebb4135a5
dir: /sys/src/cmd/lex/sub1.c/
# include "ldefs.h" uchar * getl(uchar *p) /* return next line of input, throw away trailing '\n' */ /* returns 0 if eof is had immediately */ { int c; uchar *s, *t; t = s = p; while(((c = gch()) != 0) && c != '\n') *t++ = c; *t = 0; if(c == 0 && s == t) return((uchar *)0); prev = '\n'; pres = '\n'; return(s); } void printerr(char *type, char *fmt, va_list argl) { char buf[1024]; if(!eof)fprint(errorf,"%s:%d ", yyfile, yyline); fprint(errorf,"(%s) ", type); vseprint(buf, buf+sizeof(buf), fmt, argl); fprint(errorf, "%s\n", buf); } void error(char *s,...) { va_list argl; va_start(argl, s); printerr("Error", s, argl); va_end(argl); # ifdef DEBUG if(debug && sect != ENDSECTION) { sect1dump(); sect2dump(); } # endif if( # ifdef DEBUG debug || # endif report == 1) statistics(); exits("error"); /* error return code */ } void warning(char *s,...) { va_list argl; va_start(argl, s); printerr("Warning", s, argl); va_end(argl); Bflush(&fout); } void lgate(void) { int fd; if (lgatflg) return; lgatflg=1; if(foutopen == 0){ fd = create("lex.yy.c", OWRITE, 0666); if(fd < 0) error("Can't open lex.yy.c: %r"); Binit(&fout, fd, OWRITE); foutopen = 1; } phead1(); } void cclinter(int sw) { /* sw = 1 ==> ccl */ int i, j, k; int m; if(!sw){ /* is NCCL */ for(i=1;i<NCH;i++) symbol[i] ^= 1; /* reverse value */ } for(i=1;i<NCH;i++) if(symbol[i]) break; if(i >= NCH) return; i = cindex[i]; /* see if ccl is already in our table */ j = 0; if(i){ for(j=1;j<NCH;j++){ if((symbol[j] && cindex[j] != i) || (!symbol[j] && cindex[j] == i)) break; } } if(j >= NCH) return; /* already in */ m = 0; k = 0; for(i=1;i<NCH;i++) if(symbol[i]){ if(!cindex[i]){ cindex[i] = ccount; symbol[i] = 0; m = 1; } else k = 1; } /* m == 1 implies last value of ccount has been used */ if(m)ccount++; if(k == 0) return; /* is now in as ccount wholly */ /* intersection must be computed */ for(i=1;i<NCH;i++){ if(symbol[i]){ m = 0; j = cindex[i]; /* will be non-zero */ for(k=1;k<NCH;k++){ if(cindex[k] == j){ if(symbol[k]) symbol[k] = 0; else { cindex[k] = ccount; m = 1; } } } if(m)ccount++; } } } int usescape(int c) { int d; switch(c){ case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'b': c = '\b'; break; case 'f': c = 014; break; /* form feed for ascii */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': c -= '0'; while('0' <= (d=gch()) && d <= '7'){ c = c * 8 + (d-'0'); if(!('0' <= peek && peek <= '7')) break; } break; } return(c); } int lookup(uchar *s, uchar **t) { int i; i = 0; while(*t){ if(strcmp((char *)s, *(char **)t) == 0) return(i); i++; t++; } return(-1); } int cpyact(void) { /* copy C action to the next ; or closing } */ int brac, c, mth; int savline, sw; char *savfile; brac = 0; sw = TRUE; savline = 0; savfile = "?"; while(!eof){ c = gch(); swt: switch( c ){ case '|': if(brac == 0 && sw == TRUE){ if(peek == '|')gch(); /* eat up an extra '|' */ return(0); } break; case ';': if( brac == 0 ){ Bputc(&fout, c); Bputc(&fout, '\n'); return(1); } break; case '{': brac++; savline=yyline; savfile=yyfile; break; case '}': brac--; if( brac == 0 ){ Bputc(&fout, c); Bputc(&fout, '\n'); return(1); } break; case '/': /* look for comments */ Bputc(&fout, c); c = gch(); if( c != '*' ) goto swt; /* it really is a comment */ Bputc(&fout, c); savline=yyline; savfile=yyfile; while( c=gch() ){ if( c=='*' ){ Bputc(&fout, c); if( (c=gch()) == '/' ) goto loop; } Bputc(&fout, c); } yyline=savline; yyfile=savfile; error( "EOF inside comment" ); case '\'': /* character constant */ mth = '\''; goto string; case '"': /* character string */ mth = '"'; string: Bputc(&fout, c); while( c=gch() ){ if( c=='\\' ){ Bputc(&fout, c); c=gch(); } else if( c==mth ) goto loop; Bputc(&fout, c); if (c == '\n') { yyline--; error( "Non-terminated string or character constant"); } } error( "EOF in string or character constant" ); case '\0': yyline = savline; yyfile = savfile; error("Action does not terminate"); default: break; /* usual character */ } loop: if(c != ' ' && c != '\t' && c != '\n') sw = FALSE; Bputc(&fout, c); } error("Premature EOF"); return(0); } int gch(void){ int c; prev = pres; c = pres = peek; peek = pushptr > pushc ? *--pushptr : Bgetc(fin); if(peek == Beof && sargc > 1){ Bterm(fin); yyfile = sargv[fptr++]; fin = Bopen(yyfile,OREAD); if(fin == 0) error("%s - cannot open file: %r",yyfile); peek = Bgetc(fin); sargc--; sargv++; } if(c == Beof) { eof = TRUE; Bterm(fin); fin = 0; return(0); } if(c == '\n')yyline++; return(c); } int mn2(int a, int d, int c) { name[tptr] = a; left[tptr] = d; right[tptr] = c; parent[tptr] = 0; nullstr[tptr] = 0; switch(a){ case RSTR: parent[d] = tptr; break; case BAR: case RNEWE: if(nullstr[d] || nullstr[c]) nullstr[tptr] = TRUE; parent[d] = parent[c] = tptr; break; case RCAT: case DIV: if(nullstr[d] && nullstr[c])nullstr[tptr] = TRUE; parent[d] = parent[c] = tptr; break; case RSCON: parent[d] = tptr; nullstr[tptr] = nullstr[d]; break; # ifdef DEBUG default: warning("bad switch mn2 %d %d",a,d); break; # endif } if(tptr > treesize) error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":"")); return(tptr++); } int mnp(int a, void *p) { name[tptr] = a; left[tptr] = 0; parent[tptr] = 0; nullstr[tptr] = 0; ptr[tptr] = p; switch(a){ case RCCL: case RNCCL: if(strlen(p) == 0) nullstr[tptr] = TRUE; break; default: error("bad switch mnp %d %P", a, p); break; } if(tptr > treesize) error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":"")); return(tptr++); } int mn1(int a, int d) { name[tptr] = a; left[tptr] = d; parent[tptr] = 0; nullstr[tptr] = 0; switch(a){ case STAR: case QUEST: nullstr[tptr] = TRUE; parent[d] = tptr; break; case PLUS: case CARAT: nullstr[tptr] = nullstr[d]; parent[d] = tptr; break; case S2FINAL: nullstr[tptr] = TRUE; break; # ifdef DEBUG case FINAL: case S1FINAL: break; default: warning("bad switch mn1 %d %d",a,d); break; # endif } if(tptr > treesize) error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":"")); return(tptr++); } int mn0(int a) { name[tptr] = a; parent[tptr] = 0; nullstr[tptr] = 0; if(a >= NCH) switch(a){ case RNULLS: nullstr[tptr] = TRUE; break; # ifdef DEBUG default: warning("bad switch mn0 %d",a); break; # endif } if(tptr > treesize) error("Parse tree too big %s",(treesize == TREESIZE?"\nTry using %e num":"")); return(tptr++); } void munputc(int p) { *pushptr++ = peek; /* watch out for this */ peek = p; if(pushptr >= pushc+TOKENSIZE) error("Too many characters pushed"); } void munputs(uchar *p) { int i,j; *pushptr++ = peek; peek = p[0]; i = strlen((char*)p); for(j = i-1; j>=1; j--) *pushptr++ = p[j]; if(pushptr >= pushc+TOKENSIZE) error("Too many characters pushed"); } int dupl(int n) { /* duplicate the subtree whose root is n, return ptr to it */ int i; i = name[n]; if(i < NCH) return(mn0(i)); switch(i){ case RNULLS: return(mn0(i)); case RCCL: case RNCCL: return(mnp(i,ptr[n])); case FINAL: case S1FINAL: case S2FINAL: return(mn1(i,left[n])); case STAR: case QUEST: case PLUS: case CARAT: return(mn1(i,dupl(left[n]))); case RSTR: case RSCON: return(mn2(i,dupl(left[n]),right[n])); case BAR: case RNEWE: case RCAT: case DIV: return(mn2(i,dupl(left[n]),dupl(right[n]))); # ifdef DEBUG default: warning("bad switch dupl %d",n); # endif } return(0); } # ifdef DEBUG void allprint(int c) { if(c < 0) c += 256; /* signed char */ switch(c){ case 014: print("\\f"); charc++; break; case '\n': print("\\n"); charc++; break; case '\t': print("\\t"); charc++; break; case '\b': print("\\b"); charc++; break; case ' ': print("\\\bb"); break; default: if(!isprint(c)){ print("\\%-3o",c); charc += 3; } else print("%c", c); break; } charc++; } void strpt(uchar *s) { charc = 0; while(*s){ allprint(*s++); if(charc > LINESIZE){ charc = 0; print("\n\t"); } } } void sect1dump(void) { int i; print("Sect 1:\n"); if(def[0]){ print("str trans\n"); i = -1; while(def[++i]) print("%s\t%s\n",def[i],subs[i]); } if(sname[0]){ print("start names\n"); i = -1; while(sname[++i]) print("%s\n",sname[i]); } } void sect2dump(void) { print("Sect 2:\n"); treedump(); } void treedump(void) { int t; uchar *p; print("treedump %d nodes:\n",tptr); for(t=0;t<tptr;t++){ print("%4d ",t); parent[t] ? print("p=%4d",parent[t]) : print(" "); print(" "); if(name[t] < NCH) allprint(name[t]); else switch(name[t]){ case RSTR: print("%d ",left[t]); allprint(right[t]); break; case RCCL: print("ccl "); allprint(ptr[t]); break; case RNCCL: print("nccl "); allprint(ptr[t]); break; case DIV: print("/ %d %d",left[t],right[t]); break; case BAR: print("| %d %d",left[t],right[t]); break; case RCAT: print("cat %d %d",left[t],right[t]); break; case PLUS: print("+ %d",left[t]); break; case STAR: print("* %d",left[t]); break; case CARAT: print("^ %d",left[t]); break; case QUEST: print("? %d",left[t]); break; case RNULLS: print("nullstring"); break; case FINAL: print("final %d",left[t]); break; case S1FINAL: print("s1final %d",left[t]); break; case S2FINAL: print("s2final %d",left[t]); break; case RNEWE: print("new %d %d",left[t],right[t]); break; case RSCON: p = (uchar *)right[t]; print("start %s",sname[*p++-1]); while(*p) print(", %s",sname[*p++-1]); print(" %d",left[t]); break; default: print("unknown %d %d %d",name[t],left[t],right[t]); break; } if(nullstr[t])print("\t(null poss.)"); print("\n"); } } # endif