absyntax_utils/get_sizeof_datatype.cc
changeset 625 c0bda77b37a0
parent 613 65a2e5ac2576
equal deleted inserted replaced
412:aad38592bdde 625:c0bda77b37a0
    43  *       as their data type is undefined (e.g. the datat type of '30'
    43  *       as their data type is undefined (e.g. the datat type of '30'
    44  *       could be 'INT' or 'SINT' or 'LINT' or 'USINT' or ...
    44  *       could be 'INT' or 'SINT' or 'LINT' or 'USINT' or ...
    45  *       NOTE: for base 10 numeric literals, any number taking up more than 64 bits
    45  *       NOTE: for base 10 numeric literals, any number taking up more than 64 bits
    46  *             will only return a bitsize of 1024!
    46  *             will only return a bitsize of 1024!
    47  *
    47  *
    48  *       For numeric literals, we return the minimum number of bits
    48  *       NOTE: The code that does the following has been commented out, since we no longer need it!
    49  *       required to store the value.
    49  *             It has been superceded by the constant_folding.cc class.
       
    50  *       // For numeric literals, we return the minimum number of bits
       
    51  *       // required to store the value.
    50  *
    52  *
    51  * E.g. TYPE new_int_t : INT; END_TYPE;
    53  * E.g. TYPE new_int_t : INT; END_TYPE;
    52  *      TYPE new_int2_t : INT = 2; END_TYPE;
    54  *      TYPE new_int2_t : INT = 2; END_TYPE;
    53  *      TYPE new_subr_t : INT (4..5); END_TYPE;
    55  *      TYPE new_subr_t : INT (4..5); END_TYPE;
    54  *
    56  *
    55  *    sizeof(SINT) ->  8
    57  *    sizeof(SINT) ->  8
    56  *    sizeof(INT)  -> 16
    58  *    sizeof(INT)  -> 16
    57  *    sizeof(DINT) -> 32
    59  *    sizeof(DINT) -> 32
    58  *    sizeof(LINT) -> 64
    60  *    sizeof(LINT) -> 64
    59  *
    61  *
    60  *    sizeof('1')       ->  1
    62  *       NOTE: The code that does the following has been commented out, since we no longer need it!
    61  *    sizeof('015')     ->  4    # Leading zeros are ignored!
    63  *             It has been superceded by the constant_folding.cc class.
    62  *    sizeof('0')       ->  1    # This is a special case! Even the value 0 needs at least 1 bit to store!
    64  *    // sizeof('1')       ->  1
    63  *    sizeof('16')      ->  5
    65  *    // sizeof('015')     ->  4    # Leading zeros are ignored!
    64  *    sizeof('2#00101') ->  3
    66  *    // sizeof('0')       ->  1    # This is a special case! Even the value 0 needs at least 1 bit to store!
    65  *    sizeof('8#334')   ->  9
    67  *    // sizeof('16')      ->  5
    66  *    sizeof('16#2A')   ->  8
    68  *    // sizeof('2#00101') ->  3
    67  *
    69  *    // sizeof('8#334')   ->  9
    68  *    sizeof('7.4')     ->  32   # all real literals return 32 bits, the size of a 'REAL'
    70  *    // sizeof('16#2A')   ->  8
    69  *                               # TODO: study IEC 60559 for the range of values that may be
    71  *
    70  *                               #       stored in a REAL (basic single width floating point format)
    72  *    // sizeof('7.4')     ->  32   # all real literals return 32 bits, the size of a 'REAL'
    71  *                               #       and in a LREAL (basic double width floating point format)
    73  *    //                            # TODO: study IEC 60559 for the range of values that may be
    72  *                               #       and see if some real literals need to return 64 instead!
    74  *    //                            #       stored in a REAL (basic single width floating point format)
       
    75  *    //                            #       and in a LREAL (basic double width floating point format)
       
    76  *    //                            #       and see if some real literals need to return 64 instead!
    73  */
    77  */
    74 
    78 
    75 #include "get_sizeof_datatype.hh"
    79 #include "get_sizeof_datatype.hh"
    76 
    80 
    77 #include <stdlib.h>
    81 #include <stdlib.h>
    78 #include <string.h>
    82 #include <string.h>
    79 #include <limits.h>  // get definition of ULLONG_MAX
    83 #include <limits.h>  // get definition of ULLONG_MAX
    80 /* tell stdint.h we want the definition of UINT64_MAX */
    84 #include <errno.h>
    81 #define __STDC_LIMIT_MACROS
    85 
    82 #include <stdint.h>  // get definition of uint64_t and UINT64_MAX
    86 #include "../main.hh" // required for ERROR() and ERROR_MSG() macros, and uint64_t and UINT64_MAX
    83 
    87 
    84 
       
    85 #define ERROR error_exit(__FILE__,__LINE__)
       
    86 /* function defined in main.cc */
       
    87 extern void error_exit(const char *file_name, int line_no);
       
    88 
    88 
    89 
    89 
    90 /* This class is a singleton.
    90 /* This class is a singleton.
    91  * So we need a pointer to the singe instance...
    91  * So we need a pointer to the singe instance...
    92  */
    92  */
    95 
    95 
    96 #define _encode_int(value)   ((void *)(((char *)NULL) + value))
    96 #define _encode_int(value)   ((void *)(((char *)NULL) + value))
    97 #define _decode_int(ptr)     (((char *)ptr) - ((char *)NULL))
    97 #define _decode_int(ptr)     (((char *)ptr) - ((char *)NULL))
    98 
    98 
    99 
    99 
   100 
   100 #if 0   /* We no longer need the code for handling numeric literals. But keep it around for a little while longer... */
   101 
       
   102 /* divide a base 10 literal in a string by 2 */
   101 /* divide a base 10 literal in a string by 2 */
   103 /* returns remainder of division (0 or 1)    */
   102 /* returns remainder of division (0 or 1)    */
   104 static int strdivby2(char **strptr) {
   103 static int strdivby2(char **strptr) {
   105   char *str = *strptr;
   104   char *str = *strptr;
   106   int carry = 0;
   105   int carry = 0;
   119   while (**strptr == '0') 
   118   while (**strptr == '0') 
   120     (*strptr)++;
   119     (*strptr)++;
   121 
   120 
   122   return carry;
   121   return carry;
   123 }
   122 }
   124 
   123 #endif
   125 
   124 
   126 /* Constructor for the singleton class */
   125 /* Constructor for the singleton class */
   127 int get_sizeof_datatype_c::getsize(symbol_c *data_type_symbol) {
   126 int get_sizeof_datatype_c::getsize(symbol_c *data_type_symbol) {
   128       if (NULL == singleton) {
   127       if (NULL == singleton) {
   129         singleton = new get_sizeof_datatype_c;
   128         singleton = new get_sizeof_datatype_c;
   137 get_sizeof_datatype_c::~get_sizeof_datatype_c(void) {
   136 get_sizeof_datatype_c::~get_sizeof_datatype_c(void) {
   138       if (NULL != singleton) delete singleton;
   137       if (NULL != singleton) delete singleton;
   139       singleton = NULL;
   138       singleton = NULL;
   140     }
   139     }
   141 
   140 
   142 
   141 #if 0   /* We no longer need the code for handling numeric literals. But keep it around for a little while longer... */
   143 /*********************/
   142 /*********************/
   144 /* B 1.2 - Constants */
   143 /* B 1.2 - Constants */
   145 /*********************/
   144 /*********************/
   146 
   145 
   147 /******************************/
   146 /******************************/
   156   */
   155   */
   157 
   156 
   158 /* NOTE: all integer_c and real_c tokens will always be positive (i.e. no leading '-')
   157 /* NOTE: all integer_c and real_c tokens will always be positive (i.e. no leading '-')
   159  * due to the way the source code is parsed by iec.flex.
   158  * due to the way the source code is parsed by iec.flex.
   160  */
   159  */
       
   160 
       
   161 /*
       
   162  * IEC6113-3 and C++ use IEC 60559 to rappresent floating point data types
       
   163  * REAL  => float       => single precision 	32 bit
       
   164  * LREAL => double      => double precision 	64 bit
       
   165  * ????? => long double => quadruple precision 128 bit
       
   166  */
   161 void *get_sizeof_datatype_c::visit(real_c *symbol) {
   167 void *get_sizeof_datatype_c::visit(real_c *symbol) {
   162   return _encode_int(32);
   168   char *endp;
       
   169   long double ld_test;
       
   170   double d_test;
       
   171   float  f_test;
       
   172 
       
   173   /* copy the original string, but leave out any underscores... */
       
   174   char *sval, *oval;
       
   175   const char *pval;
       
   176   oval = sval = (char *)malloc(strlen(symbol->value)+1);
       
   177   if (NULL ==  sval) ERROR;
       
   178   
       
   179   for (pval = symbol->value, sval = oval; *pval != '\0'; pval++) {
       
   180     if ('_' != *pval) {*sval = *pval; sval++;}
       
   181   }  
       
   182   *sval = '\0';  
       
   183   
       
   184   sval = oval;
       
   185   if ('\0' == *sval) ERROR;
       
   186 
       
   187   /* now do the conversion using the new string... */
       
   188   f_test = strtof(sval, &endp);
       
   189   if (*endp != '\0') ERROR;
       
   190   if (ERANGE != errno) {
       
   191     /* No overflow/underflow! => It fits in a float! */
       
   192     free(oval);
       
   193     return _encode_int(32);
       
   194   }
       
   195   
       
   196   d_test = strtod(sval, &endp);
       
   197   if (*endp != '\0') ERROR;
       
   198   if (ERANGE != errno) {
       
   199     /* No overflow/underflow! => It fits in a double! */
       
   200     free(oval);
       
   201     return _encode_int(64);
       
   202   }
       
   203   
       
   204   ld_test = strtold(sval, &endp);
       
   205   if (*endp != '\0') ERROR;
       
   206   if (ERANGE != errno) {
       
   207     /* No overflow/underflow! => It fits in a long double! */
       
   208     free(oval);
       
   209     return _encode_int(128);
       
   210   }
       
   211 
       
   212   free(oval);
       
   213   return _encode_int(65535); /* a very large number!!! */
   163 }
   214 }
   164 
   215 
   165 void *get_sizeof_datatype_c::visit(neg_real_c *symbol) {
   216 void *get_sizeof_datatype_c::visit(neg_real_c *symbol) {
   166   return symbol->exp->accept(*this);
   217   return symbol->exp->accept(*this);
   167 }
   218 }
   280   for (bitsize = 0; '\0' != *sval; sval++) {
   331   for (bitsize = 0; '\0' != *sval; sval++) {
   281     /* consistency check: make sure we only have binary digits! */
   332     /* consistency check: make sure we only have binary digits! */
   282     if (('0' != *sval) && ('1' != *sval) && ('_' != *sval))
   333     if (('0' != *sval) && ('1' != *sval) && ('_' != *sval))
   283       ERROR;
   334       ERROR;
   284 
   335 
   285     if ('_' != *sval) bitsize ++; /* 1 bits per binary digit */
   336     if ('_' != *sval) bitsize++; /* 1 bits per binary digit */
   286   }
   337   }
   287 
   338 
   288   /* special case... if (value == 0) <=> (bitsize == 0), return bit size of 1 ! */
   339   /* special case... if (value == 0) <=> (bitsize == 0), return bit size of 1 ! */
   289   if (0 == bitsize) bitsize = 1;
   340   if (0 == bitsize) bitsize = 1;
   290 
   341 
   350   for (bitsize = 0; '\0' != *sval; sval++) {
   401   for (bitsize = 0; '\0' != *sval; sval++) {
   351     /* consistency check: make sure we only have hex digits or underscores! */
   402     /* consistency check: make sure we only have hex digits or underscores! */
   352     /* Assumes ASCII */
   403     /* Assumes ASCII */
   353     if (!(('0' <= *sval) && ('9' >= *sval)) && 
   404     if (!(('0' <= *sval) && ('9' >= *sval)) && 
   354         !(('A' <= *sval) && ('F' >= *sval)) &&
   405         !(('A' <= *sval) && ('F' >= *sval)) &&
   355         !(('a' <= *sval) && ('b' >= *sval)) &&
   406         !(('a' <= *sval) && ('f' >= *sval)) &&
   356         ! ('_' == *sval))
   407         ! ('_' == *sval))
   357       ERROR;
   408       ERROR;
   358 
   409 
   359     if ('_' != *sval) bitsize += 4; /* 4 bits per hex digit */
   410     if ('_' != *sval) bitsize += 4; /* 4 bits per hex digit */
   360   }
   411   }
   362   /* special case... if (value == 0) <=> (bitsize == 0), return bit size of 1 ! */
   413   /* special case... if (value == 0) <=> (bitsize == 0), return bit size of 1 ! */
   363   if (0 == bitsize) bitsize = 1;
   414   if (0 == bitsize) bitsize = 1;
   364 
   415 
   365   return _encode_int(bitsize);
   416   return _encode_int(bitsize);
   366 }
   417 }
   367 
   418 #endif
   368 
   419 
   369 /***********************************/
   420 /***********************************/
   370 /* B 1.3.1 - Elementary Data Types */
   421 /* B 1.3.1 - Elementary Data Types */
   371 /***********************************/
   422 /***********************************/
   372 // void *get_sizeof_datatype_c::visit(time_type_name_c *symbol) {return _encode_int(0); }
   423 // void *get_sizeof_datatype_c::visit(time_type_name_c *symbol) {return _encode_int(0); }