xref: /csrg-svn/old/as.vax/asexpr.c (revision 593)
1 /* Copyright (c) 1980 Regents of the University of California */
2 static	char sccsid[] = "@(#)asexpr.c 4.1 08/13/80";
3 #include <stdio.h>
4 #include <sys/types.h>
5 #include "as.h"
6 #include "asexpr.h"
7 
8 /*
9  * Tables for combination of operands.
10  */
11 #define	XTXRN	5<<1		/* indexes last row/column when right shifted */
12 
13 /*
14  *	table for +
15  */
16 readonly char pltab[6][6] = {
17 /*		UND	ABS	TXT	DAT	BSS	EXT */
18 
19 /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
20 /*ABS*/		XUNDEF,	XABS,	XTEXT,	XDATA,	XBSS,	XXTRN,
21 /*TXT*/		XUNDEF,	XTEXT,	ERR,	ERR,	ERR,	ERR,
22 /*DAT*/		XUNDEF,	XDATA,	ERR,	ERR,	ERR,	ERR,
23 /*BSS*/		XUNDEF,	XBSS,	ERR,	ERR,	ERR,	ERR,
24 /*EXT*/		XUNDEF,	XXTRN,	ERR,	ERR,	ERR,	ERR,
25 };
26 
27 /*
28  *	table for -
29  */
30 readonly char mintab[6][6] = {
31 /*		UND	ABS	TXT	DAT	BSS	EXT */
32 
33 /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
34 /*ABS*/		XUNDEF,	XABS,	ERR,	ERR,	ERR,	ERR,
35 /*TXT*/		XUNDEF,	XTEXT,	XABS,	ERR,	ERR,	ERR,
36 /*DAT*/		XUNDEF,	XDATA,	ERR,	XABS,	ERR,	ERR,
37 /*BSS*/		XUNDEF,	XBSS,	ERR,	ERR,	XABS,	ERR,
38 /*EXT*/		XUNDEF,	XXTRN,	ERR,	ERR,	ERR,	ERR,
39 };
40 
41 /*
42  *	table for other operators
43  */
44 readonly char othtab[6][6] = {
45 /*		UND	ABS	TXT	DAT	BSS	EXT */
46 
47 /*UND*/		XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,	XUNDEF,
48 /*ABS*/		XUNDEF,	XABS,	ERR,	ERR,	ERR,	ERR,
49 /*TXT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
50 /*DAT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
51 /*BSS*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
52 /*EXT*/		XUNDEF,	ERR,	ERR,	ERR,	ERR,	ERR,
53 };
54 
55 struct exp *
56 combine(op, exp1, exp2)
57 	register struct exp *exp1, *exp2;
58 {
59 	register 	e1_type, e2_type;
60 	register	type;
61 
62 	lastnam=0; 			/* kludge for jxxx instructions */
63 
64 	e1_type = exp1->xtype&XTYPE;
65 	e2_type = exp2->xtype&XTYPE;
66 
67 	if (exp1->xtype==XXTRN+XUNDEF)
68 		e1_type = XTXRN;
69 	if (exp2->xtype==XXTRN+XUNDEF)
70 		e2_type = XTXRN;
71 	if (passno==1)
72 		if (exp1->xloc!=exp2->xloc && e1_type==e2_type)
73 			e1_type = e2_type = XTXRN;	/* error on != loc ctrs */
74 	e1_type >>= 1;		/*dispose of the external (XXTRN) bit*/
75 	e2_type >>= 1;
76 
77 	switch (op) {
78 	case PLUS:
79 		exp1->xvalue += exp2->xvalue;
80 		type = pltab[e1_type][e2_type];
81 		break;
82 	case MINUS:
83 		exp1->xvalue -= exp2->xvalue;
84 		type = mintab[e1_type][e2_type];
85 		break;
86 	case IOR:
87 		exp1->xvalue |= exp2->xvalue;
88 		goto comm;
89 	case XOR:
90 		exp1->xvalue ^= exp2->xvalue;
91 		goto comm;
92 	case AND:
93 		exp1->xvalue &= exp2->xvalue;
94 		goto comm;
95 	case ORNOT:
96 		exp1->xvalue |= ~exp2->xvalue;
97 		goto comm;
98 	case LSH:
99 		exp1->xvalue <<= exp2->xvalue;
100 		goto comm;
101 	case RSH:
102 		exp1->xvalue >>= exp2->xvalue;
103 		goto comm;
104 	case TILDE:
105 		exp1->xvalue |= ~ exp2->xvalue;
106 		goto comm;
107 	case MUL:
108 		exp1->xvalue *= exp2->xvalue;
109 		goto comm;
110 	case DIV:
111 		if (exp2->xvalue == 0)
112 			yyerror("Divide check");
113 		else
114 			exp1->xvalue /= exp2->xvalue;
115 		goto comm;
116 	case REGOP:
117 		if (exp2->xvalue == 0)
118 			yyerror("Divide check (modulo)");
119 		else
120 			exp1->xvalue %= exp2->xvalue;
121 		goto comm;
122 
123 	comm:
124 		type = othtab[e1_type][e2_type];
125 		break;
126 	default:
127 		yyerror("Internal error: unknown operator");
128 	}
129 
130 	if (e2_type==(XTXRN>>1))
131 		exp1->xname = exp2->xname;
132 	exp1->xtype = type | (
133 			(exp1->xtype|exp2->xtype) & (XFORW|XXTRN) );
134 	if (type==ERR)
135 		yyerror("Relocation error");
136 	return(exp1);
137 }
138 
139 buildtokensets()
140 {
141 #define clobber(val, set) tokensets[(val)] |= (set)
142 
143 	clobber(SEMI,	LINSTBEGIN);
144 	clobber(NL,	LINSTBEGIN);
145 	clobber(INT,	LINSTBEGIN);
146 
147 	clobber(NAME,	YUKKYEXPRBEG + LINSTBEGIN);
148 	clobber(INSTn,	YUKKYEXPRBEG);
149 	clobber(INST0,	YUKKYEXPRBEG);
150 	clobber(REG,	YUKKYEXPRBEG);
151 	clobber(BFINT,	YUKKYEXPRBEG);
152 
153 	clobber(INT,	SAFEEXPRBEG);
154 	clobber(FLTNUM,	SAFEEXPRBEG);
155 
156 	clobber(PLUS,	ADDOPS);
157 	clobber(MINUS,	ADDOPS + EBEGOPS);
158 
159 	clobber(LP,	EBEGOPS);
160 
161 	clobber(IOR,	BOOLOPS);
162 	clobber(XOR,	BOOLOPS);
163 	clobber(AND,	BOOLOPS);
164 	clobber(ORNOT,	BOOLOPS);
165 
166 	clobber(TILDE,	MULOPS + EBEGOPS);
167 	clobber(LSH,	MULOPS);
168 	clobber(RSH,	MULOPS);
169 	clobber(MUL,	MULOPS);
170 	clobber(DIV,	MULOPS);
171 	clobber(REGOP,	MULOPS);	/* % */
172 
173 }
174 
175 /*
176  *	We keep the current token class in this global variable, so
177  *	the recursive descent expression analyzers can talk amongst
178  *	themselves, and so that we may use the macros shift and shift over
179  */
180 
181 extern	int	yylval;		/*the value of the lexical value*/
182 extern	struct	exp	*xp;	/*the next free expression slot*/
183 
184 static int	val;
185 int exprparse(inval, backexpr)	/*return the value the read head is sitting on*/
186 	int	inval;
187 	struct	exp **backexpr;
188 {
189 	register struct exp *lexpr;
190 	int	op;
191 
192 	val = inval;
193 	lexpr = boolterm();
194 	while (INTOKSET(val, ADDOPS)){
195 		op = val;
196 		shift;
197 		lexpr = combine(op, lexpr, boolterm());
198 	}
199 	*backexpr = lexpr;
200 	return(val);
201 }
202 
203 struct exp *boolterm()
204 {
205 	register	struct exp *lexpr;
206 	int	op;
207 
208 	lexpr = term();
209 	while(INTOKSET(val, BOOLOPS)){
210 		op = val;
211 		shift;
212 		lexpr = combine(op, lexpr, term());
213 	}
214 	return(lexpr);
215 }
216 
217 struct exp *term()
218 {
219 	register	struct	exp	*lexpr;
220 	int		op;
221 
222 	lexpr = factor();
223 	while(INTOKSET(val, MULOPS)){
224 		op = val;
225 		shift;
226 		lexpr = combine(op, lexpr, factor());
227 	}
228 	return(lexpr);
229 }
230 
231 struct exp *factor()
232 {
233 	struct	exp *lexpr;
234 	int		op;
235 	extern		int	droppedLP;	/*called exprparse after consuming an LP*/
236 
237 	if (val == LP || droppedLP){
238 		if (droppedLP)
239 			droppedLP = 0;
240 		else
241 			shift;		/*the LP*/
242 		val = exprparse(val, &lexpr);
243 		if (val != RP)
244 			yyerror("right parenthesis expected");
245 		else
246 			shift;
247 	} else
248 	if (INTOKSET(val, YUKKYEXPRBEG)){
249 		lexpr = yukkyexpr(val, yylval);
250 		shift;
251 	}
252 	else if (INTOKSET(val, SAFEEXPRBEG)){
253 		lexpr = (struct exp *)yylval;
254 		shift;
255 	}
256 	else if ( (val == TILDE) || (val == MINUS) ){
257 		op = val;
258 		shift;
259 		lexpr = xp++;
260 		lexpr->xtype = XABS;
261 		lexpr->xvalue = 0;
262 		lexpr = combine(op, lexpr, factor());
263 	}
264 	else {
265 		yyerror("Bad expression syntax");
266 		lexpr = xp++;
267 		lexpr->xtype = XABS;
268 		lexpr->xvalue = 0;
269 	}
270 	return(lexpr);
271 }
272 
273 struct exp *yukkyexpr(val, np)
274 	int	val;
275 	register	np;
276 {
277 	register	struct exp *locxp;
278 	extern		int	exprisname;	/*last factor is a name*/
279 
280 	exprisname = 0;
281 	locxp = xp++;
282 	if (val == NAME || val == BFINT){
283 		if (val == BFINT) {
284 			int off = 0;
285 			yylval = ((struct exp *)np)->xvalue;
286 			if (yylval < 0) {
287 				yylval = -yylval;
288 				yylval--;
289 				off = -1;
290 				if (lgensym[yylval] == 1)
291 					yyerror("Reference to undefined local label %db", yylval);
292 			} else {
293 				yylval--;
294 				genref[yylval] = 1;
295 			}
296 			sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off);
297 			yylval = np = (int)*lookup(passno == 1);
298 			lastnam = (struct symtab *)np;
299 		}
300 		exprisname++;
301 		locxp->xtype = ((struct symtab *)np)->type;
302 		if (( ((struct symtab *)np)->type&XTYPE)==XUNDEF) { /*forward*/
303 			locxp->xname = (struct symtab *)np;
304 			locxp->xvalue = 0;
305 			if (passno==1)
306 				((struct symtab *)np)->type |= XFORW;
307 		} else {	/*otherwise, just get the value*/
308 			locxp->xvalue = ((struct symtab *)np)->value;
309 			locxp->xname = NULL;
310 		}
311 	} else {	/*INSTn or INST0 or REG*/
312 		locxp->xtype = XABS;
313 		locxp->xvalue = ( (int)np) & 0xFF;
314 		locxp->xloc = 0;
315 		locxp->xname = NULL;
316 	}
317 
318 	return(locxp);
319 }
320 
321 
322 #ifdef DEBUG
323 char	*tok_name[LASTTOKEN - FIRSTTOKEN + 1];
324 struct Tok_Desc{
325 	int		tok_which;
326 	char		*tok_name;
327 } tok_desc[] = {
328 	FIRSTTOKEN,	"firsttoken",	/* 0 */
329 	ISPACE,		"ispace", 	/* 1 */
330 	IBYTE,		"ibyte", 	/* 2 */
331 	IWORD,		"iword", 	/* 3 */
332 	IINT,		"iint", 	/* 4 */
333 	ILONG,		"ilong", 	/* 5 */
334 	IDATA,		"idata", 	/* 6 */
335 	IGLOBAL,	"iglobal", 	/* 7 */
336 	ISET,		"iset", 	/* 8 */
337 	ITEXT,		"itext", 	/* 9 */
338 	ICOMM,		"icomm", 	/* 10 */
339 	ILCOMM,		"ilcomm", 	/* 11 */
340 	IFLOAT,		"ifloat", 	/* 12 */
341 	IDOUBLE,	"idouble", 	/* 13 */
342 	IORG,		"iorg", 	/* 14 */
343 	IASCII,		"iascii", 	/* 15 */
344 	IASCIZ,		"iasciz", 	/* 16 */
345 	ILSYM,		"ilsym", 	/* 17 */
346 	IFILE,		"ifile", 	/* 18 */
347 	ILINENO,	"ilineno", 	/* 19 */
348 	IABORT,		"iabort", 	/* 20 */
349 	ISTAB,		"istab", 	/* 23 */
350 	ISTABSTR,	"istabstr", 	/* 24 */
351 	ISTABNONE,	"istabnone", 	/* 25 */
352 	ISTABDOT,	"istabdot", 	/* 26 */
353 	IJXXX,		"ijxxx", 	/* 27 */
354 	IALIGN,		"ialign", 	/* 28 */
355 	INST0,		"inst0", 	/* 29 */
356 	INSTn,		"instn", 	/* 30 */
357 	BFINT,		"bfint",	/* 31 */
358 	PARSEEOF,	"parseeof",	/* 32 */
359 	ILINESKIP,	"ilineskip",	/* 33 */
360 	VOID,		"void",		/* 34 */
361 	SKIP,		"skip",		/* 35 */
362 	INT,		"int",		/* 36 */
363 	FLTNUM,		"fltnum",	/* 37 */
364 	NAME,		"name",		/* 38 */
365 	STRING,		"string",	/* 39 */
366 	QUAD,		"quad",		/* 40 */
367 	SIZESPEC,	"sizespec", 	/* 41 */
368 	REG,		"reg",		/* 42 */
369 	MUL,		"mul",		/* 43 */
370 	LITOP,		"litop",	/* 44 */
371 	LP,		"lp",		/* 45 */
372 	MP,		"mp",		/* 46 */
373 	NEEDSBUF,	"needsbuf",	/* 48 */
374 	REGOP,		"regop",	/* 49 */
375 	NL,		"nl",		/* 50 */
376 	SCANEOF,	"scaneof",	/* 51 */
377 	BADCHAR,	"badchar",	/* 52 */
378 	SP,		"sp",		/* 53 */
379 	ALPH,		"alph",		/* 54 */
380 	DIG,		"dig",		/* 55 */
381 	SQ,		"sq",		/* 56 */
382 	DQ,		"dq",		/* 57 */
383 	SH,		"sh",		/* 58 */
384 	LSH,		"lsh",		/* 59 */
385 	RSH,		"rsh",		/* 60 */
386 	MINUS,		"minus",	/* 61 */
387 	SIZEQUOTE,	"sizequote",	/* 62 */
388 	XOR,		"xor",		/* 64 */
389 	DIV,		"div",		/* 65 */
390 	SEMI,		"semi",		/* 66 */
391 	COLON,		"colon",	/* 67 */
392 	PLUS,		"plus",		/* 68 */
393 	IOR,		"ior",		/* 69 */
394 	AND,		"and",		/* 70 */
395 	TILDE,		"tilde",	/* 71 */
396 	ORNOT,		"ornot",	/* 72 */
397 	CM,		"cm",		/* 73 */
398 	LB,		"lb",		/* 74 */
399 	RB,		"rb",		/* 75 */
400 	RP,		"rp",		/* 76 */
401 	LASTTOKEN,	"lasttoken"	/* 80 */
402 };
403 /*
404  *	turn a token type into a string
405  */
406 static	int	fixed = 0;
407 char *tok_to_name(token)
408 {
409 	if (!fixed){
410 		int	i;
411 		for (i = FIRSTTOKEN; i <= LASTTOKEN; i++)
412 			tok_name[i] = "NOT ASSIGNED";
413 		for (i = FIRSTTOKEN; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){
414 			tok_name[tok_desc[i].tok_which] = tok_desc[i].tok_name;
415 		}
416 		fixed = 1;
417 	}
418 	if (FIRSTTOKEN <= token && token <= LASTTOKEN)
419 		return(tok_name[token]);
420 	else
421 		panic("Unknown token number, %d\n", token);
422 	/*NOTREACHED*/
423 }
424 #endif DEBUG
425