absyntax_utils/absyntax_utils.cc
changeset 596 4efb11e44065
parent 591 76bad7199896
child 719 19595fce59f0
equal deleted inserted replaced
595:c41975a290ce 596:4efb11e44065
    48 #include <iostream>
    48 #include <iostream>
    49 #include <sstream>
    49 #include <sstream>
    50 #include <typeinfo>
    50 #include <typeinfo>
    51 #include <list>
    51 #include <list>
    52 #include <strings.h>
    52 #include <strings.h>
    53 #include <string.h>  /* required for strlen() */
    53 // #include <string.h>  /* required for strlen() */
    54 #include <stdlib.h>  /* required for atoi() */
    54 // #include <stdlib.h>  /* required for atoi() */
    55 #include <errno.h>   /* required for errno */
    55 // #include <errno.h>   /* required for errno */
    56 
    56 
    57 #include "../util/symtable.hh"
    57 #include "../util/symtable.hh"
    58 #include "../util/dsymtable.hh"
    58 #include "../util/dsymtable.hh"
    59 #include "../absyntax/visitor.hh"
    59 #include "../absyntax/visitor.hh"
       
    60 #include "../main.hh" // required for ERROR() and ERROR_MSG() macros.
    60 
    61 
    61 
    62 
    62 
    63 
    63 //#define DEBUG
    64 //#define DEBUG
    64 #ifdef DEBUG
    65 #ifdef DEBUG
    65 #define TRACE(classname) printf("\n____%s____\n",classname);
    66 #define TRACE(classname) printf("\n____%s____\n",classname);
    66 #else
    67 #else
    67 #define TRACE(classname)
    68 #define TRACE(classname)
    68 #endif
    69 #endif
    69 
    70 
    70 #define ERROR error_exit(__FILE__,__LINE__)
       
    71 /* function defined in main.cc */
       
    72 extern void error_exit(const char *file_name, int line_no);
       
    73 
    71 
    74 
    72 
    75 /***********************************************************************/
    73 /***********************************************************************/
    76 /***********************************************************************/
    74 /***********************************************************************/
    77 /***********************************************************************/
    75 /***********************************************************************/
    92   if (strcasecmp(name1->value, name2->value) == 0)
    90   if (strcasecmp(name1->value, name2->value) == 0)
    93     return 0;
    91     return 0;
    94 
    92 
    95   /* identifiers do not match! */
    93   /* identifiers do not match! */
    96   return 1;
    94   return 1;
    97 }
       
    98 
       
    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 
       
   120 /* extract the value of an integer from an integer_c object !! */
       
   121 /* NOTE: it must ignore underscores! */
       
   122 int64_t extract_int64_value(symbol_c *sym, bool *overflow) {
       
   123   std::string str = "";
       
   124   integer_c *integer;
       
   125   neg_integer_c * neg_integer;
       
   126   char *endptr;
       
   127   int64_t ret;
       
   128 
       
   129   if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR;
       
   130   for(unsigned int i = 0; i < strlen(integer->value); i++)
       
   131     if (integer->value[i] != '_')  str += integer->value[i];
       
   132 
       
   133   errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly!
       
   134   ret = matiec_strtoint64((int64_t *)NULL, str.c_str(), &endptr, 10);
       
   135   if (overflow != NULL)
       
   136     *overflow = (errno == ERANGE);
       
   137   if ((errno != 0) && (errno != ERANGE))
       
   138     ERROR;
       
   139 
       
   140   return ret;
       
   141 }
       
   142 
       
   143 uint64_t extract_uint64_value(symbol_c *sym, bool *overflow) {
       
   144   std::string str = "";
       
   145   integer_c *integer;
       
   146   neg_integer_c * neg_integer;
       
   147   char *endptr;
       
   148   uint64_t ret;
       
   149   
       
   150   if ((integer = dynamic_cast<integer_c *>(sym)) == NULL) ERROR;
       
   151   for(unsigned int i = 0; i < strlen(integer->value); i++)
       
   152     if (integer->value[i] != '_')  str += integer->value[i];
       
   153 
       
   154   errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly!
       
   155   ret = matiec_strtouint64((uint64_t *)NULL, str.c_str(), &endptr, 10);
       
   156   if (overflow != NULL)
       
   157     *overflow = (errno == ERANGE);
       
   158   if ((errno != 0) && (errno != ERANGE))
       
   159     ERROR;
       
   160 
       
   161   return ret;
       
   162 }
       
   163 
       
   164 
       
   165 /* extract the value of an hex integer from an hex_integer_c object !! */
       
   166 /* NOTE: it must ignore underscores! */
       
   167 uint64_t extract_hex_value(symbol_c *sym) {
       
   168   std::string str = "";
       
   169   char *endptr;
       
   170   hex_integer_c * hex_integer;
       
   171   uint64_t ret;
       
   172 
       
   173   if ((hex_integer = dynamic_cast<hex_integer_c *>(sym)) == NULL) ERROR;
       
   174   for(unsigned int i = 3; i < strlen(hex_integer->value); i++)
       
   175     if (hex_integer->value[i] != '_') str += hex_integer->value[i];
       
   176     
       
   177   errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly!
       
   178   ret = strtoull(str.c_str(), &endptr, 16);
       
   179   if (errno != 0) ERROR;
       
   180 
       
   181   return ret;
       
   182 }
       
   183 
       
   184 
       
   185 /* extract the value of a real from an real_c object !! */
       
   186 /* NOTE: it must ignore underscores! */
       
   187 /* From iec_bison.yy
       
   188  *  real:
       
   189  *   real_token		{$$ = new real_c($1, locloc(@$));}
       
   190  * | fixed_point_token	{$$ = new real_c($1, locloc(@$));}
       
   191  *
       
   192  * From iec_flex.ll
       
   193  * {real}			{yylval.ID=strdup(yytext); return real_token;}
       
   194  * {fixed_point}		{yylval.ID=strdup(yytext); return fixed_point_token;}
       
   195  *
       
   196  * real		{integer}\.{integer}{exponent}
       
   197  * fixed_point		{integer}\.{integer}
       
   198  * exponent        [Ee]([+-]?){integer}
       
   199  * integer         {digit}((_?{digit})*)
       
   200  */
       
   201 real64_t extract_real_value(symbol_c *sym, bool *overflow) {
       
   202   std::string str = "";
       
   203   real_c * real_sym;
       
   204   real64_t ret;
       
   205 
       
   206   if ((real_sym = dynamic_cast<real_c *>(sym)) == NULL) ERROR;
       
   207   for(unsigned int i = 0; i < strlen(real_sym->value); i++)
       
   208     if (real_sym->value[i] != '_') str += real_sym->value[i];
       
   209     
       
   210   errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly!
       
   211   #if    (real64_t  == float)
       
   212     ret = strtof(str.c_str(), NULL);
       
   213   #elif  (real64_t  == double)
       
   214     ret = strtod(str.c_str(), NULL);
       
   215   #elif  (real64_t  == long_double)
       
   216     ret = strtold(str.c_str(), NULL);
       
   217   #else 
       
   218     #error Could not determine which data type is being used for real64_t (defined in absyntax.hh). Aborting!
       
   219   #endif
       
   220   if (overflow != NULL)
       
   221     *overflow = (errno == ERANGE);
       
   222   if ((errno != 0) && (errno != ERANGE)) 
       
   223     ERROR;
       
   224 
       
   225   return ret;
       
   226 }
    95 }
   227 
    96 
   228 
    97 
   229 
    98 
   230 /***********************************************************************/
    99 /***********************************************************************/