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