xref: /plan9/sys/src/cmd/hoc/hoc.y (revision 1066d6debf4f3ce80fbab98c906650d920c13a7a)
13e12c5d1SDavid du Colombier %{
23e12c5d1SDavid du Colombier #include "hoc.h"
33e12c5d1SDavid du Colombier #define	code2(c1,c2)	code(c1); code(c2)
43e12c5d1SDavid du Colombier #define	code3(c1,c2,c3)	code(c1); code(c2); code(c3)
53e12c5d1SDavid du Colombier %}
63e12c5d1SDavid du Colombier %union {
73e12c5d1SDavid du Colombier 	Symbol	*sym;	/* symbol table pointer */
83e12c5d1SDavid du Colombier 	Inst	*inst;	/* machine instruction */
93e12c5d1SDavid du Colombier 	int	narg;	/* number of arguments */
107dd7cddfSDavid du Colombier 	Formal	*formals;	/* list of formal parameters */
113e12c5d1SDavid du Colombier }
123e12c5d1SDavid du Colombier %token	<sym>	NUMBER STRING PRINT VAR BLTIN UNDEF WHILE FOR IF ELSE
133e12c5d1SDavid du Colombier %token	<sym>	FUNCTION PROCEDURE RETURN FUNC PROC READ
147dd7cddfSDavid du Colombier %type	<formals>	formals
153e12c5d1SDavid du Colombier %type	<inst>	expr stmt asgn prlist stmtlist
163e12c5d1SDavid du Colombier %type	<inst>	cond while for if begin end
173e12c5d1SDavid du Colombier %type	<sym>	procname
183e12c5d1SDavid du Colombier %type	<narg>	arglist
193e12c5d1SDavid du Colombier %right	'=' ADDEQ SUBEQ MULEQ DIVEQ MODEQ
203e12c5d1SDavid du Colombier %left	OR
213e12c5d1SDavid du Colombier %left	AND
223e12c5d1SDavid du Colombier %left	GT GE LT LE EQ NE
233e12c5d1SDavid du Colombier %left	'+' '-'
243e12c5d1SDavid du Colombier %left	'*' '/' '%'
253e12c5d1SDavid du Colombier %left	UNARYMINUS NOT INC DEC
263e12c5d1SDavid du Colombier %right	'^'
273e12c5d1SDavid du Colombier %%
283e12c5d1SDavid du Colombier list:	  /* nothing */
293e12c5d1SDavid du Colombier 	| list '\n'
303e12c5d1SDavid du Colombier 	| list defn '\n'
313e12c5d1SDavid du Colombier 	| list asgn '\n'  { code2(xpop, STOP); return 1; }
323e12c5d1SDavid du Colombier 	| list stmt '\n'  { code(STOP); return 1; }
333e12c5d1SDavid du Colombier 	| list expr '\n'  { code2(printtop, STOP); return 1; }
343e12c5d1SDavid du Colombier 	| list error '\n' { yyerrok; }
353e12c5d1SDavid du Colombier 	;
363e12c5d1SDavid du Colombier asgn:	  VAR '=' expr { code3(varpush,(Inst)$1,assign); $$=$3; }
373e12c5d1SDavid du Colombier 	| VAR ADDEQ expr	{ code3(varpush,(Inst)$1,addeq); $$=$3; }
383e12c5d1SDavid du Colombier 	| VAR SUBEQ expr	{ code3(varpush,(Inst)$1,subeq); $$=$3; }
393e12c5d1SDavid du Colombier 	| VAR MULEQ expr	{ code3(varpush,(Inst)$1,muleq); $$=$3; }
403e12c5d1SDavid du Colombier 	| VAR DIVEQ expr	{ code3(varpush,(Inst)$1,diveq); $$=$3; }
413e12c5d1SDavid du Colombier 	| VAR MODEQ expr	{ code3(varpush,(Inst)$1,modeq); $$=$3; }
423e12c5d1SDavid du Colombier 	;
433e12c5d1SDavid du Colombier stmt:	  expr	{ code(xpop); }
443e12c5d1SDavid du Colombier 	| RETURN { defnonly("return"); code(procret); }
453e12c5d1SDavid du Colombier 	| RETURN expr
463e12c5d1SDavid du Colombier 	        { defnonly("return"); $$=$2; code(funcret); }
473e12c5d1SDavid du Colombier 	| PROCEDURE begin '(' arglist ')'
483e12c5d1SDavid du Colombier 		{ $$ = $2; code3(call, (Inst)$1, (Inst)$4); }
493e12c5d1SDavid du Colombier 	| PRINT prlist	{ $$ = $2; }
503e12c5d1SDavid du Colombier 	| while '(' cond ')' stmt end {
513e12c5d1SDavid du Colombier 		($1)[1] = (Inst)$5;	/* body of loop */
523e12c5d1SDavid du Colombier 		($1)[2] = (Inst)$6; }	/* end, if cond fails */
533e12c5d1SDavid du Colombier 	| for '(' cond ';' cond ';' cond ')' stmt end {
543e12c5d1SDavid du Colombier 		($1)[1] = (Inst)$5;	/* condition */
553e12c5d1SDavid du Colombier 		($1)[2] = (Inst)$7;	/* post loop */
563e12c5d1SDavid du Colombier 		($1)[3] = (Inst)$9;	/* body of loop */
573e12c5d1SDavid du Colombier 		($1)[4] = (Inst)$10; }	/* end, if cond fails */
583e12c5d1SDavid du Colombier 	| if '(' cond ')' stmt end {	/* else-less if */
593e12c5d1SDavid du Colombier 		($1)[1] = (Inst)$5;	/* thenpart */
603e12c5d1SDavid du Colombier 		($1)[3] = (Inst)$6; }	/* end, if cond fails */
613e12c5d1SDavid du Colombier 	| if '(' cond ')' stmt end ELSE stmt end {	/* if with else */
623e12c5d1SDavid du Colombier 		($1)[1] = (Inst)$5;	/* thenpart */
633e12c5d1SDavid du Colombier 		($1)[2] = (Inst)$8;	/* elsepart */
643e12c5d1SDavid du Colombier 		($1)[3] = (Inst)$9; }	/* end, if cond fails */
653e12c5d1SDavid du Colombier 	| '{' stmtlist '}'	{ $$ = $2; }
663e12c5d1SDavid du Colombier 	;
673e12c5d1SDavid du Colombier cond:	   expr 	{ code(STOP); }
683e12c5d1SDavid du Colombier 	;
693e12c5d1SDavid du Colombier while:	  WHILE	{ $$ = code3(whilecode,STOP,STOP); }
703e12c5d1SDavid du Colombier 	;
713e12c5d1SDavid du Colombier for:	  FOR	{ $$ = code(forcode); code3(STOP,STOP,STOP); code(STOP); }
723e12c5d1SDavid du Colombier 	;
733e12c5d1SDavid du Colombier if:	  IF	{ $$ = code(ifcode); code3(STOP,STOP,STOP); }
743e12c5d1SDavid du Colombier 	;
753e12c5d1SDavid du Colombier begin:	  /* nothing */		{ $$ = progp; }
763e12c5d1SDavid du Colombier 	;
773e12c5d1SDavid du Colombier end:	  /* nothing */		{ code(STOP); $$ = progp; }
783e12c5d1SDavid du Colombier 	;
793e12c5d1SDavid du Colombier stmtlist: /* nothing */		{ $$ = progp; }
803e12c5d1SDavid du Colombier 	| stmtlist '\n'
813e12c5d1SDavid du Colombier 	| stmtlist stmt
823e12c5d1SDavid du Colombier 	;
833e12c5d1SDavid du Colombier expr:	  NUMBER { $$ = code2(constpush, (Inst)$1); }
843e12c5d1SDavid du Colombier 	| VAR	 { $$ = code3(varpush, (Inst)$1, eval); }
853e12c5d1SDavid du Colombier 	| asgn
863e12c5d1SDavid du Colombier 	| FUNCTION begin '(' arglist ')'
873e12c5d1SDavid du Colombier 		{ $$ = $2; code3(call,(Inst)$1,(Inst)$4); }
883e12c5d1SDavid du Colombier 	| READ '(' VAR ')' { $$ = code2(varread, (Inst)$3); }
893e12c5d1SDavid du Colombier 	| BLTIN '(' expr ')' { $$=$3; code2(bltin, (Inst)$1->u.ptr); }
903e12c5d1SDavid du Colombier 	| '(' expr ')'	{ $$ = $2; }
913e12c5d1SDavid du Colombier 	| expr '+' expr	{ code(add); }
923e12c5d1SDavid du Colombier 	| expr '-' expr	{ code(sub); }
933e12c5d1SDavid du Colombier 	| expr '*' expr	{ code(mul); }
943e12c5d1SDavid du Colombier 	| expr '/' expr	{ code(div); }
953e12c5d1SDavid du Colombier 	| expr '%' expr	{ code(mod); }
963e12c5d1SDavid du Colombier 	| expr '^' expr	{ code (power); }
973e12c5d1SDavid du Colombier 	| '-' expr   %prec UNARYMINUS   { $$=$2; code(negate); }
983e12c5d1SDavid du Colombier 	| expr GT expr	{ code(gt); }
993e12c5d1SDavid du Colombier 	| expr GE expr	{ code(ge); }
1003e12c5d1SDavid du Colombier 	| expr LT expr	{ code(lt); }
1013e12c5d1SDavid du Colombier 	| expr LE expr	{ code(le); }
1023e12c5d1SDavid du Colombier 	| expr EQ expr	{ code(eq); }
1033e12c5d1SDavid du Colombier 	| expr NE expr	{ code(ne); }
1043e12c5d1SDavid du Colombier 	| expr AND expr	{ code(and); }
1053e12c5d1SDavid du Colombier 	| expr OR expr	{ code(or); }
1063e12c5d1SDavid du Colombier 	| NOT expr	{ $$ = $2; code(not); }
1073e12c5d1SDavid du Colombier 	| INC VAR	{ $$ = code2(preinc,(Inst)$2); }
1083e12c5d1SDavid du Colombier 	| DEC VAR	{ $$ = code2(predec,(Inst)$2); }
1093e12c5d1SDavid du Colombier 	| VAR INC	{ $$ = code2(postinc,(Inst)$1); }
1103e12c5d1SDavid du Colombier 	| VAR DEC	{ $$ = code2(postdec,(Inst)$1); }
1113e12c5d1SDavid du Colombier 	;
1123e12c5d1SDavid du Colombier prlist:	  expr			{ code(prexpr); }
1133e12c5d1SDavid du Colombier 	| STRING		{ $$ = code2(prstr, (Inst)$1); }
1143e12c5d1SDavid du Colombier 	| prlist ',' expr	{ code(prexpr); }
1153e12c5d1SDavid du Colombier 	| prlist ',' STRING	{ code2(prstr, (Inst)$3); }
1163e12c5d1SDavid du Colombier 	;
1173e12c5d1SDavid du Colombier defn:	  FUNC procname { $2->type=FUNCTION; indef=1; }
1187dd7cddfSDavid du Colombier 	    '(' formals ')' stmt { code(procret); define($2, $5); indef=0; }
1193e12c5d1SDavid du Colombier 	| PROC procname { $2->type=PROCEDURE; indef=1; }
1207dd7cddfSDavid du Colombier 	    '(' formals ')' stmt { code(procret); define($2, $5); indef=0; }
1217dd7cddfSDavid du Colombier 	;
1227dd7cddfSDavid du Colombier formals:	{ $$ = 0; }
1237dd7cddfSDavid du Colombier 	| VAR			{ $$ = formallist($1, 0); }
1247dd7cddfSDavid du Colombier 	| VAR ',' formals	{ $$ = formallist($1, $3); }
1253e12c5d1SDavid du Colombier 	;
1263e12c5d1SDavid du Colombier procname: VAR
1273e12c5d1SDavid du Colombier 	| FUNCTION
1283e12c5d1SDavid du Colombier 	| PROCEDURE
1293e12c5d1SDavid du Colombier 	;
1303e12c5d1SDavid du Colombier arglist:  /* nothing */ 	{ $$ = 0; }
1313e12c5d1SDavid du Colombier 	| expr			{ $$ = 1; }
1323e12c5d1SDavid du Colombier 	| arglist ',' expr	{ $$ = $1 + 1; }
1333e12c5d1SDavid du Colombier 	;
1343e12c5d1SDavid du Colombier %%
1353e12c5d1SDavid du Colombier 	/* end of grammar */
1363e12c5d1SDavid du Colombier #include <u.h>
1373e12c5d1SDavid du Colombier #include <libc.h>
1383e12c5d1SDavid du Colombier #include <bio.h>
1393e12c5d1SDavid du Colombier #include <ctype.h>
1403e12c5d1SDavid du Colombier char	*progname;
1413e12c5d1SDavid du Colombier int	lineno = 1;
1423e12c5d1SDavid du Colombier jmp_buf	begin;
1433e12c5d1SDavid du Colombier int	indef;
1443e12c5d1SDavid du Colombier char	*infile;	/* input file name */
1453e12c5d1SDavid du Colombier Biobuf	*bin;		/* input file descriptor */
1463e12c5d1SDavid du Colombier Biobuf	binbuf;
1473e12c5d1SDavid du Colombier char	**gargv;	/* global argument list */
1483e12c5d1SDavid du Colombier int	gargc;
1493e12c5d1SDavid du Colombier 
1503e12c5d1SDavid du Colombier int c = '\n';	/* global for use by warning() */
1513e12c5d1SDavid du Colombier 
1523e12c5d1SDavid du Colombier int	backslash(int), follow(int, int, int);
1533e12c5d1SDavid du Colombier void	defnonly(char*), run(void);
1543e12c5d1SDavid du Colombier void	warning(char*, char*);
1553e12c5d1SDavid du Colombier 
1563e12c5d1SDavid du Colombier yylex(void)		/* hoc6 */
1573e12c5d1SDavid du Colombier {
1583e12c5d1SDavid du Colombier 	while ((c=Bgetc(bin)) == ' ' || c == '\t')
1593e12c5d1SDavid du Colombier 		;
1603e12c5d1SDavid du Colombier 	if (c < 0)
1613e12c5d1SDavid du Colombier 		return 0;
1623e12c5d1SDavid du Colombier 	if (c == '\\') {
1633e12c5d1SDavid du Colombier 		c = Bgetc(bin);
1643e12c5d1SDavid du Colombier 		if (c == '\n') {
1653e12c5d1SDavid du Colombier 			lineno++;
1663e12c5d1SDavid du Colombier 			return yylex();
1673e12c5d1SDavid du Colombier 		}
1683e12c5d1SDavid du Colombier 	}
1693e12c5d1SDavid du Colombier 	if (c == '#') {		/* comment */
1703e12c5d1SDavid du Colombier 		while ((c=Bgetc(bin)) != '\n' && c >= 0)
1713e12c5d1SDavid du Colombier 			;
1723e12c5d1SDavid du Colombier 		if (c == '\n')
1733e12c5d1SDavid du Colombier 			lineno++;
1743e12c5d1SDavid du Colombier 		return c;
1753e12c5d1SDavid du Colombier 	}
1763e12c5d1SDavid du Colombier 	if (c == '.' || isdigit(c)) {	/* number */
1773e12c5d1SDavid du Colombier 		double d;
1783e12c5d1SDavid du Colombier 		Bungetc(bin);
1793e12c5d1SDavid du Colombier 		Bgetd(bin, &d);
1803e12c5d1SDavid du Colombier 		yylval.sym = install("", NUMBER, d);
1813e12c5d1SDavid du Colombier 		return NUMBER;
1823e12c5d1SDavid du Colombier 	}
183*1066d6deSDavid du Colombier 	if (isalpha(c) || c == '_' || c >= 0x80) {
1843e12c5d1SDavid du Colombier 		Symbol *s;
1853e12c5d1SDavid du Colombier 		char sbuf[100], *p = sbuf;
1863e12c5d1SDavid du Colombier 		do {
1873e12c5d1SDavid du Colombier 			if (p >= sbuf + sizeof(sbuf) - 1) {
1883e12c5d1SDavid du Colombier 				*p = '\0';
1893e12c5d1SDavid du Colombier 				execerror("name too long", sbuf);
1903e12c5d1SDavid du Colombier 			}
1913e12c5d1SDavid du Colombier 			*p++ = c;
192*1066d6deSDavid du Colombier 		} while ((c=Bgetc(bin)) >= 0 && (isalnum(c) || c == '_' || c >= 0x80));
1933e12c5d1SDavid du Colombier 		Bungetc(bin);
1943e12c5d1SDavid du Colombier 		*p = '\0';
1953e12c5d1SDavid du Colombier 		if ((s=lookup(sbuf)) == 0)
1963e12c5d1SDavid du Colombier 			s = install(sbuf, UNDEF, 0.0);
1973e12c5d1SDavid du Colombier 		yylval.sym = s;
1983e12c5d1SDavid du Colombier 		return s->type == UNDEF ? VAR : s->type;
1993e12c5d1SDavid du Colombier 	}
2003e12c5d1SDavid du Colombier 	if (c == '"') {	/* quoted string */
2013e12c5d1SDavid du Colombier 		char sbuf[100], *p;
2023e12c5d1SDavid du Colombier 		for (p = sbuf; (c=Bgetc(bin)) != '"'; p++) {
2033e12c5d1SDavid du Colombier 			if (c == '\n' || c == Beof)
2043e12c5d1SDavid du Colombier 				execerror("missing quote", "");
2053e12c5d1SDavid du Colombier 			if (p >= sbuf + sizeof(sbuf) - 1) {
2063e12c5d1SDavid du Colombier 				*p = '\0';
2073e12c5d1SDavid du Colombier 				execerror("string too long", sbuf);
2083e12c5d1SDavid du Colombier 			}
2093e12c5d1SDavid du Colombier 			*p = backslash(c);
2103e12c5d1SDavid du Colombier 		}
2113e12c5d1SDavid du Colombier 		*p = 0;
2123e12c5d1SDavid du Colombier 		yylval.sym = (Symbol *)emalloc(strlen(sbuf)+1);
2133e12c5d1SDavid du Colombier 		strcpy((char*)yylval.sym, sbuf);
2143e12c5d1SDavid du Colombier 		return STRING;
2153e12c5d1SDavid du Colombier 	}
2163e12c5d1SDavid du Colombier 	switch (c) {
2173e12c5d1SDavid du Colombier 	case '+':	return follow('+', INC, follow('=', ADDEQ, '+'));
2183e12c5d1SDavid du Colombier 	case '-':	return follow('-', DEC, follow('=', SUBEQ, '-'));
2193e12c5d1SDavid du Colombier 	case '*':	return follow('=', MULEQ, '*');
2203e12c5d1SDavid du Colombier 	case '/':	return follow('=', DIVEQ, '/');
2213e12c5d1SDavid du Colombier 	case '%':	return follow('=', MODEQ, '%');
2223e12c5d1SDavid du Colombier 	case '>':	return follow('=', GE, GT);
2233e12c5d1SDavid du Colombier 	case '<':	return follow('=', LE, LT);
2243e12c5d1SDavid du Colombier 	case '=':	return follow('=', EQ, '=');
2253e12c5d1SDavid du Colombier 	case '!':	return follow('=', NE, NOT);
2263e12c5d1SDavid du Colombier 	case '|':	return follow('|', OR, '|');
2273e12c5d1SDavid du Colombier 	case '&':	return follow('&', AND, '&');
2283e12c5d1SDavid du Colombier 	case '\n':	lineno++; return '\n';
2293e12c5d1SDavid du Colombier 	default:	return c;
2303e12c5d1SDavid du Colombier 	}
2313e12c5d1SDavid du Colombier }
2323e12c5d1SDavid du Colombier 
2333e12c5d1SDavid du Colombier backslash(int c)	/* get next char with \'s interpreted */
2343e12c5d1SDavid du Colombier {
2353e12c5d1SDavid du Colombier 	static char transtab[] = "b\bf\fn\nr\rt\t";
2363e12c5d1SDavid du Colombier 	if (c != '\\')
2373e12c5d1SDavid du Colombier 		return c;
2383e12c5d1SDavid du Colombier 	c = Bgetc(bin);
2393e12c5d1SDavid du Colombier 	if (islower(c) && strchr(transtab, c))
2403e12c5d1SDavid du Colombier 		return strchr(transtab, c)[1];
2413e12c5d1SDavid du Colombier 	return c;
2423e12c5d1SDavid du Colombier }
2433e12c5d1SDavid du Colombier 
2443e12c5d1SDavid du Colombier follow(int expect, int ifyes, int ifno)	/* look ahead for >=, etc. */
2453e12c5d1SDavid du Colombier {
2463e12c5d1SDavid du Colombier 	int c = Bgetc(bin);
2473e12c5d1SDavid du Colombier 
2483e12c5d1SDavid du Colombier 	if (c == expect)
2493e12c5d1SDavid du Colombier 		return ifyes;
2503e12c5d1SDavid du Colombier 	Bungetc(bin);
2513e12c5d1SDavid du Colombier 	return ifno;
2523e12c5d1SDavid du Colombier }
2533e12c5d1SDavid du Colombier 
2543e12c5d1SDavid du Colombier void
2553e12c5d1SDavid du Colombier yyerror(char* s)	/* report compile-time error */
2563e12c5d1SDavid du Colombier {
2573e12c5d1SDavid du Colombier /*rob
2583e12c5d1SDavid du Colombier 	warning(s, (char *)0);
2593e12c5d1SDavid du Colombier 	longjmp(begin, 0);
2603e12c5d1SDavid du Colombier rob*/
2613e12c5d1SDavid du Colombier 	execerror(s, (char *)0);
2623e12c5d1SDavid du Colombier }
2633e12c5d1SDavid du Colombier 
2643e12c5d1SDavid du Colombier void
2653e12c5d1SDavid du Colombier execerror(char* s, char* t)	/* recover from run-time error */
2663e12c5d1SDavid du Colombier {
2673e12c5d1SDavid du Colombier 	warning(s, t);
2683e12c5d1SDavid du Colombier 	Bseek(bin, 0L, 2);		/* flush rest of file */
2697dd7cddfSDavid du Colombier 	restoreall();
2703e12c5d1SDavid du Colombier 	longjmp(begin, 0);
2713e12c5d1SDavid du Colombier }
2723e12c5d1SDavid du Colombier 
2733e12c5d1SDavid du Colombier void
2743e12c5d1SDavid du Colombier fpecatch(void)	/* catch floating point exceptions */
2753e12c5d1SDavid du Colombier {
2763e12c5d1SDavid du Colombier 	execerror("floating point exception", (char *) 0);
2773e12c5d1SDavid du Colombier }
2783e12c5d1SDavid du Colombier 
2793e12c5d1SDavid du Colombier void
2803e12c5d1SDavid du Colombier intcatch(void)	/* catch interrupts */
2813e12c5d1SDavid du Colombier {
2823e12c5d1SDavid du Colombier 	execerror("interrupt", 0);
2833e12c5d1SDavid du Colombier }
2843e12c5d1SDavid du Colombier 
2853e12c5d1SDavid du Colombier void
2863e12c5d1SDavid du Colombier run(void)	/* execute until EOF */
2873e12c5d1SDavid du Colombier {
2883e12c5d1SDavid du Colombier 	setjmp(begin);
2893e12c5d1SDavid du Colombier 	for (initcode(); yyparse(); initcode())
2903e12c5d1SDavid du Colombier 		execute(progbase);
2913e12c5d1SDavid du Colombier }
2923e12c5d1SDavid du Colombier 
2933e12c5d1SDavid du Colombier void
2943e12c5d1SDavid du Colombier main(int argc, char* argv[])	/* hoc6 */
2953e12c5d1SDavid du Colombier {
2963e12c5d1SDavid du Colombier 	static int first = 1;
2973e12c5d1SDavid du Colombier #ifdef YYDEBUG
2983e12c5d1SDavid du Colombier 	extern int yydebug;
2993e12c5d1SDavid du Colombier 	yydebug=3;
3003e12c5d1SDavid du Colombier #endif
3013e12c5d1SDavid du Colombier 	progname = argv[0];
3023e12c5d1SDavid du Colombier 	init();
3033e12c5d1SDavid du Colombier 	if (argc == 1) {	/* fake an argument list */
3043e12c5d1SDavid du Colombier 		static char *stdinonly[] = { "-" };
3053e12c5d1SDavid du Colombier 
3063e12c5d1SDavid du Colombier 		gargv = stdinonly;
3073e12c5d1SDavid du Colombier 		gargc = 1;
3083e12c5d1SDavid du Colombier 	} else if (first) {	/* for interrupts */
3093e12c5d1SDavid du Colombier 		first = 0;
3103e12c5d1SDavid du Colombier 		gargv = argv+1;
3113e12c5d1SDavid du Colombier 		gargc = argc-1;
3123e12c5d1SDavid du Colombier 	}
3133e12c5d1SDavid du Colombier 	Binit(&binbuf, 0, OREAD);
3143e12c5d1SDavid du Colombier 	bin = &binbuf;
3153e12c5d1SDavid du Colombier 	while (moreinput())
3163e12c5d1SDavid du Colombier 		run();
3173e12c5d1SDavid du Colombier 	exits(0);
3183e12c5d1SDavid du Colombier }
3193e12c5d1SDavid du Colombier 
3203e12c5d1SDavid du Colombier moreinput(void)
3213e12c5d1SDavid du Colombier {
32280ee5cbfSDavid du Colombier 	char *expr;
32380ee5cbfSDavid du Colombier 	static char buf[64];
3247dd7cddfSDavid du Colombier 	int fd;
3257dd7cddfSDavid du Colombier 	static Biobuf b;
3267dd7cddfSDavid du Colombier 
3273e12c5d1SDavid du Colombier 	if (gargc-- <= 0)
3283e12c5d1SDavid du Colombier 		return 0;
3297dd7cddfSDavid du Colombier 	if (bin && bin != &binbuf)
330219b2ee8SDavid du Colombier 		Bterm(bin);
3313e12c5d1SDavid du Colombier 	infile = *gargv++;
3323e12c5d1SDavid du Colombier 	lineno = 1;
3333e12c5d1SDavid du Colombier 	if (strcmp(infile, "-") == 0) {
3343e12c5d1SDavid du Colombier 		bin = &binbuf;
3353e12c5d1SDavid du Colombier 		infile = 0;
3367dd7cddfSDavid du Colombier 		return 1;
3377dd7cddfSDavid du Colombier 	}
3387dd7cddfSDavid du Colombier 	if(strncmp(infile, "-e", 2) == 0) {
3397dd7cddfSDavid du Colombier 		if(infile[2]==0){
3407dd7cddfSDavid du Colombier 			if(gargc == 0){
3417dd7cddfSDavid du Colombier 				fprint(2, "%s: no argument for -e\n", progname);
3427dd7cddfSDavid du Colombier 				return 0;
3437dd7cddfSDavid du Colombier 			}
3447dd7cddfSDavid du Colombier 			gargc--;
3457dd7cddfSDavid du Colombier 			expr = *gargv++;
3467dd7cddfSDavid du Colombier 		}else
3477dd7cddfSDavid du Colombier 			expr = infile+2;
3487dd7cddfSDavid du Colombier 		sprint(buf, "/tmp/hocXXXXXXX");
3497dd7cddfSDavid du Colombier 		infile = mktemp(buf);
3507dd7cddfSDavid du Colombier 		fd = create(infile, ORDWR|ORCLOSE, 0600);
3517dd7cddfSDavid du Colombier 		if(fd < 0){
3527dd7cddfSDavid du Colombier 			fprint(2, "%s: can't create temp. file: %r\n", progname);
3537dd7cddfSDavid du Colombier 			return 0;
3547dd7cddfSDavid du Colombier 		}
3557dd7cddfSDavid du Colombier 		fprint(fd, "%s\n", expr);
3567dd7cddfSDavid du Colombier 		/* leave fd around; file will be removed on exit */
35780ee5cbfSDavid du Colombier 		/* the following looks weird but is required for unix version */
3587dd7cddfSDavid du Colombier 		bin = &b;
3597dd7cddfSDavid du Colombier 		seek(fd, 0, 0);
3607dd7cddfSDavid du Colombier 		Binit(bin, fd, OREAD);
3617dd7cddfSDavid du Colombier 	} else {
3627dd7cddfSDavid du Colombier 		bin=Bopen(infile, OREAD);
3637dd7cddfSDavid du Colombier 		if (bin == 0) {
3643e12c5d1SDavid du Colombier 			fprint(2, "%s: can't open %s\n", progname, infile);
3653e12c5d1SDavid du Colombier 			return moreinput();
3663e12c5d1SDavid du Colombier 		}
3677dd7cddfSDavid du Colombier 	}
3683e12c5d1SDavid du Colombier 	return 1;
3693e12c5d1SDavid du Colombier }
3703e12c5d1SDavid du Colombier 
3713e12c5d1SDavid du Colombier void
3723e12c5d1SDavid du Colombier warning(char* s, char* t)	/* print warning message */
3733e12c5d1SDavid du Colombier {
3743e12c5d1SDavid du Colombier 	fprint(2, "%s: %s", progname, s);
3753e12c5d1SDavid du Colombier 	if (t)
3763e12c5d1SDavid du Colombier 		fprint(2, " %s", t);
3773e12c5d1SDavid du Colombier 	if (infile)
3783e12c5d1SDavid du Colombier 		fprint(2, " in %s", infile);
3793e12c5d1SDavid du Colombier 	fprint(2, " near line %d\n", lineno);
3803e12c5d1SDavid du Colombier 	while (c != '\n' && c != Beof)
3813e12c5d1SDavid du Colombier 		if((c = Bgetc(bin)) == '\n')	/* flush rest of input line */
3823e12c5d1SDavid du Colombier 			lineno++;
3833e12c5d1SDavid du Colombier }
3843e12c5d1SDavid du Colombier 
3853e12c5d1SDavid du Colombier void
3863e12c5d1SDavid du Colombier defnonly(char *s)	/* warn if illegal definition */
3873e12c5d1SDavid du Colombier {
3883e12c5d1SDavid du Colombier 	if (!indef)
3893e12c5d1SDavid du Colombier 		execerror(s, "used outside definition");
3903e12c5d1SDavid du Colombier }
391