* tiny
[mascara-docs.git] / compilers / bcc / linux86-0.16.17 / as / express.c
blob51537c3a42e38c28a6707fb9f550769d840cc057
1 /* express.c - expression handler for assembler */
3 #include "syshead.h"
4 #include "const.h"
5 #include "type.h"
6 #include "address.h"
7 #include "globvar.h"
8 #include "scan.h"
9 #include "source.h"
11 FORWARD void experror P((char * err_str));
12 FORWARD void expundefined P((void));
13 FORWARD void simple2 P((void));
14 FORWARD void simple P((void));
15 FORWARD void term P((void));
16 FORWARD void factor2 P((void));
18 PUBLIC void absexpres()
20 expres();
21 chkabs();
24 /* check lastexp.data is abs */
26 PUBLIC void chkabs()
28 if (lastexp.data & RELBIT)
30 if (pass == last_pass)
31 error(ABSREQ);
32 expundefined();
36 PRIVATE void experror(err_str)
37 char * err_str;
39 error(err_str);
40 expundefined();
43 PRIVATE void expundefined()
45 if( last_pass == 1 )
46 lastexp.data = FORBIT | UNDBIT;
47 else
48 lastexp.data = UNDBIT;
51 PUBLIC void nonimpexpres()
53 expres();
54 if (lastexp.data & IMPBIT)
55 experror(NONIMPREQ);
58 /* generate relocation error if pass 2, make lastexp.data forward&undefined */
60 PUBLIC void showrelbad()
62 if (pass == last_pass)
63 error(RELBAD);
64 expundefined();
67 PUBLIC void symabsexpres()
69 getsym();
70 absexpres();
73 PUBLIC void symexpres()
75 getsym();
76 expres();
80 expres() parses expression = simple expression [op simple expression],
81 where op is =, < or >.
82 Parameters: sym, number in number, identifier from symname to lineptr - 1.
83 Returns value in lastexp.
86 PUBLIC void expres()
88 offset_t leftoffset;
90 simple();
91 leftoffset = lastexp.offset;
92 if (sym == EQOP)
94 simple2();
95 if (leftoffset == lastexp.offset)
96 lastexp.offset = -1;
97 else
98 lastexp.offset = 0;
100 else if (sym == LESSTHAN)
102 /* context-sensitive, LESSTHAN really means less than here */
103 simple2();
104 if (leftoffset < lastexp.offset)
105 lastexp.offset = -1;
106 else
107 lastexp.offset = 0;
109 else if (sym == GREATERTHAN)
111 /* context-sensitive, GREATERTHAN really means greater than here */
112 simple2();
113 if (leftoffset > lastexp.offset)
114 lastexp.offset = -1;
115 else
116 lastexp.offset = 0;
120 /* get symbol and 2nd simple expression, check both rel or both abs */
122 PRIVATE void simple2()
124 unsigned char leftdata;
126 leftdata = lastexp.data;
127 getsym();
128 simple();
129 if ((leftdata | lastexp.data) & IMPBIT ||
130 (leftdata ^ lastexp.data) & (RELBIT | SEGM))
131 showrelbad();
132 else
133 lastexp.data = (leftdata & lastexp.data) & ~(RELBIT | SEGM);
137 simple() parses simple expression = [+-] term {op term},
138 where op is +, -, or \ (OR).
141 PRIVATE void simple()
143 offset_t leftoffset;
144 unsigned char leftdata;
146 if (sym == ADDOP || sym == SUBOP)
147 lastexp.data = lastexp.offset = 0;
148 else
149 term();
150 while (TRUE)
152 leftoffset = lastexp.offset;
153 leftdata = lastexp.data;
154 if (sym == ADDOP)
156 getsym();
157 term();
158 if (leftdata & lastexp.data & RELBIT)
159 showrelbad(); /* rel + rel no good */
160 else
161 lastexp.data |= leftdata;
162 lastexp.offset += leftoffset;
164 else if (sym == SUBOP)
166 getsym();
167 term();
168 /* check not abs - rel or rel - rel with mismatch */
169 if (lastexp.data & RELBIT &&
170 (!(leftdata & RELBIT) ||
171 (leftdata | lastexp.data) & IMPBIT ||
172 (leftdata ^ lastexp.data) & (RELBIT | SEGM)))
173 showrelbad();
174 else
175 lastexp.data = ((leftdata | lastexp.data) & ~(RELBIT | SEGM))
176 | ((leftdata ^ lastexp.data) & (RELBIT | SEGM));
177 lastexp.offset = leftoffset - lastexp.offset;
179 else if (sym == OROP)
181 getsym();
182 term();
183 lastexp.data |= leftdata;
184 chkabs(); /* both must be absolute */
185 lastexp.offset |= leftoffset;
187 else
188 return;
192 /* term() parses term = factor {op factor}, where op is *, /, &, <<, or >>. */
194 PRIVATE void term()
196 offset_t leftoffset;
198 factor();
199 while (TRUE)
201 leftoffset = lastexp.offset;
202 if (sym == STAR)
204 /* context-sensitive, STAR means multiplication here */
205 factor2();
206 lastexp.offset *= leftoffset;
208 else if (sym == SLASH)
210 /* context-sensitive, SLASH means division here */
211 factor2();
212 lastexp.offset = leftoffset / lastexp.offset;
214 else if (sym == ANDOP)
216 factor2();
217 lastexp.offset &= leftoffset;
219 else if (sym == SLOP)
221 factor2();
222 lastexp.offset = leftoffset << lastexp.offset;
224 else if (sym == SROP)
226 factor2();
227 lastexp.offset = leftoffset >> lastexp.offset;
229 else
230 return;
234 /* get symbol and 2nd or later factor, check both abs */
236 PRIVATE void factor2()
238 unsigned char leftdata;
240 leftdata = lastexp.data;
241 getsym();
242 factor();
243 lastexp.data |= leftdata;
244 chkabs();
248 factor() parses factor = number | identifier | * | (expression) | ! factor,
249 ! is complementation. Returns value in lastexp.offset, possible flags
250 IMPBIT, FORBIT, RELBIT and UNDBIT in lastexp.data, and segment in SEGM
251 part of lastexp.data, and lastexp.sym at imported symbol if IMPBIT.
252 If the factor is an identifier, LOOKUP is used to get its value
253 (so the ident is installed in the symbol table if necessary, with
254 default flags inidata). If the identifier is not a label,
255 (could be imported, or later in the program), its FORBIT is set.
256 The expression FORBIT, IMPBIT, RELBIT, UNDBIT and SEGM are then
257 taken from the identifier.
260 PUBLIC void factor()
262 switch (sym)
264 case SLASH:
265 /* context-sensitive, SLASH means a hex number here */
266 context_hexconst();
267 case INTCONST:
268 lastexp.data = 0; /* absolute & not forward or undefined */
269 lastexp.offset = number;
270 getsym();
271 return;
272 case IDENT:
274 register struct sym_s *symptr;
276 symptr = gsymptr;
277 if (symptr->type & (MNREGBIT | MACBIT))
278 experror(symptr->type & MACBIT ? MACUID :
279 symptr->data & REGBIT ? REGUID : MNUID);
280 else
282 if (!(symptr->type & (LABIT | VARBIT)))
284 if( last_pass == 1 )
285 symptr->data |= FORBIT;
286 lastexp.sym = symptr;
288 if (pass != last_pass)
290 if( last_pass == 1 )
291 lastexp.data = symptr->data &
292 (FORBIT | RELBIT | UNDBIT | SEGM);
293 else
294 lastexp.data = symptr->data &
295 (RELBIT | UNDBIT | SEGM);
296 /* possible flags for pass 1 */
297 lastexp.offset = symptr->value_reg_or_op.value;
299 else
301 if ((lastexp.data = symptr->data) & IMPBIT)
302 lastexp.offset = 0; /* value != 0 for commons */
303 /* OK even if UNDBIT */
304 else
306 lastexp.offset = symptr->value_reg_or_op.value;
307 if (lastexp.data & UNDBIT)
308 experror(UNBLAB);
312 getsym();
313 return;
315 #ifndef MC6809
316 case LBRACKET:
317 if (!asld_compatible)
318 break; /* error, LPAREN is the grouping symbol */
319 getsym();
320 expres();
321 if (sym != RBRACKET)
322 error(RBEXP);
323 else
324 getsym();
325 return;
326 #endif
327 case LPAREN:
328 #ifndef MC6809
329 if (asld_compatible)
330 break; /* error, LBRACKET is the grouping symbol */
331 #endif
332 getsym();
333 expres();
334 if (sym != RPAREN)
335 error(RPEXP);
336 else
337 getsym();
338 return;
339 case NOTOP:
340 getsym();
341 factor();
342 chkabs();
343 lastexp.offset = ~lastexp.offset;
344 return;
345 case ADDOP:
346 getsym();
347 factor();
348 return;
349 case SUBOP:
350 getsym();
351 factor();
352 chkabs();
353 lastexp.offset = -lastexp.offset;
354 return;
355 case STAR:
356 /* context-sensitive, STAR means location counter here */
357 lastexp.offset = lc;
358 if ((lastexp.data = lcdata) & UNDBIT && pass == last_pass)
359 experror(UNBLAB);
360 getsym();
361 return;
363 experror(FACEXP);
367 string compare for IFC/ELSEIFC
368 expects (<string1>,<string2>)
369 returns logical value in lastexp
372 PUBLIC void scompare()
374 /* prepare flags for OK, lastexp.offset for error */
375 lastexp.data = lastexp.offset = 0;
376 if (sym != LPAREN)
377 experror(LPEXP);
378 else
380 register char *string1;
381 register char *string2;
383 for (string2 = string1 = lineptr; *string2 != ','; ++string2)
384 if (*string2 == 0 || *string2 == ')')
386 symname = string2;
387 experror(COMEXP);
388 return;
390 string2++;
391 while (*string1++ == *string2++)
393 if (string2[-1] == ')')
395 if (string1[-1] == ',')
396 lastexp.offset = TRUE; /* else leave FALSE */
397 lineptr = string2;
399 else /* FALSE, keep reading to verify syntax */
401 for (; *string2 != ')'; ++string2)
402 if (*string2 == 0 || *string2 == ',')
404 symname = string2;
405 experror(RPEXP);
407 lineptr = ++string2;
409 getsym();