1 /* express.c - expression handler for assembler */
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()
24 /* check lastexp.data is abs */
28 if (lastexp
.data
& RELBIT
)
30 if (pass
== last_pass
)
36 PRIVATE
void experror(err_str
)
43 PRIVATE
void expundefined()
46 lastexp
.data
= FORBIT
| UNDBIT
;
48 lastexp
.data
= UNDBIT
;
51 PUBLIC
void nonimpexpres()
54 if (lastexp
.data
& IMPBIT
)
58 /* generate relocation error if pass 2, make lastexp.data forward&undefined */
60 PUBLIC
void showrelbad()
62 if (pass
== last_pass
)
67 PUBLIC
void symabsexpres()
73 PUBLIC
void symexpres()
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.
91 leftoffset
= lastexp
.offset
;
95 if (leftoffset
== lastexp
.offset
)
100 else if (sym
== LESSTHAN
)
102 /* context-sensitive, LESSTHAN really means less than here */
104 if (leftoffset
< lastexp
.offset
)
109 else if (sym
== GREATERTHAN
)
111 /* context-sensitive, GREATERTHAN really means greater than here */
113 if (leftoffset
> lastexp
.offset
)
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
;
129 if ((leftdata
| lastexp
.data
) & IMPBIT
||
130 (leftdata
^ lastexp
.data
) & (RELBIT
| SEGM
))
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()
144 unsigned char leftdata
;
146 if (sym
== ADDOP
|| sym
== SUBOP
)
147 lastexp
.data
= lastexp
.offset
= 0;
152 leftoffset
= lastexp
.offset
;
153 leftdata
= lastexp
.data
;
158 if (leftdata
& lastexp
.data
& RELBIT
)
159 showrelbad(); /* rel + rel no good */
161 lastexp
.data
|= leftdata
;
162 lastexp
.offset
+= leftoffset
;
164 else if (sym
== SUBOP
)
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
)))
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
)
183 lastexp
.data
|= leftdata
;
184 chkabs(); /* both must be absolute */
185 lastexp
.offset
|= leftoffset
;
192 /* term() parses term = factor {op factor}, where op is *, /, &, <<, or >>. */
201 leftoffset
= lastexp
.offset
;
204 /* context-sensitive, STAR means multiplication here */
206 lastexp
.offset
*= leftoffset
;
208 else if (sym
== SLASH
)
210 /* context-sensitive, SLASH means division here */
212 lastexp
.offset
= leftoffset
/ lastexp
.offset
;
214 else if (sym
== ANDOP
)
217 lastexp
.offset
&= leftoffset
;
219 else if (sym
== SLOP
)
222 lastexp
.offset
= leftoffset
<< lastexp
.offset
;
224 else if (sym
== SROP
)
227 lastexp
.offset
= leftoffset
>> lastexp
.offset
;
234 /* get symbol and 2nd or later factor, check both abs */
236 PRIVATE
void factor2()
238 unsigned char leftdata
;
240 leftdata
= lastexp
.data
;
243 lastexp
.data
|= leftdata
;
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.
265 /* context-sensitive, SLASH means a hex number here */
268 lastexp
.data
= 0; /* absolute & not forward or undefined */
269 lastexp
.offset
= number
;
274 register struct sym_s
*symptr
;
277 if (symptr
->type
& (MNREGBIT
| MACBIT
))
278 experror(symptr
->type
& MACBIT
? MACUID
:
279 symptr
->data
& REGBIT
? REGUID
: MNUID
);
282 if (!(symptr
->type
& (LABIT
| VARBIT
)))
285 symptr
->data
|= FORBIT
;
286 lastexp
.sym
= symptr
;
288 if (pass
!= last_pass
)
291 lastexp
.data
= symptr
->data
&
292 (FORBIT
| RELBIT
| UNDBIT
| SEGM
);
294 lastexp
.data
= symptr
->data
&
295 (RELBIT
| UNDBIT
| SEGM
);
296 /* possible flags for pass 1 */
297 lastexp
.offset
= symptr
->value_reg_or_op
.value
;
301 if ((lastexp
.data
= symptr
->data
) & IMPBIT
)
302 lastexp
.offset
= 0; /* value != 0 for commons */
303 /* OK even if UNDBIT */
306 lastexp
.offset
= symptr
->value_reg_or_op
.value
;
307 if (lastexp
.data
& UNDBIT
)
317 if (!asld_compatible
)
318 break; /* error, LPAREN is the grouping symbol */
330 break; /* error, LBRACKET is the grouping symbol */
343 lastexp
.offset
= ~lastexp
.offset
;
353 lastexp
.offset
= -lastexp
.offset
;
356 /* context-sensitive, STAR means location counter here */
358 if ((lastexp
.data
= lcdata
) & UNDBIT
&& pass
== last_pass
)
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;
380 register char *string1
;
381 register char *string2
;
383 for (string2
= string1
= lineptr
; *string2
!= ','; ++string2
)
384 if (*string2
== 0 || *string2
== ')')
391 while (*string1
++ == *string2
++)
393 if (string2
[-1] == ')')
395 if (string1
[-1] == ',')
396 lastexp
.offset
= TRUE
; /* else leave FALSE */
399 else /* FALSE, keep reading to verify syntax */
401 for (; *string2
!= ')'; ++string2
)
402 if (*string2
== 0 || *string2
== ',')