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 } |