stdio.h defines BUFSIZ
[unix-history] / usr / src / usr.bin / bc / bc.y
CommitLineData
a27f2922 1%{
392fe950 2static char *sccsid = "@(#)bc.y 4.7 (Berkeley) 89/09/15";
a27f2922
BJ
3 int *getout();
4%}
5%right '='
6%left '+' '-'
7%left '*' '/' '%'
8%right '^'
9%left UMINUS
10
11%term LETTER DIGIT SQRT LENGTH _IF FFF EQ
12%term _WHILE _FOR NE LE GE INCR DECR
13%term _RETURN _BREAK _DEFINE BASE OBASE SCALE
14%term EQPL EQMI EQMUL EQDIV EQREM EQEXP
15%term _AUTO DOT
16%term QSTR
17
18%{
392fe950 19#include <sys/signal.h>
a27f2922 20#include <stdio.h>
6d987ad7 21#include <varargs.h>
0092fa3d 22#include "pathnames.h"
4e44ae42 23FILE *in;
a27f2922
BJ
24char cary[1000], *cp = { cary };
25char string[1000], *str = {string};
26int crs = '0';
27int rcrs = '0'; /* reset crs */
28int bindx = 0;
29int lev = 0;
30int ln;
31char *ss;
32int bstack[10] = { 0 };
33char *numb[15] = {
34 " 0", " 1", " 2", " 3", " 4", " 5",
35 " 6", " 7", " 8", " 9", " 10", " 11",
36 " 12", " 13", " 14" };
37int *pre, *post;
38%}
39%%
40start :
41 | start stat tail
42 = output( $2 );
43 | start def dargs ')' '{' dlist slist '}'
44 ={ bundle( 6,pre, $7, post ,"0",numb[lev],"Q");
45 conout( $$, $2 );
46 rcrs = crs;
47 output( "" );
48 lev = bindx = 0;
49 }
50 ;
51
52dlist : tail
53 | dlist _AUTO dlets tail
54 ;
55
56stat : e
57 ={ bundle(2, $1, "ps." ); }
58 |
59 ={ bundle(1, "" ); }
60 | QSTR
61 ={ bundle(3,"[",$1,"]P");}
62 | LETTER '=' e
63 ={ bundle(3, $3, "s", $1 ); }
64 | LETTER '[' e ']' '=' e
65 ={ bundle(4, $6, $3, ":", geta($1)); }
66 | LETTER EQOP e
67 ={ bundle(6, "l", $1, $3, $2, "s", $1 ); }
68 | LETTER '[' e ']' EQOP e
69 ={ bundle(8,$3, ";", geta($1), $6, $5, $3, ":", geta($1));}
70 | _BREAK
71 ={ bundle(2, numb[lev-bstack[bindx-1]], "Q" ); }
72 | _RETURN '(' e ')'
73 = bundle(4, $3, post, numb[lev], "Q" );
74 | _RETURN '(' ')'
75 = bundle(4, "0", post, numb[lev], "Q" );
76 | _RETURN
77 = bundle(4,"0",post,numb[lev],"Q");
78 | SCALE '=' e
79 = bundle(2, $3, "k");
80 | SCALE EQOP e
81 = bundle(4,"K",$3,$2,"k");
82 | BASE '=' e
83 = bundle(2,$3, "i");
84 | BASE EQOP e
85 = bundle(4,"I",$3,$2,"i");
86 | OBASE '=' e
87 = bundle(2,$3,"o");
88 | OBASE EQOP e
89 = bundle(4,"O",$3,$2,"o");
90 | '{' slist '}'
91 ={ $$ = $2; }
92 | FFF
93 ={ bundle(1,"fY"); }
94 | error
95 ={ bundle(1,"c"); }
96 | _IF CRS BLEV '(' re ')' stat
97 ={ conout( $7, $2 );
98 bundle(3, $5, $2, " " );
99 }
100 | _WHILE CRS '(' re ')' stat BLEV
101 ={ bundle(3, $6, $4, $2 );
102 conout( $$, $2 );
103 bundle(3, $4, $2, " " );
104 }
105 | fprefix CRS re ';' e ')' stat BLEV
106 ={ bundle(5, $7, $5, "s.", $3, $2 );
107 conout( $$, $2 );
108 bundle(5, $1, "s.", $3, $2, " " );
109 }
110 | '~' LETTER '=' e
111 ={ bundle(3,$4,"S",$2); }
112 ;
113
114EQOP : EQPL
115 ={ $$ = "+"; }
116 | EQMI
117 ={ $$ = "-"; }
118 | EQMUL
119 ={ $$ = "*"; }
120 | EQDIV
121 ={ $$ = "/"; }
122 | EQREM
123 ={ $$ = "%%"; }
124 | EQEXP
125 ={ $$ = "^"; }
126 ;
127
128fprefix : _FOR '(' e ';'
129 ={ $$ = $3; }
130 ;
131
132BLEV :
133 ={ --bindx; }
134 ;
135
136slist : stat
137 | slist tail stat
138 ={ bundle(2, $1, $3 ); }
139 ;
140
141tail : '\n'
142 ={ln++;}
143 | ';'
144 ;
145
146re : e EQ e
147 = bundle(3, $1, $3, "=" );
148 | e '<' e
149 = bundle(3, $1, $3, ">" );
150 | e '>' e
151 = bundle(3, $1, $3, "<" );
152 | e NE e
153 = bundle(3, $1, $3, "!=" );
154 | e GE e
155 = bundle(3, $1, $3, "!>" );
156 | e LE e
157 = bundle(3, $1, $3, "!<" );
158 | e
159 = bundle(2, $1, " 0!=" );
160 ;
161
162e : e '+' e
163 = bundle(3, $1, $3, "+" );
164 | e '-' e
165 = bundle(3, $1, $3, "-" );
166 | '-' e %prec UMINUS
167 = bundle(3, " 0", $2, "-" );
168 | e '*' e
169 = bundle(3, $1, $3, "*" );
170 | e '/' e
171 = bundle(3, $1, $3, "/" );
172 | e '%' e
173 = bundle(3, $1, $3, "%%" );
174 | e '^' e
175 = bundle(3, $1, $3, "^" );
176 | LETTER '[' e ']'
177 ={ bundle(3,$3, ";", geta($1)); }
178 | LETTER INCR
179 = bundle(4, "l", $1, "d1+s", $1 );
180 | INCR LETTER
181 = bundle(4, "l", $2, "1+ds", $2 );
182 | DECR LETTER
183 = bundle(4, "l", $2, "1-ds", $2 );
184 | LETTER DECR
185 = bundle(4, "l", $1, "d1-s", $1 );
186 | LETTER '[' e ']' INCR
187 = bundle(7,$3,";",geta($1),"d1+",$3,":",geta($1));
188 | INCR LETTER '[' e ']'
189 = bundle(7,$4,";",geta($2),"1+d",$4,":",geta($2));
190 | LETTER '[' e ']' DECR
191 = bundle(7,$3,";",geta($1),"d1-",$3,":",geta($1));
192 | DECR LETTER '[' e ']'
193 = bundle(7,$4,";",geta($2),"1-d",$4,":",geta($2));
194 | SCALE INCR
195 = bundle(1,"Kd1+k");
196 | INCR SCALE
197 = bundle(1,"K1+dk");
198 | SCALE DECR
199 = bundle(1,"Kd1-k");
200 | DECR SCALE
201 = bundle(1,"K1-dk");
202 | BASE INCR
203 = bundle(1,"Id1+i");
204 | INCR BASE
205 = bundle(1,"I1+di");
206 | BASE DECR
207 = bundle(1,"Id1-i");
208 | DECR BASE
209 = bundle(1,"I1-di");
210 | OBASE INCR
211 = bundle(1,"Od1+o");
212 | INCR OBASE
213 = bundle(1,"O1+do");
214 | OBASE DECR
215 = bundle(1,"Od1-o");
216 | DECR OBASE
217 = bundle(1,"O1-do");
218 | LETTER '(' cargs ')'
219 = bundle(4, $3, "l", getf($1), "x" );
220 | LETTER '(' ')'
221 = bundle(3, "l", getf($1), "x" );
222 | cons
223 ={ bundle(2, " ", $1 ); }
224 | DOT cons
225 ={ bundle(2, " .", $2 ); }
226 | cons DOT cons
227 ={ bundle(4, " ", $1, ".", $3 ); }
228 | cons DOT
229 ={ bundle(3, " ", $1, "." ); }
230 | DOT
231 ={ $$ = "l."; }
232 | LETTER
233 = { bundle(2, "l", $1 ); }
234 | LETTER '=' e
235 ={ bundle(3, $3, "ds", $1 ); }
236 | LETTER EQOP e %prec '='
237 ={ bundle(6, "l", $1, $3, $2, "ds", $1 ); }
238 | LETTER '[' e ']' '=' e
239 = { bundle(5,$6,"d",$3,":",geta($1)); }
240 | LETTER '[' e ']' EQOP e
241 = { bundle(9,$3,";",geta($1),$6,$5,"d",$3,":",geta($1)); }
242 | LENGTH '(' e ')'
243 = bundle(2,$3,"Z");
244 | SCALE '(' e ')'
245 = bundle(2,$3,"X"); /* must be before '(' e ')' */
246 | '(' e ')'
247 = { $$ = $2; }
248 | '?'
249 ={ bundle(1, "?" ); }
250 | SQRT '(' e ')'
251 ={ bundle(2, $3, "v" ); }
252 | '~' LETTER
253 ={ bundle(2,"L",$2); }
254 | SCALE '=' e
255 = bundle(2,$3,"dk");
256 | SCALE EQOP e %prec '='
257 = bundle(4,"K",$3,$2,"dk");
258 | BASE '=' e
259 = bundle(2,$3,"di");
260 | BASE EQOP e %prec '='
261 = bundle(4,"I",$3,$2,"di");
262 | OBASE '=' e
263 = bundle(2,$3,"do");
264 | OBASE EQOP e %prec '='
265 = bundle(4,"O",$3,$2,"do");
266 | SCALE
267 = bundle(1,"K");
268 | BASE
269 = bundle(1,"I");
270 | OBASE
271 = bundle(1,"O");
272 ;
273
274cargs : eora
275 | cargs ',' eora
276 = bundle(2, $1, $3 );
277 ;
278eora: e
279 | LETTER '[' ']'
280 =bundle(2,"l",geta($1));
281 ;
282
283cons : constant
284 ={ *cp++ = '\0'; }
285
286constant:
287 '_'
288 ={ $$ = cp; *cp++ = '_'; }
289 | DIGIT
290 ={ $$ = cp; *cp++ = $1; }
291 | constant DIGIT
292 ={ *cp++ = $2; }
293 ;
294
295CRS :
296 ={ $$ = cp; *cp++ = crs++; *cp++ = '\0';
297 if(crs == '[')crs+=3;
298 if(crs == 'a')crs='{';
299 if(crs >= 0241){yyerror("program too big");
300 getout();
301 }
302 bstack[bindx++] = lev++; }
303 ;
304
305def : _DEFINE LETTER '('
306 ={ $$ = getf($2);
307 pre = "";
308 post = "";
309 lev = 1;
310 bstack[bindx=0] = 0;
311 }
312 ;
313
314dargs :
315 | lora
316 ={ pp( $1 ); }
317 | dargs ',' lora
318 ={ pp( $3 ); }
319 ;
320
321dlets : lora
322 ={ tp($1); }
323 | dlets ',' lora
324 ={ tp($3); }
325 ;
326lora : LETTER
327 | LETTER '[' ']'
328 ={ $$ = geta($1); }
329 ;
330
331%%
332# define error 256
333
334int peekc = -1;
335int sargc;
336int ifile;
337char **sargv;
338
339char funtab[52] = {
340 01,0,02,0,03,0,04,0,05,0,06,0,07,0,010,0,011,0,012,0,013,0,014,0,015,0,016,0,017,0,
341 020,0,021,0,022,0,023,0,024,0,025,0,026,0,027,0,030,0,031,0,032,0 };
342char atab[52] = {
343 0241,0,0242,0,0243,0,0244,0,0245,0,0246,0,0247,0,0250,0,0251,0,0252,0,0253,0,
344 0254,0,0255,0,0256,0,0257,0,0260,0,0261,0,0262,0,0263,0,0264,0,0265,0,0266,0,
345 0267,0,0270,0,0271,0,0272,0};
346char *letr[26] = {
347 "a","b","c","d","e","f","g","h","i","j",
348 "k","l","m","n","o","p","q","r","s","t",
349 "u","v","w","x","y","z" } ;
350char *dot = { "." };
351yylex(){
352 int c, ch;
353restart:
354 c = getch();
355 peekc = -1;
356 while( c == ' ' || c == '\t' ) c = getch();
357 if(c == '\\'){
358 getch();
359 goto restart;
360 }
361 if( c<= 'z' && c >= 'a' ) {
362 /* look ahead to look for reserved words */
363 peekc = getch();
364 if( peekc >= 'a' && peekc <= 'z' ){ /* must be reserved word */
365 if( c=='i' && peekc=='f' ){ c=_IF; goto skip; }
366 if( c=='w' && peekc=='h' ){ c=_WHILE; goto skip; }
367 if( c=='f' && peekc=='o' ){ c=_FOR; goto skip; }
368 if( c=='s' && peekc=='q' ){ c=SQRT; goto skip; }
369 if( c=='r' && peekc=='e' ){ c=_RETURN; goto skip; }
370 if( c=='b' && peekc=='r' ){ c=_BREAK; goto skip; }
371 if( c=='d' && peekc=='e' ){ c=_DEFINE; goto skip; }
372 if( c=='s' && peekc=='c' ){ c= SCALE; goto skip; }
373 if( c=='b' && peekc=='a' ){ c=BASE; goto skip; }
374 if( c=='i' && peekc == 'b'){ c=BASE; goto skip; }
375 if( c=='o' && peekc=='b' ){ c=OBASE; goto skip; }
376 if( c=='d' && peekc=='i' ){ c=FFF; goto skip; }
377 if( c=='a' && peekc=='u' ){ c=_AUTO; goto skip; }
378 if( c == 'l' && peekc=='e'){ c=LENGTH; goto skip; }
379 if( c == 'q' && peekc == 'u'){getout();}
380 /* could not be found */
381 return( error );
382 skip: /* skip over rest of word */
383 peekc = -1;
384 while( (ch = getch()) >= 'a' && ch <= 'z' );
385 peekc = ch;
386 return( c );
387 }
388
389 /* usual case; just one single letter */
390
391 yylval = letr[c-'a'];
392 return( LETTER );
393 }
394 if( c>= '0' && c <= '9' || c>= 'A' && c<= 'F' ){
395 yylval = c;
396 return( DIGIT );
397 }
398 switch( c ){
399 case '.': return( DOT );
400 case '=':
401 switch( peekc = getch() ){
402 case '=': c=EQ; goto gotit;
403 case '+': c=EQPL; goto gotit;
404 case '-': c=EQMI; goto gotit;
405 case '*': c=EQMUL; goto gotit;
406 case '/': c=EQDIV; goto gotit;
407 case '%': c=EQREM; goto gotit;
408 case '^': c=EQEXP; goto gotit;
409 default: return( '=' );
410 gotit: peekc = -1; return(c);
411 }
3321b8ce
BJ
412 case '+': return( cpeek( '+', INCR, cpeek( '=', EQPL, '+') ) );
413 case '-': return( cpeek( '-', DECR, cpeek( '=', EQMI, '-') ) );
a27f2922
BJ
414 case '<': return( cpeek( '=', LE, '<' ) );
415 case '>': return( cpeek( '=', GE, '>' ) );
416 case '!': return( cpeek( '=', NE, '!' ) );
417 case '/':
418 if((peekc = getch()) == '*'){
419 peekc = -1;
420 while((getch() != '*') || ((peekc = getch()) != '/'));
421 peekc = -1;
422 goto restart;
423 }
3321b8ce
BJ
424 else if (peekc == '=') {
425 c=EQDIV;
426 goto gotit;
427 }
a27f2922 428 else return(c);
3321b8ce
BJ
429 case '*':
430 return( cpeek( '=', EQMUL, '*' ) );
431 case '%':
432 return( cpeek( '=', EQREM, '%' ) );
433 case '^':
434 return( cpeek( '=', EQEXP, '^' ) );
a27f2922
BJ
435 case '"':
436 yylval = str;
437 while((c=getch()) != '"'){*str++ = c;
438 if(str >= &string[999]){yyerror("string space exceeded");
439 getout();
440 }
441 }
442 *str++ = '\0';
443 return(QSTR);
444 default: return( c );
445 }
446}
447
448cpeek( c, yes, no ){
449 if( (peekc=getch()) != c ) return( no );
450 else {
451 peekc = -1;
452 return( yes );
453 }
454}
455
456getch(){
457 int ch;
458loop:
459 ch = (peekc < 0) ? getc(in) : peekc;
460 peekc = -1;
461 if(ch != EOF)return(ch);
462 if(++ifile > sargc){
463 if(ifile >= sargc+2)getout();
464 in = stdin;
465 ln = 0;
466 goto loop;
467 }
468 fclose(in);
469 if((in = fopen(sargv[ifile],"r")) != NULL){
470 ln = 0;
471 ss = sargv[ifile];
472 goto loop;
473 }
474 yyerror("cannot open input file");
475}
476# define b_sp_max 3000
477int b_space [ b_sp_max ];
478int * b_sp_nxt = { b_space };
479
480int bdebug = 0;
6d987ad7
KB
481/*VARARGS*/
482bundle(va_alist) va_dcl {
483 va_list ap;
484 int i, *q;
a27f2922 485
6d987ad7
KB
486 va_start(ap);
487 i = va_arg(ap, int);
a27f2922
BJ
488 q = b_sp_nxt;
489 if( bdebug ) printf("bundle %d elements at %o\n",i, q );
490 while(i-- > 0){
491 if( b_sp_nxt >= & b_space[b_sp_max] ) yyerror( "bundling space exceeded" );
6d987ad7 492 * b_sp_nxt++ = va_arg(ap, int);
a27f2922
BJ
493 }
494 * b_sp_nxt++ = 0;
495 yyval = q;
6d987ad7 496 va_end(ap);
a27f2922
BJ
497 return( q );
498}
499
500routput(p) int *p; {
501 if( bdebug ) printf("routput(%o)\n", p );
502 if( p >= &b_space[0] && p < &b_space[b_sp_max]){
503 /* part of a bundle */
504 while( *p != 0 ) routput( *p++ );
505 }
506 else printf( p ); /* character string */
507}
508
509output( p ) int *p; {
510 routput( p );
511 b_sp_nxt = & b_space[0];
512 printf( "\n" );
513 fflush(stdout);
514 cp = cary;
515 crs = rcrs;
516}
517
518conout( p, s ) int *p; char *s; {
519 printf("[");
520 routput( p );
521 printf("]s%s\n", s );
522 fflush(stdout);
523 lev--;
524}
525
526yyerror( s ) char *s; {
527 if(ifile > sargc)ss="teletype";
528 printf("c[%s on line %d, %s]pc\n", s ,ln+1,ss);
529 fflush(stdout);
530 cp = cary;
531 crs = rcrs;
532 bindx = 0;
533 lev = 0;
534 b_sp_nxt = &b_space[0];
535}
536
537pp( s ) char *s; {
538 /* puts the relevant stuff on pre and post for the letter s */
539
540 bundle(3, "S", s, pre );
541 pre = yyval;
542 bundle(4, post, "L", s, "s." );
543 post = yyval;
544}
545
546tp( s ) char *s; { /* same as pp, but for temps */
547 bundle(3, "0S", s, pre );
548 pre = yyval;
549 bundle(4, post, "L", s, "s." );
550 post = yyval;
551}
552
553yyinit(argc,argv) int argc; char *argv[];{
392fe950 554 (void)signal(SIGINT, SIG_IGN); /* ignore all interrupts */
a27f2922
BJ
555 sargv=argv;
556 sargc= -- argc;
557 if(sargc == 0)in=stdin;
db2c044e 558 else if((in = fopen(sargv[1],"r")) == NULL) {
a27f2922 559 yyerror("cannot open input file");
db2c044e
SL
560 in = stdin;
561 }
a27f2922
BJ
562 ifile = 1;
563 ln = 0;
564 ss = sargv[1];
565}
566int *getout(){
567 printf("q");
568 fflush(stdout);
6d987ad7 569 exit(0);
a27f2922
BJ
570}
571
572int *
573getf(p) char *p;{
574 return(&funtab[2*(*p -0141)]);
575}
576int *
577geta(p) char *p;{
578 return(&atab[2*(*p - 0141)]);
579}
580
581main(argc, argv)
582char **argv;
583{
584 int p[2];
585
586
587 if (argc > 1 && *argv[1] == '-') {
588 if((argv[1][1] == 'd')||(argv[1][1] == 'c')){
589 yyinit(--argc, ++argv);
590 yyparse();
6d987ad7 591 exit(0);
a27f2922
BJ
592 }
593 if(argv[1][1] != 'l'){
594 printf("unrecognizable argument\n");
595 fflush(stdout);
6d987ad7 596 exit(1);
a27f2922 597 }
0092fa3d 598 argv[1] = _PATH_LIBB;
a27f2922
BJ
599 }
600 pipe(p);
601 if (fork()==0) {
602 close(1);
603 dup(p[1]);
604 close(p[0]);
605 close(p[1]);
606 yyinit(argc, argv);
607 yyparse();
6d987ad7 608 exit(0);
a27f2922
BJ
609 }
610 close(0);
611 dup(p[0]);
612 close(p[0]);
613 close(p[1]);
0092fa3d 614 execl(_PATH_DC, "dc", "-", (char *)0);
6d987ad7
KB
615 perror("bc: can't find dc");
616 exit(1);
a27f2922 617}