+
+ val->type = val->etype = newLink (SPECIFIER);
+ SPEC_NOUN (val->type) = V_FLOAT;
+ SPEC_SCLS (val->type) = S_LITERAL;
+ SPEC_CVAL (val->type).v_fixed16x16 = fixed16x16FromDouble ( sval );
+
+ return val;
+}
+
+/*-----------------------------------------------------------------*/
+/* constVal - converts an INTEGER constant into a cheapest value */
+/*-----------------------------------------------------------------*/
+value *constVal (char *s)
+{
+ value *val;
+ short hex = 0, octal = 0;
+ double dval;
+
+ val = newValue (); /* alloc space for value */
+
+ val->type = val->etype = newLink (SPECIFIER); /* create the spcifier */
+ SPEC_SCLS (val->type) = S_LITERAL;
+ // let's start with a signed char
+ SPEC_NOUN (val->type) = V_CHAR;
+ SPEC_USIGN (val->type) = 0;
+
+ hex = ((strchr (s, 'x') || strchr (s, 'X')) ? 1 : 0);
+
+ /* set the octal flag */
+ if (!hex && *s == '0' && *(s + 1))
+ octal = 1;
+
+ errno = 0;
+ if (hex || octal) {
+ unsigned long sval;
+ sval = strtoul (s, NULL, 0);
+ dval=sval;
+ if (errno) {
+ dval = 4294967295.0;
+ werror (W_INVALID_INT_CONST, s, dval);
+ }
+ } else {
+ sscanf (s, "%lf", &dval);
+ }
+
+ /* Setup the flags first */
+ /* set the b_long flag if 'lL' is found */
+ if (strchr (s, 'l') || strchr (s, 'L')) {
+ SPEC_NOUN (val->type) = V_INT;
+ SPEC_LONG (val->type) = 1;
+ }
+
+ /* set the unsigned flag if 'uU' is found */
+ if (strchr (s, 'u') || strchr (s, 'U')) {
+ SPEC_USIGN (val->type) = 1;
+ }
+
+ if (dval<0) { // "-28u" will still be signed and negative
+ if (dval<-128) { // check if we have to promote to int
+ SPEC_NOUN (val->type) = V_INT;
+ }
+ if (dval<-32768) { // check if we have to promote to long int
+ SPEC_LONG (val->type) = 1;
+ }
+ } else { // >=0
+ if (dval>0xff || /* check if we have to promote to int */
+ SPEC_USIGN (val->type)) { /* if it's unsigned, we can't use unsigned
+ char. After an integral promotion it will
+ be a signed int; this certainly isn't what
+ the programer wants */
+ SPEC_NOUN (val->type) = V_INT;
+ }
+ else { /* store char's always as unsigned; this helps other optimizations */
+ SPEC_USIGN (val->type) = 1;
+ }
+ if (dval>0xffff && SPEC_USIGN (val->type)) { // check if we have to promote to long
+ SPEC_LONG (val->type) = 1;
+ }
+ else if (dval>0x7fff && !SPEC_USIGN (val->type)) { // check if we have to promote to long int
+ if ((hex || octal) && /* hex or octal constants may be stored in unsigned type */
+ dval<=0xffff) {
+ SPEC_USIGN (val->type) = 1;
+ } else {
+ SPEC_LONG (val->type) = 1;
+ if (dval>0x7fffffff) {
+ SPEC_USIGN (val->type) = 1;
+ }
+ }
+ }
+ }
+
+ /* check for out of range */
+ if (dval<-2147483648.0) {
+ dval = -2147483648.0;
+ werror (W_INVALID_INT_CONST, s, dval);
+ }
+ if (dval>2147483647.0 && !SPEC_USIGN (val->type)) {
+ dval = 2147483647.0;
+ werror (W_INVALID_INT_CONST, s, dval);
+ }
+ if (dval>4294967295.0) {
+ dval = 4294967295.0;
+ werror (W_INVALID_INT_CONST, s, dval);
+ }
+
+ if (SPEC_LONG (val->type))
+ {
+ if (SPEC_USIGN (val->type))
+ {
+ SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD)dval;
+ }
+ else
+ {
+ SPEC_CVAL (val->type).v_long = (TYPE_DWORD)dval;
+ }
+ }
+ else
+ {
+ if (SPEC_USIGN (val->type))
+ {
+ SPEC_CVAL (val->type).v_uint = (TYPE_UWORD)dval;
+ }
+ else
+ {
+ SPEC_CVAL (val->type).v_int = (TYPE_WORD)dval;
+ }