Introduction
Introduction Statistics Contact Development Disclaimer Help
bc.y - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
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(…
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 w…
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 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.