diff -r be4373d07201 -r 0f7bcc160568 stage4/generate_c/generate_c_st.cc --- a/stage4/generate_c/generate_c_st.cc Sun Sep 28 17:48:42 2014 +0100 +++ b/stage4/generate_c/generate_c_st.cc Sun Oct 19 08:36:49 2014 +0100 @@ -348,8 +348,10 @@ || get_datatype_info_c::is_sfc_step (symbol->record_variable->datatype)) { if (NULL == symbol->record_variable->scope) ERROR; search_var_instance_decl_c search_var_instance_decl(symbol->record_variable->scope); - if (search_var_instance_decl_c::external_vt == search_var_instance_decl.get_vartype(get_var_name_c::get_last_field(symbol->record_variable))) - s4o.print("->"); + if (search_var_instance_decl_c::external_vt == search_var_instance_decl.get_vartype(get_var_name_c::get_last_field(symbol->record_variable))) + s4o.print("->"); /* please read the comment in visit(deref_operator_c *) tio understand what this line is doing! */ + else if (dynamic_cast(symbol->record_variable) != NULL) + s4o.print("->"); /* please read the comment in visit(deref_operator_c *) tio understand what this line is doing! */ else s4o.print("."); symbol->field_selector->accept(*this); @@ -360,12 +362,22 @@ // the following condition MUST be a negation of the above condition used in the 'case complextype_base_vg:' if (!( get_datatype_info_c::is_function_block(symbol->record_variable->datatype) // if the record variable is not a FB... || get_datatype_info_c::is_sfc_step (symbol->record_variable->datatype))) { // ...nor an SFC step name, then it will certainly be a structure! - s4o.print("."); + if (dynamic_cast(symbol->record_variable) != NULL) + s4o.print("->"); /* please read the comment in visit(deref_operator_c *) tio understand what this line is doing! */ + else + s4o.print("."); symbol->field_selector->accept(*this); } break; default: if (this->is_variable_prefix_null()) { + /* We are writing code for a FUNCTION. In this case, deref_operator_c are not transformed into the C pointer derefence syntax '->' (e.g. ptr->elem). + * We use instead the '*' syntax (e.g. (*ptr).elem) + * While in FB the '->' is generated by this structured_variable_c visitor, in Functions the '*' syntax is generated by the deref_operator_c visitor + * This is why here we do NOT have --> {if (dynamic_cast(symbol->record_variable) != NULL) ..} + * + * please read the comment in visit(deref_operator_c *) for more information! + */ symbol->record_variable->accept(*this); s4o.print("."); symbol->field_selector->accept(*this); @@ -463,6 +475,45 @@ /***********************/ /* B 3.1 - Expressions */ /***********************/ +void *visit(deref_operator_c *symbol) { + /* When producing C code for FUNCTION_BLOCKS, we use the '*' syntax (e.g. (*ptr).elem) + * When producing C code for a FUNCTION_BLOCK, the deref_operator_c are transformed in two ways, depending on where they occur. + * - deref_operator between a struct and its elem (e.g. struct_ref^.elem1) + * are transformed into C using the C pointer derefence syntax '->' (e.g. struct_ref->elem1). + * (In this case, '->' is generated by this structured_variable_c visitor) + * - deref_operator at the end of a struct variable (e.g. struct.elem_ptr^) + * are transformed using the '*' syntax for C pointer dereferencing (e.g. *(struct.elem_ptr) ) + * + * NOTE: Ideally, we should always use the '*' C pointer dereferencing syntax. However, due to the + * was the GET_VAR and SET_VAR are transformed into C, this does not work for '^' between a struct and its + * element (e.g. struct_ref^.elem), which is whey in this case only we use the '->' syntax. + * NOTE: The use of the -> syntax means that pointers to pointers are not supported betweem a struct and its elem + * (e.g. . struct_ref_ref^^.elem) as this would be transformed into the invalid C code struct_ref_ref->->elem. + * This is why we add a test for this case, and bug out with an error if we encounter it!! + */ + if (this->is_variable_prefix_null()) { + /* For code in FUNCTIONs */ + s4o.print("(*"); + symbol->exp->accept(*this); + s4o.print(")"); + } else { + /* For code in FBs, and PROGRAMS... */ + if (NULL == dynamic_cast(symbol->parent)) { + s4o.print("(*"); + symbol->exp->accept(*this); + s4o.print(")"); + } else { + /* We are in a structured variable - the structured_variable_c itself will already have printed out the '->' !! */ + if (NULL != dynamic_cast(symbol->exp)) + STAGE4_ERROR(symbol, symbol->exp, "The use of consecutive derefencing operators between a struct and its elem (ex: struct_ref_ref^^.elem) is currently not supported for code inside a Function_Block."); + symbol->exp->accept(*this); + } + } + + return NULL; +} + + void *visit(deref_expression_c *symbol) { s4o.print("("); if (this->is_variable_prefix_null()) { @@ -472,7 +523,6 @@ s4o.print(""); } else { /* For code in FBs, and PROGRAMS... */ - s4o.print("("); unsigned int vartype = analyse_variable_c::first_nonfb_vardecltype(symbol->exp, scope_); if (vartype == search_var_instance_decl_c::external_vt) { if (!get_datatype_info_c::is_type_valid (symbol->exp->datatype)) ERROR; @@ -496,8 +546,6 @@ symbol->exp->accept(*this); s4o.print(")"); wanted_variablegeneration = old_wanted_variablegeneration; - - s4o.print(")"); } s4o.print(")");