b54208f81f2f2ba893ce9d5d00ab1a48fa9cbc32
[fw/sdcc] / src / SDCCast.c
1 /*-------------------------------------------------------------------------
2   SDCCast.c - source file for parser support & all ast related routines
3
4              Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
24
25 #define DEBUG_CF(x) /* puts(x); */
26
27 #include "common.h"
28
29 int currLineno = 0;
30 set *astList = NULL;
31 set *operKeyReset = NULL;
32 ast *staticAutos = NULL;
33 int labelKey = 1;
34
35 #define LRVAL(x) x->left->rvalue
36 #define RRVAL(x) x->right->rvalue
37 #define TRVAL(x) x->rvalue
38 #define LLVAL(x) x->left->lvalue
39 #define RLVAL(x) x->right->lvalue
40 #define TLVAL(x) x->lvalue
41 #define RTYPE(x) x->right->ftype
42 #define RETYPE(x) x->right->etype
43 #define LTYPE(x) x->left->ftype
44 #define LETYPE(x) x->left->etype
45 #define TTYPE(x) x->ftype
46 #define TETYPE(x) x->etype
47 #define ALLOCATE 1
48 #define DEALLOCATE 2
49
50 int noLineno = 0;
51 int noAlloc = 0;
52 symbol *currFunc=NULL;
53 static ast *createIval (ast *, sym_link *, initList *, ast *);
54 static ast *createIvalCharPtr (ast *, sym_link *, ast *);
55 static ast *optimizeCompare (ast *);
56 ast *optimizeRRCRLC (ast *);
57 ast *optimizeSWAP (ast *);
58 ast *optimizeGetHbit (ast *);
59 ast *backPatchLabels (ast *, symbol *, symbol *);
60 void PA(ast *t);
61 int inInitMode = 0;
62 memmap *GcurMemmap=NULL;  /* points to the memmap that's currently active */
63 FILE *codeOutFile;
64 int 
65 ptt (ast * tree)
66 {
67   printTypeChain (tree->ftype, stdout);
68   return 0;
69 }
70
71
72 /*-----------------------------------------------------------------*/
73 /* newAst - creates a fresh node for an expression tree            */
74 /*-----------------------------------------------------------------*/
75 static ast *
76 newAst_ (unsigned type)
77 {
78   ast *ex;
79   static int oldLineno = 0;
80
81   ex = Safe_alloc ( sizeof (ast));
82
83   ex->type = type;
84   ex->lineno = (noLineno ? oldLineno : mylineno);
85   ex->filename = currFname;
86   ex->level = NestLevel;
87   ex->block = currBlockno;
88   ex->initMode = inInitMode;
89   ex->seqPoint = seqPointNo;
90   return ex;
91 }
92
93 ast *
94 newAst_VALUE (value * val)
95 {
96   ast *ex = newAst_ (EX_VALUE);
97   ex->opval.val = val;
98   return ex;
99 }
100
101 ast *
102 newAst_OP (unsigned op)
103 {
104   ast *ex = newAst_ (EX_OP);
105   ex->opval.op = op;
106   return ex;
107 }
108
109 ast *
110 newAst_LINK (sym_link * val)
111 {
112   ast *ex = newAst_ (EX_LINK);
113   ex->opval.lnk = val;
114   return ex;
115 }
116
117 /*-----------------------------------------------------------------*/
118 /* newNode - creates a new node                                    */
119 /*-----------------------------------------------------------------*/
120 ast *
121 newNode (long op, ast * left, ast * right)
122 {
123   ast *ex;
124
125   ex = newAst_OP (op);
126   ex->left = left;
127   ex->right = right;
128
129   return ex;
130 }
131
132 /*-----------------------------------------------------------------*/
133 /* newIfxNode - creates a new Ifx Node                             */
134 /*-----------------------------------------------------------------*/
135 ast *
136 newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel)
137 {
138   ast *ifxNode;
139
140   /* if this is a literal then we already know the result */
141   if (condAst->etype && IS_LITERAL (condAst->etype))
142     {
143       /* then depending on the expression value */
144       if (floatFromVal (condAst->opval.val))
145         ifxNode = newNode (GOTO,
146                            newAst_VALUE (symbolVal (trueLabel)),
147                            NULL);
148       else
149         ifxNode = newNode (GOTO,
150                            newAst_VALUE (symbolVal (falseLabel)),
151                            NULL);
152     }
153   else
154     {
155       ifxNode = newNode (IFX, condAst, NULL);
156       ifxNode->trueLabel = trueLabel;
157       ifxNode->falseLabel = falseLabel;
158     }
159
160   return ifxNode;
161 }
162
163 /*-----------------------------------------------------------------*/
164 /* copyAstValues - copies value portion of ast if needed     */
165 /*-----------------------------------------------------------------*/
166 void
167 copyAstValues (ast * dest, ast * src)
168 {
169   switch (src->opval.op)
170     {
171     case BLOCK:
172       dest->values.sym = copySymbolChain (src->values.sym);
173       break;
174
175     case SWITCH:
176       dest->values.switchVals.swVals =
177         copyValue (src->values.switchVals.swVals);
178       dest->values.switchVals.swDefault =
179         src->values.switchVals.swDefault;
180       dest->values.switchVals.swNum =
181         src->values.switchVals.swNum;
182       break;
183
184     case INLINEASM:
185       dest->values.inlineasm =  Safe_strdup(src->values.inlineasm);
186       break;
187
188     case ARRAYINIT:
189         dest->values.constlist = copyLiteralList(src->values.constlist);
190         break;
191
192     case FOR:
193       AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel));
194       AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel));
195       AST_FOR (dest, falseLabel) = copySymbol (AST_FOR (src, falseLabel));
196       AST_FOR (dest, condLabel) = copySymbol (AST_FOR (src, condLabel));
197       AST_FOR (dest, initExpr) = copyAst (AST_FOR (src, initExpr));
198       AST_FOR (dest, condExpr) = copyAst (AST_FOR (src, condExpr));
199       AST_FOR (dest, loopExpr) = copyAst (AST_FOR (src, loopExpr));
200     }
201
202 }
203
204 /*-----------------------------------------------------------------*/
205 /* copyAst - makes a copy of a given astession                     */
206 /*-----------------------------------------------------------------*/
207 ast *
208 copyAst (ast * src)
209 {
210   ast *dest;
211
212   if (!src)
213     return NULL;
214
215   dest = Safe_alloc ( sizeof (ast));
216
217   dest->type = src->type;
218   dest->lineno = src->lineno;
219   dest->level = src->level;
220   dest->funcName = src->funcName;
221
222   if (src->ftype)
223     dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
224
225   /* if this is a leaf */
226   /* if value */
227   if (src->type == EX_VALUE)
228     {
229       dest->opval.val = copyValue (src->opval.val);
230       goto exit;
231     }
232
233   /* if link */
234   if (src->type == EX_LINK)
235     {
236       dest->opval.lnk = copyLinkChain (src->opval.lnk);
237       goto exit;
238     }
239
240   dest->opval.op = src->opval.op;
241
242   /* if this is a node that has special values */
243   copyAstValues (dest, src);
244
245   dest->trueLabel = copySymbol (src->trueLabel);
246   dest->falseLabel = copySymbol (src->falseLabel);
247   dest->left = copyAst (src->left);
248   dest->right = copyAst (src->right);
249 exit:
250   return dest;
251
252 }
253
254 /*-----------------------------------------------------------------*/
255 /* removeIncDecOps: remove for side effects in *_ASSIGN's          */
256 /*                  "*s++ += 3" -> "*s++ = *s++ + 3"               */
257 /*-----------------------------------------------------------------*/
258 ast *removeIncDecOps (ast * tree) {
259
260   // traverse the tree and remove inc/dec ops
261
262   if (!tree)
263     return NULL;
264
265   if (tree->type == EX_OP &&
266       (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
267     if (tree->left)
268       tree=tree->left;
269     else
270       tree=tree->right;
271   }
272
273   tree->left=removeIncDecOps(tree->left);
274   tree->right=removeIncDecOps(tree->right);
275
276  return tree;
277 }
278
279 /*-----------------------------------------------------------------*/
280 /* removePreIncDecOps: remove for side effects in *_ASSIGN's       */
281 /*                  "*++s += 3" -> "*++s = *++s + 3"               */
282 /*-----------------------------------------------------------------*/
283 ast *removePreIncDecOps (ast * tree) {
284
285   // traverse the tree and remove pre-inc/dec ops
286
287   if (!tree)
288     return NULL;
289
290   if (tree->type == EX_OP &&
291       (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
292     if (tree->right)
293       tree=tree->right;
294   }
295
296   tree->left=removePreIncDecOps(tree->left);
297   tree->right=removePreIncDecOps(tree->right);
298
299  return tree;
300 }
301
302 /*-----------------------------------------------------------------*/
303 /* removePostIncDecOps: remove for side effects in *_ASSIGN's      */
304 /*                  "*s++ += 3" -> "*s++ = *s++ + 3"               */
305 /*-----------------------------------------------------------------*/
306 ast *removePostIncDecOps (ast * tree) {
307
308   // traverse the tree and remove pre-inc/dec ops
309
310   if (!tree)
311     return NULL;
312
313   if (tree->type == EX_OP &&
314       (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
315     if (tree->left)
316       tree=tree->left;
317   }
318
319   tree->left=removePostIncDecOps(tree->left);
320   tree->right=removePostIncDecOps(tree->right);
321
322  return tree;
323 }
324
325 /*-----------------------------------------------------------------*/
326 /* hasSEFcalls - returns TRUE if tree has a function call          */
327 /*-----------------------------------------------------------------*/
328 bool
329 hasSEFcalls (ast * tree)
330 {
331   if (!tree)
332     return FALSE;
333
334   if (tree->type == EX_OP &&
335       (tree->opval.op == CALL ||
336        tree->opval.op == PCALL ||
337        tree->opval.op == '=' ||
338        tree->opval.op == INC_OP ||
339        tree->opval.op == DEC_OP))
340     return TRUE;
341
342   return (hasSEFcalls (tree->left) |
343           hasSEFcalls (tree->right));
344 }
345
346 /*-----------------------------------------------------------------*/
347 /* isAstEqual - compares two asts & returns 1 if they are equal    */
348 /*-----------------------------------------------------------------*/
349 static int
350 isAstEqual (ast * t1, ast * t2)
351 {
352   if (!t1 && !t2)
353     return 1;
354
355   if (!t1 || !t2)
356     return 0;
357
358   /* match type */
359   if (t1->type != t2->type)
360     return 0;
361
362   switch (t1->type)
363     {
364     case EX_OP:
365       if (t1->opval.op != t2->opval.op)
366         return 0;
367       return (isAstEqual (t1->left, t2->left) &&
368               isAstEqual (t1->right, t2->right));
369       break;
370
371     case EX_VALUE:
372       if (t1->opval.val->sym)
373         {
374           if (!t2->opval.val->sym)
375             return 0;
376           else
377             return isSymbolEqual (t1->opval.val->sym,
378                                   t2->opval.val->sym);
379         }
380       else
381         {
382           if (t2->opval.val->sym)
383             return 0;
384           else
385             return (floatFromVal (t1->opval.val) ==
386                     floatFromVal (t2->opval.val));
387         }
388       break;
389
390       /* only compare these two types */
391     default:
392       return 0;
393     }
394
395   return 0;
396 }
397
398 /*-----------------------------------------------------------------*/
399 /* resolveSymbols - resolve symbols from the symbol table          */
400 /*-----------------------------------------------------------------*/
401 ast *
402 resolveSymbols (ast * tree)
403 {
404   /* walk the entire tree and check for values */
405   /* with symbols if we find one then replace  */
406   /* symbol with that from the symbol table    */
407
408   if (tree == NULL)
409     return tree;
410
411 #if 0
412   /* print the line          */
413   /* if not block & function */
414   if (tree->type == EX_OP &&
415       (tree->opval.op != FUNCTION &&
416        tree->opval.op != BLOCK &&
417        tree->opval.op != NULLOP))
418     {
419       filename = tree->filename;
420       lineno = tree->lineno;
421     }
422 #endif
423
424   /* make sure we resolve the true & false labels for ifx */
425   if (tree->type == EX_OP && tree->opval.op == IFX)
426     {
427       symbol *csym;
428
429       if (tree->trueLabel)
430         {
431           if ((csym = findSym (LabelTab, tree->trueLabel,
432                                tree->trueLabel->name)))
433             tree->trueLabel = csym;
434           else
435             werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
436                       tree->trueLabel->name);
437         }
438
439       if (tree->falseLabel)
440         {
441           if ((csym = findSym (LabelTab,
442                                tree->falseLabel,
443                                tree->falseLabel->name)))
444             tree->falseLabel = csym;
445           else
446             werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
447                       tree->falseLabel->name);
448         }
449
450     }
451
452   /* if this is a label resolve it from the labelTab */
453   if (IS_AST_VALUE (tree) &&
454       tree->opval.val->sym &&
455       tree->opval.val->sym->islbl)
456     {
457
458       symbol *csym = findSym (LabelTab, tree->opval.val->sym,
459                               tree->opval.val->sym->name);
460
461       if (!csym)
462         werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
463                   tree->opval.val->sym->name);
464       else
465         tree->opval.val->sym = csym;
466
467       goto resolveChildren;
468     }
469
470   /* do only for leafs */
471   if (IS_AST_VALUE (tree) &&
472       tree->opval.val->sym &&
473       !tree->opval.val->sym->implicit)
474     {
475
476       symbol *csym = findSymWithLevel (SymbolTab, tree->opval.val->sym);
477
478       /* if found in the symbol table & they r not the same */
479       if (csym && tree->opval.val->sym != csym)
480         {
481           tree->opval.val->sym = csym;
482           tree->opval.val->type = csym->type;
483           tree->opval.val->etype = csym->etype;
484         }
485
486       /* if not found in the symbol table */
487       /* mark it as undefined assume it is */
488       /* an integer in data space         */
489       if (!csym && !tree->opval.val->sym->implicit)
490         {
491
492           /* if this is a function name then */
493           /* mark it as returning an int     */
494           if (tree->funcName)
495             {
496               tree->opval.val->sym->type = newLink (DECLARATOR);
497               DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
498               tree->opval.val->sym->type->next =
499                 tree->opval.val->sym->etype = newIntLink ();
500               tree->opval.val->etype = tree->opval.val->etype;
501               tree->opval.val->type = tree->opval.val->sym->type;
502               werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
503                         tree->opval.val->sym->name);
504               //tree->opval.val->sym->undefined = 1;
505               allocVariables (tree->opval.val->sym);
506             }
507           else
508             {
509               tree->opval.val->sym->undefined = 1;
510               tree->opval.val->type =
511                 tree->opval.val->etype = newIntLink ();
512               tree->opval.val->sym->type =
513                 tree->opval.val->sym->etype = newIntLink ();
514             }
515         }
516     }
517
518 resolveChildren:
519   resolveSymbols (tree->left);
520   resolveSymbols (tree->right);
521
522   return tree;
523 }
524
525 /*-----------------------------------------------------------------*/
526 /* setAstLineno - walks a ast tree & sets the line number          */
527 /*-----------------------------------------------------------------*/
528 int setAstLineno (ast * tree, int lineno)
529 {
530   if (!tree)
531     return 0;
532
533   tree->lineno = lineno;
534   setAstLineno (tree->left, lineno);
535   setAstLineno (tree->right, lineno);
536   return 0;
537 }
538
539 /*-----------------------------------------------------------------*/
540 /* funcOfType :- function of type with name                        */
541 /*-----------------------------------------------------------------*/
542 symbol *
543 funcOfType (char *name, sym_link * type, sym_link * argType,
544             int nArgs, int rent)
545 {
546   symbol *sym;
547   /* create the symbol */
548   sym = newSymbol (name, 0);
549
550   /* setup return value */
551   sym->type = newLink (DECLARATOR);
552   DCL_TYPE (sym->type) = FUNCTION;
553   sym->type->next = copyLinkChain (type);
554   sym->etype = getSpec (sym->type);
555   FUNC_ISREENT(sym->type) = rent ? 1 : 0;
556
557   /* if arguments required */
558   if (nArgs)
559     {
560       value *args;
561       args = FUNC_ARGS(sym->type) = newValue ();
562
563       while (nArgs--)
564         {
565           args->type = copyLinkChain (argType);
566           args->etype = getSpec (args->type);
567           SPEC_EXTR(args->etype)=1;
568           if (!nArgs)
569             break;
570           args = args->next = newValue ();
571         }
572     }
573
574   /* save it */
575   addSymChain (sym);
576   sym->cdef = 1;
577   allocVariables (sym);
578   return sym;
579
580 }
581
582 /*-----------------------------------------------------------------*/
583 /* funcOfTypeVarg :- function of type with name and argtype        */
584 /*-----------------------------------------------------------------*/
585 symbol *
586 funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
587 {
588   
589     symbol *sym;
590     int i ;
591     /* create the symbol */
592     sym = newSymbol (name, 0);
593     
594     /* setup return value */
595     sym->type = newLink (DECLARATOR);
596     DCL_TYPE (sym->type) = FUNCTION;
597     sym->type->next = typeFromStr(rtype);
598     sym->etype = getSpec (sym->type);
599     
600     /* if arguments required */
601     if (nArgs) {
602         value *args;
603         args = FUNC_ARGS(sym->type) = newValue ();
604         
605         for ( i = 0 ; i < nArgs ; i++ ) {
606             args->type = typeFromStr(atypes[i]);
607             args->etype = getSpec (args->type);
608             SPEC_EXTR(args->etype)=1;
609             if ((i + 1) == nArgs) break;
610             args = args->next = newValue ();
611         }
612     }
613
614     /* save it */
615     addSymChain (sym);
616     sym->cdef = 1;
617     allocVariables (sym);
618     return sym;
619
620 }
621
622 /*-----------------------------------------------------------------*/
623 /* reverseParms - will reverse a parameter tree                    */
624 /*-----------------------------------------------------------------*/
625 static void
626 reverseParms (ast * ptree)
627 {
628   ast *ttree;
629   if (!ptree)
630     return;
631
632   /* top down if we find a nonParm tree then quit */
633   if (ptree->type == EX_OP && ptree->opval.op == PARAM)
634     {
635       ttree = ptree->left;
636       ptree->left = ptree->right;
637       ptree->right = ttree;
638       reverseParms (ptree->left);
639       reverseParms (ptree->right);
640     }
641
642   return;
643 }
644
645 /*-----------------------------------------------------------------*/
646 /* processParms  - makes sure the parameters are okay and do some  */
647 /*                 processing with them                            */
648 /*-----------------------------------------------------------------*/
649 static int
650 processParms (ast *func,
651               value *defParm,
652               ast **actParm,
653               int *parmNumber, /* unused, although updated */
654               bool rightmost)
655 {
656   RESULT_TYPE resultType;
657   sym_link *functype;
658   
659   /* if none of them exist */
660   if (!defParm && !*actParm)
661     return 0;
662
663   if (defParm)
664     {
665       if (getenv("DEBUG_SANITY"))
666         {
667           fprintf (stderr, "processParms: %s ", defParm->name);
668         }
669       /* make sure the type is complete and sane */
670       checkTypeSanity(defParm->etype, defParm->name);
671     }
672
673   if (IS_CODEPTR (func->ftype))
674     functype = func->ftype->next;
675   else
676     functype = func->ftype;
677     
678   /* if the function is being called via a pointer &   */
679   /* it has not been defined a reentrant then we cannot */
680   /* have parameters                                   */
681   if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
682     {
683       werror (W_NONRENT_ARGS);
684       fatalError++;
685       return 1;
686     }
687
688   /* if defined parameters ended but actual parameters */
689   /* exist and this is not defined as a variable arg   */
690   if (!defParm && *actParm && !IFFUNC_HASVARARGS(functype))
691     {
692       werror (E_TOO_MANY_PARMS);
693       return 1;
694     }
695
696   /* if defined parameters present but no actual parameters */
697   if (defParm && !*actParm)
698     {
699       werror (E_TOO_FEW_PARMS);
700       return 1;
701     }
702
703   /* if this is a PARAM node then match left & right */
704   if ((*actParm)->type == EX_OP && (*actParm)->opval.op == PARAM)
705     {
706       (*actParm)->decorated = 1;
707       return (processParms (func, defParm,
708                             &(*actParm)->left,  parmNumber, FALSE) ||
709               processParms (func, defParm ? defParm->next : NULL,
710                             &(*actParm)->right, parmNumber, rightmost));
711     }
712   else if (defParm) /* not vararg */
713     {
714       /* If we have found a value node by following only right-hand links,
715        * then we know that there are no more values after us.
716        *
717        * Therefore, if there are more defined parameters, the caller didn't
718        * supply enough.
719        */
720       if (rightmost && defParm->next)
721         {
722           werror (E_TOO_FEW_PARMS);
723           return 1;
724         }
725     }
726
727   /* decorate parameter */
728   resultType = defParm ? getResultTypeFromType (defParm->etype) :
729                          RESULT_TYPE_NONE;
730   *actParm = decorateType (*actParm, resultType);
731
732   if (IS_VOID((*actParm)->ftype))
733     {
734       werror (E_VOID_VALUE_USED);
735       return 1;
736     }
737
738   /* If this is a varargs function... */
739   if (!defParm && *actParm && IFFUNC_HASVARARGS(functype))
740     {
741       ast *newType = NULL;
742       sym_link *ftype;
743
744       if (IS_CAST_OP (*actParm)
745           || (IS_AST_LIT_VALUE (*actParm) && (*actParm)->values.literalFromCast))
746         {
747           /* Parameter was explicitly typecast; don't touch it. */
748           return 0;
749         }
750
751       ftype = (*actParm)->ftype;
752
753       /* If it's a char, upcast to int. */
754       if (IS_INTEGRAL (ftype)
755           && (getSize (ftype) < (unsigned) INTSIZE))
756         {
757           newType = newAst_LINK(INTTYPE);  
758         }
759
760       if (IS_PTR(ftype) && !IS_GENPTR(ftype))
761         {
762           newType = newAst_LINK (copyLinkChain(ftype));
763           DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
764         }
765
766       if (IS_AGGREGATE (ftype))
767         {
768           newType = newAst_LINK (copyLinkChain (ftype));
769           DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
770         }
771       
772       if (newType)
773         {
774           /* cast required; change this op to a cast. */
775           ast *parmCopy = resolveSymbols (copyAst (*actParm));
776
777           (*actParm)->type = EX_OP;
778           (*actParm)->opval.op = CAST;
779           (*actParm)->left = newType;
780           (*actParm)->right = parmCopy;
781           (*actParm)->decorated = 0; /* force typechecking */
782           decorateType (*actParm, RESULT_TYPE_NONE);
783         }
784       return 0;
785     } /* vararg */
786
787   /* if defined parameters ended but actual has not & */
788   /* reentrant */
789   if (!defParm && *actParm &&
790       (options.stackAuto || IFFUNC_ISREENT (functype)))
791     return 0;
792
793   resolveSymbols (*actParm);
794   
795   /* the parameter type must be at least castable */
796   if (compareType (defParm->type, (*actParm)->ftype) == 0)
797     {
798       werror (E_INCOMPAT_TYPES);
799       printFromToType ((*actParm)->ftype, defParm->type);
800       return 1;
801     }
802
803   /* if the parameter is castable then add the cast */
804   if (compareType (defParm->type, (*actParm)->ftype) < 0)
805     {
806       ast *pTree;
807
808       resultType = getResultTypeFromType (defParm->etype);
809       pTree = resolveSymbols (copyAst (*actParm));
810       
811       /* now change the current one to a cast */
812       (*actParm)->type = EX_OP;
813       (*actParm)->opval.op = CAST;
814       (*actParm)->left = newAst_LINK (defParm->type);
815       (*actParm)->right = pTree;
816       (*actParm)->decorated = 0; /* force typechecking */
817       decorateType (*actParm, resultType);
818     }
819
820   /* make a copy and change the regparm type to the defined parm */
821   (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
822   SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
823   SPEC_ARGREG  ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
824   (*parmNumber)++;
825   return 0;
826 }
827
828 /*-----------------------------------------------------------------*/
829 /* createIvalType - generates ival for basic types                 */
830 /*-----------------------------------------------------------------*/
831 static ast *
832 createIvalType (ast * sym, sym_link * type, initList * ilist)
833 {
834   ast *iExpr;
835
836   /* if initList is deep */
837   if (ilist->type == INIT_DEEP)
838     ilist = ilist->init.deep;
839
840   iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK);
841   return decorateType (newNode ('=', sym, iExpr), RESULT_CHECK);
842 }
843
844 /*-----------------------------------------------------------------*/
845 /* createIvalStruct - generates initial value for structures       */
846 /*-----------------------------------------------------------------*/
847 static ast *
848 createIvalStruct (ast * sym, sym_link * type, initList * ilist)
849 {
850   ast *rast = NULL;
851   ast *lAst;
852   symbol *sflds;
853   initList *iloop;
854
855   sflds = SPEC_STRUCT (type)->fields;
856   if (ilist->type != INIT_DEEP)
857     {
858       werror (E_INIT_STRUCT, "");
859       return NULL;
860     }
861
862   iloop = ilist->init.deep;
863
864   for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
865     {
866       /* if we have come to end */
867       if (!iloop)
868         break;
869       sflds->implicit = 1;
870       lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
871       lAst = decorateType (resolveSymbols (lAst), RESULT_CHECK);
872       rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)), RESULT_CHECK);
873     }
874
875   if (iloop) {
876     werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
877               W_EXCESS_INITIALIZERS, "struct", 
878               sym->opval.val->sym->name);
879   }
880
881   return rast;
882 }
883
884
885 /*-----------------------------------------------------------------*/
886 /* createIvalArray - generates code for array initialization       */
887 /*-----------------------------------------------------------------*/
888 static ast *
889 createIvalArray (ast * sym, sym_link * type, initList * ilist)
890 {
891   ast *rast = NULL;
892   initList *iloop;
893   int lcnt = 0, size = 0;
894   literalList *literalL;
895
896   /* take care of the special   case  */
897   /* array of characters can be init  */
898   /* by a string                      */
899   if (IS_CHAR (type->next))
900     if ((rast = createIvalCharPtr (sym,
901                                    type,
902                         decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK))))
903
904       return decorateType (resolveSymbols (rast), RESULT_CHECK);
905
906     /* not the special case             */
907     if (ilist->type != INIT_DEEP)
908     {
909         werror (E_INIT_STRUCT, "");
910         return NULL;
911     }
912
913     iloop = ilist->init.deep;
914     lcnt = DCL_ELEM (type);
915
916     if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
917     {
918         ast *aSym;
919
920         aSym = decorateType (resolveSymbols(sym), RESULT_CHECK);
921         
922         rast = newNode(ARRAYINIT, aSym, NULL);
923         rast->values.constlist = literalL;
924         
925         // Make sure size is set to length of initializer list.
926         while (iloop)
927         {
928             size++;
929             iloop = iloop->next;
930         }
931         
932         if (lcnt && size > lcnt)
933         {
934             // Array size was specified, and we have more initializers than needed.
935             char *name=sym->opval.val->sym->name;
936             int lineno=sym->opval.val->sym->lineDef;
937             char *filename=sym->opval.val->sym->fileDef;
938             
939             werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
940         }
941     }
942     else
943     {
944         for (;;)
945         {
946             ast *aSym;
947             
948             aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
949             aSym = decorateType (resolveSymbols (aSym), RESULT_CHECK);
950             rast = createIval (aSym, type->next, iloop, rast);
951             iloop = (iloop ? iloop->next : NULL);
952             if (!iloop)
953             {
954                 break;
955             }
956             
957             /* no of elements given and we    */
958             /* have generated for all of them */
959             if (!--lcnt) 
960             {
961                 // there has to be a better way
962                 char *name=sym->opval.val->sym->name;
963                 int lineno=sym->opval.val->sym->lineDef;
964                 char *filename=sym->opval.val->sym->fileDef;
965                 werrorfl (filename, lineno, W_EXCESS_INITIALIZERS, "array", name);
966                 
967                 break;
968             }
969         }
970     }
971
972     /* if we have not been given a size  */
973     if (!DCL_ELEM (type))
974     {
975         DCL_ELEM (type) = size;
976     }
977
978     return decorateType (resolveSymbols (rast), RESULT_CHECK);
979 }
980
981
982 /*-----------------------------------------------------------------*/
983 /* createIvalCharPtr - generates initial values for char pointers  */
984 /*-----------------------------------------------------------------*/
985 static ast *
986 createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
987 {
988   ast *rast = NULL;
989
990   /* if this is a pointer & right is a literal array then */
991   /* just assignment will do                              */
992   if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
993                          SPEC_SCLS (iexpr->etype) == S_CODE)
994                         && IS_ARRAY (iexpr->ftype)))
995     return newNode ('=', sym, iexpr);
996
997   /* left side is an array so we have to assign each */
998   /* element                                         */
999   if ((IS_LITERAL (iexpr->etype) ||
1000        SPEC_SCLS (iexpr->etype) == S_CODE)
1001       && IS_ARRAY (iexpr->ftype))
1002     {
1003       /* for each character generate an assignment */
1004       /* to the array element */
1005       char *s = SPEC_CVAL (iexpr->etype).v_char;
1006       int i = 0;
1007       int size = getSize (iexpr->ftype);
1008       int symsize = getSize (type);
1009       
1010       if (size>symsize)
1011         {
1012           if (size>(symsize+1))
1013             werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
1014                       "string", sym->opval.val->sym->name);
1015           size = symsize;
1016         }
1017
1018       for (i=0;i<size;i++)
1019         {
1020           rast = newNode (NULLOP,
1021                           rast,
1022                           newNode ('=',
1023                                    newNode ('[', sym,
1024                                    newAst_VALUE (valueFromLit ((float) i))),
1025                                    newAst_VALUE (valueFromLit (*s))));
1026           s++;
1027         }
1028
1029       // now WE don't need iexpr's symbol anymore
1030       freeStringSymbol(AST_SYMBOL(iexpr));
1031
1032       return decorateType (resolveSymbols (rast), RESULT_CHECK);
1033     }
1034
1035   return NULL;
1036 }
1037
1038 /*-----------------------------------------------------------------*/
1039 /* createIvalPtr - generates initial value for pointers            */
1040 /*-----------------------------------------------------------------*/
1041 static ast *
1042 createIvalPtr (ast * sym, sym_link * type, initList * ilist)
1043 {
1044   ast *rast;
1045   ast *iexpr;
1046
1047   /* if deep then   */
1048   if (ilist->type == INIT_DEEP)
1049     ilist = ilist->init.deep;
1050
1051   iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK);
1052
1053   /* if character pointer */
1054   if (IS_CHAR (type->next))
1055     if ((rast = createIvalCharPtr (sym, type, iexpr)))
1056       return rast;
1057
1058   return newNode ('=', sym, iexpr);
1059 }
1060
1061 /*-----------------------------------------------------------------*/
1062 /* createIval - generates code for initial value                   */
1063 /*-----------------------------------------------------------------*/
1064 static ast *
1065 createIval (ast * sym, sym_link * type, initList * ilist, ast * wid)
1066 {
1067   ast *rast = NULL;
1068
1069   if (!ilist)
1070     return NULL;
1071
1072   /* if structure then    */
1073   if (IS_STRUCT (type))
1074     rast = createIvalStruct (sym, type, ilist);
1075   else
1076     /* if this is a pointer */
1077   if (IS_PTR (type))
1078     rast = createIvalPtr (sym, type, ilist);
1079   else
1080     /* if this is an array   */
1081   if (IS_ARRAY (type))
1082     rast = createIvalArray (sym, type, ilist);
1083   else
1084     /* if type is SPECIFIER */
1085   if (IS_SPEC (type))
1086     rast = createIvalType (sym, type, ilist);
1087
1088   if (wid)
1089     return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_CHECK);
1090   else
1091     return decorateType (resolveSymbols (rast), RESULT_CHECK);
1092 }
1093
1094 /*-----------------------------------------------------------------*/
1095 /* initAggregates - initialises aggregate variables with initv     */
1096 /*-----------------------------------------------------------------*/
1097 ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
1098   return createIval (newAst_VALUE (symbolVal (sym)), sym->type, ival, wid);
1099 }
1100
1101 /*-----------------------------------------------------------------*/
1102 /* gatherAutoInit - creates assignment expressions for initial     */
1103 /*    values                 */
1104 /*-----------------------------------------------------------------*/
1105 static ast *
1106 gatherAutoInit (symbol * autoChain)
1107 {
1108   ast *init = NULL;
1109   ast *work;
1110   symbol *sym;
1111
1112   inInitMode = 1;
1113   for (sym = autoChain; sym; sym = sym->next)
1114     {
1115
1116       /* resolve the symbols in the ival */
1117       if (sym->ival)
1118         resolveIvalSym (sym->ival, sym->type);
1119
1120       /* if this is a static variable & has an */
1121       /* initial value the code needs to be lifted */
1122       /* here to the main portion since they can be */
1123       /* initialised only once at the start    */
1124       if (IS_STATIC (sym->etype) && sym->ival &&
1125           SPEC_SCLS (sym->etype) != S_CODE)
1126         {
1127           symbol *newSym;
1128           
1129           /* insert the symbol into the symbol table */
1130           /* with level = 0 & name = rname       */
1131           newSym = copySymbol (sym);
1132           addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
1133
1134           /* now lift the code to main */
1135           if (IS_AGGREGATE (sym->type)) {
1136             work = initAggregates (sym, sym->ival, NULL);
1137           } else {
1138             if (getNelements(sym->type, sym->ival)>1) {
1139               werrorfl (sym->fileDef, sym->lineDef,
1140                         W_EXCESS_INITIALIZERS, "scalar", 
1141                         sym->name);
1142             }
1143             work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
1144                             list2expr (sym->ival));
1145           }
1146
1147           setAstLineno (work, sym->lineDef);
1148
1149           sym->ival = NULL;
1150           if (staticAutos)
1151             staticAutos = newNode (NULLOP, staticAutos, work);
1152           else
1153             staticAutos = work;
1154
1155           continue;
1156         }
1157
1158       /* if there is an initial value */
1159       if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
1160         {
1161           initList *ilist=sym->ival;
1162           
1163           while (ilist->type == INIT_DEEP) {
1164             ilist = ilist->init.deep;
1165           }
1166
1167           /* update lineno for error msg */
1168           lineno=sym->lineDef;
1169           setAstLineno (ilist->init.node, lineno);
1170           
1171           if (IS_AGGREGATE (sym->type)) {
1172             work = initAggregates (sym, sym->ival, NULL);
1173           } else {
1174             if (getNelements(sym->type, sym->ival)>1) {
1175               werrorfl (sym->fileDef, sym->lineDef,
1176                         W_EXCESS_INITIALIZERS, "scalar", 
1177                         sym->name);
1178             }
1179             work = newNode ('=', newAst_VALUE (symbolVal (sym)),
1180                             list2expr (sym->ival));
1181           }
1182           
1183           // just to be sure
1184           setAstLineno (work, sym->lineDef);
1185
1186           sym->ival = NULL;
1187           if (init)
1188             init = newNode (NULLOP, init, work);
1189           else
1190             init = work;
1191         }
1192     }
1193   inInitMode = 0;
1194   return init;
1195 }
1196
1197 /*-----------------------------------------------------------------*/
1198 /* freeStringSymbol - delete a literal string if no more usage     */
1199 /*-----------------------------------------------------------------*/
1200 void freeStringSymbol(symbol *sym) {
1201   /* make sure this is a literal string */
1202   assert (sym->isstrlit);
1203   if (--sym->isstrlit == 0) { // lower the usage count
1204     memmap *segment=SPEC_OCLS(sym->etype);
1205     if (segment) {
1206       deleteSetItem(&segment->syms, sym);
1207     }
1208   }
1209 }
1210   
1211 /*-----------------------------------------------------------------*/
1212 /* stringToSymbol - creates a symbol from a literal string         */
1213 /*-----------------------------------------------------------------*/
1214 static value *
1215 stringToSymbol (value * val)
1216 {
1217   char name[SDCC_NAME_MAX + 1];
1218   static int charLbl = 0;
1219   symbol *sym;
1220   set *sp;
1221   int size;
1222
1223   // have we heard this before?
1224   for (sp=statsg->syms; sp; sp=sp->next) {
1225     sym=sp->item;
1226     size = getSize (sym->type);
1227     if (sym->isstrlit && size == getSize (val->type) &&
1228         !memcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char, size)) {
1229       // yes, this is old news. Don't publish it again.
1230       sym->isstrlit++; // but raise the usage count
1231       return symbolVal(sym);
1232     }
1233   }
1234
1235   SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
1236   sym = newSymbol (name, 0);    /* make it @ level 0 */
1237   strncpyz (sym->rname, name, SDCC_NAME_MAX);
1238
1239   /* copy the type from the value passed */
1240   sym->type = copyLinkChain (val->type);
1241   sym->etype = getSpec (sym->type);
1242   /* change to storage class & output class */
1243   SPEC_SCLS (sym->etype) = S_CODE;
1244   SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char;
1245   SPEC_STAT (sym->etype) = 1;
1246   /* make the level & block = 0 */
1247   sym->block = sym->level = 0;
1248   sym->isstrlit = 1;
1249   /* create an ival */
1250   sym->ival = newiList (INIT_NODE, newAst_VALUE (val));
1251   if (noAlloc == 0)
1252     {
1253       /* allocate it */
1254       addSymChain (sym);
1255       allocVariables (sym);
1256     }
1257   sym->ival = NULL;
1258   return symbolVal (sym);
1259
1260 }
1261
1262 /*-----------------------------------------------------------------*/
1263 /* processBlockVars - will go thru the ast looking for block if    */
1264 /*                    a block is found then will allocate the syms */
1265 /*                    will also gather the auto inits present      */
1266 /*-----------------------------------------------------------------*/
1267 ast *
1268 processBlockVars (ast * tree, int *stack, int action)
1269 {
1270   if (!tree)
1271     return NULL;
1272
1273   /* if this is a block */
1274   if (tree->type == EX_OP && tree->opval.op == BLOCK)
1275     {
1276       ast *autoInit;
1277
1278       if (action == ALLOCATE)
1279         {
1280           *stack += allocVariables (tree->values.sym);
1281           autoInit = gatherAutoInit (tree->values.sym);
1282         
1283           /* if there are auto inits then do them */
1284           if (autoInit)
1285             tree->left = newNode (NULLOP, autoInit, tree->left);
1286         }
1287       else                      /* action is deallocate */
1288         deallocLocal (tree->values.sym);
1289     }
1290
1291   processBlockVars (tree->left, stack, action);
1292   processBlockVars (tree->right, stack, action);
1293   return tree;
1294 }
1295
1296
1297 /*-------------------------------------------------------------*/
1298 /* constExprTree - returns TRUE if this tree is a constant     */
1299 /*                 expression                                  */
1300 /*-------------------------------------------------------------*/
1301 bool constExprTree (ast *cexpr) {
1302
1303   if (!cexpr) {
1304     return TRUE;
1305   }
1306
1307   cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK);
1308
1309   switch (cexpr->type) 
1310     {
1311     case EX_VALUE:
1312       if (IS_AST_LIT_VALUE(cexpr)) {
1313         // this is a literal
1314         return TRUE;
1315       }
1316       if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
1317         // a function's address will never change
1318         return TRUE;
1319       }
1320       if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
1321         // an array's address will never change
1322         return TRUE;
1323       }
1324       if (IS_AST_SYM_VALUE(cexpr) && 
1325           IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
1326         // a symbol in code space will never change
1327         // This is only for the 'char *s="hallo"' case and will have to leave
1328         //printf(" code space symbol");
1329         return TRUE;
1330       }
1331       return FALSE;
1332     case EX_LINK:
1333       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1334               "unexpected link in expression tree\n");
1335       return FALSE;
1336     case EX_OP:
1337       if (cexpr->opval.op==ARRAYINIT) {
1338         // this is a list of literals
1339         return TRUE;
1340       }
1341       if (cexpr->opval.op=='=') {
1342         return constExprTree(cexpr->right);
1343       }
1344       if (cexpr->opval.op==CAST) {
1345         // cast ignored, maybe we should throw a warning here?
1346         return constExprTree(cexpr->right);
1347       }
1348       if (cexpr->opval.op=='&') { 
1349         return TRUE;
1350       }
1351       if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
1352         return FALSE;
1353       }
1354       if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
1355         return TRUE;
1356       }
1357       return FALSE;
1358     case EX_OPERAND:
1359       return IS_CONSTANT(operandType(cexpr->opval.oprnd));
1360     }
1361   return FALSE;
1362 }
1363     
1364 /*-----------------------------------------------------------------*/
1365 /* constExprValue - returns the value of a constant expression     */
1366 /*                  or NULL if it is not a constant expression     */
1367 /*-----------------------------------------------------------------*/
1368 value *
1369 constExprValue (ast * cexpr, int check)
1370 {
1371   cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK);
1372
1373   /* if this is not a constant then */
1374   if (!IS_LITERAL (cexpr->ftype))
1375     {
1376       /* then check if this is a literal array
1377          in code segment */
1378       if (SPEC_SCLS (cexpr->etype) == S_CODE &&
1379           SPEC_CVAL (cexpr->etype).v_char &&
1380           IS_ARRAY (cexpr->ftype))
1381         {
1382           value *val = valFromType (cexpr->ftype);
1383           SPEC_SCLS (val->etype) = S_LITERAL;
1384           val->sym = cexpr->opval.val->sym;
1385           val->sym->type = copyLinkChain (cexpr->ftype);
1386           val->sym->etype = getSpec (val->sym->type);
1387           strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
1388           return val;
1389         }
1390
1391       /* if we are casting a literal value then */
1392       if (IS_AST_OP (cexpr) &&
1393           cexpr->opval.op == CAST &&
1394           IS_LITERAL (cexpr->right->ftype))
1395         {
1396         return valCastLiteral (cexpr->ftype,
1397                                floatFromVal (cexpr->right->opval.val));
1398         }
1399
1400       if (IS_AST_VALUE (cexpr))
1401         {
1402         return cexpr->opval.val;
1403         }
1404
1405       if (check)
1406         werror (E_CONST_EXPECTED, "found expression");
1407
1408       return NULL;
1409     }
1410
1411   /* return the value */
1412   return cexpr->opval.val;
1413
1414 }
1415
1416 /*-----------------------------------------------------------------*/
1417 /* isLabelInAst - will return true if a given label is found       */
1418 /*-----------------------------------------------------------------*/
1419 bool 
1420 isLabelInAst (symbol * label, ast * tree)
1421 {
1422   if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
1423     return FALSE;
1424
1425   if (IS_AST_OP (tree) &&
1426       tree->opval.op == LABEL &&
1427       isSymbolEqual (AST_SYMBOL (tree->left), label))
1428     return TRUE;
1429
1430   return isLabelInAst (label, tree->right) &&
1431     isLabelInAst (label, tree->left);
1432
1433 }
1434
1435 /*-----------------------------------------------------------------*/
1436 /* isLoopCountable - return true if the loop count can be determi- */
1437 /* -ned at compile time .                                          */
1438 /*-----------------------------------------------------------------*/
1439 bool 
1440 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
1441                  symbol ** sym, ast ** init, ast ** end)
1442 {
1443
1444   /* the loop is considered countable if the following
1445      conditions are true :-
1446
1447      a) initExpr :- <sym> = <const>
1448      b) condExpr :- <sym> < <const1>
1449      c) loopExpr :- <sym> ++
1450    */
1451
1452   /* first check the initExpr */
1453   if (IS_AST_OP (initExpr) &&
1454       initExpr->opval.op == '=' &&      /* is assignment */
1455       IS_AST_SYM_VALUE (initExpr->left))
1456     {                           /* left is a symbol */
1457
1458       *sym = AST_SYMBOL (initExpr->left);
1459       *init = initExpr->right;
1460     }
1461   else
1462     return FALSE;
1463
1464   /* for now the symbol has to be of
1465      integral type */
1466   if (!IS_INTEGRAL ((*sym)->type))
1467     return FALSE;
1468
1469   /* now check condExpr */
1470   if (IS_AST_OP (condExpr))
1471     {
1472
1473       switch (condExpr->opval.op)
1474         {
1475         case '<':
1476           if (IS_AST_SYM_VALUE (condExpr->left) &&
1477               isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
1478               IS_AST_LIT_VALUE (condExpr->right))
1479             {
1480               *end = condExpr->right;
1481               break;
1482             }
1483           return FALSE;
1484
1485         case '!':
1486           if (IS_AST_OP (condExpr->left) &&
1487               condExpr->left->opval.op == '>' &&
1488               IS_AST_LIT_VALUE (condExpr->left->right) &&
1489               IS_AST_SYM_VALUE (condExpr->left->left) &&
1490               isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
1491             {
1492
1493               *end = newNode ('+', condExpr->left->right,
1494                               newAst_VALUE (constVal ("1")));
1495               break;
1496             }
1497           return FALSE;
1498
1499         default:
1500           return FALSE;
1501         }
1502
1503     }
1504
1505   /* check loop expression is of the form <sym>++ */
1506   if (!IS_AST_OP (loopExpr))
1507     return FALSE;
1508
1509   /* check if <sym> ++ */
1510   if (loopExpr->opval.op == INC_OP)
1511     {
1512
1513       if (loopExpr->left)
1514         {
1515           /* pre */
1516           if (IS_AST_SYM_VALUE (loopExpr->left) &&
1517               isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
1518             return TRUE;
1519
1520         }
1521       else
1522         {
1523           /* post */
1524           if (IS_AST_SYM_VALUE (loopExpr->right) &&
1525               isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
1526             return TRUE;
1527         }
1528
1529     }
1530   else
1531     {
1532       /* check for += */
1533       if (loopExpr->opval.op == ADD_ASSIGN)
1534         {
1535
1536           if (IS_AST_SYM_VALUE (loopExpr->left) &&
1537               isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
1538               IS_AST_LIT_VALUE (loopExpr->right) &&
1539               (int) AST_LIT_VALUE (loopExpr->right) != 1)
1540             return TRUE;
1541         }
1542     }
1543
1544   return FALSE;
1545 }
1546
1547 /*-----------------------------------------------------------------*/
1548 /* astHasVolatile - returns true if ast contains any volatile      */
1549 /*-----------------------------------------------------------------*/
1550 bool 
1551 astHasVolatile (ast * tree)
1552 {
1553   if (!tree)
1554     return FALSE;
1555
1556   if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
1557     return TRUE;
1558
1559   if (IS_AST_OP (tree))
1560     return astHasVolatile (tree->left) ||
1561       astHasVolatile (tree->right);
1562   else
1563     return FALSE;
1564 }
1565
1566 /*-----------------------------------------------------------------*/
1567 /* astHasPointer - return true if the ast contains any ptr variable */
1568 /*-----------------------------------------------------------------*/
1569 bool 
1570 astHasPointer (ast * tree)
1571 {
1572   if (!tree)
1573     return FALSE;
1574
1575   if (IS_AST_LINK (tree))
1576     return TRUE;
1577
1578   /* if we hit an array expression then check
1579      only the left side */
1580   if (IS_AST_OP (tree) && tree->opval.op == '[')
1581     return astHasPointer (tree->left);
1582
1583   if (IS_AST_VALUE (tree))
1584     return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
1585
1586   return astHasPointer (tree->left) ||
1587     astHasPointer (tree->right);
1588
1589 }
1590
1591 /*-----------------------------------------------------------------*/
1592 /* astHasSymbol - return true if the ast has the given symbol      */
1593 /*-----------------------------------------------------------------*/
1594 bool 
1595 astHasSymbol (ast * tree, symbol * sym)
1596 {
1597   if (!tree || IS_AST_LINK (tree))
1598     return FALSE;
1599
1600   if (IS_AST_VALUE (tree))
1601     {
1602       if (IS_AST_SYM_VALUE (tree))
1603         return isSymbolEqual (AST_SYMBOL (tree), sym);
1604       else
1605         return FALSE;
1606     }
1607
1608   return astHasSymbol (tree->left, sym) ||
1609     astHasSymbol (tree->right, sym);
1610 }
1611
1612 /*-----------------------------------------------------------------*/
1613 /* astHasDeref - return true if the ast has an indirect access     */
1614 /*-----------------------------------------------------------------*/
1615 static bool 
1616 astHasDeref (ast * tree)
1617 {
1618   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
1619     return FALSE;
1620
1621   if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
1622   
1623   return astHasDeref (tree->left) || astHasDeref (tree->right);
1624 }
1625
1626 /*-----------------------------------------------------------------*/
1627 /* isConformingBody - the loop body has to conform to a set of rules */
1628 /* for the loop to be considered reversible read on for rules      */
1629 /*-----------------------------------------------------------------*/
1630 bool 
1631 isConformingBody (ast * pbody, symbol * sym, ast * body)
1632 {
1633
1634   /* we are going to do a pre-order traversal of the
1635      tree && check for the following conditions. (essentially
1636      a set of very shallow tests )
1637      a) the sym passed does not participate in
1638      any arithmetic operation
1639      b) There are no function calls
1640      c) all jumps are within the body
1641      d) address of loop control variable not taken
1642      e) if an assignment has a pointer on the
1643      left hand side make sure right does not have
1644      loop control variable */
1645
1646   /* if we reach the end or a leaf then true */
1647   if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1648     return TRUE;
1649   
1650   /* if anything else is "volatile" */
1651   if (IS_VOLATILE (TETYPE (pbody)))
1652     return FALSE;
1653
1654   /* we will walk the body in a pre-order traversal for
1655      efficiency sake */
1656   switch (pbody->opval.op)
1657     {
1658 /*------------------------------------------------------------------*/
1659     case '[':
1660       // if the loopvar is used as an index
1661       if (astHasSymbol(pbody->right, sym)) {
1662         return FALSE;
1663       }
1664       return isConformingBody (pbody->right, sym, body);
1665
1666 /*------------------------------------------------------------------*/
1667     case PTR_OP:
1668     case '.':
1669       return TRUE;
1670
1671 /*------------------------------------------------------------------*/
1672     case INC_OP:
1673     case DEC_OP:
1674
1675       /* sure we are not sym is not modified */
1676       if (pbody->left &&
1677           IS_AST_SYM_VALUE (pbody->left) &&
1678           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1679         return FALSE;
1680
1681       if (pbody->right &&
1682           IS_AST_SYM_VALUE (pbody->right) &&
1683           isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1684         return FALSE;
1685
1686       return TRUE;
1687
1688 /*------------------------------------------------------------------*/
1689
1690     case '*':                   /* can be unary  : if right is null then unary operation */
1691     case '+':
1692     case '-':
1693     case '&':
1694
1695       /* if right is NULL then unary operation  */
1696 /*------------------------------------------------------------------*/
1697 /*----------------------------*/
1698       /*  address of                */
1699 /*----------------------------*/
1700       if (!pbody->right)
1701         {
1702           if (IS_AST_SYM_VALUE (pbody->left) &&
1703               isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1704             return FALSE;
1705           else
1706             return isConformingBody (pbody->left, sym, body);
1707         }
1708       else
1709         {
1710           if (astHasSymbol (pbody->left, sym) ||
1711               astHasSymbol (pbody->right, sym))
1712             return FALSE;
1713         }
1714
1715
1716 /*------------------------------------------------------------------*/
1717     case '|':
1718     case '^':
1719     case '/':
1720     case '%':
1721     case LEFT_OP:
1722     case RIGHT_OP:
1723
1724       if (IS_AST_SYM_VALUE (pbody->left) &&
1725           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1726         return FALSE;
1727
1728       if (IS_AST_SYM_VALUE (pbody->right) &&
1729           isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1730         return FALSE;
1731
1732       return isConformingBody (pbody->left, sym, body) &&
1733         isConformingBody (pbody->right, sym, body);
1734
1735     case '~':
1736     case '!':
1737     case RRC:
1738     case RLC:
1739     case GETHBIT:
1740     case SWAP:
1741       if (IS_AST_SYM_VALUE (pbody->left) &&
1742           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1743         return FALSE;
1744       return isConformingBody (pbody->left, sym, body);
1745
1746 /*------------------------------------------------------------------*/
1747
1748     case AND_OP:
1749     case OR_OP:
1750     case '>':
1751     case '<':
1752     case LE_OP:
1753     case GE_OP:
1754     case EQ_OP:
1755     case NE_OP:
1756     case '?':
1757     case ':':
1758     case SIZEOF:                /* evaluate wihout code generation */
1759
1760       if (IS_AST_SYM_VALUE (pbody->left) &&
1761           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1762         return FALSE;
1763
1764       if (IS_AST_SYM_VALUE (pbody->right) &&
1765           isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1766         return FALSE;
1767
1768       return isConformingBody (pbody->left, sym, body) &&
1769         isConformingBody (pbody->right, sym, body);
1770
1771 /*------------------------------------------------------------------*/
1772     case '=':
1773
1774       /* if left has a pointer & right has loop
1775          control variable then we cannot */
1776       if (astHasPointer (pbody->left) &&
1777           astHasSymbol (pbody->right, sym))
1778         return FALSE;
1779       if (astHasVolatile (pbody->left))
1780         return FALSE;
1781
1782       if (IS_AST_SYM_VALUE (pbody->left)) {
1783         // if the loopvar has an assignment
1784         if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1785           return FALSE;
1786         // if the loopvar is used in another (maybe conditional) block
1787         if (astHasSymbol (pbody->right, sym) &&
1788             (pbody->level >= body->level)) {
1789           return FALSE;
1790         }
1791       }
1792
1793       if (astHasVolatile (pbody->left))
1794         return FALSE;
1795
1796       if (astHasDeref(pbody->right)) return FALSE;
1797
1798       return isConformingBody (pbody->left, sym, body) &&
1799         isConformingBody (pbody->right, sym, body);
1800
1801     case MUL_ASSIGN:
1802     case DIV_ASSIGN:
1803     case AND_ASSIGN:
1804     case OR_ASSIGN:
1805     case XOR_ASSIGN:
1806     case RIGHT_ASSIGN:
1807     case LEFT_ASSIGN:
1808     case SUB_ASSIGN:
1809     case ADD_ASSIGN:
1810       assert ("Parser should not have generated this\n");
1811
1812 /*------------------------------------------------------------------*/
1813 /*----------------------------*/
1814       /*      comma operator        */
1815 /*----------------------------*/
1816     case ',':
1817       return isConformingBody (pbody->left, sym, body) &&
1818         isConformingBody (pbody->right, sym, body);
1819
1820 /*------------------------------------------------------------------*/
1821 /*----------------------------*/
1822       /*       function call        */
1823 /*----------------------------*/
1824     case CALL:
1825         /* if local & not passed as paramater then ok */
1826         if (sym->level && !astHasSymbol(pbody->right,sym)) 
1827             return TRUE;
1828       return FALSE;
1829
1830 /*------------------------------------------------------------------*/
1831 /*----------------------------*/
1832       /*     return statement       */
1833 /*----------------------------*/
1834     case RETURN:
1835       return FALSE;
1836
1837     case GOTO:
1838       if (isLabelInAst (AST_SYMBOL (pbody->left), body))
1839         return TRUE;
1840       else
1841         return FALSE;
1842     case SWITCH:
1843       if (astHasSymbol (pbody->left, sym))
1844         return FALSE;
1845
1846     default:
1847       break;
1848     }
1849
1850   return isConformingBody (pbody->left, sym, body) &&
1851     isConformingBody (pbody->right, sym, body);
1852
1853
1854
1855 }
1856
1857 /*-----------------------------------------------------------------*/
1858 /* isLoopReversible - takes a for loop as input && returns true    */
1859 /* if the for loop is reversible. If yes will set the value of     */
1860 /* the loop control var & init value & termination value           */
1861 /*-----------------------------------------------------------------*/
1862 bool
1863 isLoopReversible (ast * loop, symbol ** loopCntrl,
1864                   ast ** init, ast ** end)
1865 {
1866   /* if option says don't do it then don't */
1867   if (optimize.noLoopReverse)
1868     return 0;
1869   /* there are several tests to determine this */
1870
1871   /* for loop has to be of the form
1872      for ( <sym> = <const1> ;
1873      [<sym> < <const2>]  ;
1874      [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
1875      forBody */
1876   if (!isLoopCountable (AST_FOR (loop, initExpr),
1877                         AST_FOR (loop, condExpr),
1878                         AST_FOR (loop, loopExpr),
1879                         loopCntrl, init, end))
1880     return 0;
1881
1882   /* now do some serious checking on the body of the loop
1883    */
1884
1885   return isConformingBody (loop->left, *loopCntrl, loop->left);
1886
1887 }
1888
1889 /*-----------------------------------------------------------------*/
1890 /* replLoopSym - replace the loop sym by loop sym -1               */
1891 /*-----------------------------------------------------------------*/
1892 static void 
1893 replLoopSym (ast * body, symbol * sym)
1894 {
1895   /* reached end */
1896   if (!body || IS_AST_LINK (body))
1897     return;
1898
1899   if (IS_AST_SYM_VALUE (body))
1900     {
1901
1902       if (isSymbolEqual (AST_SYMBOL (body), sym))
1903         {
1904
1905           body->type = EX_OP;
1906           body->opval.op = '-';
1907           body->left = newAst_VALUE (symbolVal (sym));
1908           body->right = newAst_VALUE (constVal ("1"));
1909
1910         }
1911
1912       return;
1913
1914     }
1915
1916   replLoopSym (body->left, sym);
1917   replLoopSym (body->right, sym);
1918
1919 }
1920
1921 /*-----------------------------------------------------------------*/
1922 /* reverseLoop - do the actual loop reversal                       */
1923 /*-----------------------------------------------------------------*/
1924 ast *
1925 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
1926 {
1927   ast *rloop;
1928
1929   /* create the following tree
1930      <sym> = loopCount ;
1931      for_continue:
1932      forbody
1933      <sym> -= 1;
1934      if (sym) goto for_continue ;
1935      <sym> = end */
1936
1937   /* put it together piece by piece */
1938   rloop = newNode (NULLOP,
1939                    createIf (newAst_VALUE (symbolVal (sym)),
1940                              newNode (GOTO,
1941                                       newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
1942                                       NULL), NULL),
1943                    newNode ('=',
1944                             newAst_VALUE (symbolVal (sym)),
1945                             end));
1946
1947   replLoopSym (loop->left, sym);
1948   setAstLineno (rloop, init->lineno);
1949
1950   rloop = newNode (NULLOP,
1951                    newNode ('=',
1952                             newAst_VALUE (symbolVal (sym)),
1953                             newNode ('-', end, init)),
1954                    createLabel (AST_FOR (loop, continueLabel),
1955                                 newNode (NULLOP,
1956                                          loop->left,
1957                                          newNode (NULLOP,
1958                                                   newNode (SUB_ASSIGN,
1959                                                            newAst_VALUE (symbolVal (sym)),
1960                                                            newAst_VALUE (constVal ("1"))),
1961                                                   rloop))));
1962
1963   rloop->lineno=init->lineno;
1964   return decorateType (rloop, RESULT_CHECK);
1965
1966 }
1967
1968 /*-----------------------------------------------------------------*/
1969 /* searchLitOp - search tree (*ops only) for an ast with literal */
1970 /*-----------------------------------------------------------------*/
1971 static ast *
1972 searchLitOp (ast *tree, ast **parent, const char *ops)
1973 {
1974   ast *ret;
1975
1976   if (tree && optimize.global_cse)
1977     {
1978       /* is there a literal operand? */
1979       if (tree->right &&
1980           IS_AST_OP(tree->right) &&
1981           tree->right->right &&
1982           (tree->right->opval.op == ops[0] || tree->right->opval.op == ops[1]))
1983         {
1984           if (IS_LITERAL (RTYPE (tree->right)) !=
1985               IS_LITERAL (LTYPE (tree->right)))
1986             {
1987               tree->right->decorated = 0;
1988               tree->decorated = 0;
1989               *parent = tree;
1990               return tree->right;
1991             }
1992           ret = searchLitOp (tree->right, parent, ops);
1993           if (ret)
1994             return ret;
1995         }
1996       if (tree->left &&
1997           IS_AST_OP(tree->left) &&
1998           tree->left->right &&
1999           (tree->left->opval.op == ops[0] || tree->left->opval.op == ops[1]))
2000         {
2001           if (IS_LITERAL (RTYPE (tree->left)) !=
2002               IS_LITERAL (LTYPE (tree->left)))
2003             {
2004               tree->left->decorated = 0;
2005               tree->decorated = 0;
2006               *parent = tree;
2007               return tree->left;
2008             }
2009           ret = searchLitOp (tree->left, parent, ops);
2010           if (ret)
2011             return ret;
2012         }
2013     }
2014   return NULL;
2015 }
2016
2017 /*-----------------------------------------------------------------*/
2018 /* getResultFromType                                               */
2019 /*-----------------------------------------------------------------*/
2020 RESULT_TYPE
2021 getResultTypeFromType (sym_link *type)
2022 {
2023   /* type = getSpec (type); */
2024   if (IS_BIT (type))
2025     return RESULT_TYPE_BIT;
2026   if (IS_BITFIELD (type))
2027     {
2028       int blen = SPEC_BLEN (type);
2029       
2030       if (blen <= 1)
2031         return RESULT_TYPE_BIT;
2032       if (blen <= 8)
2033         return RESULT_TYPE_CHAR;
2034       return RESULT_TYPE_INT;
2035     }
2036   if (IS_CHAR (type))
2037     return RESULT_TYPE_CHAR;
2038   if (   IS_INT (type)
2039       && !IS_LONG (type))
2040     return RESULT_TYPE_INT;
2041   return RESULT_TYPE_OTHER;
2042 }
2043
2044 /*-----------------------------------------------------------------*/
2045 /* addCast - adds casts to a type specified by RESULT_TYPE         */
2046 /*-----------------------------------------------------------------*/
2047 static ast *
2048 addCast (ast *tree, RESULT_TYPE resultType, bool upcast)
2049 {
2050   sym_link *newLink;
2051   bool upCasted = FALSE;
2052   
2053   switch (resultType)
2054     {
2055       case RESULT_TYPE_NONE:
2056         /* char: promote to int */
2057         if (!upcast ||
2058             getSize (tree->etype) >= INTSIZE)
2059           return tree;
2060         newLink = newIntLink();
2061         upCasted = TRUE;
2062         break;
2063       case RESULT_TYPE_CHAR:
2064         if (IS_CHAR (tree->etype))
2065           return tree;
2066         newLink = newCharLink();
2067         break;
2068       case RESULT_TYPE_INT:
2069 #if 0
2070         if (getSize (tree->etype) > INTSIZE)
2071           {
2072             /* warn ("Loosing significant digits"); */
2073             return;
2074           }
2075 #endif
2076         /* char: promote to int */
2077         if (!upcast ||
2078             getSize (tree->etype) >= INTSIZE)
2079           return tree;
2080         newLink = newIntLink();
2081         upCasted = TRUE;
2082         break;
2083       case RESULT_TYPE_OTHER:
2084         if (!upcast)
2085           return tree;
2086         /* return type is long, float: promote char to int */
2087         if (getSize (tree->etype) >= INTSIZE)
2088           return tree;
2089         newLink = newIntLink();
2090         upCasted = TRUE;
2091         break;
2092       default:
2093         return tree;
2094     }
2095   tree->decorated = 0;
2096   tree = newNode (CAST, newAst_LINK (newLink), tree);
2097   tree->lineno = tree->right->lineno;
2098   /* keep unsigned type during cast to smaller type,
2099      but not when promoting from char to int */
2100   if (!upCasted)
2101     SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2102   return decorateType (tree, resultType);
2103 }
2104
2105 /*-----------------------------------------------------------------*/
2106 /* resultTypePropagate - decides if resultType can be propagated   */
2107 /*-----------------------------------------------------------------*/
2108 static RESULT_TYPE
2109 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2110 {
2111   switch (tree->opval.op)
2112     {
2113       case '=':
2114       case '?':
2115       case ':':
2116       case '|':
2117       case '^':
2118       case '~':
2119       case '*':
2120       case '+':
2121       case '-':
2122       case LABEL:
2123         return resultType;
2124       case '&':
2125         if (!tree->right)
2126           /* can be unary */
2127           return RESULT_TYPE_NONE;
2128         else
2129           return resultType;
2130       case IFX:
2131         return RESULT_TYPE_IFX;
2132       default:
2133         return RESULT_TYPE_NONE;
2134     }
2135 }
2136
2137 /*-----------------------------------------------------------------*/
2138 /* getLeftResultType - gets type from left branch for propagation  */
2139 /*-----------------------------------------------------------------*/
2140 static RESULT_TYPE
2141 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2142 {
2143   switch (tree->opval.op)
2144     {
2145       case '=':
2146       case CAST:
2147         if (IS_PTR (LTYPE (tree)))
2148           return RESULT_TYPE_NONE;
2149         else
2150           return getResultTypeFromType (LETYPE (tree));
2151       case RETURN:
2152         if (IS_PTR (currFunc->type->next))
2153           return RESULT_TYPE_NONE;
2154         else
2155           return getResultTypeFromType (currFunc->type->next);
2156       case '[':
2157         if (!IS_ARRAY (LTYPE (tree)))
2158           return resultType;
2159         if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 256)
2160           return RESULT_TYPE_CHAR;
2161         return resultType;
2162       default:
2163         return resultType;
2164     }
2165 }
2166
2167 /*--------------------------------------------------------------------*/
2168 /* decorateType - compute type for this tree, also does type checking.*/
2169 /* This is done bottom up, since type has to flow upwards.            */
2170 /* resultType flows top-down and forces e.g. char-arithmetik, if the  */
2171 /* result is a char and the operand(s) are int's.                     */
2172 /* It also does constant folding, and parameter checking.             */
2173 /*--------------------------------------------------------------------*/
2174 ast *
2175 decorateType (ast * tree, RESULT_TYPE resultType)
2176 {
2177   int parmNumber;
2178   sym_link *p;
2179   RESULT_TYPE resultTypeProp;
2180
2181   if (!tree)
2182     return tree;
2183
2184   /* if already has type then do nothing */
2185   if (tree->decorated)
2186     return tree;
2187
2188   tree->decorated = 1;
2189
2190 #if 0
2191   /* print the line          */
2192   /* if not block & function */
2193   if (tree->type == EX_OP &&
2194       (tree->opval.op != FUNCTION &&
2195        tree->opval.op != BLOCK &&
2196        tree->opval.op != NULLOP))
2197     {
2198       filename = tree->filename;
2199       lineno = tree->lineno;
2200     }
2201 #endif
2202
2203   /* if any child is an error | this one is an error do nothing */
2204   if (tree->isError ||
2205       (tree->left && tree->left->isError) ||
2206       (tree->right && tree->right->isError))
2207     return tree;
2208
2209 /*------------------------------------------------------------------*/
2210 /*----------------------------*/
2211 /*   leaf has been reached    */
2212 /*----------------------------*/
2213   lineno=tree->lineno;
2214   /* if this is of type value */
2215   /* just get the type        */
2216   if (tree->type == EX_VALUE)
2217     {
2218
2219       if (IS_LITERAL (tree->opval.val->etype))
2220         {
2221
2222           /* if this is a character array then declare it */
2223           if (IS_ARRAY (tree->opval.val->type))
2224             tree->opval.val = stringToSymbol (tree->opval.val);
2225
2226           /* otherwise just copy the type information */
2227           COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2228           return tree;
2229         }
2230
2231       if (tree->opval.val->sym)
2232         {
2233           /* if the undefined flag is set then give error message */
2234           if (tree->opval.val->sym->undefined)
2235             {
2236               werror (E_ID_UNDEF, tree->opval.val->sym->name);
2237               /* assume int */
2238               TTYPE (tree) = TETYPE (tree) =
2239                 tree->opval.val->type = tree->opval.val->sym->type =
2240                 tree->opval.val->etype = tree->opval.val->sym->etype =
2241                 copyLinkChain (INTTYPE);
2242             }
2243           else
2244             {
2245
2246               /* if impilicit i.e. struct/union member then no type */
2247               if (tree->opval.val->sym->implicit)
2248                 TTYPE (tree) = TETYPE (tree) = NULL;
2249
2250               else
2251                 {
2252
2253                   /* else copy the type */
2254                   COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2255
2256                   /* and mark it as referenced */
2257                   tree->opval.val->sym->isref = 1;
2258                 }
2259             }
2260         }
2261
2262       return tree;
2263     }
2264
2265   /* if type link for the case of cast */
2266   if (tree->type == EX_LINK)
2267     {
2268       COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2269       return tree;
2270     }
2271
2272   {
2273     ast *dtl, *dtr;
2274
2275     #if 0
2276     if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2277       {
2278         if (tree->left && tree->left->type == EX_OPERAND
2279             && (tree->left->opval.op == INC_OP
2280                 || tree->left->opval.op == DEC_OP)
2281             && tree->left->left)
2282           {
2283             tree->left->right = tree->left->left;
2284             tree->left->left = NULL;
2285           }
2286         if (tree->right && tree->right->type == EX_OPERAND
2287             && (tree->right->opval.op == INC_OP
2288                 || tree->right->opval.op == DEC_OP)
2289             && tree->right->left)
2290           {
2291             tree->right->right = tree->right->left;
2292             tree->right->left = NULL;
2293           }
2294       }
2295     #endif
2296
2297     /* Before decorating the left branch we've to decide in dependence
2298        upon tree->opval.op, if resultType can be propagated */
2299     resultTypeProp = resultTypePropagate (tree, resultType);
2300
2301     if (tree->opval.op == '?')
2302       dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2303     else
2304       dtl = decorateType (tree->left, resultTypeProp);
2305
2306     /* if an array node, we may need to swap branches */
2307     if (tree->opval.op == '[')
2308       {
2309         /* determine which is the array & which the index */
2310         if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2311             IS_INTEGRAL (LTYPE (tree)))
2312           {
2313             ast *tempTree = tree->left;
2314             tree->left = tree->right;
2315             tree->right = tempTree;
2316           }
2317       }
2318
2319     /* After decorating the left branch there's type information available
2320        in tree->left->?type. If the op is e.g. '=' we extract the type
2321        information from there and propagate it to the right branch. */
2322     resultTypeProp = getLeftResultType (tree, resultTypeProp);
2323     
2324     switch (tree->opval.op)
2325       {
2326         case '?':
2327           /* delay right side for '?' operator since conditional macro
2328              expansions might rely on this */
2329           dtr = tree->right;
2330           break;
2331         case CALL: 
2332           /* decorate right side for CALL (parameter list) in processParms();
2333              there is resultType available */
2334           dtr = tree->right;
2335           break;
2336         default:     
2337           dtr = decorateType (tree->right, resultTypeProp);
2338           break;
2339       }
2340
2341     /* this is to take care of situations
2342        when the tree gets rewritten */
2343     if (dtl != tree->left)
2344       tree->left = dtl;
2345     if (dtr != tree->right)
2346       tree->right = dtr;
2347     if ((dtl && dtl->isError) || (dtr && dtr->isError))
2348       return tree;
2349   }
2350
2351   /* depending on type of operator do */
2352
2353   switch (tree->opval.op)
2354     {
2355         /*------------------------------------------------------------------*/
2356         /*----------------------------*/
2357         /*        array node          */
2358         /*----------------------------*/
2359     case '[':
2360
2361       /* first check if this is a array or a pointer */
2362       if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2363         {
2364           werror (E_NEED_ARRAY_PTR, "[]");
2365           goto errorTreeReturn;
2366         }
2367
2368       /* check if the type of the idx */
2369       if (!IS_INTEGRAL (RTYPE (tree)))
2370         {
2371           werror (E_IDX_NOT_INT);
2372           goto errorTreeReturn;
2373         }
2374
2375       /* if the left is an rvalue then error */
2376       if (LRVAL (tree))
2377         {
2378           werror (E_LVALUE_REQUIRED, "array access");
2379           goto errorTreeReturn;
2380         }
2381
2382       if (IS_LITERAL (RTYPE (tree)))
2383         {
2384           int arrayIndex = (int) floatFromVal (valFromType (RETYPE (tree)));
2385           int arraySize = DCL_ELEM (LTYPE (tree));
2386           if (arraySize && arrayIndex >= arraySize)
2387             {
2388               werror (W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2389             }
2390         }
2391
2392       RRVAL (tree) = 1;
2393       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2394       return tree;
2395
2396       /*------------------------------------------------------------------*/
2397       /*----------------------------*/
2398       /*      struct/union          */
2399       /*----------------------------*/
2400     case '.':
2401       /* if this is not a structure */
2402       if (!IS_STRUCT (LTYPE (tree)))
2403         {
2404           werror (E_STRUCT_UNION, ".");
2405           goto errorTreeReturn;
2406         }
2407       TTYPE (tree) = structElemType (LTYPE (tree),
2408                                      (tree->right->type == EX_VALUE ?
2409                                tree->right->opval.val : NULL));
2410       TETYPE (tree) = getSpec (TTYPE (tree));
2411       return tree;
2412
2413       /*------------------------------------------------------------------*/
2414       /*----------------------------*/
2415       /*    struct/union pointer    */
2416       /*----------------------------*/
2417     case PTR_OP:
2418       /* if not pointer to a structure */
2419       if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2420         {
2421           werror (E_PTR_REQD);
2422           goto errorTreeReturn;
2423         }
2424
2425       if (!IS_STRUCT (LTYPE (tree)->next))
2426         {
2427           werror (E_STRUCT_UNION, "->");
2428           goto errorTreeReturn;
2429         }
2430
2431       TTYPE (tree) = structElemType (LTYPE (tree)->next,
2432                                      (tree->right->type == EX_VALUE ?
2433                                tree->right->opval.val : NULL));
2434       TETYPE (tree) = getSpec (TTYPE (tree));
2435
2436       /* adjust the storage class */
2437       switch (DCL_TYPE(tree->left->ftype)) {
2438       case POINTER:
2439         SPEC_SCLS(TETYPE(tree)) = S_DATA; 
2440         break;
2441       case FPOINTER:
2442         SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
2443         break;
2444       case CPOINTER:
2445         SPEC_SCLS(TETYPE(tree)) = S_CODE; 
2446         break;
2447       case GPOINTER:
2448         SPEC_SCLS (TETYPE (tree)) = 0;
2449         break;
2450       case PPOINTER:
2451         SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
2452         break;
2453       case IPOINTER:
2454         SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2455         break;
2456       case EEPPOINTER:
2457         SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2458         break;
2459       case UPOINTER:
2460         SPEC_SCLS (TETYPE (tree)) = 0;
2461         break;
2462       case ARRAY:
2463       case FUNCTION:
2464         break;
2465       }
2466       
2467       /* This breaks with extern declarations, bitfields, and perhaps other */
2468       /* cases (gcse). Let's leave this optimization disabled for now and   */
2469       /* ponder if there's a safe way to do this. -- EEP                    */
2470       #if 0
2471       if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2472           && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2473         {
2474             /* If defined    struct type at addr var
2475                then rewrite  (&struct var)->member
2476                as            temp
2477                and define    membertype at (addr+offsetof(struct var,member)) temp
2478             */
2479             symbol *sym;
2480             symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2481                                                 AST_SYMBOL(tree->right));
2482
2483             sym = newSymbol(genSymName (0), 0);
2484             sym->type = TTYPE (tree);
2485             sym->etype = getSpec(sym->type);
2486             sym->lineDef = tree->lineno;
2487             sym->cdef = 1;
2488             sym->isref = 1;
2489             SPEC_STAT (sym->etype) = 1;
2490             SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2491                                      + element->offset;
2492             SPEC_ABSA(sym->etype) = 1;
2493             addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2494             allocGlobal (sym);
2495             
2496             AST_VALUE (tree) = symbolVal(sym);
2497             TLVAL (tree) = 1;
2498             TRVAL (tree) = 0;
2499             tree->type = EX_VALUE;
2500             tree->left = NULL;
2501             tree->right = NULL;
2502         }
2503       #endif
2504       
2505       return tree;
2506
2507       /*------------------------------------------------------------------*/
2508       /*----------------------------*/
2509       /*  ++/-- operation           */
2510       /*----------------------------*/
2511     case INC_OP:
2512     case DEC_OP:
2513       {
2514         sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2515         COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2516         if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2517           werror (E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2518
2519         if (tree->right)
2520           RLVAL (tree) = 1;
2521         else
2522           LLVAL (tree) = 1;
2523         return tree;
2524       }
2525
2526       /*------------------------------------------------------------------*/
2527       /*----------------------------*/
2528       /*  bitwise and               */
2529       /*----------------------------*/
2530     case '&':                   /* can be unary   */
2531       /* if right is NULL then unary operation  */
2532       if (tree->right)          /* not an unary operation */
2533         {
2534
2535           if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2536             {
2537               werror (E_BITWISE_OP);
2538               werror (W_CONTINUE, "left & right types are ");
2539               printTypeChain (LTYPE (tree), stderr);
2540               fprintf (stderr, ",");
2541               printTypeChain (RTYPE (tree), stderr);
2542               fprintf (stderr, "\n");
2543               goto errorTreeReturn;
2544             }
2545
2546           /* if they are both literal */
2547           if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2548             {
2549               tree->type = EX_VALUE;
2550               tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2551                                           valFromType (RETYPE (tree)), '&');
2552
2553               tree->right = tree->left = NULL;
2554               TETYPE (tree) = tree->opval.val->etype;
2555               TTYPE (tree) = tree->opval.val->type;
2556               return tree;
2557             }
2558
2559           /* see if this is a GETHBIT operation if yes
2560              then return that */
2561           {
2562             ast *otree = optimizeGetHbit (tree);
2563
2564             if (otree != tree)
2565               return decorateType (otree, RESULT_CHECK);
2566           }
2567
2568           TTYPE (tree) = computeType (LTYPE (tree),
2569                                       RTYPE (tree),
2570                                       resultType,
2571                                       tree->opval.op);
2572           TETYPE (tree) = getSpec (TTYPE (tree));
2573
2574           /* if left is a literal exchange left & right */
2575           if (IS_LITERAL (LTYPE (tree)))
2576             {
2577               ast *tTree = tree->left;
2578               tree->left = tree->right;
2579               tree->right = tTree;
2580             }
2581
2582           /* if right is a literal and */
2583           /* we can find a 2nd literal in a and-tree then */
2584           /* rearrange the tree */
2585           if (IS_LITERAL (RTYPE (tree)))
2586             {
2587               ast *parent;
2588               ast *litTree = searchLitOp (tree, &parent, "&");
2589               if (litTree)
2590                 {
2591                   DEBUG_CF("&")
2592                   ast *tTree = litTree->left;
2593                   litTree->left = tree->right;
2594                   tree->right = tTree;
2595                   /* both operands in tTree are literal now */
2596                   decorateType (parent, resultType);
2597                 }
2598             }
2599
2600           LRVAL (tree) = RRVAL (tree) = 1;
2601           
2602           return tree;
2603         }
2604
2605       /*------------------------------------------------------------------*/
2606       /*----------------------------*/
2607       /*  address of                */
2608       /*----------------------------*/
2609       p = newLink (DECLARATOR);
2610       /* if bit field then error */
2611       if (IS_BITVAR (tree->left->etype))
2612         {
2613           werror (E_ILLEGAL_ADDR, "address of bit variable");
2614           goto errorTreeReturn;
2615         }
2616
2617       if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2618         {
2619           werror (E_ILLEGAL_ADDR, "address of register variable");
2620           goto errorTreeReturn;
2621         }
2622
2623       if (IS_FUNC (LTYPE (tree)))
2624         {
2625           // this ought to be ignored
2626           return (tree->left);
2627         }
2628
2629       if (IS_LITERAL(LTYPE(tree)))
2630         {
2631           werror (E_ILLEGAL_ADDR, "address of literal");
2632           goto errorTreeReturn;
2633         }
2634
2635      if (LRVAL (tree))
2636         {
2637           werror (E_LVALUE_REQUIRED, "address of");
2638           goto errorTreeReturn;
2639         }
2640       if (!LETYPE (tree))
2641         DCL_TYPE (p) = POINTER;
2642       else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2643         DCL_TYPE (p) = CPOINTER;
2644       else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2645         DCL_TYPE (p) = FPOINTER;
2646       else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2647         DCL_TYPE (p) = PPOINTER;
2648       else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2649         DCL_TYPE (p) = IPOINTER;
2650       else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2651         DCL_TYPE (p) = EEPPOINTER;
2652       else if (SPEC_OCLS(tree->left->etype))
2653           DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2654       else
2655           DCL_TYPE (p) = POINTER;
2656
2657       if (IS_AST_SYM_VALUE (tree->left))
2658         {
2659           AST_SYMBOL (tree->left)->addrtaken = 1;
2660           AST_SYMBOL (tree->left)->allocreq = 1;
2661         }
2662
2663       p->next = LTYPE (tree);
2664       TTYPE (tree) = p;
2665       TETYPE (tree) = getSpec (TTYPE (tree));
2666       LLVAL (tree) = 1;
2667       TLVAL (tree) = 1;
2668
2669       #if 0
2670       if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2671           && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2672         {
2673           symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2674                                       AST_SYMBOL(tree->left->right));
2675           AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2676                                     valueFromLit(element->offset));
2677           tree->left = NULL;
2678           tree->right = NULL;
2679           tree->type = EX_VALUE;
2680           tree->values.literalFromCast = 1;
2681         }
2682       #endif
2683
2684       return tree;
2685
2686       /*------------------------------------------------------------------*/
2687       /*----------------------------*/
2688       /*  bitwise or                */
2689       /*----------------------------*/
2690     case '|':
2691       /* if the rewrite succeeds then don't go any furthur */
2692       {
2693         ast *wtree = optimizeRRCRLC (tree);
2694         if (wtree != tree)
2695           return decorateType (wtree, RESULT_CHECK);
2696         
2697         wtree = optimizeSWAP (tree);
2698         if (wtree != tree)
2699           return decorateType (wtree, RESULT_CHECK);
2700       }
2701
2702       /* if left is a literal exchange left & right */
2703       if (IS_LITERAL (LTYPE (tree)))
2704         {
2705           ast *tTree = tree->left;
2706           tree->left = tree->right;
2707           tree->right = tTree;
2708         }
2709
2710       /* if right is a literal and */
2711       /* we can find a 2nd literal in a or-tree then */
2712       /* rearrange the tree */
2713       if (IS_LITERAL (RTYPE (tree)))
2714         {
2715           ast *parent;
2716           ast *litTree = searchLitOp (tree, &parent, "|");
2717           if (litTree)
2718             {
2719               DEBUG_CF("|")
2720               ast *tTree = litTree->left;
2721               litTree->left = tree->right;
2722               tree->right = tTree;
2723               /* both operands in tTree are literal now */
2724               decorateType (parent, resultType);
2725             }
2726         }
2727       /* fall through */
2728
2729       /*------------------------------------------------------------------*/
2730       /*----------------------------*/
2731       /*  bitwise xor               */
2732       /*----------------------------*/
2733     case '^':
2734       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2735         {
2736           werror (E_BITWISE_OP);
2737           werror (W_CONTINUE, "left & right types are ");
2738           printTypeChain (LTYPE (tree), stderr);
2739           fprintf (stderr, ",");
2740           printTypeChain (RTYPE (tree), stderr);
2741           fprintf (stderr, "\n");
2742           goto errorTreeReturn;
2743         }
2744
2745       /* if they are both literal then */
2746       /* rewrite the tree */
2747       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2748         {
2749           tree->type = EX_VALUE;
2750           tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2751                                         valFromType (RETYPE (tree)),
2752                                         tree->opval.op);
2753           tree->right = tree->left = NULL;
2754           TETYPE (tree) = tree->opval.val->etype;
2755           TTYPE (tree) = tree->opval.val->type;
2756           return tree;
2757         }
2758
2759       /* if left is a literal exchange left & right */
2760       if (IS_LITERAL (LTYPE (tree)))
2761         {
2762           ast *tTree = tree->left;
2763           tree->left = tree->right;
2764           tree->right = tTree;
2765         }
2766
2767       /* if right is a literal and */
2768       /* we can find a 2nd literal in a xor-tree then */
2769       /* rearrange the tree */
2770       if (IS_LITERAL (RTYPE (tree)) &&
2771           tree->opval.op == '^') /* the same source is used by 'bitwise or' */
2772         {
2773           ast *parent;
2774           ast *litTree = searchLitOp (tree, &parent, "^");
2775           if (litTree)
2776             {
2777               DEBUG_CF("^")
2778               ast *tTree = litTree->left;
2779               litTree->left = tree->right;
2780               tree->right = tTree;
2781               /* both operands in litTree are literal now */
2782               decorateType (parent, resultType);
2783             }
2784         }
2785
2786       LRVAL (tree) = RRVAL (tree) = 1;
2787       TETYPE (tree) = getSpec (TTYPE (tree) =
2788                                computeType (LTYPE (tree),
2789                                             RTYPE (tree),
2790                                             resultType,
2791                                             tree->opval.op));
2792
2793       return tree;
2794
2795       /*------------------------------------------------------------------*/
2796       /*----------------------------*/
2797       /*  division                  */
2798       /*----------------------------*/
2799     case '/':
2800       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
2801         {
2802           werror (E_INVALID_OP, "divide");
2803           goto errorTreeReturn;
2804         }
2805       /* if they are both literal then */
2806       /* rewrite the tree */
2807       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2808         {
2809           tree->type = EX_VALUE;
2810           tree->opval.val = valDiv (valFromType (LETYPE (tree)),
2811                                     valFromType (RETYPE (tree)));
2812           tree->right = tree->left = NULL;
2813           TETYPE (tree) = getSpec (TTYPE (tree) =
2814                                    tree->opval.val->type);
2815           return tree;
2816         }
2817
2818       LRVAL (tree) = RRVAL (tree) = 1;
2819
2820       TETYPE (tree) = getSpec (TTYPE (tree) =
2821                                computeType (LTYPE (tree),
2822                                             RTYPE (tree),
2823                                             resultType,
2824                                             tree->opval.op));
2825
2826       /* if right is a literal and */
2827       /* left is also a division by a literal then */
2828       /* rearrange the tree */
2829       if (IS_LITERAL (RTYPE (tree))
2830           /* avoid infinite loop */
2831           && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 1)
2832         {
2833           ast *parent;
2834           ast *litTree = searchLitOp (tree, &parent, "/");
2835           if (litTree)
2836             {
2837               if (IS_LITERAL (RTYPE (litTree)))
2838                 {
2839                   /* foo_div */
2840                   DEBUG_CF("div r")
2841                   litTree->right = newNode ('*',
2842                                             litTree->right,
2843                                             copyAst (tree->right));
2844                   litTree->right->lineno = tree->lineno;
2845
2846                   tree->right->opval.val = constVal ("1");
2847                   decorateType (parent, resultType);
2848                 }
2849               else
2850                 {
2851                   /* litTree->left is literal: no gcse possible.
2852                      We can't call decorateType(parent, RESULT_CHECK), because
2853                      this would cause an infinit loop. */
2854                   parent->decorated = 1;
2855                   decorateType (litTree, resultType);
2856                 }
2857             }
2858         }
2859
2860       return tree;
2861
2862       /*------------------------------------------------------------------*/
2863       /*----------------------------*/
2864       /*            modulus         */
2865       /*----------------------------*/
2866     case '%':
2867       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2868         {
2869           werror (E_BITWISE_OP);
2870           werror (W_CONTINUE, "left & right types are ");
2871           printTypeChain (LTYPE (tree), stderr);
2872           fprintf (stderr, ",");
2873           printTypeChain (RTYPE (tree), stderr);
2874           fprintf (stderr, "\n");
2875           goto errorTreeReturn;
2876         }
2877       /* if they are both literal then */
2878       /* rewrite the tree */
2879       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2880         {
2881           tree->type = EX_VALUE;
2882           tree->opval.val = valMod (valFromType (LETYPE (tree)),
2883                                     valFromType (RETYPE (tree)));
2884           tree->right = tree->left = NULL;
2885           TETYPE (tree) = getSpec (TTYPE (tree) =
2886                                    tree->opval.val->type);
2887           return tree;
2888         }
2889       LRVAL (tree) = RRVAL (tree) = 1;
2890       TETYPE (tree) = getSpec (TTYPE (tree) =
2891                                computeType (LTYPE (tree),
2892                                             RTYPE (tree),
2893                                             resultType,
2894                                             tree->opval.op));
2895       return tree;
2896
2897       /*------------------------------------------------------------------*/
2898       /*----------------------------*/
2899       /*  address dereference       */
2900       /*----------------------------*/
2901     case '*':                   /* can be unary  : if right is null then unary operation */
2902       if (!tree->right)
2903         {
2904           if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
2905             {
2906               werror (E_PTR_REQD);
2907               goto errorTreeReturn;
2908             }
2909
2910           if (LRVAL (tree))
2911             {
2912               werror (E_LVALUE_REQUIRED, "pointer deref");
2913               goto errorTreeReturn;
2914             }
2915           if (IS_ADDRESS_OF_OP(tree->left))
2916             {
2917               /* replace *&obj with obj */
2918               return tree->left->left;
2919             }
2920           TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
2921           TETYPE (tree) = getSpec (TTYPE (tree));
2922           /* adjust the storage class */
2923           switch (DCL_TYPE(tree->left->ftype)) {
2924             case POINTER:
2925               SPEC_SCLS(TETYPE(tree)) = S_DATA;
2926               break;
2927             case FPOINTER:
2928               SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
2929               break;
2930             case CPOINTER:
2931               SPEC_SCLS(TETYPE(tree)) = S_CODE; 
2932               break;
2933             case GPOINTER:
2934               SPEC_SCLS (TETYPE (tree)) = 0;
2935               break;
2936             case PPOINTER:
2937               SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
2938               break;
2939             case IPOINTER:
2940               SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2941               break;
2942             case EEPPOINTER:
2943               SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2944               break;
2945             case UPOINTER:
2946               SPEC_SCLS (TETYPE (tree)) = 0;
2947               break;
2948             case ARRAY:
2949             case FUNCTION:
2950               break;
2951           }
2952           return tree;
2953         }
2954
2955       /*------------------------------------------------------------------*/
2956       /*----------------------------*/
2957       /*      multiplication        */
2958       /*----------------------------*/
2959       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
2960         {
2961           werror (E_INVALID_OP, "multiplication");
2962           goto errorTreeReturn;
2963         }
2964
2965       /* if they are both literal then */
2966       /* rewrite the tree */
2967       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2968         {
2969           tree->type = EX_VALUE;
2970           tree->opval.val = valMult (valFromType (LETYPE (tree)),
2971                                      valFromType (RETYPE (tree)));
2972           tree->right = tree->left = NULL;
2973           TETYPE (tree) = getSpec (TTYPE (tree) =
2974                                    tree->opval.val->type);
2975           return tree;
2976         }
2977
2978       /* if left is a literal exchange left & right */
2979       if (IS_LITERAL (LTYPE (tree)))
2980         {
2981           ast *tTree = tree->left;
2982           tree->left = tree->right;
2983           tree->right = tTree;
2984         }
2985
2986       /* if right is a literal and */
2987       /* we can find a 2nd literal in a mul-tree then */
2988       /* rearrange the tree */
2989       if (IS_LITERAL (RTYPE (tree)))
2990         {
2991           ast *parent;
2992           ast *litTree = searchLitOp (tree, &parent, "*");
2993           if (litTree)
2994             {
2995               DEBUG_CF("mul")
2996               ast *tTree = litTree->left;
2997               litTree->left = tree->right;
2998               tree->right = tTree;
2999               /* both operands in litTree are literal now */
3000               decorateType (parent, resultType);
3001             }
3002         }
3003
3004       LRVAL (tree) = RRVAL (tree) = 1;
3005       tree->left  = addCast (tree->left,  resultType, FALSE);
3006       tree->right = addCast (tree->right, resultType, FALSE);
3007       TETYPE (tree) = getSpec (TTYPE (tree) =
3008                                    computeType (LTYPE (tree),
3009                                                 RTYPE (tree),
3010                                                 resultType,
3011                                                 tree->opval.op));
3012
3013       return tree;
3014
3015       /*------------------------------------------------------------------*/
3016       /*----------------------------*/
3017       /*    unary '+' operator      */
3018       /*----------------------------*/
3019     case '+':
3020       /* if unary plus */
3021       if (!tree->right)
3022         {
3023           if (!IS_ARITHMETIC (LTYPE (tree)))
3024             {
3025               werror (E_UNARY_OP, '+');
3026               goto errorTreeReturn;
3027             }
3028
3029           /* if left is a literal then do it */
3030           if (IS_LITERAL (LTYPE (tree)))
3031             {
3032               tree->type = EX_VALUE;
3033               tree->opval.val = valFromType (LETYPE (tree));
3034               tree->left = NULL;
3035               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3036               return tree;
3037             }
3038           LRVAL (tree) = 1;
3039           COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3040           return tree;
3041         }
3042
3043       /*------------------------------------------------------------------*/
3044       /*----------------------------*/
3045       /*      addition              */
3046       /*----------------------------*/
3047
3048       /* this is not a unary operation */
3049       /* if both pointers then problem */
3050       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3051           (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3052         {
3053           werror (E_PTR_PLUS_PTR);
3054           goto errorTreeReturn;
3055         }
3056
3057       if (!IS_ARITHMETIC (LTYPE (tree)) &&
3058           !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3059         {
3060           werror (E_PLUS_INVALID, "+");
3061           goto errorTreeReturn;
3062         }
3063
3064       if (!IS_ARITHMETIC (RTYPE (tree)) &&
3065           !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3066         {
3067           werror (E_PLUS_INVALID, "+");
3068           goto errorTreeReturn;
3069         }
3070       /* if they are both literal then */
3071       /* rewrite the tree */
3072       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3073         {
3074           tree->type = EX_VALUE;
3075           tree->left  = addCast (tree->left,  resultType, TRUE);
3076           tree->right = addCast (tree->right, resultType, TRUE);
3077           tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3078                                      valFromType (RETYPE (tree)));
3079           tree->right = tree->left = NULL;
3080           TETYPE (tree) = getSpec (TTYPE (tree) =
3081                                    tree->opval.val->type);
3082           return tree;
3083         }
3084
3085       /* if the right is a pointer or left is a literal
3086          xchange left & right */
3087       if (IS_ARRAY (RTYPE (tree)) ||
3088           IS_PTR (RTYPE (tree)) ||
3089           IS_LITERAL (LTYPE (tree)))
3090         {
3091           ast *tTree = tree->left;
3092           tree->left = tree->right;
3093           tree->right = tTree;
3094         }
3095
3096       /* if right is a literal and */
3097       /* left is also an addition/subtraction with a literal then */
3098       /* rearrange the tree */
3099       if (IS_LITERAL (RTYPE (tree)))
3100         {
3101           ast *litTree, *parent;
3102           litTree = searchLitOp (tree, &parent, "+-");
3103           if (litTree)
3104             {
3105               if (litTree->opval.op == '+')
3106                 {
3107                   /* foo_aa */
3108                   DEBUG_CF("+ 1 AA")
3109                   ast *tTree = litTree->left;
3110                   litTree->left = tree->right;
3111                   tree->right = tree->left;
3112                   tree->left = tTree;
3113                 }
3114               else if (litTree->opval.op == '-')
3115                 {
3116                   if (IS_LITERAL (RTYPE (litTree)))
3117                     {
3118                       DEBUG_CF("+ 2 ASR")
3119                       /* foo_asr */
3120                       ast *tTree = litTree->left;
3121                       litTree->left = tree->right;
3122                       tree->right = tTree;
3123                     }
3124                   else
3125                     {
3126                       DEBUG_CF("+ 3 ASL")
3127                       /* foo_asl */
3128                       ast *tTree = litTree->right;
3129                       litTree->right = tree->right;
3130                       tree->right = tTree;
3131                       litTree->opval.op = '+';
3132                       tree->opval.op = '-';
3133                     }
3134                 }
3135               decorateType (parent, resultType);
3136             }
3137         }
3138
3139       LRVAL (tree) = RRVAL (tree) = 1;
3140       /* if the left is a pointer */
3141       if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3142         TETYPE (tree) = getSpec (TTYPE (tree) =
3143                                  LTYPE (tree));
3144       else
3145         {
3146           tree->left  = addCast (tree->left,  resultType, TRUE);
3147           tree->right = addCast (tree->right, resultType, TRUE);
3148           TETYPE (tree) = getSpec (TTYPE (tree) =
3149                                      computeType (LTYPE (tree),
3150                                                   RTYPE (tree),
3151                                                   resultType,
3152                                                   tree->opval.op));
3153         }
3154         
3155       return tree;
3156
3157       /*------------------------------------------------------------------*/
3158       /*----------------------------*/
3159       /*      unary '-'             */
3160       /*----------------------------*/
3161     case '-':                   /* can be unary   */
3162       /* if right is null then unary */
3163       if (!tree->right)
3164         {
3165
3166           if (!IS_ARITHMETIC (LTYPE (tree)))
3167             {
3168               werror (E_UNARY_OP, tree->opval.op);
3169               goto errorTreeReturn;
3170             }
3171
3172           /* if left is a literal then do it */
3173           if (IS_LITERAL (LTYPE (tree)))
3174             {
3175               tree->type = EX_VALUE;
3176               tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3177               tree->left = NULL;
3178               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3179               SPEC_USIGN(TETYPE(tree)) = 0;
3180               return tree;
3181             }
3182           LRVAL (tree) = 1;
3183           TETYPE(tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3184           return tree;
3185         }
3186
3187       /*------------------------------------------------------------------*/
3188       /*----------------------------*/
3189       /*    subtraction             */
3190       /*----------------------------*/
3191
3192       if (!(IS_PTR (LTYPE (tree)) ||
3193             IS_ARRAY (LTYPE (tree)) ||
3194             IS_ARITHMETIC (LTYPE (tree))))
3195         {
3196           werror (E_PLUS_INVALID, "-");
3197           goto errorTreeReturn;
3198         }
3199
3200       if (!(IS_PTR (RTYPE (tree)) ||
3201             IS_ARRAY (RTYPE (tree)) ||
3202             IS_ARITHMETIC (RTYPE (tree))))
3203         {
3204           werror (E_PLUS_INVALID, "-");
3205           goto errorTreeReturn;
3206         }
3207
3208       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3209           !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3210             IS_INTEGRAL (RTYPE (tree))))
3211         {
3212           werror (E_PLUS_INVALID, "-");
3213           goto errorTreeReturn;
3214         }
3215
3216       /* if they are both literal then */
3217       /* rewrite the tree */
3218       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3219         {
3220           tree->type = EX_VALUE;
3221           tree->left  = addCast (tree->left,  resultType, TRUE);
3222           tree->right = addCast (tree->right, resultType, TRUE);
3223           tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3224                                       valFromType (RETYPE (tree)));
3225           tree->right = tree->left = NULL;
3226           TETYPE (tree) = getSpec (TTYPE (tree) =
3227                                    tree->opval.val->type);
3228           return tree;
3229         }
3230
3231       /* if the left & right are equal then zero */
3232       if (isAstEqual (tree->left, tree->right))
3233         {
3234           tree->type = EX_VALUE;
3235           tree->left = tree->right = NULL;
3236           tree->opval.val = constVal ("0");
3237           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3238           return tree;
3239         }
3240
3241       /* if both of them are pointers or arrays then */
3242       /* the result is going to be an integer        */
3243       if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3244           (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3245         TETYPE (tree) = TTYPE (tree) = newIntLink ();
3246       else
3247         /* if only the left is a pointer */
3248         /* then result is a pointer      */
3249       if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3250         TETYPE (tree) = getSpec (TTYPE (tree) =
3251                                  LTYPE (tree));
3252       else
3253         {
3254           tree->left  = addCast (tree->left,  resultType, TRUE);
3255           tree->right = addCast (tree->right, resultType, TRUE);
3256
3257           TETYPE (tree) = getSpec (TTYPE (tree) =
3258                                      computeType (LTYPE (tree),
3259                                                   RTYPE (tree),
3260                                                   resultType,
3261                                                   tree->opval.op));
3262         }
3263
3264       LRVAL (tree) = RRVAL (tree) = 1;
3265
3266       /* if right is a literal and */
3267       /* left is also an addition/subtraction with a literal then */
3268       /* rearrange the tree */
3269       if (IS_LITERAL (RTYPE (tree))
3270           /* avoid infinite loop */
3271           && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 0)
3272         {
3273           ast *litTree, *litParent;
3274           litTree = searchLitOp (tree, &litParent, "+-");
3275           if (litTree)
3276             {
3277               if (litTree->opval.op == '+')
3278                 {
3279                   /* foo_sa */
3280                   DEBUG_CF("- 1 SA")
3281                   ast *tTree = litTree->left;
3282                   litTree->left = litTree->right;
3283                   litTree->right = tree->right;
3284                   tree->right = tTree;
3285                   tree->opval.op = '+';
3286                   litTree->opval.op = '-';
3287                 }
3288               else if (litTree->opval.op == '-')
3289                 {
3290                   if (IS_LITERAL (RTYPE (litTree)))
3291                     {
3292                       /* foo_ssr */
3293                       DEBUG_CF("- 2 SSR")
3294                       ast *tTree = litTree->left;
3295                       litTree->left = tree->right;
3296                       tree->right = litParent->left;
3297                       litParent->left = tTree;
3298                       litTree->opval.op = '+';
3299                       
3300                       tree->decorated = 0;
3301                       decorateType (tree, resultType);
3302                     }
3303                   else
3304                     {
3305                       /* foo_ssl */
3306                       DEBUG_CF("- 3 SSL")
3307                       ast *tTree = litTree->right;
3308                       litTree->right = tree->right;
3309                       tree->right = tTree;
3310                     }
3311                 }
3312               decorateType (litParent, resultType);
3313             }
3314         }
3315       return tree;
3316
3317       /*------------------------------------------------------------------*/
3318       /*----------------------------*/
3319       /*    complement              */
3320       /*----------------------------*/
3321     case '~':
3322       /* can be only integral type */
3323       if (!IS_INTEGRAL (LTYPE (tree)))
3324         {
3325           werror (E_UNARY_OP, tree->opval.op);
3326           goto errorTreeReturn;
3327         }
3328
3329       /* if left is a literal then do it */
3330       if (IS_LITERAL (LTYPE (tree)))
3331         {
3332           tree->type = EX_VALUE;
3333           tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3334           tree->left = NULL;
3335           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3336           return tree;
3337         }
3338       tree->left = addCast (tree->left, resultType, TRUE);
3339       LRVAL (tree) = 1;
3340       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3341       return tree;
3342
3343       /*------------------------------------------------------------------*/
3344       /*----------------------------*/
3345       /*           not              */
3346       /*----------------------------*/
3347     case '!':
3348       /* can be pointer */
3349       if (!IS_ARITHMETIC (LTYPE (tree)) &&
3350           !IS_PTR (LTYPE (tree)) &&
3351           !IS_ARRAY (LTYPE (tree)))
3352         {
3353           werror (E_UNARY_OP, tree->opval.op);
3354           goto errorTreeReturn;
3355         }
3356
3357       /* if left is a literal then do it */
3358       if (IS_LITERAL (LTYPE (tree)))
3359         {
3360           tree->type = EX_VALUE;
3361           tree->opval.val = valNot (valFromType (LETYPE (tree)));
3362           tree->left = NULL;
3363           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3364           return tree;
3365         }
3366       LRVAL (tree) = 1;
3367       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3368       return tree;
3369
3370       /*------------------------------------------------------------------*/
3371       /*----------------------------*/
3372       /*           shift            */
3373       /*----------------------------*/
3374     case RRC:
3375     case RLC:
3376     case SWAP:
3377       TTYPE (tree) = LTYPE (tree);
3378       TETYPE (tree) = LETYPE (tree);
3379       return tree;
3380
3381     case GETHBIT:
3382       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3383       return tree;
3384
3385     case LEFT_OP:
3386     case RIGHT_OP:
3387       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3388         {
3389           werror (E_SHIFT_OP_INVALID);
3390           werror (W_CONTINUE, "left & right types are ");
3391           printTypeChain (LTYPE (tree), stderr);
3392           fprintf (stderr, ",");
3393           printTypeChain (RTYPE (tree), stderr);
3394           fprintf (stderr, "\n");
3395           goto errorTreeReturn;
3396         }
3397
3398       /* make smaller type only if it's a LEFT_OP */
3399       if (tree->opval.op == LEFT_OP)
3400         tree->left = addCast (tree->left, resultType, TRUE);
3401       
3402       /* if they are both literal then */
3403       /* rewrite the tree */
3404       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3405         {
3406           tree->type = EX_VALUE;
3407           tree->opval.val = valShift (valFromType (LETYPE (tree)),
3408                                       valFromType (RETYPE (tree)),
3409                                       (tree->opval.op == LEFT_OP ? 1 : 0));
3410           tree->right = tree->left = NULL;
3411           TETYPE (tree) = getSpec (TTYPE (tree) =
3412                                    tree->opval.val->type);
3413           return tree;
3414         }
3415
3416       LRVAL (tree) = RRVAL (tree) = 1;
3417       if (tree->opval.op == LEFT_OP)
3418         {
3419           TETYPE (tree) = getSpec (TTYPE (tree) =
3420                                        computeType (LTYPE (tree),
3421                                                     NULL,
3422                                                     resultType,
3423                                                     tree->opval.op));
3424         }
3425       else /* RIGHT_OP */
3426         {
3427           /* no promotion necessary */
3428           TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3429           if (IS_LITERAL (TTYPE (tree)))
3430             SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3431         }
3432
3433       /* if only the right side is a literal & we are
3434          shifting more than size of the left operand then zero */
3435       if (IS_LITERAL (RTYPE (tree)) &&
3436           ((TYPE_UDWORD) floatFromVal (valFromType (RETYPE (tree)))) >=
3437           (getSize (TETYPE (tree)) * 8))
3438         {
3439           if (tree->opval.op==LEFT_OP ||
3440               (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3441             {
3442               lineno=tree->lineno;
3443               werror (W_SHIFT_CHANGED,
3444                       (tree->opval.op == LEFT_OP ? "left" : "right"));
3445               tree->type = EX_VALUE;
3446               tree->left = tree->right = NULL;
3447               tree->opval.val = constVal ("0");
3448               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3449               return tree;
3450             }
3451         }
3452
3453       return tree;
3454
3455       /*------------------------------------------------------------------*/
3456       /*----------------------------*/
3457       /*         casting            */
3458       /*----------------------------*/
3459     case CAST:                  /* change the type   */
3460       /* cannot cast to an aggregate type */
3461       if (IS_AGGREGATE (LTYPE (tree)))
3462         {
3463           werror (E_CAST_ILLEGAL);
3464           goto errorTreeReturn;
3465         }
3466
3467       /* make sure the type is complete and sane */
3468       checkTypeSanity(LETYPE(tree), "(cast)");
3469
3470       /* If code memory is read only, then pointers to code memory */
3471       /* implicitly point to constants -- make this explicit       */
3472       {
3473         sym_link *t = LTYPE(tree);
3474         while (t && t->next)
3475           {
3476             if (IS_CODEPTR(t) && port->mem.code_ro)
3477               {
3478                 if (IS_SPEC(t->next))
3479                   SPEC_CONST (t->next) = 1;
3480                 else
3481                   DCL_PTR_CONST (t->next) = 1;
3482               }
3483             t = t->next;
3484           }
3485       }
3486
3487 #if 0
3488       /* if the right is a literal replace the tree */
3489       if (IS_LITERAL (RETYPE (tree))) {
3490               if (!IS_PTR (LTYPE (tree))) {
3491                       tree->type = EX_VALUE;
3492                       tree->opval.val =
3493                               valCastLiteral (LTYPE (tree),
3494                                               floatFromVal (valFromType (RETYPE (tree))));
3495                       tree->left = NULL;
3496                       tree->right = NULL;
3497                       TTYPE (tree) = tree->opval.val->type;
3498                       tree->values.literalFromCast = 1;
3499               } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3500                          ((int)floatFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */  {
3501                       sym_link *rest = LTYPE(tree)->next;
3502                       werror(W_LITERAL_GENERIC);
3503                       TTYPE(tree) = newLink(DECLARATOR);
3504                       DCL_TYPE(TTYPE(tree)) = FPOINTER;
3505                       TTYPE(tree)->next = rest;
3506                       tree->left->opval.lnk = TTYPE(tree);
3507                       LRVAL (tree) = 1;
3508               } else {
3509                       TTYPE (tree) = LTYPE (tree);
3510                       LRVAL (tree) = 1;
3511               }
3512       } else {
3513               TTYPE (tree) = LTYPE (tree);
3514               LRVAL (tree) = 1;
3515       }
3516 #else
3517 #if 0 // this is already checked, now this could be explicit
3518       /* if pointer to struct then check names */
3519       if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3520           IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3521           strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3522         {
3523           werror(W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3524                  SPEC_STRUCT(LETYPE(tree))->tag);
3525         }
3526 #endif
3527       if (IS_ADDRESS_OF_OP(tree->right)
3528           && IS_AST_SYM_VALUE (tree->right->left)
3529           && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3530
3531         tree->type = EX_VALUE;
3532         tree->opval.val =
3533           valCastLiteral (LTYPE (tree),
3534                           SPEC_ADDR (AST_SYMBOL (tree->right->left)->etype));
3535         TTYPE (tree) = tree->opval.val->type;
3536         TETYPE (tree) = getSpec (TTYPE (tree));
3537         tree->left = NULL;
3538         tree->right = NULL;
3539         tree->values.literalFromCast = 1;
3540         return tree;
3541       }
3542
3543       /* handle offsetof macro:            */
3544       /* #define offsetof(TYPE, MEMBER) \  */
3545       /* ((unsigned) &((TYPE *)0)->MEMBER) */
3546       if (IS_ADDRESS_OF_OP(tree->right)
3547           && IS_AST_OP (tree->right->left)
3548           && tree->right->left->opval.op == PTR_OP
3549           && IS_AST_OP (tree->right->left->left)
3550           && tree->right->left->left->opval.op == CAST
3551           && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3552
3553         symbol *element = getStructElement (
3554           SPEC_STRUCT (LETYPE(tree->right->left)),
3555           AST_SYMBOL(tree->right->left->right)
3556         );
3557
3558         if (element) {
3559           tree->type = EX_VALUE;
3560           tree->opval.val = valCastLiteral (
3561             LTYPE (tree),
3562             element->offset
3563             + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
3564           );
3565
3566           TTYPE (tree) = tree->opval.val->type;
3567           TETYPE (tree) = getSpec (TTYPE (tree));
3568           tree->left = NULL;
3569           tree->right = NULL;
3570           return tree;
3571         }
3572       }
3573
3574       /* if the right is a literal replace the tree */
3575       if (IS_LITERAL (RETYPE (tree))) {
3576         #if 0
3577         if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3578           /* rewrite      (type *)litaddr
3579              as           &temp
3580              and define   type at litaddr temp
3581              (but only if type's storage class is not generic)
3582           */
3583           ast *newTree = newNode ('&', NULL, NULL);
3584           symbol *sym;
3585
3586           TTYPE (newTree) = LTYPE (tree);
3587           TETYPE (newTree) = getSpec(LTYPE (tree));
3588
3589           /* define a global symbol at the casted address*/
3590           sym = newSymbol(genSymName (0), 0);
3591           sym->type = LTYPE (tree)->next;
3592           if (!sym->type)
3593             sym->type = newLink (V_VOID);
3594           sym->etype = getSpec(sym->type);
3595           SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
3596           sym->lineDef = tree->lineno;
3597           sym->cdef = 1;
3598           sym->isref = 1;
3599           SPEC_STAT (sym->etype) = 1;
3600           SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
3601           SPEC_ABSA(sym->etype) = 1;
3602           addSym (SymbolTab, sym, sym->name, 0, 0, 0);
3603           allocGlobal (sym);
3604
3605           newTree->left = newAst_VALUE(symbolVal(sym));
3606           newTree->left->lineno = tree->lineno;
3607           LTYPE (newTree) = sym->type;
3608           LETYPE (newTree) = sym->etype;
3609           LLVAL (newTree) = 1;
3610           LRVAL (newTree) = 0;
3611           TLVAL (newTree) = 1;
3612           return newTree;
3613         }
3614         #endif
3615         if (!IS_PTR (LTYPE (tree))) {
3616           tree->type = EX_VALUE;
3617           tree->opval.val =
3618           valCastLiteral (LTYPE (tree),
3619                           floatFromVal (valFromType (RTYPE (tree))));
3620           TTYPE (tree) = tree->opval.val->type;
3621           tree->left = NULL;
3622           tree->right = NULL;
3623           tree->values.literalFromCast = 1;
3624           TETYPE (tree) = getSpec (TTYPE (tree));
3625           return tree;
3626         }
3627       }
3628       TTYPE (tree) = LTYPE (tree);
3629       LRVAL (tree) = 1;
3630
3631 #endif
3632       TETYPE (tree) = getSpec (TTYPE (tree));
3633
3634       return tree;
3635
3636       /*------------------------------------------------------------------*/
3637       /*----------------------------*/
3638       /*       logical &&, ||       */
3639       /*----------------------------*/
3640     case AND_OP:
3641     case OR_OP:
3642       /* each must be arithmetic type or be a pointer */
3643       if (!IS_PTR (LTYPE (tree)) &&
3644           !IS_ARRAY (LTYPE (tree)) &&
3645           !IS_INTEGRAL (LTYPE (tree)))
3646         {
3647           werror (E_COMPARE_OP);
3648           goto errorTreeReturn;
3649         }
3650
3651       if (!IS_PTR (RTYPE (tree)) &&
3652           !IS_ARRAY (RTYPE (tree)) &&
3653           !IS_INTEGRAL (RTYPE (tree)))
3654         {
3655           werror (E_COMPARE_OP);
3656           goto errorTreeReturn;
3657         }
3658       /* if they are both literal then */
3659       /* rewrite the tree */
3660       if (IS_LITERAL (RTYPE (tree)) &&
3661           IS_LITERAL (LTYPE (tree)))
3662         {
3663           tree->type = EX_VALUE;
3664           tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
3665                                            valFromType (RTYPE (tree)),
3666                                            tree->opval.op);
3667           tree->right = tree->left = NULL;
3668           TETYPE (tree) = getSpec (TTYPE (tree) =
3669                                    tree->opval.val->type);
3670           return tree;
3671         }
3672       LRVAL (tree) = RRVAL (tree) = 1;
3673       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3674       return tree;
3675
3676       /*------------------------------------------------------------------*/
3677       /*----------------------------*/
3678       /*     comparison operators   */
3679       /*----------------------------*/
3680     case '>':
3681     case '<':
3682     case LE_OP:
3683     case GE_OP:
3684     case EQ_OP:
3685     case NE_OP:
3686       {
3687         ast *lt = optimizeCompare (tree);
3688
3689         if (tree != lt)
3690           return lt;
3691       }
3692
3693       /* if they are pointers they must be castable */
3694       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
3695         {
3696           if (tree->opval.op==EQ_OP &&
3697               !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
3698             // we cannot cast a gptr to a !gptr: switch the leaves
3699             struct ast *s=tree->left;
3700             tree->left=tree->right;
3701             tree->right=s;
3702           }
3703           if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3704             {
3705               werror (E_COMPARE_OP);
3706               fprintf (stderr, "comparing type ");
3707               printTypeChain (LTYPE (tree), stderr);
3708               fprintf (stderr, "to type ");
3709               printTypeChain (RTYPE (tree), stderr);
3710               fprintf (stderr, "\n");
3711               goto errorTreeReturn;
3712             }
3713         }
3714       /* else they should be promotable to one another */
3715       else
3716         {
3717           if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
3718                 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
3719
3720             if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3721               {
3722                 werror (E_COMPARE_OP);
3723                 fprintf (stderr, "comparing type ");
3724                 printTypeChain (LTYPE (tree), stderr);
3725                 fprintf (stderr, "to type ");
3726                 printTypeChain (RTYPE (tree), stderr);
3727                 fprintf (stderr, "\n");
3728                 goto errorTreeReturn;
3729               }
3730         }
3731       /* if unsigned value < 0  then always false */
3732       /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
3733       if (SPEC_USIGN(LETYPE(tree)) &&
3734           !IS_CHAR(LETYPE(tree)) && /* promotion to signed int */
3735           IS_LITERAL(RTYPE(tree))  &&
3736           ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0)
3737         {
3738           if (tree->opval.op == '<')
3739             {
3740               return tree->right;
3741             }
3742           if (tree->opval.op == '>')
3743             {
3744               if (resultType == RESULT_TYPE_IFX)
3745                 {
3746                   /* the parent is an ifx: */
3747                   /* if (unsigned value) */
3748                   return tree->left;
3749                 }
3750               
3751               /* (unsigned value) ? 1 : 0 */
3752               tree->opval.op = '?';
3753               tree->right = newNode (':',
3754                                      newAst_VALUE (constVal ("1")),
3755                                      tree->right); /* val 0 */
3756               tree->right->lineno = tree->lineno;
3757               tree->right->left->lineno = tree->lineno;
3758               decorateType (tree->right, RESULT_CHECK);
3759             }
3760         }
3761       /* if they are both literal then */
3762       /* rewrite the tree */
3763       if (IS_LITERAL (RTYPE (tree)) &&
3764           IS_LITERAL (LTYPE (tree)))
3765         {
3766           tree->type = EX_VALUE;
3767           tree->opval.val = valCompare (valFromType (LETYPE (tree)),
3768                                         valFromType (RETYPE (tree)),
3769                                         tree->opval.op);
3770           tree->right = tree->left = NULL;
3771           TETYPE (tree) = getSpec (TTYPE (tree) =
3772                                    tree->opval.val->type);
3773           return tree;
3774         }
3775       LRVAL (tree) = RRVAL (tree) = 1;
3776       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3777       return tree;
3778
3779       /*------------------------------------------------------------------*/
3780       /*----------------------------*/
3781       /*             sizeof         */
3782       /*----------------------------*/
3783     case SIZEOF:                /* evaluate wihout code generation */
3784       /* change the type to a integer */
3785       {
3786         int size = getSize (tree->right->ftype);
3787         SNPRINTF(buffer, sizeof(buffer), "%d", size);
3788         if (!size && !IS_VOID(tree->right->ftype))
3789           werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
3790       }
3791       tree->type = EX_VALUE;
3792       tree->opval.val = constVal (buffer);
3793       tree->right = tree->left = NULL;
3794       TETYPE (tree) = getSpec (TTYPE (tree) =
3795                                tree->opval.val->type);
3796       return tree;
3797
3798       /*------------------------------------------------------------------*/
3799       /*----------------------------*/
3800       /*             typeof         */
3801       /*----------------------------*/
3802     case TYPEOF:
3803         /* return typeof enum value */
3804         tree->type = EX_VALUE;
3805         {
3806             int typeofv = 0;
3807             if (IS_SPEC(tree->right->ftype)) {
3808                 switch (SPEC_NOUN(tree->right->ftype)) {
3809                 case V_INT:
3810                     if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
3811                     else typeofv = TYPEOF_INT;
3812                     break;
3813                 case V_FLOAT:
3814                     typeofv = TYPEOF_FLOAT;
3815                     break;
3816                 case V_CHAR:
3817                     typeofv = TYPEOF_CHAR;
3818                     break;
3819                 case V_VOID:
3820                     typeofv = TYPEOF_VOID;
3821                     break;
3822                 case V_STRUCT:
3823                     typeofv = TYPEOF_STRUCT;
3824                     break;
3825                 case V_BITFIELD:
3826                     typeofv = TYPEOF_BITFIELD;
3827                     break;
3828                 case V_BIT:
3829                     typeofv = TYPEOF_BIT;
3830                     break;
3831                 case V_SBIT:
3832                     typeofv = TYPEOF_SBIT;
3833                     break;
3834                 default:
3835                     break;
3836                 }
3837             } else {
3838                 switch (DCL_TYPE(tree->right->ftype)) {
3839                 case POINTER:
3840                     typeofv = TYPEOF_POINTER;
3841                     break;
3842                 case FPOINTER:
3843                     typeofv = TYPEOF_FPOINTER;
3844                     break;
3845                 case CPOINTER:
3846                     typeofv = TYPEOF_CPOINTER;
3847                     break;
3848                 case GPOINTER:
3849                     typeofv = TYPEOF_GPOINTER;
3850                     break;
3851                 case PPOINTER:
3852                     typeofv = TYPEOF_PPOINTER;
3853                     break;
3854                 case IPOINTER:
3855                     typeofv = TYPEOF_IPOINTER;
3856                     break;
3857                 case ARRAY:
3858                     typeofv = TYPEOF_ARRAY;
3859                     break;
3860                 case FUNCTION:
3861                     typeofv = TYPEOF_FUNCTION;
3862                     break;
3863                 default:
3864                     break;
3865                 }
3866             }
3867             SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
3868             tree->opval.val = constVal (buffer);
3869             tree->right = tree->left = NULL;
3870             TETYPE (tree) = getSpec (TTYPE (tree) =
3871                                      tree->opval.val->type);
3872         }
3873         return tree;
3874       /*------------------------------------------------------------------*/
3875       /*----------------------------*/
3876       /* conditional operator  '?'  */
3877       /*----------------------------*/
3878     case '?':
3879       /* the type is value of the colon operator (on the right) */
3880       assert (IS_COLON_OP (tree->right));
3881       /* if already known then replace the tree : optimizer will do it
3882          but faster to do it here */
3883       if (IS_LITERAL (LTYPE (tree)))
3884         {
3885           if (((int) floatFromVal (valFromType (LETYPE (tree)))) != 0)
3886             return decorateType (tree->right->left, resultTypeProp);
3887           else
3888             return decorateType (tree->right->right, resultTypeProp);
3889         }
3890       else
3891         {
3892           tree->right = decorateType (tree->right, resultTypeProp);
3893           TTYPE (tree) = RTYPE (tree);
3894           TETYPE (tree) = getSpec (TTYPE (tree));
3895         }
3896       return tree;
3897
3898     case ':':
3899       /* if they don't match we have a problem */
3900       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3901         {
3902           werror (E_TYPE_MISMATCH, "conditional operator", " ");
3903           goto errorTreeReturn;
3904         }
3905
3906       TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
3907                                   resultType, tree->opval.op);
3908       TETYPE (tree) = getSpec (TTYPE (tree));
3909       return tree;
3910
3911
3912 #if 0 // assignment operators are converted by the parser
3913       /*------------------------------------------------------------------*/
3914       /*----------------------------*/
3915       /*    assignment operators    */
3916       /*----------------------------*/
3917     case MUL_ASSIGN:
3918     case DIV_ASSIGN:
3919       /* for these it must be both must be integral */
3920       if (!IS_ARITHMETIC (LTYPE (tree)) ||
3921           !IS_ARITHMETIC (RTYPE (tree)))
3922         {
3923           werror (E_OPS_INTEGRAL);
3924           goto errorTreeReturn;
3925         }
3926       RRVAL (tree) = 1;
3927       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3928
3929       if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
3930         werror (E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
3931
3932       if (LRVAL (tree))
3933         {
3934           werror (E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
3935           goto errorTreeReturn;
3936         }
3937       LLVAL (tree) = 1;
3938
3939       return tree;
3940
3941     case AND_ASSIGN:
3942     case OR_ASSIGN:
3943     case XOR_ASSIGN:
3944     case RIGHT_ASSIGN:
3945     case LEFT_ASSIGN:
3946       /* for these it must be both must be integral */
3947       if (!IS_INTEGRAL (LTYPE (tree)) ||
3948           !IS_INTEGRAL (RTYPE (tree)))
3949         {
3950           werror (E_OPS_INTEGRAL);
3951           goto errorTreeReturn;
3952         }
3953       RRVAL (tree) = 1;
3954       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3955
3956       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
3957         werror (E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
3958
3959       if (LRVAL (tree))
3960         {
3961           werror (E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
3962           goto errorTreeReturn;
3963         }
3964       LLVAL (tree) = 1;
3965
3966       return tree;
3967
3968       /*------------------------------------------------------------------*/
3969       /*----------------------------*/
3970       /*    -= operator             */
3971       /*----------------------------*/
3972     case SUB_ASSIGN:
3973       if (!(IS_PTR (LTYPE (tree)) ||
3974             IS_ARITHMETIC (LTYPE (tree))))
3975         {
3976           werror (E_PLUS_INVALID, "-=");
3977           goto errorTreeReturn;
3978         }
3979
3980       if (!(IS_PTR (RTYPE (tree)) ||
3981             IS_ARITHMETIC (RTYPE (tree))))
3982         {
3983           werror (E_PLUS_INVALID, "-=");
3984           goto errorTreeReturn;
3985         }
3986       RRVAL (tree) = 1;
3987       TETYPE (tree) = getSpec (TTYPE (tree) =
3988                                computeType (LTYPE (tree),
3989                                             RTYPE (tree),
3990                                             RESULT_TYPE_NOPROM,
3991                                             tree->opval.op));
3992
3993       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
3994         werror (E_CODE_WRITE, "-=");
3995
3996       if (LRVAL (tree))
3997         {
3998           werror (E_LVALUE_REQUIRED, "-=");
3999           goto errorTreeReturn;
4000         }
4001       LLVAL (tree) = 1;
4002
4003       return tree;
4004
4005       /*------------------------------------------------------------------*/
4006       /*----------------------------*/
4007       /*          += operator       */
4008       /*----------------------------*/
4009     case ADD_ASSIGN:
4010       /* this is not a unary operation */
4011       /* if both pointers then problem */
4012       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4013         {
4014           werror (E_PTR_PLUS_PTR);
4015           goto errorTreeReturn;
4016         }
4017
4018       if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4019         {
4020           werror (E_PLUS_INVALID, "+=");
4021           goto errorTreeReturn;
4022         }
4023
4024       if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4025         {
4026           werror (E_PLUS_INVALID, "+=");
4027           goto errorTreeReturn;
4028         }
4029       RRVAL (tree) = 1;
4030       TETYPE (tree) = getSpec (TTYPE (tree) =
4031                                computeType (LTYPE (tree),
4032                                             RTYPE (tree),
4033                                             RESULT_TYPE_NOPROM,
4034                                             tree->opval.op));
4035
4036       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4037         werror (E_CODE_WRITE, "+=");
4038
4039       if (LRVAL (tree))
4040         {
4041           werror (E_LVALUE_REQUIRED, "+=");
4042           goto errorTreeReturn;
4043         }
4044
4045       tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_CHECK);
4046       tree->opval.op = '=';
4047
4048       return tree;
4049 #endif
4050
4051       /*------------------------------------------------------------------*/
4052       /*----------------------------*/
4053       /*      straight assignemnt   */
4054       /*----------------------------*/
4055     case '=':
4056       /* cannot be an aggregate */
4057       if (IS_AGGREGATE (LTYPE (tree)))
4058         {
4059           werror (E_AGGR_ASSIGN);
4060           goto errorTreeReturn;
4061         }
4062
4063       /* they should either match or be castable */
4064       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4065         {
4066           werror (E_TYPE_MISMATCH, "assignment", " ");
4067           printFromToType(RTYPE(tree),LTYPE(tree));
4068         }
4069
4070       /* if the left side of the tree is of type void
4071          then report error */
4072       if (IS_VOID (LTYPE (tree)))
4073         {
4074           werror (E_CAST_ZERO);
4075           printFromToType(RTYPE(tree), LTYPE(tree));
4076         }
4077
4078       TETYPE (tree) = getSpec (TTYPE (tree) =
4079                                LTYPE (tree));
4080       RRVAL (tree) = 1;
4081       LLVAL (tree) = 1;
4082       if (!tree->initMode ) {
4083         if (IS_CONSTANT(LTYPE(tree)))
4084           werror (E_CODE_WRITE, "=");
4085       }
4086       if (LRVAL (tree))
4087         {
4088           werror (E_LVALUE_REQUIRED, "=");
4089           goto errorTreeReturn;
4090         }
4091
4092       return tree;
4093
4094       /*------------------------------------------------------------------*/
4095       /*----------------------------*/
4096       /*      comma operator        */
4097       /*----------------------------*/
4098     case ',':
4099       TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4100       return tree;
4101
4102       /*------------------------------------------------------------------*/
4103       /*----------------------------*/
4104       /*       function call        */
4105       /*----------------------------*/
4106     case CALL:
4107       
4108       /* undo any explicit pointer derefernce; PCALL will handle it instead */
4109       if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4110         {
4111           if (tree->left->opval.op == '*' && !tree->left->right)
4112             tree->left = tree->left->left;
4113         }
4114
4115       /* require a function or pointer to function */
4116       if (!IS_FUNC (LTYPE (tree))
4117           && !(IS_CODEPTR (LTYPE (tree)) && IS_FUNC (LTYPE (tree)->next)))
4118         {
4119           werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4120           goto errorTreeReturn;
4121         }
4122
4123       {
4124         sym_link *functype;      
4125         parmNumber = 1;
4126
4127         if (IS_CODEPTR(LTYPE(tree)))
4128           functype = LTYPE (tree)->next;
4129         else
4130           functype = LTYPE (tree);
4131
4132         if (processParms (tree->left, FUNC_ARGS(functype),
4133                           &tree->right, &parmNumber, TRUE)) {
4134           goto errorTreeReturn;
4135         }
4136
4137         if ((options.stackAuto || IFFUNC_ISREENT (functype)) && 
4138             !IFFUNC_ISBUILTIN(functype))
4139           {
4140             reverseParms (tree->right);
4141           }
4142
4143         TTYPE (tree) = functype->next;
4144         TETYPE (tree) = getSpec (TTYPE (tree));
4145       }
4146       return tree;
4147
4148       /*------------------------------------------------------------------*/
4149       /*----------------------------*/
4150       /*     return statement       */
4151       /*----------------------------*/
4152     case RETURN:
4153       if (!tree->right)
4154         goto voidcheck;
4155
4156       if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4157         {
4158           werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4159           printFromToType (RTYPE(tree), currFunc->type->next);
4160           goto errorTreeReturn;
4161         }
4162
4163       if (IS_VOID (currFunc->type->next)
4164           && tree->right &&
4165           !IS_VOID (RTYPE (tree)))
4166         {
4167           werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4168           goto errorTreeReturn;
4169         }
4170
4171       /* if there is going to be a casting required then add it */
4172       if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4173         {
4174           tree->right =
4175             decorateType (newNode (CAST,
4176                           newAst_LINK (copyLinkChain (currFunc->type->next)),
4177                                         tree->right),
4178                           RESULT_CHECK);
4179         }
4180
4181       RRVAL (tree) = 1;
4182       return tree;
4183
4184     voidcheck:
4185
4186       if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4187         {
4188           werror (W_VOID_FUNC, currFunc->name);
4189           goto errorTreeReturn;
4190         }
4191
4192       TTYPE (tree) = TETYPE (tree) = NULL;
4193       return tree;
4194
4195       /*------------------------------------------------------------------*/
4196       /*----------------------------*/
4197       /*     switch statement       */
4198       /*----------------------------*/
4199     case SWITCH:
4200       /* the switch value must be an integer */
4201       if (!IS_INTEGRAL (LTYPE (tree)))
4202         {
4203           werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4204           goto errorTreeReturn;
4205         }
4206       LRVAL (tree) = 1;
4207       TTYPE (tree) = TETYPE (tree) = NULL;
4208       return tree;
4209
4210       /*------------------------------------------------------------------*/
4211       /*----------------------------*/
4212       /* ifx Statement              */
4213       /*----------------------------*/
4214     case IFX:
4215       tree->left = backPatchLabels (tree->left,
4216                                     tree->trueLabel,
4217                                     tree->falseLabel);
4218       TTYPE (tree) = TETYPE (tree) = NULL;
4219       return tree;
4220
4221       /*------------------------------------------------------------------*/
4222       /*----------------------------*/
4223       /* for Statement              */
4224       /*----------------------------*/
4225     case FOR:
4226
4227       decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_CHECK);
4228       decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_CHECK);
4229       decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_CHECK);
4230
4231       /* if the for loop is reversible then
4232          reverse it otherwise do what we normally
4233          do */
4234       {
4235         symbol *sym;
4236         ast *init, *end;
4237
4238         if (isLoopReversible (tree, &sym, &init, &end))
4239           return reverseLoop (tree, sym, init, end);
4240         else
4241           return decorateType (createFor (AST_FOR (tree, trueLabel),
4242                                           AST_FOR (tree, continueLabel),
4243                                           AST_FOR (tree, falseLabel),
4244                                           AST_FOR (tree, condLabel),
4245                                           AST_FOR (tree, initExpr),
4246                                           AST_FOR (tree, condExpr),
4247                                           AST_FOR (tree, loopExpr),
4248                                           tree->left), RESULT_CHECK);
4249       }
4250     case PARAM:
4251       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4252               "node PARAM shouldn't be processed here");
4253               /* but in processParams() */
4254       return tree;
4255     default:
4256       TTYPE (tree) = TETYPE (tree) = NULL;
4257       return tree;
4258     }
4259
4260   /* some error found this tree will be killed */
4261 errorTreeReturn:
4262   TTYPE (tree) = TETYPE (tree) = newCharLink ();
4263   tree->opval.op = NULLOP;
4264   tree->isError = 1;
4265
4266   return tree;
4267 }
4268
4269 /*-----------------------------------------------------------------*/
4270 /* sizeofOp - processes size of operation                          */
4271 /*-----------------------------------------------------------------*/
4272 value *
4273 sizeofOp (sym_link * type)
4274 {
4275   char buff[10];
4276   int size;
4277
4278   /* make sure the type is complete and sane */
4279   checkTypeSanity(type, "(sizeof)");
4280
4281   /* get the size and convert it to character  */
4282   SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4283   if (!size && !IS_VOID(type))
4284     werror (E_SIZEOF_INCOMPLETE_TYPE);
4285
4286   /* now convert into value  */
4287   return constVal (buff);
4288 }
4289
4290
4291 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4292 #define IS_OR(ex)  (ex->type == EX_OP && ex->opval.op == OR_OP )
4293 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4294 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4295 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4296 #define IS_LT(ex)  (ex->type == EX_OP && ex->opval.op == '<' )
4297 #define IS_GT(ex)  (ex->type == EX_OP && ex->opval.op == '>')
4298
4299 /*-----------------------------------------------------------------*/
4300 /* backPatchLabels - change and or not operators to flow control    */
4301 /*-----------------------------------------------------------------*/
4302 ast *
4303 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4304 {
4305
4306   if (!tree)
4307     return NULL;
4308
4309   if (!(IS_ANDORNOT (tree)))
4310     return tree;
4311
4312   /* if this an and */
4313   if (IS_AND (tree))
4314     {
4315       static int localLbl = 0;
4316       symbol *localLabel;
4317
4318       SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4319       localLabel = newSymbol (buffer, NestLevel);
4320
4321       tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4322
4323       /* if left is already a IFX then just change the if true label in that */
4324       if (!IS_IFX (tree->left))
4325         tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4326
4327       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4328       /* right is a IFX then just join */
4329       if (IS_IFX (tree->right))
4330         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4331
4332       tree->right = createLabel (localLabel, tree->right);
4333       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4334
4335       return newNode (NULLOP, tree->left, tree->right);
4336     }
4337
4338   /* if this is an or operation */
4339   if (IS_OR (tree))
4340     {
4341       static int localLbl = 0;
4342       symbol *localLabel;
4343
4344       SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4345       localLabel = newSymbol (buffer, NestLevel);
4346
4347       tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4348
4349       /* if left is already a IFX then just change the if true label in that */
4350       if (!IS_IFX (tree->left))
4351         tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4352
4353       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4354       /* right is a IFX then just join */
4355       if (IS_IFX (tree->right))
4356         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4357
4358       tree->right = createLabel (localLabel, tree->right);
4359       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4360
4361       return newNode (NULLOP, tree->left, tree->right);
4362     }
4363
4364   /* change not */
4365   if (IS_NOT (tree))
4366     {
4367       int wasnot = IS_NOT (tree->left);
4368       tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4369
4370       /* if the left is already a IFX */
4371       if (!IS_IFX (tree->left))
4372         tree->left = newNode (IFX, tree->left, NULL);
4373
4374       if (wasnot)
4375         {
4376           tree->left->trueLabel = trueLabel;
4377           tree->left->falseLabel = falseLabel;
4378         }
4379       else
4380         {
4381           tree->left->trueLabel = falseLabel;
4382           tree->left->falseLabel = trueLabel;
4383         }
4384       return tree->left;
4385     }
4386
4387   if (IS_IFX (tree))
4388     {
4389       tree->trueLabel = trueLabel;
4390       tree->falseLabel = falseLabel;
4391     }
4392
4393   return tree;
4394 }
4395
4396
4397 /*-----------------------------------------------------------------*/
4398 /* createBlock - create expression tree for block                  */
4399 /*-----------------------------------------------------------------*/
4400 ast *
4401 createBlock (symbol * decl, ast * body)
4402 {
4403   ast *ex;
4404
4405   /* if the block has nothing */
4406   if (!body && !decl)
4407     return NULL;
4408
4409   ex = newNode (BLOCK, NULL, body);
4410   ex->values.sym = decl;
4411   
4412   ex->right = ex->right;
4413   ex->level++;
4414   ex->lineno = 0;
4415   return ex;
4416 }
4417
4418 /*-----------------------------------------------------------------*/
4419 /* createLabel - creates the expression tree for labels            */
4420 /*-----------------------------------------------------------------*/
4421 ast *
4422 createLabel (symbol * label, ast * stmnt)
4423 {
4424   symbol *csym;
4425   char name[SDCC_NAME_MAX + 1];
4426   ast *rValue;
4427
4428   /* must create fresh symbol if the symbol name  */
4429   /* exists in the symbol table, since there can  */
4430   /* be a variable with the same name as the labl */
4431   if ((csym = findSym (SymbolTab, NULL, label->name)) &&
4432       (csym->level == label->level))
4433     label = newSymbol (label->name, label->level);
4434
4435   /* change the name before putting it in add _ */
4436   SNPRINTF(name, sizeof(name), "%s", label->name);
4437
4438   /* put the label in the LabelSymbol table    */
4439   /* but first check if a label of the same    */
4440   /* name exists                               */
4441   if ((csym = findSym (LabelTab, NULL, name)))
4442     werror (E_DUPLICATE_LABEL, label->name);
4443   else
4444     addSym (LabelTab, label, name, label->level, 0, 0);
4445
4446   label->islbl = 1;
4447   label->key = labelKey++;
4448   rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
4449   rValue->lineno = 0;
4450
4451   return rValue;
4452 }
4453
4454 /*-----------------------------------------------------------------*/
4455 /* createCase - generates the parsetree for a case statement       */
4456 /*-----------------------------------------------------------------*/
4457 ast *
4458 createCase (ast * swStat, ast * caseVal, ast * stmnt)
4459 {
4460   char caseLbl[SDCC_NAME_MAX + 1];
4461   ast *rexpr;
4462   value *val;
4463
4464   /* if the switch statement does not exist */
4465   /* then case is out of context            */
4466   if (!swStat)
4467     {
4468       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
4469       return NULL;
4470     }
4471
4472   caseVal = decorateType (resolveSymbols (caseVal), RESULT_CHECK);
4473   /* if not a constant then error  */
4474   if (!IS_LITERAL (caseVal->ftype))
4475     {
4476       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
4477       return NULL;
4478     }
4479
4480   /* if not a integer than error */
4481   if (!IS_INTEGRAL (caseVal->ftype))
4482     {
4483       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
4484       return NULL;
4485     }
4486
4487   /* find the end of the switch values chain   */
4488   if (!(val = swStat->values.switchVals.swVals))
4489     swStat->values.switchVals.swVals = caseVal->opval.val;
4490   else
4491     {
4492       /* also order the cases according to value */
4493       value *pval = NULL;
4494       int cVal = (int) floatFromVal (caseVal->opval.val);
4495       while (val && (int) floatFromVal (val) < cVal)
4496         {
4497           pval = val;
4498           val = val->next;
4499         }
4500
4501       /* if we reached the end then */
4502       if (!val)
4503         {
4504           pval->next = caseVal->opval.val;
4505         }
4506       else if ((int) floatFromVal (val) == cVal)
4507         {
4508           werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
4509                     "case");
4510           return NULL;
4511         }
4512       else
4513         {
4514           /* we found a value greater than */
4515           /* the current value we must add this */
4516           /* before the value */
4517           caseVal->opval.val->next = val;
4518
4519           /* if this was the first in chain */
4520           if (swStat->values.switchVals.swVals == val)
4521             swStat->values.switchVals.swVals =
4522               caseVal->opval.val;
4523           else
4524             pval->next = caseVal->opval.val;
4525         }
4526
4527     }
4528
4529   /* create the case label   */
4530   SNPRINTF(caseLbl, sizeof(caseLbl), 
4531            "_case_%d_%d",
4532            swStat->values.switchVals.swNum,
4533            (int) floatFromVal (caseVal->opval.val));
4534
4535   rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
4536   rexpr->lineno = 0;
4537   return rexpr;
4538 }
4539
4540 /*-----------------------------------------------------------------*/
4541 /* createDefault - creates the parse tree for the default statement */
4542 /*-----------------------------------------------------------------*/
4543 ast *
4544 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
4545 {
4546   char defLbl[SDCC_NAME_MAX + 1];
4547
4548   /* if the switch statement does not exist */
4549   /* then case is out of context            */
4550   if (!swStat)
4551     {
4552       werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
4553       return NULL;
4554     }
4555
4556   if (swStat->values.switchVals.swDefault)
4557     {
4558       werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
4559                 "default");
4560       return NULL;
4561     }
4562
4563   /* turn on the default flag   */
4564   swStat->values.switchVals.swDefault = 1;
4565
4566   /* create the label  */
4567   SNPRINTF (defLbl, sizeof(defLbl),
4568             "_default_%d", swStat->values.switchVals.swNum);
4569   return createLabel (newSymbol (defLbl, 0), stmnt);
4570 }
4571
4572 /*-----------------------------------------------------------------*/
4573 /* createIf - creates the parsetree for the if statement           */
4574 /*-----------------------------------------------------------------*/
4575 ast *
4576 createIf (ast * condAst, ast * ifBody, ast * elseBody)
4577 {
4578   static int Lblnum = 0;
4579   ast *ifTree;
4580   symbol *ifTrue, *ifFalse, *ifEnd;
4581
4582   /* if neither exists */
4583   if (!elseBody && !ifBody) {
4584     // if there are no side effects (i++, j() etc)
4585     if (!hasSEFcalls(condAst)) {
4586       return condAst;
4587     }
4588   }
4589
4590   /* create the labels */
4591   SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
4592   ifFalse = newSymbol (buffer, NestLevel);
4593   /* if no else body then end == false */
4594   if (!elseBody)
4595     ifEnd = ifFalse;
4596   else
4597     {
4598       SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
4599       ifEnd = newSymbol (buffer, NestLevel);
4600     }
4601
4602   SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
4603   ifTrue = newSymbol (buffer, NestLevel);
4604
4605   Lblnum++;
4606
4607   /* attach the ifTrue label to the top of it body */
4608   ifBody = createLabel (ifTrue, ifBody);
4609   /* attach a goto end to the ifBody if else is present */
4610   if (elseBody)
4611     {
4612       ifBody = newNode (NULLOP, ifBody,
4613                         newNode (GOTO,
4614                                  newAst_VALUE (symbolVal (ifEnd)),
4615                                  NULL));
4616       /* put the elseLabel on the else body */
4617       elseBody = createLabel (ifFalse, elseBody);
4618       /* out the end at the end of the body */
4619       elseBody = newNode (NULLOP,
4620                           elseBody,
4621                           createLabel (ifEnd, NULL));
4622     }
4623   else
4624     {
4625       ifBody = newNode (NULLOP, ifBody,
4626                         createLabel (ifFalse, NULL));
4627     }
4628   condAst = backPatchLabels (condAst, ifTrue, ifFalse);
4629   if (IS_IFX (condAst))
4630     ifTree = condAst;
4631   else
4632     ifTree = newIfxNode (condAst, ifTrue, ifFalse);
4633
4634   return newNode (NULLOP, ifTree,
4635                   newNode (NULLOP, ifBody, elseBody));
4636
4637 }
4638
4639 /*-----------------------------------------------------------------*/
4640 /* createDo - creates parse tree for do                            */
4641 /*        _dobody_n:                                               */
4642 /*            statements                                           */
4643 /*        _docontinue_n:                                           */
4644 /*            condition_expression +-> trueLabel -> _dobody_n      */
4645 /*                                 |                               */
4646 /*                                 +-> falseLabel-> _dobreak_n     */
4647 /*        _dobreak_n:                                              */
4648 /*-----------------------------------------------------------------*/
4649 ast *
4650 createDo (symbol * trueLabel, symbol * continueLabel,
4651           symbol * falseLabel, ast * condAst, ast * doBody)
4652 {
4653   ast *doTree;
4654
4655
4656   /* if the body does not exist then it is simple */
4657   if (!doBody)
4658     {
4659       condAst = backPatchLabels (condAst, continueLabel, NULL);
4660       doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
4661                 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
4662       doTree->trueLabel = continueLabel;
4663       doTree->falseLabel = NULL;
4664       return doTree;
4665     }
4666
4667   /* otherwise we have a body */
4668   condAst = backPatchLabels (condAst, trueLabel, falseLabel);
4669
4670   /* attach the body label to the top */
4671   doBody = createLabel (trueLabel, doBody);
4672   /* attach the continue label to end of body */
4673   doBody = newNode (NULLOP, doBody,
4674                     createLabel (continueLabel, NULL));
4675
4676   /* now put the break label at the end */
4677   if (IS_IFX (condAst))
4678     doTree = condAst;
4679   else
4680     doTree = newIfxNode (condAst, trueLabel, falseLabel);
4681
4682   doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
4683
4684   /* putting it together */
4685   return newNode (NULLOP, doBody, doTree);
4686 }
4687
4688 /*-----------------------------------------------------------------*/
4689 /* createFor - creates parse tree for 'for' statement              */
4690 /*        initExpr                                                 */
4691 /*   _forcond_n:                                                   */
4692 /*        condExpr  +-> trueLabel -> _forbody_n                    */
4693 /*                  |                                              */
4694 /*                  +-> falseLabel-> _forbreak_n                   */
4695 /*   _forbody_n:                                                   */
4696 /*        statements                                               */
4697 /*   _forcontinue_n:                                               */
4698 /*        loopExpr                                                 */
4699 /*        goto _forcond_n ;                                        */
4700 /*   _forbreak_n:                                                  */
4701 /*-----------------------------------------------------------------*/
4702 ast *
4703 createFor (symbol * trueLabel, symbol * continueLabel,
4704            symbol * falseLabel, symbol * condLabel,
4705            ast * initExpr, ast * condExpr, ast * loopExpr,
4706            ast * forBody)
4707 {
4708   ast *forTree;
4709
4710   /* if loopexpression not present then we can generate it */
4711   /* the same way as a while */
4712   if (!loopExpr)
4713     return newNode (NULLOP, initExpr,
4714                     createWhile (trueLabel, continueLabel,
4715                                  falseLabel, condExpr, forBody));
4716   /* vanilla for statement */
4717   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
4718
4719   if (condExpr && !IS_IFX (condExpr))
4720     condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
4721
4722
4723   /* attach condition label to condition */
4724   condExpr = createLabel (condLabel, condExpr);
4725
4726   /* attach body label to body */
4727   forBody = createLabel (trueLabel, forBody);
4728
4729   /* attach continue to forLoop expression & attach */
4730   /* goto the forcond @ and of loopExpression       */
4731   loopExpr = createLabel (continueLabel,
4732                           newNode (NULLOP,
4733                                    loopExpr,
4734                                    newNode (GOTO,
4735                                        newAst_VALUE (symbolVal (condLabel)),
4736                                             NULL)));
4737   /* now start putting them together */
4738   forTree = newNode (NULLOP, initExpr, condExpr);
4739   forTree = newNode (NULLOP, forTree, forBody);
4740   forTree = newNode (NULLOP, forTree, loopExpr);
4741   /* finally add the break label */
4742   forTree = newNode (NULLOP, forTree,
4743                      createLabel (falseLabel, NULL));
4744   return forTree;
4745 }
4746
4747 /*-----------------------------------------------------------------*/
4748 /* createWhile - creates parse tree for while statement            */
4749 /*               the while statement will be created as follows    */
4750 /*                                                                 */
4751 /*      _while_continue_n:                                         */
4752 /*            condition_expression +-> trueLabel -> _while_boby_n  */
4753 /*                                 |                               */
4754 /*                                 +-> falseLabel -> _while_break_n */
4755 /*      _while_body_n:                                             */
4756 /*            statements                                           */
4757 /*            goto _while_continue_n                               */
4758 /*      _while_break_n:                                            */
4759 /*-----------------------------------------------------------------*/
4760 ast *
4761 createWhile (symbol * trueLabel, symbol * continueLabel,
4762              symbol * falseLabel, ast * condExpr, ast * whileBody)
4763 {
4764   ast *whileTree;
4765
4766   /* put the continue label */
4767   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
4768   condExpr = createLabel (continueLabel, condExpr);
4769   condExpr->lineno = 0;
4770
4771   /* put the body label in front of the body */
4772   whileBody = createLabel (trueLabel, whileBody);
4773   whileBody->lineno = 0;
4774   /* put a jump to continue at the end of the body */
4775   /* and put break label at the end of the body */
4776   whileBody = newNode (NULLOP,
4777                        whileBody,
4778                        newNode (GOTO,
4779                                 newAst_VALUE (symbolVal (continueLabel)),
4780                                 createLabel (falseLabel, NULL)));
4781
4782   /* put it all together */
4783   if (IS_IFX (condExpr))
4784     whileTree = condExpr;
4785   else
4786     {
4787       whileTree = newNode (IFX, condExpr, NULL);
4788       /* put the true & false labels in place */
4789       whileTree->trueLabel = trueLabel;
4790       whileTree->falseLabel = falseLabel;
4791     }
4792
4793   return newNode (NULLOP, whileTree, whileBody);
4794 }
4795
4796 /*-----------------------------------------------------------------*/
4797 /* optimizeGetHbit - get highest order bit of the expression       */
4798 /*-----------------------------------------------------------------*/
4799 ast *
4800 optimizeGetHbit (ast * tree)
4801 {
4802   int i, j;
4803   /* if this is not a bit and */
4804   if (!IS_BITAND (tree))
4805     return tree;
4806
4807   /* will look for tree of the form
4808      ( expr >> ((sizeof expr) -1) ) & 1 */
4809   if (!IS_AST_LIT_VALUE (tree->right))
4810     return tree;
4811
4812   if (AST_LIT_VALUE (tree->right) != 1)
4813     return tree;
4814
4815   if (!IS_RIGHT_OP (tree->left))
4816     return tree;
4817
4818   if (!IS_AST_LIT_VALUE (tree->left->right))
4819     return tree;
4820
4821   if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
4822       (j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
4823     return tree;
4824       
4825   /* make sure the port supports GETHBIT */
4826   if (port->hasExtBitOp
4827       && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
4828     return tree;
4829
4830   return decorateType (newNode (GETHBIT, tree->left->left, NULL), RESULT_CHECK);
4831
4832 }
4833
4834 /*-----------------------------------------------------------------*/
4835 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry     */
4836 /*-----------------------------------------------------------------*/
4837 ast *
4838 optimizeRRCRLC (ast * root)
4839 {
4840   /* will look for trees of the form
4841      (?expr << 1) | (?expr >> 7) or
4842      (?expr >> 7) | (?expr << 1) will make that
4843      into a RLC : operation ..
4844      Will also look for
4845      (?expr >> 1) | (?expr << 7) or
4846      (?expr << 7) | (?expr >> 1) will make that
4847      into a RRC operation
4848      note : by 7 I mean (number of bits required to hold the
4849      variable -1 ) */
4850   /* if the root operations is not a | operation the not */
4851   if (!IS_BITOR (root))
4852     return root;
4853
4854   /* I have to think of a better way to match patterns this sucks */
4855   /* that aside let start looking for the first case : I use a the
4856      negative check a lot to improve the efficiency */
4857   /* (?expr << 1) | (?expr >> 7) */
4858   if (IS_LEFT_OP (root->left) &&
4859       IS_RIGHT_OP (root->right))
4860     {
4861
4862       if (!SPEC_USIGN (TETYPE (root->left->left)))
4863         return root;
4864
4865       if (!IS_AST_LIT_VALUE (root->left->right) ||
4866           !IS_AST_LIT_VALUE (root->right->right))
4867         goto tryNext0;
4868
4869       /* make sure it is the same expression */
4870       if (!isAstEqual (root->left->left,
4871                        root->right->left))
4872         goto tryNext0;
4873
4874       if (AST_LIT_VALUE (root->left->right) != 1)
4875         goto tryNext0;
4876
4877       if (AST_LIT_VALUE (root->right->right) !=
4878           (getSize (TTYPE (root->left->left)) * 8 - 1))
4879         goto tryNext0;
4880
4881       /* make sure the port supports RLC */
4882       if (port->hasExtBitOp
4883           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
4884         return root;
4885
4886       /* whew got the first case : create the AST */
4887       return newNode (RLC, root->left->left, NULL);
4888     }
4889
4890 tryNext0:
4891   /* check for second case */
4892   /* (?expr >> 7) | (?expr << 1) */
4893   if (IS_LEFT_OP (root->right) &&
4894       IS_RIGHT_OP (root->left))
4895     {
4896
4897       if (!SPEC_USIGN (TETYPE (root->left->left)))
4898         return root;
4899
4900       if (!IS_AST_LIT_VALUE (root->left->right) ||
4901           !IS_AST_LIT_VALUE (root->right->right))
4902         goto tryNext1;
4903
4904       /* make sure it is the same symbol */
4905       if (!isAstEqual (root->left->left,
4906                        root->right->left))
4907         goto tryNext1;
4908
4909       if (AST_LIT_VALUE (root->right->right) != 1)
4910         goto tryNext1;
4911
4912       if (AST_LIT_VALUE (root->left->right) !=
4913           (getSize (TTYPE (root->left->left)) * 8 - 1))
4914         goto tryNext1;
4915
4916       /* make sure the port supports RLC */
4917       if (port->hasExtBitOp
4918           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
4919         return root;
4920
4921       /* whew got the first case : create the AST */
4922       return newNode (RLC, root->left->left, NULL);
4923
4924     }
4925
4926 tryNext1:
4927   /* third case for RRC */
4928   /*  (?symbol >> 1) | (?symbol << 7) */
4929   if (IS_LEFT_OP (root->right) &&
4930       IS_RIGHT_OP (root->left))
4931     {
4932
4933       if (!SPEC_USIGN (TETYPE (root->left->left)))
4934         return root;
4935
4936       if (!IS_AST_LIT_VALUE (root->left->right) ||
4937           !IS_AST_LIT_VALUE (root->right->right))
4938         goto tryNext2;
4939
4940       /* make sure it is the same symbol */
4941       if (!isAstEqual (root->left->left,
4942                        root->right->left))
4943         goto tryNext2;
4944
4945       if (AST_LIT_VALUE (root->left->right) != 1)
4946         goto tryNext2;
4947
4948       if (AST_LIT_VALUE (root->right->right) !=
4949           (getSize (TTYPE (root->left->left)) * 8 - 1))
4950         goto tryNext2;
4951
4952       /* make sure the port supports RRC */
4953       if (port->hasExtBitOp
4954           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
4955         return root;
4956
4957       /* whew got the first case : create the AST */
4958       return newNode (RRC, root->left->left, NULL);
4959
4960     }
4961 tryNext2:
4962   /* fourth and last case for now */
4963   /* (?symbol << 7) | (?symbol >> 1) */
4964   if (IS_RIGHT_OP (root->right) &&
4965       IS_LEFT_OP (root->left))
4966     {
4967
4968       if (!SPEC_USIGN (TETYPE (root->left->left)))
4969         return root;
4970
4971       if (!IS_AST_LIT_VALUE (root->left->right) ||
4972           !IS_AST_LIT_VALUE (root->right->right))
4973         return root;
4974
4975       /* make sure it is the same symbol */
4976       if (!isAstEqual (root->left->left,
4977                        root->right->left))
4978         return root;
4979
4980       if (AST_LIT_VALUE (root->right->right) != 1)
4981         return root;
4982
4983       if (AST_LIT_VALUE (root->left->right) !=
4984           (getSize (TTYPE (root->left->left)) * 8 - 1))
4985         return root;
4986
4987       /* make sure the port supports RRC */
4988       if (port->hasExtBitOp
4989           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
4990         return root;
4991
4992       /* whew got the first case : create the AST */
4993       return newNode (RRC, root->left->left, NULL);
4994
4995     }
4996
4997   /* not found return root */
4998   return root;
4999 }
5000
5001 /*-----------------------------------------------------------------*/
5002 /* optimizeSWAP :- optimize for nibble/byte/word swaps             */
5003 /*-----------------------------------------------------------------*/
5004 ast *
5005 optimizeSWAP (ast * root)
5006 {
5007   /* will look for trees of the form
5008      (?expr << 4) | (?expr >> 4) or
5009      (?expr >> 4) | (?expr << 4) will make that
5010      into a SWAP : operation ..
5011      note : by 4 I mean (number of bits required to hold the
5012      variable /2 ) */
5013   /* if the root operations is not a | operation the not */
5014   if (!IS_BITOR (root))
5015     return root;
5016
5017   /* (?expr << 4) | (?expr >> 4) */
5018   if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5019       || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5020     {
5021
5022       if (!SPEC_USIGN (TETYPE (root->left->left)))
5023         return root;
5024
5025       if (!IS_AST_LIT_VALUE (root->left->right) ||
5026           !IS_AST_LIT_VALUE (root->right->right))
5027         return root;
5028
5029       /* make sure it is the same expression */
5030       if (!isAstEqual (root->left->left,
5031                        root->right->left))
5032         return root;
5033
5034       if (AST_LIT_VALUE (root->left->right) !=
5035           (getSize (TTYPE (root->left->left)) * 4))
5036         return root;
5037
5038       if (AST_LIT_VALUE (root->right->right) !=
5039           (getSize (TTYPE (root->left->left)) * 4))
5040         return root;
5041
5042       /* make sure the port supports SWAP */
5043       if (port->hasExtBitOp
5044           && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5045         return root;
5046
5047       /* found it : create the AST */
5048       return newNode (SWAP, root->left->left, NULL);
5049     }
5050
5051
5052   /* not found return root */
5053   return root;
5054 }
5055
5056 /*-----------------------------------------------------------------*/
5057 /* optimizeCompare - otimizes compares for bit variables     */
5058 /*-----------------------------------------------------------------*/
5059 static ast *
5060 optimizeCompare (ast * root)
5061 {
5062   ast *optExpr = NULL;
5063   value *vleft;
5064   value *vright;
5065   unsigned int litValue;
5066
5067   /* if nothing then return nothing */
5068   if (!root)
5069     return NULL;
5070
5071   /* if not a compare op then do leaves */
5072   if (!IS_COMPARE_OP (root))
5073     {
5074       root->left = optimizeCompare (root->left);
5075       root->right = optimizeCompare (root->right);
5076       return root;
5077     }
5078
5079   /* if left & right are the same then depending
5080      of the operation do */
5081   if (isAstEqual (root->left, root->right))
5082     {
5083       switch (root->opval.op)
5084         {
5085         case '>':
5086         case '<':
5087         case NE_OP:
5088           optExpr = newAst_VALUE (constVal ("0"));
5089           break;
5090         case GE_OP:
5091         case LE_OP:
5092         case EQ_OP:
5093           optExpr = newAst_VALUE (constVal ("1"));
5094           break;
5095         }
5096
5097       return decorateType (optExpr, RESULT_CHECK);
5098     }
5099
5100   vleft = (root->left->type == EX_VALUE ?
5101            root->left->opval.val : NULL);
5102
5103   vright = (root->right->type == EX_VALUE ?
5104             root->right->opval.val : NULL);
5105
5106   /* if left is a BITVAR in BITSPACE */
5107   /* and right is a LITERAL then opt- */
5108   /* imize else do nothing       */
5109   if (vleft && vright &&
5110       IS_BITVAR (vleft->etype) &&
5111       IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5112       IS_LITERAL (vright->etype))
5113     {
5114
5115       /* if right side > 1 then comparison may never succeed */
5116       if ((litValue = (int) floatFromVal (vright)) > 1)
5117         {
5118           werror (W_BAD_COMPARE);
5119           goto noOptimize;
5120         }
5121
5122       if (litValue)
5123         {
5124           switch (root->opval.op)
5125             {
5126             case '>':           /* bit value greater than 1 cannot be */
5127               werror (W_BAD_COMPARE);
5128               goto noOptimize;
5129               break;
5130
5131             case '<':           /* bit value < 1 means 0 */
5132             case NE_OP:
5133               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5134               break;
5135
5136             case LE_OP: /* bit value <= 1 means no check */
5137               optExpr = newAst_VALUE (vright);
5138               break;
5139
5140             case GE_OP: /* bit value >= 1 means only check for = */
5141             case EQ_OP:
5142               optExpr = newAst_VALUE (vleft);
5143               break;
5144             }
5145         }
5146       else
5147         {                       /* literal is zero */
5148           switch (root->opval.op)
5149             {
5150             case '<':           /* bit value < 0 cannot be */
5151               werror (W_BAD_COMPARE);
5152               goto noOptimize;
5153               break;
5154
5155             case '>':           /* bit value > 0 means 1 */
5156             case NE_OP:
5157               optExpr = newAst_VALUE (vleft);
5158               break;
5159
5160             case LE_OP: /* bit value <= 0 means no check */
5161             case GE_OP: /* bit value >= 0 means no check */
5162               werror (W_BAD_COMPARE);
5163               goto noOptimize;
5164               break;
5165
5166             case EQ_OP: /* bit == 0 means ! of bit */
5167               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5168               break;
5169             }
5170         }
5171       return decorateType (resolveSymbols (optExpr), RESULT_CHECK);
5172     }                           /* end-of-if of BITVAR */
5173
5174 noOptimize:
5175   return root;
5176 }
5177 /*-----------------------------------------------------------------*/
5178 /* addSymToBlock : adds the symbol to the first block we find      */
5179 /*-----------------------------------------------------------------*/
5180 void 
5181 addSymToBlock (symbol * sym, ast * tree)
5182 {
5183   /* reached end of tree or a leaf */
5184   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5185     return;
5186
5187   /* found a block */
5188   if (IS_AST_OP (tree) &&
5189       tree->opval.op == BLOCK)
5190     {
5191
5192       symbol *lsym = copySymbol (sym);
5193
5194       lsym->next = AST_VALUES (tree, sym);
5195       AST_VALUES (tree, sym) = lsym;
5196       return;
5197     }
5198
5199   addSymToBlock (sym, tree->left);
5200   addSymToBlock (sym, tree->right);
5201 }
5202
5203 /*-----------------------------------------------------------------*/
5204 /* processRegParms - do processing for register parameters         */
5205 /*-----------------------------------------------------------------*/
5206 static void 
5207 processRegParms (value * args, ast * body)
5208 {
5209   while (args)
5210     {
5211       if (IS_REGPARM (args->etype))
5212         addSymToBlock (args->sym, body);
5213       args = args->next;
5214     }
5215 }
5216
5217 /*-----------------------------------------------------------------*/
5218 /* resetParmKey - resets the operandkeys for the symbols           */
5219 /*-----------------------------------------------------------------*/
5220 DEFSETFUNC (resetParmKey)
5221 {
5222   symbol *sym = item;
5223
5224   sym->key = 0;
5225   sym->defs = NULL;
5226   sym->uses = NULL;
5227   sym->remat = 0;
5228   return 1;
5229 }
5230
5231 /*-----------------------------------------------------------------*/
5232 /* createFunction - This is the key node that calls the iCode for  */
5233 /*                  generating the code for a function. Note code  */
5234 /*                  is generated function by function, later when  */
5235 /*                  add inter-procedural analysis this will change */
5236 /*-----------------------------------------------------------------*/
5237 ast *
5238 createFunction (symbol * name, ast * body)
5239 {
5240   ast *ex;
5241   symbol *csym;
5242   int stack = 0;
5243   sym_link *fetype;
5244   iCode *piCode = NULL;
5245
5246   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
5247     fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
5248
5249   /* if check function return 0 then some problem */
5250   if (checkFunction (name, NULL) == 0)
5251     return NULL;
5252
5253   /* create a dummy block if none exists */
5254   if (!body)
5255     body = newNode (BLOCK, NULL, NULL);
5256
5257   noLineno++;
5258
5259   /* check if the function name already in the symbol table */
5260   if ((csym = findSym (SymbolTab, NULL, name->name)))
5261     {
5262       name = csym;
5263       /* special case for compiler defined functions
5264          we need to add the name to the publics list : this
5265          actually means we are now compiling the compiler
5266          support routine */
5267       if (name->cdef)
5268         {
5269           addSet (&publics, name);
5270         }
5271     }
5272   else
5273     {
5274       addSymChain (name);
5275       allocVariables (name);
5276     }
5277   name->lastLine = mylineno;
5278   currFunc = name;
5279
5280   /* set the stack pointer */
5281   /* PENDING: check this for the mcs51 */
5282   stackPtr = -port->stack.direction * port->stack.call_overhead;
5283   if (IFFUNC_ISISR (name->type))
5284     stackPtr -= port->stack.direction * port->stack.isr_overhead;
5285   if (IFFUNC_ISREENT (name->type) || options.stackAuto)
5286     stackPtr -= port->stack.direction * port->stack.reent_overhead;
5287
5288   xstackPtr = -port->stack.direction * port->stack.call_overhead;
5289
5290   fetype = getSpec (name->type);        /* get the specifier for the function */
5291   /* if this is a reentrant function then */
5292   if (IFFUNC_ISREENT (name->type))
5293     reentrant++;
5294
5295   allocParms (FUNC_ARGS(name->type));   /* allocate the parameters */
5296
5297   /* do processing for parameters that are passed in registers */
5298   processRegParms (FUNC_ARGS(name->type), body);
5299
5300   /* set the stack pointer */
5301   stackPtr = 0;
5302   xstackPtr = -1;
5303
5304   /* allocate & autoinit the block variables */
5305   processBlockVars (body, &stack, ALLOCATE);
5306
5307   /* save the stack information */
5308   if (options.useXstack)
5309     name->xstack = SPEC_STAK (fetype) = stack;
5310   else
5311     name->stack = SPEC_STAK (fetype) = stack;
5312
5313   /* name needs to be mangled */
5314   SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
5315
5316   body = resolveSymbols (body); /* resolve the symbols */
5317   body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
5318                                         
5319
5320   ex = newAst_VALUE (symbolVal (name)); /* create name */
5321   ex = newNode (FUNCTION, ex, body);
5322   ex->values.args = FUNC_ARGS(name->type);
5323   ex->decorated=1;
5324   if (options.dump_tree) PA(ex);
5325   if (fatalError)
5326     {
5327       werror (E_FUNC_NO_CODE, name->name);
5328       goto skipall;
5329     }
5330
5331   /* create the node & generate intermediate code */
5332   GcurMemmap = code;
5333   codeOutFile = code->oFile;
5334   piCode = iCodeFromAst (ex);
5335
5336   if (fatalError)
5337     {
5338       werror (E_FUNC_NO_CODE, name->name);
5339       goto skipall;
5340     }
5341
5342   eBBlockFromiCode (piCode);
5343
5344   /* if there are any statics then do them */
5345   if (staticAutos)
5346     {
5347       GcurMemmap = statsg;
5348       codeOutFile = statsg->oFile;
5349       eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_CHECK)));
5350       staticAutos = NULL;
5351     }
5352
5353 skipall:
5354
5355   /* dealloc the block variables */
5356   processBlockVars (body, &stack, DEALLOCATE);
5357   outputDebugStackSymbols();
5358   /* deallocate paramaters */
5359   deallocParms (FUNC_ARGS(name->type));
5360
5361   if (IFFUNC_ISREENT (name->type))
5362     reentrant--;
5363
5364   /* we are done freeup memory & cleanup */
5365   noLineno--;
5366   if (port->reset_labelKey) labelKey = 1;
5367   name->key = 0;
5368   FUNC_HASBODY(name->type) = 1;
5369   addSet (&operKeyReset, name);
5370   applyToSet (operKeyReset, resetParmKey);
5371
5372   if (options.debug)
5373     cdbStructBlock(1);
5374
5375   cleanUpLevel (LabelTab, 0);
5376   cleanUpBlock (StructTab, 1);
5377   cleanUpBlock (TypedefTab, 1);
5378
5379   xstack->syms = NULL;
5380   istack->syms = NULL;
5381   return NULL;
5382 }
5383
5384
5385 #define INDENT(x,f) { int i ; fprintf (f, "%d:", tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
5386 /*-----------------------------------------------------------------*/
5387 /* ast_print : prints the ast (for debugging purposes)             */
5388 /*-----------------------------------------------------------------*/
5389
5390 void ast_print (ast * tree, FILE *outfile, int indent)
5391 {
5392
5393         if (!tree) return ;
5394
5395         /* can print only decorated trees */
5396         if (!tree->decorated) return;
5397
5398         /* if any child is an error | this one is an error do nothing */
5399         if (tree->isError ||
5400             (tree->left && tree->left->isError) ||
5401             (tree->right && tree->right->isError)) {
5402                 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
5403         }
5404
5405
5406         /* print the line          */
5407         /* if not block & function */
5408         if (tree->type == EX_OP &&
5409             (tree->opval.op != FUNCTION &&
5410              tree->opval.op != BLOCK &&
5411              tree->opval.op != NULLOP)) {
5412         }
5413
5414         if (tree->opval.op == FUNCTION) {
5415                 int arg=0;
5416                 value *args=FUNC_ARGS(tree->left->opval.val->type);
5417                 fprintf(outfile,"FUNCTION (%s=%p) type (",
5418                         tree->left->opval.val->name, tree);
5419                 printTypeChain (tree->left->opval.val->type->next,outfile);
5420                 fprintf(outfile,") args (");
5421                 do {
5422                   if (arg) {
5423                     fprintf (outfile, ", ");
5424                   }
5425                   printTypeChain (args ? args->type : NULL, outfile);
5426                   arg++;
5427                   args= args ? args->next : NULL;
5428                 } while (args);
5429                 fprintf(outfile,")\n");
5430                 ast_print(tree->left,outfile,indent);
5431                 ast_print(tree->right,outfile,indent);
5432                 return ;
5433         }
5434         if (tree->opval.op == BLOCK) {
5435                 symbol *decls = tree->values.sym;
5436                 INDENT(indent,outfile);
5437                 fprintf(outfile,"{\n");
5438                 while (decls) {
5439                         INDENT(indent+2,outfile);
5440                         fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
5441                                 decls->name, decls);
5442                         printTypeChain(decls->type,outfile);
5443                         fprintf(outfile,")\n");
5444
5445                         decls = decls->next;
5446                 }
5447                 ast_print(tree->right,outfile,indent+2);
5448                 INDENT(indent,outfile);
5449                 fprintf(outfile,"}\n");
5450                 return;
5451         }
5452         if (tree->opval.op == NULLOP) {
5453                 ast_print(tree->left,outfile,indent);
5454                 ast_print(tree->right,outfile,indent);
5455                 return ;
5456         }
5457         INDENT(indent,outfile);
5458
5459         /*------------------------------------------------------------------*/
5460         /*----------------------------*/
5461         /*   leaf has been reached    */
5462         /*----------------------------*/
5463         /* if this is of type value */
5464         /* just get the type        */
5465         if (tree->type == EX_VALUE) {
5466
5467                 if (IS_LITERAL (tree->opval.val->etype)) {
5468                         fprintf(outfile,"CONSTANT (%p) value = ", tree);
5469                         if (SPEC_USIGN (tree->opval.val->etype))
5470                                 fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val));
5471                         else
5472                                 fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val));
5473                         fprintf(outfile,", 0x%x, %f", (TYPE_UDWORD) floatFromVal(tree->opval.val),
5474                                                       floatFromVal(tree->opval.val));
5475                 } else if (tree->opval.val->sym) {
5476                         /* if the undefined flag is set then give error message */
5477                         if (tree->opval.val->sym->undefined) {
5478                                 fprintf(outfile,"UNDEFINED SYMBOL ");
5479                         } else {
5480                                 fprintf(outfile,"SYMBOL ");
5481                         }
5482                         fprintf(outfile,"(%s=%p)",
5483                                 tree->opval.val->sym->name,tree);
5484                 }
5485                 if (tree->ftype) {
5486                         fprintf(outfile," type (");
5487                         printTypeChain(tree->ftype,outfile);
5488                         fprintf(outfile,")\n");
5489                 } else {
5490                         fprintf(outfile,"\n");
5491                 }
5492                 return ;
5493         }
5494
5495         /* if type link for the case of cast */
5496         if (tree->type == EX_LINK) {
5497                 fprintf(outfile,"TYPENODE (%p) type = (",tree);
5498                 printTypeChain(tree->opval.lnk,outfile);
5499                 fprintf(outfile,")\n");
5500                 return ;
5501         }
5502
5503
5504         /* depending on type of operator do */
5505
5506         switch (tree->opval.op) {
5507                 /*------------------------------------------------------------------*/
5508                 /*----------------------------*/
5509                 /*        array node          */
5510                 /*----------------------------*/
5511         case '[':
5512                 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
5513                 printTypeChain(tree->ftype,outfile);
5514                 fprintf(outfile,")\n");
5515                 ast_print(tree->left,outfile,indent+2);
5516                 ast_print(tree->right,outfile,indent+2);
5517                 return;
5518
5519                 /*------------------------------------------------------------------*/
5520                 /*----------------------------*/
5521                 /*      struct/union          */
5522                 /*----------------------------*/
5523         case '.':
5524                 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
5525                 printTypeChain(tree->ftype,outfile);
5526                 fprintf(outfile,")\n");
5527                 ast_print(tree->left,outfile,indent+2);
5528                 ast_print(tree->right,outfile,indent+2);
5529                 return ;
5530
5531                 /*------------------------------------------------------------------*/
5532                 /*----------------------------*/
5533                 /*    struct/union pointer    */
5534                 /*----------------------------*/
5535         case PTR_OP:
5536                 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
5537                 printTypeChain(tree->ftype,outfile);
5538                 fprintf(outfile,")\n");
5539                 ast_print(tree->left,outfile,indent+2);
5540                 ast_print(tree->right,outfile,indent+2);
5541                 return ;
5542
5543                 /*------------------------------------------------------------------*/
5544                 /*----------------------------*/
5545                 /*  ++/-- operation           */
5546                 /*----------------------------*/
5547         case INC_OP:
5548                 if (tree->left)
5549                   fprintf(outfile,"post-");
5550                 else
5551                   fprintf(outfile,"pre-");
5552                 fprintf(outfile,"INC_OP (%p) type (",tree);
5553                 printTypeChain(tree->ftype,outfile);
5554                 fprintf(outfile,")\n");
5555                 ast_print(tree->left,outfile,indent+2); /* postincrement case */
5556                 ast_print(tree->right,outfile,indent+2); /* preincrement case */
5557                 return ;
5558
5559         case DEC_OP:
5560                 if (tree->left)
5561                   fprintf(outfile,"post-");
5562                 else
5563                   fprintf(outfile,"pre-");
5564                 fprintf(outfile,"DEC_OP (%p) type (",tree);
5565                 printTypeChain(tree->ftype,outfile);
5566                 fprintf(outfile,")\n");
5567                 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
5568                 ast_print(tree->right,outfile,indent+2); /* predecrement case */
5569                 return ;
5570
5571                 /*------------------------------------------------------------------*/
5572                 /*----------------------------*/
5573                 /*  bitwise and               */
5574                 /*----------------------------*/
5575         case '&':
5576                 if (tree->right) {
5577                         fprintf(outfile,"& (%p) type (",tree);
5578                         printTypeChain(tree->ftype,outfile);
5579                         fprintf(outfile,")\n");
5580                         ast_print(tree->left,outfile,indent+2);
5581                         ast_print(tree->right,outfile,indent+2);
5582                 } else {
5583                         fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
5584                         printTypeChain(tree->ftype,outfile);
5585                         fprintf(outfile,")\n");
5586                         ast_print(tree->left,outfile,indent+2);
5587                         ast_print(tree->right,outfile,indent+2);
5588                 }
5589                 return ;
5590                 /*----------------------------*/
5591                 /*  bitwise or                */
5592                 /*----------------------------*/
5593         case '|':
5594                 fprintf(outfile,"OR (%p) type (",tree);
5595                 printTypeChain(tree->ftype,outfile);
5596                 fprintf(outfile,")\n");
5597                 ast_print(tree->left,outfile,indent+2);
5598                 ast_print(tree->right,outfile,indent+2);
5599                 return ;
5600                 /*------------------------------------------------------------------*/
5601                 /*----------------------------*/
5602                 /*  bitwise xor               */
5603                 /*----------------------------*/
5604         case '^':
5605                 fprintf(outfile,"XOR (%p) type (",tree);
5606                 printTypeChain(tree->ftype,outfile);
5607                 fprintf(outfile,")\n");
5608                 ast_print(tree->left,outfile,indent+2);
5609                 ast_print(tree->right,outfile,indent+2);
5610                 return ;
5611
5612                 /*------------------------------------------------------------------*/
5613                 /*----------------------------*/
5614                 /*  division                  */
5615                 /*----------------------------*/
5616         case '/':
5617                 fprintf(outfile,"DIV (%p) type (",tree);
5618                 printTypeChain(tree->ftype,outfile);
5619                 fprintf(outfile,")\n");
5620                 ast_print(tree->left,outfile,indent+2);
5621                 ast_print(tree->right,outfile,indent+2);
5622                 return ;
5623                 /*------------------------------------------------------------------*/
5624                 /*----------------------------*/
5625                 /*            modulus         */
5626                 /*----------------------------*/
5627         case '%':
5628                 fprintf(outfile,"MOD (%p) type (",tree);
5629                 printTypeChain(tree->ftype,outfile);
5630                 fprintf(outfile,")\n");
5631                 ast_print(tree->left,outfile,indent+2);
5632                 ast_print(tree->right,outfile,indent+2);
5633                 return ;
5634
5635                 /*------------------------------------------------------------------*/
5636                 /*----------------------------*/
5637                 /*  address dereference       */
5638                 /*----------------------------*/
5639         case '*':                       /* can be unary  : if right is null then unary operation */
5640                 if (!tree->right) {
5641                         fprintf(outfile,"DEREF (%p) type (",tree);
5642                         printTypeChain(tree->ftype,outfile);
5643                         fprintf(outfile,")\n");
5644                         ast_print(tree->left,outfile,indent+2);
5645                         return ;
5646                 }                       
5647                 /*------------------------------------------------------------------*/
5648                 /*----------------------------*/
5649                 /*      multiplication        */
5650                 /*----------------------------*/                
5651                 fprintf(outfile,"MULT (%p) type (",tree);
5652                 printTypeChain(tree->ftype,outfile);
5653                 fprintf(outfile,")\n");
5654                 ast_print(tree->left,outfile,indent+2);
5655                 ast_print(tree->right,outfile,indent+2);
5656                 return ;
5657
5658
5659                 /*------------------------------------------------------------------*/
5660                 /*----------------------------*/
5661                 /*    unary '+' operator      */
5662                 /*----------------------------*/
5663         case '+':
5664                 /* if unary plus */
5665                 if (!tree->right) {
5666                         fprintf(outfile,"UPLUS (%p) type (",tree);
5667                         printTypeChain(tree->ftype,outfile);
5668                         fprintf(outfile,")\n");
5669                         ast_print(tree->left,outfile,indent+2);
5670                 } else {
5671                         /*------------------------------------------------------------------*/
5672                         /*----------------------------*/
5673                         /*      addition              */
5674                         /*----------------------------*/
5675                         fprintf(outfile,"ADD (%p) type (",tree);
5676                         printTypeChain(tree->ftype,outfile);
5677                         fprintf(outfile,")\n");
5678                         ast_print(tree->left,outfile,indent+2);
5679                         ast_print(tree->right,outfile,indent+2);
5680                 }
5681                 return;
5682                 /*------------------------------------------------------------------*/
5683                 /*----------------------------*/
5684                 /*      unary '-'             */
5685                 /*----------------------------*/
5686         case '-':                       /* can be unary   */
5687                 if (!tree->right) {
5688                         fprintf(outfile,"UMINUS (%p) type (",tree);
5689                         printTypeChain(tree->ftype,outfile);
5690                         fprintf(outfile,")\n");
5691                         ast_print(tree->left,outfile,indent+2);
5692                 } else {
5693                         /*------------------------------------------------------------------*/
5694                         /*----------------------------*/
5695                         /*      subtraction           */
5696                         /*----------------------------*/
5697                         fprintf(outfile,"SUB (%p) type (",tree);
5698                         printTypeChain(tree->ftype,outfile);
5699                         fprintf(outfile,")\n");
5700                         ast_print(tree->left,outfile,indent+2);
5701                         ast_print(tree->right,outfile,indent+2);
5702                 }
5703                 return;
5704                 /*------------------------------------------------------------------*/
5705                 /*----------------------------*/
5706                 /*    compliment              */
5707                 /*----------------------------*/
5708         case '~':
5709                 fprintf(outfile,"COMPL (%p) type (",tree);
5710                 printTypeChain(tree->ftype,outfile);
5711                 fprintf(outfile,")\n");
5712                 ast_print(tree->left,outfile,indent+2);
5713                 return ;
5714                 /*------------------------------------------------------------------*/
5715                 /*----------------------------*/
5716                 /*           not              */
5717                 /*----------------------------*/
5718         case '!':
5719                 fprintf(outfile,"NOT (%p) type (",tree);
5720                 printTypeChain(tree->ftype,outfile);
5721                 fprintf(outfile,")\n");
5722                 ast_print(tree->left,outfile,indent+2);
5723                 return ;
5724                 /*------------------------------------------------------------------*/
5725                 /*----------------------------*/
5726                 /*           shift            */
5727                 /*----------------------------*/
5728         case RRC:
5729                 fprintf(outfile,"RRC (%p) type (",tree);
5730                 printTypeChain(tree->ftype,outfile);
5731                 fprintf(outfile,")\n");
5732                 ast_print(tree->left,outfile,indent+2);
5733                 return ;
5734
5735         case RLC:
5736                 fprintf(outfile,"RLC (%p) type (",tree);
5737                 printTypeChain(tree->ftype,outfile);
5738                 fprintf(outfile,")\n");
5739                 ast_print(tree->left,outfile,indent+2);
5740                 return ;
5741         case SWAP:
5742                 fprintf(outfile,"SWAP (%p) type (",tree);
5743                 printTypeChain(tree->ftype,outfile);
5744                 fprintf(outfile,")\n");
5745                 ast_print(tree->left,outfile,indent+2);
5746                 return ;
5747         case GETHBIT:
5748                 fprintf(outfile,"GETHBIT (%p) type (",tree);
5749                 printTypeChain(tree->ftype,outfile);
5750                 fprintf(outfile,")\n");
5751                 ast_print(tree->left,outfile,indent+2);
5752                 return ;
5753         case LEFT_OP:
5754                 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
5755                 printTypeChain(tree->ftype,outfile);
5756                 fprintf(outfile,")\n");
5757                 ast_print(tree->left,outfile,indent+2);
5758                 ast_print(tree->right,outfile,indent+2);
5759                 return ;
5760         case RIGHT_OP:
5761                 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
5762                 printTypeChain(tree->ftype,outfile);
5763                 fprintf(outfile,")\n");
5764                 ast_print(tree->left,outfile,indent+2);
5765                 ast_print(tree->right,outfile,indent+2);
5766                 return ;
5767                 /*------------------------------------------------------------------*/
5768                 /*----------------------------*/
5769                 /*         casting            */
5770                 /*----------------------------*/
5771         case CAST:                      /* change the type   */
5772                 fprintf(outfile,"CAST (%p) from type (",tree);
5773                 printTypeChain(tree->right->ftype,outfile);
5774                 fprintf(outfile,") to type (");
5775                 printTypeChain(tree->ftype,outfile);
5776                 fprintf(outfile,")\n");
5777                 ast_print(tree->right,outfile,indent+2);
5778                 return ;
5779                 
5780         case AND_OP:
5781                 fprintf(outfile,"ANDAND (%p) type (",tree);
5782                 printTypeChain(tree->ftype,outfile);
5783                 fprintf(outfile,")\n");
5784                 ast_print(tree->left,outfile,indent+2);
5785                 ast_print(tree->right,outfile,indent+2);
5786                 return ;
5787         case OR_OP:
5788                 fprintf(outfile,"OROR (%p) type (",tree);
5789                 printTypeChain(tree->ftype,outfile);
5790                 fprintf(outfile,")\n");
5791                 ast_print(tree->left,outfile,indent+2);
5792                 ast_print(tree->right,outfile,indent+2);
5793                 return ;
5794                 
5795                 /*------------------------------------------------------------------*/
5796                 /*----------------------------*/
5797                 /*     comparison operators   */
5798                 /*----------------------------*/
5799         case '>':
5800                 fprintf(outfile,"GT(>) (%p) type (",tree);
5801                 printTypeChain(tree->ftype,outfile);
5802                 fprintf(outfile,")\n");
5803                 ast_print(tree->left,outfile,indent+2);
5804                 ast_print(tree->right,outfile,indent+2);
5805                 return ;
5806         case '<':
5807                 fprintf(outfile,"LT(<) (%p) type (",tree);
5808                 printTypeChain(tree->ftype,outfile);
5809                 fprintf(outfile,")\n");
5810                 ast_print(tree->left,outfile,indent+2);
5811                 ast_print(tree->right,outfile,indent+2);
5812                 return ;
5813         case LE_OP:
5814                 fprintf(outfile,"LE(<=) (%p) type (",tree);
5815                 printTypeChain(tree->ftype,outfile);
5816                 fprintf(outfile,")\n");
5817                 ast_print(tree->left,outfile,indent+2);
5818                 ast_print(tree->right,outfile,indent+2);
5819                 return ;
5820         case GE_OP:
5821                 fprintf(outfile,"GE(>=) (%p) type (",tree);
5822                 printTypeChain(tree->ftype,outfile);
5823                 fprintf(outfile,")\n");
5824                 ast_print(tree->left,outfile,indent+2);
5825                 ast_print(tree->right,outfile,indent+2);
5826                 return ;
5827         case EQ_OP:
5828                 fprintf(outfile,"EQ(==) (%p) type (",tree);
5829                 printTypeChain(tree->ftype,outfile);
5830                 fprintf(outfile,")\n");
5831                 ast_print(tree->left,outfile,indent+2);
5832                 ast_print(tree->right,outfile,indent+2);
5833                 return ;
5834         case NE_OP:
5835                 fprintf(outfile,"NE(!=) (%p) type (",tree);
5836                 printTypeChain(tree->ftype,outfile);
5837                 fprintf(outfile,")\n");
5838                 ast_print(tree->left,outfile,indent+2);
5839                 ast_print(tree->right,outfile,indent+2);
5840                 /*------------------------------------------------------------------*/
5841                 /*----------------------------*/
5842                 /*             sizeof         */
5843                 /*----------------------------*/
5844         case SIZEOF:            /* evaluate wihout code generation */
5845                 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
5846                 return ;
5847
5848                 /*------------------------------------------------------------------*/
5849                 /*----------------------------*/
5850                 /* conditional operator  '?'  */
5851                 /*----------------------------*/
5852         case '?':
5853                 fprintf(outfile,"QUEST(?) (%p) type (",tree);
5854                 printTypeChain(tree->ftype,outfile);
5855                 fprintf(outfile,")\n");
5856                 ast_print(tree->left,outfile,indent+2);
5857                 ast_print(tree->right,outfile,indent+2);
5858                 return;
5859
5860         case ':':
5861                 fprintf(outfile,"COLON(:) (%p) type (",tree);
5862                 printTypeChain(tree->ftype,outfile);
5863                 fprintf(outfile,")\n");
5864                 ast_print(tree->left,outfile,indent+2);
5865                 ast_print(tree->right,outfile,indent+2);
5866                 return ;
5867
5868                 /*------------------------------------------------------------------*/
5869                 /*----------------------------*/
5870                 /*    assignment operators    */
5871                 /*----------------------------*/
5872         case MUL_ASSIGN:
5873                 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
5874                 printTypeChain(tree->ftype,outfile);
5875                 fprintf(outfile,")\n");
5876                 ast_print(tree->left,outfile,indent+2);
5877                 ast_print(tree->right,outfile,indent+2);
5878                 return;
5879         case DIV_ASSIGN:
5880                 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
5881                 printTypeChain(tree->ftype,outfile);
5882                 fprintf(outfile,")\n");
5883                 ast_print(tree->left,outfile,indent+2);
5884                 ast_print(tree->right,outfile,indent+2);
5885                 return;
5886         case AND_ASSIGN:
5887                 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
5888                 printTypeChain(tree->ftype,outfile);
5889                 fprintf(outfile,")\n");
5890                 ast_print(tree->left,outfile,indent+2);
5891                 ast_print(tree->right,outfile,indent+2);
5892                 return;
5893         case OR_ASSIGN:
5894                 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
5895                 printTypeChain(tree->ftype,outfile);
5896                 fprintf(outfile,")\n");
5897                 ast_print(tree->left,outfile,indent+2);
5898                 ast_print(tree->right,outfile,indent+2);
5899                 return;
5900         case XOR_ASSIGN:
5901                 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
5902                 printTypeChain(tree->ftype,outfile);
5903                 fprintf(outfile,")\n");
5904                 ast_print(tree->left,outfile,indent+2);
5905                 ast_print(tree->right,outfile,indent+2);
5906                 return;
5907         case RIGHT_ASSIGN:
5908                 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
5909                 printTypeChain(tree->ftype,outfile);
5910                 fprintf(outfile,")\n");
5911                 ast_print(tree->left,outfile,indent+2);
5912                 ast_print(tree->right,outfile,indent+2);
5913                 return;
5914         case LEFT_ASSIGN:
5915                 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
5916                 printTypeChain(tree->ftype,outfile);
5917                 fprintf(outfile,")\n");
5918                 ast_print(tree->left,outfile,indent+2);
5919                 ast_print(tree->right,outfile,indent+2);
5920                 return;
5921                 /*------------------------------------------------------------------*/
5922                 /*----------------------------*/
5923                 /*    -= operator             */
5924                 /*----------------------------*/
5925         case SUB_ASSIGN:
5926                 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
5927                 printTypeChain(tree->ftype,outfile);
5928                 fprintf(outfile,")\n");
5929                 ast_print(tree->left,outfile,indent+2);
5930                 ast_print(tree->right,outfile,indent+2);
5931                 return;
5932                 /*------------------------------------------------------------------*/
5933                 /*----------------------------*/
5934                 /*          += operator       */
5935                 /*----------------------------*/
5936         case ADD_ASSIGN:
5937                 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
5938                 printTypeChain(tree->ftype,outfile);
5939                 fprintf(outfile,")\n");
5940                 ast_print(tree->left,outfile,indent+2);
5941                 ast_print(tree->right,outfile,indent+2);
5942                 return;
5943                 /*------------------------------------------------------------------*/
5944                 /*----------------------------*/
5945                 /*      straight assignemnt   */
5946                 /*----------------------------*/
5947         case '=':
5948                 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
5949                 printTypeChain(tree->ftype,outfile);
5950                 fprintf(outfile,")\n");
5951                 ast_print(tree->left,outfile,indent+2);
5952                 ast_print(tree->right,outfile,indent+2);
5953                 return;     
5954                 /*------------------------------------------------------------------*/
5955                 /*----------------------------*/
5956                 /*      comma operator        */
5957                 /*----------------------------*/
5958         case ',':
5959                 fprintf(outfile,"COMMA(,) (%p) type (",tree);
5960                 printTypeChain(tree->ftype,outfile);
5961                 fprintf(outfile,")\n");
5962                 ast_print(tree->left,outfile,indent+2);
5963                 ast_print(tree->right,outfile,indent+2);
5964                 return;
5965                 /*------------------------------------------------------------------*/
5966                 /*----------------------------*/
5967                 /*       function call        */
5968                 /*----------------------------*/
5969         case CALL:
5970         case PCALL:
5971                 fprintf(outfile,"CALL (%p) type (",tree);
5972                 printTypeChain(tree->ftype,outfile);
5973                 fprintf(outfile,")\n");
5974                 ast_print(tree->left,outfile,indent+2);
5975                 ast_print(tree->right,outfile,indent+2);
5976                 return;
5977         case PARAM:
5978                 fprintf(outfile,"PARMS\n");
5979                 ast_print(tree->left,outfile,indent+2);
5980                 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
5981                         ast_print(tree->right,outfile,indent+2);
5982                 }
5983                 return ;
5984                 /*------------------------------------------------------------------*/
5985                 /*----------------------------*/
5986                 /*     return statement       */
5987                 /*----------------------------*/
5988         case RETURN:
5989                 fprintf(outfile,"RETURN (%p) type (",tree);
5990                 if (tree->right) {
5991                     printTypeChain(tree->right->ftype,outfile);
5992                 }
5993                 fprintf(outfile,")\n");
5994                 ast_print(tree->right,outfile,indent+2);
5995                 return ;
5996                 /*------------------------------------------------------------------*/
5997                 /*----------------------------*/
5998                 /*     label statement        */
5999                 /*----------------------------*/
6000         case LABEL :
6001                 fprintf(outfile,"LABEL (%p)\n",tree);
6002                 ast_print(tree->left,outfile,indent+2);
6003                 ast_print(tree->right,outfile,indent);
6004                 return;
6005                 /*------------------------------------------------------------------*/
6006                 /*----------------------------*/
6007                 /*     switch statement       */
6008                 /*----------------------------*/
6009         case SWITCH:
6010                 {
6011                         value *val;
6012                         fprintf(outfile,"SWITCH (%p) ",tree);
6013                         ast_print(tree->left,outfile,0);
6014                         for (val = tree->values.switchVals.swVals; val ; val = val->next) {
6015                                 INDENT(indent+2,outfile);
6016                                 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
6017                                         (int) floatFromVal(val),
6018                                         tree->values.switchVals.swNum,
6019                                         (int) floatFromVal(val));
6020                         }
6021                         ast_print(tree->right,outfile,indent);
6022                 }
6023                 return ;
6024                 /*------------------------------------------------------------------*/
6025                 /*----------------------------*/
6026                 /* ifx Statement              */
6027                 /*----------------------------*/
6028         case IFX:
6029                 fprintf(outfile,"IF (%p) \n",tree);
6030                 ast_print(tree->left,outfile,indent+2);
6031                 if (tree->trueLabel) {
6032                         INDENT(indent+2,outfile);
6033                         fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
6034                 }
6035                 if (tree->falseLabel) {
6036                         INDENT(indent+2,outfile);
6037                         fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
6038                 }
6039                 ast_print(tree->right,outfile,indent+2);
6040                 return ;
6041                 /*----------------------------*/
6042                 /* goto Statement              */
6043                 /*----------------------------*/
6044         case GOTO:
6045                 fprintf(outfile,"GOTO (%p) \n",tree);
6046                 ast_print(tree->left,outfile,indent+2);
6047                 fprintf(outfile,"\n");
6048                 return ;
6049                 /*------------------------------------------------------------------*/
6050                 /*----------------------------*/
6051                 /* for Statement              */
6052                 /*----------------------------*/
6053         case FOR:
6054                 fprintf(outfile,"FOR (%p) \n",tree);
6055                 if (AST_FOR( tree, initExpr)) {
6056                         INDENT(indent+2,outfile);
6057                         fprintf(outfile,"INIT EXPR ");
6058                         ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
6059                 }
6060                 if (AST_FOR( tree, condExpr)) {
6061                         INDENT(indent+2,outfile);
6062                         fprintf(outfile,"COND EXPR ");
6063                         ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
6064                 }
6065                 if (AST_FOR( tree, loopExpr)) {
6066                         INDENT(indent+2,outfile);
6067                         fprintf(outfile,"LOOP EXPR ");
6068                         ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
6069                 }
6070                 fprintf(outfile,"FOR LOOP BODY \n");
6071                 ast_print(tree->left,outfile,indent+2);
6072                 return ;
6073         case CRITICAL:
6074                 fprintf(outfile,"CRITICAL (%p) \n",tree);
6075                 ast_print(tree->left,outfile,indent+2);
6076         default:
6077             return ;
6078         }
6079 }
6080
6081 void PA(ast *t)
6082 {
6083         ast_print(t,stdout,0);
6084 }
6085
6086
6087
6088 /*-----------------------------------------------------------------*/
6089 /* astErrors : returns non-zero if errors present in tree          */
6090 /*-----------------------------------------------------------------*/
6091 int astErrors(ast *t)
6092 {
6093   int errors=0;
6094   
6095   if (t)
6096     {
6097       if (t->isError)
6098         errors++;
6099   
6100       if (t->type == EX_VALUE
6101           && t->opval.val->sym
6102           && t->opval.val->sym->undefined)
6103         errors++;
6104
6105       errors += astErrors(t->left);
6106       errors += astErrors(t->right);
6107     }
6108     
6109   return errors;
6110 }