absyntax_utils/get_datatype_info.cc
changeset 987 562b67922966
parent 986 2064a22cc1f2
child 1016 91bef6704b44
equal deleted inserted replaced
986:2064a22cc1f2 987:562b67922966
   621  *    082  ->  82
   621  *    082  ->  82
   622  *   +082  ->  82
   622  *   +082  ->  82
   623  *    -82  -> -82
   623  *    -82  -> -82
   624  *    -8_2 -> -82
   624  *    -8_2 -> -82
   625  *   -082  -> -82
   625  *   -082  -> -82
       
   626  * 
       
   627  * NOTE: since matiec supports arrays with a variable size (a non compliant IEC 61131-3 extension)
       
   628  *        (e.g.: ARRAY [1..max] of INT, where max must be a constant variable)
       
   629  *       the symbol passed to this function may also be a symbolic_variable
       
   630  *       (or more correctly, a symbolic_constant_c).
       
   631  *       In this case we simply return the string itself.
   626  */
   632  */
   627 #include <string.h>  /* required for strlen() */
   633 #include <string.h>  /* required for strlen() */
   628 static std::string normalize_integer(symbol_c *symbol) {
   634 static std::string normalize_subrange_limit(symbol_c *symbol) {
   629   integer_c *token = dynamic_cast<integer_c *>(symbol);
   635   // See if it is an integer...  
   630   if (NULL == token) ERROR;
   636   integer_c *integer = dynamic_cast<integer_c *>(symbol);
   631   
   637   if (NULL != integer) {
   632   std::string str = "";
   638     // handle it as an integer!
   633   bool leading_zero = true;
   639     std::string str = "";
   634   unsigned int offset = 0;
   640     bool leading_zero = true;
   635 
   641     unsigned int offset = 0;
   636   // handle any possible leading '-' or '+'
   642 
   637   if        (token->value[0] == '-') {
   643     // handle any possible leading '-' or '+'
   638       //    '-' -> retained
   644     if        (integer->value[0] == '-') {
   639       str += token->value[0];
   645         //    '-' -> retained
   640       offset++;
   646         str += integer->value[0];
   641   } else if (token->value[0] == '+')
   647         offset++;
   642       //    '+' -> skip, so '+8' and '8' will both result in '8'
   648     } else if (integer->value[0] == '+')
   643       offset++;
   649         //    '+' -> skip, so '+8' and '8' will both result in '8'
   644     
   650         offset++;
   645   for (unsigned int i = offset; i < strlen(token->value); i++) {
   651       
   646     if (leading_zero && (token->value[i] != '0'))
   652     for (unsigned int i = offset; i < strlen(integer->value); i++) {
   647       leading_zero = false;
   653       if (leading_zero && (integer->value[i] != '0'))
   648     if (!leading_zero && token->value[i] != '_')
   654         leading_zero = false;
   649       str += token->value[i];
   655       if (!leading_zero && integer->value[i] != '_')
       
   656         str += integer->value[i];
       
   657     }
       
   658     return str;
   650   }
   659   }
   651   return str;
   660   
       
   661   // See if it is an sybolic_variable_c or symbolic_constant_c...  
       
   662   /* NOTE: Remember that this is only needed if the subrange limit has not yet been
       
   663    *       constant_folded --> when the const_value is valid, the normalize_subrange_limit()
       
   664    *       never gets called!!
       
   665    * 
       
   666    *       Situations where it has not been constant folded can occur if:
       
   667    *         - the get_datatype_info_c::is_type_equal() is called before the constant folding algorithm does its thing
       
   668    *         - the constant folding algorithm is called before get_datatype_info_c::is_type_equal(), but
       
   669    *           the symbol does not get constant folded
       
   670    *           (e.g: the POU containing a VAR_EXTERN is not instantiated, and that external variable is used to define a 
       
   671    *            limit of an array (ARRAY of [1..ext_var] OF INT)
       
   672    *        However, currently get_datatype_info_c::is_type_equal() is not called to handle the above case, 
       
   673    *        and constant_folding is being called before all algorithms that call get_datatype_info_c::is_type_equal(),
       
   674    *        which means that the following code is really not needed. But it is best to have it here just in case...
       
   675    */
       
   676   token_c             *token    = NULL;
       
   677   symbolic_constant_c *symconst = dynamic_cast<symbolic_constant_c *>(symbol);
       
   678   symbolic_variable_c *symvar   = dynamic_cast<symbolic_variable_c *>(symbol);
       
   679   if (NULL != symconst) token   = dynamic_cast<            token_c *>(symconst->var_name);
       
   680   if (NULL != symvar  ) token   = dynamic_cast<            token_c *>(symvar  ->var_name);
       
   681   if (NULL != token)
       
   682     // handle it as a symbolic_variable/constant_c
       
   683     return token->value;    
       
   684   
       
   685   ERROR;
       
   686   return NULL; // humour the compiler...
   652 }
   687 }
   653 
   688 
   654 
   689 
   655 /* A helper method to get_datatype_info_c::is_type_equal()
   690 /* A helper method to get_datatype_info_c::is_type_equal()
   656  *  Assuming the relaxed datatype model, determine whether the two array datatypes are equal/equivalent
   691  *  Assuming the relaxed datatype model, determine whether the two array datatypes are equal/equivalent
   689          && (subrange_2->upper_limit->const_value._int64.is_valid() || subrange_2->upper_limit->const_value._uint64.is_valid())
   724          && (subrange_2->upper_limit->const_value._int64.is_valid() || subrange_2->upper_limit->const_value._uint64.is_valid())
   690        ) {
   725        ) {
   691       if (! (subrange_1->lower_limit->const_value == subrange_2->lower_limit->const_value)) return false;
   726       if (! (subrange_1->lower_limit->const_value == subrange_2->lower_limit->const_value)) return false;
   692       if (! (subrange_1->upper_limit->const_value == subrange_2->upper_limit->const_value)) return false;
   727       if (! (subrange_1->upper_limit->const_value == subrange_2->upper_limit->const_value)) return false;
   693     } else {
   728     } else {
   694       if (normalize_integer(subrange_1->lower_limit) != normalize_integer(subrange_2->lower_limit)) return false;
   729       // NOTE: nocasecmp_c() class is defined in absyntax.hh. nocasecmp_c() instantiates an object, and nocasecmp_c()() uses the () operator on that object. 
   695       if (normalize_integer(subrange_1->upper_limit) != normalize_integer(subrange_2->upper_limit)) return false;
   730       if (! nocasecmp_c()(normalize_subrange_limit(subrange_1->lower_limit), normalize_subrange_limit(subrange_2->lower_limit))) return false;
       
   731       if (! nocasecmp_c()(normalize_subrange_limit(subrange_1->upper_limit), normalize_subrange_limit(subrange_2->upper_limit))) return false;
   696     }
   732     }
   697   }
   733   }
   698 
   734 
   699   return is_type_equal(search_base_type_c::get_basetype_decl(array_1->non_generic_type_name),
   735   return is_type_equal(search_base_type_c::get_basetype_decl(array_1->non_generic_type_name),
   700                        search_base_type_c::get_basetype_decl(array_2->non_generic_type_name));
   736                        search_base_type_c::get_basetype_decl(array_2->non_generic_type_name));