diff -r a7d9e0b8636b -r 9c6c588fd708 stage4/generate_c/generate_c.cc --- a/stage4/generate_c/generate_c.cc Wed Feb 19 22:25:10 2014 +0100 +++ b/stage4/generate_c/generate_c.cc Wed Feb 19 22:27:11 2014 +0100 @@ -340,6 +340,131 @@ /***********************************************************************/ /***********************************************************************/ +/* A helper class that analyses if the datatype of a variable is 'complex'. */ +/* 'complex' means that it is either a strcuture or an array! */ +class analyse_variable_c: public search_visitor_c { + private: + static analyse_variable_c *singleton_; + + public: + analyse_variable_c(void) {}; + + static bool is_complex_type(symbol_c *symbol) { + if (NULL == symbol) ERROR; + if (!get_datatype_info_c::is_type_valid (symbol->datatype)) ERROR; + return ( get_datatype_info_c::is_structure(symbol->datatype) + || get_datatype_info_c::is_array (symbol->datatype) + ); + } + + + private: + symbol_c *last_fb, *first_non_fb_identifier; + + public: + /* returns the first element (from left to right) in a structured variable that is not a FB, i.e. is either a structure or an array! */ + /* eg: + * fb1.fb2.fb3.real returns ?????? + * fb1.fb2.struct1.real returns struct1 + * struct1.real returns struct1 + */ + static symbol_c *find_first_nonfb(symbol_c *symbol) { + if (NULL == singleton_) singleton_ = new analyse_variable_c(); + if (NULL == singleton_) ERROR; + if (NULL == symbol) ERROR; + + singleton_->last_fb = NULL; + singleton_->first_non_fb_identifier = NULL; + return (symbol_c *)symbol->accept(*singleton_); + } + + /* returns true if a strcutured variable (e.g. fb1.fb2.strcut1.real) contains a structure or array */ + /* eg: + * fb1.fb2.fb3.real returns FALSE + * fb1.fb2.struct1.real returns TRUE + * struct1.real returns TRUE + */ + static bool contains_complex_type(symbol_c *symbol) { + if (NULL == symbol) ERROR; + if (!get_datatype_info_c::is_type_valid(symbol->datatype)) ERROR; + + symbol_c *first_non_fb = (symbol_c *)find_first_nonfb(symbol); + return is_complex_type(first_non_fb->datatype); + } + + + /* returns the datatype of the variable returned by find_first_nonfb() */ + /* eg: + * fb1.fb2.fb3.real returns ?????? + * fb1.fb2.struct1.real returns datatype of struct1 + * struct1.real returns datatype of struct1 + */ + static search_var_instance_decl_c::vt_t first_nonfb_vardecltype(symbol_c *symbol, symbol_c *scope) { + if (NULL == symbol) ERROR; + if (!get_datatype_info_c::is_type_valid(symbol->datatype)) ERROR; + + symbol_c *first_non_fb = (symbol_c *)find_first_nonfb(symbol); + if (NULL != singleton_->last_fb) { + scope = singleton_->last_fb->datatype; + symbol = singleton_->first_non_fb_identifier; + } + + search_var_instance_decl_c search_var_instance_decl(scope); + + return search_var_instance_decl.get_vartype(symbol); + } + + + /*********************/ + /* B 1.4 - Variables */ + /*********************/ + void *visit(symbolic_variable_c *symbol) { + if (!get_datatype_info_c::is_type_valid (symbol->datatype)) ERROR; + if (!get_datatype_info_c::is_function_block(symbol->datatype)) { + first_non_fb_identifier = symbol; + return (void *)symbol; + } + last_fb = symbol; + return NULL; + } + + /*************************************/ + /* B.1.4.2 Multi-element Variables */ + /*************************************/ + + // SYM_REF2(structured_variable_c, record_variable, field_selector) + void *visit(structured_variable_c *symbol) { + symbol_c *res = (symbol_c *)symbol->record_variable->accept(*this); + if (NULL != res) return res; + + if (!get_datatype_info_c::is_type_valid (symbol->datatype)) ERROR; + if (!get_datatype_info_c::is_function_block(symbol->datatype)) { + first_non_fb_identifier = symbol->field_selector; + return (void *)symbol; + } + + last_fb = symbol; + return NULL; + } + + /* subscripted_variable '[' subscript_list ']' */ + //SYM_REF2(array_variable_c, subscripted_variable, subscript_list) + void *visit(array_variable_c *symbol) { + void *res = symbol->subscripted_variable->accept(*this); + if (NULL != res) return res; + return (void *)symbol; + } + + +}; + +analyse_variable_c *analyse_variable_c::singleton_ = NULL; + +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ + #include "generate_c_st.cc" #include "generate_c_il.cc" @@ -588,15 +713,13 @@ } inlinearray_mode_t; private: - stage4out_c *s4o_ptr; std::map inline_array_defined; std::string current_array_name; inlinearray_mode_t current_mode; public: generate_c_datatypes_c(stage4out_c *s4o_ptr, stage4out_c *s4o_incl_ptr) - : generate_c_typedecl_c(s4o_ptr, s4o_incl_ptr) { - generate_c_datatypes_c::s4o_ptr = s4o_ptr; + : generate_c_typedecl_c(s4o_incl_ptr) { current_mode = none_im; }; virtual ~generate_c_datatypes_c(void) { @@ -782,11 +905,20 @@ void *visit(array_spec_init_c *symbol) { switch (current_mode) { case arraydeclaration_im: + { + array_specification_c *specification = dynamic_cast(symbol->array_specification); + if (specification != NULL) + symbol->array_specification->accept(*this); + } + break; case arrayname_im: { array_specification_c *specification = dynamic_cast(symbol->array_specification); if (specification != NULL) symbol->array_specification->accept(*this); + identifier_c *name = dynamic_cast(symbol->array_specification); + if (name != NULL) + s4o_incl.print(name->value); } break; default: @@ -1013,14 +1145,13 @@ /***********************************************************************/ -class generate_c_pous_c: public generate_c_typedecl_c { +class generate_c_pous_c: public generate_c_base_c { private: - stage4out_c *s4o_ptr; + stage4out_c &s4o_incl; public: generate_c_pous_c(stage4out_c *s4o_ptr, stage4out_c *s4o_incl_ptr) - : generate_c_typedecl_c(s4o_ptr, s4o_incl_ptr) { - generate_c_pous_c::s4o_ptr = s4o_ptr; + : generate_c_base_c(s4o_ptr), s4o_incl(*s4o_incl_ptr) { }; virtual ~generate_c_pous_c(void) {} @@ -1054,8 +1185,8 @@ /********************/ /* 2.1.6 - Pragmas */ /********************/ -void *visit(enable_code_generation_pragma_c * symbol) {s4o_ptr->enable_output(); return NULL;} -void *visit(disable_code_generation_pragma_c * symbol) {s4o_ptr->disable_output(); return NULL;} +void *visit(enable_code_generation_pragma_c * symbol) {s4o.enable_output(); return NULL;} +void *visit(disable_code_generation_pragma_c * symbol) {s4o.disable_output(); return NULL;} /*************************/ /* B.1 - Common elements */ @@ -1617,16 +1748,13 @@ /***********************************************************************/ /***********************************************************************/ -class generate_c_config_c: public generate_c_typedecl_c { +class generate_c_config_c: public generate_c_base_c { private: - stage4out_c *s4o_ptr; - stage4out_c *s4o_incl_ptr; + stage4out_c &s4o_incl; public: generate_c_config_c(stage4out_c *s4o_ptr, stage4out_c *s4o_incl_ptr) - : generate_c_typedecl_c(s4o_ptr, s4o_incl_ptr) { - generate_c_config_c::s4o_ptr = s4o_ptr; - generate_c_config_c::s4o_incl_ptr = s4o_incl_ptr; + : generate_c_base_c(s4o_ptr), s4o_incl(*s4o_incl_ptr) { }; virtual ~generate_c_config_c(void) {} @@ -1646,14 +1774,14 @@ /* 2.1.6 - Pragmas */ /********************/ void *visit(enable_code_generation_pragma_c * symbol) { - s4o_ptr->enable_output(); - s4o_incl_ptr->enable_output(); + s4o.enable_output(); + s4o_incl.enable_output(); return NULL; } void *visit(disable_code_generation_pragma_c * symbol) { - s4o_ptr->disable_output(); - s4o_incl_ptr->disable_output(); + s4o.disable_output(); + s4o_incl.disable_output(); return NULL; }