6d645ee200cfa4010ebe33ed34364520ce58b9ff
[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<=0xffff) {
347       SPEC_LONG(val->type)=0;
348       SPEC_CVAL(val->type).v_uint = uval;
349     }
350     if (uval<=0xff) {
351       SPEC_NOUN(val->type)=V_CHAR;
352     }
353   } else { // not unsigned
354     if (sval<0) {
355       if (sval>=-32768) {
356         SPEC_LONG(val->type)=0;
357         SPEC_CVAL(val->type).v_int = sval & 0xffff;
358       }
359       if (sval>=-128) {
360         SPEC_NOUN(val->type)=V_CHAR;
361         SPEC_CVAL(val->type).v_int &= 0xff;
362       }
363     } else { // sval>=0
364       SPEC_USIGN(val->type)=1;
365       if (sval<=65535) {
366         SPEC_LONG(val->type)=0;
367         SPEC_CVAL(val->type).v_int = sval;
368       }
369       if (sval<=255) {
370         SPEC_NOUN(val->type)=V_CHAR;
371       }
372     }
373   }
374   return val;
375 }
376
377 /*-----------------------------------------------------------------*/
378 /* valueFromLit - creates a value from a literal                   */
379 /*-----------------------------------------------------------------*/
380 value *
381 valueFromLit (double lit)
382 {
383   char buffer[50];
384
385   if ((((long) lit) - lit) == 0)
386     {
387       sprintf (buffer, "%ld", (long) lit);
388       return constVal (buffer);
389     }
390
391   sprintf (buffer, "%f", lit);
392   return constFloatVal (buffer);
393 }
394
395 /*-----------------------------------------------------------------*/
396 /* constFloatVal - converts a FLOAT constant to value              */
397 /*-----------------------------------------------------------------*/
398 value *
399 constFloatVal (char *s)
400 {
401   value *val = newValue ();
402   double sval;
403
404   if (sscanf (s, "%lf", &sval) != 1)
405     {
406       werror (E_INVALID_FLOAT_CONST, s);
407       return constVal ("0");
408     }
409
410   val->type = val->etype = newLink ();
411   val->type->class = SPECIFIER;
412   SPEC_NOUN (val->type) = V_FLOAT;
413   SPEC_SCLS (val->type) = S_LITERAL;
414   SPEC_CVAL (val->type).v_float = sval;
415
416   return val;
417 }
418
419 /*-----------------------------------------------------------------*/
420 /* constVal - converts an INTEGER constant into a cheapest value   */
421 /*-----------------------------------------------------------------*/
422 value *constVal (char *s)
423 {
424   value *val;
425   short hex = 0, octal = 0;
426   char scanFmt[10];
427   int scI = 0;
428   LONG_LONG sval;
429
430   val = newValue ();            /* alloc space for value   */
431
432   val->type = val->etype = newLink ();  /* create the spcifier */
433   val->type->class = SPECIFIER;
434   SPEC_SCLS (val->type) = S_LITERAL;
435   // let's start with an unsigned char
436   SPEC_NOUN (val->type) = V_CHAR;
437   SPEC_USIGN (val->type) = 1;
438
439   /* set the _long flag if 'lL' is found */
440   if (strchr (s, 'l') || strchr (s, 'L'))
441     SPEC_LONG (val->type) = 1;
442
443   hex = ((strchr (s, 'x') || strchr (s, 'X')) ? 1 : 0);
444
445   /* set the octal flag   */
446   if (!hex && *s == '0' && *(s + 1))
447     octal = 1;
448
449   /* create the scan string */
450   scanFmt[scI++] = '%';
451
452   scanFmt[scI++] = 'l';
453   scanFmt[scI++] = 'l';
454
455   if (octal)
456     scanFmt[scI++] = 'o';
457   else if (hex)
458     scanFmt[scI++] = 'x';
459   else
460     scanFmt[scI++] = 'd';
461
462   scanFmt[scI++] = '\0';
463
464   sscanf (s, scanFmt, &sval);
465
466   if (sval<0) { // "-28u" will still be signed and negative
467     SPEC_USIGN (val->type) = 0;
468     if (sval<-32768) { // check if we have to promote to long
469       SPEC_NOUN (val->type) = V_INT;
470       SPEC_LONG (val->type) = 1;
471       SPEC_CVAL (val->type).v_long=sval;
472     } else {
473       SPEC_CVAL (val->type).v_int=sval;
474       if (sval<-128) { // check if we have to promote to int
475         SPEC_NOUN (val->type) = V_INT;
476       }
477     }
478   } else {
479     if (sval>0xffff) { // check if we have to promote to long
480       SPEC_NOUN (val->type) = V_INT;
481       SPEC_LONG (val->type) = 1;
482       SPEC_CVAL (val->type).v_ulong=sval;
483     } else {
484       SPEC_CVAL (val->type).v_uint=sval;
485       if (sval>0xff) { // check if we have to promote to int
486         SPEC_NOUN (val->type) = V_INT;
487       }
488     }
489   }
490
491   return val;
492 }
493
494 /*! /fn char hexEscape(char **src)
495
496     /param src Pointer to 'x' from start of hex character value
497 */
498
499 unsigned char hexEscape(char **src)
500 {
501   char *s ;
502   unsigned long value ;
503   
504   (*src)++ ;    /* Skip over the 'x' */
505   s = *src ;    /* Save for error detection */
506   
507   value = strtol (*src, src, 16);
508   
509   if (s == *src) {
510       // no valid hex found
511       werror(E_INVALID_HEX);
512   } else {
513     if (value > 255) {
514       werror(W_ESC_SEQ_OOR_FOR_CHAR);
515     }
516   }
517   return (char) value;
518 }
519
520 /*------------------------------------------------------------------*/
521 /* octalEscape - process an octal constant of max three digits      */
522 /* return the octal value, throw a warning for illegal octal        */
523 /* adjust src to point at the last proccesed char                   */
524 /*------------------------------------------------------------------*/
525
526 unsigned char octalEscape (char **str) {
527   int digits;
528   unsigned value=0;
529
530   for (digits=0; digits<3; digits++) {
531     if (**str>='0' && **str<='7') {
532       value = value*8 + (**str-'0');
533       (*str)++;
534     } else {
535       break;
536     }
537   }
538   if (digits) {
539     if (value > 255 /* || (**str>='0' && **str<='7') */ ) {
540       werror (W_ESC_SEQ_OOR_FOR_CHAR);
541     }
542   }
543   return value;
544 }
545
546 /*! 
547   /fn int copyStr (char *dest, char *src)
548   
549   Copies a source string to a dest buffer interpreting escape sequences
550   and special characters
551
552   /param dest Buffer to receive the resultant string
553   /param src  Buffer containing the source string with escape sequecnes
554   /return Number of characters in output string
555
556 */
557
558 int 
559 copyStr (char *dest, char *src)
560
561 {
562   char *OriginalDest = dest ;
563
564   while (*src)
565     {
566       if (*src == '\"')
567         src++;
568       else if (*src == '\\')
569         {
570           src++;
571           switch (*src)
572             {
573             case 'n':
574               *dest++ = '\n';
575               break;
576             case 't':
577               *dest++ = '\t';
578               break;
579             case 'v':
580               *dest++ = '\v';
581               break;
582             case 'b':
583               *dest++ = '\b';
584               break;
585             case 'r':
586               *dest++ = '\r';
587               break;
588             case 'f':
589               *dest++ = '\f';
590               break;
591             case 'a':
592               *dest++ = '\a';
593               break;
594
595             case '0':
596             case '1':
597             case '2':
598             case '3':
599             case '4':
600             case '5':
601             case '6':
602             case '7':
603               *dest++ = octalEscape(&src);
604               src-- ;
605               break;
606
607             case 'x': 
608               *dest++ = hexEscape(&src) ;
609               src-- ;
610               break ;
611
612             case '\\':
613               *dest++ = '\\';
614               break;
615             case '\?':
616               *dest++ = '\?';
617               break;
618             case '\'':
619               *dest++ = '\'';
620               break;
621             case '\"':
622               *dest++ = '\"';
623               break;
624             default:
625               *dest++ = *src;
626             }
627           src++;
628         }
629       else
630         *dest++ = *src++;
631     }
632
633   *dest++ = '\0';
634
635   return dest - OriginalDest ;
636 }
637
638 /*------------------------------------------------------------------*/
639 /* strVal - converts a string constant to a value       */
640 /*------------------------------------------------------------------*/
641 value *
642 strVal (char *s)
643 {
644   value *val;
645
646   val = newValue ();            /* get a new one */
647
648   /* get a declarator */
649   val->type = newLink ();
650   DCL_TYPE (val->type) = ARRAY;
651   val->type->next = val->etype = newLink ();
652   val->etype->class = SPECIFIER;
653   SPEC_NOUN (val->etype) = V_CHAR;
654   SPEC_SCLS (val->etype) = S_LITERAL;
655
656   SPEC_CVAL (val->etype).v_char = Safe_alloc (strlen (s) + 1);
657   DCL_ELEM (val->type) = copyStr (SPEC_CVAL (val->etype).v_char, s);
658
659   return val;
660 }
661
662
663 /*------------------------------------------------------------------*/
664 /* reverseValWithType - reverses value chain with type & etype      */
665 /*------------------------------------------------------------------*/
666 value *
667 reverseValWithType (value * val)
668 {
669   sym_link *type;
670   sym_link *etype;
671
672   if (!val)
673     return NULL;
674
675   /* save the type * etype chains */
676   type = val->type;
677   etype = val->etype;
678
679   /* set the current one 2b null */
680   val->type = val->etype = NULL;
681   val = reverseVal (val);
682
683   /* restore type & etype */
684   val->type = type;
685   val->etype = etype;
686
687   return val;
688 }
689
690 /*------------------------------------------------------------------*/
691 /* reverseVal - reverses the values for a value  chain        */
692 /*------------------------------------------------------------------*/
693 value *
694 reverseVal (value * val)
695 {
696   value *prev, *curr, *next;
697
698   if (!val)
699     return NULL;
700
701   prev = val;
702   curr = val->next;
703
704   while (curr)
705     {
706       next = curr->next;
707       curr->next = prev;
708       prev = curr;
709       curr = next;
710     }
711   val->next = (void *) NULL;
712   return prev;
713 }
714
715 /*------------------------------------------------------------------*/
716 /* copyValueChain - will copy a chain of values                     */
717 /*------------------------------------------------------------------*/
718 value *
719 copyValueChain (value * src)
720 {
721   value *dest;
722
723   if (!src)
724     return NULL;
725
726   dest = copyValue (src);
727   dest->next = copyValueChain (src->next);
728
729   return dest;
730 }
731
732 /*------------------------------------------------------------------*/
733 /* copyValue - copies contents of a value to a fresh one            */
734 /*------------------------------------------------------------------*/
735 value *
736 copyValue (value * src)
737 {
738   value *dest;
739
740   dest = newValue ();
741   dest->sym = copySymbol (src->sym);
742   strcpy (dest->name, src->name);
743   dest->type = (src->type ? copyLinkChain (src->type) : NULL);
744   dest->etype = (src->type ? getSpec (dest->type) : NULL);
745
746   return dest;
747 }
748
749 /*------------------------------------------------------------------*/
750 /* charVal - converts a character constant to a value       */
751 /*------------------------------------------------------------------*/
752 value *
753 charVal (char *s)
754 {
755   value *val;
756 //  unsigned uValue ;
757
758   val = newValue ();
759
760   val->type = val->etype = newLink ();
761   val->type->class = SPECIFIER;
762   SPEC_NOUN (val->type) = V_CHAR;
763   SPEC_USIGN(val->type) = 1;
764   SPEC_SCLS (val->type) = S_LITERAL;
765
766   s++;                          /* get rid of quotation */
767   /* if \ then special processing */
768   if (*s == '\\')
769     {
770       s++;                      /* go beyond the backslash  */
771       switch (*s)
772         {
773         case 'n':
774           SPEC_CVAL (val->type).v_int = '\n';
775           break;
776         case 't':
777           SPEC_CVAL (val->type).v_int = '\t';
778           break;
779         case 'v':
780           SPEC_CVAL (val->type).v_int = '\v';
781           break;
782         case 'b':
783           SPEC_CVAL (val->type).v_int = '\b';
784           break;
785         case 'r':
786           SPEC_CVAL (val->type).v_int = '\r';
787           break;
788         case 'f':
789           SPEC_CVAL (val->type).v_int = '\f';
790           break;
791         case 'a':
792           SPEC_CVAL (val->type).v_int = '\a';
793           break;
794         case '\\':
795           SPEC_CVAL (val->type).v_int = '\\';
796           break;
797         case '\?':
798           SPEC_CVAL (val->type).v_int = '\?';
799           break;
800         case '\'':
801           SPEC_CVAL (val->type).v_int = '\'';
802           break;
803         case '\"':
804           SPEC_CVAL (val->type).v_int = '\"';
805           break;
806
807         case '0' :
808         case '1' :
809         case '2' :
810         case '3' :
811         case '4' :
812         case '5' :
813         case '6' :
814         case '7' :
815           SPEC_CVAL (val->type).v_uint = octalEscape(&s);
816           break;
817
818         case 'x':
819           SPEC_CVAL (val->type).v_uint = hexEscape(&s) ;
820           break;
821
822         default:
823           SPEC_CVAL (val->type).v_uint = (unsigned char)*s;
824           break;
825         }
826     }
827   else                          /* not a backslash */
828     SPEC_CVAL (val->type).v_uint = (unsigned char)*s;
829
830   return val;
831 }
832
833 /*------------------------------------------------------------------*/
834 /* valFromType - creates a value from type given                    */
835 /*------------------------------------------------------------------*/
836 value *
837 valFromType (sym_link * type)
838 {
839   value *val = newValue ();
840   val->type = copyLinkChain (type);
841   val->etype = getSpec (val->type);
842   return val;
843 }
844
845 /*------------------------------------------------------------------*/
846 /* floatFromVal - value to unsinged integer conversion        */
847 /*------------------------------------------------------------------*/
848 double 
849 floatFromVal (value * val)
850 {
851   if (!val)
852     return 0;
853
854   if (val->etype && SPEC_SCLS (val->etype) != S_LITERAL)
855     {
856       werror (E_CONST_EXPECTED, val->name);
857       return 0;
858     }
859
860   /* if it is not a specifier then we can assume that */
861   /* it will be an unsigned long                      */
862   if (!IS_SPEC (val->type))
863     return (double) SPEC_CVAL (val->etype).v_ulong;
864
865   if (SPEC_NOUN (val->etype) == V_FLOAT)
866     return (double) SPEC_CVAL (val->etype).v_float;
867
868   if (SPEC_LONG (val->etype))
869     {
870       if (SPEC_USIGN (val->etype))
871         return (double) SPEC_CVAL (val->etype).v_ulong;
872       else
873         return (double) SPEC_CVAL (val->etype).v_long;
874     }
875   
876   if (SPEC_NOUN(val->etype)==V_INT) {
877     if (SPEC_USIGN (val->etype))
878       return (double) SPEC_CVAL (val->etype).v_uint;
879     else
880       return (double) SPEC_CVAL (val->etype).v_int;
881   } else { // SPEC_NOUN==V_CHAR
882     if (SPEC_USIGN (val->etype))
883       return (double) ((unsigned char)SPEC_CVAL (val->etype).v_uint);
884     else
885       return (double) ((signed char)SPEC_CVAL (val->etype).v_int);
886   }
887 }
888
889
890 /*------------------------------------------------------------------*/
891 /* valUnaryPM - does the unary +/- operation on a constant          */
892 /*------------------------------------------------------------------*/
893 value *
894 valUnaryPM (value * val)
895 {
896   /* depending on type */
897   if (SPEC_NOUN (val->etype) == V_FLOAT)
898     SPEC_CVAL (val->etype).v_float = -1.0 * SPEC_CVAL (val->etype).v_float;
899   else
900     {
901       if (SPEC_LONG (val->etype))
902         {
903           if (SPEC_USIGN (val->etype))
904             SPEC_CVAL (val->etype).v_ulong = 0-SPEC_CVAL (val->etype).v_ulong;
905           else
906             SPEC_CVAL (val->etype).v_long = -SPEC_CVAL (val->etype).v_long;
907         }
908       else
909         {
910           if (SPEC_USIGN (val->etype))
911             SPEC_CVAL (val->etype).v_uint = 0-SPEC_CVAL (val->etype).v_uint;
912           else
913             SPEC_CVAL (val->etype).v_int = -SPEC_CVAL (val->etype).v_int;
914           if (SPEC_NOUN (val->etype)==V_CHAR) {
915             SPEC_CVAL (val->etype).v_uint &= 0xff;
916           }
917         }
918     }
919   // -(unsigned 3) now really is signed
920   SPEC_USIGN(val->etype)=0;
921   return val;
922 }
923
924 /*------------------------------------------------------------------*/
925 /* valueComplement - complements a constant                         */
926 /*------------------------------------------------------------------*/
927 value *
928 valComplement (value * val)
929 {
930   /* depending on type */
931   if (SPEC_LONG (val->etype))
932     {
933       if (SPEC_USIGN (val->etype))
934         SPEC_CVAL (val->etype).v_ulong = ~SPEC_CVAL (val->etype).v_ulong;
935       else
936         SPEC_CVAL (val->etype).v_long = ~SPEC_CVAL (val->etype).v_long;
937     }
938   else
939     {
940       if (SPEC_USIGN (val->etype))
941         SPEC_CVAL (val->etype).v_uint = ~SPEC_CVAL (val->etype).v_uint;
942       else
943         SPEC_CVAL (val->etype).v_int = ~SPEC_CVAL (val->etype).v_int;
944       if (SPEC_NOUN (val->etype)==V_CHAR) {
945         SPEC_CVAL (val->etype).v_uint &= 0xff;
946       }
947     }
948   return val;
949 }
950
951 /*------------------------------------------------------------------*/
952 /* valueNot - complements a constant                                */
953 /*------------------------------------------------------------------*/
954 value *
955 valNot (value * val)
956 {
957   /* depending on type */
958   if (SPEC_LONG (val->etype))
959     {
960       if (SPEC_USIGN (val->etype))
961         SPEC_CVAL (val->etype).v_ulong = !SPEC_CVAL (val->etype).v_ulong;
962       else
963         SPEC_CVAL (val->etype).v_long = !SPEC_CVAL (val->etype).v_long;
964     }
965   else
966     {
967       if (SPEC_USIGN (val->etype))
968         SPEC_CVAL (val->etype).v_uint = !SPEC_CVAL (val->etype).v_uint;
969       else
970         SPEC_CVAL (val->etype).v_int = !SPEC_CVAL (val->etype).v_int;
971       if (SPEC_NOUN (val->etype)==V_CHAR) {
972         SPEC_CVAL (val->etype).v_uint &= 0xff;
973       }
974     }
975   return val;
976 }
977
978 /*------------------------------------------------------------------*/
979 /* valMult - multiply constants                                     */
980 /*------------------------------------------------------------------*/
981 value *
982 valMult (value * lval, value * rval)
983 {
984   value *val;
985
986   /* create a new value */
987   val = newValue ();
988   val->type = val->etype = newLink ();
989   val->type->class = SPECIFIER;
990   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
991                            IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
992   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
993   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) & SPEC_USIGN (rval->etype));
994   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
995
996   if (IS_FLOAT (val->type))
997     SPEC_CVAL (val->type).v_float = floatFromVal (lval) * floatFromVal (rval);
998   else
999     {
1000       if (SPEC_LONG (val->type))
1001         {
1002           if (SPEC_USIGN (val->type))
1003             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) *
1004               (unsigned long) floatFromVal (rval);
1005           else
1006             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) *
1007               (long) floatFromVal (rval);
1008         }
1009       else
1010         {
1011           if (SPEC_USIGN (val->type))
1012             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) *
1013               (unsigned) floatFromVal (rval);
1014           else
1015             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) *
1016               (int) floatFromVal (rval);
1017         }
1018     }
1019   return cheapestVal(val);
1020 }
1021
1022 /*------------------------------------------------------------------*/
1023 /* valDiv  - Divide   constants                                     */
1024 /*------------------------------------------------------------------*/
1025 value *
1026 valDiv (value * lval, value * rval)
1027 {
1028   value *val;
1029
1030   if (floatFromVal (rval) == 0)
1031     {
1032       werror (E_DIVIDE_BY_ZERO);
1033       return rval;
1034     }
1035
1036   /* create a new value */
1037   val = newValue ();
1038   val->type = val->etype = newLink();
1039   val->type->class = SPECIFIER;
1040   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
1041                            IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
1042   SPEC_SCLS (val->etype) = S_LITERAL;
1043   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) & SPEC_USIGN (rval->etype));
1044   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1045
1046   if (IS_FLOAT (val->type))
1047     SPEC_CVAL (val->type).v_float = floatFromVal (lval) / floatFromVal (rval);
1048   else
1049     {
1050       if (SPEC_LONG (val->type))
1051         {
1052           if (SPEC_USIGN (val->type))
1053             SPEC_CVAL (val->type).v_ulong = 
1054               (unsigned long) floatFromVal (lval) /
1055               (unsigned long) floatFromVal (rval);
1056           else
1057             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) /
1058               (long) floatFromVal (rval);
1059         }
1060       else
1061         {
1062           if (SPEC_USIGN (val->type)) {
1063             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) /
1064               (unsigned) floatFromVal (rval);
1065           } else {
1066             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) /
1067               (int) floatFromVal (rval);
1068           }
1069         }
1070     }
1071   return cheapestVal(val);
1072 }
1073
1074 /*------------------------------------------------------------------*/
1075 /* valMod  - Modulus  constants                                     */
1076 /*------------------------------------------------------------------*/
1077 value *
1078 valMod (value * lval, value * rval)
1079 {
1080   value *val;
1081
1082   /* create a new value */
1083   val = newValue ();
1084   val->type = val->etype = newLink ();
1085   val->type->class = SPECIFIER;
1086   SPEC_NOUN (val->type) = V_INT;        /* type is int */
1087   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1088   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) & SPEC_USIGN (rval->etype));
1089   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1090
1091   if (SPEC_LONG (val->type))
1092     {
1093       if (SPEC_USIGN (val->type))
1094         SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) %
1095           (unsigned long) floatFromVal (rval);
1096       else
1097         SPEC_CVAL (val->type).v_long = (unsigned long) floatFromVal (lval) %
1098           (unsigned long) floatFromVal (rval);
1099     }
1100   else
1101     {
1102       if (SPEC_USIGN (val->type)) {
1103         SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) %
1104           (unsigned) floatFromVal (rval);
1105       } else {
1106         SPEC_CVAL (val->type).v_int = (unsigned) floatFromVal (lval) %
1107           (unsigned) floatFromVal (rval);
1108       }
1109     }
1110
1111   return cheapestVal(val);
1112 }
1113
1114 /*------------------------------------------------------------------*/
1115 /* valPlus - Addition constants                                     */
1116 /*------------------------------------------------------------------*/
1117 value *
1118 valPlus (value * lval, value * rval)
1119 {
1120   value *val;
1121
1122   /* create a new value */
1123   val = newValue ();
1124   val->type = val->etype = newLink ();
1125   val->type->class = SPECIFIER;
1126   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
1127                            IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
1128   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1129   SPEC_USIGN (val->type) = 
1130     SPEC_USIGN (lval->etype) &&
1131     SPEC_USIGN (rval->etype) &&
1132     (floatFromVal(lval)+floatFromVal(rval))>=0;
1133     
1134   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1135
1136   if (IS_FLOAT (val->type))
1137     SPEC_CVAL (val->type).v_float = floatFromVal (lval) + floatFromVal (rval);
1138   else
1139     {
1140       if (SPEC_LONG (val->type))
1141         {
1142           if (SPEC_USIGN (val->type))
1143             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) +
1144               (unsigned long) floatFromVal (rval);
1145           else
1146             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) +
1147               (long) floatFromVal (rval);
1148         }
1149       else
1150         {
1151           if (SPEC_USIGN (val->type)) {
1152             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) +
1153               (unsigned) floatFromVal (rval);
1154           } else {
1155             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) +
1156               (int) floatFromVal (rval);
1157           }
1158         }
1159     }
1160   return cheapestVal(val);
1161 }
1162
1163 /*------------------------------------------------------------------*/
1164 /* valMinus - Addition constants                                    */
1165 /*------------------------------------------------------------------*/
1166 value *
1167 valMinus (value * lval, value * rval)
1168 {
1169   value *val;
1170
1171   /* create a new value */
1172   val = newValue ();
1173   val->type = val->etype = newLink ();
1174   val->type->class = SPECIFIER;
1175   SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
1176                            IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
1177   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1178   SPEC_USIGN (val->type) = 
1179     SPEC_USIGN (lval->etype) &&
1180     SPEC_USIGN (rval->etype) &&
1181     (floatFromVal(lval)-floatFromVal(rval))>=0;
1182
1183   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1184
1185   if (IS_FLOAT (val->type))
1186     SPEC_CVAL (val->type).v_float = floatFromVal (lval) - floatFromVal (rval);
1187   else
1188     {
1189       if (SPEC_LONG (val->type))
1190         {
1191           if (SPEC_USIGN (val->type)) {
1192             SPEC_CVAL (val->type).v_ulong = 
1193               (unsigned long) floatFromVal (lval) -
1194               (unsigned long) floatFromVal (rval);
1195           } else {
1196             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) -
1197               (long) floatFromVal (rval);
1198           }
1199         }
1200       else
1201         {
1202           if (SPEC_USIGN (val->type)) {
1203             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) -
1204               (unsigned) floatFromVal (rval);
1205           } else {
1206             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) - 
1207               (int) floatFromVal (rval);
1208           }
1209         }
1210     }
1211   return cheapestVal(val);
1212 }
1213
1214 /*------------------------------------------------------------------*/
1215 /* valShift - Shift left or right                                   */
1216 /*------------------------------------------------------------------*/
1217 value *
1218 valShift (value * lval, value * rval, int lr)
1219 {
1220   value *val;
1221
1222   /* create a new value */
1223   val = newValue ();
1224   val->type = val->etype = newIntLink ();
1225   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1226   SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) & SPEC_USIGN (rval->etype));
1227   SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
1228
1229   if (SPEC_LONG (val->type))
1230     {
1231       if (SPEC_USIGN (val->type))
1232         SPEC_CVAL (val->type).v_ulong = lr ? 
1233           (unsigned long) floatFromVal (lval) << (unsigned long) floatFromVal (rval) : \
1234           (unsigned long) floatFromVal (lval) >> (unsigned long) floatFromVal (rval);
1235       else
1236         SPEC_CVAL (val->type).v_long = lr ?
1237           (long) floatFromVal (lval) << (long) floatFromVal (rval) : \
1238           (long) floatFromVal (lval) >> (long) floatFromVal (rval);
1239     }
1240   else
1241     {
1242       if (SPEC_USIGN (val->type)) {
1243         SPEC_CVAL (val->type).v_uint = lr ? 
1244           (unsigned) floatFromVal (lval) << (unsigned) floatFromVal (rval) :\
1245           (unsigned) floatFromVal (lval) >> (unsigned) floatFromVal (rval);
1246       } else {
1247         SPEC_CVAL (val->type).v_int = lr ?
1248           (int) floatFromVal (lval) << (int) floatFromVal (rval) : \
1249           (int) floatFromVal (lval) >> (int) floatFromVal (rval);
1250       }
1251     }
1252
1253   return cheapestVal(val);
1254 }
1255
1256 /*------------------------------------------------------------------*/
1257 /* valCompare- Compares two literal                                 */
1258 /*------------------------------------------------------------------*/
1259 value *
1260 valCompare (value * lval, value * rval, int ctype)
1261 {
1262   value *val;
1263
1264   /* create a new value */
1265   val = newValue ();
1266   val->type = val->etype = newCharLink ();
1267   val->type->class = SPECIFIER;
1268   SPEC_NOUN (val->type) = V_CHAR;       /* type is char */
1269   SPEC_USIGN (val->type) = 1;
1270   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1271
1272   switch (ctype)
1273     {
1274     case '<':
1275       SPEC_CVAL (val->type).v_int = floatFromVal (lval) < floatFromVal (rval);
1276       break;
1277
1278     case '>':
1279       SPEC_CVAL (val->type).v_int = floatFromVal (lval) > floatFromVal (rval);
1280       break;
1281
1282     case LE_OP:
1283       SPEC_CVAL (val->type).v_int = floatFromVal (lval) <= floatFromVal (rval);
1284       break;
1285
1286     case GE_OP:
1287       SPEC_CVAL (val->type).v_int = floatFromVal (lval) >= floatFromVal (rval);
1288       break;
1289
1290     case EQ_OP:
1291       SPEC_CVAL (val->type).v_int = floatFromVal (lval) == floatFromVal (rval);
1292       break;
1293
1294     case NE_OP:
1295       SPEC_CVAL (val->type).v_int = floatFromVal (lval) != floatFromVal (rval);
1296       break;
1297
1298     }
1299
1300   return val;
1301 }
1302
1303 /*------------------------------------------------------------------*/
1304 /* valBitwise - Bitwise operation                                   */
1305 /*------------------------------------------------------------------*/
1306 value *
1307 valBitwise (value * lval, value * rval, int op)
1308 {
1309   value *val;
1310
1311   /* create a new value */
1312   val = newValue ();
1313   val->type = copyLinkChain (lval->type);
1314   val->etype = getSpec (val->type);
1315
1316   switch (op)
1317     {
1318     case '&':
1319       if (SPEC_LONG (val->type))
1320         {
1321           if (SPEC_USIGN (val->type))
1322             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) &
1323               (unsigned long) floatFromVal (rval);
1324           else
1325             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) &
1326               (long) floatFromVal (rval);
1327         }
1328       else
1329         {
1330           if (SPEC_USIGN (val->type))
1331             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) &
1332               (unsigned) floatFromVal (rval);
1333           else
1334             SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) & (int) floatFromVal (rval);
1335         }
1336       break;
1337
1338     case '|':
1339       if (SPEC_LONG (val->type))
1340         {
1341           if (SPEC_USIGN (val->type))
1342             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) |
1343               (unsigned long) floatFromVal (rval);
1344           else
1345             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) |
1346               (long) floatFromVal (rval);
1347         }
1348       else
1349         {
1350           if (SPEC_USIGN (val->type))
1351             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) |
1352               (unsigned) floatFromVal (rval);
1353           else
1354             SPEC_CVAL (val->type).v_int =
1355               (int) floatFromVal (lval) | (int) floatFromVal (rval);
1356         }
1357
1358       break;
1359
1360     case '^':
1361       if (SPEC_LONG (val->type))
1362         {
1363           if (SPEC_USIGN (val->type))
1364             SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) ^
1365               (unsigned long) floatFromVal (rval);
1366           else
1367             SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) ^
1368               (long) floatFromVal (rval);
1369         }
1370       else
1371         {
1372           if (SPEC_USIGN (val->type))
1373             SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) ^
1374               (unsigned) floatFromVal (rval);
1375           else
1376             SPEC_CVAL (val->type).v_int =
1377               (int) floatFromVal (lval) ^ (int) floatFromVal (rval);
1378         }
1379       break;
1380     }
1381
1382   return cheapestVal(val);
1383 }
1384
1385 /*------------------------------------------------------------------*/
1386 /* valAndOr   - Generates code for and / or operation               */
1387 /*------------------------------------------------------------------*/
1388 value *
1389 valLogicAndOr (value * lval, value * rval, int op)
1390 {
1391   value *val;
1392
1393   /* create a new value */
1394   val = newValue ();
1395   val->type = val->etype = newCharLink ();
1396   val->type->class = SPECIFIER;
1397   SPEC_SCLS (val->type) = S_LITERAL;    /* will remain literal */
1398   SPEC_USIGN (val->type) = 0;
1399
1400   switch (op)
1401     {
1402     case AND_OP:
1403       SPEC_CVAL (val->type).v_int = floatFromVal (lval) && floatFromVal (rval);
1404       break;
1405
1406     case OR_OP:
1407       SPEC_CVAL (val->type).v_int = floatFromVal (lval) || floatFromVal (rval);
1408       break;
1409     }
1410
1411
1412   return val;
1413 }
1414
1415 /*------------------------------------------------------------------*/
1416 /* valCastLiteral - casts a literal value to another type           */
1417 /*------------------------------------------------------------------*/
1418 value *
1419 valCastLiteral (sym_link * dtype, double fval)
1420 {
1421   value *val;
1422
1423   if (!dtype)
1424     return NULL;
1425
1426   val = newValue ();
1427   val->etype = getSpec (val->type = copyLinkChain (dtype));
1428   SPEC_SCLS (val->etype) = S_LITERAL;
1429   /* if it is not a specifier then we can assume that */
1430   /* it will be an unsigned long                      */
1431   if (!IS_SPEC (val->type))
1432     {
1433       SPEC_CVAL (val->etype).v_ulong = (unsigned long) fval;
1434       return val;
1435     }
1436
1437   if (SPEC_NOUN (val->etype) == V_FLOAT)
1438     SPEC_CVAL (val->etype).v_float = fval;
1439   else
1440     {
1441       if (SPEC_LONG (val->etype))
1442         {
1443           if (SPEC_USIGN (val->etype))
1444             SPEC_CVAL (val->etype).v_ulong = (unsigned long) fval;
1445           else
1446             SPEC_CVAL (val->etype).v_long = (long) fval;
1447         }
1448       else
1449         {
1450           if (SPEC_USIGN (val->etype))
1451             SPEC_CVAL (val->etype).v_uint = (unsigned short)fval;
1452           else
1453             SPEC_CVAL (val->etype).v_int = (short)fval;
1454           if (SPEC_NOUN (val->etype)==V_CHAR) {
1455             SPEC_CVAL (val->etype).v_uint &= 0xff; 
1456           }
1457         }
1458     }
1459   return val;
1460 }
1461
1462 /*------------------------------------------------------------------*/
1463 /* getNelements - determines # of elements from init list           */
1464 /*------------------------------------------------------------------*/
1465 int 
1466 getNelements (sym_link * type, initList * ilist)
1467 {
1468   sym_link *etype = getSpec (type);
1469   int i;
1470
1471   if (!ilist)
1472     return 0;
1473
1474   if (ilist->type == INIT_DEEP)
1475     ilist = ilist->init.deep;
1476
1477   /* if type is a character array and there is only one
1478      (string) initialiser then get the length of the string */
1479   if (IS_ARRAY (type) && IS_CHAR (etype) && !ilist->next)
1480     {
1481       ast *iast = ilist->init.node;
1482       value *v = (iast->type == EX_VALUE ? iast->opval.val : NULL);
1483       if (!v)
1484         {
1485           werror (W_INIT_WRONG);
1486           return 0;
1487         }
1488
1489       if (IS_ARRAY (v->type) && IS_CHAR (v->etype))
1490         // yep, it's a string
1491         {
1492           return DCL_ELEM (v->type);
1493         }
1494     }
1495
1496   i = 0;
1497   while (ilist)
1498     {
1499       i++;
1500       ilist = ilist->next;
1501     }
1502
1503   return i;
1504 }
1505
1506 /*-----------------------------------------------------------------*/
1507 /* valForArray - returns a value with name of array index          */
1508 /*-----------------------------------------------------------------*/
1509 value *
1510 valForArray (ast * arrExpr)
1511 {
1512   value *val, *lval = NULL;
1513   char buffer[128];
1514   int size = getSize (arrExpr->left->ftype->next);
1515   /* if the right or left is an array
1516      resolve it first */
1517   if (IS_AST_OP (arrExpr->left))
1518     {
1519       if (arrExpr->left->opval.op == '[')
1520         lval = valForArray (arrExpr->left);
1521       else if (arrExpr->left->opval.op == '.')
1522         lval = valForStructElem (arrExpr->left->left,
1523                                  arrExpr->left->right);
1524       else if (arrExpr->left->opval.op == PTR_OP &&
1525                IS_ADDRESS_OF_OP (arrExpr->left->left))
1526         lval = valForStructElem (arrExpr->left->left->left,
1527                                  arrExpr->left->right);
1528       else
1529         return NULL;
1530
1531     }
1532   else if (!IS_AST_SYM_VALUE (arrExpr->left))
1533     return NULL;
1534
1535   if (!IS_AST_LIT_VALUE (arrExpr->right))
1536     return NULL;
1537
1538   val = newValue ();
1539   if (!lval)
1540     sprintf (buffer, "%s", AST_SYMBOL (arrExpr->left)->rname);
1541   else
1542     sprintf (buffer, "%s", lval->name);
1543
1544   sprintf (val->name, "(%s + %d)", buffer,
1545            (int) AST_LIT_VALUE (arrExpr->right) * size);
1546
1547   val->type = newLink ();
1548   if (SPEC_SCLS (arrExpr->left->etype) == S_CODE)
1549     {
1550       DCL_TYPE (val->type) = CPOINTER;
1551       DCL_PTR_CONST (val->type) = port->mem.code_ro;
1552     }
1553   else if (SPEC_SCLS (arrExpr->left->etype) == S_XDATA)
1554     DCL_TYPE (val->type) = FPOINTER;
1555   else if (SPEC_SCLS (arrExpr->left->etype) == S_XSTACK)
1556     DCL_TYPE (val->type) = PPOINTER;
1557   else if (SPEC_SCLS (arrExpr->left->etype) == S_IDATA)
1558     DCL_TYPE (val->type) = IPOINTER;
1559   else if (SPEC_SCLS (arrExpr->left->etype) == S_EEPROM)
1560     DCL_TYPE (val->type) = EEPPOINTER;
1561   else
1562     DCL_TYPE (val->type) = POINTER;
1563   val->type->next = arrExpr->left->ftype;
1564   val->etype = getSpec (val->type);
1565   return val;
1566 }
1567
1568 /*-----------------------------------------------------------------*/
1569 /* valForStructElem - returns value with name of struct element    */
1570 /*-----------------------------------------------------------------*/
1571 value *
1572 valForStructElem (ast * structT, ast * elemT)
1573 {
1574   value *val, *lval = NULL;
1575   char buffer[128];
1576   symbol *sym;
1577
1578   /* left could be furthur derefed */
1579   if (IS_AST_OP (structT))
1580     {
1581       if (structT->opval.op == '[')
1582         lval = valForArray (structT);
1583       else if (structT->opval.op == '.')
1584         lval = valForStructElem (structT->left, structT->right);
1585       else if (structT->opval.op == PTR_OP &&
1586                IS_ADDRESS_OF_OP (structT->left))
1587         lval = valForStructElem (structT->left->left,
1588                                  structT->right);
1589       else
1590         return NULL;
1591     }
1592
1593   if (!IS_AST_SYM_VALUE (elemT))
1594     return NULL;
1595
1596   if (!IS_STRUCT (structT->etype))
1597     return NULL;
1598
1599   if ((sym = getStructElement (SPEC_STRUCT (structT->etype),
1600                                AST_SYMBOL (elemT))) == NULL)
1601     {
1602       return NULL;
1603     }
1604
1605   val = newValue ();
1606   if (!lval)
1607     sprintf (buffer, "%s", AST_SYMBOL (structT)->rname);
1608   else
1609     sprintf (buffer, "%s", lval->name);
1610
1611   sprintf (val->name, "(%s + %d)", buffer,
1612            (int) sym->offset);
1613
1614   val->type = newLink ();
1615   if (SPEC_SCLS (structT->etype) == S_CODE)
1616     {
1617       DCL_TYPE (val->type) = CPOINTER;
1618       DCL_PTR_CONST (val->type) = port->mem.code_ro;
1619     }
1620   else if (SPEC_SCLS (structT->etype) == S_XDATA)
1621     DCL_TYPE (val->type) = FPOINTER;
1622   else if (SPEC_SCLS (structT->etype) == S_XSTACK)
1623     DCL_TYPE (val->type) = PPOINTER;
1624   else if (SPEC_SCLS (structT->etype) == S_IDATA)
1625     DCL_TYPE (val->type) = IPOINTER;
1626   else if (SPEC_SCLS (structT->etype) == S_EEPROM)
1627     DCL_TYPE (val->type) = EEPPOINTER;
1628   else
1629     DCL_TYPE (val->type) = POINTER;
1630   val->type->next = sym->type;
1631   val->etype = getSpec (val->type);
1632   return val;
1633 }
1634
1635 /*-----------------------------------------------------------------*/
1636 /* valForCastAggr - will return value for a cast of an aggregate   */
1637 /*                  plus minus a constant                          */
1638 /*-----------------------------------------------------------------*/
1639 value *
1640 valForCastAggr (ast * aexpr, sym_link * type, ast * cnst, int op)
1641 {
1642   value *val;
1643
1644   if (!IS_AST_SYM_VALUE (aexpr))
1645     return NULL;
1646   if (!IS_AST_LIT_VALUE (cnst))
1647     return NULL;
1648
1649   val = newValue ();
1650
1651   sprintf (val->name, "(%s %c %d)",
1652            AST_SYMBOL (aexpr)->rname, op,
1653            getSize (type->next) * (int) AST_LIT_VALUE (cnst));
1654
1655   val->type = type;
1656   val->etype = getSpec (val->type);
1657   return val;
1658 }
1659
1660 /*-----------------------------------------------------------------*/
1661 /* valForCastAggr - will return value for a cast of an aggregate   */
1662 /*                  with no constant                               */
1663 /*-----------------------------------------------------------------*/
1664 value *
1665 valForCastArr (ast * aexpr, sym_link * type)
1666 {
1667   value *val;
1668
1669   if (!IS_AST_SYM_VALUE (aexpr))
1670     return NULL;
1671
1672   val = newValue ();
1673
1674   sprintf (val->name, "(%s)",
1675            AST_SYMBOL (aexpr)->rname);
1676
1677   val->type = type;
1678   val->etype = getSpec (val->type);
1679   return val;
1680 }