Blob
1 %{2 #include <u.h>3 #include <libc.h>4 #include <bio.h>6 #define bsp_max 50008 Biobuf *in;9 #define stdin bstdin10 #define stdout bstdout11 Biobuf stdin;12 Biobuf stdout;13 char cary[1000];14 char* cp = { cary };15 char string[1000];16 char* str = { string };17 int crs = 128;18 int rcrs = 128; /* reset crs */19 int bindx = 0;20 int lev = 0;21 int ln;22 int* ttp;23 char* ss = "";24 int bstack[10] = { 0 };25 char* numb[15] =26 {27 " 0", " 1", " 2", " 3", " 4", " 5",28 " 6", " 7", " 8", " 9", " 10", " 11",29 " 12", " 13", " 14"30 };31 int* pre;32 int* post;34 long peekc = -1;35 int sargc;36 int ifile;37 char** sargv;39 char *funtab[] =40 {41 "<1>","<2>","<3>","<4>","<5>",42 "<6>","<7>","<8>","<9>","<10>",43 "<11>","<12>","<13>","<14>","<15>",44 "<16>","<17>","<18>","<19>","<20>",45 "<21>","<22>","<23>","<24>","<25>",46 "<26>"47 };48 char *atab[] =49 {50 "<221>","<222>","<223>","<224>","<225>",51 "<226>","<227>","<228>","<229>","<230>",52 "<231>","<232>","<233>","<234>","<235>",53 "<236>","<237>","<238>","<239>","<240>",54 "<241>","<242>","<243>","<244>","<245>",55 "<246>"56 };57 char* letr[26] =58 {59 "a","b","c","d","e","f","g","h","i","j",60 "k","l","m","n","o","p","q","r","s","t",61 "u","v","w","x","y","z"62 };63 char* dot = { "." };64 int bspace[bsp_max];65 int* bsp_nxt = { bspace };66 int bdebug = 0;67 int lflag;68 int cflag;69 int sflag;71 int* bundle(int, ...);72 void conout(int*, char*);73 int cpeek(int, int, int);74 int getch(void);75 int* geta(char*);76 int* getf(char*);77 void getout(void);78 void output(int*);79 void pp(char*);80 void routput(int*);81 void tp(char*);82 void yyerror(char*, ...);83 int yyparse(void);85 typedef void* pointer;86 /* #pragma varargck type "lx" pointer */88 %}89 %union90 {91 int* iptr;92 char* cptr;93 int cc;94 }96 %type <iptr> pstat stat stat1 def slist dlets e ase nase97 %type <iptr> slist re fprefix cargs eora cons constant lora98 %type <cptr> crs100 %token <cptr> LETTER EQOP _AUTO DOT101 %token <cc> DIGIT SQRT LENGTH _IF FFF EQ102 %token <cc> _PRINT _WHILE _FOR NE LE GE INCR DECR103 %token <cc> _RETURN _BREAK _DEFINE BASE OBASE SCALE104 %token <cc> QSTR ERROR106 %right '=' EQOP107 %left '+' '-'108 %left '*' '/' '%'109 %right '^'110 %left UMINUS112 %%113 start:114 start stuff115 | stuff117 stuff:118 pstat tail119 {120 output($1);121 }122 | def dargs ')' '{' dlist slist '}'123 {124 ttp = bundle(6, pre, $6, post , "0", numb[lev], "Q");125 conout(ttp, (char*)$1);126 rcrs = crs;127 output((int*)""); /* this is horse puk!! */128 lev = bindx = 0;129 }131 dlist:132 tail133 | dlist _AUTO dlets tail135 stat:136 stat1137 | nase138 {139 if(sflag)140 bundle(2, $1, "s.");141 }143 pstat:144 stat1145 {146 if(sflag)147 bundle(2, $1, "0");148 }149 | nase150 {151 if(!sflag)152 bundle(2, $1, "ps.");153 }155 stat1:156 {157 bundle(1, "");158 }159 | ase160 {161 bundle(2, $1, "s.");162 }163 | SCALE '=' e164 {165 bundle(2, $3, "k");166 }167 | SCALE EQOP e168 {169 bundle(4, "K", $3, $2, "k");170 }171 | BASE '=' e172 {173 bundle(2, $3, "i");174 }175 | BASE EQOP e176 {177 bundle(4, "I", $3, $2, "i");178 }179 | OBASE '=' e180 {181 bundle(2, $3, "o");182 }183 | OBASE EQOP e184 {185 bundle(4, "O", $3, $2, "o");186 }187 | QSTR188 {189 bundle(3, "[", $1, "]P");190 }191 | _BREAK192 {193 bundle(2, numb[lev-bstack[bindx-1]], "Q");194 }195 | _PRINT e196 {197 bundle(2, $2, "ps.");198 }199 | _RETURN e200 {201 bundle(4, $2, post, numb[lev], "Q");202 }203 | _RETURN204 {205 bundle(4, "0", post, numb[lev], "Q");206 }207 | '{' slist '}'208 {209 $$ = $2;210 }211 | FFF212 {213 bundle(1, "fY");214 }215 | _IF crs BLEV '(' re ')' stat216 {217 conout($7, $2);218 bundle(3, $5, $2, " ");219 }220 | _WHILE crs '(' re ')' stat BLEV221 {222 bundle(3, $6, $4, $2);223 conout($$, $2);224 bundle(3, $4, $2, " ");225 }226 | fprefix crs re ';' e ')' stat BLEV227 {228 bundle(5, $7, $5, "s.", $3, $2);229 conout($$, $2);230 bundle(5, $1, "s.", $3, $2, " ");231 }232 | '~' LETTER '=' e233 {234 bundle(3, $4, "S", $2);235 }237 fprefix:238 _FOR '(' e ';'239 {240 $$ = $3;241 }243 BLEV:244 =245 {246 --bindx;247 }249 slist:250 stat251 | slist tail stat252 {253 bundle(2, $1, $3);254 }256 tail:257 '\n'258 {259 ln++;260 }261 | ';'263 re:264 e EQ e265 {266 $$ = bundle(3, $1, $3, "=");267 }268 | e '<' e269 {270 bundle(3, $1, $3, ">");271 }272 | e '>' e273 {274 bundle(3, $1, $3, "<");275 }276 | e NE e277 {278 bundle(3, $1, $3, "!=");279 }280 | e GE e281 {282 bundle(3, $1, $3, "!>");283 }284 | e LE e285 {286 bundle(3, $1, $3, "!<");287 }288 | e289 {290 bundle(2, $1, " 0!=");291 }293 nase:294 '(' e ')'295 {296 $$ = $2;297 }298 | cons299 {300 bundle(3, " ", $1, " ");301 }302 | DOT cons303 {304 bundle(3, " .", $2, " ");305 }306 | cons DOT cons307 {308 bundle(5, " ", $1, ".", $3, " ");309 }310 | cons DOT311 {312 bundle(4, " ", $1, ".", " ");313 }314 | DOT315 {316 $<cptr>$ = "l.";317 }318 | LETTER '[' e ']'319 {320 bundle(3, $3, ";", geta($1));321 }322 | LETTER INCR323 {324 bundle(4, "l", $1, "d1+s", $1);325 }326 | INCR LETTER327 {328 bundle(4, "l", $2, "1+ds", $2);329 }330 | DECR LETTER331 {332 bundle(4, "l", $2, "1-ds", $2);333 }334 | LETTER DECR335 {336 bundle(4, "l", $1, "d1-s", $1);337 }338 | LETTER '[' e ']' INCR339 {340 bundle(7, $3, ";", geta($1), "d1+" ,$3, ":" ,geta($1));341 }342 | INCR LETTER '[' e ']'343 {344 bundle(7, $4, ";", geta($2), "1+d", $4, ":", geta($2));345 }346 | LETTER '[' e ']' DECR347 {348 bundle(7, $3, ";", geta($1), "d1-", $3, ":", geta($1));349 }350 | DECR LETTER '[' e ']'351 {352 bundle(7, $4, ";", geta($2), "1-d", $4, ":" ,geta($2));353 }354 | SCALE INCR355 {356 bundle(1, "Kd1+k");357 }358 | INCR SCALE359 {360 bundle(1, "K1+dk");361 }362 | SCALE DECR363 {364 bundle(1, "Kd1-k");365 }366 | DECR SCALE367 {368 bundle(1, "K1-dk");369 }370 | BASE INCR371 {372 bundle(1, "Id1+i");373 }374 | INCR BASE375 {376 bundle(1, "I1+di");377 }378 | BASE DECR379 {380 bundle(1, "Id1-i");381 }382 | DECR BASE383 {384 bundle(1, "I1-di");385 }386 | OBASE INCR387 {388 bundle(1, "Od1+o");389 }390 | INCR OBASE391 {392 bundle(1, "O1+do");393 }394 | OBASE DECR395 {396 bundle(1, "Od1-o");397 }398 | DECR OBASE399 {400 bundle(1, "O1-do");401 }402 | LETTER '(' cargs ')'403 {404 bundle(4, $3, "l", getf($1), "x");405 }406 | LETTER '(' ')'407 {408 bundle(3, "l", getf($1), "x");409 }410 | LETTER = {411 bundle(2, "l", $1);412 }413 | LENGTH '(' e ')'414 {415 bundle(2, $3, "Z");416 }417 | SCALE '(' e ')'418 {419 bundle(2, $3, "X");420 }421 | '?'422 {423 bundle(1, "?");424 }425 | SQRT '(' e ')'426 {427 bundle(2, $3, "v");428 }429 | '~' LETTER430 {431 bundle(2, "L", $2);432 }433 | SCALE434 {435 bundle(1, "K");436 }437 | BASE438 {439 bundle(1, "I");440 }441 | OBASE442 {443 bundle(1, "O");444 }445 | '-' e446 {447 bundle(3, " 0", $2, "-");448 }449 | e '+' e450 {451 bundle(3, $1, $3, "+");452 }453 | e '-' e454 {455 bundle(3, $1, $3, "-");456 }457 | e '*' e458 {459 bundle(3, $1, $3, "*");460 }461 | e '/' e462 {463 bundle(3, $1, $3, "/");464 }465 | e '%' e466 {467 bundle(3, $1, $3, "%%");468 }469 | e '^' e470 {471 bundle(3, $1, $3, "^");472 }474 ase:475 LETTER '=' e476 {477 bundle(3, $3, "ds", $1);478 }479 | LETTER '[' e ']' '=' e480 {481 bundle(5, $6, "d", $3, ":", geta($1));482 }483 | LETTER EQOP e484 {485 bundle(6, "l", $1, $3, $2, "ds", $1);486 }487 | LETTER '[' e ']' EQOP e488 {489 bundle(9, $3, ";", geta($1), $6, $5, "d", $3, ":", geta($1));490 }492 e:493 ase494 | nase496 cargs:497 eora498 | cargs ',' eora499 {500 bundle(2, $1, $3);501 }503 eora:504 e505 | LETTER '[' ']'506 {507 bundle(2, "l", geta($1));508 }510 cons:511 constant512 {513 *cp++ = 0;514 }516 constant:517 '_'518 {519 $<cptr>$ = cp;520 *cp++ = '_';521 }522 | DIGIT523 {524 $<cptr>$ = cp;525 *cp++ = $1;526 }527 | constant DIGIT528 {529 *cp++ = $2;530 }532 crs:533 =534 {535 $$ = cp;536 *cp++ = '<';537 *cp++ = crs/100+'0';538 *cp++ = (crs%100)/10+'0';539 *cp++ = crs%10+'0';540 *cp++ = '>';541 *cp++ = '\0';542 if(crs++ >= 220) {543 yyerror("program too big");544 getout();545 }546 bstack[bindx++] = lev++;547 }549 def:550 _DEFINE LETTER '('551 {552 $$ = getf($2);553 pre = (int*)"";554 post = (int*)"";555 lev = 1;556 bindx = 0;557 bstack[bindx] = 0;558 }560 dargs:561 | lora562 {563 pp((char*)$1);564 }565 | dargs ',' lora566 {567 pp((char*)$3);568 }570 dlets:571 lora572 {573 tp((char*)$1);574 }575 | dlets ',' lora576 {577 tp((char*)$3);578 }580 lora:581 LETTER582 {583 $<cptr>$=$1;584 }585 | LETTER '[' ']'586 {587 $$ = geta($1);588 }590 %%592 int593 yylex(void)594 {595 int c, ch;597 restart:598 c = getch();599 peekc = -1;600 while(c == ' ' || c == '\t')601 c = getch();602 if(c == '\\') {603 getch();604 goto restart;605 }606 if(c >= 'a' && c <= 'z') {607 /* look ahead to look for reserved words */608 peekc = getch();609 if(peekc >= 'a' && peekc <= 'z') { /* must be reserved word */610 if(c=='p' && peekc=='r') {611 c = _PRINT;612 goto skip;613 }614 if(c=='i' && peekc=='f') {615 c = _IF;616 goto skip;617 }618 if(c=='w' && peekc=='h') {619 c = _WHILE;620 goto skip;621 }622 if(c=='f' && peekc=='o') {623 c = _FOR;624 goto skip;625 }626 if(c=='s' && peekc=='q') {627 c = SQRT;628 goto skip;629 }630 if(c=='r' && peekc=='e') {631 c = _RETURN;632 goto skip;633 }634 if(c=='b' && peekc=='r') {635 c = _BREAK;636 goto skip;637 }638 if(c=='d' && peekc=='e') {639 c = _DEFINE;640 goto skip;641 }642 if(c=='s' && peekc=='c') {643 c = SCALE;644 goto skip;645 }646 if(c=='b' && peekc=='a') {647 c = BASE;648 goto skip;649 }650 if(c=='i' && peekc=='b') {651 c = BASE;652 goto skip;653 }654 if(c=='o' && peekc=='b') {655 c = OBASE;656 goto skip;657 }658 if(c=='d' && peekc=='i') {659 c = FFF;660 goto skip;661 }662 if(c=='a' && peekc=='u') {663 c = _AUTO;664 goto skip;665 }666 if(c=='l' && peekc=='e') {667 c = LENGTH;668 goto skip;669 }670 if(c=='q' && peekc=='u')671 getout();672 /* could not be found */673 return ERROR;675 skip: /* skip over rest of word */676 peekc = -1;677 for(;;) {678 ch = getch();679 if(ch < 'a' || ch > 'z')680 break;681 }682 peekc = ch;683 return c;684 }686 /* usual case; just one single letter */687 yylval.cptr = letr[c-'a'];688 return LETTER;689 }690 if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {691 yylval.cc = c;692 return DIGIT;693 }694 switch(c) {695 case '.':696 return DOT;697 case '*':698 yylval.cptr = "*";699 return cpeek('=', EQOP, c);700 case '%':701 yylval.cptr = "%%";702 return cpeek('=', EQOP, c);703 case '^':704 yylval.cptr = "^";705 return cpeek('=', EQOP, c);706 case '+':707 ch = cpeek('=', EQOP, c);708 if(ch == EQOP) {709 yylval.cptr = "+";710 return ch;711 }712 return cpeek('+', INCR, c);713 case '-':714 ch = cpeek('=', EQOP, c);715 if(ch == EQOP) {716 yylval.cptr = "-";717 return ch;718 }719 return cpeek('-', DECR, c);720 case '=':721 return cpeek('=', EQ, '=');722 case '<':723 return cpeek('=', LE, '<');724 case '>':725 return cpeek('=', GE, '>');726 case '!':727 return cpeek('=', NE, '!');728 case '/':729 ch = cpeek('=', EQOP, c);730 if(ch == EQOP) {731 yylval.cptr = "/";732 return ch;733 }734 if(peekc == '*') {735 peekc = -1;736 for(;;) {737 ch = getch();738 if(ch == '*') {739 peekc = getch();740 if(peekc == '/') {741 peekc = -1;742 goto restart;743 }744 }745 }746 }747 return c;748 case '"':749 yylval.cptr = str;750 while((c=getch()) != '"'){751 *str++ = c;752 if(str >= &string[999]){753 yyerror("string space exceeded");754 getout();755 }756 }757 *str++ = 0;758 return QSTR;759 default:760 return c;761 }762 }764 int765 cpeek(int c, int yes, int no)766 {768 peekc = getch();769 if(peekc == c) {770 peekc = -1;771 return yes;772 }773 return no;774 }776 int777 getch(void)778 {779 long ch;781 loop:782 ch = peekc;783 if(ch < 0){784 if(in == 0)785 ch = -1;786 else787 ch = Bgetc(in);788 }789 peekc = -1;790 if(ch >= 0)791 return ch;792 ifile++;793 if(ifile > sargc) {794 if(ifile >= sargc+2)795 getout();796 in = &stdin;797 Binit(in, 0, OREAD);798 ln = 0;799 goto loop;800 }801 Bterm(in);802 if((in = Bopen(sargv[ifile], OREAD)) != 0){803 ln = 0;804 ss = sargv[ifile];805 goto loop;806 }807 yyerror("cannot open input file");808 return 0; /* shut up ken */809 }811 int*812 bundle(int a, ...)813 {814 int i, *p, *q;816 p = &a;817 i = *p++;818 q = bsp_nxt;819 if(bdebug)820 fprint(2, "bundle %d elements at %lx\n", i, q);821 while(i-- > 0) {822 if(bsp_nxt >= &bspace[bsp_max])823 yyerror("bundling space exceeded");824 *bsp_nxt++ = *p++;825 }826 *bsp_nxt++ = 0;827 yyval.iptr = q;828 return q;829 }831 void832 routput(int *p)833 {834 if(bdebug)835 fprint(2, "routput(%lx)\n", p);836 if(p >= &bspace[0] && p < &bspace[bsp_max]) {837 /* part of a bundle */838 while(*p != 0)839 routput((int*)(*p++));840 } else841 Bprint(&stdout, (char*)p); /* character string */842 }844 void845 output(int *p)846 {847 routput(p);848 bsp_nxt = &bspace[0];849 Bprint(&stdout, "\n");850 Bflush(&stdout);851 cp = cary;852 crs = rcrs;853 }855 void856 conout(int *p, char *s)857 {858 Bprint(&stdout, "[");859 routput(p);860 Bprint(&stdout, "]s%s\n", s);861 Bflush(&stdout);862 lev--;863 }865 void866 yyerror(char *s, ...)867 {868 if(ifile > sargc)869 ss = "teletype";870 Bprint(&stdout, "c[%s on line %d, %s]pc\n", s, ln+1, ss);871 Bflush(&stdout);872 cp = cary;873 crs = rcrs;874 bindx = 0;875 lev = 0;876 bsp_nxt = &bspace[0];877 }879 void880 pp(char *s)881 {882 /* puts the relevant stuff on pre and post for the letter s */883 bundle(3, "S", s, pre);884 pre = yyval.iptr;885 bundle(4, post, "L", s, "s.");886 post = yyval.iptr;887 }889 void890 tp(char *s)891 {892 /* same as pp, but for temps */893 bundle(3, "0S", s, pre);894 pre = yyval.iptr;895 bundle(4, post, "L", s, "s.");896 post = yyval.iptr;897 }899 void900 yyinit(int argc, char **argv)901 {902 Binit(&stdout, 1, OWRITE);903 sargv = argv;904 sargc = argc - 1;905 if(sargc == 0) {906 in = &stdin;907 Binit(in, 0, OREAD);908 } else if((in = Bopen(sargv[1], OREAD)) == 0)909 yyerror("cannot open input file");910 ifile = 1;911 ln = 0;912 ss = sargv[1];913 }915 void916 getout(void)917 {918 Bprint(&stdout, "q");919 Bflush(&stdout);920 exits(0);921 }923 int*924 getf(char *p)925 {926 return (int*)funtab[*p - 'a'];927 }929 int*930 geta(char *p)931 {932 return (int*)atab[*p - 'a'];933 }935 void936 main(int argc, char **argv)937 {938 int p[2];940 while(argc > 1 && *argv[1] == '-') {941 switch(argv[1][1]) {942 case 'd':943 bdebug++;944 break;945 case 'c':946 cflag++;947 break;948 case 'l':949 lflag++;950 break;951 case 's':952 sflag++;953 break;954 default:955 fprint(2, "Usage: bc [-l] [-c] [file ...]\n");956 exits("usage");957 }958 argc--;959 argv++;960 }961 if(lflag) {962 argv--;963 argc++;964 argv[1] = "/sys/lib/bclib";965 }966 if(cflag) {967 yyinit(argc, argv);968 for(;;)969 yyparse();970 exits(0);971 }972 pipe(p);973 if(fork() == 0) {974 dup(p[1], 1);975 close(p[0]);976 close(p[1]);977 yyinit(argc, argv);978 for(;;)979 yyparse();980 }981 dup(p[0], 0);982 close(p[0]);983 close(p[1]);984 execlp("dc", "dc", 0);985 }