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