. how to recognize integer constant (1) get the value from literal string & check overflow > integer in hex
int d = 0; while(*++rcp) { if (map[*rcp] & DIGIT) { d = *rcp - '0'; } else if(*rcp > 'a' && *rcp < 'f') { d = *rcp - 'a' + 10; } else if(*rcp > 'A' && *rcp < 'F') { d = *rcp - 'A' + 10; } else // maybe 0x1234u, or 0x1ul break;
if( n & ~(~0UL >> 4) ) { overflow = 1; // !!! overflow } else { n = (n << 4) + d; } }
> integer in oct
int err = 0; for(; map[*rcp++] & DIGIT; ) { if( *rcp == '8' || *rcp == '9' ) { err = 1; } if( n & ~(~0UL >> 3) ) { overflow = 1; // !!! overflow } else { n = (n << 3) + (*rcp - '0'); } }
> integer in decimal for( n = *token - '0'; map[*rcp] & DIGIT; ) { int d = *rcp - '0';
if( n > (ULONG_MAX -d) /10 ) { // !!! overflow, 10 * n + d > ULONG_MAX overflow = 1; } else { n = n * 10 + d; } }
(2) give an appropriate integer type & value store in a high-level integer type than that cause overflows.
IF with suffix string{'u'|'U' . 'l'|'L'} // stored in unsigned long type tval.type <- unsignedlong ELSE IF with suffix 'u'|'U' // stored in unsigned int or unsigned long IF overflow || n > unsignedtype->u.sym->u.limits.max.i tval.type <- unsignedlong //store in unsigned long, if unsigned is insufficient ELSE tval.type <- unsignedtype ELSE IF with suffix 'l'|'L' IF overflow || n > longtype->u.sym->u.limits.max.i tval.type <- unsignedlong ELSE tval.type <- longtype ELSE IF overflow || n > longtype->u.sym->u.limits.max.i tval.type <- unsignedlong ELSE IF n > inttype->u.sym->u.limits.max.i tval.type <- longtype ELSE IF base != 10 && n > inttype->u.sym->u.limits.max.i tval.type <- unsignedtype ELSE tval.type <- inttype
// store an appropriate value CASE tval.type->op: INT) IF overflow || n > tval.type->u.sym->u.limits.max.i warning overflows tval.u.c.v.i <- tval.type->u.sym->u.limits.max.i ELSE tval.u.c.v.i <- n UNSIGNED) IF overflow || n > tval.type->u.sym->u.limits.max.u warning overflows tval.u.c.v.u <- tval.type->u.sym->u.limits.max.u ELSE tval.u.c.v.u <- n ESAC
. how to recognize floating const (1) DFA of a floating constant f -> [+|-] f_part [exp_part] f_part -> i_part | i_part.[i_part] exp_part -> e|E +|- i_part i_part -> [0-9]+ // [2]
(2) how to get the value of floating constant & check flow lcc calculates the value of a floating constant and check overflow by POSIX API strtod(). This can be see in function fcon().
(3) give an appropriate floating type & value // 0. !!! different from type assignment of integer constant // 1. give a corresponding floating type according to suffix direction // 2. stores in double type, if no suffix direction tval.u.c.v.d = strtod(token, NULL) if (errno == ERANGE) { warning overflow... } if (*cp == 'f' || *cp == 'F') { ++cp; if (tval.u.c.v.d > floattype->u.sym->u.limits.max.d) { warning overflow... } tval.type = floattype; } else if (*cp == 'l' || *cp == 'L') { ++cp; tval.type = longdouble; } else { if (tval.u.c.v.d > doubletype->u.sym->u.limits.max.d) { warning overflow... } tval.type = doubletype; }
. lcc source codes arrangement DFA of integer constant: |-> static Symbol icon(unsigned long n, int overflow, int base) // see note1: DFA of floating constant: |-> static Symbol fcon(void) // see note2:
note1: icon() reads suffix of a integer constant, like "u", "l", or "ul" combination, and return a symbol of integer constant. [3] note2: fcon scans the floating constant string after decimal point (i.e, decimal point, digits after the decimal point, and exponent part), explains suffix like "l", "L", "f", or "F", and returns a symbol of floating constant.
[1]unsigned long long; // it's interpreted 64bits even if in word length of 32 machineOn the IA32 architecture, 64-bit integer are implemented in using two 32-bit registers (eax and edx).
however, lcc-4.1 does not support c99 yet.
[2] 0123 // oct integer 0123.134 // floating number, and convert it to a floating number by API strtod()
[3]see ch3.6 for integeral impression of constant symbols.