* device/lib/time.c (mktime): fixed bug reported by Bert Thomas
[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_BIT (type))
2023     return RESULT_TYPE_BIT;
2024   if (IS_BITFIELD (type))
2025     {
2026       int blen = SPEC_BLEN (type);
2027       
2028       if (blen <= 1)
2029         return RESULT_TYPE_BIT;
2030       if (blen <= 8)
2031         return RESULT_TYPE_CHAR;
2032       return RESULT_TYPE_INT;
2033     }
2034   if (IS_CHAR (type))
2035     return RESULT_TYPE_CHAR;
2036   if (   IS_INT (type)
2037       && !IS_LONG (type))
2038     return RESULT_TYPE_INT;
2039   return RESULT_TYPE_OTHER;
2040 }
2041
2042 /*-----------------------------------------------------------------*/
2043 /* addCast - adds casts to a type specified by RESULT_TYPE         */
2044 /*-----------------------------------------------------------------*/
2045 static ast *
2046 addCast (ast *tree, RESULT_TYPE resultType, bool upcast)
2047 {
2048   sym_link *newLink;
2049   bool upCasted = FALSE;
2050   
2051   switch (resultType)
2052     {
2053       case RESULT_TYPE_NONE:
2054         /* char: promote to int */
2055         if (!upcast ||
2056             getSize (tree->etype) >= INTSIZE)
2057           return tree;
2058         newLink = newIntLink();
2059         upCasted = TRUE;
2060         break;
2061       case RESULT_TYPE_CHAR:
2062         if (IS_CHAR (tree->etype))
2063           return tree;
2064         newLink = newCharLink();
2065         break;
2066       case RESULT_TYPE_INT:
2067 #if 0
2068         if (getSize (tree->etype) > INTSIZE)
2069           {
2070             /* warn ("Loosing significant digits"); */
2071             return;
2072           }
2073 #endif
2074         /* char: promote to int */
2075         if (!upcast ||
2076             getSize (tree->etype) >= INTSIZE)
2077           return tree;
2078         newLink = newIntLink();
2079         upCasted = TRUE;
2080         break;
2081       case RESULT_TYPE_OTHER:
2082         if (!upcast)
2083           return tree;
2084         /* return type is long, float: promote char to int */
2085         if (getSize (tree->etype) >= INTSIZE)
2086           return tree;
2087         newLink = newIntLink();
2088         upCasted = TRUE;
2089         break;
2090       default:
2091         return tree;
2092     }
2093   tree->decorated = 0;
2094   tree = newNode (CAST, newAst_LINK (newLink), tree);
2095   tree->lineno = tree->right->lineno;
2096   /* keep unsigned type during cast to smaller type,
2097      but not when promoting from char to int */
2098   if (!upCasted)
2099     SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2100   return decorateType (tree, resultType);
2101 }
2102
2103 /*-----------------------------------------------------------------*/
2104 /* resultTypePropagate - decides if resultType can be propagated   */
2105 /*-----------------------------------------------------------------*/
2106 static RESULT_TYPE
2107 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2108 {
2109   switch (tree->opval.op)
2110     {
2111       case '=':
2112       case '?':
2113       case ':':
2114       case '|':
2115       case '^':
2116       case '*':
2117       case '+':
2118       case '-':
2119       case LABEL:
2120         return resultType;
2121       case '&':
2122         if (!tree->right)
2123           /* can be unary */
2124           return RESULT_TYPE_NONE;
2125         else
2126           return resultType;
2127       case IFX:
2128         return RESULT_TYPE_IFX;
2129       default:
2130         return RESULT_TYPE_NONE;
2131     }
2132 }
2133
2134 /*-----------------------------------------------------------------*/
2135 /* getLeftResultType - gets type from left branch for propagation  */
2136 /*-----------------------------------------------------------------*/
2137 static RESULT_TYPE
2138 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2139 {
2140   switch (tree->opval.op)
2141     {
2142       case '=':
2143       case CAST:
2144         if (IS_PTR (LTYPE (tree)))
2145           return RESULT_TYPE_NONE;
2146         else
2147           return getResultTypeFromType (LETYPE (tree));
2148       case RETURN:
2149         if (IS_PTR (currFunc->type->next))
2150           return RESULT_TYPE_NONE;
2151         else
2152           return getResultTypeFromType (currFunc->type->next);
2153       case '[':
2154         if (!IS_ARRAY (LTYPE (tree)))
2155           return resultType;
2156         if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 256)
2157           return RESULT_TYPE_CHAR;
2158         return resultType;
2159       default:
2160         return resultType;
2161     }
2162 }
2163
2164 /*--------------------------------------------------------------------*/
2165 /* decorateType - compute type for this tree, also does type checking.*/
2166 /* This is done bottom up, since type has to flow upwards.            */
2167 /* resultType flows top-down and forces e.g. char-arithmetik, if the  */
2168 /* result is a char and the operand(s) are int's.                     */
2169 /* It also does constant folding, and parameter checking.             */
2170 /*--------------------------------------------------------------------*/
2171 ast *
2172 decorateType (ast * tree, RESULT_TYPE resultType)
2173 {
2174   int parmNumber;
2175   sym_link *p;
2176   RESULT_TYPE resultTypeProp;
2177
2178   if (!tree)
2179     return tree;
2180
2181   /* if already has type then do nothing */
2182   if (tree->decorated)
2183     return tree;
2184
2185   tree->decorated = 1;
2186
2187 #if 0
2188   /* print the line          */
2189   /* if not block & function */
2190   if (tree->type == EX_OP &&
2191       (tree->opval.op != FUNCTION &&
2192        tree->opval.op != BLOCK &&
2193        tree->opval.op != NULLOP))
2194     {
2195       filename = tree->filename;
2196       lineno = tree->lineno;
2197     }
2198 #endif
2199
2200   /* if any child is an error | this one is an error do nothing */
2201   if (tree->isError ||
2202       (tree->left && tree->left->isError) ||
2203       (tree->right && tree->right->isError))
2204     return tree;
2205
2206 /*------------------------------------------------------------------*/
2207 /*----------------------------*/
2208 /*   leaf has been reached    */
2209 /*----------------------------*/
2210   lineno=tree->lineno;
2211   /* if this is of type value */
2212   /* just get the type        */
2213   if (tree->type == EX_VALUE)
2214     {
2215
2216       if (IS_LITERAL (tree->opval.val->etype))
2217         {
2218
2219           /* if this is a character array then declare it */
2220           if (IS_ARRAY (tree->opval.val->type))
2221             tree->opval.val = stringToSymbol (tree->opval.val);
2222
2223           /* otherwise just copy the type information */
2224           COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2225           return tree;
2226         }
2227
2228       if (tree->opval.val->sym)
2229         {
2230           /* if the undefined flag is set then give error message */
2231           if (tree->opval.val->sym->undefined)
2232             {
2233               werror (E_ID_UNDEF, tree->opval.val->sym->name);
2234               /* assume int */
2235               TTYPE (tree) = TETYPE (tree) =
2236                 tree->opval.val->type = tree->opval.val->sym->type =
2237                 tree->opval.val->etype = tree->opval.val->sym->etype =
2238                 copyLinkChain (INTTYPE);
2239             }
2240           else
2241             {
2242
2243               /* if impilicit i.e. struct/union member then no type */
2244               if (tree->opval.val->sym->implicit)
2245                 TTYPE (tree) = TETYPE (tree) = NULL;
2246
2247               else
2248                 {
2249
2250                   /* else copy the type */
2251                   COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2252
2253                   /* and mark it as referenced */
2254                   tree->opval.val->sym->isref = 1;
2255                 }
2256             }
2257         }
2258
2259       return tree;
2260     }
2261
2262   /* if type link for the case of cast */
2263   if (tree->type == EX_LINK)
2264     {
2265       COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2266       return tree;
2267     }
2268
2269   {
2270     ast *dtl, *dtr;
2271
2272     #if 0
2273     if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2274       {
2275         if (tree->left && tree->left->type == EX_OPERAND
2276             && (tree->left->opval.op == INC_OP
2277                 || tree->left->opval.op == DEC_OP)
2278             && tree->left->left)
2279           {
2280             tree->left->right = tree->left->left;
2281             tree->left->left = NULL;
2282           }
2283         if (tree->right && tree->right->type == EX_OPERAND
2284             && (tree->right->opval.op == INC_OP
2285                 || tree->right->opval.op == DEC_OP)
2286             && tree->right->left)
2287           {
2288             tree->right->right = tree->right->left;
2289             tree->right->left = NULL;
2290           }
2291       }
2292     #endif
2293
2294     /* Before decorating the left branch we've to decide in dependence
2295        upon tree->opval.op, if resultType can be propagated */
2296     resultTypeProp = resultTypePropagate (tree, resultType);
2297
2298     if (tree->opval.op == '?')
2299       dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2300     else
2301       dtl = decorateType (tree->left, resultTypeProp);
2302
2303     /* if an array node, we may need to swap branches */
2304     if (tree->opval.op == '[')
2305       {
2306         /* determine which is the array & which the index */
2307         if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2308             IS_INTEGRAL (LTYPE (tree)))
2309           {
2310             ast *tempTree = tree->left;
2311             tree->left = tree->right;
2312             tree->right = tempTree;
2313           }
2314       }
2315
2316     /* After decorating the left branch there's type information available
2317        in tree->left->?type. If the op is e.g. '=' we extract the type
2318        information from there and propagate it to the right branch. */
2319     resultTypeProp = getLeftResultType (tree, resultTypeProp);
2320     
2321     switch (tree->opval.op)
2322       {
2323         case '?':
2324           /* delay right side for '?' operator since conditional macro
2325              expansions might rely on this */
2326           dtr = tree->right;
2327           break;
2328         case CALL: 
2329           /* decorate right side for CALL (parameter list) in processParms();
2330              there is resultType available */
2331           dtr = tree->right;
2332           break;
2333         default:     
2334           dtr = decorateType (tree->right, resultTypeProp);
2335           break;
2336       }
2337
2338     /* this is to take care of situations
2339        when the tree gets rewritten */
2340     if (dtl != tree->left)
2341       tree->left = dtl;
2342     if (dtr != tree->right)
2343       tree->right = dtr;
2344     if ((dtl && dtl->isError) || (dtr && dtr->isError))
2345       return tree;
2346   }
2347
2348   /* depending on type of operator do */
2349
2350   switch (tree->opval.op)
2351     {
2352         /*------------------------------------------------------------------*/
2353         /*----------------------------*/
2354         /*        array node          */
2355         /*----------------------------*/
2356     case '[':
2357
2358       /* first check if this is a array or a pointer */
2359       if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2360         {
2361           werror (E_NEED_ARRAY_PTR, "[]");
2362           goto errorTreeReturn;
2363         }
2364
2365       /* check if the type of the idx */
2366       if (!IS_INTEGRAL (RTYPE (tree)))
2367         {
2368           werror (E_IDX_NOT_INT);
2369           goto errorTreeReturn;
2370         }
2371
2372       /* if the left is an rvalue then error */
2373       if (LRVAL (tree))
2374         {
2375           werror (E_LVALUE_REQUIRED, "array access");
2376           goto errorTreeReturn;
2377         }
2378
2379       if (IS_LITERAL (RTYPE (tree)))
2380         {
2381           int arrayIndex = (int) floatFromVal (valFromType (RETYPE (tree)));
2382           int arraySize = DCL_ELEM (LTYPE (tree));
2383           if (arraySize && arrayIndex >= arraySize)
2384             {
2385               werror (W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2386             }
2387         }
2388
2389       RRVAL (tree) = 1;
2390       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2391       return tree;
2392
2393       /*------------------------------------------------------------------*/
2394       /*----------------------------*/
2395       /*      struct/union          */
2396       /*----------------------------*/
2397     case '.':
2398       /* if this is not a structure */
2399       if (!IS_STRUCT (LTYPE (tree)))
2400         {
2401           werror (E_STRUCT_UNION, ".");
2402           goto errorTreeReturn;
2403         }
2404       TTYPE (tree) = structElemType (LTYPE (tree),
2405                                      (tree->right->type == EX_VALUE ?
2406                                tree->right->opval.val : NULL));
2407       TETYPE (tree) = getSpec (TTYPE (tree));
2408       return tree;
2409
2410       /*------------------------------------------------------------------*/
2411       /*----------------------------*/
2412       /*    struct/union pointer    */
2413       /*----------------------------*/
2414     case PTR_OP:
2415       /* if not pointer to a structure */
2416       if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2417         {
2418           werror (E_PTR_REQD);
2419           goto errorTreeReturn;
2420         }
2421
2422       if (!IS_STRUCT (LTYPE (tree)->next))
2423         {
2424           werror (E_STRUCT_UNION, "->");
2425           goto errorTreeReturn;
2426         }
2427
2428       TTYPE (tree) = structElemType (LTYPE (tree)->next,
2429                                      (tree->right->type == EX_VALUE ?
2430                                tree->right->opval.val : NULL));
2431       TETYPE (tree) = getSpec (TTYPE (tree));
2432
2433       /* adjust the storage class */
2434       switch (DCL_TYPE(tree->left->ftype)) {
2435       case POINTER:
2436         SPEC_SCLS(TETYPE(tree)) = S_DATA; 
2437         break;
2438       case FPOINTER:
2439         SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
2440         break;
2441       case CPOINTER:
2442         SPEC_SCLS(TETYPE(tree)) = S_CODE; 
2443         break;
2444       case GPOINTER:
2445         SPEC_SCLS (TETYPE (tree)) = 0;
2446         break;
2447       case PPOINTER:
2448         SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
2449         break;
2450       case IPOINTER:
2451         SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2452         break;
2453       case EEPPOINTER:
2454         SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2455         break;
2456       case UPOINTER:
2457         SPEC_SCLS (TETYPE (tree)) = 0;
2458         break;
2459       case ARRAY:
2460       case FUNCTION:
2461         break;
2462       }
2463       
2464       /* This breaks with extern declarations, bitfields, and perhaps other */
2465       /* cases (gcse). Let's leave this optimization disabled for now and   */
2466       /* ponder if there's a safe way to do this. -- EEP                    */
2467       #if 0
2468       if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2469           && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2470         {
2471             /* If defined    struct type at addr var
2472                then rewrite  (&struct var)->member
2473                as            temp
2474                and define    membertype at (addr+offsetof(struct var,member)) temp
2475             */
2476             symbol *sym;
2477             symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2478                                                 AST_SYMBOL(tree->right));
2479
2480             sym = newSymbol(genSymName (0), 0);
2481             sym->type = TTYPE (tree);
2482             sym->etype = getSpec(sym->type);
2483             sym->lineDef = tree->lineno;
2484             sym->cdef = 1;
2485             sym->isref = 1;
2486             SPEC_STAT (sym->etype) = 1;
2487             SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2488                                      + element->offset;
2489             SPEC_ABSA(sym->etype) = 1;
2490             addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2491             allocGlobal (sym);
2492             
2493             AST_VALUE (tree) = symbolVal(sym);
2494             TLVAL (tree) = 1;
2495             TRVAL (tree) = 0;
2496             tree->type = EX_VALUE;
2497             tree->left = NULL;
2498             tree->right = NULL;
2499         }
2500       #endif
2501       
2502       return tree;
2503
2504       /*------------------------------------------------------------------*/
2505       /*----------------------------*/
2506       /*  ++/-- operation           */
2507       /*----------------------------*/
2508     case INC_OP:
2509     case DEC_OP:
2510       {
2511         sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2512         COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2513         if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2514           werror (E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2515
2516         if (tree->right)
2517           RLVAL (tree) = 1;
2518         else
2519           LLVAL (tree) = 1;
2520         return tree;
2521       }
2522
2523       /*------------------------------------------------------------------*/
2524       /*----------------------------*/
2525       /*  bitwise and               */
2526       /*----------------------------*/
2527     case '&':                   /* can be unary   */
2528       /* if right is NULL then unary operation  */
2529       if (tree->right)          /* not an unary operation */
2530         {
2531
2532           if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2533             {
2534               werror (E_BITWISE_OP);
2535               werror (W_CONTINUE, "left & right types are ");
2536               printTypeChain (LTYPE (tree), stderr);
2537               fprintf (stderr, ",");
2538               printTypeChain (RTYPE (tree), stderr);
2539               fprintf (stderr, "\n");
2540               goto errorTreeReturn;
2541             }
2542
2543           /* if they are both literal */
2544           if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2545             {
2546               tree->type = EX_VALUE;
2547               tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2548                                           valFromType (RETYPE (tree)), '&');
2549
2550               tree->right = tree->left = NULL;
2551               TETYPE (tree) = tree->opval.val->etype;
2552               TTYPE (tree) = tree->opval.val->type;
2553               return tree;
2554             }
2555
2556           /* see if this is a GETHBIT operation if yes
2557              then return that */
2558           {
2559             ast *otree = optimizeGetHbit (tree);
2560
2561             if (otree != tree)
2562               return decorateType (otree, RESULT_CHECK);
2563           }
2564
2565           TTYPE (tree) = computeType (LTYPE (tree),
2566                                       RTYPE (tree),
2567                                       resultType,
2568                                       tree->opval.op);
2569           TETYPE (tree) = getSpec (TTYPE (tree));
2570
2571           /* if left is a literal exchange left & right */
2572           if (IS_LITERAL (LTYPE (tree)))
2573             {
2574               ast *tTree = tree->left;
2575               tree->left = tree->right;
2576               tree->right = tTree;
2577             }
2578
2579           /* if right is a literal and */
2580           /* we can find a 2nd literal in a and-tree then */
2581           /* rearrange the tree */
2582           if (IS_LITERAL (RTYPE (tree)))
2583             {
2584               ast *parent;
2585               ast *litTree = searchLitOp (tree, &parent, "&");
2586               if (litTree)
2587                 {
2588                   ast *tTree = litTree->left;
2589                   litTree->left = tree->right;
2590                   tree->right = tTree;
2591                   /* both operands in tTree are literal now */
2592                   decorateType (parent, RESULT_CHECK);
2593                 }
2594             }
2595
2596           LRVAL (tree) = RRVAL (tree) = 1;
2597           
2598           return tree;
2599         }
2600
2601       /*------------------------------------------------------------------*/
2602       /*----------------------------*/
2603       /*  address of                */
2604       /*----------------------------*/
2605       p = newLink (DECLARATOR);
2606       /* if bit field then error */
2607       if (IS_BITVAR (tree->left->etype))
2608         {
2609           werror (E_ILLEGAL_ADDR, "address of bit variable");
2610           goto errorTreeReturn;
2611         }
2612
2613       if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2614         {
2615           werror (E_ILLEGAL_ADDR, "address of register variable");
2616           goto errorTreeReturn;
2617         }
2618
2619       if (IS_FUNC (LTYPE (tree)))
2620         {
2621           // this ought to be ignored
2622           return (tree->left);
2623         }
2624
2625       if (IS_LITERAL(LTYPE(tree)))
2626         {
2627           werror (E_ILLEGAL_ADDR, "address of literal");
2628           goto errorTreeReturn;
2629         }
2630
2631      if (LRVAL (tree))
2632         {
2633           werror (E_LVALUE_REQUIRED, "address of");
2634           goto errorTreeReturn;
2635         }
2636       if (!LETYPE (tree))
2637         DCL_TYPE (p) = POINTER;
2638       else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2639         DCL_TYPE (p) = CPOINTER;
2640       else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2641         DCL_TYPE (p) = FPOINTER;
2642       else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2643         DCL_TYPE (p) = PPOINTER;
2644       else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2645         DCL_TYPE (p) = IPOINTER;
2646       else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2647         DCL_TYPE (p) = EEPPOINTER;
2648       else if (SPEC_OCLS(tree->left->etype))
2649           DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2650       else
2651           DCL_TYPE (p) = POINTER;
2652
2653       if (IS_AST_SYM_VALUE (tree->left))
2654         {
2655           AST_SYMBOL (tree->left)->addrtaken = 1;
2656           AST_SYMBOL (tree->left)->allocreq = 1;
2657         }
2658
2659       p->next = LTYPE (tree);
2660       TTYPE (tree) = p;
2661       TETYPE (tree) = getSpec (TTYPE (tree));
2662       LLVAL (tree) = 1;
2663       TLVAL (tree) = 1;
2664
2665       #if 0
2666       if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2667           && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2668         {
2669           symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2670                                       AST_SYMBOL(tree->left->right));
2671           AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2672                                     valueFromLit(element->offset));
2673           tree->left = NULL;
2674           tree->right = NULL;
2675           tree->type = EX_VALUE;
2676           tree->values.literalFromCast = 1;
2677         }
2678       #endif
2679
2680       return tree;
2681
2682       /*------------------------------------------------------------------*/
2683       /*----------------------------*/
2684       /*  bitwise or                */
2685       /*----------------------------*/
2686     case '|':
2687       /* if the rewrite succeeds then don't go any furthur */
2688       {
2689         ast *wtree = optimizeRRCRLC (tree);
2690         if (wtree != tree)
2691           return decorateType (wtree, RESULT_CHECK);
2692         
2693         wtree = optimizeSWAP (tree);
2694         if (wtree != tree)
2695           return decorateType (wtree, RESULT_CHECK);
2696       }
2697
2698       /* if left is a literal exchange left & right */
2699       if (IS_LITERAL (LTYPE (tree)))
2700         {
2701           ast *tTree = tree->left;
2702           tree->left = tree->right;
2703           tree->right = tTree;
2704         }
2705
2706       /* if right is a literal and */
2707       /* we can find a 2nd literal in a or-tree then */
2708       /* rearrange the tree */
2709       if (IS_LITERAL (RTYPE (tree)))
2710         {
2711           ast *parent;
2712           ast *litTree = searchLitOp (tree, &parent, "|");
2713           if (litTree)
2714             {
2715               ast *tTree = litTree->left;
2716               litTree->left = tree->right;
2717               tree->right = tTree;
2718               /* both operands in tTree are literal now */
2719               decorateType (parent, RESULT_CHECK);
2720             }
2721         }
2722       /* fall through */
2723
2724       /*------------------------------------------------------------------*/
2725       /*----------------------------*/
2726       /*  bitwise xor               */
2727       /*----------------------------*/
2728     case '^':
2729       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2730         {
2731           werror (E_BITWISE_OP);
2732           werror (W_CONTINUE, "left & right types are ");
2733           printTypeChain (LTYPE (tree), stderr);
2734           fprintf (stderr, ",");
2735           printTypeChain (RTYPE (tree), stderr);
2736           fprintf (stderr, "\n");
2737           goto errorTreeReturn;
2738         }
2739
2740       /* if they are both literal then */
2741       /* rewrite the tree */
2742       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2743         {
2744           tree->type = EX_VALUE;
2745           tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2746                                         valFromType (RETYPE (tree)),
2747                                         tree->opval.op);
2748           tree->right = tree->left = NULL;
2749           TETYPE (tree) = tree->opval.val->etype;
2750           TTYPE (tree) = tree->opval.val->type;
2751           return tree;
2752         }
2753
2754       /* if left is a literal exchange left & right */
2755       if (IS_LITERAL (LTYPE (tree)))
2756         {
2757           ast *tTree = tree->left;
2758           tree->left = tree->right;
2759           tree->right = tTree;
2760         }
2761
2762       /* if right is a literal and */
2763       /* we can find a 2nd literal in a xor-tree then */
2764       /* rearrange the tree */
2765       if (IS_LITERAL (RTYPE (tree)) &&
2766           tree->opval.op == '^') /* the same source is used by 'bitwise or' */
2767         {
2768           ast *parent;
2769           ast *litTree = searchLitOp (tree, &parent, "^");
2770           if (litTree)
2771             {
2772               ast *tTree = litTree->left;
2773               litTree->left = tree->right;
2774               tree->right = tTree;
2775               /* both operands in litTree are literal now */
2776               decorateType (parent, RESULT_CHECK);
2777             }
2778         }
2779
2780       LRVAL (tree) = RRVAL (tree) = 1;
2781       TETYPE (tree) = getSpec (TTYPE (tree) =
2782                                computeType (LTYPE (tree),
2783                                             RTYPE (tree),
2784                                             resultType,
2785                                             tree->opval.op));
2786
2787       return tree;
2788
2789       /*------------------------------------------------------------------*/
2790       /*----------------------------*/
2791       /*  division                  */
2792       /*----------------------------*/
2793     case '/':
2794       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
2795         {
2796           werror (E_INVALID_OP, "divide");
2797           goto errorTreeReturn;
2798         }
2799       /* if they are both literal then */
2800       /* rewrite the tree */
2801       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2802         {
2803           tree->type = EX_VALUE;
2804           tree->opval.val = valDiv (valFromType (LETYPE (tree)),
2805                                     valFromType (RETYPE (tree)));
2806           tree->right = tree->left = NULL;
2807           TETYPE (tree) = getSpec (TTYPE (tree) =
2808                                    tree->opval.val->type);
2809           return tree;
2810         }
2811
2812       LRVAL (tree) = RRVAL (tree) = 1;
2813
2814       TETYPE (tree) = getSpec (TTYPE (tree) =
2815                                computeType (LTYPE (tree),
2816                                             RTYPE (tree),
2817                                             resultType,
2818                                             tree->opval.op));
2819
2820       /* if right is a literal and */
2821       /* left is also a division by a literal then */
2822       /* rearrange the tree */
2823       if (IS_LITERAL (RTYPE (tree))
2824           /* avoid infinite loop */
2825           && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 1)
2826         {
2827           ast *parent;
2828           ast *litTree = searchLitOp (tree, &parent, "/");
2829           if (litTree)
2830             {
2831               if (IS_LITERAL (RTYPE (litTree)))
2832                 {
2833                   /* foo_div */
2834                   litTree->right = newNode ('*', litTree->right, tree->right);
2835                   litTree->right->lineno = tree->lineno;
2836
2837                   tree->right->opval.val = constVal ("1");
2838                   decorateType (parent, RESULT_CHECK);
2839                 }
2840               else
2841                 {
2842                   /* litTree->left is literal: no gcse possible.
2843                      We can't call decorateType(parent, RESULT_CHECK), because
2844                      this would cause an infinit loop. */
2845                   parent->decorated = 1;
2846                   decorateType (litTree, RESULT_CHECK);
2847                 }
2848             }
2849         }
2850
2851       return tree;
2852
2853       /*------------------------------------------------------------------*/
2854       /*----------------------------*/
2855       /*            modulus         */
2856       /*----------------------------*/
2857     case '%':
2858       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2859         {
2860           werror (E_BITWISE_OP);
2861           werror (W_CONTINUE, "left & right types are ");
2862           printTypeChain (LTYPE (tree), stderr);
2863           fprintf (stderr, ",");
2864           printTypeChain (RTYPE (tree), stderr);
2865           fprintf (stderr, "\n");
2866           goto errorTreeReturn;
2867         }
2868       /* if they are both literal then */
2869       /* rewrite the tree */
2870       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2871         {
2872           tree->type = EX_VALUE;
2873           tree->opval.val = valMod (valFromType (LETYPE (tree)),
2874                                     valFromType (RETYPE (tree)));
2875           tree->right = tree->left = NULL;
2876           TETYPE (tree) = getSpec (TTYPE (tree) =
2877                                    tree->opval.val->type);
2878           return tree;
2879         }
2880       LRVAL (tree) = RRVAL (tree) = 1;
2881       TETYPE (tree) = getSpec (TTYPE (tree) =
2882                                computeType (LTYPE (tree),
2883                                             RTYPE (tree),
2884                                             resultType,
2885                                             tree->opval.op));
2886       return tree;
2887
2888       /*------------------------------------------------------------------*/
2889       /*----------------------------*/
2890       /*  address dereference       */
2891       /*----------------------------*/
2892     case '*':                   /* can be unary  : if right is null then unary operation */
2893       if (!tree->right)
2894         {
2895           if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
2896             {
2897               werror (E_PTR_REQD);
2898               goto errorTreeReturn;
2899             }
2900
2901           if (LRVAL (tree))
2902             {
2903               werror (E_LVALUE_REQUIRED, "pointer deref");
2904               goto errorTreeReturn;
2905             }
2906           if (IS_ADDRESS_OF_OP(tree->left))
2907             {
2908               /* replace *&obj with obj */
2909               return tree->left->left;
2910             }
2911           TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
2912           TETYPE (tree) = getSpec (TTYPE (tree));
2913           /* adjust the storage class */
2914           switch (DCL_TYPE(tree->left->ftype)) {
2915             case POINTER:
2916               SPEC_SCLS(TETYPE(tree)) = S_DATA;
2917               break;
2918             case FPOINTER:
2919               SPEC_SCLS(TETYPE(tree)) = S_XDATA; 
2920               break;
2921             case CPOINTER:
2922               SPEC_SCLS(TETYPE(tree)) = S_CODE; 
2923               break;
2924             case GPOINTER:
2925               SPEC_SCLS (TETYPE (tree)) = 0;
2926               break;
2927             case PPOINTER:
2928               SPEC_SCLS(TETYPE(tree)) = S_XSTACK; 
2929               break;
2930             case IPOINTER:
2931               SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2932               break;
2933             case EEPPOINTER:
2934               SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2935               break;
2936             case UPOINTER:
2937               SPEC_SCLS (TETYPE (tree)) = 0;
2938               break;
2939             case ARRAY:
2940             case FUNCTION:
2941               break;
2942           }
2943           return tree;
2944         }
2945
2946       /*------------------------------------------------------------------*/
2947       /*----------------------------*/
2948       /*      multiplication        */
2949       /*----------------------------*/
2950       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
2951         {
2952           werror (E_INVALID_OP, "multiplication");
2953           goto errorTreeReturn;
2954         }
2955
2956       /* if they are both literal then */
2957       /* rewrite the tree */
2958       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2959         {
2960           tree->type = EX_VALUE;
2961           tree->opval.val = valMult (valFromType (LETYPE (tree)),
2962                                      valFromType (RETYPE (tree)));
2963           tree->right = tree->left = NULL;
2964           TETYPE (tree) = getSpec (TTYPE (tree) =
2965                                    tree->opval.val->type);
2966           return tree;
2967         }
2968
2969       /* if left is a literal exchange left & right */
2970       if (IS_LITERAL (LTYPE (tree)))
2971         {
2972           ast *tTree = tree->left;
2973           tree->left = tree->right;
2974           tree->right = tTree;
2975         }
2976
2977       /* if right is a literal and */
2978       /* we can find a 2nd literal in a mul-tree then */
2979       /* rearrange the tree */
2980       if (IS_LITERAL (RTYPE (tree)))
2981         {
2982           ast *parent;
2983           ast *litTree = searchLitOp (tree, &parent, "*");
2984           if (litTree)
2985             {
2986               ast *tTree = litTree->left;
2987               litTree->left = tree->right;
2988               tree->right = tTree;
2989               /* both operands in litTree are literal now */
2990               decorateType (parent, RESULT_CHECK);
2991             }
2992         }
2993
2994       LRVAL (tree) = RRVAL (tree) = 1;
2995       tree->left  = addCast (tree->left,  resultType, FALSE);
2996       tree->right = addCast (tree->right, resultType, FALSE);
2997       TETYPE (tree) = getSpec (TTYPE (tree) =
2998                                    computeType (LTYPE (tree),
2999                                                 RTYPE (tree),
3000                                                 resultType,
3001                                                 tree->opval.op));
3002
3003       return tree;
3004
3005       /*------------------------------------------------------------------*/
3006       /*----------------------------*/
3007       /*    unary '+' operator      */
3008       /*----------------------------*/
3009     case '+':
3010       /* if unary plus */
3011       if (!tree->right)
3012         {
3013           if (!IS_ARITHMETIC (LTYPE (tree)))
3014             {
3015               werror (E_UNARY_OP, '+');
3016               goto errorTreeReturn;
3017             }
3018
3019           /* if left is a literal then do it */
3020           if (IS_LITERAL (LTYPE (tree)))
3021             {
3022               tree->type = EX_VALUE;
3023               tree->opval.val = valFromType (LETYPE (tree));
3024               tree->left = NULL;
3025               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3026               return tree;
3027             }
3028           LRVAL (tree) = 1;
3029           COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3030           return tree;
3031         }
3032
3033       /*------------------------------------------------------------------*/
3034       /*----------------------------*/
3035       /*      addition              */
3036       /*----------------------------*/
3037
3038       /* this is not a unary operation */
3039       /* if both pointers then problem */
3040       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3041           (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3042         {
3043           werror (E_PTR_PLUS_PTR);
3044           goto errorTreeReturn;
3045         }
3046
3047       if (!IS_ARITHMETIC (LTYPE (tree)) &&
3048           !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3049         {
3050           werror (E_PLUS_INVALID, "+");
3051           goto errorTreeReturn;
3052         }
3053
3054       if (!IS_ARITHMETIC (RTYPE (tree)) &&
3055           !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3056         {
3057           werror (E_PLUS_INVALID, "+");
3058           goto errorTreeReturn;
3059         }
3060       /* if they are both literal then */
3061       /* rewrite the tree */
3062       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3063         {
3064           tree->type = EX_VALUE;
3065           tree->left  = addCast (tree->left,  resultType, TRUE);
3066           tree->right = addCast (tree->right, resultType, TRUE);
3067           tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3068                                      valFromType (RETYPE (tree)));
3069           tree->right = tree->left = NULL;
3070           TETYPE (tree) = getSpec (TTYPE (tree) =
3071                                    tree->opval.val->type);
3072           return tree;
3073         }
3074
3075       /* if the right is a pointer or left is a literal
3076          xchange left & right */
3077       if (IS_ARRAY (RTYPE (tree)) ||
3078           IS_PTR (RTYPE (tree)) ||
3079           IS_LITERAL (LTYPE (tree)))
3080         {
3081           ast *tTree = tree->left;
3082           tree->left = tree->right;
3083           tree->right = tTree;
3084         }
3085
3086       /* if right is a literal and */
3087       /* left is also an addition/subtraction with a literal then */
3088       /* rearrange the tree */
3089       if (IS_LITERAL (RTYPE (tree)))
3090         {
3091           ast *litTree, *parent;
3092           litTree = searchLitOp (tree, &parent, "+-");
3093           if (litTree)
3094             {
3095               if (litTree->opval.op == '+')
3096                 {
3097                   /* foo_aa */
3098                   ast *tTree = litTree->left;
3099                   litTree->left = tree->right;
3100                   tree->right = tree->left;
3101                   tree->left = tTree;
3102                 }
3103               else if (litTree->opval.op == '-')
3104                 {
3105                   if (IS_LITERAL (RTYPE (litTree)))
3106                     {
3107                       /* foo_asr */
3108                       ast *tTree = litTree->left;
3109                       litTree->left = tree->right;
3110                       tree->right = tTree;
3111                     }
3112                   else
3113                     {
3114                       /* foo_asl */
3115                       ast *tTree = litTree->right;
3116                       litTree->right = tree->right;
3117                       tree->right = tTree;
3118                       litTree->opval.op = '+';
3119                       tree->opval.op = '-';
3120                     }
3121                 }
3122               decorateType (parent, RESULT_CHECK);
3123             }
3124         }
3125
3126       LRVAL (tree) = RRVAL (tree) = 1;
3127       /* if the left is a pointer */
3128       if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3129         TETYPE (tree) = getSpec (TTYPE (tree) =
3130                                  LTYPE (tree));
3131       else
3132         {
3133           tree->left  = addCast (tree->left,  resultType, TRUE);
3134           tree->right = addCast (tree->right, resultType, TRUE);
3135           TETYPE (tree) = getSpec (TTYPE (tree) =
3136                                      computeType (LTYPE (tree),
3137                                                   RTYPE (tree),
3138                                                   resultType,
3139                                                   tree->opval.op));
3140         }
3141         
3142       return tree;
3143
3144       /*------------------------------------------------------------------*/
3145       /*----------------------------*/
3146       /*      unary '-'             */
3147       /*----------------------------*/
3148     case '-':                   /* can be unary   */
3149       /* if right is null then unary */
3150       if (!tree->right)
3151         {
3152
3153           if (!IS_ARITHMETIC (LTYPE (tree)))
3154             {
3155               werror (E_UNARY_OP, tree->opval.op);
3156               goto errorTreeReturn;
3157             }
3158
3159           /* if left is a literal then do it */
3160           if (IS_LITERAL (LTYPE (tree)))
3161             {
3162               tree->type = EX_VALUE;
3163               tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3164               tree->left = NULL;
3165               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3166               SPEC_USIGN(TETYPE(tree)) = 0;
3167               return tree;
3168             }
3169           LRVAL (tree) = 1;
3170           TETYPE(tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3171           return tree;
3172         }
3173
3174       /*------------------------------------------------------------------*/
3175       /*----------------------------*/
3176       /*    subtraction             */
3177       /*----------------------------*/
3178
3179       if (!(IS_PTR (LTYPE (tree)) ||
3180             IS_ARRAY (LTYPE (tree)) ||
3181             IS_ARITHMETIC (LTYPE (tree))))
3182         {
3183           werror (E_PLUS_INVALID, "-");
3184           goto errorTreeReturn;
3185         }
3186
3187       if (!(IS_PTR (RTYPE (tree)) ||
3188             IS_ARRAY (RTYPE (tree)) ||
3189             IS_ARITHMETIC (RTYPE (tree))))
3190         {
3191           werror (E_PLUS_INVALID, "-");
3192           goto errorTreeReturn;
3193         }
3194
3195       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3196           !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3197             IS_INTEGRAL (RTYPE (tree))))
3198         {
3199           werror (E_PLUS_INVALID, "-");
3200           goto errorTreeReturn;
3201         }
3202
3203       /* if they are both literal then */
3204       /* rewrite the tree */
3205       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3206         {
3207           tree->type = EX_VALUE;
3208           tree->left  = addCast (tree->left,  resultType, TRUE);
3209           tree->right = addCast (tree->right, resultType, TRUE);
3210           tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3211                                       valFromType (RETYPE (tree)));
3212           tree->right = tree->left = NULL;
3213           TETYPE (tree) = getSpec (TTYPE (tree) =
3214                                    tree->opval.val->type);
3215           return tree;
3216         }
3217
3218       /* if the left & right are equal then zero */
3219       if (isAstEqual (tree->left, tree->right))
3220         {
3221           tree->type = EX_VALUE;
3222           tree->left = tree->right = NULL;
3223           tree->opval.val = constVal ("0");
3224           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3225           return tree;
3226         }
3227
3228       /* if both of them are pointers or arrays then */
3229       /* the result is going to be an integer        */
3230       if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3231           (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3232         TETYPE (tree) = TTYPE (tree) = newIntLink ();
3233       else
3234         /* if only the left is a pointer */
3235         /* then result is a pointer      */
3236       if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3237         TETYPE (tree) = getSpec (TTYPE (tree) =
3238                                  LTYPE (tree));
3239       else
3240         {
3241           tree->left  = addCast (tree->left,  resultType, TRUE);
3242           tree->right = addCast (tree->right, resultType, TRUE);
3243
3244           TETYPE (tree) = getSpec (TTYPE (tree) =
3245                                      computeType (LTYPE (tree),
3246                                                   RTYPE (tree),
3247                                                   resultType,
3248                                                   tree->opval.op));
3249         }
3250
3251       LRVAL (tree) = RRVAL (tree) = 1;
3252
3253       /* if right is a literal and */
3254       /* left is also an addition/subtraction with a literal then */
3255       /* rearrange the tree */
3256       if (IS_LITERAL (RTYPE (tree))
3257           /* avoid infinite loop */
3258           && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 0)
3259         {
3260           ast *litTree, *litParent;
3261           litTree = searchLitOp (tree, &litParent, "+-");
3262           if (litTree)
3263             {
3264               if (litTree->opval.op == '+')
3265                 {
3266                   /* foo_sa */
3267                   litTree->right = newNode ('-', litTree->right, tree->right);
3268                   litTree->right->lineno = tree->lineno;
3269
3270                   tree->right->opval.val = constVal ("0");
3271                 }
3272               else if (litTree->opval.op == '-')
3273                 {
3274                   if (IS_LITERAL (RTYPE (litTree)))
3275                     {
3276                       /* foo_ssr */
3277                       litTree->right = newNode ('+', tree->right, litTree->right);
3278                       litTree->right->lineno = tree->lineno;
3279
3280                       tree->right->opval.val = constVal ("0");
3281                     }
3282                   else
3283                     {
3284                       /* foo_ssl */
3285                       ast *tTree = litTree->right;
3286                       litTree->right = tree->right;
3287                       tree->right = tTree;
3288                     }
3289                 }
3290               decorateType (litParent, RESULT_CHECK);
3291             }
3292         }
3293       return tree;
3294
3295       /*------------------------------------------------------------------*/
3296       /*----------------------------*/
3297       /*    complement              */
3298       /*----------------------------*/
3299     case '~':
3300       /* can be only integral type */
3301       if (!IS_INTEGRAL (LTYPE (tree)))
3302         {
3303           werror (E_UNARY_OP, tree->opval.op);
3304           goto errorTreeReturn;
3305         }
3306
3307       /* if left is a literal then do it */
3308       if (IS_LITERAL (LTYPE (tree)))
3309         {
3310           tree->type = EX_VALUE;
3311           tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3312           tree->left = NULL;
3313           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3314           return tree;
3315         }
3316       LRVAL (tree) = 1;
3317       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3318       return tree;
3319
3320       /*------------------------------------------------------------------*/
3321       /*----------------------------*/
3322       /*           not              */
3323       /*----------------------------*/
3324     case '!':
3325       /* can be pointer */
3326       if (!IS_ARITHMETIC (LTYPE (tree)) &&
3327           !IS_PTR (LTYPE (tree)) &&
3328           !IS_ARRAY (LTYPE (tree)))
3329         {
3330           werror (E_UNARY_OP, tree->opval.op);
3331           goto errorTreeReturn;
3332         }
3333
3334       /* if left is a literal then do it */
3335       if (IS_LITERAL (LTYPE (tree)))
3336         {
3337           tree->type = EX_VALUE;
3338           tree->opval.val = valNot (valFromType (LETYPE (tree)));
3339           tree->left = NULL;
3340           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3341           return tree;
3342         }
3343       LRVAL (tree) = 1;
3344       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3345       return tree;
3346
3347       /*------------------------------------------------------------------*/
3348       /*----------------------------*/
3349       /*           shift            */
3350       /*----------------------------*/
3351     case RRC:
3352     case RLC:
3353     case SWAP:
3354       TTYPE (tree) = LTYPE (tree);
3355       TETYPE (tree) = LETYPE (tree);
3356       return tree;
3357
3358     case GETHBIT:
3359       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3360       return tree;
3361
3362     case LEFT_OP:
3363     case RIGHT_OP:
3364       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3365         {
3366           werror (E_SHIFT_OP_INVALID);
3367           werror (W_CONTINUE, "left & right types are ");
3368           printTypeChain (LTYPE (tree), stderr);
3369           fprintf (stderr, ",");
3370           printTypeChain (RTYPE (tree), stderr);
3371           fprintf (stderr, "\n");
3372           goto errorTreeReturn;
3373         }
3374
3375       /* make smaller type only if it's a LEFT_OP */
3376       if (tree->opval.op == LEFT_OP)
3377         tree->left = addCast (tree->left, resultType, TRUE);
3378       
3379       /* if they are both literal then */
3380       /* rewrite the tree */
3381       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3382         {
3383           tree->type = EX_VALUE;
3384           tree->opval.val = valShift (valFromType (LETYPE (tree)),
3385                                       valFromType (RETYPE (tree)),
3386                                       (tree->opval.op == LEFT_OP ? 1 : 0));
3387           tree->right = tree->left = NULL;
3388           TETYPE (tree) = getSpec (TTYPE (tree) =
3389                                    tree->opval.val->type);
3390           return tree;
3391         }
3392
3393       LRVAL (tree) = RRVAL (tree) = 1;
3394       if (tree->opval.op == LEFT_OP)
3395         {
3396           TETYPE (tree) = getSpec (TTYPE (tree) =
3397                                        computeType (LTYPE (tree),
3398                                                     NULL,
3399                                                     resultType,
3400                                                     tree->opval.op));
3401         }
3402       else /* RIGHT_OP */
3403         {
3404           /* no promotion necessary */
3405           TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3406           if (IS_LITERAL (TTYPE (tree)))
3407             SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3408         }
3409
3410       /* if only the right side is a literal & we are
3411          shifting more than size of the left operand then zero */
3412       if (IS_LITERAL (RTYPE (tree)) &&
3413           ((TYPE_UDWORD) floatFromVal (valFromType (RETYPE (tree)))) >=
3414           (getSize (TETYPE (tree)) * 8))
3415         {
3416           if (tree->opval.op==LEFT_OP ||
3417               (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3418             {
3419               lineno=tree->lineno;
3420               werror (W_SHIFT_CHANGED,
3421                       (tree->opval.op == LEFT_OP ? "left" : "right"));
3422               tree->type = EX_VALUE;
3423               tree->left = tree->right = NULL;
3424               tree->opval.val = constVal ("0");
3425               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3426               return tree;
3427             }
3428         }
3429
3430       return tree;
3431
3432       /*------------------------------------------------------------------*/
3433       /*----------------------------*/
3434       /*         casting            */
3435       /*----------------------------*/
3436     case CAST:                  /* change the type   */
3437       /* cannot cast to an aggregate type */
3438       if (IS_AGGREGATE (LTYPE (tree)))
3439         {
3440           werror (E_CAST_ILLEGAL);
3441           goto errorTreeReturn;
3442         }
3443
3444       /* make sure the type is complete and sane */
3445       checkTypeSanity(LETYPE(tree), "(cast)");
3446
3447       /* If code memory is read only, then pointers to code memory */
3448       /* implicitly point to constants -- make this explicit       */
3449       {
3450         sym_link *t = LTYPE(tree);
3451         while (t && t->next)
3452           {
3453             if (IS_CODEPTR(t) && port->mem.code_ro)
3454               {
3455                 if (IS_SPEC(t->next))
3456                   SPEC_CONST (t->next) = 1;
3457                 else
3458                   DCL_PTR_CONST (t->next) = 1;
3459               }
3460             t = t->next;
3461           }
3462       }
3463
3464 #if 0
3465       /* if the right is a literal replace the tree */
3466       if (IS_LITERAL (RETYPE (tree))) {
3467               if (!IS_PTR (LTYPE (tree))) {
3468                       tree->type = EX_VALUE;
3469                       tree->opval.val =
3470                               valCastLiteral (LTYPE (tree),
3471                                               floatFromVal (valFromType (RETYPE (tree))));
3472                       tree->left = NULL;
3473                       tree->right = NULL;
3474                       TTYPE (tree) = tree->opval.val->type;
3475                       tree->values.literalFromCast = 1;
3476               } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3477                          ((int)floatFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */  {
3478                       sym_link *rest = LTYPE(tree)->next;
3479                       werror(W_LITERAL_GENERIC);
3480                       TTYPE(tree) = newLink(DECLARATOR);
3481                       DCL_TYPE(TTYPE(tree)) = FPOINTER;
3482                       TTYPE(tree)->next = rest;
3483                       tree->left->opval.lnk = TTYPE(tree);
3484                       LRVAL (tree) = 1;
3485               } else {
3486                       TTYPE (tree) = LTYPE (tree);
3487                       LRVAL (tree) = 1;
3488               }
3489       } else {
3490               TTYPE (tree) = LTYPE (tree);
3491               LRVAL (tree) = 1;
3492       }
3493 #else
3494 #if 0 // this is already checked, now this could be explicit
3495       /* if pointer to struct then check names */
3496       if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3497           IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3498           strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3499         {
3500           werror(W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3501                  SPEC_STRUCT(LETYPE(tree))->tag);
3502         }
3503 #endif
3504       if (IS_ADDRESS_OF_OP(tree->right)
3505           && IS_AST_SYM_VALUE (tree->right->left)
3506           && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3507
3508         tree->type = EX_VALUE;
3509         tree->opval.val =
3510           valCastLiteral (LTYPE (tree),
3511                           SPEC_ADDR (AST_SYMBOL (tree->right->left)->etype));
3512         TTYPE (tree) = tree->opval.val->type;
3513         TETYPE (tree) = getSpec (TTYPE (tree));
3514         tree->left = NULL;
3515         tree->right = NULL;
3516         tree->values.literalFromCast = 1;
3517         return tree;
3518       }
3519
3520       /* handle offsetof macro:            */
3521       /* #define offsetof(TYPE, MEMBER) \  */
3522       /* ((unsigned) &((TYPE *)0)->MEMBER) */
3523       if (IS_ADDRESS_OF_OP(tree->right)
3524           && IS_AST_OP (tree->right->left)
3525           && tree->right->left->opval.op == PTR_OP
3526           && IS_AST_OP (tree->right->left->left)
3527           && tree->right->left->left->opval.op == CAST
3528           && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3529
3530         symbol *element = getStructElement (
3531           SPEC_STRUCT (LETYPE(tree->right->left)),
3532           AST_SYMBOL(tree->right->left->right)
3533         );
3534
3535         if (element) {
3536           tree->type = EX_VALUE;
3537           tree->opval.val = valCastLiteral (
3538             LTYPE (tree),
3539             element->offset
3540             + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
3541           );
3542
3543           TTYPE (tree) = tree->opval.val->type;
3544           TETYPE (tree) = getSpec (TTYPE (tree));
3545           tree->left = NULL;
3546           tree->right = NULL;
3547           return tree;
3548         }
3549       }
3550
3551       /* if the right is a literal replace the tree */
3552       if (IS_LITERAL (RETYPE (tree))) {
3553         #if 0
3554         if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3555           /* rewrite      (type *)litaddr
3556              as           &temp
3557              and define   type at litaddr temp
3558              (but only if type's storage class is not generic)
3559           */
3560           ast *newTree = newNode ('&', NULL, NULL);
3561           symbol *sym;
3562
3563           TTYPE (newTree) = LTYPE (tree);
3564           TETYPE (newTree) = getSpec(LTYPE (tree));
3565
3566           /* define a global symbol at the casted address*/
3567           sym = newSymbol(genSymName (0), 0);
3568           sym->type = LTYPE (tree)->next;
3569           if (!sym->type)
3570             sym->type = newLink (V_VOID);
3571           sym->etype = getSpec(sym->type);
3572           SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
3573           sym->lineDef = tree->lineno;
3574           sym->cdef = 1;
3575           sym->isref = 1;
3576           SPEC_STAT (sym->etype) = 1;
3577           SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
3578           SPEC_ABSA(sym->etype) = 1;
3579           addSym (SymbolTab, sym, sym->name, 0, 0, 0);
3580           allocGlobal (sym);
3581
3582           newTree->left = newAst_VALUE(symbolVal(sym));
3583           newTree->left->lineno = tree->lineno;
3584           LTYPE (newTree) = sym->type;
3585           LETYPE (newTree) = sym->etype;
3586           LLVAL (newTree) = 1;
3587           LRVAL (newTree) = 0;
3588           TLVAL (newTree) = 1;
3589           return newTree;
3590         }
3591         #endif
3592         if (!IS_PTR (LTYPE (tree))) {
3593           tree->type = EX_VALUE;
3594           tree->opval.val =
3595           valCastLiteral (LTYPE (tree),
3596                           floatFromVal (valFromType (RTYPE (tree))));
3597           TTYPE (tree) = tree->opval.val->type;
3598           tree->left = NULL;
3599           tree->right = NULL;
3600           tree->values.literalFromCast = 1;
3601           TETYPE (tree) = getSpec (TTYPE (tree));
3602           return tree;
3603         }
3604       }
3605       TTYPE (tree) = LTYPE (tree);
3606       LRVAL (tree) = 1;
3607
3608 #endif
3609       TETYPE (tree) = getSpec (TTYPE (tree));
3610
3611       return tree;
3612
3613       /*------------------------------------------------------------------*/
3614       /*----------------------------*/
3615       /*       logical &&, ||       */
3616       /*----------------------------*/
3617     case AND_OP:
3618     case OR_OP:
3619       /* each must me arithmetic type or be a pointer */
3620       if (!IS_PTR (LTYPE (tree)) &&
3621           !IS_ARRAY (LTYPE (tree)) &&
3622           !IS_INTEGRAL (LTYPE (tree)))
3623         {
3624           werror (E_COMPARE_OP);
3625           goto errorTreeReturn;
3626         }
3627
3628       if (!IS_PTR (RTYPE (tree)) &&
3629           !IS_ARRAY (RTYPE (tree)) &&
3630           !IS_INTEGRAL (RTYPE (tree)))
3631         {
3632           werror (E_COMPARE_OP);
3633           goto errorTreeReturn;
3634         }
3635       /* if they are both literal then */
3636       /* rewrite the tree */
3637       if (IS_LITERAL (RTYPE (tree)) &&
3638           IS_LITERAL (LTYPE (tree)))
3639         {
3640           tree->type = EX_VALUE;
3641           tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
3642                                            valFromType (RTYPE (tree)),
3643                                            tree->opval.op);
3644           tree->right = tree->left = NULL;
3645           TETYPE (tree) = getSpec (TTYPE (tree) =
3646                                    tree->opval.val->type);
3647           return tree;
3648         }
3649       LRVAL (tree) = RRVAL (tree) = 1;
3650       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3651       return tree;
3652
3653       /*------------------------------------------------------------------*/
3654       /*----------------------------*/
3655       /*     comparison operators   */
3656       /*----------------------------*/
3657     case '>':
3658     case '<':
3659     case LE_OP:
3660     case GE_OP:
3661     case EQ_OP:
3662     case NE_OP:
3663       {
3664         ast *lt = optimizeCompare (tree);
3665
3666         if (tree != lt)
3667           return lt;
3668       }
3669
3670       /* if they are pointers they must be castable */
3671       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
3672         {
3673           if (tree->opval.op==EQ_OP &&
3674               !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
3675             // we cannot cast a gptr to a !gptr: switch the leaves
3676             struct ast *s=tree->left;
3677             tree->left=tree->right;
3678             tree->right=s;
3679           }
3680           if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3681             {
3682               werror (E_COMPARE_OP);
3683               fprintf (stderr, "comparing type ");
3684               printTypeChain (LTYPE (tree), stderr);
3685               fprintf (stderr, "to type ");
3686               printTypeChain (RTYPE (tree), stderr);
3687               fprintf (stderr, "\n");
3688               goto errorTreeReturn;
3689             }
3690         }
3691       /* else they should be promotable to one another */
3692       else
3693         {
3694           if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
3695                 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
3696
3697             if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3698               {
3699                 werror (E_COMPARE_OP);
3700                 fprintf (stderr, "comparing type ");
3701                 printTypeChain (LTYPE (tree), stderr);
3702                 fprintf (stderr, "to type ");
3703                 printTypeChain (RTYPE (tree), stderr);
3704                 fprintf (stderr, "\n");
3705                 goto errorTreeReturn;
3706               }
3707         }
3708       /* if unsigned value < 0  then always false */
3709       /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
3710       if (SPEC_USIGN(LETYPE(tree)) &&
3711           !IS_CHAR(LETYPE(tree)) && /* promotion to signed int */
3712           IS_LITERAL(RTYPE(tree))  &&
3713           ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0)
3714         {
3715           if (tree->opval.op == '<')
3716             {
3717               return tree->right;
3718             }
3719           if (tree->opval.op == '>')
3720             {
3721               if (resultType == RESULT_TYPE_IFX)
3722                 {
3723                   /* the parent is an ifx: */
3724                   /* if (unsigned value) */
3725                   return tree->left;
3726                 }
3727               
3728               /* (unsigned value) ? 1 : 0 */
3729               tree->opval.op = '?';
3730               tree->right = newNode (':',
3731                                      newAst_VALUE (constVal ("1")),
3732                                      tree->right); /* val 0 */
3733               tree->right->lineno = tree->lineno;
3734               tree->right->left->lineno = tree->lineno;
3735               decorateType (tree->right, RESULT_CHECK);
3736             }
3737         }
3738       /* if they are both literal then */
3739       /* rewrite the tree */
3740       if (IS_LITERAL (RTYPE (tree)) &&
3741           IS_LITERAL (LTYPE (tree)))
3742         {
3743           tree->type = EX_VALUE;
3744           tree->opval.val = valCompare (valFromType (LETYPE (tree)),
3745                                         valFromType (RETYPE (tree)),
3746                                         tree->opval.op);
3747           tree->right = tree->left = NULL;
3748           TETYPE (tree) = getSpec (TTYPE (tree) =
3749                                    tree->opval.val->type);
3750           return tree;
3751         }
3752       LRVAL (tree) = RRVAL (tree) = 1;
3753       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3754       return tree;
3755
3756       /*------------------------------------------------------------------*/
3757       /*----------------------------*/
3758       /*             sizeof         */
3759       /*----------------------------*/
3760     case SIZEOF:                /* evaluate wihout code generation */
3761       /* change the type to a integer */
3762       {
3763         int size = getSize (tree->right->ftype);
3764         SNPRINTF(buffer, sizeof(buffer), "%d", size);
3765         if (!size && !IS_VOID(tree->right->ftype))
3766           werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
3767       }
3768       tree->type = EX_VALUE;
3769       tree->opval.val = constVal (buffer);
3770       tree->right = tree->left = NULL;
3771       TETYPE (tree) = getSpec (TTYPE (tree) =
3772                                tree->opval.val->type);
3773       return tree;
3774
3775       /*------------------------------------------------------------------*/
3776       /*----------------------------*/
3777       /*             typeof         */
3778       /*----------------------------*/
3779     case TYPEOF:
3780         /* return typeof enum value */
3781         tree->type = EX_VALUE;
3782         {
3783             int typeofv = 0;
3784             if (IS_SPEC(tree->right->ftype)) {
3785                 switch (SPEC_NOUN(tree->right->ftype)) {
3786                 case V_INT:
3787                     if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
3788                     else typeofv = TYPEOF_INT;
3789                     break;
3790                 case V_FLOAT:
3791                     typeofv = TYPEOF_FLOAT;
3792                     break;
3793                 case V_CHAR:
3794                     typeofv = TYPEOF_CHAR;
3795                     break;
3796                 case V_VOID:
3797                     typeofv = TYPEOF_VOID;
3798                     break;
3799                 case V_STRUCT:
3800                     typeofv = TYPEOF_STRUCT;
3801                     break;
3802                 case V_BITFIELD:
3803                     typeofv = TYPEOF_BITFIELD;
3804                     break;
3805                 case V_BIT:
3806                     typeofv = TYPEOF_BIT;
3807                     break;
3808                 case V_SBIT:
3809                     typeofv = TYPEOF_SBIT;
3810                     break;
3811                 default:
3812                     break;
3813                 }
3814             } else {
3815                 switch (DCL_TYPE(tree->right->ftype)) {
3816                 case POINTER:
3817                     typeofv = TYPEOF_POINTER;
3818                     break;
3819                 case FPOINTER:
3820                     typeofv = TYPEOF_FPOINTER;
3821                     break;
3822                 case CPOINTER:
3823                     typeofv = TYPEOF_CPOINTER;
3824                     break;
3825                 case GPOINTER:
3826                     typeofv = TYPEOF_GPOINTER;
3827                     break;
3828                 case PPOINTER:
3829                     typeofv = TYPEOF_PPOINTER;
3830                     break;
3831                 case IPOINTER:
3832                     typeofv = TYPEOF_IPOINTER;
3833                     break;
3834                 case ARRAY:
3835                     typeofv = TYPEOF_ARRAY;
3836                     break;
3837                 case FUNCTION:
3838                     typeofv = TYPEOF_FUNCTION;
3839                     break;
3840                 default:
3841                     break;
3842                 }
3843             }
3844             SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
3845             tree->opval.val = constVal (buffer);
3846             tree->right = tree->left = NULL;
3847             TETYPE (tree) = getSpec (TTYPE (tree) =
3848                                      tree->opval.val->type);
3849         }
3850         return tree;
3851       /*------------------------------------------------------------------*/
3852       /*----------------------------*/
3853       /* conditional operator  '?'  */
3854       /*----------------------------*/
3855     case '?':
3856       /* the type is value of the colon operator (on the right) */
3857       assert (IS_COLON_OP (tree->right));
3858       /* if already known then replace the tree : optimizer will do it
3859          but faster to do it here */
3860       if (IS_LITERAL (LTYPE (tree)))
3861         {
3862           if (((int) floatFromVal (valFromType (LETYPE (tree)))) != 0)
3863             return decorateType (tree->right->left, resultTypeProp);
3864           else
3865             return decorateType (tree->right->right, resultTypeProp);
3866         }
3867       else
3868         {
3869           tree->right = decorateType (tree->right, resultTypeProp);
3870           TTYPE (tree) = RTYPE (tree);
3871           TETYPE (tree) = getSpec (TTYPE (tree));
3872         }
3873       return tree;
3874
3875     case ':':
3876       /* if they don't match we have a problem */
3877       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3878         {
3879           werror (E_TYPE_MISMATCH, "conditional operator", " ");
3880           goto errorTreeReturn;
3881         }
3882
3883       TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
3884                                   resultType, tree->opval.op);
3885       TETYPE (tree) = getSpec (TTYPE (tree));
3886       return tree;
3887
3888
3889 #if 0 // assignment operators are converted by the parser
3890       /*------------------------------------------------------------------*/
3891       /*----------------------------*/
3892       /*    assignment operators    */
3893       /*----------------------------*/
3894     case MUL_ASSIGN:
3895     case DIV_ASSIGN:
3896       /* for these it must be both must be integral */
3897       if (!IS_ARITHMETIC (LTYPE (tree)) ||
3898           !IS_ARITHMETIC (RTYPE (tree)))
3899         {
3900           werror (E_OPS_INTEGRAL);
3901           goto errorTreeReturn;
3902         }
3903       RRVAL (tree) = 1;
3904       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3905
3906       if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
3907         werror (E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
3908
3909       if (LRVAL (tree))
3910         {
3911           werror (E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
3912           goto errorTreeReturn;
3913         }
3914       LLVAL (tree) = 1;
3915
3916       return tree;
3917
3918     case AND_ASSIGN:
3919     case OR_ASSIGN:
3920     case XOR_ASSIGN:
3921     case RIGHT_ASSIGN:
3922     case LEFT_ASSIGN:
3923       /* for these it must be both must be integral */
3924       if (!IS_INTEGRAL (LTYPE (tree)) ||
3925           !IS_INTEGRAL (RTYPE (tree)))
3926         {
3927           werror (E_OPS_INTEGRAL);
3928           goto errorTreeReturn;
3929         }
3930       RRVAL (tree) = 1;
3931       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3932
3933       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
3934         werror (E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
3935
3936       if (LRVAL (tree))
3937         {
3938           werror (E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
3939           goto errorTreeReturn;
3940         }
3941       LLVAL (tree) = 1;
3942
3943       return tree;
3944
3945       /*------------------------------------------------------------------*/
3946       /*----------------------------*/
3947       /*    -= operator             */
3948       /*----------------------------*/
3949     case SUB_ASSIGN:
3950       if (!(IS_PTR (LTYPE (tree)) ||
3951             IS_ARITHMETIC (LTYPE (tree))))
3952         {
3953           werror (E_PLUS_INVALID, "-=");
3954           goto errorTreeReturn;
3955         }
3956
3957       if (!(IS_PTR (RTYPE (tree)) ||
3958             IS_ARITHMETIC (RTYPE (tree))))
3959         {
3960           werror (E_PLUS_INVALID, "-=");
3961           goto errorTreeReturn;
3962         }
3963       RRVAL (tree) = 1;
3964       TETYPE (tree) = getSpec (TTYPE (tree) =
3965                                computeType (LTYPE (tree),
3966                                             RTYPE (tree),
3967                                             RESULT_TYPE_NOPROM,
3968                                             tree->opval.op));
3969
3970       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
3971         werror (E_CODE_WRITE, "-=");
3972
3973       if (LRVAL (tree))
3974         {
3975           werror (E_LVALUE_REQUIRED, "-=");
3976           goto errorTreeReturn;
3977         }
3978       LLVAL (tree) = 1;
3979
3980       return tree;
3981
3982       /*------------------------------------------------------------------*/
3983       /*----------------------------*/
3984       /*          += operator       */
3985       /*----------------------------*/
3986     case ADD_ASSIGN:
3987       /* this is not a unary operation */
3988       /* if both pointers then problem */
3989       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
3990         {
3991           werror (E_PTR_PLUS_PTR);
3992           goto errorTreeReturn;
3993         }
3994
3995       if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
3996         {
3997           werror (E_PLUS_INVALID, "+=");
3998           goto errorTreeReturn;
3999         }
4000
4001       if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4002         {
4003           werror (E_PLUS_INVALID, "+=");
4004           goto errorTreeReturn;
4005         }
4006       RRVAL (tree) = 1;
4007       TETYPE (tree) = getSpec (TTYPE (tree) =
4008                                computeType (LTYPE (tree),
4009                                             RTYPE (tree),
4010                                             RESULT_TYPE_NOPROM,
4011                                             tree->opval.op));
4012
4013       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4014         werror (E_CODE_WRITE, "+=");
4015
4016       if (LRVAL (tree))
4017         {
4018           werror (E_LVALUE_REQUIRED, "+=");
4019           goto errorTreeReturn;
4020         }
4021
4022       tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_CHECK);
4023       tree->opval.op = '=';
4024
4025       return tree;
4026 #endif
4027
4028       /*------------------------------------------------------------------*/
4029       /*----------------------------*/
4030       /*      straight assignemnt   */
4031       /*----------------------------*/
4032     case '=':
4033       /* cannot be an aggregate */
4034       if (IS_AGGREGATE (LTYPE (tree)))
4035         {
4036           werror (E_AGGR_ASSIGN);
4037           goto errorTreeReturn;
4038         }
4039
4040       /* they should either match or be castable */
4041       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4042         {
4043           werror (E_TYPE_MISMATCH, "assignment", " ");
4044           printFromToType(RTYPE(tree),LTYPE(tree));
4045         }
4046
4047       /* if the left side of the tree is of type void
4048          then report error */
4049       if (IS_VOID (LTYPE (tree)))
4050         {
4051           werror (E_CAST_ZERO);
4052           printFromToType(RTYPE(tree), LTYPE(tree));
4053         }
4054
4055       TETYPE (tree) = getSpec (TTYPE (tree) =
4056                                LTYPE (tree));
4057       RRVAL (tree) = 1;
4058       LLVAL (tree) = 1;
4059       if (!tree->initMode ) {
4060         if (IS_CONSTANT(LTYPE(tree)))
4061           werror (E_CODE_WRITE, "=");
4062       }
4063       if (LRVAL (tree))
4064         {
4065           werror (E_LVALUE_REQUIRED, "=");
4066           goto errorTreeReturn;
4067         }
4068
4069       return tree;
4070
4071       /*------------------------------------------------------------------*/
4072       /*----------------------------*/
4073       /*      comma operator        */
4074       /*----------------------------*/
4075     case ',':
4076       TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4077       return tree;
4078
4079       /*------------------------------------------------------------------*/
4080       /*----------------------------*/
4081       /*       function call        */
4082       /*----------------------------*/
4083     case CALL:
4084       
4085       /* undo any explicit pointer derefernce; PCALL will handle it instead */
4086       if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4087         {
4088           if (tree->left->opval.op == '*' && !tree->left->right)
4089             tree->left = tree->left->left;
4090         }
4091
4092       /* require a function or pointer to function */
4093       if (!IS_FUNC (LTYPE (tree))
4094           && !(IS_CODEPTR (LTYPE (tree)) && IS_FUNC (LTYPE (tree)->next)))
4095         {
4096           werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4097           goto errorTreeReturn;
4098         }
4099
4100       {
4101         sym_link *functype;      
4102         parmNumber = 1;
4103
4104         if (IS_CODEPTR(LTYPE(tree)))
4105           functype = LTYPE (tree)->next;
4106         else
4107           functype = LTYPE (tree);
4108
4109         if (processParms (tree->left, FUNC_ARGS(functype),
4110                           tree->right, &parmNumber, TRUE)) {
4111           goto errorTreeReturn;
4112         }
4113
4114         if ((options.stackAuto || IFFUNC_ISREENT (functype)) && 
4115             !IFFUNC_ISBUILTIN(functype))
4116           {
4117             reverseParms (tree->right);
4118           }
4119
4120         TTYPE (tree) = functype->next;
4121         TETYPE (tree) = getSpec (TTYPE (tree));
4122       }
4123       return tree;
4124
4125       /*------------------------------------------------------------------*/
4126       /*----------------------------*/
4127       /*     return statement       */
4128       /*----------------------------*/
4129     case RETURN:
4130       if (!tree->right)
4131         goto voidcheck;
4132
4133       if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4134         {
4135           werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4136           printFromToType (RTYPE(tree), currFunc->type->next);
4137           goto errorTreeReturn;
4138         }
4139
4140       if (IS_VOID (currFunc->type->next)
4141           && tree->right &&
4142           !IS_VOID (RTYPE (tree)))
4143         {
4144           werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4145           goto errorTreeReturn;
4146         }
4147
4148       /* if there is going to be a casting required then add it */
4149       if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4150         {
4151           tree->right =
4152             decorateType (newNode (CAST,
4153                           newAst_LINK (copyLinkChain (currFunc->type->next)),
4154                                         tree->right),
4155                           RESULT_CHECK);
4156         }
4157
4158       RRVAL (tree) = 1;
4159       return tree;
4160
4161     voidcheck:
4162
4163       if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4164         {
4165           werror (W_VOID_FUNC, currFunc->name);
4166           goto errorTreeReturn;
4167         }
4168
4169       TTYPE (tree) = TETYPE (tree) = NULL;
4170       return tree;
4171
4172       /*------------------------------------------------------------------*/
4173       /*----------------------------*/
4174       /*     switch statement       */
4175       /*----------------------------*/
4176     case SWITCH:
4177       /* the switch value must be an integer */
4178       if (!IS_INTEGRAL (LTYPE (tree)))
4179         {
4180           werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4181           goto errorTreeReturn;
4182         }
4183       LRVAL (tree) = 1;
4184       TTYPE (tree) = TETYPE (tree) = NULL;
4185       return tree;
4186
4187       /*------------------------------------------------------------------*/
4188       /*----------------------------*/
4189       /* ifx Statement              */
4190       /*----------------------------*/
4191     case IFX:
4192       tree->left = backPatchLabels (tree->left,
4193                                     tree->trueLabel,
4194                                     tree->falseLabel);
4195       TTYPE (tree) = TETYPE (tree) = NULL;
4196       return tree;
4197
4198       /*------------------------------------------------------------------*/
4199       /*----------------------------*/
4200       /* for Statement              */
4201       /*----------------------------*/
4202     case FOR:
4203
4204       decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_CHECK);
4205       decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_CHECK);
4206       decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_CHECK);
4207
4208       /* if the for loop is reversible then
4209          reverse it otherwise do what we normally
4210          do */
4211       {
4212         symbol *sym;
4213         ast *init, *end;
4214
4215         if (isLoopReversible (tree, &sym, &init, &end))
4216           return reverseLoop (tree, sym, init, end);
4217         else
4218           return decorateType (createFor (AST_FOR (tree, trueLabel),
4219                                           AST_FOR (tree, continueLabel),
4220                                           AST_FOR (tree, falseLabel),
4221                                           AST_FOR (tree, condLabel),
4222                                           AST_FOR (tree, initExpr),
4223                                           AST_FOR (tree, condExpr),
4224                                           AST_FOR (tree, loopExpr),
4225                                           tree->left), RESULT_CHECK);
4226       }
4227     case PARAM:
4228       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4229               "node PARAM shouldn't be processed here");
4230               /* but in processParams() */
4231       return tree;
4232     default:
4233       TTYPE (tree) = TETYPE (tree) = NULL;
4234       return tree;
4235     }
4236
4237   /* some error found this tree will be killed */
4238 errorTreeReturn:
4239   TTYPE (tree) = TETYPE (tree) = newCharLink ();
4240   tree->opval.op = NULLOP;
4241   tree->isError = 1;
4242
4243   return tree;
4244 }
4245
4246 /*-----------------------------------------------------------------*/
4247 /* sizeofOp - processes size of operation                          */
4248 /*-----------------------------------------------------------------*/
4249 value *
4250 sizeofOp (sym_link * type)
4251 {
4252   char buff[10];
4253   int size;
4254
4255   /* make sure the type is complete and sane */
4256   checkTypeSanity(type, "(sizeof)");
4257
4258   /* get the size and convert it to character  */
4259   SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4260   if (!size && !IS_VOID(type))
4261     werror (E_SIZEOF_INCOMPLETE_TYPE);
4262
4263   /* now convert into value  */
4264   return constVal (buff);
4265 }
4266
4267
4268 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4269 #define IS_OR(ex)  (ex->type == EX_OP && ex->opval.op == OR_OP )
4270 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4271 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4272 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4273 #define IS_LT(ex)  (ex->type == EX_OP && ex->opval.op == '<' )
4274 #define IS_GT(ex)  (ex->type == EX_OP && ex->opval.op == '>')
4275
4276 /*-----------------------------------------------------------------*/
4277 /* backPatchLabels - change and or not operators to flow control    */
4278 /*-----------------------------------------------------------------*/
4279 ast *
4280 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4281 {
4282
4283   if (!tree)
4284     return NULL;
4285
4286   if (!(IS_ANDORNOT (tree)))
4287     return tree;
4288
4289   /* if this an and */
4290   if (IS_AND (tree))
4291     {
4292       static int localLbl = 0;
4293       symbol *localLabel;
4294
4295       SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4296       localLabel = newSymbol (buffer, NestLevel);
4297
4298       tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4299
4300       /* if left is already a IFX then just change the if true label in that */
4301       if (!IS_IFX (tree->left))
4302         tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4303
4304       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4305       /* right is a IFX then just join */
4306       if (IS_IFX (tree->right))
4307         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4308
4309       tree->right = createLabel (localLabel, tree->right);
4310       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4311
4312       return newNode (NULLOP, tree->left, tree->right);
4313     }
4314
4315   /* if this is an or operation */
4316   if (IS_OR (tree))
4317     {
4318       static int localLbl = 0;
4319       symbol *localLabel;
4320
4321       SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4322       localLabel = newSymbol (buffer, NestLevel);
4323
4324       tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4325
4326       /* if left is already a IFX then just change the if true label in that */
4327       if (!IS_IFX (tree->left))
4328         tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4329
4330       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4331       /* right is a IFX then just join */
4332       if (IS_IFX (tree->right))
4333         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4334
4335       tree->right = createLabel (localLabel, tree->right);
4336       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4337
4338       return newNode (NULLOP, tree->left, tree->right);
4339     }
4340
4341   /* change not */
4342   if (IS_NOT (tree))
4343     {
4344       int wasnot = IS_NOT (tree->left);
4345       tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4346
4347       /* if the left is already a IFX */
4348       if (!IS_IFX (tree->left))
4349         tree->left = newNode (IFX, tree->left, NULL);
4350
4351       if (wasnot)
4352         {
4353           tree->left->trueLabel = trueLabel;
4354           tree->left->falseLabel = falseLabel;
4355         }
4356       else
4357         {
4358           tree->left->trueLabel = falseLabel;
4359           tree->left->falseLabel = trueLabel;
4360         }
4361       return tree->left;
4362     }
4363
4364   if (IS_IFX (tree))
4365     {
4366       tree->trueLabel = trueLabel;
4367       tree->falseLabel = falseLabel;
4368     }
4369
4370   return tree;
4371 }
4372
4373
4374 /*-----------------------------------------------------------------*/
4375 /* createBlock - create expression tree for block                  */
4376 /*-----------------------------------------------------------------*/
4377 ast *
4378 createBlock (symbol * decl, ast * body)
4379 {
4380   ast *ex;
4381
4382   /* if the block has nothing */
4383   if (!body && !decl)
4384     return NULL;
4385
4386   ex = newNode (BLOCK, NULL, body);
4387   ex->values.sym = decl;
4388   
4389   ex->right = ex->right;
4390   ex->level++;
4391   ex->lineno = 0;
4392   return ex;
4393 }
4394
4395 /*-----------------------------------------------------------------*/
4396 /* createLabel - creates the expression tree for labels            */
4397 /*-----------------------------------------------------------------*/
4398 ast *
4399 createLabel (symbol * label, ast * stmnt)
4400 {
4401   symbol *csym;
4402   char name[SDCC_NAME_MAX + 1];
4403   ast *rValue;
4404
4405   /* must create fresh symbol if the symbol name  */
4406   /* exists in the symbol table, since there can  */
4407   /* be a variable with the same name as the labl */
4408   if ((csym = findSym (SymbolTab, NULL, label->name)) &&
4409       (csym->level == label->level))
4410     label = newSymbol (label->name, label->level);
4411
4412   /* change the name before putting it in add _ */
4413   SNPRINTF(name, sizeof(name), "%s", label->name);
4414
4415   /* put the label in the LabelSymbol table    */
4416   /* but first check if a label of the same    */
4417   /* name exists                               */
4418   if ((csym = findSym (LabelTab, NULL, name)))
4419     werror (E_DUPLICATE_LABEL, label->name);
4420   else
4421     addSym (LabelTab, label, name, label->level, 0, 0);
4422
4423   label->islbl = 1;
4424   label->key = labelKey++;
4425   rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
4426   rValue->lineno = 0;
4427
4428   return rValue;
4429 }
4430
4431 /*-----------------------------------------------------------------*/
4432 /* createCase - generates the parsetree for a case statement       */
4433 /*-----------------------------------------------------------------*/
4434 ast *
4435 createCase (ast * swStat, ast * caseVal, ast * stmnt)
4436 {
4437   char caseLbl[SDCC_NAME_MAX + 1];
4438   ast *rexpr;
4439   value *val;
4440
4441   /* if the switch statement does not exist */
4442   /* then case is out of context            */
4443   if (!swStat)
4444     {
4445       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
4446       return NULL;
4447     }
4448
4449   caseVal = decorateType (resolveSymbols (caseVal), RESULT_CHECK);
4450   /* if not a constant then error  */
4451   if (!IS_LITERAL (caseVal->ftype))
4452     {
4453       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
4454       return NULL;
4455     }
4456
4457   /* if not a integer than error */
4458   if (!IS_INTEGRAL (caseVal->ftype))
4459     {
4460       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
4461       return NULL;
4462     }
4463
4464   /* find the end of the switch values chain   */
4465   if (!(val = swStat->values.switchVals.swVals))
4466     swStat->values.switchVals.swVals = caseVal->opval.val;
4467   else
4468     {
4469       /* also order the cases according to value */
4470       value *pval = NULL;
4471       int cVal = (int) floatFromVal (caseVal->opval.val);
4472       while (val && (int) floatFromVal (val) < cVal)
4473         {
4474           pval = val;
4475           val = val->next;
4476         }
4477
4478       /* if we reached the end then */
4479       if (!val)
4480         {
4481           pval->next = caseVal->opval.val;
4482         }
4483       else if ((int) floatFromVal (val) == cVal)
4484         {
4485           werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
4486                     "case");
4487           return NULL;
4488         }
4489       else
4490         {
4491           /* we found a value greater than */
4492           /* the current value we must add this */
4493           /* before the value */
4494           caseVal->opval.val->next = val;
4495
4496           /* if this was the first in chain */
4497           if (swStat->values.switchVals.swVals == val)
4498             swStat->values.switchVals.swVals =
4499               caseVal->opval.val;
4500           else
4501             pval->next = caseVal->opval.val;
4502         }
4503
4504     }
4505
4506   /* create the case label   */
4507   SNPRINTF(caseLbl, sizeof(caseLbl), 
4508            "_case_%d_%d",
4509            swStat->values.switchVals.swNum,
4510            (int) floatFromVal (caseVal->opval.val));
4511
4512   rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
4513   rexpr->lineno = 0;
4514   return rexpr;
4515 }
4516
4517 /*-----------------------------------------------------------------*/
4518 /* createDefault - creates the parse tree for the default statement */
4519 /*-----------------------------------------------------------------*/
4520 ast *
4521 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
4522 {
4523   char defLbl[SDCC_NAME_MAX + 1];
4524
4525   /* if the switch statement does not exist */
4526   /* then case is out of context            */
4527   if (!swStat)
4528     {
4529       werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
4530       return NULL;
4531     }
4532
4533   if (swStat->values.switchVals.swDefault)
4534     {
4535       werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
4536                 "default");
4537       return NULL;
4538     }
4539
4540   /* turn on the default flag   */
4541   swStat->values.switchVals.swDefault = 1;
4542
4543   /* create the label  */
4544   SNPRINTF (defLbl, sizeof(defLbl),
4545             "_default_%d", swStat->values.switchVals.swNum);
4546   return createLabel (newSymbol (defLbl, 0), stmnt);
4547 }
4548
4549 /*-----------------------------------------------------------------*/
4550 /* createIf - creates the parsetree for the if statement           */
4551 /*-----------------------------------------------------------------*/
4552 ast *
4553 createIf (ast * condAst, ast * ifBody, ast * elseBody)
4554 {
4555   static int Lblnum = 0;
4556   ast *ifTree;
4557   symbol *ifTrue, *ifFalse, *ifEnd;
4558
4559   /* if neither exists */
4560   if (!elseBody && !ifBody) {
4561     // if there are no side effects (i++, j() etc)
4562     if (!hasSEFcalls(condAst)) {
4563       return condAst;
4564     }
4565   }
4566
4567   /* create the labels */
4568   SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
4569   ifFalse = newSymbol (buffer, NestLevel);
4570   /* if no else body then end == false */
4571   if (!elseBody)
4572     ifEnd = ifFalse;
4573   else
4574     {
4575       SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
4576       ifEnd = newSymbol (buffer, NestLevel);
4577     }
4578
4579   SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
4580   ifTrue = newSymbol (buffer, NestLevel);
4581
4582   Lblnum++;
4583
4584   /* attach the ifTrue label to the top of it body */
4585   ifBody = createLabel (ifTrue, ifBody);
4586   /* attach a goto end to the ifBody if else is present */
4587   if (elseBody)
4588     {
4589       ifBody = newNode (NULLOP, ifBody,
4590                         newNode (GOTO,
4591                                  newAst_VALUE (symbolVal (ifEnd)),
4592                                  NULL));
4593       /* put the elseLabel on the else body */
4594       elseBody = createLabel (ifFalse, elseBody);
4595       /* out the end at the end of the body */
4596       elseBody = newNode (NULLOP,
4597                           elseBody,
4598                           createLabel (ifEnd, NULL));
4599     }
4600   else
4601     {
4602       ifBody = newNode (NULLOP, ifBody,
4603                         createLabel (ifFalse, NULL));
4604     }
4605   condAst = backPatchLabels (condAst, ifTrue, ifFalse);
4606   if (IS_IFX (condAst))
4607     ifTree = condAst;
4608   else
4609     ifTree = newIfxNode (condAst, ifTrue, ifFalse);
4610
4611   return newNode (NULLOP, ifTree,
4612                   newNode (NULLOP, ifBody, elseBody));
4613
4614 }
4615
4616 /*-----------------------------------------------------------------*/
4617 /* createDo - creates parse tree for do                            */
4618 /*        _dobody_n:                                               */
4619 /*            statements                                           */
4620 /*        _docontinue_n:                                           */
4621 /*            condition_expression +-> trueLabel -> _dobody_n      */
4622 /*                                 |                               */
4623 /*                                 +-> falseLabel-> _dobreak_n     */
4624 /*        _dobreak_n:                                              */
4625 /*-----------------------------------------------------------------*/
4626 ast *
4627 createDo (symbol * trueLabel, symbol * continueLabel,
4628           symbol * falseLabel, ast * condAst, ast * doBody)
4629 {
4630   ast *doTree;
4631
4632
4633   /* if the body does not exist then it is simple */
4634   if (!doBody)
4635     {
4636       condAst = backPatchLabels (condAst, continueLabel, NULL);
4637       doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
4638                 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
4639       doTree->trueLabel = continueLabel;
4640       doTree->falseLabel = NULL;
4641       return doTree;
4642     }
4643
4644   /* otherwise we have a body */
4645   condAst = backPatchLabels (condAst, trueLabel, falseLabel);
4646
4647   /* attach the body label to the top */
4648   doBody = createLabel (trueLabel, doBody);
4649   /* attach the continue label to end of body */
4650   doBody = newNode (NULLOP, doBody,
4651                     createLabel (continueLabel, NULL));
4652
4653   /* now put the break label at the end */
4654   if (IS_IFX (condAst))
4655     doTree = condAst;
4656   else
4657     doTree = newIfxNode (condAst, trueLabel, falseLabel);
4658
4659   doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
4660
4661   /* putting it together */
4662   return newNode (NULLOP, doBody, doTree);
4663 }
4664
4665 /*-----------------------------------------------------------------*/
4666 /* createFor - creates parse tree for 'for' statement              */
4667 /*        initExpr                                                 */
4668 /*   _forcond_n:                                                   */
4669 /*        condExpr  +-> trueLabel -> _forbody_n                    */
4670 /*                  |                                              */
4671 /*                  +-> falseLabel-> _forbreak_n                   */
4672 /*   _forbody_n:                                                   */
4673 /*        statements                                               */
4674 /*   _forcontinue_n:                                               */
4675 /*        loopExpr                                                 */
4676 /*        goto _forcond_n ;                                        */
4677 /*   _forbreak_n:                                                  */
4678 /*-----------------------------------------------------------------*/
4679 ast *
4680 createFor (symbol * trueLabel, symbol * continueLabel,
4681            symbol * falseLabel, symbol * condLabel,
4682            ast * initExpr, ast * condExpr, ast * loopExpr,
4683            ast * forBody)
4684 {
4685   ast *forTree;
4686
4687   /* if loopexpression not present then we can generate it */
4688   /* the same way as a while */
4689   if (!loopExpr)
4690     return newNode (NULLOP, initExpr,
4691                     createWhile (trueLabel, continueLabel,
4692                                  falseLabel, condExpr, forBody));
4693   /* vanilla for statement */
4694   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
4695
4696   if (condExpr && !IS_IFX (condExpr))
4697     condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
4698
4699
4700   /* attach condition label to condition */
4701   condExpr = createLabel (condLabel, condExpr);
4702
4703   /* attach body label to body */
4704   forBody = createLabel (trueLabel, forBody);
4705
4706   /* attach continue to forLoop expression & attach */
4707   /* goto the forcond @ and of loopExpression       */
4708   loopExpr = createLabel (continueLabel,
4709                           newNode (NULLOP,
4710                                    loopExpr,
4711                                    newNode (GOTO,
4712                                        newAst_VALUE (symbolVal (condLabel)),
4713                                             NULL)));
4714   /* now start putting them together */
4715   forTree = newNode (NULLOP, initExpr, condExpr);
4716   forTree = newNode (NULLOP, forTree, forBody);
4717   forTree = newNode (NULLOP, forTree, loopExpr);
4718   /* finally add the break label */
4719   forTree = newNode (NULLOP, forTree,
4720                      createLabel (falseLabel, NULL));
4721   return forTree;
4722 }
4723
4724 /*-----------------------------------------------------------------*/
4725 /* createWhile - creates parse tree for while statement            */
4726 /*               the while statement will be created as follows    */
4727 /*                                                                 */
4728 /*      _while_continue_n:                                         */
4729 /*            condition_expression +-> trueLabel -> _while_boby_n  */
4730 /*                                 |                               */
4731 /*                                 +-> falseLabel -> _while_break_n */
4732 /*      _while_body_n:                                             */
4733 /*            statements                                           */
4734 /*            goto _while_continue_n                               */
4735 /*      _while_break_n:                                            */
4736 /*-----------------------------------------------------------------*/
4737 ast *
4738 createWhile (symbol * trueLabel, symbol * continueLabel,
4739              symbol * falseLabel, ast * condExpr, ast * whileBody)
4740 {
4741   ast *whileTree;
4742
4743   /* put the continue label */
4744   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
4745   condExpr = createLabel (continueLabel, condExpr);
4746   condExpr->lineno = 0;
4747
4748   /* put the body label in front of the body */
4749   whileBody = createLabel (trueLabel, whileBody);
4750   whileBody->lineno = 0;
4751   /* put a jump to continue at the end of the body */
4752   /* and put break label at the end of the body */
4753   whileBody = newNode (NULLOP,
4754                        whileBody,
4755                        newNode (GOTO,
4756                                 newAst_VALUE (symbolVal (continueLabel)),
4757                                 createLabel (falseLabel, NULL)));
4758
4759   /* put it all together */
4760   if (IS_IFX (condExpr))
4761     whileTree = condExpr;
4762   else
4763     {
4764       whileTree = newNode (IFX, condExpr, NULL);
4765       /* put the true & false labels in place */
4766       whileTree->trueLabel = trueLabel;
4767       whileTree->falseLabel = falseLabel;
4768     }
4769
4770   return newNode (NULLOP, whileTree, whileBody);
4771 }
4772
4773 /*-----------------------------------------------------------------*/
4774 /* optimizeGetHbit - get highest order bit of the expression       */
4775 /*-----------------------------------------------------------------*/
4776 ast *
4777 optimizeGetHbit (ast * tree)
4778 {
4779   int i, j;
4780   /* if this is not a bit and */
4781   if (!IS_BITAND (tree))
4782     return tree;
4783
4784   /* will look for tree of the form
4785      ( expr >> ((sizeof expr) -1) ) & 1 */
4786   if (!IS_AST_LIT_VALUE (tree->right))
4787     return tree;
4788
4789   if (AST_LIT_VALUE (tree->right) != 1)
4790     return tree;
4791
4792   if (!IS_RIGHT_OP (tree->left))
4793     return tree;
4794
4795   if (!IS_AST_LIT_VALUE (tree->left->right))
4796     return tree;
4797
4798   if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
4799       (j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
4800     return tree;
4801       
4802   /* make sure the port supports GETHBIT */
4803   if (port->hasExtBitOp
4804       && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
4805     return tree;
4806
4807   return decorateType (newNode (GETHBIT, tree->left->left, NULL), RESULT_CHECK);
4808
4809 }
4810
4811 /*-----------------------------------------------------------------*/
4812 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry     */
4813 /*-----------------------------------------------------------------*/
4814 ast *
4815 optimizeRRCRLC (ast * root)
4816 {
4817   /* will look for trees of the form
4818      (?expr << 1) | (?expr >> 7) or
4819      (?expr >> 7) | (?expr << 1) will make that
4820      into a RLC : operation ..
4821      Will also look for
4822      (?expr >> 1) | (?expr << 7) or
4823      (?expr << 7) | (?expr >> 1) will make that
4824      into a RRC operation
4825      note : by 7 I mean (number of bits required to hold the
4826      variable -1 ) */
4827   /* if the root operations is not a | operation the not */
4828   if (!IS_BITOR (root))
4829     return root;
4830
4831   /* I have to think of a better way to match patterns this sucks */
4832   /* that aside let start looking for the first case : I use a the
4833      negative check a lot to improve the efficiency */
4834   /* (?expr << 1) | (?expr >> 7) */
4835   if (IS_LEFT_OP (root->left) &&
4836       IS_RIGHT_OP (root->right))
4837     {
4838
4839       if (!SPEC_USIGN (TETYPE (root->left->left)))
4840         return root;
4841
4842       if (!IS_AST_LIT_VALUE (root->left->right) ||
4843           !IS_AST_LIT_VALUE (root->right->right))
4844         goto tryNext0;
4845
4846       /* make sure it is the same expression */
4847       if (!isAstEqual (root->left->left,
4848                        root->right->left))
4849         goto tryNext0;
4850
4851       if (AST_LIT_VALUE (root->left->right) != 1)
4852         goto tryNext0;
4853
4854       if (AST_LIT_VALUE (root->right->right) !=
4855           (getSize (TTYPE (root->left->left)) * 8 - 1))
4856         goto tryNext0;
4857
4858       /* make sure the port supports RLC */
4859       if (port->hasExtBitOp
4860           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
4861         return root;
4862
4863       /* whew got the first case : create the AST */
4864       return newNode (RLC, root->left->left, NULL);
4865     }
4866
4867 tryNext0:
4868   /* check for second case */
4869   /* (?expr >> 7) | (?expr << 1) */
4870   if (IS_LEFT_OP (root->right) &&
4871       IS_RIGHT_OP (root->left))
4872     {
4873
4874       if (!SPEC_USIGN (TETYPE (root->left->left)))
4875         return root;
4876
4877       if (!IS_AST_LIT_VALUE (root->left->right) ||
4878           !IS_AST_LIT_VALUE (root->right->right))
4879         goto tryNext1;
4880
4881       /* make sure it is the same symbol */
4882       if (!isAstEqual (root->left->left,
4883                        root->right->left))
4884         goto tryNext1;
4885
4886       if (AST_LIT_VALUE (root->right->right) != 1)
4887         goto tryNext1;
4888
4889       if (AST_LIT_VALUE (root->left->right) !=
4890           (getSize (TTYPE (root->left->left)) * 8 - 1))
4891         goto tryNext1;
4892
4893       /* make sure the port supports RLC */
4894       if (port->hasExtBitOp
4895           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
4896         return root;
4897
4898       /* whew got the first case : create the AST */
4899       return newNode (RLC, root->left->left, NULL);
4900
4901     }
4902
4903 tryNext1:
4904   /* third case for RRC */
4905   /*  (?symbol >> 1) | (?symbol << 7) */
4906   if (IS_LEFT_OP (root->right) &&
4907       IS_RIGHT_OP (root->left))
4908     {
4909
4910       if (!SPEC_USIGN (TETYPE (root->left->left)))
4911         return root;
4912
4913       if (!IS_AST_LIT_VALUE (root->left->right) ||
4914           !IS_AST_LIT_VALUE (root->right->right))
4915         goto tryNext2;
4916
4917       /* make sure it is the same symbol */
4918       if (!isAstEqual (root->left->left,
4919                        root->right->left))
4920         goto tryNext2;
4921
4922       if (AST_LIT_VALUE (root->left->right) != 1)
4923         goto tryNext2;
4924
4925       if (AST_LIT_VALUE (root->right->right) !=
4926           (getSize (TTYPE (root->left->left)) * 8 - 1))
4927         goto tryNext2;
4928
4929       /* make sure the port supports RRC */
4930       if (port->hasExtBitOp
4931           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
4932         return root;
4933
4934       /* whew got the first case : create the AST */
4935       return newNode (RRC, root->left->left, NULL);
4936
4937     }
4938 tryNext2:
4939   /* fourth and last case for now */
4940   /* (?symbol << 7) | (?symbol >> 1) */
4941   if (IS_RIGHT_OP (root->right) &&
4942       IS_LEFT_OP (root->left))
4943     {
4944
4945       if (!SPEC_USIGN (TETYPE (root->left->left)))
4946         return root;
4947
4948       if (!IS_AST_LIT_VALUE (root->left->right) ||
4949           !IS_AST_LIT_VALUE (root->right->right))
4950         return root;
4951
4952       /* make sure it is the same symbol */
4953       if (!isAstEqual (root->left->left,
4954                        root->right->left))
4955         return root;
4956
4957       if (AST_LIT_VALUE (root->right->right) != 1)
4958         return root;
4959
4960       if (AST_LIT_VALUE (root->left->right) !=
4961           (getSize (TTYPE (root->left->left)) * 8 - 1))
4962         return root;
4963
4964       /* make sure the port supports RRC */
4965       if (port->hasExtBitOp
4966           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
4967         return root;
4968
4969       /* whew got the first case : create the AST */
4970       return newNode (RRC, root->left->left, NULL);
4971
4972     }
4973
4974   /* not found return root */
4975   return root;
4976 }
4977
4978 /*-----------------------------------------------------------------*/
4979 /* optimizeSWAP :- optimize for nibble/byte/word swaps             */
4980 /*-----------------------------------------------------------------*/
4981 ast *
4982 optimizeSWAP (ast * root)
4983 {
4984   /* will look for trees of the form
4985      (?expr << 4) | (?expr >> 4) or
4986      (?expr >> 4) | (?expr << 4) will make that
4987      into a SWAP : operation ..
4988      note : by 4 I mean (number of bits required to hold the
4989      variable /2 ) */
4990   /* if the root operations is not a | operation the not */
4991   if (!IS_BITOR (root))
4992     return root;
4993
4994   /* (?expr << 4) | (?expr >> 4) */
4995   if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
4996       || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
4997     {
4998
4999       if (!SPEC_USIGN (TETYPE (root->left->left)))
5000         return root;
5001
5002       if (!IS_AST_LIT_VALUE (root->left->right) ||
5003           !IS_AST_LIT_VALUE (root->right->right))
5004         return root;
5005
5006       /* make sure it is the same expression */
5007       if (!isAstEqual (root->left->left,
5008                        root->right->left))
5009         return root;
5010
5011       if (AST_LIT_VALUE (root->left->right) !=
5012           (getSize (TTYPE (root->left->left)) * 4))
5013         return root;
5014
5015       if (AST_LIT_VALUE (root->right->right) !=
5016           (getSize (TTYPE (root->left->left)) * 4))
5017         return root;
5018
5019       /* make sure the port supports SWAP */
5020       if (port->hasExtBitOp
5021           && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5022         return root;
5023
5024       /* found it : create the AST */
5025       return newNode (SWAP, root->left->left, NULL);
5026     }
5027
5028
5029   /* not found return root */
5030   return root;
5031 }
5032
5033 /*-----------------------------------------------------------------*/
5034 /* optimizeCompare - otimizes compares for bit variables     */
5035 /*-----------------------------------------------------------------*/
5036 static ast *
5037 optimizeCompare (ast * root)
5038 {
5039   ast *optExpr = NULL;
5040   value *vleft;
5041   value *vright;
5042   unsigned int litValue;
5043
5044   /* if nothing then return nothing */
5045   if (!root)
5046     return NULL;
5047
5048   /* if not a compare op then do leaves */
5049   if (!IS_COMPARE_OP (root))
5050     {
5051       root->left = optimizeCompare (root->left);
5052       root->right = optimizeCompare (root->right);
5053       return root;
5054     }
5055
5056   /* if left & right are the same then depending
5057      of the operation do */
5058   if (isAstEqual (root->left, root->right))
5059     {
5060       switch (root->opval.op)
5061         {
5062         case '>':
5063         case '<':
5064         case NE_OP:
5065           optExpr = newAst_VALUE (constVal ("0"));
5066           break;
5067         case GE_OP:
5068         case LE_OP:
5069         case EQ_OP:
5070           optExpr = newAst_VALUE (constVal ("1"));
5071           break;
5072         }
5073
5074       return decorateType (optExpr, RESULT_CHECK);
5075     }
5076
5077   vleft = (root->left->type == EX_VALUE ?
5078            root->left->opval.val : NULL);
5079
5080   vright = (root->right->type == EX_VALUE ?
5081             root->right->opval.val : NULL);
5082
5083   /* if left is a BITVAR in BITSPACE */
5084   /* and right is a LITERAL then opt- */
5085   /* imize else do nothing       */
5086   if (vleft && vright &&
5087       IS_BITVAR (vleft->etype) &&
5088       IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5089       IS_LITERAL (vright->etype))
5090     {
5091
5092       /* if right side > 1 then comparison may never succeed */
5093       if ((litValue = (int) floatFromVal (vright)) > 1)
5094         {
5095           werror (W_BAD_COMPARE);
5096           goto noOptimize;
5097         }
5098
5099       if (litValue)
5100         {
5101           switch (root->opval.op)
5102             {
5103             case '>':           /* bit value greater than 1 cannot be */
5104               werror (W_BAD_COMPARE);
5105               goto noOptimize;
5106               break;
5107
5108             case '<':           /* bit value < 1 means 0 */
5109             case NE_OP:
5110               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5111               break;
5112
5113             case LE_OP: /* bit value <= 1 means no check */
5114               optExpr = newAst_VALUE (vright);
5115               break;
5116
5117             case GE_OP: /* bit value >= 1 means only check for = */
5118             case EQ_OP:
5119               optExpr = newAst_VALUE (vleft);
5120               break;
5121             }
5122         }
5123       else
5124         {                       /* literal is zero */
5125           switch (root->opval.op)
5126             {
5127             case '<':           /* bit value < 0 cannot be */
5128               werror (W_BAD_COMPARE);
5129               goto noOptimize;
5130               break;
5131
5132             case '>':           /* bit value > 0 means 1 */
5133             case NE_OP:
5134               optExpr = newAst_VALUE (vleft);
5135               break;
5136
5137             case LE_OP: /* bit value <= 0 means no check */
5138             case GE_OP: /* bit value >= 0 means no check */
5139               werror (W_BAD_COMPARE);
5140               goto noOptimize;
5141               break;
5142
5143             case EQ_OP: /* bit == 0 means ! of bit */
5144               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5145               break;
5146             }
5147         }
5148       return decorateType (resolveSymbols (optExpr), RESULT_CHECK);
5149     }                           /* end-of-if of BITVAR */
5150
5151 noOptimize:
5152   return root;
5153 }
5154 /*-----------------------------------------------------------------*/
5155 /* addSymToBlock : adds the symbol to the first block we find      */
5156 /*-----------------------------------------------------------------*/
5157 void 
5158 addSymToBlock (symbol * sym, ast * tree)
5159 {
5160   /* reached end of tree or a leaf */
5161   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5162     return;
5163
5164   /* found a block */
5165   if (IS_AST_OP (tree) &&
5166       tree->opval.op == BLOCK)
5167     {
5168
5169       symbol *lsym = copySymbol (sym);
5170
5171       lsym->next = AST_VALUES (tree, sym);
5172       AST_VALUES (tree, sym) = lsym;
5173       return;
5174     }
5175
5176   addSymToBlock (sym, tree->left);
5177   addSymToBlock (sym, tree->right);
5178 }
5179
5180 /*-----------------------------------------------------------------*/
5181 /* processRegParms - do processing for register parameters         */
5182 /*-----------------------------------------------------------------*/
5183 static void 
5184 processRegParms (value * args, ast * body)
5185 {
5186   while (args)
5187     {
5188       if (IS_REGPARM (args->etype))
5189         addSymToBlock (args->sym, body);
5190       args = args->next;
5191     }
5192 }
5193
5194 /*-----------------------------------------------------------------*/
5195 /* resetParmKey - resets the operandkeys for the symbols           */
5196 /*-----------------------------------------------------------------*/
5197 DEFSETFUNC (resetParmKey)
5198 {
5199   symbol *sym = item;
5200
5201   sym->key = 0;
5202   sym->defs = NULL;
5203   sym->uses = NULL;
5204   sym->remat = 0;
5205   return 1;
5206 }
5207
5208 /*-----------------------------------------------------------------*/
5209 /* createFunction - This is the key node that calls the iCode for  */
5210 /*                  generating the code for a function. Note code  */
5211 /*                  is generated function by function, later when  */
5212 /*                  add inter-procedural analysis this will change */
5213 /*-----------------------------------------------------------------*/
5214 ast *
5215 createFunction (symbol * name, ast * body)
5216 {
5217   ast *ex;
5218   symbol *csym;
5219   int stack = 0;
5220   sym_link *fetype;
5221   iCode *piCode = NULL;
5222
5223   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
5224     fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
5225
5226   /* if check function return 0 then some problem */
5227   if (checkFunction (name, NULL) == 0)
5228     return NULL;
5229
5230   /* create a dummy block if none exists */
5231   if (!body)
5232     body = newNode (BLOCK, NULL, NULL);
5233
5234   noLineno++;
5235
5236   /* check if the function name already in the symbol table */
5237   if ((csym = findSym (SymbolTab, NULL, name->name)))
5238     {
5239       name = csym;
5240       /* special case for compiler defined functions
5241          we need to add the name to the publics list : this
5242          actually means we are now compiling the compiler
5243          support routine */
5244       if (name->cdef)
5245         {
5246           addSet (&publics, name);
5247         }
5248     }
5249   else
5250     {
5251       addSymChain (name);
5252       allocVariables (name);
5253     }
5254   name->lastLine = mylineno;
5255   currFunc = name;
5256
5257   /* set the stack pointer */
5258   /* PENDING: check this for the mcs51 */
5259   stackPtr = -port->stack.direction * port->stack.call_overhead;
5260   if (IFFUNC_ISISR (name->type))
5261     stackPtr -= port->stack.direction * port->stack.isr_overhead;
5262   if (IFFUNC_ISREENT (name->type) || options.stackAuto)
5263     stackPtr -= port->stack.direction * port->stack.reent_overhead;
5264
5265   xstackPtr = -port->stack.direction * port->stack.call_overhead;
5266
5267   fetype = getSpec (name->type);        /* get the specifier for the function */
5268   /* if this is a reentrant function then */
5269   if (IFFUNC_ISREENT (name->type))
5270     reentrant++;
5271
5272   allocParms (FUNC_ARGS(name->type));   /* allocate the parameters */
5273
5274   /* do processing for parameters that are passed in registers */
5275   processRegParms (FUNC_ARGS(name->type), body);
5276
5277   /* set the stack pointer */
5278   stackPtr = 0;
5279   xstackPtr = -1;
5280
5281   /* allocate & autoinit the block variables */
5282   processBlockVars (body, &stack, ALLOCATE);
5283
5284   /* save the stack information */
5285   if (options.useXstack)
5286     name->xstack = SPEC_STAK (fetype) = stack;
5287   else
5288     name->stack = SPEC_STAK (fetype) = stack;
5289
5290   /* name needs to be mangled */
5291   SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
5292
5293   body = resolveSymbols (body); /* resolve the symbols */
5294   body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
5295                                         
5296
5297   ex = newAst_VALUE (symbolVal (name)); /* create name */
5298   ex = newNode (FUNCTION, ex, body);
5299   ex->values.args = FUNC_ARGS(name->type);
5300   ex->decorated=1;
5301   if (options.dump_tree) PA(ex);
5302   if (fatalError)
5303     {
5304       werror (E_FUNC_NO_CODE, name->name);
5305       goto skipall;
5306     }
5307
5308   /* create the node & generate intermediate code */
5309   GcurMemmap = code;
5310   codeOutFile = code->oFile;
5311   piCode = iCodeFromAst (ex);
5312
5313   if (fatalError)
5314     {
5315       werror (E_FUNC_NO_CODE, name->name);
5316       goto skipall;
5317     }
5318
5319   eBBlockFromiCode (piCode);
5320
5321   /* if there are any statics then do them */
5322   if (staticAutos)
5323     {
5324       GcurMemmap = statsg;
5325       codeOutFile = statsg->oFile;
5326       eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_CHECK)));
5327       staticAutos = NULL;
5328     }
5329
5330 skipall:
5331
5332   /* dealloc the block variables */
5333   processBlockVars (body, &stack, DEALLOCATE);
5334   outputDebugStackSymbols();
5335   /* deallocate paramaters */
5336   deallocParms (FUNC_ARGS(name->type));
5337
5338   if (IFFUNC_ISREENT (name->type))
5339     reentrant--;
5340
5341   /* we are done freeup memory & cleanup */
5342   noLineno--;
5343   if (port->reset_labelKey) labelKey = 1;
5344   name->key = 0;
5345   FUNC_HASBODY(name->type) = 1;
5346   addSet (&operKeyReset, name);
5347   applyToSet (operKeyReset, resetParmKey);
5348
5349   if (options.debug)
5350     cdbStructBlock(1);
5351
5352   cleanUpLevel (LabelTab, 0);
5353   cleanUpBlock (StructTab, 1);
5354   cleanUpBlock (TypedefTab, 1);
5355
5356   xstack->syms = NULL;
5357   istack->syms = NULL;
5358   return NULL;
5359 }
5360
5361
5362 #define INDENT(x,f) { int i ; fprintf (f, "%d:", tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
5363 /*-----------------------------------------------------------------*/
5364 /* ast_print : prints the ast (for debugging purposes)             */
5365 /*-----------------------------------------------------------------*/
5366
5367 void ast_print (ast * tree, FILE *outfile, int indent)
5368 {
5369
5370         if (!tree) return ;
5371
5372         /* can print only decorated trees */
5373         if (!tree->decorated) return;
5374
5375         /* if any child is an error | this one is an error do nothing */
5376         if (tree->isError ||
5377             (tree->left && tree->left->isError) ||
5378             (tree->right && tree->right->isError)) {
5379                 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
5380         }
5381
5382
5383         /* print the line          */
5384         /* if not block & function */
5385         if (tree->type == EX_OP &&
5386             (tree->opval.op != FUNCTION &&
5387              tree->opval.op != BLOCK &&
5388              tree->opval.op != NULLOP)) {
5389         }
5390
5391         if (tree->opval.op == FUNCTION) {
5392                 int arg=0;
5393                 value *args=FUNC_ARGS(tree->left->opval.val->type);
5394                 fprintf(outfile,"FUNCTION (%s=%p) type (",
5395                         tree->left->opval.val->name, tree);
5396                 printTypeChain (tree->left->opval.val->type->next,outfile);
5397                 fprintf(outfile,") args (");
5398                 do {
5399                   if (arg) {
5400                     fprintf (outfile, ", ");
5401                   }
5402                   printTypeChain (args ? args->type : NULL, outfile);
5403                   arg++;
5404                   args= args ? args->next : NULL;
5405                 } while (args);
5406                 fprintf(outfile,")\n");
5407                 ast_print(tree->left,outfile,indent);
5408                 ast_print(tree->right,outfile,indent);
5409                 return ;
5410         }
5411         if (tree->opval.op == BLOCK) {
5412                 symbol *decls = tree->values.sym;
5413                 INDENT(indent,outfile);
5414                 fprintf(outfile,"{\n");
5415                 while (decls) {
5416                         INDENT(indent+2,outfile);
5417                         fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
5418                                 decls->name, decls);
5419                         printTypeChain(decls->type,outfile);
5420                         fprintf(outfile,")\n");
5421
5422                         decls = decls->next;
5423                 }
5424                 ast_print(tree->right,outfile,indent+2);
5425                 INDENT(indent,outfile);
5426                 fprintf(outfile,"}\n");
5427                 return;
5428         }
5429         if (tree->opval.op == NULLOP) {
5430                 ast_print(tree->left,outfile,indent);
5431                 ast_print(tree->right,outfile,indent);
5432                 return ;
5433         }
5434         INDENT(indent,outfile);
5435
5436         /*------------------------------------------------------------------*/
5437         /*----------------------------*/
5438         /*   leaf has been reached    */
5439         /*----------------------------*/
5440         /* if this is of type value */
5441         /* just get the type        */
5442         if (tree->type == EX_VALUE) {
5443
5444                 if (IS_LITERAL (tree->opval.val->etype)) {
5445                         fprintf(outfile,"CONSTANT (%p) value = ", tree);
5446                         if (SPEC_USIGN (tree->opval.val->etype))
5447                                 fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val));
5448                         else
5449                                 fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val));
5450                         fprintf(outfile,", 0x%x, %f", (TYPE_UDWORD) floatFromVal(tree->opval.val),
5451                                                       floatFromVal(tree->opval.val));
5452                 } else if (tree->opval.val->sym) {
5453                         /* if the undefined flag is set then give error message */
5454                         if (tree->opval.val->sym->undefined) {
5455                                 fprintf(outfile,"UNDEFINED SYMBOL ");
5456                         } else {
5457                                 fprintf(outfile,"SYMBOL ");
5458                         }
5459                         fprintf(outfile,"(%s=%p)",
5460                                 tree->opval.val->sym->name,tree);
5461                 }
5462                 if (tree->ftype) {
5463                         fprintf(outfile," type (");
5464                         printTypeChain(tree->ftype,outfile);
5465                         fprintf(outfile,")\n");
5466                 } else {
5467                         fprintf(outfile,"\n");
5468                 }
5469                 return ;
5470         }
5471
5472         /* if type link for the case of cast */
5473         if (tree->type == EX_LINK) {
5474                 fprintf(outfile,"TYPENODE (%p) type = (",tree);
5475                 printTypeChain(tree->opval.lnk,outfile);
5476                 fprintf(outfile,")\n");
5477                 return ;
5478         }
5479
5480
5481         /* depending on type of operator do */
5482
5483         switch (tree->opval.op) {
5484                 /*------------------------------------------------------------------*/
5485                 /*----------------------------*/
5486                 /*        array node          */
5487                 /*----------------------------*/
5488         case '[':
5489                 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
5490                 printTypeChain(tree->ftype,outfile);
5491                 fprintf(outfile,")\n");
5492                 ast_print(tree->left,outfile,indent+2);
5493                 ast_print(tree->right,outfile,indent+2);
5494                 return;
5495
5496                 /*------------------------------------------------------------------*/
5497                 /*----------------------------*/
5498                 /*      struct/union          */
5499                 /*----------------------------*/
5500         case '.':
5501                 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
5502                 printTypeChain(tree->ftype,outfile);
5503                 fprintf(outfile,")\n");
5504                 ast_print(tree->left,outfile,indent+2);
5505                 ast_print(tree->right,outfile,indent+2);
5506                 return ;
5507
5508                 /*------------------------------------------------------------------*/
5509                 /*----------------------------*/
5510                 /*    struct/union pointer    */
5511                 /*----------------------------*/
5512         case PTR_OP:
5513                 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
5514                 printTypeChain(tree->ftype,outfile);
5515                 fprintf(outfile,")\n");
5516                 ast_print(tree->left,outfile,indent+2);
5517                 ast_print(tree->right,outfile,indent+2);
5518                 return ;
5519
5520                 /*------------------------------------------------------------------*/
5521                 /*----------------------------*/
5522                 /*  ++/-- operation           */
5523                 /*----------------------------*/
5524         case INC_OP:
5525                 if (tree->left)
5526                   fprintf(outfile,"post-");
5527                 else
5528                   fprintf(outfile,"pre-");
5529                 fprintf(outfile,"INC_OP (%p) type (",tree);
5530                 printTypeChain(tree->ftype,outfile);
5531                 fprintf(outfile,")\n");
5532                 ast_print(tree->left,outfile,indent+2); /* postincrement case */
5533                 ast_print(tree->right,outfile,indent+2); /* preincrement case */
5534                 return ;
5535
5536         case DEC_OP:
5537                 if (tree->left)
5538                   fprintf(outfile,"post-");
5539                 else
5540                   fprintf(outfile,"pre-");
5541                 fprintf(outfile,"DEC_OP (%p) type (",tree);
5542                 printTypeChain(tree->ftype,outfile);
5543                 fprintf(outfile,")\n");
5544                 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
5545                 ast_print(tree->right,outfile,indent+2); /* predecrement case */
5546                 return ;
5547
5548                 /*------------------------------------------------------------------*/
5549                 /*----------------------------*/
5550                 /*  bitwise and               */
5551                 /*----------------------------*/
5552         case '&':
5553                 if (tree->right) {
5554                         fprintf(outfile,"& (%p) type (",tree);
5555                         printTypeChain(tree->ftype,outfile);
5556                         fprintf(outfile,")\n");
5557                         ast_print(tree->left,outfile,indent+2);
5558                         ast_print(tree->right,outfile,indent+2);
5559                 } else {
5560                         fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
5561                         printTypeChain(tree->ftype,outfile);
5562                         fprintf(outfile,")\n");
5563                         ast_print(tree->left,outfile,indent+2);
5564                         ast_print(tree->right,outfile,indent+2);
5565                 }
5566                 return ;
5567                 /*----------------------------*/
5568                 /*  bitwise or                */
5569                 /*----------------------------*/
5570         case '|':
5571                 fprintf(outfile,"OR (%p) type (",tree);
5572                 printTypeChain(tree->ftype,outfile);
5573                 fprintf(outfile,")\n");
5574                 ast_print(tree->left,outfile,indent+2);
5575                 ast_print(tree->right,outfile,indent+2);
5576                 return ;
5577                 /*------------------------------------------------------------------*/
5578                 /*----------------------------*/
5579                 /*  bitwise xor               */
5580                 /*----------------------------*/
5581         case '^':
5582                 fprintf(outfile,"XOR (%p) type (",tree);
5583                 printTypeChain(tree->ftype,outfile);
5584                 fprintf(outfile,")\n");
5585                 ast_print(tree->left,outfile,indent+2);
5586                 ast_print(tree->right,outfile,indent+2);
5587                 return ;
5588
5589                 /*------------------------------------------------------------------*/
5590                 /*----------------------------*/
5591                 /*  division                  */
5592                 /*----------------------------*/
5593         case '/':
5594                 fprintf(outfile,"DIV (%p) type (",tree);
5595                 printTypeChain(tree->ftype,outfile);
5596                 fprintf(outfile,")\n");
5597                 ast_print(tree->left,outfile,indent+2);
5598                 ast_print(tree->right,outfile,indent+2);
5599                 return ;
5600                 /*------------------------------------------------------------------*/
5601                 /*----------------------------*/
5602                 /*            modulus         */
5603                 /*----------------------------*/
5604         case '%':
5605                 fprintf(outfile,"MOD (%p) type (",tree);
5606                 printTypeChain(tree->ftype,outfile);
5607                 fprintf(outfile,")\n");
5608                 ast_print(tree->left,outfile,indent+2);
5609                 ast_print(tree->right,outfile,indent+2);
5610                 return ;
5611
5612                 /*------------------------------------------------------------------*/
5613                 /*----------------------------*/
5614                 /*  address dereference       */
5615                 /*----------------------------*/
5616         case '*':                       /* can be unary  : if right is null then unary operation */
5617                 if (!tree->right) {
5618                         fprintf(outfile,"DEREF (%p) type (",tree);
5619                         printTypeChain(tree->ftype,outfile);
5620                         fprintf(outfile,")\n");
5621                         ast_print(tree->left,outfile,indent+2);
5622                         return ;
5623                 }                       
5624                 /*------------------------------------------------------------------*/
5625                 /*----------------------------*/
5626                 /*      multiplication        */
5627                 /*----------------------------*/                
5628                 fprintf(outfile,"MULT (%p) type (",tree);
5629                 printTypeChain(tree->ftype,outfile);
5630                 fprintf(outfile,")\n");
5631                 ast_print(tree->left,outfile,indent+2);
5632                 ast_print(tree->right,outfile,indent+2);
5633                 return ;
5634
5635
5636                 /*------------------------------------------------------------------*/
5637                 /*----------------------------*/
5638                 /*    unary '+' operator      */
5639                 /*----------------------------*/
5640         case '+':
5641                 /* if unary plus */
5642                 if (!tree->right) {
5643                         fprintf(outfile,"UPLUS (%p) type (",tree);
5644                         printTypeChain(tree->ftype,outfile);
5645                         fprintf(outfile,")\n");
5646                         ast_print(tree->left,outfile,indent+2);
5647                 } else {
5648                         /*------------------------------------------------------------------*/
5649                         /*----------------------------*/
5650                         /*      addition              */
5651                         /*----------------------------*/
5652                         fprintf(outfile,"ADD (%p) type (",tree);
5653                         printTypeChain(tree->ftype,outfile);
5654                         fprintf(outfile,")\n");
5655                         ast_print(tree->left,outfile,indent+2);
5656                         ast_print(tree->right,outfile,indent+2);
5657                 }
5658                 return;
5659                 /*------------------------------------------------------------------*/
5660                 /*----------------------------*/
5661                 /*      unary '-'             */
5662                 /*----------------------------*/
5663         case '-':                       /* can be unary   */
5664                 if (!tree->right) {
5665                         fprintf(outfile,"UMINUS (%p) type (",tree);
5666                         printTypeChain(tree->ftype,outfile);
5667                         fprintf(outfile,")\n");
5668                         ast_print(tree->left,outfile,indent+2);
5669                 } else {
5670                         /*------------------------------------------------------------------*/
5671                         /*----------------------------*/
5672                         /*      subtraction           */
5673                         /*----------------------------*/
5674                         fprintf(outfile,"SUB (%p) type (",tree);
5675                         printTypeChain(tree->ftype,outfile);
5676                         fprintf(outfile,")\n");
5677                         ast_print(tree->left,outfile,indent+2);
5678                         ast_print(tree->right,outfile,indent+2);
5679                 }
5680                 return;
5681                 /*------------------------------------------------------------------*/
5682                 /*----------------------------*/
5683                 /*    compliment              */
5684                 /*----------------------------*/
5685         case '~':
5686                 fprintf(outfile,"COMPL (%p) type (",tree);
5687                 printTypeChain(tree->ftype,outfile);
5688                 fprintf(outfile,")\n");
5689                 ast_print(tree->left,outfile,indent+2);
5690                 return ;
5691                 /*------------------------------------------------------------------*/
5692                 /*----------------------------*/
5693                 /*           not              */
5694                 /*----------------------------*/
5695         case '!':
5696                 fprintf(outfile,"NOT (%p) type (",tree);
5697                 printTypeChain(tree->ftype,outfile);
5698                 fprintf(outfile,")\n");
5699                 ast_print(tree->left,outfile,indent+2);
5700                 return ;
5701                 /*------------------------------------------------------------------*/
5702                 /*----------------------------*/
5703                 /*           shift            */
5704                 /*----------------------------*/
5705         case RRC:
5706                 fprintf(outfile,"RRC (%p) type (",tree);
5707                 printTypeChain(tree->ftype,outfile);
5708                 fprintf(outfile,")\n");
5709                 ast_print(tree->left,outfile,indent+2);
5710                 return ;
5711
5712         case RLC:
5713                 fprintf(outfile,"RLC (%p) type (",tree);
5714                 printTypeChain(tree->ftype,outfile);
5715                 fprintf(outfile,")\n");
5716                 ast_print(tree->left,outfile,indent+2);
5717                 return ;
5718         case SWAP:
5719                 fprintf(outfile,"SWAP (%p) type (",tree);
5720                 printTypeChain(tree->ftype,outfile);
5721                 fprintf(outfile,")\n");
5722                 ast_print(tree->left,outfile,indent+2);
5723                 return ;
5724         case GETHBIT:
5725                 fprintf(outfile,"GETHBIT (%p) type (",tree);
5726                 printTypeChain(tree->ftype,outfile);
5727                 fprintf(outfile,")\n");
5728                 ast_print(tree->left,outfile,indent+2);
5729                 return ;
5730         case LEFT_OP:
5731                 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
5732                 printTypeChain(tree->ftype,outfile);
5733                 fprintf(outfile,")\n");
5734                 ast_print(tree->left,outfile,indent+2);
5735                 ast_print(tree->right,outfile,indent+2);
5736                 return ;
5737         case RIGHT_OP:
5738                 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
5739                 printTypeChain(tree->ftype,outfile);
5740                 fprintf(outfile,")\n");
5741                 ast_print(tree->left,outfile,indent+2);
5742                 ast_print(tree->right,outfile,indent+2);
5743                 return ;
5744                 /*------------------------------------------------------------------*/
5745                 /*----------------------------*/
5746                 /*         casting            */
5747                 /*----------------------------*/
5748         case CAST:                      /* change the type   */
5749                 fprintf(outfile,"CAST (%p) from type (",tree);
5750                 printTypeChain(tree->right->ftype,outfile);
5751                 fprintf(outfile,") to type (");
5752                 printTypeChain(tree->ftype,outfile);
5753                 fprintf(outfile,")\n");
5754                 ast_print(tree->right,outfile,indent+2);
5755                 return ;
5756                 
5757         case AND_OP:
5758                 fprintf(outfile,"ANDAND (%p) type (",tree);
5759                 printTypeChain(tree->ftype,outfile);
5760                 fprintf(outfile,")\n");
5761                 ast_print(tree->left,outfile,indent+2);
5762                 ast_print(tree->right,outfile,indent+2);
5763                 return ;
5764         case OR_OP:
5765                 fprintf(outfile,"OROR (%p) type (",tree);
5766                 printTypeChain(tree->ftype,outfile);
5767                 fprintf(outfile,")\n");
5768                 ast_print(tree->left,outfile,indent+2);
5769                 ast_print(tree->right,outfile,indent+2);
5770                 return ;
5771                 
5772                 /*------------------------------------------------------------------*/
5773                 /*----------------------------*/
5774                 /*     comparison operators   */
5775                 /*----------------------------*/
5776         case '>':
5777                 fprintf(outfile,"GT(>) (%p) type (",tree);
5778                 printTypeChain(tree->ftype,outfile);
5779                 fprintf(outfile,")\n");
5780                 ast_print(tree->left,outfile,indent+2);
5781                 ast_print(tree->right,outfile,indent+2);
5782                 return ;
5783         case '<':
5784                 fprintf(outfile,"LT(<) (%p) type (",tree);
5785                 printTypeChain(tree->ftype,outfile);
5786                 fprintf(outfile,")\n");
5787                 ast_print(tree->left,outfile,indent+2);
5788                 ast_print(tree->right,outfile,indent+2);
5789                 return ;
5790         case LE_OP:
5791                 fprintf(outfile,"LE(<=) (%p) type (",tree);
5792                 printTypeChain(tree->ftype,outfile);
5793                 fprintf(outfile,")\n");
5794                 ast_print(tree->left,outfile,indent+2);
5795                 ast_print(tree->right,outfile,indent+2);
5796                 return ;
5797         case GE_OP:
5798                 fprintf(outfile,"GE(>=) (%p) type (",tree);
5799                 printTypeChain(tree->ftype,outfile);
5800                 fprintf(outfile,")\n");
5801                 ast_print(tree->left,outfile,indent+2);
5802                 ast_print(tree->right,outfile,indent+2);
5803                 return ;
5804         case EQ_OP:
5805                 fprintf(outfile,"EQ(==) (%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         case NE_OP:
5812                 fprintf(outfile,"NE(!=) (%p) type (",tree);
5813                 printTypeChain(tree->ftype,outfile);
5814                 fprintf(outfile,")\n");
5815                 ast_print(tree->left,outfile,indent+2);
5816                 ast_print(tree->right,outfile,indent+2);
5817                 /*------------------------------------------------------------------*/
5818                 /*----------------------------*/
5819                 /*             sizeof         */
5820                 /*----------------------------*/
5821         case SIZEOF:            /* evaluate wihout code generation */
5822                 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
5823                 return ;
5824
5825                 /*------------------------------------------------------------------*/
5826                 /*----------------------------*/
5827                 /* conditional operator  '?'  */
5828                 /*----------------------------*/
5829         case '?':
5830                 fprintf(outfile,"QUEST(?) (%p) type (",tree);
5831                 printTypeChain(tree->ftype,outfile);
5832                 fprintf(outfile,")\n");
5833                 ast_print(tree->left,outfile,indent+2);
5834                 ast_print(tree->right,outfile,indent+2);
5835                 return;
5836
5837         case ':':
5838                 fprintf(outfile,"COLON(:) (%p) type (",tree);
5839                 printTypeChain(tree->ftype,outfile);
5840                 fprintf(outfile,")\n");
5841                 ast_print(tree->left,outfile,indent+2);
5842                 ast_print(tree->right,outfile,indent+2);
5843                 return ;
5844
5845                 /*------------------------------------------------------------------*/
5846                 /*----------------------------*/
5847                 /*    assignment operators    */
5848                 /*----------------------------*/
5849         case MUL_ASSIGN:
5850                 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
5851                 printTypeChain(tree->ftype,outfile);
5852                 fprintf(outfile,")\n");
5853                 ast_print(tree->left,outfile,indent+2);
5854                 ast_print(tree->right,outfile,indent+2);
5855                 return;
5856         case DIV_ASSIGN:
5857                 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
5858                 printTypeChain(tree->ftype,outfile);
5859                 fprintf(outfile,")\n");
5860                 ast_print(tree->left,outfile,indent+2);
5861                 ast_print(tree->right,outfile,indent+2);
5862                 return;
5863         case AND_ASSIGN:
5864                 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
5865                 printTypeChain(tree->ftype,outfile);
5866                 fprintf(outfile,")\n");
5867                 ast_print(tree->left,outfile,indent+2);
5868                 ast_print(tree->right,outfile,indent+2);
5869                 return;
5870         case OR_ASSIGN:
5871                 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
5872                 printTypeChain(tree->ftype,outfile);
5873                 fprintf(outfile,")\n");
5874                 ast_print(tree->left,outfile,indent+2);
5875                 ast_print(tree->right,outfile,indent+2);
5876                 return;
5877         case XOR_ASSIGN:
5878                 fprintf(outfile,"XORASS(^=) (%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         case RIGHT_ASSIGN:
5885                 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
5886                 printTypeChain(tree->ftype,outfile);
5887                 fprintf(outfile,")\n");
5888                 ast_print(tree->left,outfile,indent+2);
5889                 ast_print(tree->right,outfile,indent+2);
5890                 return;
5891         case LEFT_ASSIGN:
5892                 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
5893                 printTypeChain(tree->ftype,outfile);
5894                 fprintf(outfile,")\n");
5895                 ast_print(tree->left,outfile,indent+2);
5896                 ast_print(tree->right,outfile,indent+2);
5897                 return;
5898                 /*------------------------------------------------------------------*/
5899                 /*----------------------------*/
5900                 /*    -= operator             */
5901                 /*----------------------------*/
5902         case SUB_ASSIGN:
5903                 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
5904                 printTypeChain(tree->ftype,outfile);
5905                 fprintf(outfile,")\n");
5906                 ast_print(tree->left,outfile,indent+2);
5907                 ast_print(tree->right,outfile,indent+2);
5908                 return;
5909                 /*------------------------------------------------------------------*/
5910                 /*----------------------------*/
5911                 /*          += operator       */
5912                 /*----------------------------*/
5913         case ADD_ASSIGN:
5914                 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
5915                 printTypeChain(tree->ftype,outfile);
5916                 fprintf(outfile,")\n");
5917                 ast_print(tree->left,outfile,indent+2);
5918                 ast_print(tree->right,outfile,indent+2);
5919                 return;
5920                 /*------------------------------------------------------------------*/
5921                 /*----------------------------*/
5922                 /*      straight assignemnt   */
5923                 /*----------------------------*/
5924         case '=':
5925                 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
5926                 printTypeChain(tree->ftype,outfile);
5927                 fprintf(outfile,")\n");
5928                 ast_print(tree->left,outfile,indent+2);
5929                 ast_print(tree->right,outfile,indent+2);
5930                 return;     
5931                 /*------------------------------------------------------------------*/
5932                 /*----------------------------*/
5933                 /*      comma operator        */
5934                 /*----------------------------*/
5935         case ',':
5936                 fprintf(outfile,"COMMA(,) (%p) type (",tree);
5937                 printTypeChain(tree->ftype,outfile);
5938                 fprintf(outfile,")\n");
5939                 ast_print(tree->left,outfile,indent+2);
5940                 ast_print(tree->right,outfile,indent+2);
5941                 return;
5942                 /*------------------------------------------------------------------*/
5943                 /*----------------------------*/
5944                 /*       function call        */
5945                 /*----------------------------*/
5946         case CALL:
5947         case PCALL:
5948                 fprintf(outfile,"CALL (%p) type (",tree);
5949                 printTypeChain(tree->ftype,outfile);
5950                 fprintf(outfile,")\n");
5951                 ast_print(tree->left,outfile,indent+2);
5952                 ast_print(tree->right,outfile,indent+2);
5953                 return;
5954         case PARAM:
5955                 fprintf(outfile,"PARMS\n");
5956                 ast_print(tree->left,outfile,indent+2);
5957                 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
5958                         ast_print(tree->right,outfile,indent+2);
5959                 }
5960                 return ;
5961                 /*------------------------------------------------------------------*/
5962                 /*----------------------------*/
5963                 /*     return statement       */
5964                 /*----------------------------*/
5965         case RETURN:
5966                 fprintf(outfile,"RETURN (%p) type (",tree);
5967                 if (tree->right) {
5968                     printTypeChain(tree->right->ftype,outfile);
5969                 }
5970                 fprintf(outfile,")\n");
5971                 ast_print(tree->right,outfile,indent+2);
5972                 return ;
5973                 /*------------------------------------------------------------------*/
5974                 /*----------------------------*/
5975                 /*     label statement        */
5976                 /*----------------------------*/
5977         case LABEL :
5978                 fprintf(outfile,"LABEL (%p)\n",tree);
5979                 ast_print(tree->left,outfile,indent+2);
5980                 ast_print(tree->right,outfile,indent);
5981                 return;
5982                 /*------------------------------------------------------------------*/
5983                 /*----------------------------*/
5984                 /*     switch statement       */
5985                 /*----------------------------*/
5986         case SWITCH:
5987                 {
5988                         value *val;
5989                         fprintf(outfile,"SWITCH (%p) ",tree);
5990                         ast_print(tree->left,outfile,0);
5991                         for (val = tree->values.switchVals.swVals; val ; val = val->next) {
5992                                 INDENT(indent+2,outfile);
5993                                 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
5994                                         (int) floatFromVal(val),
5995                                         tree->values.switchVals.swNum,
5996                                         (int) floatFromVal(val));
5997                         }
5998                         ast_print(tree->right,outfile,indent);
5999                 }
6000                 return ;
6001                 /*------------------------------------------------------------------*/
6002                 /*----------------------------*/
6003                 /* ifx Statement              */
6004                 /*----------------------------*/
6005         case IFX:
6006                 fprintf(outfile,"IF (%p) \n",tree);
6007                 ast_print(tree->left,outfile,indent+2);
6008                 if (tree->trueLabel) {
6009                         INDENT(indent+2,outfile);
6010                         fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
6011                 }
6012                 if (tree->falseLabel) {
6013                         INDENT(indent+2,outfile);
6014                         fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
6015                 }
6016                 ast_print(tree->right,outfile,indent+2);
6017                 return ;
6018                 /*----------------------------*/
6019                 /* goto Statement              */
6020                 /*----------------------------*/
6021         case GOTO:
6022                 fprintf(outfile,"GOTO (%p) \n",tree);
6023                 ast_print(tree->left,outfile,indent+2);
6024                 fprintf(outfile,"\n");
6025                 return ;
6026                 /*------------------------------------------------------------------*/
6027                 /*----------------------------*/
6028                 /* for Statement              */
6029                 /*----------------------------*/
6030         case FOR:
6031                 fprintf(outfile,"FOR (%p) \n",tree);
6032                 if (AST_FOR( tree, initExpr)) {
6033                         INDENT(indent+2,outfile);
6034                         fprintf(outfile,"INIT EXPR ");
6035                         ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
6036                 }
6037                 if (AST_FOR( tree, condExpr)) {
6038                         INDENT(indent+2,outfile);
6039                         fprintf(outfile,"COND EXPR ");
6040                         ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
6041                 }
6042                 if (AST_FOR( tree, loopExpr)) {
6043                         INDENT(indent+2,outfile);
6044                         fprintf(outfile,"LOOP EXPR ");
6045                         ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
6046                 }
6047                 fprintf(outfile,"FOR LOOP BODY \n");
6048                 ast_print(tree->left,outfile,indent+2);
6049                 return ;
6050         case CRITICAL:
6051                 fprintf(outfile,"CRITICAL (%p) \n",tree);
6052                 ast_print(tree->left,outfile,indent+2);
6053         default:
6054             return ;
6055         }
6056 }
6057
6058 void PA(ast *t)
6059 {
6060         ast_print(t,stdout,0);
6061 }
6062
6063
6064
6065 /*-----------------------------------------------------------------*/
6066 /* astErrors : returns non-zero if errors present in tree          */
6067 /*-----------------------------------------------------------------*/
6068 int astErrors(ast *t)
6069 {
6070   int errors=0;
6071   
6072   if (t)
6073     {
6074       if (t->isError)
6075         errors++;
6076   
6077       if (t->type == EX_VALUE
6078           && t->opval.val->sym
6079           && t->opval.val->sym->undefined)
6080         errors++;
6081
6082       errors += astErrors(t->left);
6083       errors += astErrors(t->right);
6084     }
6085     
6086   return errors;
6087 }