253 static uint64_t matiec_strtouint64(unsigned long long int *dummy, const char *nptr, char **endptr, int base) {return strtoull(nptr, endptr, base);} |
253 static uint64_t matiec_strtouint64(unsigned long long int *dummy, const char *nptr, char **endptr, int base) {return strtoull(nptr, endptr, base);} |
254 |
254 |
255 |
255 |
256 /* extract the value of an integer from an integer_c object !! */ |
256 /* extract the value of an integer from an integer_c object !! */ |
257 /* NOTE: it must ignore underscores! */ |
257 /* NOTE: it must ignore underscores! */ |
258 int64_t extract_int64_value(symbol_c *sym, bool *overflow) { |
258 int64_t extract_int64_value(symbol_c *sym, int base, bool *overflow) { |
259 std::string str = ""; |
259 std::string str = ""; |
260 integer_c *integer; |
260 integer_c *integer; |
261 char *endptr; |
261 char *endptr; |
262 int64_t ret; |
262 int64_t ret; |
263 |
263 |
264 if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR; |
264 if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR; |
265 for(unsigned int i = 0; i < strlen(integer->value); i++) |
265 for(unsigned int i = 0; i < strlen(integer->value); i++) |
266 if (integer->value[i] != '_') str += integer->value[i]; |
266 if (integer->value[i] != '_') str += integer->value[i]; |
267 |
267 |
268 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
268 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
269 ret = matiec_strtoint64((int64_t *)NULL, str.c_str(), &endptr, 10); |
269 ret = matiec_strtoint64((int64_t *)NULL, str.c_str(), &endptr, base); |
270 if (overflow != NULL) |
270 if (overflow != NULL) |
271 *overflow = (errno == ERANGE); |
271 *overflow = (errno == ERANGE); |
272 if ((errno != 0) && (errno != ERANGE)) |
272 if (((errno != 0) && (errno != ERANGE)) || (*endptr != '\0')) |
273 ERROR; |
273 ERROR; |
274 |
274 |
275 return ret; |
275 return ret; |
276 } |
276 } |
277 |
277 |
278 uint64_t extract_uint64_value(symbol_c *sym, bool *overflow) { |
278 uint64_t extract_uint64_value(symbol_c *sym, int base, bool *overflow) { |
279 std::string str = ""; |
279 std::string str = ""; |
280 integer_c *integer; |
280 integer_c *integer; |
281 neg_integer_c * neg_integer; |
|
282 char *endptr; |
281 char *endptr; |
283 uint64_t ret; |
282 uint64_t ret; |
284 |
283 |
285 if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR; |
284 if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR; |
286 for(unsigned int i = 0; i < strlen(integer->value); i++) |
285 for(unsigned int i = 0; i < strlen(integer->value); i++) |
287 if (integer->value[i] != '_') str += integer->value[i]; |
286 if (integer->value[i] != '_') str += integer->value[i]; |
288 |
287 |
289 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
288 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
290 ret = matiec_strtouint64((uint64_t *)NULL, str.c_str(), &endptr, 10); |
289 ret = matiec_strtouint64((uint64_t *)NULL, str.c_str(), &endptr, base); |
291 if (overflow != NULL) |
290 if (overflow != NULL) |
292 *overflow = (errno == ERANGE); |
291 *overflow = (errno == ERANGE); |
293 if ((errno != 0) && (errno != ERANGE)) |
292 if (((errno != 0) && (errno != ERANGE)) || (*endptr != '\0')) |
294 ERROR; |
293 ERROR; |
295 |
294 |
296 return ret; |
295 return ret; |
297 } |
296 } |
298 |
297 |
299 |
|
300 |
|
301 /* extract the value of an hex integer from an hex_integer_c object !! */ |
|
302 /* NOTE: it must ignore underscores! */ |
|
303 uint64_t extract_hex_value(symbol_c *sym) { |
|
304 std::string str = ""; |
|
305 char *endptr; |
|
306 hex_integer_c * hex_integer; |
|
307 uint64_t ret; |
|
308 |
|
309 if ((hex_integer = dynamic_cast<hex_integer_c *>(sym)) == NULL) ERROR; |
|
310 for(unsigned int i = 3; i < strlen(hex_integer->value); i++) |
|
311 if (hex_integer->value[i] != '_') str += hex_integer->value[i]; |
|
312 |
|
313 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
|
314 ret = strtoull(str.c_str(), &endptr, 16); |
|
315 if (errno != 0) ERROR; |
|
316 |
|
317 return ret; |
|
318 } |
|
319 |
298 |
320 |
299 |
321 /* extract the value of a real from an real_c object !! */ |
300 /* extract the value of a real from an real_c object !! */ |
322 /* NOTE: it must ignore underscores! */ |
301 /* NOTE: it must ignore underscores! */ |
323 /* From iec_bison.yy |
302 /* From iec_bison.yy |
334 * exponent [Ee]([+-]?){integer} |
313 * exponent [Ee]([+-]?){integer} |
335 * integer {digit}((_?{digit})*) |
314 * integer {digit}((_?{digit})*) |
336 */ |
315 */ |
337 real64_t extract_real_value(symbol_c *sym, bool *overflow) { |
316 real64_t extract_real_value(symbol_c *sym, bool *overflow) { |
338 std::string str = ""; |
317 std::string str = ""; |
339 real_c * real_sym; |
318 real_c *real_sym; |
|
319 char *endptr; |
340 real64_t ret; |
320 real64_t ret; |
341 |
321 |
342 if ((real_sym = dynamic_cast<real_c *>(sym)) == NULL) ERROR; |
322 if ((real_sym = dynamic_cast<real_c *>(sym)) == NULL) ERROR; |
343 for(unsigned int i = 0; i < strlen(real_sym->value); i++) |
323 for(unsigned int i = 0; i < strlen(real_sym->value); i++) |
344 if (real_sym->value[i] != '_') str += real_sym->value[i]; |
324 if (real_sym->value[i] != '_') str += real_sym->value[i]; |
345 |
325 |
346 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
326 errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! |
347 #if (real64_t == float) |
327 #if (real64_t == float) |
348 ret = strtof(str.c_str(), NULL); |
328 ret = strtof(str.c_str(), &endptr); |
349 #elif (real64_t == double) |
329 #elif (real64_t == double) |
350 ret = strtod(str.c_str(), NULL); |
330 ret = strtod(str.c_str(), &endptr); |
351 #elif (real64_t == long_double) |
331 #elif (real64_t == long_double) |
352 ret = strtold(str.c_str(), NULL); |
332 ret = strtold(str.c_str(), &endptr); |
353 #else |
333 #else |
354 #error Could not determine which data type is being used for real64_t (defined in absyntax.hh). Aborting! |
334 #error Could not determine which data type is being used for real64_t (defined in absyntax.hh). Aborting! |
355 #endif |
335 #endif |
356 if (overflow != NULL) |
336 if (overflow != NULL) |
357 *overflow = (errno == ERANGE); |
337 *overflow = (errno == ERANGE); |
358 if ((errno != 0) && (errno != ERANGE)) |
338 if (((errno != 0) && (errno != ERANGE)) || (*endptr != '\0')) |
359 ERROR; |
339 ERROR; |
360 |
340 |
361 return ret; |
341 return ret; |
362 } |
342 } |
363 |
343 |
591 } |
571 } |
592 |
572 |
593 |
573 |
594 void *constant_folding_c::visit(integer_c *symbol) { |
574 void *constant_folding_c::visit(integer_c *symbol) { |
595 bool overflow; |
575 bool overflow; |
596 NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, extract_int64_value(symbol, &overflow)); |
576 NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, extract_int64_value (symbol, 10, &overflow)); |
597 if (overflow) SET_OVFLOW(int64, symbol); |
577 if (overflow) SET_OVFLOW(int64, symbol); |
598 NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow)); |
578 NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, 10, &overflow)); |
599 if (overflow) SET_OVFLOW(uint64, symbol); |
579 if (overflow) SET_OVFLOW(uint64, symbol); |
600 return NULL; |
580 return NULL; |
601 } |
581 } |
602 |
582 |
603 |
583 |
616 /* NOTE 1: INT64_MIN = -(INT64_MAX + 1) ---> assuming two's complement representation!!! |
596 /* NOTE 1: INT64_MIN = -(INT64_MAX + 1) ---> assuming two's complement representation!!! |
617 * NOTE 2: if the user happens to want INT_MIN, that value will first be parsed as a positive integer, before being negated here. |
597 * NOTE 2: if the user happens to want INT_MIN, that value will first be parsed as a positive integer, before being negated here. |
618 * However, the positive value cannot be stored inside an int64! So, in this case, we will get the value from the uint64 cvalue. |
598 * However, the positive value cannot be stored inside an int64! So, in this case, we will get the value from the uint64 cvalue. |
619 */ |
599 */ |
620 // if (INT64_MIN == -INT64_MAX - 1) // We do not really need to check that the platform uses two's complement |
600 // if (INT64_MIN == -INT64_MAX - 1) // We do not really need to check that the platform uses two's complement |
621 if (VALID_CVALUE(uint64, symbol->exp) && (GET_CVALUE(uint64, symbol->exp) == -INT64_MIN)) { |
601 if (VALID_CVALUE(uint64, symbol->exp) && (GET_CVALUE(uint64, symbol->exp) == -INT64_MIN)) { // How do we stop the compiler from complaining about a comparison between int and unsigned int? |
622 NEW_CVALUE(int64, symbol); // in principle, if the above condition is true, then no new cvalue was created by DO_UNARY_OPER(). Not that it would be a problem to create a new one! |
602 NEW_CVALUE(int64, symbol); // in principle, if the above condition is true, then no new cvalue was created by DO_UNARY_OPER(). Not that it would be a problem to create a new one! |
623 SET_CVALUE(int64, symbol, INT64_MIN); |
603 SET_CVALUE(int64, symbol, INT64_MIN); |
624 } |
604 } |
625 return NULL; |
605 return NULL; |
626 } |
606 } |
627 |
607 |
628 |
608 |
629 void *constant_folding_c::visit(binary_integer_c *symbol) { |
609 void *constant_folding_c::visit(binary_integer_c *symbol) { |
|
610 bool overflow; |
|
611 NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, extract_int64_value (symbol, 2, &overflow)); |
|
612 if (overflow) SET_OVFLOW(int64, symbol); |
|
613 NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, 2, &overflow)); |
|
614 if (overflow) SET_OVFLOW(uint64, symbol); |
630 return NULL; |
615 return NULL; |
631 } |
616 } |
632 |
617 |
633 |
618 |
634 void *constant_folding_c::visit(octal_integer_c *symbol) { |
619 void *constant_folding_c::visit(octal_integer_c *symbol) { |
|
620 bool overflow; |
|
621 NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, extract_int64_value (symbol, 8, &overflow)); |
|
622 if (overflow) SET_OVFLOW(int64, symbol); |
|
623 NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, 8, &overflow)); |
|
624 if (overflow) SET_OVFLOW(uint64, symbol); |
635 return NULL; |
625 return NULL; |
636 } |
626 } |
637 |
627 |
638 |
628 |
639 void *constant_folding_c::visit(hex_integer_c *symbol) { |
629 void *constant_folding_c::visit(hex_integer_c *symbol) { |
640 NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, extract_hex_value(symbol)); |
630 bool overflow; |
641 NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, extract_hex_value(symbol)); |
631 NEW_CVALUE( int64, symbol); SET_CVALUE( int64, symbol, extract_int64_value (symbol, 16, &overflow)); |
|
632 if (overflow) SET_OVFLOW(int64, symbol); |
|
633 NEW_CVALUE(uint64, symbol); SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, 16, &overflow)); |
|
634 if (overflow) SET_OVFLOW(uint64, symbol); |
642 return NULL; |
635 return NULL; |
643 } |
636 } |
644 |
637 |
645 |
638 |
646 /* |
639 /* |