95 /* identifiers do not match! */ |
95 /* identifiers do not match! */ |
96 return 1; |
96 return 1; |
97 } |
97 } |
98 |
98 |
99 |
99 |
|
100 |
|
101 /* To allow the compiler to be portable, we cannot assume that int64_t is mapped onto long long int, |
|
102 * so we cannot call strtoll() and strtoull() in extract_int64() and extract_uint64(). |
|
103 * |
|
104 * So, we create our own strtouint64() and strtoint64() functions. |
|
105 * (We actually call them matiec_strtoint64() so they will not clash with any function |
|
106 * that may be added to the standard library in the future). |
|
107 * We actually create several of each, and let the compiler choose which is the correct one, |
|
108 * by having it resolve the call to the overloaded function. For the C++ compiler to be able |
|
109 * to resolve this ambiguity, we need to add a dummy parameter to each function! |
|
110 * |
|
111 * TODO: support platforms in which int64_t is mapped onto int !! Is this really needed? |
|
112 */ |
|
113 static int64_t matiec_strtoint64 ( long int *dummy, const char *nptr, char **endptr, int base) {return strtol (nptr, endptr, base);} |
|
114 static int64_t matiec_strtoint64 ( long long int *dummy, const char *nptr, char **endptr, int base) {return strtoll (nptr, endptr, base);} |
|
115 |
|
116 static uint64_t matiec_strtouint64(unsigned long int *dummy, const char *nptr, char **endptr, int base) {return strtoul (nptr, endptr, base);} |
|
117 static uint64_t matiec_strtouint64(unsigned long long int *dummy, const char *nptr, char **endptr, int base) {return strtoull(nptr, endptr, base);} |
|
118 |
|
119 |
100 /* extract the value of an integer from an integer_c object !! */ |
120 /* extract the value of an integer from an integer_c object !! */ |
101 /* NOTE: it must ignore underscores! */ |
121 /* NOTE: it must ignore underscores! */ |
102 int64_t extract_int64_value(symbol_c *sym, bool *overflow) { |
122 int64_t extract_int64_value(symbol_c *sym, bool *overflow) { |
103 std::string str = ""; |
123 std::string str = ""; |
104 integer_c *integer; |
124 integer_c *integer; |
112 if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR; |
132 if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR; |
113 |
133 |
114 for(unsigned int i = 0; i < strlen(integer->value); i++) |
134 for(unsigned int i = 0; i < strlen(integer->value); i++) |
115 if (integer->value[i] != '_') str += integer->value[i]; |
135 if (integer->value[i] != '_') str += integer->value[i]; |
116 |
136 |
117 errno = 0; |
137 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
118 ret = strtoll(str.c_str(), &endptr, 10); |
138 ret = matiec_strtoint64((int64_t *)NULL, str.c_str(), &endptr, 10); |
119 if (overflow != NULL) |
139 if (overflow != NULL) |
120 *overflow = (errno == ERANGE); |
140 *overflow = (errno == ERANGE); |
121 if ((errno != 0) && (errno != ERANGE)) |
141 if ((errno != 0) && (errno != ERANGE)) |
122 ERROR; |
142 ERROR; |
123 |
143 |
134 if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR; |
154 if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR; |
135 |
155 |
136 for(unsigned int i = 0; i < strlen(integer->value); i++) |
156 for(unsigned int i = 0; i < strlen(integer->value); i++) |
137 if (integer->value[i] != '_') str += integer->value[i]; |
157 if (integer->value[i] != '_') str += integer->value[i]; |
138 |
158 |
139 errno = 0; |
159 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
140 ret = strtoull(str.c_str(), &endptr, 10); |
160 ret = matiec_strtouint64((uint64_t *)NULL, str.c_str(), &endptr, 10); |
141 if (overflow != NULL) |
161 if (overflow != NULL) |
142 *overflow = (errno == ERANGE); |
162 *overflow = (errno == ERANGE); |
143 if ((errno != 0) && (errno != ERANGE)) |
163 if ((errno != 0) && (errno != ERANGE)) |
144 ERROR; |
164 ERROR; |
145 |
165 |