bc.y - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       bc.y (13425B)
       ---
            1 %{
            2         #include        <u.h>
            3         #include        <libc.h>
            4         #include        <bio.h>
            5 
            6         #define        bsp_max        5000
            7 
            8         Biobuf        *in;
            9         Biobuf        bstdin;
           10         Biobuf        bstdout;
           11         char        cary[1000];
           12         char*        cp = { cary };
           13         char        string[1000];
           14         char*        str = { string };
           15         int        crs = 128;
           16         int        rcrs = 128;        /* reset crs */
           17         int        bindx = 0;
           18         int        lev = 0;
           19         int        ln;
           20         char*        ttp;
           21         char*        ss = "";
           22         int        bstack[10] = { 0 };
           23         char*        numb[15] =
           24         {
           25                 " 0", " 1", " 2", " 3", " 4", " 5",
           26                 " 6", " 7", " 8", " 9", " 10", " 11",
           27                 " 12", " 13", " 14"
           28         };
           29         char*        pre;
           30         char*        post;
           31 
           32         long        peekc = -1;
           33         int        sargc;
           34         int        ifile;
           35         char**        sargv;
           36 
           37         char        *funtab[] =
           38         {
           39                 "<1>","<2>","<3>","<4>","<5>",
           40                 "<6>","<7>","<8>","<9>","<10>",
           41                 "<11>","<12>","<13>","<14>","<15>",
           42                 "<16>","<17>","<18>","<19>","<20>",
           43                 "<21>","<22>","<23>","<24>","<25>",
           44                 "<26>"
           45         };
           46         char        *atab[] =
           47         {
           48                 "<221>","<222>","<223>","<224>","<225>",
           49                 "<226>","<227>","<228>","<229>","<230>",
           50                 "<231>","<232>","<233>","<234>","<235>",
           51                 "<236>","<237>","<238>","<239>","<240>",
           52                 "<241>","<242>","<243>","<244>","<245>",
           53                 "<246>"
           54         };
           55         char*        letr[26] =
           56         {
           57                 "a","b","c","d","e","f","g","h","i","j",
           58                 "k","l","m","n","o","p","q","r","s","t",
           59                 "u","v","w","x","y","z"
           60         };
           61         char*        dot = { "." };
           62         char*        bspace[bsp_max];
           63         char**        bsp_nxt = bspace;
           64         int        bdebug = 0;
           65         int        lflag;
           66         int        cflag;
           67         int        sflag;
           68 
           69         char*        bundle(int, ...);
           70         void        conout(char*, char*);
           71         int        cpeek(int, int, int);
           72         int        getch(void);
           73         char*        geta(char*);
           74         char*        getf(char*);
           75         void        getout(void);
           76         void        output(char*);
           77         void        pp(char*);
           78         void        routput(char*);
           79         void        tp(char*);
           80         void        yyerror(char*, ...);
           81         int        yyparse(void);
           82 
           83         typedef        void*        pointer;
           84         #pragma        varargck        type        "lx"        pointer
           85 
           86 %}
           87 %union
           88 {
           89         char*        cptr;
           90         int        cc;
           91 }
           92 
           93 %type        <cptr>        pstat stat stat1 def slist dlets e ase nase
           94 %type        <cptr>        slist re fprefix cargs eora cons constant lora
           95 %type        <cptr>        crs
           96 
           97 %token        <cptr>        LETTER EQOP _AUTO DOT
           98 %token        <cc>        DIGIT SQRT LENGTH _IF FFF EQ
           99 %token        <cc>        _PRINT _WHILE _FOR NE LE GE INCR DECR
          100 %token        <cc>        _RETURN _BREAK _DEFINE BASE OBASE SCALE
          101 %token        <cc>        QSTR ERROR
          102 
          103 %right        '=' EQOP
          104 %left        '+' '-'
          105 %left        '*' '/' '%'
          106 %right        '^'
          107 %left        UMINUS
          108 
          109 %%
          110 start:
          111         start stuff
          112 |        stuff
          113 
          114 stuff:
          115         pstat tail
          116         {
          117                 output($1);
          118         }
          119 |        def dargs ')' '{' dlist slist '}'
          120         {
          121                 ttp = bundle(6, pre, $6, post , "0", numb[lev], "Q");
          122                 conout(ttp, (char*)$1);
          123                 rcrs = crs;
          124                 output("");
          125                 lev = bindx = 0;
          126         }
          127 
          128 dlist:
          129         tail
          130 |        dlist _AUTO dlets tail
          131 
          132 stat:
          133         stat1
          134 |        nase
          135         {
          136                 if(sflag)
          137                         bundle(2, $1, "s.");
          138         }
          139 
          140 pstat:
          141         stat1
          142         {
          143                 if(sflag)
          144                         bundle(2, $1, "0");
          145         }
          146 |        nase
          147         {
          148                 if(!sflag)
          149                         bundle(2, $1, "ps.");
          150         }
          151 
          152 stat1:
          153         {
          154                 bundle(1, "");
          155         }
          156 |        ase
          157         {
          158                 bundle(2, $1, "s.");
          159         }
          160 |        SCALE '=' e
          161         {
          162                 bundle(2, $3, "k");
          163         }
          164 |        SCALE EQOP e
          165         {
          166                 bundle(4, "K", $3, $2, "k");
          167         }
          168 |        BASE '=' e
          169         {
          170                 bundle(2, $3, "i");
          171         }
          172 |        BASE EQOP e
          173         {
          174                 bundle(4, "I", $3, $2, "i");
          175         }
          176 |        OBASE '=' e
          177         {
          178                 bundle(2, $3, "o");
          179         }
          180 |        OBASE EQOP e
          181         {
          182                 bundle(4, "O", $3, $2, "o");
          183         }
          184 |        QSTR
          185         {
          186                 bundle(3, "[", $1, "]P");
          187         }
          188 |        _BREAK
          189         {
          190                 bundle(2, numb[lev-bstack[bindx-1]], "Q");
          191         }
          192 |        _PRINT e
          193         {
          194                 bundle(2, $2, "ps.");
          195         }
          196 |        _RETURN e
          197         {
          198                 bundle(4, $2, post, numb[lev], "Q");
          199         }
          200 |        _RETURN
          201         {
          202                 bundle(4, "0", post, numb[lev], "Q");
          203         }
          204 |        '{' slist '}'
          205         {
          206                 $$ = $2;
          207         }
          208 |        FFF
          209         {
          210                 bundle(1, "fY");
          211         }
          212 |        _IF crs BLEV '(' re ')' stat
          213         {
          214                 conout($7, $2);
          215                 bundle(3, $5, $2, " ");
          216         }
          217 |        _WHILE crs '(' re ')' stat BLEV
          218         {
          219                 bundle(3, $6, $4, $2);
          220                 conout($$, $2);
          221                 bundle(3, $4, $2, " ");
          222         }
          223 |        fprefix crs re ';' e ')' stat BLEV
          224         {
          225                 bundle(5, $7, $5, "s.", $3, $2);
          226                 conout($$, $2);
          227                 bundle(5, $1, "s.", $3, $2, " ");
          228         }
          229 |        '~' LETTER '=' e
          230         {
          231                 bundle(3, $4, "S", $2);
          232         }
          233 
          234 fprefix:
          235         _FOR '(' e ';'
          236         {
          237                 $$ = $3;
          238         }
          239 
          240 BLEV:
          241         =
          242         {
          243                 --bindx;
          244         }
          245 
          246 slist:
          247         stat
          248 |        slist tail stat
          249         {
          250                 bundle(2, $1, $3);
          251         }
          252 
          253 tail:
          254         '\n'
          255         {
          256                 ln++;
          257         }
          258 |        ';'
          259 
          260 re:
          261         e EQ e
          262         {
          263                 $$ = bundle(3, $1, $3, "=");
          264         }
          265 |        e '<' e
          266         {
          267                 bundle(3, $1, $3, ">");
          268         }
          269 |        e '>' e
          270         {
          271                 bundle(3, $1, $3, "<");
          272         }
          273 |        e NE e
          274         {
          275                 bundle(3, $1, $3, "!=");
          276         }
          277 |        e GE e
          278         {
          279                 bundle(3, $1, $3, "!>");
          280         }
          281 |        e LE e
          282         {
          283                 bundle(3, $1, $3, "!<");
          284         }
          285 |        e
          286         {
          287                 bundle(2, $1, " 0!=");
          288         }
          289 
          290 nase:
          291         '(' e ')'
          292         {
          293                 $$ = $2;
          294         }
          295 |        cons
          296         {
          297                 bundle(3, " ", $1, " ");
          298         }
          299 |        DOT cons
          300         {
          301                 bundle(3, " .", $2, " ");
          302         }
          303 |        cons DOT cons
          304         {
          305                 bundle(5, " ", $1, ".", $3, " ");
          306         }
          307 |        cons DOT
          308         {
          309                 bundle(4, " ", $1, ".", " ");
          310         }
          311 |        DOT
          312         {
          313                 $<cptr>$ = "l.";
          314         }
          315 |        LETTER '[' e ']'
          316         {
          317                 bundle(3, $3, ";", geta($1));
          318         }
          319 |        LETTER INCR
          320         {
          321                 bundle(4, "l", $1, "d1+s", $1);
          322         }
          323 |        INCR LETTER
          324         {
          325                 bundle(4, "l", $2, "1+ds", $2);
          326         }
          327 |        DECR LETTER
          328         {
          329                 bundle(4, "l", $2, "1-ds", $2);
          330         }
          331 |        LETTER DECR
          332         {
          333                 bundle(4, "l", $1, "d1-s", $1);
          334         }
          335 |        LETTER '[' e ']' INCR
          336         {
          337                 bundle(7, $3, ";", geta($1), "d1+" ,$3, ":" ,geta($1));
          338         }
          339 |        INCR LETTER '[' e ']'
          340         {
          341                 bundle(7, $4, ";", geta($2), "1+d", $4, ":", geta($2));
          342         }
          343 |        LETTER '[' e ']' DECR
          344         {
          345                 bundle(7, $3, ";", geta($1), "d1-", $3, ":", geta($1));
          346         }
          347 |        DECR LETTER '[' e ']'
          348         {
          349                 bundle(7, $4, ";", geta($2), "1-d", $4, ":" ,geta($2));
          350         }
          351 |        SCALE INCR
          352         {
          353                 bundle(1, "Kd1+k");
          354         }
          355 |        INCR SCALE
          356         {
          357                 bundle(1, "K1+dk");
          358         }
          359 |        SCALE DECR
          360         {
          361                 bundle(1, "Kd1-k");
          362         }
          363 |        DECR SCALE
          364         {
          365                 bundle(1, "K1-dk");
          366         }
          367 |        BASE INCR
          368         {
          369                 bundle(1, "Id1+i");
          370         }
          371 |        INCR BASE
          372         {
          373                 bundle(1, "I1+di");
          374         }
          375 |        BASE DECR
          376         {
          377                 bundle(1, "Id1-i");
          378         }
          379 |        DECR BASE
          380         {
          381                 bundle(1, "I1-di");
          382         }
          383 |        OBASE INCR
          384         {
          385                 bundle(1, "Od1+o");
          386         }
          387 |        INCR OBASE
          388         {
          389                 bundle(1, "O1+do");
          390         }
          391 |        OBASE DECR
          392         {
          393                 bundle(1, "Od1-o");
          394         }
          395 |        DECR OBASE
          396         {
          397                 bundle(1, "O1-do");
          398         }
          399 |        LETTER '(' cargs ')'
          400         {
          401                 bundle(4, $3, "l", getf($1), "x");
          402         }
          403 |        LETTER '(' ')'
          404         {
          405                 bundle(3, "l", getf($1), "x");
          406         }
          407 |        LETTER = {
          408                 bundle(2, "l", $1);
          409         }
          410 |        LENGTH '(' e ')'
          411         {
          412                 bundle(2, $3, "Z");
          413         }
          414 |        SCALE '(' e ')'
          415         {
          416                 bundle(2, $3, "X");
          417         }
          418 |        '?'
          419         {
          420                 bundle(1, "?");
          421         }
          422 |        SQRT '(' e ')'
          423         {
          424                 bundle(2, $3, "v");
          425         }
          426 |        '~' LETTER
          427         {
          428                 bundle(2, "L", $2);
          429         }
          430 |        SCALE
          431         {
          432                 bundle(1, "K");
          433         }
          434 |        BASE
          435         {
          436                 bundle(1, "I");
          437         }
          438 |        OBASE
          439         {
          440                 bundle(1, "O");
          441         }
          442 |        '-' e
          443         {
          444                 bundle(3, " 0", $2, "-");
          445         }
          446 |        e '+' e
          447         {
          448                 bundle(3, $1, $3, "+");
          449         }
          450 |        e '-' e
          451         {
          452                 bundle(3, $1, $3, "-");
          453         }
          454 |        e '*' e
          455         {
          456                 bundle(3, $1, $3, "*");
          457         }
          458 |        e '/' e
          459         {
          460                 bundle(3, $1, $3, "/");
          461         }
          462 |        e '%' e
          463         {
          464                 bundle(3, $1, $3, "%%");
          465         }
          466 |        e '^' e
          467         {
          468                 bundle(3, $1, $3, "^");
          469         }
          470 
          471 ase:
          472         LETTER '=' e
          473         {
          474                 bundle(3, $3, "ds", $1);
          475         }
          476 |        LETTER '[' e ']' '=' e
          477         {
          478                 bundle(5, $6, "d", $3, ":", geta($1));
          479         }
          480 |        LETTER EQOP e
          481         {
          482                 bundle(6, "l", $1, $3, $2, "ds", $1);
          483         }
          484 |        LETTER '[' e ']' EQOP e
          485         {
          486                 bundle(9, $3, ";", geta($1), $6, $5, "d", $3, ":", geta($1));
          487         }
          488 
          489 e:
          490         ase
          491 |        nase
          492 
          493 cargs:
          494         eora
          495 |        cargs ',' eora
          496         {
          497                 bundle(2, $1, $3);
          498         }
          499 
          500 eora:
          501         e
          502 |        LETTER '[' ']'
          503         {
          504                 bundle(2, "l", geta($1));
          505         }
          506 
          507 cons:
          508         constant
          509         {
          510                 *cp++ = 0;
          511         }
          512 
          513 constant:
          514         '_'
          515         {
          516                 $<cptr>$ = cp;
          517                 *cp++ = '_';
          518         }
          519 |        DIGIT
          520         {
          521                 $<cptr>$ = cp;
          522                 *cp++ = $1;
          523         }
          524 |        constant DIGIT
          525         {
          526                 *cp++ = $2;
          527         }
          528 
          529 crs:
          530         =
          531         {
          532                 $$ = cp;
          533                 *cp++ = '<';
          534                 *cp++ = crs/100+'0';
          535                 *cp++ = (crs%100)/10+'0';
          536                 *cp++ = crs%10+'0';
          537                 *cp++ = '>';
          538                 *cp++ = '\0';
          539                 if(crs++ >= 220) {
          540                         yyerror("program too big");
          541                         getout();
          542                 }
          543                 bstack[bindx++] = lev++;
          544         }
          545 
          546 def:
          547         _DEFINE LETTER '('
          548         {
          549                 $$ = getf($2);
          550                 pre = (char*)"";
          551                 post = (char*)"";
          552                 lev = 1;
          553                 bindx = 0;
          554                 bstack[bindx] = 0;
          555         }
          556 
          557 dargs:
          558 |        lora
          559         {
          560                 pp((char*)$1);
          561         }
          562 |        dargs ',' lora
          563         {
          564                 pp((char*)$3);
          565         }
          566 
          567 dlets:
          568         lora
          569         {
          570                 tp((char*)$1);
          571         }
          572 |        dlets ',' lora
          573         {
          574                 tp((char*)$3);
          575         }
          576 
          577 lora:
          578         LETTER
          579         {
          580                 $<cptr>$=$1;
          581         }
          582 |        LETTER '[' ']'
          583         {
          584                 $$ = geta($1);
          585         }
          586 
          587 %%
          588 
          589 int
          590 yylex(void)
          591 {
          592         int c, ch;
          593 
          594 restart:
          595         c = getch();
          596         peekc = -1;
          597         while(c == ' ' || c == '\t')
          598                 c = getch();
          599         if(c == '\\') {
          600                 getch();
          601                 goto restart;
          602         }
          603         if(c >= 'a' && c <= 'z') {
          604                 /* look ahead to look for reserved words */
          605                 peekc = getch();
          606                 if(peekc >= 'a' && peekc <= 'z') { /* must be reserved word */
          607                         if(c=='p' && peekc=='r') {
          608                                 c = _PRINT;
          609                                 goto skip;
          610                         }
          611                         if(c=='i' && peekc=='f') {
          612                                 c = _IF;
          613                                 goto skip;
          614                         }
          615                         if(c=='w' && peekc=='h') {
          616                                 c = _WHILE;
          617                                 goto skip;
          618                         }
          619                         if(c=='f' && peekc=='o') {
          620                                 c = _FOR;
          621                                 goto skip;
          622                         }
          623                         if(c=='s' && peekc=='q') {
          624                                 c = SQRT;
          625                                 goto skip;
          626                         }
          627                         if(c=='r' && peekc=='e') {
          628                                 c = _RETURN;
          629                                 goto skip;
          630                         }
          631                         if(c=='b' && peekc=='r') {
          632                                 c = _BREAK;
          633                                 goto skip;
          634                         }
          635                         if(c=='d' && peekc=='e') {
          636                                 c = _DEFINE;
          637                                 goto skip;
          638                         }
          639                         if(c=='s' && peekc=='c') {
          640                                 c = SCALE;
          641                                 goto skip;
          642                         }
          643                         if(c=='b' && peekc=='a') {
          644                                 c = BASE;
          645                                 goto skip;
          646                         }
          647                         if(c=='i' && peekc=='b') {
          648                                 c = BASE;
          649                                 goto skip;
          650                         }
          651                         if(c=='o' && peekc=='b') {
          652                                 c = OBASE;
          653                                 goto skip;
          654                         }
          655                         if(c=='d' && peekc=='i') {
          656                                 c = FFF;
          657                                 goto skip;
          658                         }
          659                         if(c=='a' && peekc=='u') {
          660                                 c = _AUTO;
          661                                 goto skip;
          662                         }
          663                         if(c=='l' && peekc=='e') {
          664                                 c = LENGTH;
          665                                 goto skip;
          666                         }
          667                         if(c=='q' && peekc=='u')
          668                                 getout();
          669                         /* could not be found */
          670                         return ERROR;
          671 
          672                 skip:        /* skip over rest of word */
          673                         peekc = -1;
          674                         for(;;) {
          675                                 ch = getch();
          676                                 if(ch < 'a' || ch > 'z')
          677                                         break;
          678                         }
          679                         peekc = ch;
          680                         return c;
          681                 }
          682 
          683                 /* usual case; just one single letter */
          684                 yylval.cptr = letr[c-'a'];
          685                 return LETTER;
          686         }
          687         if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
          688                 yylval.cc = c;
          689                 return DIGIT;
          690         }
          691         switch(c) {
          692         case '.':
          693                 return DOT;
          694         case '*':
          695                 yylval.cptr = "*";
          696                 return cpeek('=', EQOP, c);
          697         case '%':
          698                 yylval.cptr = "%%";
          699                 return cpeek('=', EQOP, c);
          700         case '^':
          701                 yylval.cptr = "^";
          702                 return cpeek('=', EQOP, c);
          703         case '+':
          704                 ch = cpeek('=', EQOP, c);
          705                 if(ch == EQOP) {
          706                         yylval.cptr = "+";
          707                         return ch;
          708                 }
          709                 return cpeek('+', INCR, c);
          710         case '-':
          711                 ch = cpeek('=', EQOP, c);
          712                 if(ch == EQOP) {
          713                         yylval.cptr = "-";
          714                         return ch;
          715                 }
          716                 return cpeek('-', DECR, c);
          717         case '=':
          718                 return cpeek('=', EQ, '=');
          719         case '<':
          720                 return cpeek('=', LE, '<');
          721         case '>':
          722                 return cpeek('=', GE, '>');
          723         case '!':
          724                 return cpeek('=', NE, '!');
          725         case '/':
          726                 ch = cpeek('=', EQOP, c);
          727                 if(ch == EQOP) {
          728                         yylval.cptr = "/";
          729                         return ch;
          730                 }
          731                 if(peekc == '*') {
          732                         peekc = -1;
          733                         for(;;) {
          734                                 ch = getch();
          735                                 if(ch == '*') {
          736                                         peekc = getch();
          737                                         if(peekc == '/') {
          738                                                 peekc = -1;
          739                                                 goto restart;
          740                                         }
          741                                 }
          742                         }
          743                 }
          744                 return c;
          745         case '"':
          746                 yylval.cptr = str;
          747                 while((c=getch()) != '"'){
          748                         *str++ = c;
          749                         if(str >= &string[999]){
          750                                 yyerror("string space exceeded");
          751                                 getout();
          752                         }
          753                 }
          754                 *str++ = 0;
          755                 return QSTR;
          756         default:
          757                 return c;
          758         }
          759 }
          760 
          761 int
          762 cpeek(int c, int yes, int no)
          763 {
          764 
          765         peekc = getch();
          766         if(peekc == c) {
          767                 peekc = -1;
          768                 return yes;
          769         }
          770         return no;
          771 }
          772 
          773 int
          774 getch(void)
          775 {
          776         long ch;
          777 
          778 loop:
          779         ch = peekc;
          780         if(ch < 0){
          781                 if(in == 0)
          782                         ch = -1;
          783                 else
          784                         ch = Bgetc(in);
          785         }
          786         peekc = -1;
          787         if(ch >= 0)
          788                 return ch;
          789 
          790         ifile++;
          791         if(ifile >= sargc) {
          792                 if(ifile >= sargc+1)
          793                         getout();
          794                 in = &bstdin;
          795                 Binit(in, 0, OREAD);
          796                 ln = 0;
          797                 goto loop;
          798         }
          799         if(in)
          800                 Bterm(in);
          801         if((in = Bopen(sargv[ifile], OREAD)) != 0){
          802                 ln = 0;
          803                 ss = sargv[ifile];
          804                 goto loop;
          805         }
          806         fprint(2, "open %s: %r\n", sargv[ifile]);
          807         yyerror("cannot open input file");
          808         return 0;                /* shut up ken */
          809 }
          810 
          811 char*
          812 bundle(int a, ...)
          813 {
          814         int i;
          815         char **q;
          816         va_list arg;
          817         
          818         i = a;
          819         va_start(arg, a);
          820         q = bsp_nxt;
          821         if(bdebug)
          822                 fprint(2, "bundle %d elements at %lx\n", i, q);
          823         while(i-- > 0) {
          824                 if(bsp_nxt >= &bspace[bsp_max])
          825                         yyerror("bundling space exceeded");
          826                 *bsp_nxt++ = va_arg(arg, char*);
          827         }
          828         *bsp_nxt++ = 0;
          829         va_end(arg);
          830         yyval.cptr = (char*)q;
          831         return (char*)q;
          832 }
          833 
          834 void
          835 routput(char *p)
          836 {
          837         char **pp;
          838         
          839         if(bdebug)
          840                 fprint(2, "routput(%lx)\n", p);
          841         if((char**)p >= &bspace[0] && (char**)p < &bspace[bsp_max]) {
          842                 /* part of a bundle */
          843                 pp = (char**)p;
          844                 while(*pp != 0)
          845                         routput(*pp++);
          846         } else
          847                 Bprint(&bstdout, p);        /* character string */
          848 }
          849 
          850 void
          851 output(char *p)
          852 {
          853         routput(p);
          854         bsp_nxt = &bspace[0];
          855         Bprint(&bstdout, "\n");
          856         Bflush(&bstdout);
          857         cp = cary;
          858         crs = rcrs;
          859 }
          860 
          861 void
          862 conout(char *p, char *s)
          863 {
          864         Bprint(&bstdout, "[");
          865         routput(p);
          866         Bprint(&bstdout, "]s%s\n", s);
          867         Bflush(&bstdout);
          868         lev--;
          869 }
          870 
          871 void
          872 yyerror(char *s, ...)
          873 {
          874         if(ifile > sargc)
          875                 ss = "teletype";
          876         Bprint(&bstdout, "c[%s:%d, %s]pc\n", s, ln+1, ss);
          877         Bflush(&bstdout);
          878         cp = cary;
          879         crs = rcrs;
          880         bindx = 0;
          881         lev = 0;
          882         bsp_nxt = &bspace[0];
          883 }
          884 
          885 void
          886 pp(char *s)
          887 {
          888         /* puts the relevant stuff on pre and post for the letter s */
          889         bundle(3, "S", s, pre);
          890         pre = yyval.cptr;
          891         bundle(4, post, "L", s, "s.");
          892         post = yyval.cptr;
          893 }
          894 
          895 void
          896 tp(char *s)
          897 {
          898         /* same as pp, but for temps */
          899         bundle(3, "0S", s, pre);
          900         pre = yyval.cptr;
          901         bundle(4, post, "L", s, "s.");
          902         post = yyval.cptr;
          903 }
          904 
          905 void
          906 yyinit(int argc, char **argv)
          907 {
          908         Binit(&bstdout, 1, OWRITE);
          909         sargv = argv;
          910         sargc = argc;
          911         if(sargc == 0) {
          912                 in = &bstdin;
          913                 Binit(in, 0, OREAD);
          914         } else if((in = Bopen(sargv[0], OREAD)) == 0)
          915                 yyerror("cannot open input file");
          916         ifile = 0;
          917         ln = 0;
          918         ss = sargv[0];
          919 }
          920 
          921 void
          922 getout(void)
          923 {
          924         Bprint(&bstdout, "q");
          925         Bflush(&bstdout);
          926         exits(0);
          927 }
          928 
          929 char*
          930 getf(char *p)
          931 {
          932         return funtab[*p - 'a'];
          933 }
          934 
          935 char*
          936 geta(char *p)
          937 {
          938         return atab[*p - 'a'];
          939 }
          940 
          941 void
          942 main(int argc, char **argv)
          943 {
          944         int p[2];
          945 
          946         ARGBEGIN{
          947         case 'd':
          948                 bdebug++;
          949                 break;
          950         case 'c':
          951                 cflag++;
          952                 break;
          953         case 'l':
          954                 lflag++;
          955                 break;
          956         case 's':
          957                 sflag++;
          958                 break;
          959         default:
          960                 fprint(2, "Usage: bc [-l] [-c] [file ...]\n");
          961                 exits("usage");
          962         }ARGEND
          963         
          964         if(lflag) {
          965                 argc++;
          966                 argv--;
          967                 *argv = unsharp("#9/lib/bclib");
          968         }
          969         if(cflag) {
          970                 yyinit(argc, argv);
          971                 for(;;)
          972                         yyparse();
          973                 exits(0);
          974         }
          975         pipe(p);
          976         if(fork() == 0) {
          977                 dup(p[1], 1);
          978                 close(p[0]);
          979                 close(p[1]);
          980                 yyinit(argc, argv);
          981                 for(;;)
          982                         yyparse();
          983         }
          984         dup(p[0], 0);
          985         close(p[0]);
          986         close(p[1]);
          987         execl(unsharp("#9/bin/dc"), "dc", nil);
          988 }