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