346 */ |
346 */ |
347 if ( get_datatype_info_c::is_function_block(symbol->record_variable->datatype) |
347 if ( get_datatype_info_c::is_function_block(symbol->record_variable->datatype) |
348 || get_datatype_info_c::is_sfc_step (symbol->record_variable->datatype)) { |
348 || get_datatype_info_c::is_sfc_step (symbol->record_variable->datatype)) { |
349 if (NULL == symbol->record_variable->scope) ERROR; |
349 if (NULL == symbol->record_variable->scope) ERROR; |
350 search_var_instance_decl_c search_var_instance_decl(symbol->record_variable->scope); |
350 search_var_instance_decl_c search_var_instance_decl(symbol->record_variable->scope); |
351 if (search_var_instance_decl_c::external_vt == search_var_instance_decl.get_vartype(get_var_name_c::get_last_field(symbol->record_variable))) |
351 if (search_var_instance_decl_c::external_vt == search_var_instance_decl.get_vartype(get_var_name_c::get_last_field(symbol->record_variable))) |
352 s4o.print("->"); |
352 s4o.print("->"); /* please read the comment in visit(deref_operator_c *) tio understand what this line is doing! */ |
|
353 else if (dynamic_cast<deref_operator_c *>(symbol->record_variable) != NULL) |
|
354 s4o.print("->"); /* please read the comment in visit(deref_operator_c *) tio understand what this line is doing! */ |
353 else |
355 else |
354 s4o.print("."); |
356 s4o.print("."); |
355 symbol->field_selector->accept(*this); |
357 symbol->field_selector->accept(*this); |
356 } |
358 } |
357 break; |
359 break; |
358 case complextype_suffix_vg: |
360 case complextype_suffix_vg: |
359 symbol->record_variable->accept(*this); |
361 symbol->record_variable->accept(*this); |
360 // the following condition MUST be a negation of the above condition used in the 'case complextype_base_vg:' |
362 // the following condition MUST be a negation of the above condition used in the 'case complextype_base_vg:' |
361 if (!( get_datatype_info_c::is_function_block(symbol->record_variable->datatype) // if the record variable is not a FB... |
363 if (!( get_datatype_info_c::is_function_block(symbol->record_variable->datatype) // if the record variable is not a FB... |
362 || get_datatype_info_c::is_sfc_step (symbol->record_variable->datatype))) { // ...nor an SFC step name, then it will certainly be a structure! |
364 || get_datatype_info_c::is_sfc_step (symbol->record_variable->datatype))) { // ...nor an SFC step name, then it will certainly be a structure! |
363 s4o.print("."); |
365 if (dynamic_cast<deref_operator_c *>(symbol->record_variable) != NULL) |
|
366 s4o.print("->"); /* please read the comment in visit(deref_operator_c *) tio understand what this line is doing! */ |
|
367 else |
|
368 s4o.print("."); |
364 symbol->field_selector->accept(*this); |
369 symbol->field_selector->accept(*this); |
365 } |
370 } |
366 break; |
371 break; |
367 default: |
372 default: |
368 if (this->is_variable_prefix_null()) { |
373 if (this->is_variable_prefix_null()) { |
|
374 /* 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). |
|
375 * We use instead the '*' syntax (e.g. (*ptr).elem) |
|
376 * While in FB the '->' is generated by this structured_variable_c visitor, in Functions the '*' syntax is generated by the deref_operator_c visitor |
|
377 * This is why here we do NOT have --> {if (dynamic_cast<deref_operator_c *>(symbol->record_variable) != NULL) ..} |
|
378 * |
|
379 * please read the comment in visit(deref_operator_c *) for more information! |
|
380 */ |
369 symbol->record_variable->accept(*this); |
381 symbol->record_variable->accept(*this); |
370 s4o.print("."); |
382 s4o.print("."); |
371 symbol->field_selector->accept(*this); |
383 symbol->field_selector->accept(*this); |
372 } |
384 } |
373 else |
385 else |
461 /* B.3 - Language ST (Structured Text) */ |
473 /* B.3 - Language ST (Structured Text) */ |
462 /***************************************/ |
474 /***************************************/ |
463 /***********************/ |
475 /***********************/ |
464 /* B 3.1 - Expressions */ |
476 /* B 3.1 - Expressions */ |
465 /***********************/ |
477 /***********************/ |
|
478 void *visit(deref_operator_c *symbol) { |
|
479 /* When producing C code for FUNCTION_BLOCKS, we use the '*' syntax (e.g. (*ptr).elem) |
|
480 * When producing C code for a FUNCTION_BLOCK, the deref_operator_c are transformed in two ways, depending on where they occur. |
|
481 * - deref_operator between a struct and its elem (e.g. struct_ref^.elem1) |
|
482 * are transformed into C using the C pointer derefence syntax '->' (e.g. struct_ref->elem1). |
|
483 * (In this case, '->' is generated by this structured_variable_c visitor) |
|
484 * - deref_operator at the end of a struct variable (e.g. struct.elem_ptr^) |
|
485 * are transformed using the '*' syntax for C pointer dereferencing (e.g. *(struct.elem_ptr) ) |
|
486 * |
|
487 * NOTE: Ideally, we should always use the '*' C pointer dereferencing syntax. However, due to the |
|
488 * was the GET_VAR and SET_VAR are transformed into C, this does not work for '^' between a struct and its |
|
489 * element (e.g. struct_ref^.elem), which is whey in this case only we use the '->' syntax. |
|
490 * NOTE: The use of the -> syntax means that pointers to pointers are not supported betweem a struct and its elem |
|
491 * (e.g. . struct_ref_ref^^.elem) as this would be transformed into the invalid C code struct_ref_ref->->elem. |
|
492 * This is why we add a test for this case, and bug out with an error if we encounter it!! |
|
493 */ |
|
494 if (this->is_variable_prefix_null()) { |
|
495 /* For code in FUNCTIONs */ |
|
496 s4o.print("(*"); |
|
497 symbol->exp->accept(*this); |
|
498 s4o.print(")"); |
|
499 } else { |
|
500 /* For code in FBs, and PROGRAMS... */ |
|
501 if (NULL == dynamic_cast<structured_variable_c *>(symbol->parent)) { |
|
502 s4o.print("(*"); |
|
503 symbol->exp->accept(*this); |
|
504 s4o.print(")"); |
|
505 } else { |
|
506 /* We are in a structured variable - the structured_variable_c itself will already have printed out the '->' !! */ |
|
507 if (NULL != dynamic_cast<deref_operator_c *>(symbol->exp)) |
|
508 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."); |
|
509 symbol->exp->accept(*this); |
|
510 } |
|
511 } |
|
512 |
|
513 return NULL; |
|
514 } |
|
515 |
|
516 |
466 void *visit(deref_expression_c *symbol) { |
517 void *visit(deref_expression_c *symbol) { |
467 s4o.print("("); |
518 s4o.print("("); |
468 if (this->is_variable_prefix_null()) { |
519 if (this->is_variable_prefix_null()) { |
469 /* For code in FUNCTIONs */ |
520 /* For code in FUNCTIONs */ |
470 s4o.print("*"); |
521 s4o.print("*"); |
471 symbol->exp->accept(*this); |
522 symbol->exp->accept(*this); |
472 s4o.print(""); |
523 s4o.print(""); |
473 } else { |
524 } else { |
474 /* For code in FBs, and PROGRAMS... */ |
525 /* For code in FBs, and PROGRAMS... */ |
475 s4o.print("("); |
|
476 unsigned int vartype = analyse_variable_c::first_nonfb_vardecltype(symbol->exp, scope_); |
526 unsigned int vartype = analyse_variable_c::first_nonfb_vardecltype(symbol->exp, scope_); |
477 if (vartype == search_var_instance_decl_c::external_vt) { |
527 if (vartype == search_var_instance_decl_c::external_vt) { |
478 if (!get_datatype_info_c::is_type_valid (symbol->exp->datatype)) ERROR; |
528 if (!get_datatype_info_c::is_type_valid (symbol->exp->datatype)) ERROR; |
479 if ( get_datatype_info_c::is_function_block(symbol->exp->datatype)) |
529 if ( get_datatype_info_c::is_function_block(symbol->exp->datatype)) |
480 s4o.print(GET_EXTERNAL_FB_DREF); |
530 s4o.print(GET_EXTERNAL_FB_DREF); |