fix parsing of non base 10 constant values.
authorMario de Sousa <msousa@fe.up.pt>
Tue, 19 Jun 2012 11:23:30 +0100
changeset 601 683ae5444237
parent 600 f5d4e9f91513
child 602 456add88d64c
fix parsing of non base 10 constant values.
stage3/constant_folding.cc
--- a/stage3/constant_folding.cc	Mon Jun 18 16:11:00 2012 +0100
+++ b/stage3/constant_folding.cc	Tue Jun 19 11:23:30 2012 +0100
@@ -255,15 +255,29 @@
 
 /* extract the value of an integer from an integer_c object !! */
 /* NOTE: it must ignore underscores! */
-int64_t extract_int64_value(symbol_c *sym, int base, bool *overflow) {
-  std::string str = "";
-  integer_c *integer;
-  char *endptr;
-  int64_t ret;
-
-  if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR;
-  for(unsigned int i = 0; i < strlen(integer->value); i++)
-    if (integer->value[i] != '_')  str += integer->value[i];
+/* NOTE: To follow the basic structure used throughout the compiler's code, we should really be
+ * writing this as a visitor_c (and do away with the dynamic casts!), but since we only have 3 distinct 
+ * symbol class types to handle, it is probably easier to read if we write it as a standard function... 
+ */
+int64_t extract_int64_value(symbol_c *sym, bool *overflow) {
+  int64_t      ret;
+  std::string  str = "";
+  char        *endptr;
+  const char  *value;
+  int          base;
+  integer_c         *integer;
+  hex_integer_c     *hex_integer;
+  octal_integer_c   *octal_integer;
+  binary_integer_c  *binary_integer;
+
+   if       ((integer        = dynamic_cast<integer_c *>(sym))        != NULL) {value = integer       ->value + 0; base = 10;}
+   else  if ((hex_integer    = dynamic_cast<hex_integer_c *>(sym))    != NULL) {value = hex_integer   ->value + 3; base = 16;}
+   else  if ((octal_integer  = dynamic_cast<octal_integer_c *>(sym))  != NULL) {value = octal_integer ->value + 2; base =  8;}
+   else  if ((binary_integer = dynamic_cast<binary_integer_c *>(sym)) != NULL) {value = binary_integer->value + 2; base =  2;}
+   else  ERROR;
+
+  for(unsigned int i = 0; i < strlen(value); i++)
+    if (value[i] != '_')  str += 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, base);
@@ -275,15 +289,27 @@
   return ret;
 }
 
-uint64_t extract_uint64_value(symbol_c *sym, int base, bool *overflow) {
-  std::string str = "";
-  integer_c *integer;
-  char *endptr;
-  uint64_t ret;
-  
-  if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR;
-  for(unsigned int i = 0; i < strlen(integer->value); i++)
-    if (integer->value[i] != '_')  str += integer->value[i];
+
+
+uint64_t extract_uint64_value(symbol_c *sym, bool *overflow) {
+  uint64_t     ret;
+  std::string  str = "";
+  char        *endptr;
+  const char  *value;
+  int          base;
+  integer_c         *integer;
+  hex_integer_c     *hex_integer;
+  octal_integer_c   *octal_integer;
+  binary_integer_c  *binary_integer;
+
+   if       ((integer        = dynamic_cast<integer_c *>(sym))        != NULL) {value = integer       ->value + 0; base = 10;}
+   else  if ((hex_integer    = dynamic_cast<hex_integer_c *>(sym))    != NULL) {value = hex_integer   ->value + 3; base = 16;}
+   else  if ((octal_integer  = dynamic_cast<octal_integer_c *>(sym))  != NULL) {value = octal_integer ->value + 2; base =  8;}
+   else  if ((binary_integer = dynamic_cast<binary_integer_c *>(sym)) != NULL) {value = binary_integer->value + 2; base =  2;}
+   else  ERROR;
+
+  for(unsigned int i = 0; i < strlen(value); i++)
+    if (value[i] != '_')  str += 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, base);
@@ -573,9 +599,9 @@
 
 void *constant_folding_c::visit(integer_c *symbol) {
 	bool overflow;
-	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value (symbol, 10, &overflow));
+	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
 	if (overflow) SET_OVFLOW(int64, symbol);
-	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, 10, &overflow));
+	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
 	if (overflow) SET_OVFLOW(uint64, symbol);
 	return NULL;
 }
@@ -608,9 +634,9 @@
 
 void *constant_folding_c::visit(binary_integer_c *symbol) {
 	bool overflow;
-	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value (symbol,  2, &overflow));
+	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
 	if (overflow) SET_OVFLOW(int64, symbol);
-	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol,  2, &overflow));
+	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
 	if (overflow) SET_OVFLOW(uint64, symbol);
 	return NULL;
 }
@@ -618,9 +644,9 @@
 
 void *constant_folding_c::visit(octal_integer_c *symbol) {
 	bool overflow;
-	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value (symbol,  8, &overflow));
+	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
 	if (overflow) SET_OVFLOW(int64, symbol);
-	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol,  8, &overflow));
+	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
 	if (overflow) SET_OVFLOW(uint64, symbol);
 	return NULL;
 }
@@ -628,9 +654,9 @@
 
 void *constant_folding_c::visit(hex_integer_c *symbol) {
 	bool overflow;
-	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value (symbol, 16, &overflow));
+	NEW_CVALUE( int64, symbol);	SET_CVALUE( int64, symbol, extract_int64_value (symbol, &overflow));
 	if (overflow) SET_OVFLOW(int64, symbol);
-	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, 16, &overflow));
+	NEW_CVALUE(uint64, symbol);	SET_CVALUE(uint64, symbol, extract_uint64_value(symbol, &overflow));
 	if (overflow) SET_OVFLOW(uint64, symbol);
 	return NULL;
 }