stage4/generate_c/generate_c_st.cc
changeset 936 0f7bcc160568
parent 933 76324f461aed
child 941 c2ef93412407
--- 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(")");