BSD 3 development
[unix-history] / usr / src / cmd / as / asexpr.c
CommitLineData
629188b5
JR
1/* Copyright (c) 1979 Regents of the University of California */
2#include <stdio.h>
3#include "as.h"
4#include "asexpr.h"
5
6/*
7 * Tables for combination of operands.
8 */
9
10/*
11 * table for +
12 */
13readonly char pltab[6][6] = {
14/* UND ABS TXT DAT BSS EXT */
15
16/*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF,
17/*ABS*/ XUNDEF, XABS, XTEXT, XDATA, XBSS, XXTRN,
18/*TXT*/ XUNDEF, XTEXT, ERR, ERR, ERR, ERR,
19/*DAT*/ XUNDEF, XDATA, ERR, ERR, ERR, ERR,
20/*BSS*/ XUNDEF, XBSS, ERR, ERR, ERR, ERR,
21/*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR,
22};
23
24/*
25 * table for -
26 */
27readonly char mintab[6][6] = {
28/* UND ABS TXT DAT BSS EXT */
29
30/*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF,
31/*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR,
32/*TXT*/ XUNDEF, XTEXT, XABS, ERR, ERR, ERR,
33/*DAT*/ XUNDEF, XDATA, ERR, XABS, ERR, ERR,
34/*BSS*/ XUNDEF, XBSS, ERR, ERR, XABS, ERR,
35/*EXT*/ XUNDEF, XXTRN, ERR, ERR, ERR, ERR,
36};
37
38/*
39 * table for other operators
40 */
41readonly char othtab[6][6] = {
42/* UND ABS TXT DAT BSS EXT */
43
44/*UND*/ XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF,
45/*ABS*/ XUNDEF, XABS, ERR, ERR, ERR, ERR,
46/*TXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR,
47/*DAT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR,
48/*BSS*/ XUNDEF, ERR, ERR, ERR, ERR, ERR,
49/*EXT*/ XUNDEF, ERR, ERR, ERR, ERR, ERR,
50};
51
52struct exp *
53combine(op, exp1, exp2)
54 register struct exp *exp1, *exp2;
55{
56 register e1_type, e2_type;
57 register type;
58
59 lastnam=0; /* kludge for jxxx instructions */
60
61 e1_type = exp1->xtype&XTYPE;
62 e2_type = exp2->xtype&XTYPE;
63
64 if (exp1->xtype==XXTRN+XUNDEF)
65 e1_type = XTXRN;
66 if (exp2->xtype==XXTRN+XUNDEF)
67 e2_type = XTXRN;
68 if (passno==1)
69 if (exp1->xloc!=exp2->xloc && e1_type==e2_type)
70 e1_type = e2_type = XTXRN; /* error on != loc ctrs */
71 e1_type >>= 1; /*dispost of the external (XXTRN) bit*/
72 e2_type >>= 1;
73
74 switch (op) {
75 case PLUS:
76 exp1->xvalue += exp2->xvalue;
77 type = pltab[e1_type][e2_type];
78 break;
79 case MINUS:
80 exp1->xvalue -= exp2->xvalue;
81 type = mintab[e1_type][e2_type];
82 break;
83 case IOR:
84 exp1->xvalue |= exp2->xvalue;
85 goto comm;
86 case XOR:
87 exp1->xvalue ^= exp2->xvalue;
88 goto comm;
89 case AND:
90 exp1->xvalue &= exp2->xvalue;
91 goto comm;
92 case ORNOT:
93 exp1->xvalue |= ~exp2->xvalue;
94 goto comm;
95 case LSH:
96 exp1->xvalue <<= exp2->xvalue;
97 goto comm;
98 case RSH:
99 exp1->xvalue >>= exp2->xvalue;
100 goto comm;
101 case TILDE:
102 exp1->xvalue |= ~ exp2->xvalue;
103 goto comm;
104 case MUL:
105 exp1->xvalue *= exp2->xvalue;
106 goto comm;
107 case DIV:
108 if (exp2->xvalue == 0)
109 yyerror("Divide check");
110 else
111 exp1->xvalue /= exp2->xvalue;
112 goto comm;
113 case REGOP:
114 if (exp2->xvalue == 0)
115 yyerror("Divide check (modulo)");
116 else
117 exp1->xvalue %= exp2->xvalue;
118 goto comm;
119
120 comm:
121 type = othtab[e1_type][e2_type];
122 break;
123 default:
124 yyerror("Internal error: unknown operator");
125 }
126
127 if (e2_type==(XTXRN>>1))
128 exp1->xname = exp2->xname;
129 exp1->xtype = type | (
130 (exp1->xtype|exp2->xtype) & (XFORW|XXTRN) );
131 if (type==ERR)
132 yyerror("Relocation error");
133 return(exp1);
134}
135
136buildtokensets()
137{
138#define clobber(val, set) tokensets[(val)] |= (set)
139
140 clobber(SEMI, LINSTBEGIN);
141 clobber(NL, LINSTBEGIN);
142
143 clobber(NAME, YUKKYEXPRBEG + LINSTBEGIN);
144 clobber(INSTn, YUKKYEXPRBEG);
145 clobber(INST0, YUKKYEXPRBEG);
146 clobber(REG, YUKKYEXPRBEG);
147
148 clobber(INT, SAFEEXPRBEG);
149 clobber(FLTNUM, SAFEEXPRBEG);
150
151 clobber(PLUS, ADDOPS);
152 clobber(MINUS, ADDOPS + EBEGOPS);
153
154 clobber(LP, EBEGOPS);
155
156 clobber(IOR, BOOLOPS);
157 clobber(XOR, BOOLOPS);
158 clobber(AND, BOOLOPS);
159 clobber(ORNOT, BOOLOPS);
160
161 clobber(TILDE, MULOPS + EBEGOPS);
162 clobber(LSH, MULOPS);
163 clobber(RSH, MULOPS);
164 clobber(MUL, MULOPS);
165 clobber(DIV, MULOPS);
166 clobber(REGOP, MULOPS); /* % */
167}
168
169/*
170 * We keep the current token class in this global variable, so
171 * the recursive descent expression analyzers can talk amongst
172 * themselves, and so that we may use the macros shift and shift over
173 */
174
175extern int yylval; /*the value of the lexical value*/
176extern struct exp *xp; /*the next free expression slot*/
177
178static int val;
179int exprparse(inval, backexpr) /*return the value the read head is sitting on*/
180 int inval;
181 struct exp **backexpr;
182{
183 register struct exp *lexpr;
184 int op;
185
186 val = inval;
187 lexpr = boolterm();
188 while (INTOKSET(val, ADDOPS)){
189 op = val;
190 shift;
191 lexpr = combine(op, lexpr, boolterm());
192 }
193 *backexpr = lexpr;
194 return(val);
195}
196
197struct exp *boolterm()
198{
199 register struct exp *lexpr;
200 int op;
201
202 lexpr = term();
203 while(INTOKSET(val, BOOLOPS)){
204 op = val;
205 shift;
206 lexpr = combine(op, lexpr, term());
207 }
208 return(lexpr);
209}
210
211struct exp *term()
212{
213 register struct exp *lexpr;
214 int op;
215
216 lexpr = factor();
217 while(INTOKSET(val, MULOPS)){
218 op = val;
219 shift;
220 lexpr = combine(op, lexpr, factor());
221 }
222 return(lexpr);
223}
224
225struct exp *factor()
226{
227 struct exp *lexpr;
228 int op;
229 extern int droppedLP; /*called exprparse after consuming an LP*/
230
231 if (val == LP || droppedLP){
232 if (droppedLP)
233 droppedLP = 0;
234 else
235 shift; /*the LP*/
236 val = exprparse(val, &lexpr);
237 if (val != RP)
238 yyerror("right parenthesis expected");
239 else
240 shift;
241 } else
242 if (INTOKSET(val, YUKKYEXPRBEG)){
243 lexpr = yukkyexpr(val, yylval);
244 shift;
245 }
246 else if (INTOKSET(val, SAFEEXPRBEG)){
247 lexpr = (struct exp *)yylval;
248 shift;
249 }
250 else if ( (val == TILDE) || (val == MINUS) ){
251 op = val;
252 shift;
253 lexpr = xp++;
254 lexpr->xtype = XABS;
255 lexpr->xvalue = 0;
256 lexpr = combine(op, lexpr, factor());
257 }
258 else {
259 yyerror("Bad expression syntax");
260 lexpr = xp++;
261 lexpr->xtype = XABS;
262 lexpr->xvalue = 0;
263 }
264 return(lexpr);
265}
266
267struct exp *yukkyexpr(val, np)
268 int val;
269 register np;
270{
271 register struct exp *locxp;
272 extern int exprisname; /*last factor is a name*/
273
274 exprisname = 0;
275 locxp = xp++;
276 if (val == NAME){
277 exprisname++;
278 locxp->xtype = ((struct symtab *)np)->type;
279 if (( ((struct symtab *)np)->type&XTYPE)==XUNDEF) { /*forward*/
280 locxp->xname = (struct symtab *)np;
281 locxp->xvalue = 0;
282 if (passno==1)
283 ((struct symtab *)np)->type |= XFORW;
284 } else { /*otherwise, just get the value*/
285 locxp->xvalue = ((struct symtab *)np)->value;
286 locxp->xname = NULL;
287 }
288 } else { /*INSTn or INST0 or REG*/
289 locxp->xtype = XABS;
290 locxp->xvalue = ( (int)np) & 0xFF;
291 locxp->xloc = 0;
292 locxp->xname = NULL;
293 }
294
295 return(locxp);
296}