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