--- 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<deref_operator_c *>(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<deref_operator_c *>(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<deref_operator_c *>(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<structured_variable_c *>(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<deref_operator_c *>(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(")");