123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989 |
- %{
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #define bsp_max 5000
- Biobuf *in;
- Biobuf bstdin;
- Biobuf bstdout;
- 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;
- char* 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"
- };
- char* pre;
- char* 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 = { "." };
- char* bspace[bsp_max];
- char** bsp_nxt = bspace;
- int bdebug = 0;
- int lflag;
- int cflag;
- int sflag;
- char* bundle(int, ...);
- void conout(char*, char*);
- int cpeek(int, int, int);
- int getch(void);
- char* geta(char*);
- char* getf(char*);
- void getout(void);
- void output(char*);
- void pp(char*);
- void routput(char*);
- void tp(char*);
- void yyerror(char*, ...);
- int yyparse(void);
- typedef void* pointer;
- #pragma varargck type "lx" pointer
- %}
- %union
- {
- char* cptr;
- int cc;
- }
- %type <cptr> pstat stat stat1 def slist dlets e ase nase
- %type <cptr> 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("");
- 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 = (char*)"";
- post = (char*)"";
- 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 = &bstdin;
- Binit(in, 0, OREAD);
- ln = 0;
- goto loop;
- }
- if(in)
- 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 */
- }
- char*
- bundle(int a, ...)
- {
- int i;
- char **q;
- va_list arg;
-
- i = a;
- va_start(arg, a);
- 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++ = va_arg(arg, char*);
- }
- *bsp_nxt++ = 0;
- va_end(arg);
- yyval.cptr = (char*)q;
- return (char*)q;
- }
- void
- routput(char *p)
- {
- char **pp;
-
- if(bdebug)
- fprint(2, "routput(%lx)\n", p);
- if((char**)p >= &bspace[0] && (char**)p < &bspace[bsp_max]) {
- /* part of a bundle */
- pp = (char**)p;
- while(*pp != 0)
- routput(*pp++);
- } else
- Bprint(&bstdout, p); /* character string */
- }
- void
- output(char *p)
- {
- routput(p);
- bsp_nxt = &bspace[0];
- Bprint(&bstdout, "\n");
- Bflush(&bstdout);
- cp = cary;
- crs = rcrs;
- }
- void
- conout(char *p, char *s)
- {
- Bprint(&bstdout, "[");
- routput(p);
- Bprint(&bstdout, "]s%s\n", s);
- Bflush(&bstdout);
- lev--;
- }
- void
- yyerror(char *s, ...)
- {
- if(ifile > sargc)
- ss = "stdin";
- Bprint(&bstdout, "c[%s:%d %s]pc\n", ss, ln+1, s);
- Bflush(&bstdout);
- 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.cptr;
- bundle(4, post, "L", s, "s.");
- post = yyval.cptr;
- }
- void
- tp(char *s)
- {
- /* same as pp, but for temps */
- bundle(3, "0S", s, pre);
- pre = yyval.cptr;
- bundle(4, post, "L", s, "s.");
- post = yyval.cptr;
- }
- void
- yyinit(int argc, char **argv)
- {
- Binit(&bstdout, 1, OWRITE);
- sargv = argv;
- sargc = argc - 1;
- if(sargc == 0) {
- in = &bstdin;
- 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(&bstdout, "q");
- Bflush(&bstdout);
- exits(0);
- }
- char*
- getf(char *p)
- {
- return funtab[*p - 'a'];
- }
- char*
- geta(char *p)
- {
- return 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 [-cdls] [file ...]\n");
- exits("usage");
- }
- argc--;
- argv++;
- }
- if(lflag) {
- argv--;
- argc++;
- argv[1] = "/sys/lib/bclib";
- }
- if(cflag) {
- yyinit(argc, argv);
- for(;;)
- yyparse();
- /* not reached */
- }
- 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", nil);
- }
|