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