diff options
author | rsc <devnull@localhost> | 2004-04-21 23:22:06 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2004-04-21 23:22:06 +0000 |
commit | 17e5fb8973d9e48ef53a88eb78f845f8a7b41a5b (patch) | |
tree | 921c649de0d83bdde4561f5868e5ff3ab9986af8 /src/cmd/bc.y | |
parent | 3e63e5c271f7a7013dc4b3fedfb83c2d547b8c26 (diff) | |
download | plan9port-17e5fb8973d9e48ef53a88eb78f845f8a7b41a5b.tar.gz plan9port-17e5fb8973d9e48ef53a88eb78f845f8a7b41a5b.tar.bz2 plan9port-17e5fb8973d9e48ef53a88eb78f845f8a7b41a5b.zip |
add new guys
Diffstat (limited to 'src/cmd/bc.y')
-rw-r--r-- | src/cmd/bc.y | 983 |
1 files changed, 983 insertions, 0 deletions
diff --git a/src/cmd/bc.y b/src/cmd/bc.y new file mode 100644 index 00000000..5eddf471 --- /dev/null +++ b/src/cmd/bc.y @@ -0,0 +1,983 @@ +%{ + #include <u.h> + #include <libc.h> + #include <bio.h> + + #define bsp_max 5000 + + Biobuf *in; + Biobuf stdin; + Biobuf stdout; + char cary[1000]; + char* cp = { cary }; + char string[1000]; + char* str = { string }; + int crs = 128; + int rcrs = 128; /* reset crs */ + int bindx = 0; + int lev = 0; + int ln; + int* ttp; + char* ss = ""; + int bstack[10] = { 0 }; + char* numb[15] = + { + " 0", " 1", " 2", " 3", " 4", " 5", + " 6", " 7", " 8", " 9", " 10", " 11", + " 12", " 13", " 14" + }; + int* pre; + int* post; + + long peekc = -1; + int sargc; + int ifile; + char** sargv; + + char *funtab[] = + { + "<1>","<2>","<3>","<4>","<5>", + "<6>","<7>","<8>","<9>","<10>", + "<11>","<12>","<13>","<14>","<15>", + "<16>","<17>","<18>","<19>","<20>", + "<21>","<22>","<23>","<24>","<25>", + "<26>" + }; + char *atab[] = + { + "<221>","<222>","<223>","<224>","<225>", + "<226>","<227>","<228>","<229>","<230>", + "<231>","<232>","<233>","<234>","<235>", + "<236>","<237>","<238>","<239>","<240>", + "<241>","<242>","<243>","<244>","<245>", + "<246>" + }; + char* letr[26] = + { + "a","b","c","d","e","f","g","h","i","j", + "k","l","m","n","o","p","q","r","s","t", + "u","v","w","x","y","z" + }; + char* dot = { "." }; + int bspace[bsp_max]; + int* bsp_nxt = { bspace }; + int bdebug = 0; + int lflag; + int cflag; + int sflag; + + int* bundle(int, ...); + void conout(int*, char*); + int cpeek(int, int, int); + int getch(void); + int* geta(char*); + int* getf(char*); + void getout(void); + void output(int*); + void pp(char*); + void routput(int*); + void tp(char*); + void yyerror(char*, ...); + int yyparse(void); + + typedef void* pointer; +/* #pragma varargck type "lx" pointer */ + +%} +%union +{ + int* iptr; + char* cptr; + int cc; +} + +%type <iptr> pstat stat stat1 def slist dlets e ase nase +%type <iptr> slist re fprefix cargs eora cons constant lora +%type <cptr> crs + +%token <cptr> LETTER EQOP _AUTO DOT +%token <cc> DIGIT SQRT LENGTH _IF FFF EQ +%token <cc> _PRINT _WHILE _FOR NE LE GE INCR DECR +%token <cc> _RETURN _BREAK _DEFINE BASE OBASE SCALE +%token <cc> QSTR ERROR + +%right '=' EQOP +%left '+' '-' +%left '*' '/' '%' +%right '^' +%left UMINUS + +%% +start: + start stuff +| stuff + +stuff: + pstat tail + { + output($1); + } +| def dargs ')' '{' dlist slist '}' + { + ttp = bundle(6, pre, $6, post , "0", numb[lev], "Q"); + conout(ttp, (char*)$1); + rcrs = crs; + output((int*)""); /* this is horse puk!! */ + lev = bindx = 0; + } + +dlist: + tail +| dlist _AUTO dlets tail + +stat: + stat1 +| nase + { + if(sflag) + bundle(2, $1, "s."); + } + +pstat: + stat1 + { + if(sflag) + bundle(2, $1, "0"); + } +| nase + { + if(!sflag) + bundle(2, $1, "ps."); + } + +stat1: + { + bundle(1, ""); + } +| ase + { + bundle(2, $1, "s."); + } +| SCALE '=' e + { + bundle(2, $3, "k"); + } +| SCALE EQOP e + { + bundle(4, "K", $3, $2, "k"); + } +| BASE '=' e + { + bundle(2, $3, "i"); + } +| BASE EQOP e + { + bundle(4, "I", $3, $2, "i"); + } +| OBASE '=' e + { + bundle(2, $3, "o"); + } +| OBASE EQOP e + { + bundle(4, "O", $3, $2, "o"); + } +| QSTR + { + bundle(3, "[", $1, "]P"); + } +| _BREAK + { + bundle(2, numb[lev-bstack[bindx-1]], "Q"); + } +| _PRINT e + { + bundle(2, $2, "ps."); + } +| _RETURN e + { + bundle(4, $2, post, numb[lev], "Q"); + } +| _RETURN + { + bundle(4, "0", post, numb[lev], "Q"); + } +| '{' slist '}' + { + $$ = $2; + } +| FFF + { + bundle(1, "fY"); + } +| _IF crs BLEV '(' re ')' stat + { + conout($7, $2); + bundle(3, $5, $2, " "); + } +| _WHILE crs '(' re ')' stat BLEV + { + bundle(3, $6, $4, $2); + conout($$, $2); + bundle(3, $4, $2, " "); + } +| fprefix crs re ';' e ')' stat BLEV + { + bundle(5, $7, $5, "s.", $3, $2); + conout($$, $2); + bundle(5, $1, "s.", $3, $2, " "); + } +| '~' LETTER '=' e + { + bundle(3, $4, "S", $2); + } + +fprefix: + _FOR '(' e ';' + { + $$ = $3; + } + +BLEV: + = + { + --bindx; + } + +slist: + stat +| slist tail stat + { + bundle(2, $1, $3); + } + +tail: + '\n' + { + ln++; + } +| ';' + +re: + e EQ e + { + $$ = bundle(3, $1, $3, "="); + } +| e '<' e + { + bundle(3, $1, $3, ">"); + } +| e '>' e + { + bundle(3, $1, $3, "<"); + } +| e NE e + { + bundle(3, $1, $3, "!="); + } +| e GE e + { + bundle(3, $1, $3, "!>"); + } +| e LE e + { + bundle(3, $1, $3, "!<"); + } +| e + { + bundle(2, $1, " 0!="); + } + +nase: + '(' e ')' + { + $$ = $2; + } +| cons + { + bundle(3, " ", $1, " "); + } +| DOT cons + { + bundle(3, " .", $2, " "); + } +| cons DOT cons + { + bundle(5, " ", $1, ".", $3, " "); + } +| cons DOT + { + bundle(4, " ", $1, ".", " "); + } +| DOT + { + $<cptr>$ = "l."; + } +| LETTER '[' e ']' + { + bundle(3, $3, ";", geta($1)); + } +| LETTER INCR + { + bundle(4, "l", $1, "d1+s", $1); + } +| INCR LETTER + { + bundle(4, "l", $2, "1+ds", $2); + } +| DECR LETTER + { + bundle(4, "l", $2, "1-ds", $2); + } +| LETTER DECR + { + bundle(4, "l", $1, "d1-s", $1); + } +| LETTER '[' e ']' INCR + { + bundle(7, $3, ";", geta($1), "d1+" ,$3, ":" ,geta($1)); + } +| INCR LETTER '[' e ']' + { + bundle(7, $4, ";", geta($2), "1+d", $4, ":", geta($2)); + } +| LETTER '[' e ']' DECR + { + bundle(7, $3, ";", geta($1), "d1-", $3, ":", geta($1)); + } +| DECR LETTER '[' e ']' + { + bundle(7, $4, ";", geta($2), "1-d", $4, ":" ,geta($2)); + } +| SCALE INCR + { + bundle(1, "Kd1+k"); + } +| INCR SCALE + { + bundle(1, "K1+dk"); + } +| SCALE DECR + { + bundle(1, "Kd1-k"); + } +| DECR SCALE + { + bundle(1, "K1-dk"); + } +| BASE INCR + { + bundle(1, "Id1+i"); + } +| INCR BASE + { + bundle(1, "I1+di"); + } +| BASE DECR + { + bundle(1, "Id1-i"); + } +| DECR BASE + { + bundle(1, "I1-di"); + } +| OBASE INCR + { + bundle(1, "Od1+o"); + } +| INCR OBASE + { + bundle(1, "O1+do"); + } +| OBASE DECR + { + bundle(1, "Od1-o"); + } +| DECR OBASE + { + bundle(1, "O1-do"); + } +| LETTER '(' cargs ')' + { + bundle(4, $3, "l", getf($1), "x"); + } +| LETTER '(' ')' + { + bundle(3, "l", getf($1), "x"); + } +| LETTER = { + bundle(2, "l", $1); + } +| LENGTH '(' e ')' + { + bundle(2, $3, "Z"); + } +| SCALE '(' e ')' + { + bundle(2, $3, "X"); + } +| '?' + { + bundle(1, "?"); + } +| SQRT '(' e ')' + { + bundle(2, $3, "v"); + } +| '~' LETTER + { + bundle(2, "L", $2); + } +| SCALE + { + bundle(1, "K"); + } +| BASE + { + bundle(1, "I"); + } +| OBASE + { + bundle(1, "O"); + } +| '-' e + { + bundle(3, " 0", $2, "-"); + } +| e '+' e + { + bundle(3, $1, $3, "+"); + } +| e '-' e + { + bundle(3, $1, $3, "-"); + } +| e '*' e + { + bundle(3, $1, $3, "*"); + } +| e '/' e + { + bundle(3, $1, $3, "/"); + } +| e '%' e + { + bundle(3, $1, $3, "%%"); + } +| e '^' e + { + bundle(3, $1, $3, "^"); + } + +ase: + LETTER '=' e + { + bundle(3, $3, "ds", $1); + } +| LETTER '[' e ']' '=' e + { + bundle(5, $6, "d", $3, ":", geta($1)); + } +| LETTER EQOP e + { + bundle(6, "l", $1, $3, $2, "ds", $1); + } +| LETTER '[' e ']' EQOP e + { + bundle(9, $3, ";", geta($1), $6, $5, "d", $3, ":", geta($1)); + } + +e: + ase +| nase + +cargs: + eora +| cargs ',' eora + { + bundle(2, $1, $3); + } + +eora: + e +| LETTER '[' ']' + { + bundle(2, "l", geta($1)); + } + +cons: + constant + { + *cp++ = 0; + } + +constant: + '_' + { + $<cptr>$ = cp; + *cp++ = '_'; + } +| DIGIT + { + $<cptr>$ = cp; + *cp++ = $1; + } +| constant DIGIT + { + *cp++ = $2; + } + +crs: + = + { + $$ = cp; + *cp++ = '<'; + *cp++ = crs/100+'0'; + *cp++ = (crs%100)/10+'0'; + *cp++ = crs%10+'0'; + *cp++ = '>'; + *cp++ = '\0'; + if(crs++ >= 220) { + yyerror("program too big"); + getout(); + } + bstack[bindx++] = lev++; + } + +def: + _DEFINE LETTER '(' + { + $$ = getf($2); + pre = (int*)""; + post = (int*)""; + lev = 1; + bindx = 0; + bstack[bindx] = 0; + } + +dargs: +| lora + { + pp((char*)$1); + } +| dargs ',' lora + { + pp((char*)$3); + } + +dlets: + lora + { + tp((char*)$1); + } +| dlets ',' lora + { + tp((char*)$3); + } + +lora: + LETTER + { + $<cptr>$=$1; + } +| LETTER '[' ']' + { + $$ = geta($1); + } + +%% + +int +yylex(void) +{ + int c, ch; + +restart: + c = getch(); + peekc = -1; + while(c == ' ' || c == '\t') + c = getch(); + if(c == '\\') { + getch(); + goto restart; + } + if(c >= 'a' && c <= 'z') { + /* look ahead to look for reserved words */ + peekc = getch(); + if(peekc >= 'a' && peekc <= 'z') { /* must be reserved word */ + if(c=='p' && peekc=='r') { + c = _PRINT; + goto skip; + } + if(c=='i' && peekc=='f') { + c = _IF; + goto skip; + } + if(c=='w' && peekc=='h') { + c = _WHILE; + goto skip; + } + if(c=='f' && peekc=='o') { + c = _FOR; + goto skip; + } + if(c=='s' && peekc=='q') { + c = SQRT; + goto skip; + } + if(c=='r' && peekc=='e') { + c = _RETURN; + goto skip; + } + if(c=='b' && peekc=='r') { + c = _BREAK; + goto skip; + } + if(c=='d' && peekc=='e') { + c = _DEFINE; + goto skip; + } + if(c=='s' && peekc=='c') { + c = SCALE; + goto skip; + } + if(c=='b' && peekc=='a') { + c = BASE; + goto skip; + } + if(c=='i' && peekc=='b') { + c = BASE; + goto skip; + } + if(c=='o' && peekc=='b') { + c = OBASE; + goto skip; + } + if(c=='d' && peekc=='i') { + c = FFF; + goto skip; + } + if(c=='a' && peekc=='u') { + c = _AUTO; + goto skip; + } + if(c=='l' && peekc=='e') { + c = LENGTH; + goto skip; + } + if(c=='q' && peekc=='u') + getout(); + /* could not be found */ + return ERROR; + + skip: /* skip over rest of word */ + peekc = -1; + for(;;) { + ch = getch(); + if(ch < 'a' || ch > 'z') + break; + } + peekc = ch; + return c; + } + + /* usual case; just one single letter */ + yylval.cptr = letr[c-'a']; + return LETTER; + } + if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) { + yylval.cc = c; + return DIGIT; + } + switch(c) { + case '.': + return DOT; + case '*': + yylval.cptr = "*"; + return cpeek('=', EQOP, c); + case '%': + yylval.cptr = "%%"; + return cpeek('=', EQOP, c); + case '^': + yylval.cptr = "^"; + return cpeek('=', EQOP, c); + case '+': + ch = cpeek('=', EQOP, c); + if(ch == EQOP) { + yylval.cptr = "+"; + return ch; + } + return cpeek('+', INCR, c); + case '-': + ch = cpeek('=', EQOP, c); + if(ch == EQOP) { + yylval.cptr = "-"; + return ch; + } + return cpeek('-', DECR, c); + case '=': + return cpeek('=', EQ, '='); + case '<': + return cpeek('=', LE, '<'); + case '>': + return cpeek('=', GE, '>'); + case '!': + return cpeek('=', NE, '!'); + case '/': + ch = cpeek('=', EQOP, c); + if(ch == EQOP) { + yylval.cptr = "/"; + return ch; + } + if(peekc == '*') { + peekc = -1; + for(;;) { + ch = getch(); + if(ch == '*') { + peekc = getch(); + if(peekc == '/') { + peekc = -1; + goto restart; + } + } + } + } + return c; + case '"': + yylval.cptr = str; + while((c=getch()) != '"'){ + *str++ = c; + if(str >= &string[999]){ + yyerror("string space exceeded"); + getout(); + } + } + *str++ = 0; + return QSTR; + default: + return c; + } +} + +int +cpeek(int c, int yes, int no) +{ + + peekc = getch(); + if(peekc == c) { + peekc = -1; + return yes; + } + return no; +} + +int +getch(void) +{ + long ch; + +loop: + ch = peekc; + if(ch < 0){ + if(in == 0) + ch = -1; + else + ch = Bgetc(in); + } + peekc = -1; + if(ch >= 0) + return ch; + ifile++; + if(ifile > sargc) { + if(ifile >= sargc+2) + getout(); + in = &stdin; + Binit(in, 0, OREAD); + ln = 0; + goto loop; + } + Bterm(in); + if((in = Bopen(sargv[ifile], OREAD)) != 0){ + ln = 0; + ss = sargv[ifile]; + goto loop; + } + yyerror("cannot open input file"); + return 0; /* shut up ken */ +} + +int* +bundle(int a, ...) +{ + int i, *p, *q; + + p = &a; + i = *p++; + q = bsp_nxt; + if(bdebug) + fprint(2, "bundle %d elements at %lx\n", i, q); + while(i-- > 0) { + if(bsp_nxt >= &bspace[bsp_max]) + yyerror("bundling space exceeded"); + *bsp_nxt++ = *p++; + } + *bsp_nxt++ = 0; + yyval.iptr = q; + return q; +} + +void +routput(int *p) +{ + if(bdebug) + fprint(2, "routput(%lx)\n", p); + if(p >= &bspace[0] && p < &bspace[bsp_max]) { + /* part of a bundle */ + while(*p != 0) + routput((int*)(*p++)); + } else + Bprint(&stdout, (char*)p); /* character string */ +} + +void +output(int *p) +{ + routput(p); + bsp_nxt = &bspace[0]; + Bprint(&stdout, "\n"); + Bflush(&stdout); + cp = cary; + crs = rcrs; +} + +void +conout(int *p, char *s) +{ + Bprint(&stdout, "["); + routput(p); + Bprint(&stdout, "]s%s\n", s); + Bflush(&stdout); + lev--; +} + +void +yyerror(char *s, ...) +{ + if(ifile > sargc) + ss = "teletype"; + Bprint(&stdout, "c[%s on line %d, %s]pc\n", s, ln+1, ss); + Bflush(&stdout); + cp = cary; + crs = rcrs; + bindx = 0; + lev = 0; + bsp_nxt = &bspace[0]; +} + +void +pp(char *s) +{ + /* puts the relevant stuff on pre and post for the letter s */ + bundle(3, "S", s, pre); + pre = yyval.iptr; + bundle(4, post, "L", s, "s."); + post = yyval.iptr; +} + +void +tp(char *s) +{ + /* same as pp, but for temps */ + bundle(3, "0S", s, pre); + pre = yyval.iptr; + bundle(4, post, "L", s, "s."); + post = yyval.iptr; +} + +void +yyinit(int argc, char **argv) +{ + Binit(&stdout, 1, OWRITE); + sargv = argv; + sargc = argc - 1; + if(sargc == 0) { + in = &stdin; + Binit(in, 0, OREAD); + } else if((in = Bopen(sargv[1], OREAD)) == 0) + yyerror("cannot open input file"); + ifile = 1; + ln = 0; + ss = sargv[1]; +} + +void +getout(void) +{ + Bprint(&stdout, "q"); + Bflush(&stdout); + exits(0); +} + +int* +getf(char *p) +{ + return (int*)funtab[*p - 'a']; +} + +int* +geta(char *p) +{ + return (int*)atab[*p - 'a']; +} + +void +main(int argc, char **argv) +{ + int p[2]; + + while(argc > 1 && *argv[1] == '-') { + switch(argv[1][1]) { + case 'd': + bdebug++; + break; + case 'c': + cflag++; + break; + case 'l': + lflag++; + break; + case 's': + sflag++; + break; + default: + fprint(2, "Usage: bc [-l] [-c] [file ...]\n"); + exits("usage"); + } + argc--; + argv++; + } + if(lflag) { + argv--; + argc++; + argv[1] = "/sys/lib/bclib"; + } + if(cflag) { + yyinit(argc, argv); + for(;;) + yyparse(); + exits(0); + } + pipe(p); + if(fork() == 0) { + dup(p[1], 1); + close(p[0]); + close(p[1]); + yyinit(argc, argv); + for(;;) + yyparse(); + } + dup(p[0], 0); + close(p[0]); + close(p[1]); + execl("/bin/dc", "dc", 0); +} |