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