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