1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 #include "asm.h"
6 #include "hash.h"
7 #include "asm_token"
8
9 #define SINGLE '\''
10
11 #define HEX_PREFIX '$'
12 #define BIN_PREFIX '#'
13 #define CURRENT_PC '@'
14
15
16 int
test_label(char * txt)17 test_label(char *txt)
18 {
19 int i;
20
21 for (i=0;i<MAX_LABEL;i++)
22 if (txt[i] >= 'A' && txt[i] <= 'Z')
23 ;
24 else if (txt[i] >= 'a' && txt[i] <= 'z')
25 ;
26 else if (i && txt[i] >= '0' && txt[i] <= '9')
27 ;
28 else if (txt[i] != '_')
29 return i;
30 return 0;
31 }
32
33
34 /* a number must start with either '\'', '+', '-', digit or BIN_/HEX_PREFIX */
35 int
test_number(char * txt,int * value)36 test_number(char *txt,int *value)
37 {
38 int base;
39 char *p,*q;
40 int sign=1, a, b;
41 p=txt;
42 /* character constant */
43 if (txt[0]==SINGLE && txt[1] && txt[2]==SINGLE)
44 {
45 *value=(unsigned char)txt[1];
46 return 3;
47 }
48 if (*p=='-')
49 { sign= -1; p++; }
50 else if (*p=='+')
51 p++; /* we like it for JR, DJNZ argument */
52 base=10;
53 if (*p==BIN_PREFIX)
54 { base=2; p++; }
55 else if (*p==HEX_PREFIX)
56 { base=16; p++; }
57 else if (*p=='0' && (p[1]=='x'||p[1]=='X'))
58 { base=16; p+=2; }
59 a=b=0;
60 for (q=p ; *p ; p++)
61 {
62 if (*p >= '0' && *p <= '1')
63 ;
64 else if (*p >= '0' && *p <= '9')
65 a=1;
66 else if (!a && !b && base==10 && (*p == 'b' || *p == 'B'))
67 { if(p==q) return 0;
68 base=3;
69 }
70 else if ((*p >='a' && *p <= 'f') || (*p >='A' && *p <= 'F'))
71 { if (p==q && base!=16) return 0;
72 b=1;
73 }
74 else if (*p == 'h' || *p == 'H')
75 { if(p==q || (base!=10 && base !=3)) return 0;
76 p++; base=16;
77 break;
78 }
79 else
80 break;
81 }
82 if (base==3 && *(p-1) != 'b' && *(p-1) != 'B')
83 return 0;
84 else if (base==3)
85 base=2;
86 if (b && base != 16 || p==q)
87 return 0;
88 *value=sign*strtol(q,NULL,base);
89 return p-txt;
90 }
91
92
93 char *
resolve_current_pc_and_store(char * txt)94 resolve_current_pc_and_store(char *txt)
95 { int a, b;
96 char *p, *q;
97 for (a=b=0;txt[b];b++)
98 a += txt[b]==CURRENT_PC;
99 if (q=malloc(strlen(txt)+1+4*a))
100 for (a=0,p=q;*p=txt[a];p++,a++)
101 if (*p==CURRENT_PC)
102 { sprintf(p,"%c%.4x",HEX_PREFIX,get_current_address());
103 p += 4;
104 }
105 return q;
106 }
107
108
109 #define STACK_SIZE 16
110 #define LIST_SIZE 256
111
112 static unsigned stack_top, list_top;
113 static struct info {
114 unsigned char type;
115 int value;
116 } *stack, *list;
117
118
swap_internal_data(struct info ** new_stack,struct info ** new_list,unsigned * new_stack_top,unsigned * new_list_top)119 static void swap_internal_data( struct info **new_stack, struct info **new_list,
120 unsigned *new_stack_top, unsigned *new_list_top)
121 {
122 unsigned temp;
123 struct info *scra;
124 temp= stack_top; stack_top= *new_stack_top; *new_stack_top=temp;
125 temp=list_top; list_top= *new_list_top; *new_list_top=temp;
126 scra= *new_stack; *new_stack=stack; stack=scra;
127 scra= *new_list; *new_list=list; list=scra;
128 }
129
130
push_on_stack(unsigned typ,int val)131 static void push_on_stack(unsigned typ, int val)
132 {
133 static struct info t;
134 t.type= typ;
135 t.value= val;
136 if (stack_top < STACK_SIZE)
137 stack[stack_top++] = t;
138 }
139
140
append_to(unsigned typ,int val)141 static void append_to(unsigned typ, int val)
142 {
143 static struct info t;
144 t.type= typ;
145 t.value= val;
146 if (list_top < LIST_SIZE)
147 list[list_top++] = t;
148 }
149
150
append(struct info t)151 static void append(struct info t)
152 {
153 if (list_top < LIST_SIZE)
154 list[list_top++] = t;
155 }
156
157
skim_higher_priorities(char * lower_priorities,char binary_operator)158 static void skim_higher_priorities(char *lower_priorities, char binary_operator)
159 {
160 while (stack_top)
161 { struct info token=stack[stack_top-1];
162 if (strchr(lower_priorities,token.type))
163 break;
164 else
165 append(stack[--stack_top]);
166 }
167 push_on_stack(binary_operator,2);
168 }
169
170
171 /* return value:
172 < 0 error and this is the error code/reason
173 lexical_analysis(txt) will return |value| used in compile(txt)
174 = 0 everything ok and defined
175 > 0 expression ok, but value undefined (return type of expression?)
176 */
177 /* monadic operators and ( as well, are always pushed onto stack */
178 /* if binary operator appears, then first stack is poped until an operator
179 of low priority or equal priority and right associativity appears.
180 (so, all higher priority or equal priority and left associative operators
181 are evaluated first)
182 if ) then stack is poped including next ( appearance
183 */
184 /* Operators for stack:
185
186 30 ( 3 opening pharenthesis
187 28 ~ 1 monadic bitwise 1-complement
188 28 1 monadic plus sign
189 28 _ 1 monadic minus sign (bitwise 2-complement)
190 28 // k 1 monadic bitsize (log_2 styricly rounded up)
191 28 ? 6 monadic is_label_defined
192 26 ** l 2 binary power
193 24 % 2 binary modulo
194 24 / 2 binary division
195 24 * 2 binary multiplication
196 20 + 2 binary addition
197 20 - 2 binary subtraction
198 19 >> a 2 binary bitwise right shift /2^
199 19 << b 2 binary bitwise left shift *2^
200 18 & 2 binary bitwise-and
201 16 | 2 binary bitwise-or
202 16 ^ 2 binary bitwise-xor
203 14 ! 1 monadic boolean == 0
204 12 > c 2 binary boolean >
205 12 < d 2 binary boolean <
206 12 == e 2 binary boolean =
207 12 != f 2 binary boolean !=
208 12 >= g 2 binary boolean >=
209 12 <= h 2 binary boolean <=
210 8 && i 2 binary boolean and
211 6 || j 2 binary boolean or
212 2 ) 4 closing pharenthesis
213 0 3 nothing (start initialization)
214 @ 5 current PC
215 number 5 numbers or labels
216 */
217 int
parse_expr(char * txt,int * value,unsigned lineno)218 parse_expr(char *txt, int* value, unsigned lineno)
219 {
220 struct info token, my_stack[STACK_SIZE], my_list[LIST_SIZE];
221 struct info *my_stack_ptr=my_stack, *my_list_ptr=my_list;
222 unsigned a,t, b=3, undef=0, pruchod=compile_pass();
223 unsigned my_list_top=0, my_stack_top= 0;
224 int ret=0;
225
226 if (!txt) return -SYNT;
227 swap_internal_data(&my_stack_ptr, &my_list_ptr, &my_stack_top, &my_list_top);
228
229 for (a=0;txt[a];a+=t)
230 { t=1;
231 switch (txt[a])
232 {
233 case '>':
234 if (b != 4 && b != 5)
235 { ret=-MISO; goto finish; }
236 if (txt[a+1]=='=') /* comparision operator >= */
237 { skim_higher_priorities("(ij",'g');
238 t=2;
239 }
240 else if (txt[a+1]=='>') /* shift operator >> */
241 { skim_higher_priorities("(ijghefcd^|&",'a');
242 t=2;
243 }
244 else /* comparision operator > */
245 { skim_higher_priorities("(ij",'c');
246 }
247 b=2;
248 break;
249 case '<':
250 if (b != 4 && b != 5)
251 { ret=-MISO; goto finish; }
252 if (txt[a+1]=='=') /* comparision operator <= */
253 { skim_higher_priorities("(ij",'h');
254 t=2;
255 }
256 else if (txt[a+1]=='<') /* shift operator << */
257 { skim_higher_priorities("(ijghefcd^|&",'b');
258 t=2;
259 }
260 else /* comparision operator < */
261 { skim_higher_priorities("(ij",'d');
262 }
263 b=2;
264 break;
265 case '=':
266 if (b != 4 && b != 5)
267 { ret=-MISO; goto finish; }
268 if (txt[a+1]=='=') /* comparision operator == */
269 { skim_higher_priorities("(ij",'e');
270 b=2; t=2;
271 break;
272 }
273 else
274 { ret=-ILO; goto finish; }
275 case '!':
276 if (txt[a+1]=='=' ? b!=4 && b!=5 : b!=3 && b!=4 && b!=5)
277 { ret=-MISO; goto finish; }
278 if (txt[a+1]=='=') /* comparision operator != */
279 { skim_higher_priorities("(ij",'f');
280 b=2; t=2;
281 }
282 else /* boolean not */
283 {
284 push_on_stack('!',1);
285 b=1;
286 }
287 break;
288 case '~':
289 if (b != 3 && b !=4 && b != 5)
290 { ret=-MISO; goto finish; }
291 push_on_stack(txt[a],1);
292 b=1;
293 break;
294 case '&':
295 case '|':
296 case '^':
297 if (b !=4 && b != 5)
298 { ret=-MISO; goto finish; }
299 if (txt[a]=='&' && txt[a+1]=='&') /* boolean and */
300 { skim_higher_priorities("(j",'i');
301 t=2;
302 }
303 if (txt[a]=='|' && txt[a+1]=='|') /* boolean or */
304 { skim_higher_priorities("(",'j');
305 t=2;
306 }
307 if (txt[a]=='&') /* bitwise and operator */
308 { skim_higher_priorities("(jihgfedc|^",txt[a]);
309 }
310 else /* bitwise or/xor operator */
311 { skim_higher_priorities("(jihgfedc",txt[a]);
312 }
313 b=2;
314 break;
315 case '+':
316 case '-':
317 if (b==4 || b == 5)
318 skim_higher_priorities("(jihgfedc|^&bc",txt[a]);
319 else
320 push_on_stack((txt[a]=='-'?'_':' '),1);
321 b=(b<=3?1:2);
322 break;
323 case '%':
324 case '/':
325 if (txt[a+1]=='/' ? b!=3 : b!=4 && b!=5)
326 { ret=-MISO; goto finish; }
327 if (txt[a+1]=='/') /* monadic bitsize */
328 { push_on_stack('k',1);
329 b=1; t=2;
330 }
331 else
332 { skim_higher_priorities("(jihgfedc|^&bc+-",'/');
333 b=2;
334 }
335 break;
336 case '*': if (b != 4 && b != 5)
337 { ret=-MISO; goto finish; }
338 if (txt[a+1]=='*') /* binary power */
339 { skim_higher_priorities("(jihgfedc|^&bc+-%/*",'l');
340 b=2; t=2;
341 }
342 else
343 { skim_higher_priorities("(jihgfedc|^&bc+-",'*');
344 b=2;
345 }
346 break;
347 case '(':
348 if (b != 1 && b != 2 && b != 3)
349 { ret=-PART; goto finish; }
350 push_on_stack('(',0);
351 b=3;
352 break;
353 case ')':
354 if (b != 4 && b != 5)
355 { ret=-MISO; goto finish; }
356 while (stack_top)
357 { token=stack[--stack_top];
358 if (token.type=='(') break;
359 else append(token);
360 }
361 if (token.type != '(')
362 { ret=-PART; goto finish; }
363 b=4;
364 break;
365 case CURRENT_PC:
366 if (b != 1 && b != 2 && b != 3)
367 { ret=-PART; goto finish; }
368 append_to(255,get_current_address());
369 b=5;
370 break;
371 case '?':
372 if (b != 3 && b !=4 && b != 5)
373 { ret=-MISO; goto finish; }
374 push_on_stack(txt[a],1);
375 b=6;
376 break;
377 default:
378
379 if (b!=1 && b!=2 && b!=3 && b!=6)
380 { ret=-PART; goto finish; }
381 if (b==6)
382 { if ((t=test_label(txt+a)))
383 { *value= is_in_table(txt+a,t,0,0);
384 }
385 else
386 { ret=-MISL; goto finish; }
387 }
388 else if ((t=test_number(txt+a,value)))
389 { append_to(255,*value);
390 b=5;
391 }
392 else if ((t=test_label(txt+a)))
393 { if (!is_in_table(txt+a,t,value,lineno))
394 { if (pruchod==1)
395 *value=get_current_address();
396 else
397 { ret=-LBNO; goto finish; }
398 undef=1;
399 }
400 append_to(255,*value);
401 b=5;
402 }
403 else
404 { ret=-ILO; goto finish; }
405 }
406 }
407 if (!undef)
408 { int c;
409 int left=0, right=0, resu=0;
410 while (stack_top)
411 { token=stack[--stack_top];
412 if (token.type=='(')
413 { ret=-PART; goto finish; }
414 else
415 append(token);
416 }
417 for (a=0;a<list_top;a++)
418 { if (list[a].type == 255) continue;
419 c= list[a].value;
420 for (b=a;c && b--;)
421 if (list[b].type == 255)
422 { if (c-- == 2) right=list[b].value;
423 else left=list[b].value;
424 list[b].type= 0;
425 }
426 switch(list[a].type)
427 { case '?': resu= left;
428 break;
429 case ' ': resu= left;
430 break;
431 case '_': resu= -left;
432 break;
433 case '+': resu= left+right;
434 break;
435 case '-': resu= left-right;
436 break;
437 case '*': resu= left*right;
438 break;
439 case '/': resu= left/right;
440 if (right*resu > left) resu--;
441 break;
442 case '%': resu= right ? left%right : left;
443 if (right > 0 && resu < 0) resu += right;
444 break;
445 case '~': resu= ~left;
446 break;
447 case '|': resu= left|right;
448 break;
449 case '^': resu= left^right;
450 break;
451 case '&': resu= left&right;
452 break;
453 case '!': resu= -(!left);
454 break;
455 case 'a': if ((unsigned)right >= sizeof(left)*8)
456 resu= (left >= 0 ? 0 : -1);
457 else
458 resu= left>>right;
459 break;
460 case 'b': if ((unsigned)right >= sizeof(left)*8)
461 resu= (left >= 0 ? 0 : 0);
462 else
463 resu= left<<right;
464 break;
465 case 'c': resu= -(left>right);
466 break;
467 case 'd': resu= -(left<right);
468 break;
469 case 'e': resu= -(left==right);
470 break;
471 case 'f': resu= -(left!=right);
472 break;
473 case 'g': resu= -(left>=right);
474 break;
475 case 'h': resu= -(left<=right);
476 break;
477 case 'i': resu= -(left&&right);
478 break;
479 case 'j': resu= -(left||right);
480 break;
481 case 'k': { unsigned v=left;
482 for (resu=0;v;v>>=1,resu++);
483 }
484 break;
485 case 'l': { switch ((unsigned)right)
486 { case 0: resu=1;
487 break;
488 case 1: resu=left;
489 break;
490 case 2: resu= left*left;
491 break;
492 default: if (!left)
493 resu=0;
494 else if (left==1)
495 resu=1;
496 else if (left== -1)
497 resu= right&1 ? -1 : 1;
498 else if (left==2)
499 resu=1<<(unsigned)right;
500 else if (left== -2)
501 resu=(right&1?-1:1)<<(unsigned)right;
502 else
503 { unsigned v=right;
504 for (resu=left;--v;resu *= left);
505 }
506 }
507 }
508 break;
509 }
510 list[b].type= 255;
511 list[b].value= resu;
512 }
513 *value=list[0].value;
514 }
515 else
516 ret=undef;
517 finish:
518 swap_internal_data(&my_stack_ptr, &my_list_ptr, &my_stack_top, &my_list_top);
519 return ret;
520 }
521