aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/bc.y
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-04-21 23:22:06 +0000
committerrsc <devnull@localhost>2004-04-21 23:22:06 +0000
commit17e5fb8973d9e48ef53a88eb78f845f8a7b41a5b (patch)
tree921c649de0d83bdde4561f5868e5ff3ab9986af8 /src/cmd/bc.y
parent3e63e5c271f7a7013dc4b3fedfb83c2d547b8c26 (diff)
downloadplan9port-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.y983
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);
+}