xref: /onnv-gate/usr/src/cmd/bc/bc.y (revision 335:d26e4323ca82)
10Sstevel@tonic-gate %{
20Sstevel@tonic-gate /*
30Sstevel@tonic-gate  * CDDL HEADER START
40Sstevel@tonic-gate  *
50Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
60Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
70Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
80Sstevel@tonic-gate  * with the License.
90Sstevel@tonic-gate  *
100Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
110Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
120Sstevel@tonic-gate  * See the License for the specific language governing permissions
130Sstevel@tonic-gate  * and limitations under the License.
140Sstevel@tonic-gate  *
150Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
160Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
170Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
180Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
190Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
200Sstevel@tonic-gate  *
210Sstevel@tonic-gate  * CDDL HEADER END
220Sstevel@tonic-gate  */
230Sstevel@tonic-gate %}
240Sstevel@tonic-gate /*
250Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
260Sstevel@tonic-gate  * Use is subject to license terms.
270Sstevel@tonic-gate  */
280Sstevel@tonic-gate 
29*335Smuffin /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
30*335Smuffin /*	  All Rights Reserved  	*/
31*335Smuffin 
320Sstevel@tonic-gate %{
33*335Smuffin #pragma ident	"%Z%%M%	%I%	%E% SMI"
340Sstevel@tonic-gate %}
350Sstevel@tonic-gate %{
360Sstevel@tonic-gate #include <stdio.h>
370Sstevel@tonic-gate #include <stdarg.h>
380Sstevel@tonic-gate #include <limits.h>
390Sstevel@tonic-gate #include <libintl.h>
400Sstevel@tonic-gate #include <locale.h>
410Sstevel@tonic-gate #include <signal.h>
420Sstevel@tonic-gate 
43*335Smuffin static void getout(int)	__NORETURN;
440Sstevel@tonic-gate static int *bundle(int, ...);
450Sstevel@tonic-gate static void usage(void);
46*335Smuffin 
47*335Smuffin int	cpeek(char, int, char, int, char);
48*335Smuffin void	yyerror(char *);
49*335Smuffin 
500Sstevel@tonic-gate %}
510Sstevel@tonic-gate %union {
520Sstevel@tonic-gate 	int *iptr;
530Sstevel@tonic-gate 	char *cptr;
540Sstevel@tonic-gate 	int cc;
550Sstevel@tonic-gate 	}
560Sstevel@tonic-gate %start start;
570Sstevel@tonic-gate %type <iptr> stat, def, slist, dlets, e
580Sstevel@tonic-gate %type <iptr> slist, re, fprefix, cargs, eora, cons, constant, lora
590Sstevel@tonic-gate %right '='
600Sstevel@tonic-gate %left '+' '-'
610Sstevel@tonic-gate %left '*' '/' '%'
620Sstevel@tonic-gate %right '^'
630Sstevel@tonic-gate %left UMINUS
640Sstevel@tonic-gate 
650Sstevel@tonic-gate %token <cptr> LETTER
660Sstevel@tonic-gate %type <cptr> EQOP, CRS
670Sstevel@tonic-gate %token <cc> DIGIT, SQRT, LENGTH, _IF, FFF, EQ
680Sstevel@tonic-gate %token <cc> _WHILE _FOR NE LE GE INCR DECR
690Sstevel@tonic-gate %token <cc> _RETURN _BREAK _DEFINE BASE OBASE SCALE
700Sstevel@tonic-gate %token <cc> EQPL EQMI EQMUL EQDIV EQREM EQEXP
710Sstevel@tonic-gate %token <cptr> _AUTO DOT
720Sstevel@tonic-gate %token <cc> QSTR
730Sstevel@tonic-gate 
740Sstevel@tonic-gate %{
750Sstevel@tonic-gate #define	STRING_SIZE	(BC_STRING_MAX + 3)	/* string plus quotes */
760Sstevel@tonic-gate 						/* plus NULL */
770Sstevel@tonic-gate 
780Sstevel@tonic-gate FILE	*in;
790Sstevel@tonic-gate char	cary[LINE_MAX+1];
800Sstevel@tonic-gate char	*cp = { cary };
810Sstevel@tonic-gate char	*cpend = &cary[LINE_MAX];	/* last address (not the null char) */
820Sstevel@tonic-gate char	string[STRING_SIZE];
830Sstevel@tonic-gate char	*str = { string };
840Sstevel@tonic-gate int	crs = '0';
850Sstevel@tonic-gate int	rcrs = '0';		/* reset crs */
860Sstevel@tonic-gate int	bindx = 0;
870Sstevel@tonic-gate int	lev = 0;			/* current scope level */
880Sstevel@tonic-gate int	ln;				/* line number of current file */
890Sstevel@tonic-gate int	*ttp;
900Sstevel@tonic-gate char	*ss;				/* current input source */
910Sstevel@tonic-gate int	bstack[10] = { 0 };
920Sstevel@tonic-gate char	*numb[15] = {
930Sstevel@tonic-gate 	" 0", " 1", " 2", " 3", " 4", " 5",
940Sstevel@tonic-gate 	" 6", " 7", " 8", " 9", " 10", " 11",
950Sstevel@tonic-gate 	" 12", " 13", " 14"
960Sstevel@tonic-gate };
970Sstevel@tonic-gate int	*pre, *post;
980Sstevel@tonic-gate int	interact = 0;			/* talking to a tty? */
990Sstevel@tonic-gate %}
1000Sstevel@tonic-gate %%
1010Sstevel@tonic-gate start	:
1020Sstevel@tonic-gate 	| start stat tail
1030Sstevel@tonic-gate 		= {
1040Sstevel@tonic-gate 			output($2);
1050Sstevel@tonic-gate 		}
1060Sstevel@tonic-gate 	| start def dargs ')' '{' dlist slist '}'
1070Sstevel@tonic-gate 		= {
1080Sstevel@tonic-gate 			ttp = bundle(6, pre, $7, post, "0", numb[lev], "Q");
109*335Smuffin 			conout(ttp, (char *)$2);
1100Sstevel@tonic-gate 			rcrs = crs;
111*335Smuffin 			output((int *)"");
1120Sstevel@tonic-gate 			lev = bindx = 0;
1130Sstevel@tonic-gate 		}
1140Sstevel@tonic-gate 	;
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate dlist	: tail
1170Sstevel@tonic-gate 	| dlist _AUTO dlets tail
1180Sstevel@tonic-gate 	;
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate stat	: e
1210Sstevel@tonic-gate 		= bundle(2, $1, "ps.");
1220Sstevel@tonic-gate 	|
1230Sstevel@tonic-gate 		= bundle(1, "");
1240Sstevel@tonic-gate 	| QSTR
1250Sstevel@tonic-gate 		= bundle(3, "[", $1, "]P");
1260Sstevel@tonic-gate 	| LETTER '=' e
1270Sstevel@tonic-gate 		= bundle(3, $3, "s", $1);
1280Sstevel@tonic-gate 	| LETTER '[' e ']' '=' e
1290Sstevel@tonic-gate 		= bundle(4, $6, $3, ":", geta($1));
1300Sstevel@tonic-gate 	| LETTER EQOP e
1310Sstevel@tonic-gate 		= bundle(6, "l", $1, $3, $2, "s", $1);
1320Sstevel@tonic-gate 	| LETTER '[' e ']' EQOP e
1330Sstevel@tonic-gate 		= bundle(8, $3, ";", geta($1), $6, $5, $3, ":", geta($1));
1340Sstevel@tonic-gate 	| _BREAK
1350Sstevel@tonic-gate 		= bundle(2, numb[lev-bstack[bindx-1]], "Q");
1360Sstevel@tonic-gate 	| _RETURN '(' e ')'
1370Sstevel@tonic-gate 		= bundle(4, $3, post, numb[lev], "Q");
1380Sstevel@tonic-gate 	| _RETURN '(' ')'
1390Sstevel@tonic-gate 		= bundle(4, "0", post, numb[lev], "Q");
1400Sstevel@tonic-gate 	| _RETURN
1410Sstevel@tonic-gate 		= bundle(4, "0", post, numb[lev], "Q");
1420Sstevel@tonic-gate 	| SCALE '=' e
1430Sstevel@tonic-gate 		= bundle(2, $3, "k");
1440Sstevel@tonic-gate 	| SCALE EQOP e
1450Sstevel@tonic-gate 		= bundle(4, "K", $3, $2, "k");
1460Sstevel@tonic-gate 	| BASE '=' e
1470Sstevel@tonic-gate 		= bundle(2, $3, "i");
1480Sstevel@tonic-gate 	| BASE EQOP e
1490Sstevel@tonic-gate 		= bundle(4, "I", $3, $2, "i");
1500Sstevel@tonic-gate 	| OBASE '=' e
1510Sstevel@tonic-gate 		= bundle(2, $3, "o");
1520Sstevel@tonic-gate 	| OBASE EQOP e
1530Sstevel@tonic-gate 		= bundle(4, "O", $3, $2, "o");
1540Sstevel@tonic-gate 	| '{' slist '}'
1550Sstevel@tonic-gate 		= {
1560Sstevel@tonic-gate 			$$ = $2;
1570Sstevel@tonic-gate 		}
1580Sstevel@tonic-gate 	| FFF
1590Sstevel@tonic-gate 		= bundle(1, "fY");
1600Sstevel@tonic-gate 	| error
1610Sstevel@tonic-gate 		= bundle(1, "c");
1620Sstevel@tonic-gate 	| _IF CRS BLEV '(' re ')' stat
1630Sstevel@tonic-gate 		= {
1640Sstevel@tonic-gate 			conout($7, $2);
1650Sstevel@tonic-gate 			bundle(3, $5, $2, " ");
1660Sstevel@tonic-gate 		}
1670Sstevel@tonic-gate 	| _WHILE CRS '(' re ')' stat BLEV
1680Sstevel@tonic-gate 		= {
1690Sstevel@tonic-gate 			bundle(3, $6, $4, $2);
1700Sstevel@tonic-gate 			conout($$, $2);
1710Sstevel@tonic-gate 			bundle(3, $4, $2, " ");
1720Sstevel@tonic-gate 		}
1730Sstevel@tonic-gate 	| fprefix CRS re ';' e ')' stat BLEV
1740Sstevel@tonic-gate 		= {
1750Sstevel@tonic-gate 			bundle(5, $7, $5, "s.", $3, $2);
1760Sstevel@tonic-gate 			conout($$, $2);
1770Sstevel@tonic-gate 			bundle(5, $1, "s.", $3, $2, " ");
1780Sstevel@tonic-gate 		}
1790Sstevel@tonic-gate 	| '~' LETTER '=' e
1800Sstevel@tonic-gate 		= bundle(3, $4, "S", $2);
1810Sstevel@tonic-gate 	;
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate EQOP	: EQPL
1840Sstevel@tonic-gate 		= {
1850Sstevel@tonic-gate 			$$ = "+";
1860Sstevel@tonic-gate 		}
1870Sstevel@tonic-gate 	| EQMI
1880Sstevel@tonic-gate 		= {
1890Sstevel@tonic-gate 			$$ = "-";
1900Sstevel@tonic-gate 		}
1910Sstevel@tonic-gate 	| EQMUL
1920Sstevel@tonic-gate 		= {
1930Sstevel@tonic-gate 			$$ = "*";
1940Sstevel@tonic-gate 		}
1950Sstevel@tonic-gate 	| EQDIV
1960Sstevel@tonic-gate 		= {
1970Sstevel@tonic-gate 			$$ = "/";
1980Sstevel@tonic-gate 		}
1990Sstevel@tonic-gate 	| EQREM
2000Sstevel@tonic-gate 		= {
2010Sstevel@tonic-gate 			$$ = "%%";
2020Sstevel@tonic-gate 		}
2030Sstevel@tonic-gate 	| EQEXP
2040Sstevel@tonic-gate 		= {
2050Sstevel@tonic-gate 			$$ = "^";
2060Sstevel@tonic-gate 		}
2070Sstevel@tonic-gate 	;
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate fprefix	: _FOR '(' e ';'
2100Sstevel@tonic-gate 		= {
2110Sstevel@tonic-gate 			$$ = $3;
2120Sstevel@tonic-gate 		}
2130Sstevel@tonic-gate 	;
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate BLEV	:
2160Sstevel@tonic-gate 		= --bindx;
2170Sstevel@tonic-gate 	;
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate slist	: stat
2200Sstevel@tonic-gate 	| slist tail stat
2210Sstevel@tonic-gate 		= bundle(2, $1, $3);
2220Sstevel@tonic-gate 	;
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate tail	: '\n'
2250Sstevel@tonic-gate 		= {
2260Sstevel@tonic-gate 			ln++;
2270Sstevel@tonic-gate 		}
2280Sstevel@tonic-gate 	| ';'
2290Sstevel@tonic-gate 	;
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate re	: e EQ e
2320Sstevel@tonic-gate 		= {
2330Sstevel@tonic-gate 			$$ = bundle(3, $1, $3, "=");
2340Sstevel@tonic-gate 		}
2350Sstevel@tonic-gate 	| e '<' e
2360Sstevel@tonic-gate 		= bundle(3, $1, $3, ">");
2370Sstevel@tonic-gate 	| e '>' e
2380Sstevel@tonic-gate 		= bundle(3, $1, $3, "<");
2390Sstevel@tonic-gate 	| e NE e
2400Sstevel@tonic-gate 		= bundle(3, $1, $3, "!=");
2410Sstevel@tonic-gate 	| e GE e
2420Sstevel@tonic-gate 		= bundle(3, $1, $3, "!>");
2430Sstevel@tonic-gate 	| e LE e
2440Sstevel@tonic-gate 		= bundle(3, $1, $3, "!<");
2450Sstevel@tonic-gate 	| e
2460Sstevel@tonic-gate 		= bundle(2, $1, " 0!=");
2470Sstevel@tonic-gate 	;
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate e	: e '+' e
2500Sstevel@tonic-gate 		= bundle(3, $1, $3, "+");
2510Sstevel@tonic-gate 	| e '-' e
2520Sstevel@tonic-gate 		= bundle(3, $1, $3, "-");
2530Sstevel@tonic-gate 	| '-' e		%prec UMINUS
2540Sstevel@tonic-gate 		= bundle(3, " 0", $2, "-");
2550Sstevel@tonic-gate 	| e '*' e
2560Sstevel@tonic-gate 		= bundle(3, $1, $3, "*");
2570Sstevel@tonic-gate 	| e '/' e
2580Sstevel@tonic-gate 		= bundle(3, $1, $3, "/");
2590Sstevel@tonic-gate 	| e '%' e
2600Sstevel@tonic-gate 		= bundle(3, $1, $3, "%%");
2610Sstevel@tonic-gate 	| e '^' e
2620Sstevel@tonic-gate 		= bundle(3, $1, $3, "^");
2630Sstevel@tonic-gate 	| LETTER '[' e ']'
2640Sstevel@tonic-gate 		= bundle(3, $3, ";", geta($1));
2650Sstevel@tonic-gate 	| LETTER INCR
2660Sstevel@tonic-gate 		= bundle(4, "l", $1, "d1+s", $1);
2670Sstevel@tonic-gate 	| INCR LETTER
2680Sstevel@tonic-gate 		= bundle(4, "l", $2, "1+ds", $2);
2690Sstevel@tonic-gate 	| DECR LETTER
2700Sstevel@tonic-gate 		= bundle(4, "l", $2, "1-ds", $2);
2710Sstevel@tonic-gate 	| LETTER DECR
2720Sstevel@tonic-gate 		= bundle(4, "l", $1, "d1-s", $1);
2730Sstevel@tonic-gate 	| LETTER '[' e ']' INCR
2740Sstevel@tonic-gate 		= bundle(7, $3, ";", geta($1), "d1+", $3, ":", geta($1));
2750Sstevel@tonic-gate 	| INCR LETTER '[' e ']'
2760Sstevel@tonic-gate 		= bundle(7, $4, ";", geta($2), "1+d", $4, ":", geta($2));
2770Sstevel@tonic-gate 	| LETTER '[' e ']' DECR
2780Sstevel@tonic-gate 		= bundle(7, $3, ";", geta($1), "d1-", $3, ":", geta($1));
2790Sstevel@tonic-gate 	| DECR LETTER '[' e ']'
2800Sstevel@tonic-gate 		= bundle(7, $4, ";", geta($2), "1-d", $4, ":", geta($2));
2810Sstevel@tonic-gate 	| SCALE INCR
2820Sstevel@tonic-gate 		= bundle(1, "Kd1+k");
2830Sstevel@tonic-gate 	| INCR SCALE
2840Sstevel@tonic-gate 		= bundle(1, "K1+dk");
2850Sstevel@tonic-gate 	| SCALE DECR
2860Sstevel@tonic-gate 		= bundle(1, "Kd1-k");
2870Sstevel@tonic-gate 	| DECR SCALE
2880Sstevel@tonic-gate 		= bundle(1, "K1-dk");
2890Sstevel@tonic-gate 	| BASE INCR
2900Sstevel@tonic-gate 		= bundle(1, "Id1+i");
2910Sstevel@tonic-gate 	| INCR BASE
2920Sstevel@tonic-gate 		= bundle(1, "I1+di");
2930Sstevel@tonic-gate 	| BASE DECR
2940Sstevel@tonic-gate 		= bundle(1, "Id1-i");
2950Sstevel@tonic-gate 	| DECR BASE
2960Sstevel@tonic-gate 		= bundle(1, "I1-di");
2970Sstevel@tonic-gate 	| OBASE INCR
2980Sstevel@tonic-gate 		= bundle(1, "Od1+o");
2990Sstevel@tonic-gate 	| INCR OBASE
3000Sstevel@tonic-gate 		= bundle(1, "O1+do");
3010Sstevel@tonic-gate 	| OBASE DECR
3020Sstevel@tonic-gate 		= bundle(1, "Od1-o");
3030Sstevel@tonic-gate 	| DECR OBASE
3040Sstevel@tonic-gate 		= bundle(1, "O1-do");
3050Sstevel@tonic-gate 	| LETTER '(' cargs ')'
3060Sstevel@tonic-gate 		= bundle(4, $3, "l", getf($1), "x");
3070Sstevel@tonic-gate 	| LETTER '(' ')'
3080Sstevel@tonic-gate 		= bundle(3, "l", getf($1), "x");
3090Sstevel@tonic-gate 	| cons
3100Sstevel@tonic-gate 		= bundle(2, " ", $1);
3110Sstevel@tonic-gate 	| DOT cons
3120Sstevel@tonic-gate 		= bundle(2, " .", $2);
3130Sstevel@tonic-gate 	| cons DOT cons
3140Sstevel@tonic-gate 		= bundle(4, " ", $1, ".", $3);
3150Sstevel@tonic-gate 	| cons DOT
3160Sstevel@tonic-gate 		= bundle(3, " ", $1, ".");
3170Sstevel@tonic-gate 	| DOT
3180Sstevel@tonic-gate 		= {
3190Sstevel@tonic-gate 			$<cptr>$ = "l.";
3200Sstevel@tonic-gate 		}
3210Sstevel@tonic-gate 	| LETTER
3220Sstevel@tonic-gate 		= bundle(2, "l", $1);
3230Sstevel@tonic-gate 	| LETTER '=' e
3240Sstevel@tonic-gate 		= bundle(3, $3, "ds", $1);
3250Sstevel@tonic-gate 	| LETTER EQOP e		%prec '='
3260Sstevel@tonic-gate 		= bundle(6, "l", $1, $3, $2, "ds", $1);
3270Sstevel@tonic-gate 	| LETTER '[' e ']' '=' e
3280Sstevel@tonic-gate 		= bundle(5, $6, "d", $3, ":", geta($1));
3290Sstevel@tonic-gate 	| LETTER '[' e ']' EQOP e
3300Sstevel@tonic-gate 		= {
3310Sstevel@tonic-gate 			bundle(9, $3, ";", geta($1), $6, $5, "d", $3, ":",
3320Sstevel@tonic-gate 			    geta($1));
3330Sstevel@tonic-gate 		}
3340Sstevel@tonic-gate 	| LENGTH '(' e ')'
3350Sstevel@tonic-gate 		= bundle(2, $3, "Z");
3360Sstevel@tonic-gate 	| SCALE '(' e ')'
3370Sstevel@tonic-gate 		= bundle(2, $3, "X");	/* must be before '(' e ')' */
3380Sstevel@tonic-gate 	| '(' e ')'
3390Sstevel@tonic-gate 		= {
3400Sstevel@tonic-gate 			$$ = $2;
3410Sstevel@tonic-gate 		}
3420Sstevel@tonic-gate 	| '?'
3430Sstevel@tonic-gate 		= bundle(1, "?");
3440Sstevel@tonic-gate 	| SQRT '(' e ')'
3450Sstevel@tonic-gate 		= bundle(2, $3, "v");
3460Sstevel@tonic-gate 	| '~' LETTER
3470Sstevel@tonic-gate 		= bundle(2, "L", $2);
3480Sstevel@tonic-gate 	| SCALE '=' e
3490Sstevel@tonic-gate 		= bundle(2, $3, "dk");
3500Sstevel@tonic-gate 	| SCALE EQOP e		%prec '='
3510Sstevel@tonic-gate 		= bundle(4, "K", $3, $2, "dk");
3520Sstevel@tonic-gate 	| BASE '=' e
3530Sstevel@tonic-gate 		= bundle(2, $3, "di");
3540Sstevel@tonic-gate 	| BASE EQOP e		%prec '='
3550Sstevel@tonic-gate 		= bundle(4, "I", $3, $2, "di");
3560Sstevel@tonic-gate 	| OBASE '=' e
3570Sstevel@tonic-gate 		= bundle(2, $3, "do");
3580Sstevel@tonic-gate 	| OBASE EQOP e		%prec '='
3590Sstevel@tonic-gate 		= bundle(4, "O", $3, $2, "do");
3600Sstevel@tonic-gate 	| SCALE
3610Sstevel@tonic-gate 		= bundle(1, "K");
3620Sstevel@tonic-gate 	| BASE
3630Sstevel@tonic-gate 		= bundle(1, "I");
3640Sstevel@tonic-gate 	| OBASE
3650Sstevel@tonic-gate 		= bundle(1, "O");
3660Sstevel@tonic-gate 	;
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate cargs	: eora
3690Sstevel@tonic-gate 	| cargs ',' eora
3700Sstevel@tonic-gate 		= bundle(2, $1, $3);
3710Sstevel@tonic-gate 	;
3720Sstevel@tonic-gate eora	: e
3730Sstevel@tonic-gate 	| LETTER '[' ']'
3740Sstevel@tonic-gate 		= bundle(2, "l", geta($1));
3750Sstevel@tonic-gate 	;
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate cons	: constant
3780Sstevel@tonic-gate 		= {
3790Sstevel@tonic-gate 			*cp++ = '\0';
3800Sstevel@tonic-gate 		}
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate constant: '_'
3830Sstevel@tonic-gate 		= {
3840Sstevel@tonic-gate 			checkbuffer();
3850Sstevel@tonic-gate 			$<cptr>$ = cp;
3860Sstevel@tonic-gate 			*cp++ = '_';
3870Sstevel@tonic-gate 		}
3880Sstevel@tonic-gate 	| DIGIT
3890Sstevel@tonic-gate 		= {
3900Sstevel@tonic-gate 			checkbuffer();
3910Sstevel@tonic-gate 			$<cptr>$ = cp;
3920Sstevel@tonic-gate 			*cp++ = $1;
3930Sstevel@tonic-gate 		}
3940Sstevel@tonic-gate 	| constant DIGIT
3950Sstevel@tonic-gate 		= {
3960Sstevel@tonic-gate 			checkbuffer();
3970Sstevel@tonic-gate 			*cp++ = $2;
3980Sstevel@tonic-gate 		}
3990Sstevel@tonic-gate 	;
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate CRS	:
4020Sstevel@tonic-gate 		= {
4030Sstevel@tonic-gate 			checkbuffer();
4040Sstevel@tonic-gate 			$$ = cp;
4050Sstevel@tonic-gate 			*cp++ = crs++;
4060Sstevel@tonic-gate 			*cp++ = '\0';
4070Sstevel@tonic-gate 			if (crs == '[')
4080Sstevel@tonic-gate 				crs += 3;
4090Sstevel@tonic-gate 			if (crs == 'a')
4100Sstevel@tonic-gate 				crs = '{';
4110Sstevel@tonic-gate 			if (crs >= 0241) {
4120Sstevel@tonic-gate 				yyerror("program too big");
4130Sstevel@tonic-gate 				getout(1);
4140Sstevel@tonic-gate 			}
4150Sstevel@tonic-gate 			bstack[bindx++] = lev++;
4160Sstevel@tonic-gate 		}
4170Sstevel@tonic-gate 	;
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate def	: _DEFINE LETTER '('
4200Sstevel@tonic-gate 		= {
4210Sstevel@tonic-gate 			$$ = getf($2);
4220Sstevel@tonic-gate 			pre = (int *)"";
4230Sstevel@tonic-gate 			post = (int *)"";
4240Sstevel@tonic-gate 			lev = 1;
4250Sstevel@tonic-gate 			bstack[bindx = 0] = 0;
4260Sstevel@tonic-gate 		}
4270Sstevel@tonic-gate 	;
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate dargs	:		/* empty */
4300Sstevel@tonic-gate 	| lora
4310Sstevel@tonic-gate 		= {
4320Sstevel@tonic-gate 			pp($1);
4330Sstevel@tonic-gate 		}
4340Sstevel@tonic-gate 	| dargs ',' lora
4350Sstevel@tonic-gate 		= {
4360Sstevel@tonic-gate 			pp($3);
4370Sstevel@tonic-gate 		}
4380Sstevel@tonic-gate 	;
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate dlets	: lora
4410Sstevel@tonic-gate 		= tp($1);
4420Sstevel@tonic-gate 	| dlets ',' lora
4430Sstevel@tonic-gate 		= tp($3);
4440Sstevel@tonic-gate 	;
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate lora	: LETTER
4470Sstevel@tonic-gate 		= {
4480Sstevel@tonic-gate 			$<cptr>$ = $1;
4490Sstevel@tonic-gate 		}
4500Sstevel@tonic-gate 	| LETTER '[' ']'
4510Sstevel@tonic-gate 		= {
4520Sstevel@tonic-gate 			$$ = geta($1);
4530Sstevel@tonic-gate 		}
4540Sstevel@tonic-gate 	;
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate %%
4570Sstevel@tonic-gate #define	error	256
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate int	peekc = -1;
4600Sstevel@tonic-gate int	ifile;			/* current index into sargv */
4610Sstevel@tonic-gate int	sargc;			/* size of sargv[] */
4620Sstevel@tonic-gate char	**sargv;		/* saved arg list without options */
4630Sstevel@tonic-gate 
4640Sstevel@tonic-gate char funtab[52] = {
4650Sstevel@tonic-gate 	01, 0, 02, 0, 03, 0, 04, 0, 05, 0, 06, 0, 07, 0,
4660Sstevel@tonic-gate 	010, 0, 011, 0, 012, 0, 013, 0, 014, 0, 015, 0, 016, 0, 017, 0,
4670Sstevel@tonic-gate 	020, 0, 021, 0, 022, 0, 023, 0, 024, 0, 025, 0, 026, 0, 027, 0,
4680Sstevel@tonic-gate 	030, 0, 031, 0, 032, 0
4690Sstevel@tonic-gate };
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate unsigned char atab[52] = {
4720Sstevel@tonic-gate 	0241, 0, 0242, 0, 0243, 0, 0244, 0, 0245, 0, 0246, 0, 0247, 0, 0250, 0,
4730Sstevel@tonic-gate 	0251, 0, 0252, 0, 0253, 0, 0254, 0, 0255, 0, 0256, 0, 0257, 0, 0260, 0,
4740Sstevel@tonic-gate 	0261, 0, 0262, 0, 0263, 0, 0264, 0, 0265, 0, 0266, 0, 0267, 0, 0270, 0,
4750Sstevel@tonic-gate 	0271, 0, 0272, 0
4760Sstevel@tonic-gate };
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate char *letr[26] = {
4790Sstevel@tonic-gate 	"a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
4800Sstevel@tonic-gate 	"k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
4810Sstevel@tonic-gate 	"u", "v", "w", "x", "y", "z"
4820Sstevel@tonic-gate };
4830Sstevel@tonic-gate 
484*335Smuffin int
yylex(void)485*335Smuffin yylex(void)
4860Sstevel@tonic-gate {
4870Sstevel@tonic-gate 	int c, ch;
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate restart:
4900Sstevel@tonic-gate 	c = getch();
4910Sstevel@tonic-gate 	peekc = -1;
4920Sstevel@tonic-gate 	while (c == ' ' || c == '\t')
4930Sstevel@tonic-gate 		c = getch();
4940Sstevel@tonic-gate 	if (c == '\\') {
4950Sstevel@tonic-gate 		(void) getch();
4960Sstevel@tonic-gate 		goto restart;
4970Sstevel@tonic-gate 	}
4980Sstevel@tonic-gate 	if (c <= 'z' && c >= 'a') {
4990Sstevel@tonic-gate 		/* look ahead to look for reserved words */
5000Sstevel@tonic-gate 		peekc = getch();
5010Sstevel@tonic-gate 		if (peekc >= 'a' && peekc <= 'z') {
5020Sstevel@tonic-gate 			/* must be reserved word */
5030Sstevel@tonic-gate 			if (c == 'i' && peekc == 'f') {
5040Sstevel@tonic-gate 				c = _IF;
5050Sstevel@tonic-gate 				goto skip;
5060Sstevel@tonic-gate 			}
5070Sstevel@tonic-gate 			if (c == 'w' && peekc == 'h') {
5080Sstevel@tonic-gate 				c = _WHILE;
5090Sstevel@tonic-gate 				goto skip;
5100Sstevel@tonic-gate 			}
5110Sstevel@tonic-gate 			if (c == 'f' && peekc == 'o') {
5120Sstevel@tonic-gate 				c = _FOR;
5130Sstevel@tonic-gate 				goto skip;
5140Sstevel@tonic-gate 			}
5150Sstevel@tonic-gate 			if (c == 's' && peekc == 'q') {
5160Sstevel@tonic-gate 				c = SQRT;
5170Sstevel@tonic-gate 				goto skip;
5180Sstevel@tonic-gate 			}
5190Sstevel@tonic-gate 			if (c == 'r' && peekc == 'e') {
5200Sstevel@tonic-gate 				c = _RETURN;
5210Sstevel@tonic-gate 				goto skip;
5220Sstevel@tonic-gate 			}
5230Sstevel@tonic-gate 			if (c == 'b' && peekc == 'r') {
5240Sstevel@tonic-gate 				c = _BREAK;
5250Sstevel@tonic-gate 				goto skip;
5260Sstevel@tonic-gate 			}
5270Sstevel@tonic-gate 			if (c == 'd' && peekc == 'e') {
5280Sstevel@tonic-gate 				c = _DEFINE;
5290Sstevel@tonic-gate 				goto skip;
5300Sstevel@tonic-gate 			}
5310Sstevel@tonic-gate 			if (c == 's' && peekc == 'c') {
5320Sstevel@tonic-gate 				c = SCALE;
5330Sstevel@tonic-gate 				goto skip;
5340Sstevel@tonic-gate 			}
5350Sstevel@tonic-gate 			if (c == 'b' && peekc == 'a') {
5360Sstevel@tonic-gate 				c = BASE;
5370Sstevel@tonic-gate 				goto skip;
5380Sstevel@tonic-gate 			}
5390Sstevel@tonic-gate 			if (c == 'i' && peekc == 'b') {
5400Sstevel@tonic-gate 				c = BASE;
5410Sstevel@tonic-gate 				goto skip;
5420Sstevel@tonic-gate 			}
5430Sstevel@tonic-gate 			if (c == 'o' && peekc == 'b') {
5440Sstevel@tonic-gate 				c = OBASE;
5450Sstevel@tonic-gate 				goto skip;
5460Sstevel@tonic-gate 			}
5470Sstevel@tonic-gate 			if (c == 'd' && peekc == 'i') {
5480Sstevel@tonic-gate 				c = FFF;
5490Sstevel@tonic-gate 				goto skip;
5500Sstevel@tonic-gate 			}
5510Sstevel@tonic-gate 			if (c == 'a' && peekc == 'u') {
5520Sstevel@tonic-gate 				c = _AUTO;
5530Sstevel@tonic-gate 				goto skip;
5540Sstevel@tonic-gate 			}
5550Sstevel@tonic-gate 			if (c == 'l' && peekc == 'e') {
5560Sstevel@tonic-gate 				c = LENGTH;
5570Sstevel@tonic-gate 				goto skip;
5580Sstevel@tonic-gate 			}
5590Sstevel@tonic-gate 			if (c == 'q' && peekc == 'u') {
5600Sstevel@tonic-gate 				getout(0);
5610Sstevel@tonic-gate 			}
5620Sstevel@tonic-gate 			/* could not be found */
5630Sstevel@tonic-gate 			return (error);
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate skip:	/* skip over rest of word */
5660Sstevel@tonic-gate 			peekc = -1;
5670Sstevel@tonic-gate 			while ((ch = getch()) >= 'a' && ch <= 'z')
5680Sstevel@tonic-gate 				;
5690Sstevel@tonic-gate 			peekc = ch;
5700Sstevel@tonic-gate 			return (c);
5710Sstevel@tonic-gate 		}
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 		/* usual case; just one single letter */
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 		yylval.cptr = letr[c-'a'];
5760Sstevel@tonic-gate 		return (LETTER);
5770Sstevel@tonic-gate 	}
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate 	if (c >= '0' && c <= '9' || c >= 'A' && c <= 'F') {
5800Sstevel@tonic-gate 		yylval.cc = c;
5810Sstevel@tonic-gate 		return (DIGIT);
5820Sstevel@tonic-gate 	}
5830Sstevel@tonic-gate 
5840Sstevel@tonic-gate 	switch (c) {
5850Sstevel@tonic-gate 	case '.':
5860Sstevel@tonic-gate 		return (DOT);
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 	case '=':
5890Sstevel@tonic-gate 		switch ((peekc = getch())) {
5900Sstevel@tonic-gate 		case '=':
5910Sstevel@tonic-gate 			c = EQ;
5920Sstevel@tonic-gate 			goto gotit;
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 		case '+':
5950Sstevel@tonic-gate 			c = EQPL;
5960Sstevel@tonic-gate 			goto gotit;
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate 		case '-':
5990Sstevel@tonic-gate 			c = EQMI;
6000Sstevel@tonic-gate 			goto gotit;
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 		case '*':
6030Sstevel@tonic-gate 			c = EQMUL;
6040Sstevel@tonic-gate 			goto gotit;
6050Sstevel@tonic-gate 
6060Sstevel@tonic-gate 		case '/':
6070Sstevel@tonic-gate 			c = EQDIV;
6080Sstevel@tonic-gate 			goto gotit;
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate 		case '%':
6110Sstevel@tonic-gate 			c = EQREM;
6120Sstevel@tonic-gate 			goto gotit;
6130Sstevel@tonic-gate 
6140Sstevel@tonic-gate 		case '^':
6150Sstevel@tonic-gate 			c = EQEXP;
6160Sstevel@tonic-gate 			goto gotit;
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate 		default:
6190Sstevel@tonic-gate 			return ('=');
6200Sstevel@tonic-gate gotit:
6210Sstevel@tonic-gate 			peekc = -1;
6220Sstevel@tonic-gate 			return (c);
6230Sstevel@tonic-gate 		}
6240Sstevel@tonic-gate 
6250Sstevel@tonic-gate 	case '+':
6260Sstevel@tonic-gate 		return (cpeek('+', INCR, '=', EQPL, '+'));
6270Sstevel@tonic-gate 
6280Sstevel@tonic-gate 	case '-':
6290Sstevel@tonic-gate 		return (cpeek('-', DECR, '=', EQMI, '-'));
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 	case '*':
6320Sstevel@tonic-gate 		return (cpeek('=', EQMUL, '\0', 0, '*'));
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate 	case '%':
6350Sstevel@tonic-gate 		return (cpeek('=', EQREM, '\0', 0, '%'));
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate 	case '^':
6380Sstevel@tonic-gate 		return (cpeek('=', EQEXP, '\0', 0, '^'));
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 	case '<':
6410Sstevel@tonic-gate 		return (cpeek('=', LE, '\0', 0, '<'));
6420Sstevel@tonic-gate 
6430Sstevel@tonic-gate 	case '>':
6440Sstevel@tonic-gate 		return (cpeek('=', GE, '\0', 0, '>'));
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate 	case '!':
6470Sstevel@tonic-gate 		return (cpeek('=', NE, '\0', 0, '!'));
6480Sstevel@tonic-gate 
6490Sstevel@tonic-gate 	case '/':
6500Sstevel@tonic-gate 		if ((peekc = getch()) == '=') {
6510Sstevel@tonic-gate 			peekc = -1;
6520Sstevel@tonic-gate 			return (EQDIV);
6530Sstevel@tonic-gate 		}
6540Sstevel@tonic-gate 		if (peekc == '*') {
6550Sstevel@tonic-gate 			peekc = -1;
6560Sstevel@tonic-gate 			while ((getch() != '*') || ((peekc = getch()) != '/'))
6570Sstevel@tonic-gate 				;
6580Sstevel@tonic-gate 			peekc = -1;
6590Sstevel@tonic-gate 			goto restart;
6600Sstevel@tonic-gate 		}
6610Sstevel@tonic-gate 		else
6620Sstevel@tonic-gate 			return (c);
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate 	case '"':
6650Sstevel@tonic-gate 		yylval.cptr = str;
6660Sstevel@tonic-gate 		while ((c = getch()) != '"') {
6670Sstevel@tonic-gate 			*str++ = c;
6680Sstevel@tonic-gate 			if (str >= &string[STRING_SIZE-1]) {
6690Sstevel@tonic-gate 				yyerror("string space exceeded");
6700Sstevel@tonic-gate 				getout(1);
6710Sstevel@tonic-gate 			}
6720Sstevel@tonic-gate 		}
6730Sstevel@tonic-gate 		*str++ = '\0';
6740Sstevel@tonic-gate 		return (QSTR);
6750Sstevel@tonic-gate 
6760Sstevel@tonic-gate 	default:
6770Sstevel@tonic-gate 		return (c);
6780Sstevel@tonic-gate 	}
6790Sstevel@tonic-gate }
6800Sstevel@tonic-gate 
681*335Smuffin int
cpeek(char c1,int yes1,char c2,int yes2,char none)682*335Smuffin cpeek(char c1, int yes1, char c2, int yes2, char none)
6830Sstevel@tonic-gate {
6840Sstevel@tonic-gate 	int r;
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate 	peekc = getch();
6870Sstevel@tonic-gate 	if (peekc == c1)
6880Sstevel@tonic-gate 		r = yes1;
6890Sstevel@tonic-gate 	else if (peekc == c2)
6900Sstevel@tonic-gate 		r = yes2;
6910Sstevel@tonic-gate 	else
6920Sstevel@tonic-gate 		return (none);
6930Sstevel@tonic-gate 	peekc = -1;
6940Sstevel@tonic-gate 	return (r);
6950Sstevel@tonic-gate }
6960Sstevel@tonic-gate 
697*335Smuffin 
698*335Smuffin int
getch(void)699*335Smuffin getch(void)
7000Sstevel@tonic-gate {
7010Sstevel@tonic-gate 	int ch;
7020Sstevel@tonic-gate 	char mbuf[LINE_MAX];
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate loop:
7050Sstevel@tonic-gate 	ch = (peekc < 0) ? getc(in) : peekc;
7060Sstevel@tonic-gate 	peekc = -1;
7070Sstevel@tonic-gate 	if (ch != EOF)
7080Sstevel@tonic-gate 		return (ch);
7090Sstevel@tonic-gate 
7100Sstevel@tonic-gate 	if (++ifile >= sargc) {
7110Sstevel@tonic-gate 		if (ifile >= sargc+1)
7120Sstevel@tonic-gate 			getout(0);
7130Sstevel@tonic-gate 		in = stdin;
7140Sstevel@tonic-gate 		ln = 0;
7150Sstevel@tonic-gate 		goto loop;
7160Sstevel@tonic-gate 	}
7170Sstevel@tonic-gate 
7180Sstevel@tonic-gate 	(void) fclose(in);
7190Sstevel@tonic-gate 	if ((in = fopen(sargv[ifile], "r")) != NULL) {
7200Sstevel@tonic-gate 		ln = 0;
7210Sstevel@tonic-gate 		ss = sargv[ifile];
7220Sstevel@tonic-gate 		goto loop;
7230Sstevel@tonic-gate 	}
7240Sstevel@tonic-gate 	(void) snprintf(mbuf, sizeof (mbuf), "can't open input file %s",
7250Sstevel@tonic-gate 		sargv[ifile]);
7260Sstevel@tonic-gate 	ln = -1;
7270Sstevel@tonic-gate 	ss = "command line";
7280Sstevel@tonic-gate 	yyerror(mbuf);
7290Sstevel@tonic-gate 	getout(1);
7300Sstevel@tonic-gate 	/*NOTREACHED*/
7310Sstevel@tonic-gate }
7320Sstevel@tonic-gate 
7330Sstevel@tonic-gate #define	b_sp_max	5000
7340Sstevel@tonic-gate int b_space[b_sp_max];
7350Sstevel@tonic-gate int *b_sp_nxt = { b_space };
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate int	bdebug = 0;
7380Sstevel@tonic-gate 
7390Sstevel@tonic-gate static int *
bundle(int i,...)7400Sstevel@tonic-gate bundle(int i, ...)
7410Sstevel@tonic-gate {
7420Sstevel@tonic-gate 	va_list ap;
7430Sstevel@tonic-gate 	int *q;
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate 	va_start(ap, i);
7460Sstevel@tonic-gate 	q = b_sp_nxt;
7470Sstevel@tonic-gate 	if (bdebug)
7480Sstevel@tonic-gate 		printf("bundle %d elements at %o\n", i, q);
7490Sstevel@tonic-gate 	while (i-- > 0) {
7500Sstevel@tonic-gate 		if (b_sp_nxt >= & b_space[b_sp_max])
7510Sstevel@tonic-gate 			yyerror("bundling space exceeded");
7520Sstevel@tonic-gate 		*b_sp_nxt++ = va_arg(ap, int);
7530Sstevel@tonic-gate 	}
7540Sstevel@tonic-gate 	* b_sp_nxt++ = 0;
7550Sstevel@tonic-gate 	yyval.iptr = q;
7560Sstevel@tonic-gate 	va_end(ap);
7570Sstevel@tonic-gate 	return (q);
7580Sstevel@tonic-gate }
7590Sstevel@tonic-gate 
760*335Smuffin void
routput(int * p)761*335Smuffin routput(int *p)
7620Sstevel@tonic-gate {
7630Sstevel@tonic-gate 	if (bdebug) printf("routput(%o)\n", p);
7640Sstevel@tonic-gate 	if (p >= &b_space[0] && p < &b_space[b_sp_max]) {
7650Sstevel@tonic-gate 		/* part of a bundle */
7660Sstevel@tonic-gate 		while (*p != 0)
767*335Smuffin 			routput((int *)*p++);
7680Sstevel@tonic-gate 	}
7690Sstevel@tonic-gate 	else
7700Sstevel@tonic-gate 		printf((char *)p);	 /* character string */
7710Sstevel@tonic-gate }
7720Sstevel@tonic-gate 
773*335Smuffin void
output(int * p)774*335Smuffin output(int *p)
7750Sstevel@tonic-gate {
7760Sstevel@tonic-gate 	routput(p);
7770Sstevel@tonic-gate 	b_sp_nxt = & b_space[0];
7780Sstevel@tonic-gate 	printf("\n");
7790Sstevel@tonic-gate 	(void) fflush(stdout);
7800Sstevel@tonic-gate 	cp = cary;
7810Sstevel@tonic-gate 	crs = rcrs;
7820Sstevel@tonic-gate }
7830Sstevel@tonic-gate 
784*335Smuffin void
conout(int * p,char * s)785*335Smuffin conout(int *p, char *s)
7860Sstevel@tonic-gate {
7870Sstevel@tonic-gate 	printf("[");
7880Sstevel@tonic-gate 	routput(p);
7890Sstevel@tonic-gate 	printf("]s%s\n", s);
7900Sstevel@tonic-gate 	(void) fflush(stdout);
7910Sstevel@tonic-gate 	lev--;
7920Sstevel@tonic-gate }
7930Sstevel@tonic-gate 
794*335Smuffin void
yyerror(char * s)795*335Smuffin yyerror(char *s)
7960Sstevel@tonic-gate {
7970Sstevel@tonic-gate 	if (ifile >= sargc)
7980Sstevel@tonic-gate 		ss = "teletype";
7990Sstevel@tonic-gate 
8000Sstevel@tonic-gate 	if (ss == 0 || *ss == 0)
8010Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("%s on line %d\n"), s, ln+1);
8020Sstevel@tonic-gate 	else
8030Sstevel@tonic-gate 		(void) fprintf(stderr, gettext("%s on line %d, %s\n"),
8040Sstevel@tonic-gate 		    s, ln+1, ss);
8050Sstevel@tonic-gate 	(void) fflush(stderr);
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate 	cp = cary;
8080Sstevel@tonic-gate 	crs = rcrs;
8090Sstevel@tonic-gate 	bindx = 0;
8100Sstevel@tonic-gate 	lev = 0;
8110Sstevel@tonic-gate 	b_sp_nxt = &b_space[0];
8120Sstevel@tonic-gate }
8130Sstevel@tonic-gate 
814*335Smuffin void
checkbuffer(void)815*335Smuffin checkbuffer(void)
8160Sstevel@tonic-gate {
8170Sstevel@tonic-gate 	/* Do not exceed the last char in input line buffer */
8180Sstevel@tonic-gate 	if (cp >= cpend) {
8190Sstevel@tonic-gate 		yyerror("line too long\n");
8200Sstevel@tonic-gate 		getout(1);
8210Sstevel@tonic-gate 	}
8220Sstevel@tonic-gate }
8230Sstevel@tonic-gate 
824*335Smuffin void
pp(int * s)825*335Smuffin pp(int *s)
8260Sstevel@tonic-gate {
8270Sstevel@tonic-gate 	/* puts the relevant stuff on pre and post for the letter s */
8280Sstevel@tonic-gate 
8290Sstevel@tonic-gate 	(void) bundle(3, "S", s, pre);
8300Sstevel@tonic-gate 	pre = yyval.iptr;
8310Sstevel@tonic-gate 	(void) bundle(4, post, "L", s, "s.");
8320Sstevel@tonic-gate 	post = yyval.iptr;
8330Sstevel@tonic-gate }
8340Sstevel@tonic-gate 
835*335Smuffin void
tp(int * s)836*335Smuffin tp(int *s)
8370Sstevel@tonic-gate {		/* same as pp, but for temps */
8380Sstevel@tonic-gate 	bundle(3, "0S", s, pre);
8390Sstevel@tonic-gate 	pre = yyval.iptr;
8400Sstevel@tonic-gate 	bundle(4, post, "L", s, "s.");
8410Sstevel@tonic-gate 	post = yyval.iptr;
8420Sstevel@tonic-gate }
8430Sstevel@tonic-gate 
844*335Smuffin void
yyinit(int argc,char ** argv)845*335Smuffin yyinit(int argc, char **argv)
8460Sstevel@tonic-gate {
8470Sstevel@tonic-gate 	char	mbuf[LINE_MAX];
8480Sstevel@tonic-gate 
8490Sstevel@tonic-gate 	(void) signal(SIGINT, SIG_IGN);		/* ignore all interrupts */
8500Sstevel@tonic-gate 
8510Sstevel@tonic-gate 	sargv = argv;
8520Sstevel@tonic-gate 	sargc = argc;
8530Sstevel@tonic-gate 	if (sargc == 0)
8540Sstevel@tonic-gate 		in = stdin;
8550Sstevel@tonic-gate 	else if ((in = fopen(sargv[0], "r")) == NULL) {
8560Sstevel@tonic-gate 		(void) snprintf(mbuf, sizeof (mbuf), "can't open input file %s",
8570Sstevel@tonic-gate 			sargv[0]);
8580Sstevel@tonic-gate 		ln = -1;
8590Sstevel@tonic-gate 		ss = "command line";
8600Sstevel@tonic-gate 		yyerror(mbuf);
8610Sstevel@tonic-gate 		getout(1);
8620Sstevel@tonic-gate 	}
8630Sstevel@tonic-gate 	ifile = 0;
8640Sstevel@tonic-gate 	ln = 0;
8650Sstevel@tonic-gate 	ss = sargv[0];
8660Sstevel@tonic-gate }
8670Sstevel@tonic-gate 
868*335Smuffin static void
getout(int code)869*335Smuffin getout(int code)
8700Sstevel@tonic-gate {
8710Sstevel@tonic-gate 	printf("q");
8720Sstevel@tonic-gate 	(void) fflush(stdout);
8730Sstevel@tonic-gate 	exit(code);
8740Sstevel@tonic-gate }
8750Sstevel@tonic-gate 
8760Sstevel@tonic-gate int *
getf(char * p)877*335Smuffin getf(char *p)
8780Sstevel@tonic-gate {
8790Sstevel@tonic-gate 	return ((int *) &funtab[2*(*p -0141)]);
8800Sstevel@tonic-gate }
8810Sstevel@tonic-gate 
8820Sstevel@tonic-gate int *
geta(char * p)883*335Smuffin geta(char *p)
8840Sstevel@tonic-gate {
8850Sstevel@tonic-gate 	return ((int *) &atab[2*(*p - 0141)]);
8860Sstevel@tonic-gate }
8870Sstevel@tonic-gate 
888*335Smuffin int
main(int argc,char ** argv)889*335Smuffin main(int argc, char **argv)
8900Sstevel@tonic-gate {
8910Sstevel@tonic-gate 	int	p[2];
8920Sstevel@tonic-gate 	int	cflag = 0;
8930Sstevel@tonic-gate 	int	lflag = 0;
8940Sstevel@tonic-gate 	int	flag = 0;
8950Sstevel@tonic-gate 	char	**av;
8960Sstevel@tonic-gate 	int 	filecounter = 0;
8970Sstevel@tonic-gate 
8980Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
8990Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D */
9000Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it weren't */
9010Sstevel@tonic-gate #endif
9020Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate 	while ((flag = getopt(argc, argv, "dcl")) != EOF) {
9050Sstevel@tonic-gate 		switch (flag) {
9060Sstevel@tonic-gate 		case 'd':
9070Sstevel@tonic-gate 		case 'c':
9080Sstevel@tonic-gate 			cflag++;
9090Sstevel@tonic-gate 			break;
9100Sstevel@tonic-gate 
9110Sstevel@tonic-gate 		case 'l':
9120Sstevel@tonic-gate 			lflag++;
9130Sstevel@tonic-gate 			break;
9140Sstevel@tonic-gate 
9150Sstevel@tonic-gate 		default:
9160Sstevel@tonic-gate 			fflush(stdout);
9170Sstevel@tonic-gate 			usage();
9180Sstevel@tonic-gate 			break;
9190Sstevel@tonic-gate 		}
9200Sstevel@tonic-gate 	}
9210Sstevel@tonic-gate 
9220Sstevel@tonic-gate 	argc -= optind;
9230Sstevel@tonic-gate 	av = &argv[optind];
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate 	/*
9260Sstevel@tonic-gate 	* argc is the count of arguments, which should be filenames,
9270Sstevel@tonic-gate 	* remaining in argv. av is a pointer to the first of the
9280Sstevel@tonic-gate 	* remaining arguments.
9290Sstevel@tonic-gate 	*/
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate 	for (filecounter = 0; filecounter < argc; filecounter++) {
9320Sstevel@tonic-gate 		if ((strlen(av[filecounter])) >= PATH_MAX) {
9330Sstevel@tonic-gate 			(void) fprintf(stderr,
9340Sstevel@tonic-gate 			    gettext("File argument too long\n"));
9350Sstevel@tonic-gate 			exit(2);
9360Sstevel@tonic-gate 		}
9370Sstevel@tonic-gate 	}
9380Sstevel@tonic-gate 
9390Sstevel@tonic-gate 	if (lflag) {
9400Sstevel@tonic-gate 		/*
9410Sstevel@tonic-gate 		* if the user wants to include the math library, prepend
9420Sstevel@tonic-gate 		* the math library filename to the argument list by
9430Sstevel@tonic-gate 		* overwriting the last option (there must be at least one
9440Sstevel@tonic-gate 		* supplied option if this is being done).
9450Sstevel@tonic-gate 		*/
9460Sstevel@tonic-gate 		av = &argv[optind-1];
9470Sstevel@tonic-gate 		av[0] = "/usr/lib/lib.b";
9480Sstevel@tonic-gate 		argc++;
9490Sstevel@tonic-gate 	}
9500Sstevel@tonic-gate 
9510Sstevel@tonic-gate 	if (cflag) {
9520Sstevel@tonic-gate 		yyinit(argc, av);
9530Sstevel@tonic-gate 		yyparse();
9540Sstevel@tonic-gate 		exit(0);
9550Sstevel@tonic-gate 	}
9560Sstevel@tonic-gate 
9570Sstevel@tonic-gate 	pipe(p);
9580Sstevel@tonic-gate 	if (fork() == 0) {
9590Sstevel@tonic-gate 		(void) close(1);
9600Sstevel@tonic-gate 		dup(p[1]);
9610Sstevel@tonic-gate 		(void) close(p[0]);
9620Sstevel@tonic-gate 		(void) close(p[1]);
9630Sstevel@tonic-gate 		yyinit(argc, av);
9640Sstevel@tonic-gate 		yyparse();
9650Sstevel@tonic-gate 		exit(0);
9660Sstevel@tonic-gate 	}
9670Sstevel@tonic-gate 	(void) close(0);
9680Sstevel@tonic-gate 	dup(p[0]);
9690Sstevel@tonic-gate 	(void) close(p[0]);
9700Sstevel@tonic-gate 	(void) close(p[1]);
9710Sstevel@tonic-gate #ifdef XPG6
9720Sstevel@tonic-gate 	execl("/usr/xpg6/bin/dc", "dc", "-", 0);
9730Sstevel@tonic-gate #else
9740Sstevel@tonic-gate 	execl("/usr/bin/dc", "dc", "-", 0);
9750Sstevel@tonic-gate #endif
976*335Smuffin 
977*335Smuffin 	return (1);
9780Sstevel@tonic-gate }
9790Sstevel@tonic-gate 
9800Sstevel@tonic-gate static void
usage(void)9810Sstevel@tonic-gate usage(void)
9820Sstevel@tonic-gate {
9830Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
9840Sstevel@tonic-gate 	    "usage: bc [ -c ] [ -l ] [ file ... ]\n"));
9850Sstevel@tonic-gate 	exit(2);
9860Sstevel@tonic-gate }
987