diff -r c41975a290ce -r 4efb11e44065 stage3/constant_folding.cc --- a/stage3/constant_folding.cc Thu Jun 14 17:50:37 2012 +0100 +++ b/stage3/constant_folding.cc Fri Jun 15 19:54:33 2012 +0100 @@ -121,6 +121,13 @@ #include /* required for pow function, and HUGE_VAL, HUGE_VALF, HUGE_VALL */ #include /* required for malloc() */ + +#include /* required for strlen() */ +// #include /* required for atoi() */ +#include /* required for errno */ + + + #define __STDC_LIMIT_MACROS /* required for UINT64_MAX, INT64_MAX, INT64_MIN, ... */ #include /* required for UINT64_MAX, INT64_MAX, INT64_MIN, ... */ @@ -217,6 +224,156 @@ +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ +/*** convert string to numerical value ***/ +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ + + + + /* To allow the compiler to be portable, we cannot assume that int64_t is mapped onto long long int, + * so we cannot call strtoll() and strtoull() in extract_int64() and extract_uint64(). + * + * So, we create our own strtouint64() and strtoint64() functions. + * (We actually call them matiec_strtoint64() so they will not clash with any function + * that may be added to the standard library in the future). + * We actually create several of each, and let the compiler choose which is the correct one, + * by having it resolve the call to the overloaded function. For the C++ compiler to be able + * to resolve this ambiguity, we need to add a dummy parameter to each function! + * + * TODO: support platforms in which int64_t is mapped onto int !! Is this really needed? + */ +static int64_t matiec_strtoint64 ( long int *dummy, const char *nptr, char **endptr, int base) {return strtol (nptr, endptr, base);} +static int64_t matiec_strtoint64 ( long long int *dummy, const char *nptr, char **endptr, int base) {return strtoll (nptr, endptr, base);} + +static uint64_t matiec_strtouint64(unsigned long int *dummy, const char *nptr, char **endptr, int base) {return strtoul (nptr, endptr, base);} +static uint64_t matiec_strtouint64(unsigned long long int *dummy, const char *nptr, char **endptr, int base) {return strtoull(nptr, endptr, base);} + + +/* extract the value of an integer from an integer_c object !! */ +/* NOTE: it must ignore underscores! */ +int64_t extract_int64_value(symbol_c *sym, bool *overflow) { + std::string str = ""; + integer_c *integer; + char *endptr; + int64_t ret; + + if ((integer = dynamic_cast(sym)) == NULL) ERROR; + for(unsigned int i = 0; i < strlen(integer->value); i++) + if (integer->value[i] != '_') str += integer->value[i]; + + errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! + ret = matiec_strtoint64((int64_t *)NULL, str.c_str(), &endptr, 10); + if (overflow != NULL) + *overflow = (errno == ERANGE); + if ((errno != 0) && (errno != ERANGE)) + ERROR; + + return ret; +} + +uint64_t extract_uint64_value(symbol_c *sym, bool *overflow) { + std::string str = ""; + integer_c *integer; + neg_integer_c * neg_integer; + char *endptr; + uint64_t ret; + + if ((integer = dynamic_cast(sym)) == NULL) ERROR; + for(unsigned int i = 0; i < strlen(integer->value); i++) + if (integer->value[i] != '_') str += integer->value[i]; + + errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! + ret = matiec_strtouint64((uint64_t *)NULL, str.c_str(), &endptr, 10); + if (overflow != NULL) + *overflow = (errno == ERANGE); + if ((errno != 0) && (errno != ERANGE)) + ERROR; + + return ret; +} + + + +/* extract the value of an hex integer from an hex_integer_c object !! */ +/* NOTE: it must ignore underscores! */ +uint64_t extract_hex_value(symbol_c *sym) { + std::string str = ""; + char *endptr; + hex_integer_c * hex_integer; + uint64_t ret; + + if ((hex_integer = dynamic_cast(sym)) == NULL) ERROR; + for(unsigned int i = 3; i < strlen(hex_integer->value); i++) + if (hex_integer->value[i] != '_') str += hex_integer->value[i]; + + errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! + ret = strtoull(str.c_str(), &endptr, 16); + if (errno != 0) ERROR; + + return ret; +} + + +/* extract the value of a real from an real_c object !! */ +/* NOTE: it must ignore underscores! */ +/* From iec_bison.yy + * real: + * real_token {$$ = new real_c($1, locloc(@$));} + * | fixed_point_token {$$ = new real_c($1, locloc(@$));} + * + * From iec_flex.ll + * {real} {yylval.ID=strdup(yytext); return real_token;} + * {fixed_point} {yylval.ID=strdup(yytext); return fixed_point_token;} + * + * real {integer}\.{integer}{exponent} + * fixed_point {integer}\.{integer} + * exponent [Ee]([+-]?){integer} + * integer {digit}((_?{digit})*) + */ +real64_t extract_real_value(symbol_c *sym, bool *overflow) { + std::string str = ""; + real_c * real_sym; + real64_t ret; + + if ((real_sym = dynamic_cast(sym)) == NULL) ERROR; + for(unsigned int i = 0; i < strlen(real_sym->value); i++) + if (real_sym->value[i] != '_') str += real_sym->value[i]; + + errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! + #if (real64_t == float) + ret = strtof(str.c_str(), NULL); + #elif (real64_t == double) + ret = strtod(str.c_str(), NULL); + #elif (real64_t == long_double) + ret = strtold(str.c_str(), NULL); + #else + #error Could not determine which data type is being used for real64_t (defined in absyntax.hh). Aborting! + #endif + if (overflow != NULL) + *overflow = (errno == ERANGE); + if ((errno != 0) && (errno != ERANGE)) + ERROR; + + return ret; +} + + + + + +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ +/*** Functions to check for overflow situation ***/ +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ + + /* NOTE: * Most of the conditions to detect overflows on signed and unsigned integer operations were adapted from * https://www.securecoding.cert.org/confluence/display/seccode/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow?showComments=false @@ -383,7 +540,13 @@ - +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ +/*** The constant_folding_c ***/ +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/