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