+#if defined(REDUCE_LITERALS)
+/*--------------------------------------------------------------------*/
+/* cheapestVal - convert a val to the cheapest as possible value */
+/*--------------------------------------------------------------------*/
+static value *cheapestVal (value *val) {
+ TYPE_DWORD sval=0;
+ TYPE_UDWORD uval=0;
+
+ if (IS_FLOAT(val->type) || IS_CHAR(val->type))
+ return val;
+
+ if (SPEC_LONG(val->type)) {
+ if (SPEC_USIGN(val->type)) {
+ uval=SPEC_CVAL(val->type).v_ulong;
+ } else {
+ sval=SPEC_CVAL(val->type).v_long;
+ }
+ } else {
+ if (SPEC_USIGN(val->type)) {
+ uval=SPEC_CVAL(val->type).v_uint;
+ } else {
+ sval=SPEC_CVAL(val->type).v_int;
+ }
+ }
+
+ if (SPEC_USIGN(val->type)) {
+ if (uval<=0xffff) {
+ SPEC_LONG(val->type)=0;
+ SPEC_CVAL(val->type).v_uint = (TYPE_UWORD)uval;
+ if (uval<=0xff) {
+ SPEC_NOUN(val->type)=V_CHAR;
+ }
+ }
+ } else { // not unsigned
+ if (sval<0) {
+ if (sval>=-32768) {
+ SPEC_LONG(val->type)=0;
+ SPEC_CVAL(val->type).v_int = (TYPE_WORD)sval;
+ if (sval>=-128) {
+ SPEC_NOUN(val->type)=V_CHAR;
+ }
+ }
+ } else { // sval>=0
+ if (sval<=32767) {
+ SPEC_LONG(val->type)=0;
+ SPEC_CVAL(val->type).v_int = (TYPE_WORD)sval;
+ if (sval<=127) {
+ SPEC_NOUN(val->type)=V_CHAR;
+ }
+ }
+ }
+ }
+ return val;
+}
+
+#else
+
+static value *cheapestVal (value *val)
+{
+ if (IS_FLOAT (val->type) || IS_CHAR (val->type))
+ return val;
+
+ /* - signed/unsigned must not be changed.
+ - long must not be changed.
+
+ the only possible reduction is from signed int to signed char,
+ because it's automatically promoted back to signed int.
+
+ a reduction from unsigned int to unsigned char is a bug,
+ because an _unsigned_ char is promoted to _signed_ int! */
+ if (IS_INT(val->type) &&
+ !SPEC_USIGN(val->type) &&
+ !SPEC_LONG(val->type) &&
+ SPEC_CVAL(val->type).v_int >= -128 &&
+ SPEC_CVAL(val->type).v_int < 0)
+
+ {
+ SPEC_NOUN(val->type) = V_CHAR;
+ }
+ /* 'unsigned char' promotes to 'signed int', so that we can
+ reduce it the other way */
+ if (IS_INT(val->type) &&
+ !SPEC_USIGN(val->type) &&
+ !SPEC_LONG(val->type) &&
+ SPEC_CVAL(val->type).v_int >= 0 &&
+ SPEC_CVAL(val->type).v_int <= 255)
+
+ {
+ SPEC_NOUN(val->type) = V_CHAR;
+ SPEC_USIGN(val->type) = 1;
+ }
+ return (val);
+}
+#endif
+