* src/SDCCast.c (decorateType),
[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       return tree;
2813
2814       /*------------------------------------------------------------------*/
2815       /*----------------------------*/
2816       /*    unary '+' operator      */
2817       /*----------------------------*/
2818     case '+':
2819       /* if unary plus */
2820       if (!tree->right)
2821         {
2822           if (!IS_ARITHMETIC (LTYPE (tree)))
2823             {
2824               werror (E_UNARY_OP, '+');
2825               goto errorTreeReturn;
2826             }
2827
2828           /* if left is a literal then do it */
2829           if (IS_LITERAL (LTYPE (tree)))
2830             {
2831               tree->type = EX_VALUE;
2832               tree->opval.val = valFromType (LETYPE (tree));
2833               tree->left = NULL;
2834               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
2835               return tree;
2836             }
2837           LRVAL (tree) = 1;
2838           COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
2839           return tree;
2840         }
2841
2842       /*------------------------------------------------------------------*/
2843       /*----------------------------*/
2844       /*      addition              */
2845       /*----------------------------*/
2846
2847       /* this is not a unary operation */
2848       /* if both pointers then problem */
2849       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
2850           (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
2851         {
2852           werror (E_PTR_PLUS_PTR);
2853           goto errorTreeReturn;
2854         }
2855
2856       if (!IS_ARITHMETIC (LTYPE (tree)) &&
2857           !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
2858         {
2859           werror (E_PLUS_INVALID, "+");
2860           goto errorTreeReturn;
2861         }
2862
2863       if (!IS_ARITHMETIC (RTYPE (tree)) &&
2864           !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
2865         {
2866           werror (E_PLUS_INVALID, "+");
2867           goto errorTreeReturn;
2868         }
2869       /* if they are both literal then */
2870       /* rewrite the tree */
2871       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2872         {
2873           tree->type = EX_VALUE;
2874           tree->opval.val = valPlus (valFromType (LETYPE (tree)),
2875                                      valFromType (RETYPE (tree)));
2876           tree->right = tree->left = NULL;
2877           TETYPE (tree) = getSpec (TTYPE (tree) =
2878                                    tree->opval.val->type);
2879           return tree;
2880         }
2881
2882       /* if the right is a pointer or left is a literal
2883          xchange left & right */
2884       if (IS_ARRAY (RTYPE (tree)) ||
2885           IS_PTR (RTYPE (tree)) ||
2886           IS_LITERAL (LTYPE (tree)))
2887         {
2888           ast *tTree = tree->left;
2889           tree->left = tree->right;
2890           tree->right = tTree;
2891         }
2892
2893       /* if right is a literal and */
2894       /* left is also an addition/subtraction with a literal then */
2895       /* rearrange the tree */
2896       if (IS_LITERAL (RTYPE (tree)))
2897         {
2898           ast *litTree, *parent;
2899           litTree = searchLitOp (tree, &parent, "+-");
2900           if (litTree)
2901             {
2902               if (litTree->opval.op == '+')
2903                 {
2904                   /* foo_aa */
2905                   ast *tTree = litTree->left;
2906                   litTree->left = tree->right;
2907                   tree->right = tree->left;
2908                   tree->left = tTree;
2909                 }
2910               else if (litTree->opval.op == '-')
2911                 {
2912                   if (IS_LITERAL (RTYPE (litTree)))
2913                     {
2914                       /* foo_asr */
2915                       ast *tTree = litTree->left;
2916                       litTree->left = tree->right;
2917                       tree->right = tTree;
2918                     }
2919                   else
2920                     {
2921                       /* foo_asl */
2922                       ast *tTree = litTree->right;
2923                       litTree->right = tree->right;
2924                       tree->right = tTree;
2925                       litTree->opval.op = '+';
2926                       tree->opval.op = '-';
2927                     }
2928                 }
2929               decorateType (parent);
2930             }
2931         }
2932
2933       LRVAL (tree) = RRVAL (tree) = 1;
2934       /* if the left is a pointer */
2935       if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
2936         TETYPE (tree) = getSpec (TTYPE (tree) =
2937                                  LTYPE (tree));
2938       else
2939         TETYPE (tree) = getSpec (TTYPE (tree) =
2940                                  computeType (LTYPE (tree),
2941                                               RTYPE (tree),
2942                                               FALSE));
2943       return tree;
2944
2945       /*------------------------------------------------------------------*/
2946       /*----------------------------*/
2947       /*      unary '-'             */
2948       /*----------------------------*/
2949     case '-':                   /* can be unary   */
2950       /* if right is null then unary */
2951       if (!tree->right)
2952         {
2953
2954           if (!IS_ARITHMETIC (LTYPE (tree)))
2955             {
2956               werror (E_UNARY_OP, tree->opval.op);
2957               goto errorTreeReturn;
2958             }
2959
2960           /* if left is a literal then do it */
2961           if (IS_LITERAL (LTYPE (tree)))
2962             {
2963               tree->type = EX_VALUE;
2964               tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
2965               tree->left = NULL;
2966               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
2967               SPEC_USIGN(TETYPE(tree)) = 0;
2968               return tree;
2969             }
2970           LRVAL (tree) = 1;
2971           TETYPE(tree) = getSpec (TTYPE (tree) = LTYPE (tree));
2972           return tree;
2973         }
2974
2975       /*------------------------------------------------------------------*/
2976       /*----------------------------*/
2977       /*    subtraction             */
2978       /*----------------------------*/
2979
2980       if (!(IS_PTR (LTYPE (tree)) ||
2981             IS_ARRAY (LTYPE (tree)) ||
2982             IS_ARITHMETIC (LTYPE (tree))))
2983         {
2984           werror (E_PLUS_INVALID, "-");
2985           goto errorTreeReturn;
2986         }
2987
2988       if (!(IS_PTR (RTYPE (tree)) ||
2989             IS_ARRAY (RTYPE (tree)) ||
2990             IS_ARITHMETIC (RTYPE (tree))))
2991         {
2992           werror (E_PLUS_INVALID, "-");
2993           goto errorTreeReturn;
2994         }
2995
2996       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
2997           !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
2998             IS_INTEGRAL (RTYPE (tree))))
2999         {
3000           werror (E_PLUS_INVALID, "-");
3001           goto errorTreeReturn;
3002         }
3003
3004       /* if they are both literal then */
3005       /* rewrite the tree */
3006       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3007         {
3008           tree->type = EX_VALUE;
3009           tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3010                                       valFromType (RETYPE (tree)));
3011           tree->right = tree->left = NULL;
3012           TETYPE (tree) = getSpec (TTYPE (tree) =
3013                                    tree->opval.val->type);
3014           return tree;
3015         }
3016
3017       /* if the left & right are equal then zero */
3018       if (isAstEqual (tree->left, tree->right))
3019         {
3020           tree->type = EX_VALUE;
3021           tree->left = tree->right = NULL;
3022           tree->opval.val = constVal ("0");
3023           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3024           return tree;
3025         }
3026
3027       /* if both of them are pointers or arrays then */
3028       /* the result is going to be an integer        */
3029       if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3030           (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3031         TETYPE (tree) = TTYPE (tree) = newIntLink ();
3032       else
3033         /* if only the left is a pointer */
3034         /* then result is a pointer      */
3035       if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3036         TETYPE (tree) = getSpec (TTYPE (tree) =
3037                                  LTYPE (tree));
3038       else
3039         TETYPE (tree) = getSpec (TTYPE (tree) =
3040                                  computeType (LTYPE (tree),
3041                                               RTYPE (tree),
3042                                               FALSE));
3043
3044       LRVAL (tree) = RRVAL (tree) = 1;
3045
3046       /* if right is a literal and */
3047       /* left is also an addition/subtraction with a literal then */
3048       /* rearrange the tree */
3049       if (IS_LITERAL (RTYPE (tree))
3050           /* avoid infinite loop */
3051           && (TYPE_UDWORD) floatFromVal (tree->right->opval.val) != 0)
3052         {
3053           ast *litTree, *litParent;
3054           litTree = searchLitOp (tree, &litParent, "+-");
3055           if (litTree)
3056             {
3057               if (litTree->opval.op == '+')
3058                 {
3059                   /* foo_sa */
3060                   litTree->right = newNode ('-', litTree->right, tree->right);
3061                   litTree->right->lineno = tree->lineno;
3062
3063                   tree->right->opval.val = constVal ("0");
3064                 }
3065               else if (litTree->opval.op == '-')
3066                 {
3067                   if (IS_LITERAL (RTYPE (litTree)))
3068                     {
3069                       /* foo_ssr */
3070                       litTree->right = newNode ('+', tree->right, litTree->right);
3071                       litTree->right->lineno = tree->lineno;
3072
3073                       tree->right->opval.val = constVal ("0");
3074                     }
3075                   else
3076                     {
3077                       /* foo_ssl */
3078                       ast *tTree = litTree->right;
3079                       litTree->right = tree->right;
3080                       tree->right = tTree;
3081                     }
3082                 }
3083               decorateType (litParent);
3084             }
3085         }
3086       return tree;
3087
3088       /*------------------------------------------------------------------*/
3089       /*----------------------------*/
3090       /*    complement              */
3091       /*----------------------------*/
3092     case '~':
3093       /* can be only integral type */
3094       if (!IS_INTEGRAL (LTYPE (tree)))
3095         {
3096           werror (E_UNARY_OP, tree->opval.op);
3097           goto errorTreeReturn;
3098         }
3099
3100       /* if left is a literal then do it */
3101       if (IS_LITERAL (LTYPE (tree)))
3102         {
3103           tree->type = EX_VALUE;
3104           tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3105           tree->left = NULL;
3106           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3107           return tree;
3108         }
3109       LRVAL (tree) = 1;
3110       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3111       return tree;
3112
3113       /*------------------------------------------------------------------*/
3114       /*----------------------------*/
3115       /*           not              */
3116       /*----------------------------*/
3117     case '!':
3118       /* can be pointer */
3119       if (!IS_ARITHMETIC (LTYPE (tree)) &&
3120           !IS_PTR (LTYPE (tree)) &&
3121           !IS_ARRAY (LTYPE (tree)))
3122         {
3123           werror (E_UNARY_OP, tree->opval.op);
3124           goto errorTreeReturn;
3125         }
3126
3127       /* if left is a literal then do it */
3128       if (IS_LITERAL (LTYPE (tree)))
3129         {
3130           tree->type = EX_VALUE;
3131           tree->opval.val = valNot (valFromType (LETYPE (tree)));
3132           tree->left = NULL;
3133           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3134           return tree;
3135         }
3136       LRVAL (tree) = 1;
3137       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3138       return tree;
3139
3140       /*------------------------------------------------------------------*/
3141       /*----------------------------*/
3142       /*           shift            */
3143       /*----------------------------*/
3144     case RRC:
3145     case RLC:
3146     case SWAP:
3147       TTYPE (tree) = LTYPE (tree);
3148       TETYPE (tree) = LETYPE (tree);
3149       return tree;
3150
3151     case GETHBIT:
3152       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3153       return tree;
3154
3155     case LEFT_OP:
3156     case RIGHT_OP:
3157       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3158         {
3159           werror (E_SHIFT_OP_INVALID);
3160           werror (W_CONTINUE, "left & right types are ");
3161           printTypeChain (LTYPE (tree), stderr);
3162           fprintf (stderr, ",");
3163           printTypeChain (RTYPE (tree), stderr);
3164           fprintf (stderr, "\n");
3165           goto errorTreeReturn;
3166         }
3167
3168       /* if they are both literal then */
3169       /* rewrite the tree */
3170       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3171         {
3172           tree->type = EX_VALUE;
3173           tree->opval.val = valShift (valFromType (LETYPE (tree)),
3174                                       valFromType (RETYPE (tree)),
3175                                       (tree->opval.op == LEFT_OP ? 1 : 0));
3176           tree->right = tree->left = NULL;
3177           TETYPE (tree) = getSpec (TTYPE (tree) =
3178                                    tree->opval.val->type);
3179           return tree;
3180         }
3181
3182       LRVAL (tree) = RRVAL (tree) = 1;
3183       if (tree->opval.op == LEFT_OP)
3184         {
3185           /* promote char to int */
3186           TETYPE (tree) = getSpec (TTYPE (tree) =
3187                                    computeType (LTYPE (tree),
3188                                                 LTYPE (tree), /* no, not RTYPE! */
3189                                                 TRUE));
3190         }
3191       else /* RIGHT_OP */
3192         {
3193           /* no promotion necessary */
3194           TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3195           if (IS_LITERAL (TTYPE (tree)))
3196             SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3197         }
3198
3199       /* if only the right side is a literal & we are
3200          shifting more than size of the left operand then zero */
3201       if (IS_LITERAL (RTYPE (tree)) &&
3202           ((TYPE_UDWORD) floatFromVal (valFromType (RETYPE (tree)))) >=
3203           (getSize (TETYPE (tree)) * 8))
3204         {
3205           if (tree->opval.op==LEFT_OP ||
3206               (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3207             {
3208               lineno=tree->lineno;
3209               werror (W_SHIFT_CHANGED,
3210                       (tree->opval.op == LEFT_OP ? "left" : "right"));
3211               tree->type = EX_VALUE;
3212               tree->left = tree->right = NULL;
3213               tree->opval.val = constVal ("0");
3214               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3215               return tree;
3216             }
3217         }
3218
3219       return tree;
3220
3221       /*------------------------------------------------------------------*/
3222       /*----------------------------*/
3223       /*         casting            */
3224       /*----------------------------*/
3225     case CAST:                  /* change the type   */
3226       /* cannot cast to an aggregate type */
3227       if (IS_AGGREGATE (LTYPE (tree)))
3228         {
3229           werror (E_CAST_ILLEGAL);
3230           goto errorTreeReturn;
3231         }
3232
3233       /* make sure the type is complete and sane */
3234       checkTypeSanity(LETYPE(tree), "(cast)");
3235
3236 #if 0
3237       /* if the right is a literal replace the tree */
3238       if (IS_LITERAL (RETYPE (tree))) {
3239               if (!IS_PTR (LTYPE (tree))) {
3240                       tree->type = EX_VALUE;
3241                       tree->opval.val =
3242                               valCastLiteral (LTYPE (tree),
3243                                               floatFromVal (valFromType (RETYPE (tree))));
3244                       tree->left = NULL;
3245                       tree->right = NULL;
3246                       TTYPE (tree) = tree->opval.val->type;
3247                       tree->values.literalFromCast = 1;
3248               } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3249                          ((int)floatFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */  {
3250                       sym_link *rest = LTYPE(tree)->next;
3251                       werror(W_LITERAL_GENERIC);
3252                       TTYPE(tree) = newLink(DECLARATOR);
3253                       DCL_TYPE(TTYPE(tree)) = FPOINTER;
3254                       TTYPE(tree)->next = rest;
3255                       tree->left->opval.lnk = TTYPE(tree);
3256                       LRVAL (tree) = 1;
3257               } else {
3258                       TTYPE (tree) = LTYPE (tree);
3259                       LRVAL (tree) = 1;
3260               }
3261       } else {
3262               TTYPE (tree) = LTYPE (tree);
3263               LRVAL (tree) = 1;
3264       }
3265 #else
3266 #if 0 // this is already checked, now this could be explicit
3267       /* if pointer to struct then check names */
3268       if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3269           IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3270           strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3271         {
3272           werror(W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3273                  SPEC_STRUCT(LETYPE(tree))->tag);
3274         }
3275 #endif
3276       if (IS_ADDRESS_OF_OP(tree->right)
3277           && IS_AST_SYM_VALUE (tree->right->left)
3278           && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3279
3280         tree->type = EX_VALUE;
3281         tree->opval.val =
3282           valCastLiteral (LTYPE (tree),
3283                           SPEC_ADDR (AST_SYMBOL (tree->right->left)->etype));
3284         TTYPE (tree) = tree->opval.val->type;
3285         TETYPE (tree) = getSpec (TTYPE (tree));
3286         tree->left = NULL;
3287         tree->right = NULL;
3288         tree->values.literalFromCast = 1;
3289         return tree;
3290       }
3291
3292       /* handle offsetof macro:            */
3293       /* #define offsetof(TYPE, MEMBER) \  */
3294       /* ((unsigned) &((TYPE *)0)->MEMBER) */
3295       if (IS_ADDRESS_OF_OP(tree->right)
3296           && IS_AST_OP (tree->right->left)
3297           && tree->right->left->opval.op == PTR_OP
3298           && IS_AST_OP (tree->right->left->left)
3299           && tree->right->left->left->opval.op == CAST
3300           && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3301
3302         symbol *element = getStructElement (
3303           SPEC_STRUCT (LETYPE(tree->right->left)),
3304           AST_SYMBOL(tree->right->left->right)
3305         );
3306
3307         if (element) {
3308           tree->type = EX_VALUE;
3309           tree->opval.val = valCastLiteral (
3310             LTYPE (tree),
3311             element->offset
3312             + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
3313           );
3314
3315           TTYPE (tree) = tree->opval.val->type;
3316           TETYPE (tree) = getSpec (TTYPE (tree));
3317           tree->left = NULL;
3318           tree->right = NULL;
3319           return tree;
3320         }
3321       }
3322
3323       /* if the right is a literal replace the tree */
3324       if (IS_LITERAL (RETYPE (tree))) {
3325         if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3326           /* rewrite      (type *)litaddr
3327              as           &temp
3328              and define   type at litaddr temp
3329              (but only if type's storage class is not generic)
3330           */
3331           ast *newTree = newNode ('&', NULL, NULL);
3332           symbol *sym;
3333
3334           TTYPE (newTree) = LTYPE (tree);
3335           TETYPE (newTree) = getSpec(LTYPE (tree));
3336
3337           /* define a global symbol at the casted address*/
3338           sym = newSymbol(genSymName (0), 0);
3339           sym->type = LTYPE (tree)->next;
3340           if (!sym->type)
3341             sym->type = newLink (V_VOID);
3342           sym->etype = getSpec(sym->type);
3343           SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
3344           sym->lineDef = tree->lineno;
3345           sym->cdef = 1;
3346           sym->isref = 1;
3347           SPEC_STAT (sym->etype) = 1;
3348           SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
3349           SPEC_ABSA(sym->etype) = 1;
3350           addSym (SymbolTab, sym, sym->name, 0, 0, 0);
3351           allocGlobal (sym);
3352
3353           newTree->left = newAst_VALUE(symbolVal(sym));
3354           newTree->left->lineno = tree->lineno;
3355           LTYPE (newTree) = sym->type;
3356           LETYPE (newTree) = sym->etype;
3357           LLVAL (newTree) = 1;
3358           LRVAL (newTree) = 0;
3359           TLVAL (newTree) = 1;
3360           return newTree;
3361         }
3362         if (!IS_PTR (LTYPE (tree))) {
3363           tree->type = EX_VALUE;
3364           tree->opval.val =
3365           valCastLiteral (LTYPE (tree),
3366                           floatFromVal (valFromType (RTYPE (tree))));
3367           TTYPE (tree) = tree->opval.val->type;
3368           tree->left = NULL;
3369           tree->right = NULL;
3370           tree->values.literalFromCast = 1;
3371           TETYPE (tree) = getSpec (TTYPE (tree));
3372           return tree;
3373         }
3374       }
3375       TTYPE (tree) = LTYPE (tree);
3376       LRVAL (tree) = 1;
3377
3378 #endif
3379       TETYPE (tree) = getSpec (TTYPE (tree));
3380
3381       return tree;
3382
3383       /*------------------------------------------------------------------*/
3384       /*----------------------------*/
3385       /*       logical &&, ||       */
3386       /*----------------------------*/
3387     case AND_OP:
3388     case OR_OP:
3389       /* each must me arithmetic type or be a pointer */
3390       if (!IS_PTR (LTYPE (tree)) &&
3391           !IS_ARRAY (LTYPE (tree)) &&
3392           !IS_INTEGRAL (LTYPE (tree)))
3393         {
3394           werror (E_COMPARE_OP);
3395           goto errorTreeReturn;
3396         }
3397
3398       if (!IS_PTR (RTYPE (tree)) &&
3399           !IS_ARRAY (RTYPE (tree)) &&
3400           !IS_INTEGRAL (RTYPE (tree)))
3401         {
3402           werror (E_COMPARE_OP);
3403           goto errorTreeReturn;
3404         }
3405       /* if they are both literal then */
3406       /* rewrite the tree */
3407       if (IS_LITERAL (RTYPE (tree)) &&
3408           IS_LITERAL (LTYPE (tree)))
3409         {
3410           tree->type = EX_VALUE;
3411           tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
3412                                            valFromType (RTYPE (tree)),
3413                                            tree->opval.op);
3414           tree->right = tree->left = NULL;
3415           TETYPE (tree) = getSpec (TTYPE (tree) =
3416                                    tree->opval.val->type);
3417           return tree;
3418         }
3419       LRVAL (tree) = RRVAL (tree) = 1;
3420       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3421       return tree;
3422
3423       /*------------------------------------------------------------------*/
3424       /*----------------------------*/
3425       /*     comparison operators   */
3426       /*----------------------------*/
3427     case '>':
3428     case '<':
3429     case LE_OP:
3430     case GE_OP:
3431     case EQ_OP:
3432     case NE_OP:
3433       {
3434         ast *lt = optimizeCompare (tree);
3435
3436         if (tree != lt)
3437           return lt;
3438       }
3439
3440       /* if they are pointers they must be castable */
3441       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
3442         {
3443           if (tree->opval.op==EQ_OP &&
3444               !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
3445             // we cannot cast a gptr to a !gptr: switch the leaves
3446             struct ast *s=tree->left;
3447             tree->left=tree->right;
3448             tree->right=s;
3449           }
3450           if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3451             {
3452               werror (E_COMPARE_OP);
3453               fprintf (stderr, "comparing type ");
3454               printTypeChain (LTYPE (tree), stderr);
3455               fprintf (stderr, "to type ");
3456               printTypeChain (RTYPE (tree), stderr);
3457               fprintf (stderr, "\n");
3458               goto errorTreeReturn;
3459             }
3460         }
3461       /* else they should be promotable to one another */
3462       else
3463         {
3464           if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
3465                 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
3466
3467             if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3468               {
3469                 werror (E_COMPARE_OP);
3470                 fprintf (stderr, "comparing type ");
3471                 printTypeChain (LTYPE (tree), stderr);
3472                 fprintf (stderr, "to type ");
3473                 printTypeChain (RTYPE (tree), stderr);
3474                 fprintf (stderr, "\n");
3475                 goto errorTreeReturn;
3476               }
3477         }
3478       /* if unsigned value < 0  then always false */
3479       /* if (unsigned value) > 0 then (unsigned value) */
3480       if (SPEC_USIGN(LETYPE(tree)) && IS_LITERAL(RTYPE(tree))  &&
3481           ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0)
3482         {
3483           if (tree->opval.op == '<')
3484             {
3485               return tree->right;
3486             }
3487           if (tree->opval.op == '>')
3488             {
3489               return tree->left;
3490             }
3491         }
3492       /* if they are both literal then */
3493       /* rewrite the tree */
3494       if (IS_LITERAL (RTYPE (tree)) &&
3495           IS_LITERAL (LTYPE (tree)))
3496         {
3497           tree->type = EX_VALUE;
3498           tree->opval.val = valCompare (valFromType (LETYPE (tree)),
3499                                         valFromType (RETYPE (tree)),
3500                                         tree->opval.op);
3501           tree->right = tree->left = NULL;
3502           TETYPE (tree) = getSpec (TTYPE (tree) =
3503                                    tree->opval.val->type);
3504           return tree;
3505         }
3506       LRVAL (tree) = RRVAL (tree) = 1;
3507       TTYPE (tree) = TETYPE (tree) = newCharLink ();
3508       return tree;
3509
3510       /*------------------------------------------------------------------*/
3511       /*----------------------------*/
3512       /*             sizeof         */
3513       /*----------------------------*/
3514     case SIZEOF:                /* evaluate wihout code generation */
3515       /* change the type to a integer */
3516       tree->type = EX_VALUE;
3517       SNPRINTF(buffer, sizeof(buffer), "%d", (getSize (tree->right->ftype)));
3518       tree->opval.val = constVal (buffer);
3519       tree->right = tree->left = NULL;
3520       TETYPE (tree) = getSpec (TTYPE (tree) =
3521                                tree->opval.val->type);
3522       return tree;
3523
3524       /*------------------------------------------------------------------*/
3525       /*----------------------------*/
3526       /*             typeof         */
3527       /*----------------------------*/
3528     case TYPEOF:
3529         /* return typeof enum value */
3530         tree->type = EX_VALUE;
3531         {
3532             int typeofv = 0;
3533             if (IS_SPEC(tree->right->ftype)) {
3534                 switch (SPEC_NOUN(tree->right->ftype)) {
3535                 case V_INT:
3536                     if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
3537                     else typeofv = TYPEOF_INT;
3538                     break;
3539                 case V_FLOAT:
3540                     typeofv = TYPEOF_FLOAT;
3541                     break;
3542                 case V_CHAR:
3543                     typeofv = TYPEOF_CHAR;
3544                     break;
3545                 case V_VOID:
3546                     typeofv = TYPEOF_VOID;
3547                     break;
3548                 case V_STRUCT:
3549                     typeofv = TYPEOF_STRUCT;
3550                     break;
3551                 case V_BITFIELD:
3552                     typeofv = TYPEOF_BITFIELD;
3553                     break;
3554                 case V_BIT:
3555                     typeofv = TYPEOF_BIT;
3556                     break;
3557                 case V_SBIT:
3558                     typeofv = TYPEOF_SBIT;
3559                     break;
3560                 default:
3561                     break;
3562                 }
3563             } else {
3564                 switch (DCL_TYPE(tree->right->ftype)) {
3565                 case POINTER:
3566                     typeofv = TYPEOF_POINTER;
3567                     break;
3568                 case FPOINTER:
3569                     typeofv = TYPEOF_FPOINTER;
3570                     break;
3571                 case CPOINTER:
3572                     typeofv = TYPEOF_CPOINTER;
3573                     break;
3574                 case GPOINTER:
3575                     typeofv = TYPEOF_GPOINTER;
3576                     break;
3577                 case PPOINTER:
3578                     typeofv = TYPEOF_PPOINTER;
3579                     break;
3580                 case IPOINTER:
3581                     typeofv = TYPEOF_IPOINTER;
3582                     break;
3583                 case ARRAY:
3584                     typeofv = TYPEOF_ARRAY;
3585                     break;
3586                 case FUNCTION:
3587                     typeofv = TYPEOF_FUNCTION;
3588                     break;
3589                 default:
3590                     break;
3591                 }
3592             }
3593             SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
3594             tree->opval.val = constVal (buffer);
3595             tree->right = tree->left = NULL;
3596             TETYPE (tree) = getSpec (TTYPE (tree) =
3597                                      tree->opval.val->type);
3598         }
3599         return tree;
3600       /*------------------------------------------------------------------*/
3601       /*----------------------------*/
3602       /* conditional operator  '?'  */
3603       /*----------------------------*/
3604     case '?':
3605       /* the type is value of the colon operator (on the right) */
3606       assert(IS_COLON_OP(tree->right));
3607       /* if already known then replace the tree : optimizer will do it
3608          but faster to do it here */
3609       if (IS_LITERAL (LTYPE(tree))) {     
3610           if ( ((int) floatFromVal (valFromType (LETYPE (tree)))) != 0) {
3611               return decorateType(tree->right->left) ;
3612           } else {
3613               return decorateType(tree->right->right) ;
3614           }
3615       } else {
3616           tree->right = decorateType(tree->right);
3617           TTYPE (tree) = RTYPE(tree);
3618           TETYPE (tree) = getSpec (TTYPE (tree));
3619       }
3620       return tree;
3621
3622     case ':':
3623       /* if they don't match we have a problem */
3624       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3625         {
3626           werror (E_TYPE_MISMATCH, "conditional operator", " ");
3627           goto errorTreeReturn;
3628         }
3629
3630       TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), FALSE);
3631       TETYPE (tree) = getSpec (TTYPE (tree));
3632       return tree;
3633
3634
3635 #if 0 // assignment operators are converted by the parser
3636       /*------------------------------------------------------------------*/
3637       /*----------------------------*/
3638       /*    assignment operators    */
3639       /*----------------------------*/
3640     case MUL_ASSIGN:
3641     case DIV_ASSIGN:
3642       /* for these it must be both must be integral */
3643       if (!IS_ARITHMETIC (LTYPE (tree)) ||
3644           !IS_ARITHMETIC (RTYPE (tree)))
3645         {
3646           werror (E_OPS_INTEGRAL);
3647           goto errorTreeReturn;
3648         }
3649       RRVAL (tree) = 1;
3650       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3651
3652       if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
3653         werror (E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
3654
3655       if (LRVAL (tree))
3656         {
3657           werror (E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
3658           goto errorTreeReturn;
3659         }
3660       LLVAL (tree) = 1;
3661
3662       return tree;
3663
3664     case AND_ASSIGN:
3665     case OR_ASSIGN:
3666     case XOR_ASSIGN:
3667     case RIGHT_ASSIGN:
3668     case LEFT_ASSIGN:
3669       /* for these it must be both must be integral */
3670       if (!IS_INTEGRAL (LTYPE (tree)) ||
3671           !IS_INTEGRAL (RTYPE (tree)))
3672         {
3673           werror (E_OPS_INTEGRAL);
3674           goto errorTreeReturn;
3675         }
3676       RRVAL (tree) = 1;
3677       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
3678
3679       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
3680         werror (E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
3681
3682       if (LRVAL (tree))
3683         {
3684           werror (E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
3685           goto errorTreeReturn;
3686         }
3687       LLVAL (tree) = 1;
3688
3689       return tree;
3690
3691       /*------------------------------------------------------------------*/
3692       /*----------------------------*/
3693       /*    -= operator             */
3694       /*----------------------------*/
3695     case SUB_ASSIGN:
3696       if (!(IS_PTR (LTYPE (tree)) ||
3697             IS_ARITHMETIC (LTYPE (tree))))
3698         {
3699           werror (E_PLUS_INVALID, "-=");
3700           goto errorTreeReturn;
3701         }
3702
3703       if (!(IS_PTR (RTYPE (tree)) ||
3704             IS_ARITHMETIC (RTYPE (tree))))
3705         {
3706           werror (E_PLUS_INVALID, "-=");
3707           goto errorTreeReturn;
3708         }
3709       RRVAL (tree) = 1;
3710       TETYPE (tree) = getSpec (TTYPE (tree) =
3711                                computeType (LTYPE (tree),
3712                                             RTYPE (tree),
3713                                             FALSE));
3714
3715       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
3716         werror (E_CODE_WRITE, "-=");
3717
3718       if (LRVAL (tree))
3719         {
3720           werror (E_LVALUE_REQUIRED, "-=");
3721           goto errorTreeReturn;
3722         }
3723       LLVAL (tree) = 1;
3724
3725       return tree;
3726
3727       /*------------------------------------------------------------------*/
3728       /*----------------------------*/
3729       /*          += operator       */
3730       /*----------------------------*/
3731     case ADD_ASSIGN:
3732       /* this is not a unary operation */
3733       /* if both pointers then problem */
3734       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
3735         {
3736           werror (E_PTR_PLUS_PTR);
3737           goto errorTreeReturn;
3738         }
3739
3740       if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
3741         {
3742           werror (E_PLUS_INVALID, "+=");
3743           goto errorTreeReturn;
3744         }
3745
3746       if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
3747         {
3748           werror (E_PLUS_INVALID, "+=");
3749           goto errorTreeReturn;
3750         }
3751       RRVAL (tree) = 1;
3752       TETYPE (tree) = getSpec (TTYPE (tree) =
3753                                computeType (LTYPE (tree),
3754                                             RTYPE (tree),
3755                                             FALSE));
3756
3757       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
3758         werror (E_CODE_WRITE, "+=");
3759
3760       if (LRVAL (tree))
3761         {
3762           werror (E_LVALUE_REQUIRED, "+=");
3763           goto errorTreeReturn;
3764         }
3765
3766       tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right));
3767       tree->opval.op = '=';
3768
3769       return tree;
3770 #endif
3771
3772       /*------------------------------------------------------------------*/
3773       /*----------------------------*/
3774       /*      straight assignemnt   */
3775       /*----------------------------*/
3776     case '=':
3777       /* cannot be an aggregate */
3778       if (IS_AGGREGATE (LTYPE (tree)))
3779         {
3780           werror (E_AGGR_ASSIGN);
3781           goto errorTreeReturn;
3782         }
3783
3784       /* they should either match or be castable */
3785       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
3786         {
3787           werror (E_TYPE_MISMATCH, "assignment", " ");
3788           printFromToType(RTYPE(tree),LTYPE(tree));
3789         }
3790
3791       /* if the left side of the tree is of type void
3792          then report error */
3793       if (IS_VOID (LTYPE (tree)))
3794         {
3795           werror (E_CAST_ZERO);
3796           printFromToType(RTYPE(tree), LTYPE(tree));
3797         }
3798
3799       TETYPE (tree) = getSpec (TTYPE (tree) =
3800                                LTYPE (tree));
3801       RRVAL (tree) = 1;
3802       LLVAL (tree) = 1;
3803       if (!tree->initMode ) {
3804         if (IS_CONSTANT(LTYPE(tree)))
3805           werror (E_CODE_WRITE, "=");
3806       }
3807       if (LRVAL (tree))
3808         {
3809           werror (E_LVALUE_REQUIRED, "=");
3810           goto errorTreeReturn;
3811         }
3812
3813       return tree;
3814
3815       /*------------------------------------------------------------------*/
3816       /*----------------------------*/
3817       /*      comma operator        */
3818       /*----------------------------*/
3819     case ',':
3820       TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
3821       return tree;
3822
3823       /*------------------------------------------------------------------*/
3824       /*----------------------------*/
3825       /*       function call        */
3826       /*----------------------------*/
3827     case CALL:
3828       parmNumber = 1;
3829
3830       if (processParms (tree->left,
3831                         FUNC_ARGS(tree->left->ftype),
3832                         tree->right, &parmNumber, TRUE)) {
3833         goto errorTreeReturn;
3834       }
3835
3836       if ((options.stackAuto || IFFUNC_ISREENT (LTYPE (tree))) && 
3837           !IFFUNC_ISBUILTIN(LTYPE(tree)))
3838         {
3839           reverseParms (tree->right);
3840         }
3841
3842       if (IS_CODEPTR(LTYPE(tree))) {
3843         TTYPE(tree) = LTYPE(tree)->next->next;
3844       } else {
3845         TTYPE(tree) = LTYPE(tree)->next;
3846       }
3847       TETYPE (tree) = getSpec (TTYPE (tree));
3848       return tree;
3849
3850       /*------------------------------------------------------------------*/
3851       /*----------------------------*/
3852       /*     return statement       */
3853       /*----------------------------*/
3854     case RETURN:
3855       if (!tree->right)
3856         goto voidcheck;
3857
3858       if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
3859         {
3860           werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
3861           printFromToType (RTYPE(tree), currFunc->type->next);
3862           goto errorTreeReturn;
3863         }
3864
3865       if (IS_VOID (currFunc->type->next)
3866           && tree->right &&
3867           !IS_VOID (RTYPE (tree)))
3868         {
3869           werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
3870           goto errorTreeReturn;
3871         }
3872
3873       /* if there is going to be a casing required then add it */
3874       if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
3875         {
3876           tree->right =
3877             decorateType (newNode (CAST,
3878                            newAst_LINK (copyLinkChain (currFunc->type->next)),
3879                                    tree->right));
3880         }
3881
3882       RRVAL (tree) = 1;
3883       return tree;
3884
3885     voidcheck:
3886
3887       if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
3888         {
3889           werror (W_VOID_FUNC, currFunc->name);
3890           goto errorTreeReturn;
3891         }
3892
3893       TTYPE (tree) = TETYPE (tree) = NULL;
3894       return tree;
3895
3896       /*------------------------------------------------------------------*/
3897       /*----------------------------*/
3898       /*     switch statement       */
3899       /*----------------------------*/
3900     case SWITCH:
3901       /* the switch value must be an integer */
3902       if (!IS_INTEGRAL (LTYPE (tree)))
3903         {
3904           werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
3905           goto errorTreeReturn;
3906         }
3907       LRVAL (tree) = 1;
3908       TTYPE (tree) = TETYPE (tree) = NULL;
3909       return tree;
3910
3911       /*------------------------------------------------------------------*/
3912       /*----------------------------*/
3913       /* ifx Statement              */
3914       /*----------------------------*/
3915     case IFX:
3916       tree->left = backPatchLabels (tree->left,
3917                                     tree->trueLabel,
3918                                     tree->falseLabel);
3919       TTYPE (tree) = TETYPE (tree) = NULL;
3920       return tree;
3921
3922       /*------------------------------------------------------------------*/
3923       /*----------------------------*/
3924       /* for Statement              */
3925       /*----------------------------*/
3926     case FOR:
3927
3928       decorateType (resolveSymbols (AST_FOR (tree, initExpr)));
3929       decorateType (resolveSymbols (AST_FOR (tree, condExpr)));
3930       decorateType (resolveSymbols (AST_FOR (tree, loopExpr)));
3931
3932       /* if the for loop is reversible then
3933          reverse it otherwise do what we normally
3934          do */
3935       {
3936         symbol *sym;
3937         ast *init, *end;
3938
3939         if (isLoopReversible (tree, &sym, &init, &end))
3940           return reverseLoop (tree, sym, init, end);
3941         else
3942           return decorateType (createFor (AST_FOR (tree, trueLabel),
3943                                           AST_FOR (tree, continueLabel),
3944                                           AST_FOR (tree, falseLabel),
3945                                           AST_FOR (tree, condLabel),
3946                                           AST_FOR (tree, initExpr),
3947                                           AST_FOR (tree, condExpr),
3948                                           AST_FOR (tree, loopExpr),
3949                                           tree->left));
3950       }
3951     default:
3952       TTYPE (tree) = TETYPE (tree) = NULL;
3953       return tree;
3954     }
3955
3956   /* some error found this tree will be killed */
3957 errorTreeReturn:
3958   TTYPE (tree) = TETYPE (tree) = newCharLink ();
3959   tree->opval.op = NULLOP;
3960   tree->isError = 1;
3961
3962   return tree;
3963 }
3964
3965 /*-----------------------------------------------------------------*/
3966 /* sizeofOp - processes size of operation                          */
3967 /*-----------------------------------------------------------------*/
3968 value *
3969 sizeofOp (sym_link * type)
3970 {
3971   char buff[10];
3972
3973   /* make sure the type is complete and sane */
3974   checkTypeSanity(type, "(sizeof)");
3975
3976   /* get the size and convert it to character  */
3977   SNPRINTF (buff, sizeof(buff), "%d", getSize (type));
3978
3979   /* now convert into value  */
3980   return constVal (buff);
3981 }
3982
3983
3984 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
3985 #define IS_OR(ex)  (ex->type == EX_OP && ex->opval.op == OR_OP )
3986 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
3987 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
3988 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
3989 #define IS_LT(ex)  (ex->type == EX_OP && ex->opval.op == '<' )
3990 #define IS_GT(ex)  (ex->type == EX_OP && ex->opval.op == '>')
3991
3992 /*-----------------------------------------------------------------*/
3993 /* backPatchLabels - change and or not operators to flow control    */
3994 /*-----------------------------------------------------------------*/
3995 ast *
3996 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
3997 {
3998
3999   if (!tree)
4000     return NULL;
4001
4002   if (!(IS_ANDORNOT (tree)))
4003     return tree;
4004
4005   /* if this an and */
4006   if (IS_AND (tree))
4007     {
4008       static int localLbl = 0;
4009       symbol *localLabel;
4010
4011       SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4012       localLabel = newSymbol (buffer, NestLevel);
4013
4014       tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4015
4016       /* if left is already a IFX then just change the if true label in that */
4017       if (!IS_IFX (tree->left))
4018         tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4019
4020       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4021       /* right is a IFX then just join */
4022       if (IS_IFX (tree->right))
4023         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4024
4025       tree->right = createLabel (localLabel, tree->right);
4026       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4027
4028       return newNode (NULLOP, tree->left, tree->right);
4029     }
4030
4031   /* if this is an or operation */
4032   if (IS_OR (tree))
4033     {
4034       static int localLbl = 0;
4035       symbol *localLabel;
4036
4037       SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4038       localLabel = newSymbol (buffer, NestLevel);
4039
4040       tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4041
4042       /* if left is already a IFX then just change the if true label in that */
4043       if (!IS_IFX (tree->left))
4044         tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4045
4046       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4047       /* right is a IFX then just join */
4048       if (IS_IFX (tree->right))
4049         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4050
4051       tree->right = createLabel (localLabel, tree->right);
4052       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4053
4054       return newNode (NULLOP, tree->left, tree->right);
4055     }
4056
4057   /* change not */
4058   if (IS_NOT (tree))
4059     {
4060       int wasnot = IS_NOT (tree->left);
4061       tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4062
4063       /* if the left is already a IFX */
4064       if (!IS_IFX (tree->left))
4065         tree->left = newNode (IFX, tree->left, NULL);
4066
4067       if (wasnot)
4068         {
4069           tree->left->trueLabel = trueLabel;
4070           tree->left->falseLabel = falseLabel;
4071         }
4072       else
4073         {
4074           tree->left->trueLabel = falseLabel;
4075           tree->left->falseLabel = trueLabel;
4076         }
4077       return tree->left;
4078     }
4079
4080   if (IS_IFX (tree))
4081     {
4082       tree->trueLabel = trueLabel;
4083       tree->falseLabel = falseLabel;
4084     }
4085
4086   return tree;
4087 }
4088
4089
4090 /*-----------------------------------------------------------------*/
4091 /* createBlock - create expression tree for block                  */
4092 /*-----------------------------------------------------------------*/
4093 ast *
4094 createBlock (symbol * decl, ast * body)
4095 {
4096   ast *ex;
4097
4098   /* if the block has nothing */
4099   if (!body && !decl)
4100     return NULL;
4101
4102   ex = newNode (BLOCK, NULL, body);
4103   ex->values.sym = decl;
4104   
4105   ex->right = ex->right;
4106   ex->level++;
4107   ex->lineno = 0;
4108   return ex;
4109 }
4110
4111 /*-----------------------------------------------------------------*/
4112 /* createLabel - creates the expression tree for labels            */
4113 /*-----------------------------------------------------------------*/
4114 ast *
4115 createLabel (symbol * label, ast * stmnt)
4116 {
4117   symbol *csym;
4118   char name[SDCC_NAME_MAX + 1];
4119   ast *rValue;
4120
4121   /* must create fresh symbol if the symbol name  */
4122   /* exists in the symbol table, since there can  */
4123   /* be a variable with the same name as the labl */
4124   if ((csym = findSym (SymbolTab, NULL, label->name)) &&
4125       (csym->level == label->level))
4126     label = newSymbol (label->name, label->level);
4127
4128   /* change the name before putting it in add _ */
4129   SNPRINTF(name, sizeof(name), "%s", label->name);
4130
4131   /* put the label in the LabelSymbol table    */
4132   /* but first check if a label of the same    */
4133   /* name exists                               */
4134   if ((csym = findSym (LabelTab, NULL, name)))
4135     werror (E_DUPLICATE_LABEL, label->name);
4136   else
4137     addSym (LabelTab, label, name, label->level, 0, 0);
4138
4139   label->islbl = 1;
4140   label->key = labelKey++;
4141   rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
4142   rValue->lineno = 0;
4143
4144   return rValue;
4145 }
4146
4147 /*-----------------------------------------------------------------*/
4148 /* createCase - generates the parsetree for a case statement       */
4149 /*-----------------------------------------------------------------*/
4150 ast *
4151 createCase (ast * swStat, ast * caseVal, ast * stmnt)
4152 {
4153   char caseLbl[SDCC_NAME_MAX + 1];
4154   ast *rexpr;
4155   value *val;
4156
4157   /* if the switch statement does not exist */
4158   /* then case is out of context            */
4159   if (!swStat)
4160     {
4161       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
4162       return NULL;
4163     }
4164
4165   caseVal = decorateType (resolveSymbols (caseVal));
4166   /* if not a constant then error  */
4167   if (!IS_LITERAL (caseVal->ftype))
4168     {
4169       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
4170       return NULL;
4171     }
4172
4173   /* if not a integer than error */
4174   if (!IS_INTEGRAL (caseVal->ftype))
4175     {
4176       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
4177       return NULL;
4178     }
4179
4180   /* find the end of the switch values chain   */
4181   if (!(val = swStat->values.switchVals.swVals))
4182     swStat->values.switchVals.swVals = caseVal->opval.val;
4183   else
4184     {
4185       /* also order the cases according to value */
4186       value *pval = NULL;
4187       int cVal = (int) floatFromVal (caseVal->opval.val);
4188       while (val && (int) floatFromVal (val) < cVal)
4189         {
4190           pval = val;
4191           val = val->next;
4192         }
4193
4194       /* if we reached the end then */
4195       if (!val)
4196         {
4197           pval->next = caseVal->opval.val;
4198         }
4199       else if ((int) floatFromVal (val) == cVal)
4200         {
4201           werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
4202                     "case");
4203           return NULL;
4204         }
4205       else
4206         {
4207           /* we found a value greater than */
4208           /* the current value we must add this */
4209           /* before the value */
4210           caseVal->opval.val->next = val;
4211
4212           /* if this was the first in chain */
4213           if (swStat->values.switchVals.swVals == val)
4214             swStat->values.switchVals.swVals =
4215               caseVal->opval.val;
4216           else
4217             pval->next = caseVal->opval.val;
4218         }
4219
4220     }
4221
4222   /* create the case label   */
4223   SNPRINTF(caseLbl, sizeof(caseLbl), 
4224            "_case_%d_%d",
4225            swStat->values.switchVals.swNum,
4226            (int) floatFromVal (caseVal->opval.val));
4227
4228   rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
4229   rexpr->lineno = 0;
4230   return rexpr;
4231 }
4232
4233 /*-----------------------------------------------------------------*/
4234 /* createDefault - creates the parse tree for the default statement */
4235 /*-----------------------------------------------------------------*/
4236 ast *
4237 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
4238 {
4239   char defLbl[SDCC_NAME_MAX + 1];
4240
4241   /* if the switch statement does not exist */
4242   /* then case is out of context            */
4243   if (!swStat)
4244     {
4245       werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
4246       return NULL;
4247     }
4248
4249   if (swStat->values.switchVals.swDefault)
4250     {
4251       werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
4252                 "default");
4253       return NULL;
4254     }
4255
4256   /* turn on the default flag   */
4257   swStat->values.switchVals.swDefault = 1;
4258
4259   /* create the label  */
4260   SNPRINTF (defLbl, sizeof(defLbl),
4261             "_default_%d", swStat->values.switchVals.swNum);
4262   return createLabel (newSymbol (defLbl, 0), stmnt);
4263 }
4264
4265 /*-----------------------------------------------------------------*/
4266 /* createIf - creates the parsetree for the if statement           */
4267 /*-----------------------------------------------------------------*/
4268 ast *
4269 createIf (ast * condAst, ast * ifBody, ast * elseBody)
4270 {
4271   static int Lblnum = 0;
4272   ast *ifTree;
4273   symbol *ifTrue, *ifFalse, *ifEnd;
4274
4275   /* if neither exists */
4276   if (!elseBody && !ifBody) {
4277     // if there are no side effects (i++, j() etc)
4278     if (!hasSEFcalls(condAst)) {
4279       return condAst;
4280     }
4281   }
4282
4283   /* create the labels */
4284   SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
4285   ifFalse = newSymbol (buffer, NestLevel);
4286   /* if no else body then end == false */
4287   if (!elseBody)
4288     ifEnd = ifFalse;
4289   else
4290     {
4291       SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
4292       ifEnd = newSymbol (buffer, NestLevel);
4293     }
4294
4295   SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
4296   ifTrue = newSymbol (buffer, NestLevel);
4297
4298   Lblnum++;
4299
4300   /* attach the ifTrue label to the top of it body */
4301   ifBody = createLabel (ifTrue, ifBody);
4302   /* attach a goto end to the ifBody if else is present */
4303   if (elseBody)
4304     {
4305       ifBody = newNode (NULLOP, ifBody,
4306                         newNode (GOTO,
4307                                  newAst_VALUE (symbolVal (ifEnd)),
4308                                  NULL));
4309       /* put the elseLabel on the else body */
4310       elseBody = createLabel (ifFalse, elseBody);
4311       /* out the end at the end of the body */
4312       elseBody = newNode (NULLOP,
4313                           elseBody,
4314                           createLabel (ifEnd, NULL));
4315     }
4316   else
4317     {
4318       ifBody = newNode (NULLOP, ifBody,
4319                         createLabel (ifFalse, NULL));
4320     }
4321   condAst = backPatchLabels (condAst, ifTrue, ifFalse);
4322   if (IS_IFX (condAst))
4323     ifTree = condAst;
4324   else
4325     ifTree = newIfxNode (condAst, ifTrue, ifFalse);
4326
4327   return newNode (NULLOP, ifTree,
4328                   newNode (NULLOP, ifBody, elseBody));
4329
4330 }
4331
4332 /*-----------------------------------------------------------------*/
4333 /* createDo - creates parse tree for do                            */
4334 /*        _dobody_n:                                               */
4335 /*            statements                                           */
4336 /*        _docontinue_n:                                           */
4337 /*            condition_expression +-> trueLabel -> _dobody_n      */
4338 /*                                 |                               */
4339 /*                                 +-> falseLabel-> _dobreak_n     */
4340 /*        _dobreak_n:                                              */
4341 /*-----------------------------------------------------------------*/
4342 ast *
4343 createDo (symbol * trueLabel, symbol * continueLabel,
4344           symbol * falseLabel, ast * condAst, ast * doBody)
4345 {
4346   ast *doTree;
4347
4348
4349   /* if the body does not exist then it is simple */
4350   if (!doBody)
4351     {
4352       condAst = backPatchLabels (condAst, continueLabel, NULL);
4353       doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
4354                 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
4355       doTree->trueLabel = continueLabel;
4356       doTree->falseLabel = NULL;
4357       return doTree;
4358     }
4359
4360   /* otherwise we have a body */
4361   condAst = backPatchLabels (condAst, trueLabel, falseLabel);
4362
4363   /* attach the body label to the top */
4364   doBody = createLabel (trueLabel, doBody);
4365   /* attach the continue label to end of body */
4366   doBody = newNode (NULLOP, doBody,
4367                     createLabel (continueLabel, NULL));
4368
4369   /* now put the break label at the end */
4370   if (IS_IFX (condAst))
4371     doTree = condAst;
4372   else
4373     doTree = newIfxNode (condAst, trueLabel, falseLabel);
4374
4375   doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
4376
4377   /* putting it together */
4378   return newNode (NULLOP, doBody, doTree);
4379 }
4380
4381 /*-----------------------------------------------------------------*/
4382 /* createFor - creates parse tree for 'for' statement              */
4383 /*        initExpr                                                 */
4384 /*   _forcond_n:                                                   */
4385 /*        condExpr  +-> trueLabel -> _forbody_n                    */
4386 /*                  |                                              */
4387 /*                  +-> falseLabel-> _forbreak_n                   */
4388 /*   _forbody_n:                                                   */
4389 /*        statements                                               */
4390 /*   _forcontinue_n:                                               */
4391 /*        loopExpr                                                 */
4392 /*        goto _forcond_n ;                                        */
4393 /*   _forbreak_n:                                                  */
4394 /*-----------------------------------------------------------------*/
4395 ast *
4396 createFor (symbol * trueLabel, symbol * continueLabel,
4397            symbol * falseLabel, symbol * condLabel,
4398            ast * initExpr, ast * condExpr, ast * loopExpr,
4399            ast * forBody)
4400 {
4401   ast *forTree;
4402
4403   /* if loopexpression not present then we can generate it */
4404   /* the same way as a while */
4405   if (!loopExpr)
4406     return newNode (NULLOP, initExpr,
4407                     createWhile (trueLabel, continueLabel,
4408                                  falseLabel, condExpr, forBody));
4409   /* vanilla for statement */
4410   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
4411
4412   if (condExpr && !IS_IFX (condExpr))
4413     condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
4414
4415
4416   /* attach condition label to condition */
4417   condExpr = createLabel (condLabel, condExpr);
4418
4419   /* attach body label to body */
4420   forBody = createLabel (trueLabel, forBody);
4421
4422   /* attach continue to forLoop expression & attach */
4423   /* goto the forcond @ and of loopExpression       */
4424   loopExpr = createLabel (continueLabel,
4425                           newNode (NULLOP,
4426                                    loopExpr,
4427                                    newNode (GOTO,
4428                                        newAst_VALUE (symbolVal (condLabel)),
4429                                             NULL)));
4430   /* now start putting them together */
4431   forTree = newNode (NULLOP, initExpr, condExpr);
4432   forTree = newNode (NULLOP, forTree, forBody);
4433   forTree = newNode (NULLOP, forTree, loopExpr);
4434   /* finally add the break label */
4435   forTree = newNode (NULLOP, forTree,
4436                      createLabel (falseLabel, NULL));
4437   return forTree;
4438 }
4439
4440 /*-----------------------------------------------------------------*/
4441 /* createWhile - creates parse tree for while statement            */
4442 /*               the while statement will be created as follows    */
4443 /*                                                                 */
4444 /*      _while_continue_n:                                         */
4445 /*            condition_expression +-> trueLabel -> _while_boby_n  */
4446 /*                                 |                               */
4447 /*                                 +-> falseLabel -> _while_break_n */
4448 /*      _while_body_n:                                             */
4449 /*            statements                                           */
4450 /*            goto _while_continue_n                               */
4451 /*      _while_break_n:                                            */
4452 /*-----------------------------------------------------------------*/
4453 ast *
4454 createWhile (symbol * trueLabel, symbol * continueLabel,
4455              symbol * falseLabel, ast * condExpr, ast * whileBody)
4456 {
4457   ast *whileTree;
4458
4459   /* put the continue label */
4460   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
4461   condExpr = createLabel (continueLabel, condExpr);
4462   condExpr->lineno = 0;
4463
4464   /* put the body label in front of the body */
4465   whileBody = createLabel (trueLabel, whileBody);
4466   whileBody->lineno = 0;
4467   /* put a jump to continue at the end of the body */
4468   /* and put break label at the end of the body */
4469   whileBody = newNode (NULLOP,
4470                        whileBody,
4471                        newNode (GOTO,
4472                                 newAst_VALUE (symbolVal (continueLabel)),
4473                                 createLabel (falseLabel, NULL)));
4474
4475   /* put it all together */
4476   if (IS_IFX (condExpr))
4477     whileTree = condExpr;
4478   else
4479     {
4480       whileTree = newNode (IFX, condExpr, NULL);
4481       /* put the true & false labels in place */
4482       whileTree->trueLabel = trueLabel;
4483       whileTree->falseLabel = falseLabel;
4484     }
4485
4486   return newNode (NULLOP, whileTree, whileBody);
4487 }
4488
4489 /*-----------------------------------------------------------------*/
4490 /* optimizeGetHbit - get highest order bit of the expression       */
4491 /*-----------------------------------------------------------------*/
4492 ast *
4493 optimizeGetHbit (ast * tree)
4494 {
4495   int i, j;
4496   /* if this is not a bit and */
4497   if (!IS_BITAND (tree))
4498     return tree;
4499
4500   /* will look for tree of the form
4501      ( expr >> ((sizeof expr) -1) ) & 1 */
4502   if (!IS_AST_LIT_VALUE (tree->right))
4503     return tree;
4504
4505   if (AST_LIT_VALUE (tree->right) != 1)
4506     return tree;
4507
4508   if (!IS_RIGHT_OP (tree->left))
4509     return tree;
4510
4511   if (!IS_AST_LIT_VALUE (tree->left->right))
4512     return tree;
4513
4514   if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
4515       (j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
4516     return tree;
4517       
4518   /* make sure the port supports GETHBIT */
4519   if (port->hasExtBitOp
4520       && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
4521     return tree;
4522
4523   return decorateType (newNode (GETHBIT, tree->left->left, NULL));
4524
4525 }
4526
4527 /*-----------------------------------------------------------------*/
4528 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry     */
4529 /*-----------------------------------------------------------------*/
4530 ast *
4531 optimizeRRCRLC (ast * root)
4532 {
4533   /* will look for trees of the form
4534      (?expr << 1) | (?expr >> 7) or
4535      (?expr >> 7) | (?expr << 1) will make that
4536      into a RLC : operation ..
4537      Will also look for
4538      (?expr >> 1) | (?expr << 7) or
4539      (?expr << 7) | (?expr >> 1) will make that
4540      into a RRC operation
4541      note : by 7 I mean (number of bits required to hold the
4542      variable -1 ) */
4543   /* if the root operations is not a | operation the not */
4544   if (!IS_BITOR (root))
4545     return root;
4546
4547   /* I have to think of a better way to match patterns this sucks */
4548   /* that aside let start looking for the first case : I use a the
4549      negative check a lot to improve the efficiency */
4550   /* (?expr << 1) | (?expr >> 7) */
4551   if (IS_LEFT_OP (root->left) &&
4552       IS_RIGHT_OP (root->right))
4553     {
4554
4555       if (!SPEC_USIGN (TETYPE (root->left->left)))
4556         return root;
4557
4558       if (!IS_AST_LIT_VALUE (root->left->right) ||
4559           !IS_AST_LIT_VALUE (root->right->right))
4560         goto tryNext0;
4561
4562       /* make sure it is the same expression */
4563       if (!isAstEqual (root->left->left,
4564                        root->right->left))
4565         goto tryNext0;
4566
4567       if (AST_LIT_VALUE (root->left->right) != 1)
4568         goto tryNext0;
4569
4570       if (AST_LIT_VALUE (root->right->right) !=
4571           (getSize (TTYPE (root->left->left)) * 8 - 1))
4572         goto tryNext0;
4573
4574       /* make sure the port supports RLC */
4575       if (port->hasExtBitOp
4576           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
4577         return root;
4578
4579       /* whew got the first case : create the AST */
4580       return newNode (RLC, root->left->left, NULL);
4581     }
4582
4583 tryNext0:
4584   /* check for second case */
4585   /* (?expr >> 7) | (?expr << 1) */
4586   if (IS_LEFT_OP (root->right) &&
4587       IS_RIGHT_OP (root->left))
4588     {
4589
4590       if (!SPEC_USIGN (TETYPE (root->left->left)))
4591         return root;
4592
4593       if (!IS_AST_LIT_VALUE (root->left->right) ||
4594           !IS_AST_LIT_VALUE (root->right->right))
4595         goto tryNext1;
4596
4597       /* make sure it is the same symbol */
4598       if (!isAstEqual (root->left->left,
4599                        root->right->left))
4600         goto tryNext1;
4601
4602       if (AST_LIT_VALUE (root->right->right) != 1)
4603         goto tryNext1;
4604
4605       if (AST_LIT_VALUE (root->left->right) !=
4606           (getSize (TTYPE (root->left->left)) * 8 - 1))
4607         goto tryNext1;
4608
4609       /* make sure the port supports RLC */
4610       if (port->hasExtBitOp
4611           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
4612         return root;
4613
4614       /* whew got the first case : create the AST */
4615       return newNode (RLC, root->left->left, NULL);
4616
4617     }
4618
4619 tryNext1:
4620   /* third case for RRC */
4621   /*  (?symbol >> 1) | (?symbol << 7) */
4622   if (IS_LEFT_OP (root->right) &&
4623       IS_RIGHT_OP (root->left))
4624     {
4625
4626       if (!SPEC_USIGN (TETYPE (root->left->left)))
4627         return root;
4628
4629       if (!IS_AST_LIT_VALUE (root->left->right) ||
4630           !IS_AST_LIT_VALUE (root->right->right))
4631         goto tryNext2;
4632
4633       /* make sure it is the same symbol */
4634       if (!isAstEqual (root->left->left,
4635                        root->right->left))
4636         goto tryNext2;
4637
4638       if (AST_LIT_VALUE (root->left->right) != 1)
4639         goto tryNext2;
4640
4641       if (AST_LIT_VALUE (root->right->right) !=
4642           (getSize (TTYPE (root->left->left)) * 8 - 1))
4643         goto tryNext2;
4644
4645       /* make sure the port supports RRC */
4646       if (port->hasExtBitOp
4647           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
4648         return root;
4649
4650       /* whew got the first case : create the AST */
4651       return newNode (RRC, root->left->left, NULL);
4652
4653     }
4654 tryNext2:
4655   /* fourth and last case for now */
4656   /* (?symbol << 7) | (?symbol >> 1) */
4657   if (IS_RIGHT_OP (root->right) &&
4658       IS_LEFT_OP (root->left))
4659     {
4660
4661       if (!SPEC_USIGN (TETYPE (root->left->left)))
4662         return root;
4663
4664       if (!IS_AST_LIT_VALUE (root->left->right) ||
4665           !IS_AST_LIT_VALUE (root->right->right))
4666         return root;
4667
4668       /* make sure it is the same symbol */
4669       if (!isAstEqual (root->left->left,
4670                        root->right->left))
4671         return root;
4672
4673       if (AST_LIT_VALUE (root->right->right) != 1)
4674         return root;
4675
4676       if (AST_LIT_VALUE (root->left->right) !=
4677           (getSize (TTYPE (root->left->left)) * 8 - 1))
4678         return root;
4679
4680       /* make sure the port supports RRC */
4681       if (port->hasExtBitOp
4682           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
4683         return root;
4684
4685       /* whew got the first case : create the AST */
4686       return newNode (RRC, root->left->left, NULL);
4687
4688     }
4689
4690   /* not found return root */
4691   return root;
4692 }
4693
4694 /*-----------------------------------------------------------------*/
4695 /* optimizeSWAP :- optimize for nibble/byte/word swaps             */
4696 /*-----------------------------------------------------------------*/
4697 ast *
4698 optimizeSWAP (ast * root)
4699 {
4700   /* will look for trees of the form
4701      (?expr << 4) | (?expr >> 4) or
4702      (?expr >> 4) | (?expr << 4) will make that
4703      into a SWAP : operation ..
4704      note : by 4 I mean (number of bits required to hold the
4705      variable /2 ) */
4706   /* if the root operations is not a | operation the not */
4707   if (!IS_BITOR (root))
4708     return root;
4709
4710   /* (?expr << 4) | (?expr >> 4) */
4711   if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
4712       || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
4713     {
4714
4715       if (!SPEC_USIGN (TETYPE (root->left->left)))
4716         return root;
4717
4718       if (!IS_AST_LIT_VALUE (root->left->right) ||
4719           !IS_AST_LIT_VALUE (root->right->right))
4720         return root;
4721
4722       /* make sure it is the same expression */
4723       if (!isAstEqual (root->left->left,
4724                        root->right->left))
4725         return root;
4726
4727       if (AST_LIT_VALUE (root->left->right) !=
4728           (getSize (TTYPE (root->left->left)) * 4))
4729         return root;
4730
4731       if (AST_LIT_VALUE (root->right->right) !=
4732           (getSize (TTYPE (root->left->left)) * 4))
4733         return root;
4734
4735       /* make sure the port supports SWAP */
4736       if (port->hasExtBitOp
4737           && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
4738         return root;
4739
4740       /* found it : create the AST */
4741       return newNode (SWAP, root->left->left, NULL);
4742     }
4743
4744
4745   /* not found return root */
4746   return root;
4747 }
4748
4749 /*-----------------------------------------------------------------*/
4750 /* optimizeCompare - otimizes compares for bit variables     */
4751 /*-----------------------------------------------------------------*/
4752 static ast *
4753 optimizeCompare (ast * root)
4754 {
4755   ast *optExpr = NULL;
4756   value *vleft;
4757   value *vright;
4758   unsigned int litValue;
4759
4760   /* if nothing then return nothing */
4761   if (!root)
4762     return NULL;
4763
4764   /* if not a compare op then do leaves */
4765   if (!IS_COMPARE_OP (root))
4766     {
4767       root->left = optimizeCompare (root->left);
4768       root->right = optimizeCompare (root->right);
4769       return root;
4770     }
4771
4772   /* if left & right are the same then depending
4773      of the operation do */
4774   if (isAstEqual (root->left, root->right))
4775     {
4776       switch (root->opval.op)
4777         {
4778         case '>':
4779         case '<':
4780         case NE_OP:
4781           optExpr = newAst_VALUE (constVal ("0"));
4782           break;
4783         case GE_OP:
4784         case LE_OP:
4785         case EQ_OP:
4786           optExpr = newAst_VALUE (constVal ("1"));
4787           break;
4788         }
4789
4790       return decorateType (optExpr);
4791     }
4792
4793   vleft = (root->left->type == EX_VALUE ?
4794            root->left->opval.val : NULL);
4795
4796   vright = (root->right->type == EX_VALUE ?
4797             root->right->opval.val : NULL);
4798
4799   /* if left is a BITVAR in BITSPACE */
4800   /* and right is a LITERAL then opt- */
4801   /* imize else do nothing       */
4802   if (vleft && vright &&
4803       IS_BITVAR (vleft->etype) &&
4804       IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
4805       IS_LITERAL (vright->etype))
4806     {
4807
4808       /* if right side > 1 then comparison may never succeed */
4809       if ((litValue = (int) floatFromVal (vright)) > 1)
4810         {
4811           werror (W_BAD_COMPARE);
4812           goto noOptimize;
4813         }
4814
4815       if (litValue)
4816         {
4817           switch (root->opval.op)
4818             {
4819             case '>':           /* bit value greater than 1 cannot be */
4820               werror (W_BAD_COMPARE);
4821               goto noOptimize;
4822               break;
4823
4824             case '<':           /* bit value < 1 means 0 */
4825             case NE_OP:
4826               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
4827               break;
4828
4829             case LE_OP: /* bit value <= 1 means no check */
4830               optExpr = newAst_VALUE (vright);
4831               break;
4832
4833             case GE_OP: /* bit value >= 1 means only check for = */
4834             case EQ_OP:
4835               optExpr = newAst_VALUE (vleft);
4836               break;
4837             }
4838         }
4839       else
4840         {                       /* literal is zero */
4841           switch (root->opval.op)
4842             {
4843             case '<':           /* bit value < 0 cannot be */
4844               werror (W_BAD_COMPARE);
4845               goto noOptimize;
4846               break;
4847
4848             case '>':           /* bit value > 0 means 1 */
4849             case NE_OP:
4850               optExpr = newAst_VALUE (vleft);
4851               break;
4852
4853             case LE_OP: /* bit value <= 0 means no check */
4854             case GE_OP: /* bit value >= 0 means no check */
4855               werror (W_BAD_COMPARE);
4856               goto noOptimize;
4857               break;
4858
4859             case EQ_OP: /* bit == 0 means ! of bit */
4860               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
4861               break;
4862             }
4863         }
4864       return decorateType (resolveSymbols (optExpr));
4865     }                           /* end-of-if of BITVAR */
4866
4867 noOptimize:
4868   return root;
4869 }
4870 /*-----------------------------------------------------------------*/
4871 /* addSymToBlock : adds the symbol to the first block we find      */
4872 /*-----------------------------------------------------------------*/
4873 void 
4874 addSymToBlock (symbol * sym, ast * tree)
4875 {
4876   /* reached end of tree or a leaf */
4877   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
4878     return;
4879
4880   /* found a block */
4881   if (IS_AST_OP (tree) &&
4882       tree->opval.op == BLOCK)
4883     {
4884
4885       symbol *lsym = copySymbol (sym);
4886
4887       lsym->next = AST_VALUES (tree, sym);
4888       AST_VALUES (tree, sym) = lsym;
4889       return;
4890     }
4891
4892   addSymToBlock (sym, tree->left);
4893   addSymToBlock (sym, tree->right);
4894 }
4895
4896 /*-----------------------------------------------------------------*/
4897 /* processRegParms - do processing for register parameters         */
4898 /*-----------------------------------------------------------------*/
4899 static void 
4900 processRegParms (value * args, ast * body)
4901 {
4902   while (args)
4903     {
4904       if (IS_REGPARM (args->etype))
4905         addSymToBlock (args->sym, body);
4906       args = args->next;
4907     }
4908 }
4909
4910 /*-----------------------------------------------------------------*/
4911 /* resetParmKey - resets the operandkeys for the symbols           */
4912 /*-----------------------------------------------------------------*/
4913 DEFSETFUNC (resetParmKey)
4914 {
4915   symbol *sym = item;
4916
4917   sym->key = 0;
4918   sym->defs = NULL;
4919   sym->uses = NULL;
4920   sym->remat = 0;
4921   return 1;
4922 }
4923
4924 /*-----------------------------------------------------------------*/
4925 /* createFunction - This is the key node that calls the iCode for  */
4926 /*                  generating the code for a function. Note code  */
4927 /*                  is generated function by function, later when  */
4928 /*                  add inter-procedural analysis this will change */
4929 /*-----------------------------------------------------------------*/
4930 ast *
4931 createFunction (symbol * name, ast * body)
4932 {
4933   ast *ex;
4934   symbol *csym;
4935   int stack = 0;
4936   sym_link *fetype;
4937   iCode *piCode = NULL;
4938
4939   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
4940     fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
4941
4942   /* if check function return 0 then some problem */
4943   if (checkFunction (name, NULL) == 0)
4944     return NULL;
4945
4946   /* create a dummy block if none exists */
4947   if (!body)
4948     body = newNode (BLOCK, NULL, NULL);
4949
4950   noLineno++;
4951
4952   /* check if the function name already in the symbol table */
4953   if ((csym = findSym (SymbolTab, NULL, name->name)))
4954     {
4955       name = csym;
4956       /* special case for compiler defined functions
4957          we need to add the name to the publics list : this
4958          actually means we are now compiling the compiler
4959          support routine */
4960       if (name->cdef)
4961         {
4962           addSet (&publics, name);
4963         }
4964     }
4965   else
4966     {
4967       addSymChain (name);
4968       allocVariables (name);
4969     }
4970   name->lastLine = mylineno;
4971   currFunc = name;
4972
4973   /* set the stack pointer */
4974   /* PENDING: check this for the mcs51 */
4975   stackPtr = -port->stack.direction * port->stack.call_overhead;
4976   if (IFFUNC_ISISR (name->type))
4977     stackPtr -= port->stack.direction * port->stack.isr_overhead;
4978   if (IFFUNC_ISREENT (name->type) || options.stackAuto)
4979     stackPtr -= port->stack.direction * port->stack.reent_overhead;
4980
4981   xstackPtr = -port->stack.direction * port->stack.call_overhead;
4982
4983   fetype = getSpec (name->type);        /* get the specifier for the function */
4984   /* if this is a reentrant function then */
4985   if (IFFUNC_ISREENT (name->type))
4986     reentrant++;
4987
4988   allocParms (FUNC_ARGS(name->type));   /* allocate the parameters */
4989
4990   /* do processing for parameters that are passed in registers */
4991   processRegParms (FUNC_ARGS(name->type), body);
4992
4993   /* set the stack pointer */
4994   stackPtr = 0;
4995   xstackPtr = -1;
4996
4997   /* allocate & autoinit the block variables */
4998   processBlockVars (body, &stack, ALLOCATE);
4999
5000   /* save the stack information */
5001   if (options.useXstack)
5002     name->xstack = SPEC_STAK (fetype) = stack;
5003   else
5004     name->stack = SPEC_STAK (fetype) = stack;
5005
5006   /* name needs to be mangled */
5007   SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
5008
5009   body = resolveSymbols (body); /* resolve the symbols */
5010   body = decorateType (body);   /* propagateType & do semantic checks */
5011
5012   ex = newAst_VALUE (symbolVal (name)); /* create name */
5013   ex = newNode (FUNCTION, ex, body);
5014   ex->values.args = FUNC_ARGS(name->type);
5015   ex->decorated=1;
5016   if (options.dump_tree) PA(ex);
5017   if (fatalError)
5018     {
5019       werror (E_FUNC_NO_CODE, name->name);
5020       goto skipall;
5021     }
5022
5023   /* create the node & generate intermediate code */
5024   GcurMemmap = code;
5025   codeOutFile = code->oFile;
5026   piCode = iCodeFromAst (ex);
5027
5028   if (fatalError)
5029     {
5030       werror (E_FUNC_NO_CODE, name->name);
5031       goto skipall;
5032     }
5033
5034   eBBlockFromiCode (piCode);
5035
5036   /* if there are any statics then do them */
5037   if (staticAutos)
5038     {
5039       GcurMemmap = statsg;
5040       codeOutFile = statsg->oFile;
5041       eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos))));
5042       staticAutos = NULL;
5043     }
5044
5045 skipall:
5046
5047   /* dealloc the block variables */
5048   processBlockVars (body, &stack, DEALLOCATE);
5049   outputDebugStackSymbols();
5050   /* deallocate paramaters */
5051   deallocParms (FUNC_ARGS(name->type));
5052
5053   if (IFFUNC_ISREENT (name->type))
5054     reentrant--;
5055
5056   /* we are done freeup memory & cleanup */
5057   noLineno--;
5058   if (port->reset_labelKey) labelKey = 1;
5059   name->key = 0;
5060   FUNC_HASBODY(name->type) = 1;
5061   addSet (&operKeyReset, name);
5062   applyToSet (operKeyReset, resetParmKey);
5063
5064   if (options.debug)
5065     cdbStructBlock(1);
5066
5067   cleanUpLevel (LabelTab, 0);
5068   cleanUpBlock (StructTab, 1);
5069   cleanUpBlock (TypedefTab, 1);
5070
5071   xstack->syms = NULL;
5072   istack->syms = NULL;
5073   return NULL;
5074 }
5075
5076
5077 #define INDENT(x,f) { int i ; fprintf (f, "%d:", tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
5078 /*-----------------------------------------------------------------*/
5079 /* ast_print : prints the ast (for debugging purposes)             */
5080 /*-----------------------------------------------------------------*/
5081
5082 void ast_print (ast * tree, FILE *outfile, int indent)
5083 {
5084
5085         if (!tree) return ;
5086
5087         /* can print only decorated trees */
5088         if (!tree->decorated) return;
5089
5090         /* if any child is an error | this one is an error do nothing */
5091         if (tree->isError ||
5092             (tree->left && tree->left->isError) ||
5093             (tree->right && tree->right->isError)) {
5094                 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
5095         }
5096
5097
5098         /* print the line          */
5099         /* if not block & function */
5100         if (tree->type == EX_OP &&
5101             (tree->opval.op != FUNCTION &&
5102              tree->opval.op != BLOCK &&
5103              tree->opval.op != NULLOP)) {
5104         }
5105
5106         if (tree->opval.op == FUNCTION) {
5107                 int arg=0;
5108                 value *args=FUNC_ARGS(tree->left->opval.val->type);
5109                 fprintf(outfile,"FUNCTION (%s=%p) type (",
5110                         tree->left->opval.val->name, tree);
5111                 printTypeChain (tree->left->opval.val->type->next,outfile);
5112                 fprintf(outfile,") args (");
5113                 do {
5114                   if (arg) {
5115                     fprintf (outfile, ", ");
5116                   }
5117                   printTypeChain (args ? args->type : NULL, outfile);
5118                   arg++;
5119                   args= args ? args->next : NULL;
5120                 } while (args);
5121                 fprintf(outfile,")\n");
5122                 ast_print(tree->left,outfile,indent);
5123                 ast_print(tree->right,outfile,indent);
5124                 return ;
5125         }
5126         if (tree->opval.op == BLOCK) {
5127                 symbol *decls = tree->values.sym;
5128                 INDENT(indent,outfile);
5129                 fprintf(outfile,"{\n");
5130                 while (decls) {
5131                         INDENT(indent+2,outfile);
5132                         fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
5133                                 decls->name, decls);
5134                         printTypeChain(decls->type,outfile);
5135                         fprintf(outfile,")\n");
5136
5137                         decls = decls->next;
5138                 }
5139                 ast_print(tree->right,outfile,indent+2);
5140                 INDENT(indent,outfile);
5141                 fprintf(outfile,"}\n");
5142                 return;
5143         }
5144         if (tree->opval.op == NULLOP) {
5145                 ast_print(tree->left,outfile,indent);
5146                 ast_print(tree->right,outfile,indent);
5147                 return ;
5148         }
5149         INDENT(indent,outfile);
5150
5151         /*------------------------------------------------------------------*/
5152         /*----------------------------*/
5153         /*   leaf has been reached    */
5154         /*----------------------------*/
5155         /* if this is of type value */
5156         /* just get the type        */
5157         if (tree->type == EX_VALUE) {
5158
5159                 if (IS_LITERAL (tree->opval.val->etype)) {
5160                         fprintf(outfile,"CONSTANT (%p) value = ", tree);
5161                         if (SPEC_USIGN (tree->opval.val->etype))
5162                                 fprintf(outfile,"%u", (TYPE_UDWORD) floatFromVal(tree->opval.val));
5163                         else
5164                                 fprintf(outfile,"%d", (TYPE_DWORD) floatFromVal(tree->opval.val));
5165                         fprintf(outfile,", 0x%x, %f", (TYPE_UDWORD) floatFromVal(tree->opval.val),
5166                                                       floatFromVal(tree->opval.val));
5167                 } else if (tree->opval.val->sym) {
5168                         /* if the undefined flag is set then give error message */
5169                         if (tree->opval.val->sym->undefined) {
5170                                 fprintf(outfile,"UNDEFINED SYMBOL ");
5171                         } else {
5172                                 fprintf(outfile,"SYMBOL ");
5173                         }
5174                         fprintf(outfile,"(%s=%p)",
5175                                 tree->opval.val->sym->name,tree);
5176                 }
5177                 if (tree->ftype) {
5178                         fprintf(outfile," type (");
5179                         printTypeChain(tree->ftype,outfile);
5180                         fprintf(outfile,")\n");
5181                 } else {
5182                         fprintf(outfile,"\n");
5183                 }
5184                 return ;
5185         }
5186
5187         /* if type link for the case of cast */
5188         if (tree->type == EX_LINK) {
5189                 fprintf(outfile,"TYPENODE (%p) type = (",tree);
5190                 printTypeChain(tree->opval.lnk,outfile);
5191                 fprintf(outfile,")\n");
5192                 return ;
5193         }
5194
5195
5196         /* depending on type of operator do */
5197
5198         switch (tree->opval.op) {
5199                 /*------------------------------------------------------------------*/
5200                 /*----------------------------*/
5201                 /*        array node          */
5202                 /*----------------------------*/
5203         case '[':
5204                 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
5205                 printTypeChain(tree->ftype,outfile);
5206                 fprintf(outfile,")\n");
5207                 ast_print(tree->left,outfile,indent+2);
5208                 ast_print(tree->right,outfile,indent+2);
5209                 return;
5210
5211                 /*------------------------------------------------------------------*/
5212                 /*----------------------------*/
5213                 /*      struct/union          */
5214                 /*----------------------------*/
5215         case '.':
5216                 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
5217                 printTypeChain(tree->ftype,outfile);
5218                 fprintf(outfile,")\n");
5219                 ast_print(tree->left,outfile,indent+2);
5220                 ast_print(tree->right,outfile,indent+2);
5221                 return ;
5222
5223                 /*------------------------------------------------------------------*/
5224                 /*----------------------------*/
5225                 /*    struct/union pointer    */
5226                 /*----------------------------*/
5227         case PTR_OP:
5228                 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
5229                 printTypeChain(tree->ftype,outfile);
5230                 fprintf(outfile,")\n");
5231                 ast_print(tree->left,outfile,indent+2);
5232                 ast_print(tree->right,outfile,indent+2);
5233                 return ;
5234
5235                 /*------------------------------------------------------------------*/
5236                 /*----------------------------*/
5237                 /*  ++/-- operation           */
5238                 /*----------------------------*/
5239         case INC_OP:
5240                 if (tree->left)
5241                   fprintf(outfile,"post-");
5242                 else
5243                   fprintf(outfile,"pre-");
5244                 fprintf(outfile,"INC_OP (%p) type (",tree);
5245                 printTypeChain(tree->ftype,outfile);
5246                 fprintf(outfile,")\n");
5247                 ast_print(tree->left,outfile,indent+2); /* postincrement case */
5248                 ast_print(tree->right,outfile,indent+2); /* preincrement case */
5249                 return ;
5250
5251         case DEC_OP:
5252                 if (tree->left)
5253                   fprintf(outfile,"post-");
5254                 else
5255                   fprintf(outfile,"pre-");
5256                 fprintf(outfile,"DEC_OP (%p) type (",tree);
5257                 printTypeChain(tree->ftype,outfile);
5258                 fprintf(outfile,")\n");
5259                 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
5260                 ast_print(tree->right,outfile,indent+2); /* predecrement case */
5261                 return ;
5262
5263                 /*------------------------------------------------------------------*/
5264                 /*----------------------------*/
5265                 /*  bitwise and               */
5266                 /*----------------------------*/
5267         case '&':
5268                 if (tree->right) {
5269                         fprintf(outfile,"& (%p) type (",tree);
5270                         printTypeChain(tree->ftype,outfile);
5271                         fprintf(outfile,")\n");
5272                         ast_print(tree->left,outfile,indent+2);
5273                         ast_print(tree->right,outfile,indent+2);
5274                 } else {
5275                         fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
5276                         printTypeChain(tree->ftype,outfile);
5277                         fprintf(outfile,")\n");
5278                         ast_print(tree->left,outfile,indent+2);
5279                         ast_print(tree->right,outfile,indent+2);
5280                 }
5281                 return ;
5282                 /*----------------------------*/
5283                 /*  bitwise or                */
5284                 /*----------------------------*/
5285         case '|':
5286                 fprintf(outfile,"OR (%p) type (",tree);
5287                 printTypeChain(tree->ftype,outfile);
5288                 fprintf(outfile,")\n");
5289                 ast_print(tree->left,outfile,indent+2);
5290                 ast_print(tree->right,outfile,indent+2);
5291                 return ;
5292                 /*------------------------------------------------------------------*/
5293                 /*----------------------------*/
5294                 /*  bitwise xor               */
5295                 /*----------------------------*/
5296         case '^':
5297                 fprintf(outfile,"XOR (%p) type (",tree);
5298                 printTypeChain(tree->ftype,outfile);
5299                 fprintf(outfile,")\n");
5300                 ast_print(tree->left,outfile,indent+2);
5301                 ast_print(tree->right,outfile,indent+2);
5302                 return ;
5303
5304                 /*------------------------------------------------------------------*/
5305                 /*----------------------------*/
5306                 /*  division                  */
5307                 /*----------------------------*/
5308         case '/':
5309                 fprintf(outfile,"DIV (%p) type (",tree);
5310                 printTypeChain(tree->ftype,outfile);
5311                 fprintf(outfile,")\n");
5312                 ast_print(tree->left,outfile,indent+2);
5313                 ast_print(tree->right,outfile,indent+2);
5314                 return ;
5315                 /*------------------------------------------------------------------*/
5316                 /*----------------------------*/
5317                 /*            modulus         */
5318                 /*----------------------------*/
5319         case '%':
5320                 fprintf(outfile,"MOD (%p) type (",tree);
5321                 printTypeChain(tree->ftype,outfile);
5322                 fprintf(outfile,")\n");
5323                 ast_print(tree->left,outfile,indent+2);
5324                 ast_print(tree->right,outfile,indent+2);
5325                 return ;
5326
5327                 /*------------------------------------------------------------------*/
5328                 /*----------------------------*/
5329                 /*  address dereference       */
5330                 /*----------------------------*/
5331         case '*':                       /* can be unary  : if right is null then unary operation */
5332                 if (!tree->right) {
5333                         fprintf(outfile,"DEREF (%p) type (",tree);
5334                         printTypeChain(tree->ftype,outfile);
5335                         fprintf(outfile,")\n");
5336                         ast_print(tree->left,outfile,indent+2);
5337                         return ;
5338                 }                       
5339                 /*------------------------------------------------------------------*/
5340                 /*----------------------------*/
5341                 /*      multiplication        */
5342                 /*----------------------------*/                
5343                 fprintf(outfile,"MULT (%p) type (",tree);
5344                 printTypeChain(tree->ftype,outfile);
5345                 fprintf(outfile,")\n");
5346                 ast_print(tree->left,outfile,indent+2);
5347                 ast_print(tree->right,outfile,indent+2);
5348                 return ;
5349
5350
5351                 /*------------------------------------------------------------------*/
5352                 /*----------------------------*/
5353                 /*    unary '+' operator      */
5354                 /*----------------------------*/
5355         case '+':
5356                 /* if unary plus */
5357                 if (!tree->right) {
5358                         fprintf(outfile,"UPLUS (%p) type (",tree);
5359                         printTypeChain(tree->ftype,outfile);
5360                         fprintf(outfile,")\n");
5361                         ast_print(tree->left,outfile,indent+2);
5362                 } else {
5363                         /*------------------------------------------------------------------*/
5364                         /*----------------------------*/
5365                         /*      addition              */
5366                         /*----------------------------*/
5367                         fprintf(outfile,"ADD (%p) type (",tree);
5368                         printTypeChain(tree->ftype,outfile);
5369                         fprintf(outfile,")\n");
5370                         ast_print(tree->left,outfile,indent+2);
5371                         ast_print(tree->right,outfile,indent+2);
5372                 }
5373                 return;
5374                 /*------------------------------------------------------------------*/
5375                 /*----------------------------*/
5376                 /*      unary '-'             */
5377                 /*----------------------------*/
5378         case '-':                       /* can be unary   */
5379                 if (!tree->right) {
5380                         fprintf(outfile,"UMINUS (%p) type (",tree);
5381                         printTypeChain(tree->ftype,outfile);
5382                         fprintf(outfile,")\n");
5383                         ast_print(tree->left,outfile,indent+2);
5384                 } else {
5385                         /*------------------------------------------------------------------*/
5386                         /*----------------------------*/
5387                         /*      subtraction           */
5388                         /*----------------------------*/
5389                         fprintf(outfile,"SUB (%p) type (",tree);
5390                         printTypeChain(tree->ftype,outfile);
5391                         fprintf(outfile,")\n");
5392                         ast_print(tree->left,outfile,indent+2);
5393                         ast_print(tree->right,outfile,indent+2);
5394                 }
5395                 return;
5396                 /*------------------------------------------------------------------*/
5397                 /*----------------------------*/
5398                 /*    compliment              */
5399                 /*----------------------------*/
5400         case '~':
5401                 fprintf(outfile,"COMPL (%p) type (",tree);
5402                 printTypeChain(tree->ftype,outfile);
5403                 fprintf(outfile,")\n");
5404                 ast_print(tree->left,outfile,indent+2);
5405                 return ;
5406                 /*------------------------------------------------------------------*/
5407                 /*----------------------------*/
5408                 /*           not              */
5409                 /*----------------------------*/
5410         case '!':
5411                 fprintf(outfile,"NOT (%p) type (",tree);
5412                 printTypeChain(tree->ftype,outfile);
5413                 fprintf(outfile,")\n");
5414                 ast_print(tree->left,outfile,indent+2);
5415                 return ;
5416                 /*------------------------------------------------------------------*/
5417                 /*----------------------------*/
5418                 /*           shift            */
5419                 /*----------------------------*/
5420         case RRC:
5421                 fprintf(outfile,"RRC (%p) type (",tree);
5422                 printTypeChain(tree->ftype,outfile);
5423                 fprintf(outfile,")\n");
5424                 ast_print(tree->left,outfile,indent+2);
5425                 return ;
5426
5427         case RLC:
5428                 fprintf(outfile,"RLC (%p) type (",tree);
5429                 printTypeChain(tree->ftype,outfile);
5430                 fprintf(outfile,")\n");
5431                 ast_print(tree->left,outfile,indent+2);
5432                 return ;
5433         case SWAP:
5434                 fprintf(outfile,"SWAP (%p) type (",tree);
5435                 printTypeChain(tree->ftype,outfile);
5436                 fprintf(outfile,")\n");
5437                 ast_print(tree->left,outfile,indent+2);
5438                 return ;
5439         case GETHBIT:
5440                 fprintf(outfile,"GETHBIT (%p) type (",tree);
5441                 printTypeChain(tree->ftype,outfile);
5442                 fprintf(outfile,")\n");
5443                 ast_print(tree->left,outfile,indent+2);
5444                 return ;
5445         case LEFT_OP:
5446                 fprintf(outfile,"LEFT_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         case RIGHT_OP:
5453                 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
5454                 printTypeChain(tree->ftype,outfile);
5455                 fprintf(outfile,")\n");
5456                 ast_print(tree->left,outfile,indent+2);
5457                 ast_print(tree->right,outfile,indent+2);
5458                 return ;
5459                 /*------------------------------------------------------------------*/
5460                 /*----------------------------*/
5461                 /*         casting            */
5462                 /*----------------------------*/
5463         case CAST:                      /* change the type   */
5464                 fprintf(outfile,"CAST (%p) from type (",tree);
5465                 printTypeChain(tree->right->ftype,outfile);
5466                 fprintf(outfile,") to type (");
5467                 printTypeChain(tree->ftype,outfile);
5468                 fprintf(outfile,")\n");
5469                 ast_print(tree->right,outfile,indent+2);
5470                 return ;
5471                 
5472         case AND_OP:
5473                 fprintf(outfile,"ANDAND (%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         case OR_OP:
5480                 fprintf(outfile,"OROR (%p) type (",tree);
5481                 printTypeChain(tree->ftype,outfile);
5482                 fprintf(outfile,")\n");
5483                 ast_print(tree->left,outfile,indent+2);
5484                 ast_print(tree->right,outfile,indent+2);
5485                 return ;
5486                 
5487                 /*------------------------------------------------------------------*/
5488                 /*----------------------------*/
5489                 /*     comparison operators   */
5490                 /*----------------------------*/
5491         case '>':
5492                 fprintf(outfile,"GT(>) (%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 '<':
5499                 fprintf(outfile,"LT(<) (%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 LE_OP:
5506                 fprintf(outfile,"LE(<=) (%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 GE_OP:
5513                 fprintf(outfile,"GE(>=) (%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 EQ_OP:
5520                 fprintf(outfile,"EQ(==) (%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                 return ;
5526         case NE_OP:
5527                 fprintf(outfile,"NE(!=) (%p) type (",tree);
5528                 printTypeChain(tree->ftype,outfile);
5529                 fprintf(outfile,")\n");
5530                 ast_print(tree->left,outfile,indent+2);
5531                 ast_print(tree->right,outfile,indent+2);
5532                 /*------------------------------------------------------------------*/
5533                 /*----------------------------*/
5534                 /*             sizeof         */
5535                 /*----------------------------*/
5536         case SIZEOF:            /* evaluate wihout code generation */
5537                 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
5538                 return ;
5539
5540                 /*------------------------------------------------------------------*/
5541                 /*----------------------------*/
5542                 /* conditional operator  '?'  */
5543                 /*----------------------------*/
5544         case '?':
5545                 fprintf(outfile,"QUEST(?) (%p) type (",tree);
5546                 printTypeChain(tree->ftype,outfile);
5547                 fprintf(outfile,")\n");
5548                 ast_print(tree->left,outfile,indent+2);
5549                 ast_print(tree->right,outfile,indent+2);
5550                 return;
5551
5552         case ':':
5553                 fprintf(outfile,"COLON(:) (%p) type (",tree);
5554                 printTypeChain(tree->ftype,outfile);
5555                 fprintf(outfile,")\n");
5556                 ast_print(tree->left,outfile,indent+2);
5557                 ast_print(tree->right,outfile,indent+2);
5558                 return ;
5559                 
5560                 /*------------------------------------------------------------------*/
5561                 /*----------------------------*/
5562                 /*    assignment operators    */
5563                 /*----------------------------*/
5564         case MUL_ASSIGN:
5565                 fprintf(outfile,"MULASS(*=) (%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 DIV_ASSIGN:
5572                 fprintf(outfile,"DIVASS(/=) (%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 AND_ASSIGN:
5579                 fprintf(outfile,"ANDASS(&=) (%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 OR_ASSIGN:
5586                 fprintf(outfile,"ORASS(|=) (%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 XOR_ASSIGN:
5593                 fprintf(outfile,"XORASS(^=) (%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 RIGHT_ASSIGN:
5600                 fprintf(outfile,"RSHFTASS(>>=) (%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         case LEFT_ASSIGN:
5607                 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
5608                 printTypeChain(tree->ftype,outfile);
5609                 fprintf(outfile,")\n");
5610                 ast_print(tree->left,outfile,indent+2);
5611                 ast_print(tree->right,outfile,indent+2);
5612                 return;
5613                 /*------------------------------------------------------------------*/
5614                 /*----------------------------*/
5615                 /*    -= operator             */
5616                 /*----------------------------*/
5617         case SUB_ASSIGN:
5618                 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
5619                 printTypeChain(tree->ftype,outfile);
5620                 fprintf(outfile,")\n");
5621                 ast_print(tree->left,outfile,indent+2);
5622                 ast_print(tree->right,outfile,indent+2);
5623                 return;
5624                 /*------------------------------------------------------------------*/
5625                 /*----------------------------*/
5626                 /*          += operator       */
5627                 /*----------------------------*/
5628         case ADD_ASSIGN:
5629                 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
5630                 printTypeChain(tree->ftype,outfile);
5631                 fprintf(outfile,")\n");
5632                 ast_print(tree->left,outfile,indent+2);
5633                 ast_print(tree->right,outfile,indent+2);
5634                 return;
5635                 /*------------------------------------------------------------------*/
5636                 /*----------------------------*/
5637                 /*      straight assignemnt   */
5638                 /*----------------------------*/
5639         case '=':
5640                 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
5641                 printTypeChain(tree->ftype,outfile);
5642                 fprintf(outfile,")\n");
5643                 ast_print(tree->left,outfile,indent+2);
5644                 ast_print(tree->right,outfile,indent+2);
5645                 return;     
5646                 /*------------------------------------------------------------------*/
5647                 /*----------------------------*/
5648                 /*      comma operator        */
5649                 /*----------------------------*/
5650         case ',':
5651                 fprintf(outfile,"COMMA(,) (%p) type (",tree);
5652                 printTypeChain(tree->ftype,outfile);
5653                 fprintf(outfile,")\n");
5654                 ast_print(tree->left,outfile,indent+2);
5655                 ast_print(tree->right,outfile,indent+2);
5656                 return;
5657                 /*------------------------------------------------------------------*/
5658                 /*----------------------------*/
5659                 /*       function call        */
5660                 /*----------------------------*/
5661         case CALL:
5662         case PCALL:
5663                 fprintf(outfile,"CALL (%p) type (",tree);
5664                 printTypeChain(tree->ftype,outfile);
5665                 fprintf(outfile,")\n");
5666                 ast_print(tree->left,outfile,indent+2);
5667                 ast_print(tree->right,outfile,indent+2);
5668                 return;
5669         case PARAM:
5670                 fprintf(outfile,"PARMS\n");
5671                 ast_print(tree->left,outfile,indent+2);
5672                 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
5673                         ast_print(tree->right,outfile,indent+2);
5674                 }
5675                 return ;
5676                 /*------------------------------------------------------------------*/
5677                 /*----------------------------*/
5678                 /*     return statement       */
5679                 /*----------------------------*/
5680         case RETURN:
5681                 fprintf(outfile,"RETURN (%p) type (",tree);
5682                 if (tree->right) {
5683                     printTypeChain(tree->right->ftype,outfile);
5684                 }
5685                 fprintf(outfile,")\n");
5686                 ast_print(tree->right,outfile,indent+2);
5687                 return ;
5688                 /*------------------------------------------------------------------*/
5689                 /*----------------------------*/
5690                 /*     label statement        */
5691                 /*----------------------------*/
5692         case LABEL :
5693                 fprintf(outfile,"LABEL (%p)\n",tree);
5694                 ast_print(tree->left,outfile,indent+2);
5695                 ast_print(tree->right,outfile,indent);
5696                 return;
5697                 /*------------------------------------------------------------------*/
5698                 /*----------------------------*/
5699                 /*     switch statement       */
5700                 /*----------------------------*/
5701         case SWITCH:
5702                 {
5703                         value *val;
5704                         fprintf(outfile,"SWITCH (%p) ",tree);
5705                         ast_print(tree->left,outfile,0);
5706                         for (val = tree->values.switchVals.swVals; val ; val = val->next) {
5707                                 INDENT(indent+2,outfile);
5708                                 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
5709                                         (int) floatFromVal(val),
5710                                         tree->values.switchVals.swNum,
5711                                         (int) floatFromVal(val));
5712                         }
5713                         ast_print(tree->right,outfile,indent);
5714                 }
5715                 return ;
5716                 /*------------------------------------------------------------------*/
5717                 /*----------------------------*/
5718                 /* ifx Statement              */
5719                 /*----------------------------*/
5720         case IFX:
5721                 fprintf(outfile,"IF (%p) \n",tree);
5722                 ast_print(tree->left,outfile,indent+2);
5723                 if (tree->trueLabel) {
5724                         INDENT(indent+2,outfile);
5725                         fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
5726                 }
5727                 if (tree->falseLabel) {
5728                         INDENT(indent+2,outfile);
5729                         fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
5730                 }
5731                 ast_print(tree->right,outfile,indent+2);
5732                 return ;
5733                 /*----------------------------*/
5734                 /* goto Statement              */
5735                 /*----------------------------*/
5736         case GOTO:
5737                 fprintf(outfile,"GOTO (%p) \n",tree);
5738                 ast_print(tree->left,outfile,indent+2);
5739                 fprintf(outfile,"\n");
5740                 return ;
5741                 /*------------------------------------------------------------------*/
5742                 /*----------------------------*/
5743                 /* for Statement              */
5744                 /*----------------------------*/
5745         case FOR:
5746                 fprintf(outfile,"FOR (%p) \n",tree);
5747                 if (AST_FOR( tree, initExpr)) {
5748                         INDENT(indent+2,outfile);
5749                         fprintf(outfile,"INIT EXPR ");
5750                         ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
5751                 }
5752                 if (AST_FOR( tree, condExpr)) {
5753                         INDENT(indent+2,outfile);
5754                         fprintf(outfile,"COND EXPR ");
5755                         ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
5756                 }
5757                 if (AST_FOR( tree, loopExpr)) {
5758                         INDENT(indent+2,outfile);
5759                         fprintf(outfile,"LOOP EXPR ");
5760                         ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
5761                 }
5762                 fprintf(outfile,"FOR LOOP BODY \n");
5763                 ast_print(tree->left,outfile,indent+2);
5764                 return ;
5765         case CRITICAL:
5766                 fprintf(outfile,"CRITICAL (%p) \n",tree);
5767                 ast_print(tree->left,outfile,indent+2);
5768         default:
5769             return ;
5770         }
5771 }
5772
5773 void PA(ast *t)
5774 {
5775         ast_print(t,stdout,0);
5776 }
5777
5778
5779
5780 /*-----------------------------------------------------------------*/
5781 /* astErrors : returns non-zero if errors present in tree          */
5782 /*-----------------------------------------------------------------*/
5783 int astErrors(ast *t)
5784 {
5785   int errors=0;
5786   
5787   if (t)
5788     {
5789       if (t->isError)
5790         errors++;
5791   
5792       if (t->type == EX_VALUE
5793           && t->opval.val->sym
5794           && t->opval.val->sym->undefined)
5795         errors++;
5796
5797       errors += astErrors(t->left);
5798       errors += astErrors(t->right);
5799     }
5800     
5801   return errors;
5802 }