Blob


1 %{
2 #include <u.h>
3 #include <libc.h>
4 #include <bio.h>
6 #define bsp_max 5000
8 Biobuf *in;
9 #define stdin bstdin
10 #define stdout bstdout
11 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 %union
90 {
91 int* iptr;
92 char* cptr;
93 int cc;
94 }
96 %type <iptr> pstat stat stat1 def slist dlets e ase nase
97 %type <iptr> slist re fprefix cargs eora cons constant lora
98 %type <cptr> crs
100 %token <cptr> LETTER EQOP _AUTO DOT
101 %token <cc> DIGIT SQRT LENGTH _IF FFF EQ
102 %token <cc> _PRINT _WHILE _FOR NE LE GE INCR DECR
103 %token <cc> _RETURN _BREAK _DEFINE BASE OBASE SCALE
104 %token <cc> QSTR ERROR
106 %right '=' EQOP
107 %left '+' '-'
108 %left '*' '/' '%'
109 %right '^'
110 %left UMINUS
112 %%
113 start:
114 start stuff
115 | stuff
117 stuff:
118 pstat tail
120 output($1);
122 | def dargs ')' '{' dlist slist '}'
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;
131 dlist:
132 tail
133 | dlist _AUTO dlets tail
135 stat:
136 stat1
137 | nase
139 if(sflag)
140 bundle(2, $1, "s.");
143 pstat:
144 stat1
146 if(sflag)
147 bundle(2, $1, "0");
149 | nase
151 if(!sflag)
152 bundle(2, $1, "ps.");
155 stat1:
157 bundle(1, "");
159 | ase
161 bundle(2, $1, "s.");
163 | SCALE '=' e
165 bundle(2, $3, "k");
167 | SCALE EQOP e
169 bundle(4, "K", $3, $2, "k");
171 | BASE '=' e
173 bundle(2, $3, "i");
175 | BASE EQOP e
177 bundle(4, "I", $3, $2, "i");
179 | OBASE '=' e
181 bundle(2, $3, "o");
183 | OBASE EQOP e
185 bundle(4, "O", $3, $2, "o");
187 | QSTR
189 bundle(3, "[", $1, "]P");
191 | _BREAK
193 bundle(2, numb[lev-bstack[bindx-1]], "Q");
195 | _PRINT e
197 bundle(2, $2, "ps.");
199 | _RETURN e
201 bundle(4, $2, post, numb[lev], "Q");
203 | _RETURN
205 bundle(4, "0", post, numb[lev], "Q");
207 | '{' slist '}'
209 $$ = $2;
211 | FFF
213 bundle(1, "fY");
215 | _IF crs BLEV '(' re ')' stat
217 conout($7, $2);
218 bundle(3, $5, $2, " ");
220 | _WHILE crs '(' re ')' stat BLEV
222 bundle(3, $6, $4, $2);
223 conout($$, $2);
224 bundle(3, $4, $2, " ");
226 | fprefix crs re ';' e ')' stat BLEV
228 bundle(5, $7, $5, "s.", $3, $2);
229 conout($$, $2);
230 bundle(5, $1, "s.", $3, $2, " ");
232 | '~' LETTER '=' e
234 bundle(3, $4, "S", $2);
237 fprefix:
238 _FOR '(' e ';'
240 $$ = $3;
243 BLEV:
246 --bindx;
249 slist:
250 stat
251 | slist tail stat
253 bundle(2, $1, $3);
256 tail:
257 '\n'
259 ln++;
261 | ';'
263 re:
264 e EQ e
266 $$ = bundle(3, $1, $3, "=");
268 | e '<' e
270 bundle(3, $1, $3, ">");
272 | e '>' e
274 bundle(3, $1, $3, "<");
276 | e NE e
278 bundle(3, $1, $3, "!=");
280 | e GE e
282 bundle(3, $1, $3, "!>");
284 | e LE e
286 bundle(3, $1, $3, "!<");
288 | e
290 bundle(2, $1, " 0!=");
293 nase:
294 '(' e ')'
296 $$ = $2;
298 | cons
300 bundle(3, " ", $1, " ");
302 | DOT cons
304 bundle(3, " .", $2, " ");
306 | cons DOT cons
308 bundle(5, " ", $1, ".", $3, " ");
310 | cons DOT
312 bundle(4, " ", $1, ".", " ");
314 | DOT
316 $<cptr>$ = "l.";
318 | LETTER '[' e ']'
320 bundle(3, $3, ";", geta($1));
322 | LETTER INCR
324 bundle(4, "l", $1, "d1+s", $1);
326 | INCR LETTER
328 bundle(4, "l", $2, "1+ds", $2);
330 | DECR LETTER
332 bundle(4, "l", $2, "1-ds", $2);
334 | LETTER DECR
336 bundle(4, "l", $1, "d1-s", $1);
338 | LETTER '[' e ']' INCR
340 bundle(7, $3, ";", geta($1), "d1+" ,$3, ":" ,geta($1));
342 | INCR LETTER '[' e ']'
344 bundle(7, $4, ";", geta($2), "1+d", $4, ":", geta($2));
346 | LETTER '[' e ']' DECR
348 bundle(7, $3, ";", geta($1), "d1-", $3, ":", geta($1));
350 | DECR LETTER '[' e ']'
352 bundle(7, $4, ";", geta($2), "1-d", $4, ":" ,geta($2));
354 | SCALE INCR
356 bundle(1, "Kd1+k");
358 | INCR SCALE
360 bundle(1, "K1+dk");
362 | SCALE DECR
364 bundle(1, "Kd1-k");
366 | DECR SCALE
368 bundle(1, "K1-dk");
370 | BASE INCR
372 bundle(1, "Id1+i");
374 | INCR BASE
376 bundle(1, "I1+di");
378 | BASE DECR
380 bundle(1, "Id1-i");
382 | DECR BASE
384 bundle(1, "I1-di");
386 | OBASE INCR
388 bundle(1, "Od1+o");
390 | INCR OBASE
392 bundle(1, "O1+do");
394 | OBASE DECR
396 bundle(1, "Od1-o");
398 | DECR OBASE
400 bundle(1, "O1-do");
402 | LETTER '(' cargs ')'
404 bundle(4, $3, "l", getf($1), "x");
406 | LETTER '(' ')'
408 bundle(3, "l", getf($1), "x");
410 | LETTER = {
411 bundle(2, "l", $1);
413 | LENGTH '(' e ')'
415 bundle(2, $3, "Z");
417 | SCALE '(' e ')'
419 bundle(2, $3, "X");
421 | '?'
423 bundle(1, "?");
425 | SQRT '(' e ')'
427 bundle(2, $3, "v");
429 | '~' LETTER
431 bundle(2, "L", $2);
433 | SCALE
435 bundle(1, "K");
437 | BASE
439 bundle(1, "I");
441 | OBASE
443 bundle(1, "O");
445 | '-' e
447 bundle(3, " 0", $2, "-");
449 | e '+' e
451 bundle(3, $1, $3, "+");
453 | e '-' e
455 bundle(3, $1, $3, "-");
457 | e '*' e
459 bundle(3, $1, $3, "*");
461 | e '/' e
463 bundle(3, $1, $3, "/");
465 | e '%' e
467 bundle(3, $1, $3, "%%");
469 | e '^' e
471 bundle(3, $1, $3, "^");
474 ase:
475 LETTER '=' e
477 bundle(3, $3, "ds", $1);
479 | LETTER '[' e ']' '=' e
481 bundle(5, $6, "d", $3, ":", geta($1));
483 | LETTER EQOP e
485 bundle(6, "l", $1, $3, $2, "ds", $1);
487 | LETTER '[' e ']' EQOP e
489 bundle(9, $3, ";", geta($1), $6, $5, "d", $3, ":", geta($1));
492 e:
493 ase
494 | nase
496 cargs:
497 eora
498 | cargs ',' eora
500 bundle(2, $1, $3);
503 eora:
505 | LETTER '[' ']'
507 bundle(2, "l", geta($1));
510 cons:
511 constant
513 *cp++ = 0;
516 constant:
517 '_'
519 $<cptr>$ = cp;
520 *cp++ = '_';
522 | DIGIT
524 $<cptr>$ = cp;
525 *cp++ = $1;
527 | constant DIGIT
529 *cp++ = $2;
532 crs:
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();
546 bstack[bindx++] = lev++;
549 def:
550 _DEFINE LETTER '('
552 $$ = getf($2);
553 pre = (int*)"";
554 post = (int*)"";
555 lev = 1;
556 bindx = 0;
557 bstack[bindx] = 0;
560 dargs:
561 | lora
563 pp((char*)$1);
565 | dargs ',' lora
567 pp((char*)$3);
570 dlets:
571 lora
573 tp((char*)$1);
575 | dlets ',' lora
577 tp((char*)$3);
580 lora:
581 LETTER
583 $<cptr>$=$1;
585 | LETTER '[' ']'
587 $$ = geta($1);
590 %%
592 int
593 yylex(void)
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;
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;
614 if(c=='i' && peekc=='f') {
615 c = _IF;
616 goto skip;
618 if(c=='w' && peekc=='h') {
619 c = _WHILE;
620 goto skip;
622 if(c=='f' && peekc=='o') {
623 c = _FOR;
624 goto skip;
626 if(c=='s' && peekc=='q') {
627 c = SQRT;
628 goto skip;
630 if(c=='r' && peekc=='e') {
631 c = _RETURN;
632 goto skip;
634 if(c=='b' && peekc=='r') {
635 c = _BREAK;
636 goto skip;
638 if(c=='d' && peekc=='e') {
639 c = _DEFINE;
640 goto skip;
642 if(c=='s' && peekc=='c') {
643 c = SCALE;
644 goto skip;
646 if(c=='b' && peekc=='a') {
647 c = BASE;
648 goto skip;
650 if(c=='i' && peekc=='b') {
651 c = BASE;
652 goto skip;
654 if(c=='o' && peekc=='b') {
655 c = OBASE;
656 goto skip;
658 if(c=='d' && peekc=='i') {
659 c = FFF;
660 goto skip;
662 if(c=='a' && peekc=='u') {
663 c = _AUTO;
664 goto skip;
666 if(c=='l' && peekc=='e') {
667 c = LENGTH;
668 goto skip;
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;
682 peekc = ch;
683 return c;
686 /* usual case; just one single letter */
687 yylval.cptr = letr[c-'a'];
688 return LETTER;
690 if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
691 yylval.cc = c;
692 return DIGIT;
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;
712 return cpeek('+', INCR, c);
713 case '-':
714 ch = cpeek('=', EQOP, c);
715 if(ch == EQOP) {
716 yylval.cptr = "-";
717 return ch;
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;
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;
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();
757 *str++ = 0;
758 return QSTR;
759 default:
760 return c;
764 int
765 cpeek(int c, int yes, int no)
768 peekc = getch();
769 if(peekc == c) {
770 peekc = -1;
771 return yes;
773 return no;
776 int
777 getch(void)
779 long ch;
781 loop:
782 ch = peekc;
783 if(ch < 0){
784 if(in == 0)
785 ch = -1;
786 else
787 ch = Bgetc(in);
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;
801 Bterm(in);
802 if((in = Bopen(sargv[ifile], OREAD)) != 0){
803 ln = 0;
804 ss = sargv[ifile];
805 goto loop;
807 yyerror("cannot open input file");
808 return 0; /* shut up ken */
811 int*
812 bundle(int a, ...)
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++;
826 *bsp_nxt++ = 0;
827 yyval.iptr = q;
828 return q;
831 void
832 routput(int *p)
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 } else
841 Bprint(&stdout, (char*)p); /* character string */
844 void
845 output(int *p)
847 routput(p);
848 bsp_nxt = &bspace[0];
849 Bprint(&stdout, "\n");
850 Bflush(&stdout);
851 cp = cary;
852 crs = rcrs;
855 void
856 conout(int *p, char *s)
858 Bprint(&stdout, "[");
859 routput(p);
860 Bprint(&stdout, "]s%s\n", s);
861 Bflush(&stdout);
862 lev--;
865 void
866 yyerror(char *s, ...)
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];
879 void
880 pp(char *s)
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;
889 void
890 tp(char *s)
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;
899 void
900 yyinit(int argc, char **argv)
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];
915 void
916 getout(void)
918 Bprint(&stdout, "q");
919 Bflush(&stdout);
920 exits(0);
923 int*
924 getf(char *p)
926 return (int*)funtab[*p - 'a'];
929 int*
930 geta(char *p)
932 return (int*)atab[*p - 'a'];
935 void
936 main(int argc, char **argv)
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");
958 argc--;
959 argv++;
961 if(lflag) {
962 argv--;
963 argc++;
964 argv[1] = unsharp("#9/lib/bclib");
966 if(cflag) {
967 yyinit(argc, argv);
968 for(;;)
969 yyparse();
970 /* exits(0); */
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();
981 dup(p[0], 0);
982 close(p[0]);
983 close(p[1]);
984 execlp("dc", "dc", 0);