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