xref: /csrg-svn/old/as.vax/asexpr.c (revision 630)
1593Sbill /* Copyright (c) 1980 Regents of the University of California */
2*630Shenry static	char sccsid[] = "@(#)asexpr.c 4.2 08/15/80";
3593Sbill #include <stdio.h>
4593Sbill #include "as.h"
5593Sbill #include "asexpr.h"
6593Sbill 
7593Sbill /*
8593Sbill  * Tables for combination of operands.
9593Sbill  */
10593Sbill #define	XTXRN	5<<1		/* indexes last row/column when right shifted */
11593Sbill 
12593Sbill /*
13593Sbill  *	table for +
14593Sbill  */
15593Sbill readonly char pltab[6][6] = {
16593Sbill /*		UND	ABS	TXT	DAT	BSS	EXT */
17593Sbill 
18593Sbill /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
19593Sbill /*ABS*/		XUNDEF,	XABS,	XTEXT,	XDATA,	XBSS,	XXTRN,
20593Sbill /*TXT*/		XUNDEF,	XTEXT,	ERR,	ERR,	ERR,	ERR,
21593Sbill /*DAT*/		XUNDEF,	XDATA,	ERR,	ERR,	ERR,	ERR,
22593Sbill /*BSS*/		XUNDEF,	XBSS,	ERR,	ERR,	ERR,	ERR,
23593Sbill /*EXT*/		XUNDEF,	XXTRN,	ERR,	ERR,	ERR,	ERR,
24593Sbill };
25593Sbill 
26593Sbill /*
27593Sbill  *	table for -
28593Sbill  */
29593Sbill readonly char mintab[6][6] = {
30593Sbill /*		UND	ABS	TXT	DAT	BSS	EXT */
31593Sbill 
32593Sbill /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
33593Sbill /*ABS*/		XUNDEF,	XABS,	ERR,	ERR,	ERR,	ERR,
34593Sbill /*TXT*/		XUNDEF,	XTEXT,	XABS,	ERR,	ERR,	ERR,
35593Sbill /*DAT*/		XUNDEF,	XDATA,	ERR,	XABS,	ERR,	ERR,
36593Sbill /*BSS*/		XUNDEF,	XBSS,	ERR,	ERR,	XABS,	ERR,
37593Sbill /*EXT*/		XUNDEF,	XXTRN,	ERR,	ERR,	ERR,	ERR,
38593Sbill };
39593Sbill 
40593Sbill /*
41593Sbill  *	table for other operators
42593Sbill  */
43593Sbill readonly char othtab[6][6] = {
44593Sbill /*		UND	ABS	TXT	DAT	BSS	EXT */
45593Sbill 
46593Sbill /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
47593Sbill /*ABS*/		XUNDEF,	XABS,	ERR,	ERR,	ERR,	ERR,
48593Sbill /*TXT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
49593Sbill /*DAT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
50593Sbill /*BSS*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
51593Sbill /*EXT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
52593Sbill };
53593Sbill 
54593Sbill struct exp *
55593Sbill combine(op, exp1, exp2)
56593Sbill 	register struct exp *exp1, *exp2;
57593Sbill {
58593Sbill 	register 	e1_type, e2_type;
59*630Shenry 	register	back_type;
60593Sbill 
61593Sbill 	lastnam=0; 			/* kludge for jxxx instructions */
62593Sbill 
63*630Shenry 	e1_type = exp1->e_xtype&XTYPE;
64*630Shenry 	e2_type = exp2->e_xtype&XTYPE;
65593Sbill 
66*630Shenry 	if (exp1->e_xtype==XXTRN+XUNDEF)
67593Sbill 		e1_type = XTXRN;
68*630Shenry 	if (exp2->e_xtype==XXTRN+XUNDEF)
69593Sbill 		e2_type = XTXRN;
70593Sbill 	if (passno==1)
71*630Shenry 		if (exp1->e_xloc!=exp2->e_xloc && e1_type==e2_type)
72593Sbill 			e1_type = e2_type = XTXRN;	/* error on != loc ctrs */
73593Sbill 	e1_type >>= 1;		/*dispose of the external (XXTRN) bit*/
74593Sbill 	e2_type >>= 1;
75593Sbill 
76593Sbill 	switch (op) {
77593Sbill 	case PLUS:
78*630Shenry 		exp1->e_xvalue += exp2->e_xvalue;
79*630Shenry 		back_type = pltab[e1_type][e2_type];
80593Sbill 		break;
81593Sbill 	case MINUS:
82*630Shenry 		exp1->e_xvalue -= exp2->e_xvalue;
83*630Shenry 		back_type = mintab[e1_type][e2_type];
84593Sbill 		break;
85593Sbill 	case IOR:
86*630Shenry 		exp1->e_xvalue |= exp2->e_xvalue;
87593Sbill 		goto comm;
88593Sbill 	case XOR:
89*630Shenry 		exp1->e_xvalue ^= exp2->e_xvalue;
90593Sbill 		goto comm;
91593Sbill 	case AND:
92*630Shenry 		exp1->e_xvalue &= exp2->e_xvalue;
93593Sbill 		goto comm;
94593Sbill 	case ORNOT:
95*630Shenry 		exp1->e_xvalue |= ~exp2->e_xvalue;
96593Sbill 		goto comm;
97593Sbill 	case LSH:
98*630Shenry 		exp1->e_xvalue <<= exp2->e_xvalue;
99593Sbill 		goto comm;
100593Sbill 	case RSH:
101*630Shenry 		exp1->e_xvalue >>= exp2->e_xvalue;
102593Sbill 		goto comm;
103593Sbill 	case TILDE:
104*630Shenry 		exp1->e_xvalue |= ~ exp2->e_xvalue;
105593Sbill 		goto comm;
106593Sbill 	case MUL:
107*630Shenry 		exp1->e_xvalue *= exp2->e_xvalue;
108593Sbill 		goto comm;
109593Sbill 	case DIV:
110*630Shenry 		if (exp2->e_xvalue == 0)
111593Sbill 			yyerror("Divide check");
112593Sbill 		else
113*630Shenry 			exp1->e_xvalue /= exp2->e_xvalue;
114593Sbill 		goto comm;
115593Sbill 	case REGOP:
116*630Shenry 		if (exp2->e_xvalue == 0)
117593Sbill 			yyerror("Divide check (modulo)");
118593Sbill 		else
119*630Shenry 			exp1->e_xvalue %= exp2->e_xvalue;
120593Sbill 		goto comm;
121593Sbill 
122593Sbill 	comm:
123*630Shenry 		back_type = othtab[e1_type][e2_type];
124593Sbill 		break;
125593Sbill 	default:
126593Sbill 		yyerror("Internal error: unknown operator");
127593Sbill 	}
128593Sbill 
129593Sbill 	if (e2_type==(XTXRN>>1))
130*630Shenry 		exp1->e_xname = exp2->e_xname;
131*630Shenry 	exp1->e_xtype = back_type | (
132*630Shenry 			(exp1->e_xtype|exp2->e_xtype) & (XFORW|XXTRN) );
133*630Shenry 	if (back_type==ERR)
134593Sbill 		yyerror("Relocation error");
135593Sbill 	return(exp1);
136593Sbill }
137593Sbill 
138593Sbill buildtokensets()
139593Sbill {
140593Sbill #define clobber(val, set) tokensets[(val)] |= (set)
141593Sbill 
142593Sbill 	clobber(SEMI,	LINSTBEGIN);
143593Sbill 	clobber(NL,	LINSTBEGIN);
144593Sbill 	clobber(INT,	LINSTBEGIN);
145593Sbill 
146593Sbill 	clobber(NAME,	YUKKYEXPRBEG + LINSTBEGIN);
147593Sbill 	clobber(INSTn,	YUKKYEXPRBEG);
148593Sbill 	clobber(INST0,	YUKKYEXPRBEG);
149593Sbill 	clobber(REG,	YUKKYEXPRBEG);
150593Sbill 	clobber(BFINT,	YUKKYEXPRBEG);
151593Sbill 
152593Sbill 	clobber(INT,	SAFEEXPRBEG);
153593Sbill 	clobber(FLTNUM,	SAFEEXPRBEG);
154593Sbill 
155593Sbill 	clobber(PLUS,	ADDOPS);
156593Sbill 	clobber(MINUS,	ADDOPS + EBEGOPS);
157593Sbill 
158593Sbill 	clobber(LP,	EBEGOPS);
159593Sbill 
160593Sbill 	clobber(IOR,	BOOLOPS);
161593Sbill 	clobber(XOR,	BOOLOPS);
162593Sbill 	clobber(AND,	BOOLOPS);
163593Sbill 	clobber(ORNOT,	BOOLOPS);
164593Sbill 
165593Sbill 	clobber(TILDE,	MULOPS + EBEGOPS);
166593Sbill 	clobber(LSH,	MULOPS);
167593Sbill 	clobber(RSH,	MULOPS);
168593Sbill 	clobber(MUL,	MULOPS);
169593Sbill 	clobber(DIV,	MULOPS);
170593Sbill 	clobber(REGOP,	MULOPS);	/* % */
171593Sbill 
172593Sbill }
173593Sbill 
174593Sbill /*
175593Sbill  *	We keep the current token class in this global variable, so
176593Sbill  *	the recursive descent expression analyzers can talk amongst
177593Sbill  *	themselves, and so that we may use the macros shift and shift over
178593Sbill  */
179593Sbill 
180593Sbill extern	int	yylval;		/*the value of the lexical value*/
181593Sbill extern	struct	exp	*xp;	/*the next free expression slot*/
182593Sbill 
183593Sbill static int	val;
184593Sbill int exprparse(inval, backexpr)	/*return the value the read head is sitting on*/
185593Sbill 	int	inval;
186593Sbill 	struct	exp **backexpr;
187593Sbill {
188593Sbill 	register struct exp *lexpr;
189593Sbill 	int	op;
190593Sbill 
191593Sbill 	val = inval;
192593Sbill 	lexpr = boolterm();
193593Sbill 	while (INTOKSET(val, ADDOPS)){
194593Sbill 		op = val;
195593Sbill 		shift;
196593Sbill 		lexpr = combine(op, lexpr, boolterm());
197593Sbill 	}
198593Sbill 	*backexpr = lexpr;
199593Sbill 	return(val);
200593Sbill }
201593Sbill 
202593Sbill struct exp *boolterm()
203593Sbill {
204593Sbill 	register	struct exp *lexpr;
205593Sbill 	int	op;
206593Sbill 
207593Sbill 	lexpr = term();
208593Sbill 	while(INTOKSET(val, BOOLOPS)){
209593Sbill 		op = val;
210593Sbill 		shift;
211593Sbill 		lexpr = combine(op, lexpr, term());
212593Sbill 	}
213593Sbill 	return(lexpr);
214593Sbill }
215593Sbill 
216593Sbill struct exp *term()
217593Sbill {
218593Sbill 	register	struct	exp	*lexpr;
219593Sbill 	int		op;
220593Sbill 
221593Sbill 	lexpr = factor();
222593Sbill 	while(INTOKSET(val, MULOPS)){
223593Sbill 		op = val;
224593Sbill 		shift;
225593Sbill 		lexpr = combine(op, lexpr, factor());
226593Sbill 	}
227593Sbill 	return(lexpr);
228593Sbill }
229593Sbill 
230593Sbill struct exp *factor()
231593Sbill {
232593Sbill 	struct	exp *lexpr;
233593Sbill 	int		op;
234593Sbill 	extern		int	droppedLP;	/*called exprparse after consuming an LP*/
235593Sbill 
236593Sbill 	if (val == LP || droppedLP){
237593Sbill 		if (droppedLP)
238593Sbill 			droppedLP = 0;
239593Sbill 		else
240593Sbill 			shift;		/*the LP*/
241593Sbill 		val = exprparse(val, &lexpr);
242593Sbill 		if (val != RP)
243593Sbill 			yyerror("right parenthesis expected");
244593Sbill 		else
245593Sbill 			shift;
246593Sbill 	} else
247593Sbill 	if (INTOKSET(val, YUKKYEXPRBEG)){
248593Sbill 		lexpr = yukkyexpr(val, yylval);
249593Sbill 		shift;
250593Sbill 	}
251593Sbill 	else if (INTOKSET(val, SAFEEXPRBEG)){
252593Sbill 		lexpr = (struct exp *)yylval;
253593Sbill 		shift;
254593Sbill 	}
255593Sbill 	else if ( (val == TILDE) || (val == MINUS) ){
256593Sbill 		op = val;
257593Sbill 		shift;
258593Sbill 		lexpr = xp++;
259*630Shenry 		lexpr->e_xtype = XABS;
260*630Shenry 		lexpr->e_xvalue = 0;
261593Sbill 		lexpr = combine(op, lexpr, factor());
262593Sbill 	}
263593Sbill 	else {
264593Sbill 		yyerror("Bad expression syntax");
265593Sbill 		lexpr = xp++;
266*630Shenry 		lexpr->e_xtype = XABS;
267*630Shenry 		lexpr->e_xvalue = 0;
268593Sbill 	}
269593Sbill 	return(lexpr);
270593Sbill }
271593Sbill 
272593Sbill struct exp *yukkyexpr(val, np)
273593Sbill 	int	val;
274593Sbill 	register	np;
275593Sbill {
276593Sbill 	register	struct exp *locxp;
277593Sbill 	extern		int	exprisname;	/*last factor is a name*/
278593Sbill 
279593Sbill 	exprisname = 0;
280593Sbill 	locxp = xp++;
281593Sbill 	if (val == NAME || val == BFINT){
282593Sbill 		if (val == BFINT) {
283593Sbill 			int off = 0;
284*630Shenry 			yylval = ((struct exp *)np)->e_xvalue;
285593Sbill 			if (yylval < 0) {
286593Sbill 				yylval = -yylval;
287593Sbill 				yylval--;
288593Sbill 				off = -1;
289593Sbill 				if (lgensym[yylval] == 1)
290593Sbill 					yyerror("Reference to undefined local label %db", yylval);
291593Sbill 			} else {
292593Sbill 				yylval--;
293593Sbill 				genref[yylval] = 1;
294593Sbill 			}
295593Sbill 			sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off);
296593Sbill 			yylval = np = (int)*lookup(passno == 1);
297593Sbill 			lastnam = (struct symtab *)np;
298593Sbill 		}
299593Sbill 		exprisname++;
300*630Shenry 		locxp->e_xtype = ((struct symtab *)np)->s_type;
301*630Shenry 		if (( ((struct symtab *)np)->s_type&XTYPE)==XUNDEF) { /*forward*/
302*630Shenry 			locxp->e_xname = (struct symtab *)np;
303*630Shenry 			locxp->e_xvalue = 0;
304593Sbill 			if (passno==1)
305*630Shenry 				((struct symtab *)np)->s_type |= XFORW;
306593Sbill 		} else {	/*otherwise, just get the value*/
307*630Shenry 			locxp->e_xvalue = ((struct symtab *)np)->s_value;
308*630Shenry 			locxp->e_xname = NULL;
309593Sbill 		}
310593Sbill 	} else {	/*INSTn or INST0 or REG*/
311*630Shenry 		locxp->e_xtype = XABS;
312*630Shenry 		locxp->e_xvalue = ( (int)np) & 0xFF;
313*630Shenry 		locxp->e_xloc = 0;
314*630Shenry 		locxp->e_xname = NULL;
315593Sbill 	}
316593Sbill 
317593Sbill 	return(locxp);
318593Sbill }
319593Sbill 
320593Sbill 
321593Sbill #ifdef DEBUG
322593Sbill char	*tok_name[LASTTOKEN - FIRSTTOKEN + 1];
323593Sbill struct Tok_Desc{
324593Sbill 	int		tok_which;
325593Sbill 	char		*tok_name;
326593Sbill } tok_desc[] = {
327593Sbill 	FIRSTTOKEN,	"firsttoken",	/* 0 */
328593Sbill 	ISPACE,		"ispace", 	/* 1 */
329593Sbill 	IBYTE,		"ibyte", 	/* 2 */
330593Sbill 	IWORD,		"iword", 	/* 3 */
331593Sbill 	IINT,		"iint", 	/* 4 */
332593Sbill 	ILONG,		"ilong", 	/* 5 */
333593Sbill 	IDATA,		"idata", 	/* 6 */
334593Sbill 	IGLOBAL,	"iglobal", 	/* 7 */
335593Sbill 	ISET,		"iset", 	/* 8 */
336593Sbill 	ITEXT,		"itext", 	/* 9 */
337593Sbill 	ICOMM,		"icomm", 	/* 10 */
338593Sbill 	ILCOMM,		"ilcomm", 	/* 11 */
339593Sbill 	IFLOAT,		"ifloat", 	/* 12 */
340593Sbill 	IDOUBLE,	"idouble", 	/* 13 */
341593Sbill 	IORG,		"iorg", 	/* 14 */
342593Sbill 	IASCII,		"iascii", 	/* 15 */
343593Sbill 	IASCIZ,		"iasciz", 	/* 16 */
344593Sbill 	ILSYM,		"ilsym", 	/* 17 */
345593Sbill 	IFILE,		"ifile", 	/* 18 */
346593Sbill 	ILINENO,	"ilineno", 	/* 19 */
347593Sbill 	IABORT,		"iabort", 	/* 20 */
348593Sbill 	ISTAB,		"istab", 	/* 23 */
349593Sbill 	ISTABSTR,	"istabstr", 	/* 24 */
350593Sbill 	ISTABNONE,	"istabnone", 	/* 25 */
351593Sbill 	ISTABDOT,	"istabdot", 	/* 26 */
352593Sbill 	IJXXX,		"ijxxx", 	/* 27 */
353593Sbill 	IALIGN,		"ialign", 	/* 28 */
354593Sbill 	INST0,		"inst0", 	/* 29 */
355593Sbill 	INSTn,		"instn", 	/* 30 */
356593Sbill 	BFINT,		"bfint",	/* 31 */
357593Sbill 	PARSEEOF,	"parseeof",	/* 32 */
358593Sbill 	ILINESKIP,	"ilineskip",	/* 33 */
359593Sbill 	VOID,		"void",		/* 34 */
360593Sbill 	SKIP,		"skip",		/* 35 */
361593Sbill 	INT,		"int",		/* 36 */
362593Sbill 	FLTNUM,		"fltnum",	/* 37 */
363593Sbill 	NAME,		"name",		/* 38 */
364593Sbill 	STRING,		"string",	/* 39 */
365593Sbill 	QUAD,		"quad",		/* 40 */
366593Sbill 	SIZESPEC,	"sizespec", 	/* 41 */
367593Sbill 	REG,		"reg",		/* 42 */
368593Sbill 	MUL,		"mul",		/* 43 */
369593Sbill 	LITOP,		"litop",	/* 44 */
370593Sbill 	LP,		"lp",		/* 45 */
371593Sbill 	MP,		"mp",		/* 46 */
372593Sbill 	NEEDSBUF,	"needsbuf",	/* 48 */
373593Sbill 	REGOP,		"regop",	/* 49 */
374593Sbill 	NL,		"nl",		/* 50 */
375593Sbill 	SCANEOF,	"scaneof",	/* 51 */
376593Sbill 	BADCHAR,	"badchar",	/* 52 */
377593Sbill 	SP,		"sp",		/* 53 */
378593Sbill 	ALPH,		"alph",		/* 54 */
379593Sbill 	DIG,		"dig",		/* 55 */
380593Sbill 	SQ,		"sq",		/* 56 */
381593Sbill 	DQ,		"dq",		/* 57 */
382593Sbill 	SH,		"sh",		/* 58 */
383593Sbill 	LSH,		"lsh",		/* 59 */
384593Sbill 	RSH,		"rsh",		/* 60 */
385593Sbill 	MINUS,		"minus",	/* 61 */
386593Sbill 	SIZEQUOTE,	"sizequote",	/* 62 */
387593Sbill 	XOR,		"xor",		/* 64 */
388593Sbill 	DIV,		"div",		/* 65 */
389593Sbill 	SEMI,		"semi",		/* 66 */
390593Sbill 	COLON,		"colon",	/* 67 */
391593Sbill 	PLUS,		"plus",		/* 68 */
392593Sbill 	IOR,		"ior",		/* 69 */
393593Sbill 	AND,		"and",		/* 70 */
394593Sbill 	TILDE,		"tilde",	/* 71 */
395593Sbill 	ORNOT,		"ornot",	/* 72 */
396593Sbill 	CM,		"cm",		/* 73 */
397593Sbill 	LB,		"lb",		/* 74 */
398593Sbill 	RB,		"rb",		/* 75 */
399593Sbill 	RP,		"rp",		/* 76 */
400593Sbill 	LASTTOKEN,	"lasttoken"	/* 80 */
401593Sbill };
402593Sbill /*
403593Sbill  *	turn a token type into a string
404593Sbill  */
405593Sbill static	int	fixed = 0;
406593Sbill char *tok_to_name(token)
407593Sbill {
408593Sbill 	if (!fixed){
409593Sbill 		int	i;
410593Sbill 		for (i = FIRSTTOKEN; i <= LASTTOKEN; i++)
411593Sbill 			tok_name[i] = "NOT ASSIGNED";
412593Sbill 		for (i = FIRSTTOKEN; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){
413593Sbill 			tok_name[tok_desc[i].tok_which] = tok_desc[i].tok_name;
414593Sbill 		}
415593Sbill 		fixed = 1;
416593Sbill 	}
417593Sbill 	if (FIRSTTOKEN <= token && token <= LASTTOKEN)
418593Sbill 		return(tok_name[token]);
419593Sbill 	else
420593Sbill 		panic("Unknown token number, %d\n", token);
421593Sbill 	/*NOTREACHED*/
422593Sbill }
423593Sbill #endif DEBUG
424