a ppc endian fix
[fw/sdcc] / src / SDCCval.c
1 /*----------------------------------------------------------------------
2     SDCCval.c :- has routine to do all kinds of fun stuff with the
3                 value wrapper & with initialiser lists.
4
5     Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6
7     This program is free software; you can redistribute it and/or modify it
8     under the terms of the GNU General Public License as published by the
9     Free Software Foundation; either version 2, or (at your option) any
10     later version.
11
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
21     In other words, you are welcome to use, share and improve this program.
22     You are forbidden to forbid anyone else to use, share and improve
23     what you give them.   Help stamp out software-hoarding!
24 -------------------------------------------------------------------------*/
25
26 #include "common.h"
27 #include <math.h>
28 #include <stdlib.h>
29 #include <limits.h>
30 #include "newalloc.h"
31
32 #if defined(__BORLANDC__) || defined(_MSC_VER)
33 #define LONG_LONG __int64
34 #else
35 #define LONG_LONG long long
36 #endif
37
38 int cNestLevel;
39
40 /*-----------------------------------------------------------------*/
41 /* newValue - allocates and returns a new value        */
42 /*-----------------------------------------------------------------*/
43 value *
44 newValue ()
45 {
46   value *val;
47
48   val = Safe_alloc (sizeof (value));
49
50   return val;
51 }
52
53 /*-----------------------------------------------------------------*/
54 /* newiList - new initializer list                                 */
55 /*-----------------------------------------------------------------*/
56 initList *
57 newiList (int type, void *ilist)
58 {
59   initList *nilist;
60
61
62   nilist = Safe_alloc (sizeof (initList));
63
64   nilist->type = type;
65   nilist->lineno = yylineno;
66
67   switch (type)
68     {
69     case INIT_NODE:
70       nilist->init.node = (struct ast *) ilist;
71       break;
72
73     case INIT_DEEP:
74       nilist->init.deep = (struct initList *) ilist;
75       break;
76     }
77
78   return nilist;
79 }
80
81 /*------------------------------------------------------------------*/
82 /* revinit   - reverses the initial values for a value  chain        */
83 /*------------------------------------------------------------------*/
84 initList *
85 revinit (initList * val)
86 {
87   initList *prev, *curr, *next;
88
89   if (!val)
90     return NULL;
91
92   prev = val;
93   curr = val->next;
94
95   while (curr)
96     {
97       next = curr->next;
98       curr->next = prev;
99       prev = curr;
100       curr = next;
101     }
102   val->next = (void *) NULL;
103   return prev;
104 }
105
106 bool
107 convertIListToConstList(initList *src, literalList **lList)
108 {
109     initList    *iLoop;
110     literalList *head, *last, *newL;
111     
112     head = last = NULL;
113     
114     if (!src || src->type != INIT_DEEP)
115     {
116         return FALSE;
117     }
118     
119     iLoop =  src->init.deep;
120     
121     while (iLoop)
122     {
123         if (iLoop->type != INIT_NODE)
124         {
125             return FALSE;
126         }
127         
128         if (!IS_AST_LIT_VALUE(decorateType(resolveSymbols(iLoop->init.node))))
129         {
130             return FALSE;
131         }
132         iLoop = iLoop->next;
133     }
134     
135     // We've now established that the initializer list contains only literal values.
136     
137     iLoop = src->init.deep;
138     while (iLoop)
139     {
140         double val = AST_LIT_VALUE(iLoop->init.node);
141         
142         if (last && last->literalValue == val)
143         {
144             last->count++;
145         }
146         else
147         {
148             newL = Safe_alloc(sizeof(literalList));
149             newL->literalValue = val;
150             newL->count = 1;
151             newL->next = NULL;
152             
153             if (last)
154             {
155                 last->next = newL;
156             }
157             else
158             {
159                 head = newL;
160             }
161             last = newL;
162         }
163         iLoop = iLoop->next;
164     }
165     
166     if (!head)    
167     {
168         return FALSE;
169     }
170     
171     *lList = head;
172     return TRUE;
173 }
174
175 literalList *
176 copyLiteralList(literalList *src)
177 {
178     literalList *head, *prev, *newL;
179     
180     head = prev = NULL;
181     
182     while (src)
183     {
184         newL = Safe_alloc(sizeof(literalList));
185         
186         newL->literalValue = src->literalValue;
187         newL->count = src->count;
188         newL->next = NULL;
189         
190         if (prev)
191         {
192             prev->next = newL;
193         }
194         else
195         {
196             head = newL;
197         }
198         prev = newL;
199         src = src->next;
200     }
201     
202     return head;
203 }
204
205
206
207 /*------------------------------------------------------------------*/
208 /* copyIlist - copy initializer list            */
209 /*------------------------------------------------------------------*/
210 initList *
211 copyIlist (initList * src)
212 {
213   initList *dest = NULL;
214
215   if (!src)
216     return NULL;
217
218   switch (src->type)
219     {
220     case INIT_DEEP:
221       dest = newiList (INIT_DEEP, copyIlist (src->init.deep));
222       break;
223     case INIT_NODE:
224       dest = newiList (INIT_NODE, copyAst (src->init.node));
225       break;
226     }
227
228   if (src->next)
229     dest->next = copyIlist (src->next);
230
231   return dest;
232 }
233
234 /*------------------------------------------------------------------*/
235 /* list2int - converts the first element of the list to value       */
236 /*------------------------------------------------------------------*/
237 double 
238 list2int (initList * val)
239 {
240   initList *i = val;
241
242   if (i->type == INIT_DEEP)
243     return list2int (val->init.deep);
244
245   return floatFromVal (constExprValue (val->init.node, TRUE));
246 }
247
248 /*------------------------------------------------------------------*/
249 /* list2val - converts the first element of the list to value       */
250 /*------------------------------------------------------------------*/
251 value *
252 list2val (initList * val)
253 {
254   if (!val)
255     return NULL;
256
257   if (val->type == INIT_DEEP)
258     return list2val (val->init.deep);
259
260   return constExprValue (val->init.node, TRUE);
261 }
262
263 /*------------------------------------------------------------------*/
264 /* list2expr - returns the first expression in the initializer list */
265 /*------------------------------------------------------------------*/
266 ast *
267 list2expr (initList * ilist)
268 {
269   if (ilist->type == INIT_DEEP)
270     return list2expr (ilist->init.deep);
271   return ilist->init.node;
272 }
273
274 /*------------------------------------------------------------------*/
275 /* resolveIvalSym - resolve symbols in initial values               */
276 /*------------------------------------------------------------------*/
277 void 
278 resolveIvalSym (initList * ilist)
279 {
280   if (!ilist)
281     return;
282
283   if (ilist->type == INIT_NODE)
284     ilist->init.node = decorateType (resolveSymbols (ilist->init.node));
285
286   if (ilist->type == INIT_DEEP)
287     resolveIvalSym (ilist->init.deep);
288
289   resolveIvalSym (ilist->next);
290 }
291
292 /*-----------------------------------------------------------------*/
293 /* symbolVal - creates a value for a symbol              */
294 /*-----------------------------------------------------------------*/
295 value *
296 symbolVal (symbol * sym)
297 {
298   value *val;
299
300   if (!sym)
301     return NULL;
302
303   val = newValue ();
304   val->sym = sym;
305
306   if (sym->type)
307     {
308       val->type = sym->type;
309       val->etype = getSpec (val->type);
310     }
311
312   if (*sym->rname)
313     sprintf (val->name, "%s", sym->rname);
314   else
315     sprintf (val->name, "_%s", sym->name);
316
317
318   return val;
319 }
320
321 /*--------------------------------------------------------------------*/
322 /* cheapestVal - convert a val to the cheapest as possible value      */
323 /*--------------------------------------------------------------------*/
324 value *cheapestVal (value *val) {
325   long sval=0;
326   unsigned long uval=0;
327
328   if (IS_FLOAT(val->type) || IS_CHAR(val->type))
329     return val;
330
331   if (SPEC_LONG(val->type)) {
332     if (SPEC_USIGN(val->type)) {
333       uval=SPEC_CVAL(val->type).v_ulong;
334     } else {
335       sval=SPEC_CVAL(val->type).v_long;
336     }
337   } else {
338     if (SPEC_USIGN(val->type)) {
339       uval=SPEC_CVAL(val->type).v_uint;
340     } else {
341       sval=SPEC_CVAL(val->type).v_int;
342     }
343   }
344
345   if (SPEC_USIGN(val->type)) {
346     if (uval<=0xff) {
347       SPEC_NOUN(val->type)=V_CHAR;
348       SPEC_LONG(val->type)=0;
349     } else {
350       if (uval<=0xffff) {
351         SPEC_LONG(val->type)=0;
352       }
353     }
354   } else {
355     if (sval<0) {
356       if (sval>=-128) {
357         SPEC_NOUN(val->type)=V_CHAR;
358         SPEC_CVAL(val->type).v_int &= 0xff;
359         SPEC_LONG(val->type)=0;
360       } else {
361         if (sval>=-32768) {
362           SPEC_LONG(val->type)=0;
363         }
364       }
365     } else {
366       if (sval<=127) {
367         SPEC_NOUN(val->type)=V_CHAR;
368         SPEC_LONG(val->type)=0;
369       } else {
370         if (sval<=32767) {
371           SPEC_LONG(val->type)=0;
372         }
373       }
374     }
375   }
376   return val;
377 }
378
379 /*-----------------------------------------------------------------*/
380 /* valueFromLit - creates a value from a literal                   */
381 /*-----------------------------------------------------------------*/
382 value *
383 valueFromLit (double lit)
384 {
385   char buffer[50];
386
387   if ((((long) lit) - lit) == 0)
388     {
389       sprintf (buffer, "%ld", (long) lit);
390       return constVal (buffer);
391     }
392
393   sprintf (buffer, "%f", lit);
394   return constFloatVal (buffer);
395 }
396
397 /*-----------------------------------------------------------------*/
398 /* constFloatVal - converts a FLOAT constant to value              */
399 /*-----------------------------------------------------------------*/
400 value *
401 constFloatVal (char *s)
402 {
403   value *val = newValue ();
404   double sval;
405
406   if (sscanf (s, "%lf", &sval) != 1)
407     {
408       werror (E_INVALID_FLOAT_CONST, s);
409       return constVal ("0");
410     }
411
412   val->type = val->etype = newLink ();
413   val->type->class = SPECIFIER;
414   SPEC_NOUN (val->type) = V_FLOAT;
415   SPEC_SCLS (val->type) = S_LITERAL;
416   SPEC_CVAL (val->type).v_float = sval;
417
418   return val;
419 }
420
421 /*-----------------------------------------------------------------*/
422 /* constVal - converts an INTEGER constant into a cheapest value   */
423 /*-----------------------------------------------------------------*/
424 value *constVal (char *s)
425 {
426   value *val;
427   short hex = 0, octal = 0;
428   char scanFmt[10];
429   int scI = 0;
430   LONG_LONG sval;
431
432   val = newValue ();            /* alloc space for value   */
433
434   val->type = val->etype = newLink ();  /* create the spcifier */
435   val->type->class = SPECIFIER;
436   SPEC_SCLS (val->type) = S_LITERAL;
437   // let's start with an unsigned char
438   SPEC_NOUN (val->type) = V_CHAR;
439   SPEC_USIGN (val->type) = 1;
440
441   /* set the _long flag if 'lL' is found */
442   if (strchr (s, 'l') || strchr (s, 'L'))
443     SPEC_LONG (val->type) = 1;
444
445   hex = ((strchr (s, 'x') || strchr (s, 'X')) ? 1 : 0);
446
447   /* set the octal flag   */
448   if (!hex && *s == '0' && *(s + 1))
449     octal = 1;
450
451   /* create the scan string */
452   scanFmt[scI++] = '%';
453
454   scanFmt[scI++] = 'l';
455   scanFmt[scI++] = 'l';
456
457   if (octal)
458     scanFmt[scI++] = 'o';
459   else if (hex)
460     scanFmt[scI++] = 'x';
461   else
462     scanFmt[scI++] = 'd';
463
464   scanFmt[scI++] = '\0';
465
466   sscanf (s, scanFmt, &sval);
467
468   if (sval<0) { // "-28u" will still be signed and negative
469     SPEC_USIGN (val->type) = 0;
470     if (sval<-32768) { // check if we have to promote to long
471       SPEC_NOUN (val->type) = V_INT;
472       SPEC_LONG (val->type) = 1;
473       SPEC_CVAL (val->type).v_long=sval;
474     } else {
475       SPEC_CVAL (val->type).v_int=sval;
476       if (sval<-128) { // check if we have to promote to int
477         SPEC_NOUN (val->type) = V_INT;
478       }
479     }
480   } else {
481     if (sval>0xffff) { // check if we have to promote to long
482       SPEC_NOUN (val->type) = V_INT;
483       SPEC_LONG (val->type) = 1;
484       SPEC_CVAL (val->type).v_ulong=sval;
485     } else {
486       SPEC_CVAL (val->type).v_uint=sval;
487       if (sval>0xff) { // check if we have to promote to int
488         SPEC_NOUN (val->type) = V_INT;
489       }
490     }
491   }
492
493   return val;
494 }
495
496 /*! /fn char hexEscape(char **src)
497
498     /param src Pointer to 'x' from start of hex character value
499 */
500
501 unsigned char hexEscape(char **src)
502 {
503   char *s ;
504   unsigned long value ;
505   
506   (*src)++ ;    /* Skip over the 'x' */
507   s = *src ;    /* Save for error detection */
508   
509   value = strtol (*src, src, 16);
510   
511   if (s == *src) {
512       // no valid hex found
513       werror(E_INVALID_HEX);
514   } else {
515     if (value > 255) {
516       werror(W_ESC_SEQ_OOR_FOR_CHAR);
517     }
518   }
519   return (char) value;
520 }
521
522 /*------------------------------------------------------------------*/
523 /* octalEscape - process an octal constant of max three digits      */
524 /* return the octal value, throw a warning for illegal octal        */
525 /* adjust src to point at the last proccesed char                   */
526 /*------------------------------------------------------------------*/
527
528 unsigned char octalEscape (char **str) {
529   int digits;
530   unsigned value=0;
531
532   for (digits=0; digits<3; digits++) {
533     if (**str>='0' && **str<='7') {
534       value = value*8 + (**str-'0');
535       (*str)++;
536     } else {
537       break;
538     }
539   }
540   if (digits) {
541     if (value > 255 /* || (**str>='0' && **str<='7') */ ) {
542       werror (W_ESC_SEQ_OOR_FOR_CHAR);
543     }
544   }
545   return value;
546 }
547
548 /*! 
549   /fn int copyStr (char *dest, char *src)
550   
551   Copies a source string to a dest buffer interpreting escape sequences
552   and special characters
553
554   /param dest Buffer to receive the resultant string
555   /param src  Buffer containing the source string with escape sequecnes
556   /return Number of characters in output string
557
558 */
559
560 int 
561 copyStr (char *dest, char *src)
562
563 {
564   char *OriginalDest = dest ;
565
566   while (*src)
567     {
568       if (*src == '\"')
569         src++;
570       else if (*src == '\\')
571         {
572           src++;
573           switch (*src)
574             {
575             case 'n':
576               *dest++ = '\n';
577               break;
578             case 't':
579               *dest++ = '\t';
580               break;
581             case 'v':
582               *dest++ = '\v';
583               break;
584             case 'b':
585               *dest++ = '\b';
586               break;
587             case 'r':
588               *dest++ = '\r';
589               break;
590             case 'f':
591               *dest++ = '\f';
592               break;
593             case 'a':
594               *dest++ = '\a';
595               break;
596
597             case '0':
598             case '1':
599             case '2':
600             case '3':
601             case '4':
602             case '5':
603             case '6':
604             case '7':
605               *dest++ = octalEscape(&src);
606               src-- ;
607               break;
608
609             case 'x': 
610               *dest++ = hexEscape(&src) ;
611               src-- ;
612               break ;
613
614             case '\\':
615               *dest++ = '\\';
616               break;
617             case '\?':
618               *dest++ = '\?';
619               break;
620             case '\'':
621               *dest++ = '\'';
622               break;
623             case '\"':
624               *dest++ = '\"';
625               break;
626             default:
627               *dest++ = *src;
628             }
629           src++;
630         }
631       else
632         *dest++ = *src++;
633     }
634
635   *dest++ = '\0';
636
637   return dest - OriginalDest ;
638 }
639
640 /*------------------------------------------------------------------*/
641 /* strVal - converts a string constant to a value       */
642 /*------------------------------------------------------------------*/
643 value *
644 strVal (char *s)
645 {
646   value *val;
647
648   val = newValue ();            /* get a new one */
649
650   /* get a declarator */
651   val->type = newLink ();
652   DCL_TYPE (val->type) = ARRAY;
653   val->type->next = val->etype = newLink ();
654   val->etype->class = SPECIFIER;
655   SPEC_NOUN (val->etype) = V_CHAR;
656   SPEC_SCLS (val->etype) = S_LITERAL;
657
658   SPEC_CVAL (val->etype).v_char = Safe_alloc (strlen (s) + 1);
659   DCL_ELEM (val->type) = copyStr (SPEC_CVAL (val->etype).v_char, s);
660
661   return val;
662 }
663
664
665 /*------------------------------------------------------------------*/
666 /* reverseValWithType - reverses value chain with type & etype      */
667 /*------------------------------------------------------------------*/
668 value *
669 reverseValWithType (value * val)
670 {
671   sym_link *type;
672   sym_link *etype;
673
674   if (!val)
675     return NULL;
676
677   /* save the type * etype chains */
678   type = val->type;
679   etype = val->etype;
680
681   /* set the current one 2b null */
682   val->type = val->etype = NULL;
683   val = reverseVal (val);
684
685   /* restore type & etype */
686   val->type = type;
687   val->etype = etype;
688
689   return val;
690 }
691
692 /*------------------------------------------------------------------*/
693 /* reverseVal - reverses the values for a value  chain        */
694 /*------------------------------------------------------------------*/
695 value *
696 reverseVal (value * val)
697 {
698   value *prev, *curr, *next;
699
700   if (!val)
701     return NULL;
702
703   prev = val;
704   curr = val->next;
705
706   while (curr)
707     {
708       next = curr->next;
709       curr->next = prev;
710       prev = curr;
711       curr = next;
712     }
713   val->next = (void *) NULL;
714   return prev;
715 }
716
717 /*------------------------------------------------------------------*/
718 /* copyValueChain - will copy a chain of values                     */
719 /*------------------------------------------------------------------*/
720 value *
721 copyValueChain (value * src)
722 {
723   value *dest;
724
725   if (!src)
726     return NULL;
727
728   dest = copyValue (src);
729   dest->next = copyValueChain (src->next);
730
731   return dest;
732 }
733
734 /*------------------------------------------------------------------*/
735 /* copyValue - copies contents of a value to a fresh one            */
736 /*------------------------------------------------------------------*/
737 value *
738 copyValue (value * src)
739 {
740   value *dest;
741
742   dest = newValue ();
743   dest->sym = copySymbol (src->sym);
744   strcpy (dest->name, src->name);
745   dest->type = (src->type ? copyLinkChain (src->type) : NULL);
746   dest->etype = (src->type ? getSpec (dest->type) : NULL);
747
748   return dest;
749 }
750
751 /*------------------------------------------------------------------*/
752 /* charVal - converts a character constant to a value       */
753 /*------------------------------------------------------------------*/
754 value *
755 charVal (char *s)
756 {
757   value *val;
758 //  unsigned uValue ;
759
760   val = newValue ();
761
762   val->type = val->etype = newLink ();
763   val->type->class = SPECIFIER;
764   SPEC_NOUN (val->type) = V_CHAR;
765   SPEC_USIGN(val->type) = 1;
766   SPEC_SCLS (val->type) = S_LITERAL;
767
768   s++;                          /* get rid of quotation */
769   /* if \ then special processing */
770   if (*s == '\\')
771     {
772       s++;                      /* go beyond the backslash  */
773       switch (*s)
774         {
775         case 'n':
776           SPEC_CVAL (val->type).v_int = '\n';
777           break;
778         case 't':
779           SPEC_CVAL (val->type).v_int = '\t';
780           break;
781         case 'v':
782           SPEC_CVAL (val->type).v_int = '\v';
783           break;
784         case 'b':
785           SPEC_CVAL (val->type).v_int = '\b';
786           break;
787         case 'r':
788           SPEC_CVAL (val->type).v_int = '\r';
789           break;
790         case 'f':
791           SPEC_CVAL (val->type).v_int = '\f';
792           break;
793         case 'a':
794           SPEC_CVAL (val->type).v_int = '\a';
795           break;
796         case '\\':
797           SPEC_CVAL (val->type).v_int = '\\';
798           break;
799         case '\?':
800           SPEC_CVAL (val->type).v_int = '\?';
801           break;
802         case '\'':
803           SPEC_CVAL (val->type).v_int = '\'';
804           break;
805         case '\"':
806           SPEC_CVAL (val->type).v_int = '\"';
807           break;
808
809         case '0' :
810         case '1' :
811         case '2' :
812         case '3' :
813         case '4' :
814         case '5' :
815         case '6' :
816         case '7' :
817           SPEC_CVAL (val->type).v_uint = octalEscape(&s);
818           break;
819
820         case 'x':
821           SPEC_CVAL (val->type).v_uint = hexEscape(&s) ;
822           break;
823
824         default:
825           SPEC_CVAL (val->type).v_uint = (unsigned char)*s;
826           break;
827         }
828     }
829   else                          /* not a backslash */
830     SPEC_CVAL (val->type).v_uint = (unsigned char)*s;
831
832   return val;
833 }
834
835 /*------------------------------------------------------------------*/
836 /* valFromType - creates a value from type given                    */
837 /*------------------------------------------------------------------*/
838 value *
839 valFromType (sym_link * type)
840 {
841   value *val = newValue ();
842   val->type = copyLinkChain (type);
843   val->etype = getSpec (val->type);
844   return val;
845 }
846
847 /*------------------------------------------------------------------*/
848 /* floatFromVal - value to unsinged integer conversion        */
849 /*------------------------------------------------------------------*/
850 double 
851 floatFromVal (value * val)
852 {
853   if (!val)
854     return 0;
855
856   if (val->etype && SPEC_SCLS (val->etype) != S_LITERAL)
857     {
858       werror (E_CONST_EXPECTED, val->name);
859       return 0;
860     }
861
862   /* if it is not a specifier then we can assume that */
863   /* it will be an unsigned long                      */
864   if (!IS_SPEC (val->type))
865     return (double) SPEC_CVAL (val->etype).v_ulong;
866
867   if (SPEC_NOUN (val->etype) == V_FLOAT)
868     return (double) SPEC_CVAL (val->etype).v_float;
869
870   if (SPEC_LONG (val->etype))
871     {
872       if (SPEC_USIGN (val->etype))
873         return (double) SPEC_CVAL (val->etype).v_ulong;
874       else
875         return (double) SPEC_CVAL (val->etype).v_long;
876     }
877   
878   if (SPEC_NOUN(val->etype)==V_INT) {
879     if (SPEC_USIGN (val->etype))
880       return (double) SPEC_CVAL (val->etype).v_uint;
881     else
882       return (double) SPEC_CVAL (val->etype).v_int;
883   } else { // SPEC_NOUN==V_CHAR
884     if (SPEC_USIGN (val->etype))
885       return (double) ((unsigned char)SPEC_CVAL (val->etype).v_uint);
886     else
887       return (double) ((signed char)SPEC_CVAL (val->etype).v_int);
888   }
889 }
890
891
892 /*------------------------------------------------------------------*/
893 /* valUnaryPM - does the unary +/- operation on a constant          */
894 /*------------------------------------------------------------------*/
895 value *
896 valUnaryPM (value * val)
897 {
898   /* depending on type */
899   if (SPEC_NOUN (val->etype) == V_FLOAT)
900     SPEC_CVAL (val->etype).v_float = -1.0 * SPEC_CVAL (val->etype).v_float;
901   else
902     {
903       if (SPEC_LONG (val->etype))
904         {
905           if (SPEC_USIGN (val->etype))
906             SPEC_CVAL (val->etype).v_ulong = 0-SPEC_CVAL (val->etype).v_ulong;
907           else
908             SPEC_CVAL (val->etype).v_long = -SPEC_CVAL (val->etype).v_long;
909         }
910       else
911         {
912           if (SPEC_USIGN (val->etype))
913             SPEC_CVAL (val->etype).v_uint = 0-SPEC_CVAL (val->etype).v_uint;
914           else
915             SPEC_CVAL (val->etype).v_int = -SPEC_CVAL (val->etype).v_int;
916           if (SPEC_NOUN (val->etype)==V_CHAR) {
917             SPEC_CVAL (val->etype).v_uint &= 0xff;
918           }
919         }
920     }
921   // -(unsigned 3) now really is signed
922   SPEC_USIGN(val->etype)=0;
923   return val;
924 }
925
926 /*------------------------------------------------------------------*/
927 /* valueComplement - complements a constant                         */
928 /*------------------------------------------------------------------*/
929 value *
930 valComplement (value * val)
931 {
932   /* depending on type */
933   if (SPEC_LONG (val->etype))
934     {
935       if (SPEC_USIGN (val->etype))
936         SPEC_CVAL (val->etype).v_ulong = ~SPEC_CVAL (val->etype).v_ulong;
937       else
938         SPEC_CVAL (val->etype).v_long = ~SPEC_CVAL (val->etype).v_long;
939     }
940   else
941     {
942       if (SPEC_USIGN (val->etype))
943         SPEC_CVAL (val->etype).v_uint = ~SPEC_CVAL (val->etype).v_uint;
944       else
945         SPEC_CVAL (val->etype).v_int = ~SPEC_CVAL (val->etype).v_int;
946       if (SPEC_NOUN (val->etype)==V_CHAR) {
947         SPEC_CVAL (val->etype).v_uint &= 0xff;
948       }
949     }
950   return val;
951 }
952
953 /*------------------------------------------------------------------*/
954 /* valueNot - complements a constant                                */
955 /*------------------------------------------------------------------*/
956 value *
957 valNot (value * val)
958 {
959   /* depending on type */
960   if (SPEC_LONG (val->etype))
961     {
962       if (SPEC_USIGN (val->etype))
963         SPEC_CVAL (val->etype).v_ulong = !SPEC_CVAL (val->etype).v_ulong;
964       else
965         SPEC_CVAL (val->etype).v_long = !SPEC_CVAL (val->etype).v_long;
966     }
967   else
968     {
969       if (SPEC_USIGN (val->etype))
970         SPEC_CVAL (val->etype).v_uint = !SPEC_CVAL (val->etype).v_uint;
971       else
972         SPEC_CVAL (val->etype).v_int = !SPEC_CVAL (val->etype).v_int;
973       if (SPEC_NOUN (val->etype)==V_CHAR) {
974         SPEC_CVAL (val->etype).v_uint &= 0xff;
975       }
976     }
977   return val;
978 }
979
980 /*------------------------------------------------------------------*/
981 /* valMult - multiply constants                                     */
982 /*------------------------------------------------------------------*/
983 value *
984 valMult (value * lval, value * rval)
985 {
986   value *val;
987
988   /* create a new value */
989   val = newValue ();
990   val->type = val->etype = newLink ();
991   val->type->class = SPECIFIER;
992   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
993                            IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
994   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
995   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) & SPEC_USIGN (rval->etype));
996   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
997
998   if (IS_FLOAT (val->type))
999     SPEC_CVAL (val->type).v_float = floatFromVal (lval) * floatFromVal (rval);
1000   else
1001     {
1002       if (SPEC_LONG (val->type))
1003         {
1004           if (SPEC_USIGN (val->type))
1005             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) *
1006               (unsigned long) floatFromVal (rval);
1007           else
1008             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) *
1009               (long) floatFromVal (rval);
1010         }
1011       else
1012         {
1013           if (SPEC_USIGN (val->type))
1014             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) *
1015               (unsigned) floatFromVal (rval);
1016           else
1017             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) *
1018               (int) floatFromVal (rval);
1019         }
1020     }
1021   return cheapestVal(val);
1022 }
1023
1024 /*------------------------------------------------------------------*/
1025 /* valDiv  - Divide   constants                                     */
1026 /*------------------------------------------------------------------*/
1027 value *
1028 valDiv (value * lval, value * rval)
1029 {
1030   value *val;
1031
1032   if (floatFromVal (rval) == 0)
1033     {
1034       werror (E_DIVIDE_BY_ZERO);
1035       return rval;
1036     }
1037
1038   /* create a new value */
1039   val = newValue ();
1040   val->type = val->etype = newLink();
1041   val->type->class = SPECIFIER;
1042   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
1043                            IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
1044   SPEC_SCLS (val->etype) = S_LITERAL;
1045   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) & SPEC_USIGN (rval->etype));
1046   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1047
1048   if (IS_FLOAT (val->type))
1049     SPEC_CVAL (val->type).v_float = floatFromVal (lval) / floatFromVal (rval);
1050   else
1051     {
1052       if (SPEC_LONG (val->type))
1053         {
1054           if (SPEC_USIGN (val->type))
1055             SPEC_CVAL (val->type).v_ulong = 
1056               (unsigned long) floatFromVal (lval) /
1057               (unsigned long) floatFromVal (rval);
1058           else
1059             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) /
1060               (long) floatFromVal (rval);
1061         }
1062       else
1063         {
1064           if (SPEC_USIGN (val->type)) {
1065             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) /
1066               (unsigned) floatFromVal (rval);
1067           } else {
1068             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) /
1069               (int) floatFromVal (rval);
1070           }
1071         }
1072     }
1073   return cheapestVal(val);
1074 }
1075
1076 /*------------------------------------------------------------------*/
1077 /* valMod  - Modulus  constants                                     */
1078 /*------------------------------------------------------------------*/
1079 value *
1080 valMod (value * lval, value * rval)
1081 {
1082   value *val;
1083
1084   /* create a new value */
1085   val = newValue ();
1086   val->type = val->etype = newLink ();
1087   val->type->class = SPECIFIER;
1088   SPEC_NOUN (val->type) = V_INT;        /* type is int */
1089   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1090   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) & SPEC_USIGN (rval->etype));
1091   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1092
1093   if (SPEC_LONG (val->type))
1094     {
1095       if (SPEC_USIGN (val->type))
1096         SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) %
1097           (unsigned long) floatFromVal (rval);
1098       else
1099         SPEC_CVAL (val->type).v_long = (unsigned long) floatFromVal (lval) %
1100           (unsigned long) floatFromVal (rval);
1101     }
1102   else
1103     {
1104       if (SPEC_USIGN (val->type)) {
1105         SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) %
1106           (unsigned) floatFromVal (rval);
1107       } else {
1108         SPEC_CVAL (val->type).v_int = (unsigned) floatFromVal (lval) %
1109           (unsigned) floatFromVal (rval);
1110       }
1111     }
1112
1113   return cheapestVal(val);
1114 }
1115
1116 /*------------------------------------------------------------------*/
1117 /* valPlus - Addition constants                                     */
1118 /*------------------------------------------------------------------*/
1119 value *
1120 valPlus (value * lval, value * rval)
1121 {
1122   value *val;
1123
1124   /* create a new value */
1125   val = newValue ();
1126   val->type = val->etype = newLink ();
1127   val->type->class = SPECIFIER;
1128   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
1129                            IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
1130   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1131   SPEC_USIGN (val->type) = 
1132     SPEC_USIGN (lval->etype) &&
1133     SPEC_USIGN (rval->etype) &&
1134     (floatFromVal(lval)+floatFromVal(rval))>=0;
1135     
1136   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1137
1138   if (IS_FLOAT (val->type))
1139     SPEC_CVAL (val->type).v_float = floatFromVal (lval) + floatFromVal (rval);
1140   else
1141     {
1142       if (SPEC_LONG (val->type))
1143         {
1144           if (SPEC_USIGN (val->type))
1145             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) +
1146               (unsigned long) floatFromVal (rval);
1147           else
1148             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) +
1149               (long) floatFromVal (rval);
1150         }
1151       else
1152         {
1153           if (SPEC_USIGN (val->type)) {
1154             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) +
1155               (unsigned) floatFromVal (rval);
1156           } else {
1157             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) +
1158               (int) floatFromVal (rval);
1159           }
1160         }
1161     }
1162   return cheapestVal(val);
1163 }
1164
1165 /*------------------------------------------------------------------*/
1166 /* valMinus - Addition constants                                    */
1167 /*------------------------------------------------------------------*/
1168 value *
1169 valMinus (value * lval, value * rval)
1170 {
1171   value *val;
1172
1173   /* create a new value */
1174   val = newValue ();
1175   val->type = val->etype = newLink ();
1176   val->type->class = SPECIFIER;
1177   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
1178                            IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
1179   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1180   SPEC_USIGN (val->type) = 
1181     SPEC_USIGN (lval->etype) &&
1182     SPEC_USIGN (rval->etype) &&
1183     (floatFromVal(lval)-floatFromVal(rval))>=0;
1184
1185   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1186
1187   if (IS_FLOAT (val->type))
1188     SPEC_CVAL (val->type).v_float = floatFromVal (lval) - floatFromVal (rval);
1189   else
1190     {
1191       if (SPEC_LONG (val->type))
1192         {
1193           if (SPEC_USIGN (val->type)) {
1194             SPEC_CVAL (val->type).v_ulong = 
1195               (unsigned long) floatFromVal (lval) -
1196               (unsigned long) floatFromVal (rval);
1197           } else {
1198             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) -
1199               (long) floatFromVal (rval);
1200           }
1201         }
1202       else
1203         {
1204           if (SPEC_USIGN (val->type)) {
1205             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) -
1206               (unsigned) floatFromVal (rval);
1207           } else {
1208             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) - 
1209               (int) floatFromVal (rval);
1210           }
1211         }
1212     }
1213   return cheapestVal(val);
1214 }
1215
1216 /*------------------------------------------------------------------*/
1217 /* valShift - Shift left or right                                   */
1218 /*------------------------------------------------------------------*/
1219 value *
1220 valShift (value * lval, value * rval, int lr)
1221 {
1222   value *val;
1223
1224   /* create a new value */
1225   val = newValue ();
1226   val->type = val->etype = newIntLink ();
1227   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1228   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) & SPEC_USIGN (rval->etype));
1229   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1230
1231   if (SPEC_LONG (val->type))
1232     {
1233       if (SPEC_USIGN (val->type))
1234         SPEC_CVAL (val->type).v_ulong = lr ? 
1235           (unsigned long) floatFromVal (lval) << (unsigned long) floatFromVal (rval) : \
1236           (unsigned long) floatFromVal (lval) >> (unsigned long) floatFromVal (rval);
1237       else
1238         SPEC_CVAL (val->type).v_long = lr ?
1239           (long) floatFromVal (lval) << (long) floatFromVal (rval) : \
1240           (long) floatFromVal (lval) >> (long) floatFromVal (rval);
1241     }
1242   else
1243     {
1244       if (SPEC_USIGN (val->type)) {
1245         SPEC_CVAL (val->type).v_uint = lr ? 
1246           (unsigned) floatFromVal (lval) << (unsigned) floatFromVal (rval) :\
1247           (unsigned) floatFromVal (lval) >> (unsigned) floatFromVal (rval);
1248       } else {
1249         SPEC_CVAL (val->type).v_int = lr ?
1250           (int) floatFromVal (lval) << (int) floatFromVal (rval) : \
1251           (int) floatFromVal (lval) >> (int) floatFromVal (rval);
1252       }
1253     }
1254
1255   return cheapestVal(val);
1256 }
1257
1258 /*------------------------------------------------------------------*/
1259 /* valCompare- Compares two literal                                 */
1260 /*------------------------------------------------------------------*/
1261 value *
1262 valCompare (value * lval, value * rval, int ctype)
1263 {
1264   value *val;
1265
1266   /* create a new value */
1267   val = newValue ();
1268   val->type = val->etype = newCharLink ();
1269   val->type->class = SPECIFIER;
1270   SPEC_NOUN (val->type) = V_CHAR;       /* type is char */
1271   SPEC_USIGN (val->type) = 1;
1272   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1273
1274   switch (ctype)
1275     {
1276     case '<':
1277       SPEC_CVAL (val->type).v_int = floatFromVal (lval) < floatFromVal (rval);
1278       break;
1279
1280     case '>':
1281       SPEC_CVAL (val->type).v_int = floatFromVal (lval) > floatFromVal (rval);
1282       break;
1283
1284     case LE_OP:
1285       SPEC_CVAL (val->type).v_int = floatFromVal (lval) <= floatFromVal (rval);
1286       break;
1287
1288     case GE_OP:
1289       SPEC_CVAL (val->type).v_int = floatFromVal (lval) >= floatFromVal (rval);
1290       break;
1291
1292     case EQ_OP:
1293       SPEC_CVAL (val->type).v_int = floatFromVal (lval) == floatFromVal (rval);
1294       break;
1295
1296     case NE_OP:
1297       SPEC_CVAL (val->type).v_int = floatFromVal (lval) != floatFromVal (rval);
1298       break;
1299
1300     }
1301
1302   return val;
1303 }
1304
1305 /*------------------------------------------------------------------*/
1306 /* valBitwise - Bitwise operation                                   */
1307 /*------------------------------------------------------------------*/
1308 value *
1309 valBitwise (value * lval, value * rval, int op)
1310 {
1311   value *val;
1312
1313   /* create a new value */
1314   val = newValue ();
1315   val->type = copyLinkChain (lval->type);
1316   val->etype = getSpec (val->type);
1317
1318   switch (op)
1319     {
1320     case '&':
1321       if (SPEC_LONG (val->type))
1322         {
1323           if (SPEC_USIGN (val->type))
1324             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) &
1325               (unsigned long) floatFromVal (rval);
1326           else
1327             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) &
1328               (long) floatFromVal (rval);
1329         }
1330       else
1331         {
1332           if (SPEC_USIGN (val->type))
1333             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) &
1334               (unsigned) floatFromVal (rval);
1335           else
1336             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) & (int) floatFromVal (rval);
1337         }
1338       break;
1339
1340     case '|':
1341       if (SPEC_LONG (val->type))
1342         {
1343           if (SPEC_USIGN (val->type))
1344             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) |
1345               (unsigned long) floatFromVal (rval);
1346           else
1347             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) |
1348               (long) floatFromVal (rval);
1349         }
1350       else
1351         {
1352           if (SPEC_USIGN (val->type))
1353             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) |
1354               (unsigned) floatFromVal (rval);
1355           else
1356             SPEC_CVAL (val->type).v_int =
1357               (int) floatFromVal (lval) | (int) floatFromVal (rval);
1358         }
1359
1360       break;
1361
1362     case '^':
1363       if (SPEC_LONG (val->type))
1364         {
1365           if (SPEC_USIGN (val->type))
1366             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) ^
1367               (unsigned long) floatFromVal (rval);
1368           else
1369             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) ^
1370               (long) floatFromVal (rval);
1371         }
1372       else
1373         {
1374           if (SPEC_USIGN (val->type))
1375             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) ^
1376               (unsigned) floatFromVal (rval);
1377           else
1378             SPEC_CVAL (val->type).v_int =
1379               (int) floatFromVal (lval) ^ (int) floatFromVal (rval);
1380         }
1381       break;
1382     }
1383
1384   return cheapestVal(val);
1385 }
1386
1387 /*------------------------------------------------------------------*/
1388 /* valAndOr   - Generates code for and / or operation               */
1389 /*------------------------------------------------------------------*/
1390 value *
1391 valLogicAndOr (value * lval, value * rval, int op)
1392 {
1393   value *val;
1394
1395   /* create a new value */
1396   val = newValue ();
1397   val->type = val->etype = newCharLink ();
1398   val->type->class = SPECIFIER;
1399   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1400   SPEC_USIGN (val->type) = 0;
1401
1402   switch (op)
1403     {
1404     case AND_OP:
1405       SPEC_CVAL (val->type).v_int = floatFromVal (lval) && floatFromVal (rval);
1406       break;
1407
1408     case OR_OP:
1409       SPEC_CVAL (val->type).v_int = floatFromVal (lval) || floatFromVal (rval);
1410       break;
1411     }
1412
1413
1414   return val;
1415 }
1416
1417 /*------------------------------------------------------------------*/
1418 /* valCastLiteral - casts a literal value to another type           */
1419 /*------------------------------------------------------------------*/
1420 value *
1421 valCastLiteral (sym_link * dtype, double fval)
1422 {
1423   value *val;
1424
1425   if (!dtype)
1426     return NULL;
1427
1428   val = newValue ();
1429   val->etype = getSpec (val->type = copyLinkChain (dtype));
1430   SPEC_SCLS (val->etype) = S_LITERAL;
1431   /* if it is not a specifier then we can assume that */
1432   /* it will be an unsigned long                      */
1433   if (!IS_SPEC (val->type))
1434     {
1435       SPEC_CVAL (val->etype).v_ulong = (unsigned long) fval;
1436       return val;
1437     }
1438
1439   if (SPEC_NOUN (val->etype) == V_FLOAT)
1440     SPEC_CVAL (val->etype).v_float = fval;
1441   else
1442     {
1443       if (SPEC_LONG (val->etype))
1444         {
1445           if (SPEC_USIGN (val->etype))
1446             SPEC_CVAL (val->etype).v_ulong = (unsigned long) fval;
1447           else
1448             SPEC_CVAL (val->etype).v_long = (long) fval;
1449         }
1450       else
1451         {
1452           if (SPEC_USIGN (val->etype))
1453             SPEC_CVAL (val->etype).v_uint = (unsigned short)fval;
1454           else
1455             SPEC_CVAL (val->etype).v_int = (short)fval;
1456           if (SPEC_NOUN (val->etype)==V_CHAR) {
1457             SPEC_CVAL (val->etype).v_uint &= 0xff; 
1458           }
1459         }
1460     }
1461   return val;
1462 }
1463
1464 /*------------------------------------------------------------------*/
1465 /* getNelements - determines # of elements from init list           */
1466 /*------------------------------------------------------------------*/
1467 int 
1468 getNelements (sym_link * type, initList * ilist)
1469 {
1470   sym_link *etype = getSpec (type);
1471   int i;
1472
1473   if (!ilist)
1474     return 0;
1475
1476   if (ilist->type == INIT_DEEP)
1477     ilist = ilist->init.deep;
1478
1479   /* if type is a character array and there is only one
1480      (string) initialiser then get the length of the string */
1481   if (IS_ARRAY (type) && IS_CHAR (etype) && !ilist->next)
1482     {
1483       ast *iast = ilist->init.node;
1484       value *v = (iast->type == EX_VALUE ? iast->opval.val : NULL);
1485       if (!v)
1486         {
1487           werror (W_INIT_WRONG);
1488           return 0;
1489         }
1490
1491       if (IS_ARRAY (v->type) && IS_CHAR (v->etype))
1492         // yep, it's a string
1493         {
1494           return DCL_ELEM (v->type);
1495         }
1496     }
1497
1498   i = 0;
1499   while (ilist)
1500     {
1501       i++;
1502       ilist = ilist->next;
1503     }
1504
1505   return i;
1506 }
1507
1508 /*-----------------------------------------------------------------*/
1509 /* valForArray - returns a value with name of array index          */
1510 /*-----------------------------------------------------------------*/
1511 value *
1512 valForArray (ast * arrExpr)
1513 {
1514   value *val, *lval = NULL;
1515   char buffer[128];
1516   int size = getSize (arrExpr->left->ftype->next);
1517   /* if the right or left is an array
1518      resolve it first */
1519   if (IS_AST_OP (arrExpr->left))
1520     {
1521       if (arrExpr->left->opval.op == '[')
1522         lval = valForArray (arrExpr->left);
1523       else if (arrExpr->left->opval.op == '.')
1524         lval = valForStructElem (arrExpr->left->left,
1525                                  arrExpr->left->right);
1526       else if (arrExpr->left->opval.op == PTR_OP &&
1527                IS_ADDRESS_OF_OP (arrExpr->left->left))
1528         lval = valForStructElem (arrExpr->left->left->left,
1529                                  arrExpr->left->right);
1530       else
1531         return NULL;
1532
1533     }
1534   else if (!IS_AST_SYM_VALUE (arrExpr->left))
1535     return NULL;
1536
1537   if (!IS_AST_LIT_VALUE (arrExpr->right))
1538     return NULL;
1539
1540   val = newValue ();
1541   if (!lval)
1542     sprintf (buffer, "%s", AST_SYMBOL (arrExpr->left)->rname);
1543   else
1544     sprintf (buffer, "%s", lval->name);
1545
1546   sprintf (val->name, "(%s + %d)", buffer,
1547            (int) AST_LIT_VALUE (arrExpr->right) * size);
1548
1549   val->type = newLink ();
1550   if (SPEC_SCLS (arrExpr->left->etype) == S_CODE)
1551     {
1552       DCL_TYPE (val->type) = CPOINTER;
1553       DCL_PTR_CONST (val->type) = port->mem.code_ro;
1554     }
1555   else if (SPEC_SCLS (arrExpr->left->etype) == S_XDATA)
1556     DCL_TYPE (val->type) = FPOINTER;
1557   else if (SPEC_SCLS (arrExpr->left->etype) == S_XSTACK)
1558     DCL_TYPE (val->type) = PPOINTER;
1559   else if (SPEC_SCLS (arrExpr->left->etype) == S_IDATA)
1560     DCL_TYPE (val->type) = IPOINTER;
1561   else if (SPEC_SCLS (arrExpr->left->etype) == S_EEPROM)
1562     DCL_TYPE (val->type) = EEPPOINTER;
1563   else
1564     DCL_TYPE (val->type) = POINTER;
1565   val->type->next = arrExpr->left->ftype;
1566   val->etype = getSpec (val->type);
1567   return val;
1568 }
1569
1570 /*-----------------------------------------------------------------*/
1571 /* valForStructElem - returns value with name of struct element    */
1572 /*-----------------------------------------------------------------*/
1573 value *
1574 valForStructElem (ast * structT, ast * elemT)
1575 {
1576   value *val, *lval = NULL;
1577   char buffer[128];
1578   symbol *sym;
1579
1580   /* left could be furthur derefed */
1581   if (IS_AST_OP (structT))
1582     {
1583       if (structT->opval.op == '[')
1584         lval = valForArray (structT);
1585       else if (structT->opval.op == '.')
1586         lval = valForStructElem (structT->left, structT->right);
1587       else if (structT->opval.op == PTR_OP &&
1588                IS_ADDRESS_OF_OP (structT->left))
1589         lval = valForStructElem (structT->left->left,
1590                                  structT->right);
1591       else
1592         return NULL;
1593     }
1594
1595   if (!IS_AST_SYM_VALUE (elemT))
1596     return NULL;
1597
1598   if (!IS_STRUCT (structT->etype))
1599     return NULL;
1600
1601   if ((sym = getStructElement (SPEC_STRUCT (structT->etype),
1602                                AST_SYMBOL (elemT))) == NULL)
1603     {
1604       return NULL;
1605     }
1606
1607   val = newValue ();
1608   if (!lval)
1609     sprintf (buffer, "%s", AST_SYMBOL (structT)->rname);
1610   else
1611     sprintf (buffer, "%s", lval->name);
1612
1613   sprintf (val->name, "(%s + %d)", buffer,
1614            (int) sym->offset);
1615
1616   val->type = newLink ();
1617   if (SPEC_SCLS (structT->etype) == S_CODE)
1618     {
1619       DCL_TYPE (val->type) = CPOINTER;
1620       DCL_PTR_CONST (val->type) = port->mem.code_ro;
1621     }
1622   else if (SPEC_SCLS (structT->etype) == S_XDATA)
1623     DCL_TYPE (val->type) = FPOINTER;
1624   else if (SPEC_SCLS (structT->etype) == S_XSTACK)
1625     DCL_TYPE (val->type) = PPOINTER;
1626   else if (SPEC_SCLS (structT->etype) == S_IDATA)
1627     DCL_TYPE (val->type) = IPOINTER;
1628   else if (SPEC_SCLS (structT->etype) == S_EEPROM)
1629     DCL_TYPE (val->type) = EEPPOINTER;
1630   else
1631     DCL_TYPE (val->type) = POINTER;
1632   val->type->next = sym->type;
1633   val->etype = getSpec (val->type);
1634   return val;
1635 }
1636
1637 /*-----------------------------------------------------------------*/
1638 /* valForCastAggr - will return value for a cast of an aggregate   */
1639 /*                  plus minus a constant                          */
1640 /*-----------------------------------------------------------------*/
1641 value *
1642 valForCastAggr (ast * aexpr, sym_link * type, ast * cnst, int op)
1643 {
1644   value *val;
1645
1646   if (!IS_AST_SYM_VALUE (aexpr))
1647     return NULL;
1648   if (!IS_AST_LIT_VALUE (cnst))
1649     return NULL;
1650
1651   val = newValue ();
1652
1653   sprintf (val->name, "(%s %c %d)",
1654            AST_SYMBOL (aexpr)->rname, op,
1655            getSize (type->next) * (int) AST_LIT_VALUE (cnst));
1656
1657   val->type = type;
1658   val->etype = getSpec (val->type);
1659   return val;
1660 }
1661
1662 /*-----------------------------------------------------------------*/
1663 /* valForCastAggr - will return value for a cast of an aggregate   */
1664 /*                  with no constant                               */
1665 /*-----------------------------------------------------------------*/
1666 value *
1667 valForCastArr (ast * aexpr, sym_link * type)
1668 {
1669   value *val;
1670
1671   if (!IS_AST_SYM_VALUE (aexpr))
1672     return NULL;
1673
1674   val = newValue ();
1675
1676   sprintf (val->name, "(%s)",
1677            AST_SYMBOL (aexpr)->rname);
1678
1679   val->type = type;
1680   val->etype = getSpec (val->type);
1681   return val;
1682 }