# HG changeset patch # User Edouard Tisserant # Date 1401269529 -7200 # Node ID 39086e324665fa818168f527dbd99d014cd4b8de # Parent 18a39a545ed98990014dd08c85a53931918a2bb0# Parent 54d5d185d6e2a993fb2c5a2386d80b2f05da2c76 merge diff -r 18a39a545ed9 -r 39086e324665 absyntax/absyntax.cc --- a/absyntax/absyntax.cc Thu Mar 20 17:27:29 2014 +0100 +++ b/absyntax/absyntax.cc Wed May 28 11:32:09 2014 +0200 @@ -57,6 +57,7 @@ this->last_column = last_column; this->last_order = last_order; this->datatype = NULL; + this->scope = NULL; this->const_value._real64.status = cs_undefined; this->const_value._int64.status = cs_undefined; this->const_value._uint64.status = cs_undefined; diff -r 18a39a545ed9 -r 39086e324665 absyntax/absyntax.hh --- a/absyntax/absyntax.hh Thu Mar 20 17:27:29 2014 +0100 +++ b/absyntax/absyntax.hh Wed May 28 11:32:09 2014 +0200 @@ -131,6 +131,10 @@ * Otherwise, it points to an object of the apropriate data type (e.g. int_type_name_c, bool_type_name_c, ...) */ symbol_c *datatype; + /* The POU in which the symbolic variable (or structured variable, or array variable, or located variable, - any more?) + * was declared. This will point to a Configuration, Resource, Program, FB, or Function. + */ + symbol_c *scope; /*** constant folding ***/ /* During stage 3 (semantic analysis/checking) we will be doing constant folding. diff -r 18a39a545ed9 -r 39086e324665 absyntax_utils/get_var_name.cc --- a/absyntax_utils/get_var_name.cc Thu Mar 20 17:27:29 2014 +0100 +++ b/absyntax_utils/get_var_name.cc Wed May 28 11:32:09 2014 +0200 @@ -35,26 +35,6 @@ * appear in the variable declaration. */ -/* For ex.: - * VAR - * A : int; - * B : ARRAY [1..9] of int; - * C : some_struct_t; - * END_VAR - * - * A := 56; - * B[8] := 99; - * C.e := 77; - * - * Calling this visitor class with symbolic_variable_c instance referencing 'A' in - * the line 'A := 56', will return the string "A". - * - * Calling this visitor class with array_variable_c instance referencing 'B[8]' in - * the line 'B[8] := 99', will return the string "B". - * - * Calling this visitor class with array_variable_c instance referencing 'C.e' in - * the line 'C.e := 77', will return the string "C". - */ #include "absyntax_utils.hh" @@ -68,6 +48,26 @@ +/* For ex.: + * VAR + * A : int; + * B : ARRAY [1..9] of int; + * C : some_struct_t; + * END_VAR + * + * A := 56; + * B[8] := 99; + * C.e := 77; + * + * Calling this method with symbolic_variable_c instance referencing 'A' in + * the line 'A := 56', will return the string "A". + * + * Calling this method with array_variable_c instance referencing 'B[8]' in + * the line 'B[8] := 99', will return the string "B". + * + * Calling this method with array_variable_c instance referencing 'C.e' in + * the line 'C.e := 77', will return the string "C". + */ token_c *get_var_name_c::get_name(symbol_c *symbol) { if (NULL == singleton_instance_) singleton_instance_ = new get_var_name_c(); @@ -77,6 +77,24 @@ } +/* Return the last field of a structured variable... + * + * A := 56; --> returns A + * B[8] := 99; --> returns B + * C.e := 77; --> returns e !!! + */ +symbol_c *get_var_name_c::get_last_field(symbol_c *symbol) { + if (NULL == singleton_instance_) singleton_instance_ = new get_var_name_c(); + if (NULL == singleton_instance_) ERROR; + + singleton_instance_->last_field = NULL; + symbol_c *res = (symbol_c*)(symbol->accept(*singleton_instance_)); + return (NULL != singleton_instance_->last_field)? singleton_instance_->last_field : res; +} + + + + /*************************/ /* B.1 - Common elements */ /*************************/ @@ -114,7 +132,11 @@ * this into account! */ // SYM_REF2(structured_variable_c, record_variable, field_selector) -void *get_var_name_c::visit(structured_variable_c *symbol) {return symbol->record_variable->accept(*this);} +void *get_var_name_c::visit(structured_variable_c *symbol) { + void *res = symbol->record_variable->accept(*this); + last_field = symbol->field_selector; + return res; +} diff -r 18a39a545ed9 -r 39086e324665 absyntax_utils/get_var_name.hh --- a/absyntax_utils/get_var_name.hh Thu Mar 20 17:27:29 2014 +0100 +++ b/absyntax_utils/get_var_name.hh Wed May 28 11:32:09 2014 +0200 @@ -63,10 +63,12 @@ public: get_var_name_c(void) {}; ~get_var_name_c(void) {}; - static token_c *get_name(symbol_c *symbol); - + static token_c *get_name(symbol_c *symbol); + static symbol_c *get_last_field(symbol_c *symbol); + private: static get_var_name_c *singleton_instance_; + symbol_c *last_field; private: /*************************/ diff -r 18a39a545ed9 -r 39086e324665 lib/accessor.h --- a/lib/accessor.h Thu Mar 20 17:27:29 2014 +0100 +++ b/lib/accessor.h Wed May 28 11:32:09 2014 +0200 @@ -113,15 +113,15 @@ // variable setting macros -#define __SET_VAR(prefix, name, new_value, ...)\ - if (!(prefix name.flags & __IEC_FORCE_FLAG)) prefix name.value __VA_ARGS__ = new_value -#define __SET_EXTERNAL(prefix, name, new_value, ...)\ - {extern IEC_BYTE __IS_GLOBAL_##name##_FORCED(void);\ - if (!(prefix name.flags & __IEC_FORCE_FLAG || __IS_GLOBAL_##name##_FORCED()))\ - (*(prefix name.value)) __VA_ARGS__ = new_value;} -#define __SET_EXTERNAL_FB(prefix, name, new_value, ...)\ - __SET_VAR((*(prefix name)), __VA_ARGS__, new_value) -#define __SET_LOCATED(prefix, name, new_value, ...)\ - if (!(prefix name.flags & __IEC_FORCE_FLAG)) *(prefix name.value) __VA_ARGS__ = new_value +#define __SET_VAR(prefix, name, suffix, new_value)\ + if (!(prefix name.flags & __IEC_FORCE_FLAG)) prefix name.value suffix = new_value +#define __SET_EXTERNAL(prefix, name, suffix, new_value)\ + {extern IEC_BYTE __IS_GLOBAL_##name##_FORCED();\ + if (!(prefix name.flags & __IEC_FORCE_FLAG || __IS_GLOBAL_##name##_FORCED()))\ + (*(prefix name.value)) suffix = new_value;} +#define __SET_EXTERNAL_FB(prefix, name, suffix, new_value)\ + __SET_VAR((*(prefix name)), suffix, new_value) +#define __SET_LOCATED(prefix, name, suffix, new_value)\ + if (!(prefix name.flags & __IEC_FORCE_FLAG)) *(prefix name.value) suffix = new_value #endif //__ACCESSOR_H diff -r 18a39a545ed9 -r 39086e324665 lib/rtc.txt --- a/lib/rtc.txt Thu Mar 20 17:27:29 2014 +0100 +++ b/lib/rtc.txt Wed May 28 11:32:09 2014 +0200 @@ -29,7 +29,7 @@ CURRENT_TIME : DT; END_VAR - {__SET_VAR(data__->,CURRENT_TIME,__CURRENT_TIME)} + {__SET_VAR(data__->,CURRENT_TIME,,__CURRENT_TIME)} IF IN THEN diff -r 18a39a545ed9 -r 39086e324665 lib/timer.txt --- a/lib/timer.txt Thu Mar 20 17:27:29 2014 +0100 +++ b/lib/timer.txt Wed May 28 11:32:09 2014 +0200 @@ -90,7 +90,7 @@ CURRENT_TIME, START_TIME : TIME; END_VAR - {__SET_VAR(data__->,CURRENT_TIME,__CURRENT_TIME)} + {__SET_VAR(data__->,CURRENT_TIME,,__CURRENT_TIME)} IF ((STATE = 0) AND NOT(PREV_IN) AND IN) (* found rising edge on IN *) THEN @@ -171,7 +171,7 @@ CURRENT_TIME, START_TIME : TIME; END_VAR - {__SET_VAR(data__->,CURRENT_TIME,__CURRENT_TIME)} + {__SET_VAR(data__->,CURRENT_TIME,,__CURRENT_TIME)} IF ((STATE = 0) AND NOT(PREV_IN) AND IN) (* found rising edge on IN *) THEN @@ -255,7 +255,7 @@ CURRENT_TIME, START_TIME : TIME; END_VAR - {__SET_VAR(data__->,CURRENT_TIME,__CURRENT_TIME)} + {__SET_VAR(data__->,CURRENT_TIME,,__CURRENT_TIME)} IF ((STATE = 0) AND PREV_IN AND NOT(IN)) (* found falling edge on IN *) THEN diff -r 18a39a545ed9 -r 39086e324665 main.hh --- a/main.hh Thu Mar 20 17:27:29 2014 +0100 +++ b/main.hh Wed May 28 11:32:09 2014 +0200 @@ -78,14 +78,16 @@ #include #if (LDBL_MANT_DIG == 53) /* NOTE: 64 bit IEC559 real has 53 bits for mantissa! */ - #define long_double long double - #define real64_t long_double /* so we can later use #if (real64_t == long_double) directives in the code! */ + #define real64_tX long_double /* so we can later use #if (real64_t == long_double) directives in the code! */ + #define real64_t long double /* NOTE: no underscore '_' between 'long' and 'double' */ #define REAL64_MAX LDBL_MAX #elif ( DBL_MANT_DIG == 53) /* NOTE: 64 bit IEC559 real has 53 bits for mantissa! */ - #define real64_t double + #define real64_tX double + #define real64_t double #define REAL64_MAX DBL_MAX #elif ( FLT_MANT_DIG == 53) /* NOTE: 64 bit IEC559 real has 53 bits for mantissa! */ - #define real64_t float + #define real64_tX float + #define real64_t float #define REAL64_MAX FLT_MAX #else #error Could not find a 64 bit floating point data type on this platform. Aborting... @@ -93,16 +95,16 @@ #if (LDBL_MANT_DIG == 24) /* NOTE: 32 bit IEC559 real has 24 bits for mantissa! */ - #ifndef long_double - #define long_double long double - #endif - #define real32_t long_double /* so we can later use #if (real32_t == long_double) directives in the code! */ + #define real32_tX long_double /* so we can later use #if (real32_t == long_double) directives in the code! */ + #define real32_t long double /* NOTE: no underscore '_' between 'long' and 'double' */ #define REAL32_MAX LDBL_MAX #elif ( DBL_MANT_DIG == 24) /* NOTE: 32 bit IEC559 real has 24 bits for mantissa! */ - #define real32_t double + #define real32_tX double + #define real32_t double #define REAL32_MAX DBL_MAX #elif ( FLT_MANT_DIG == 24) /* NOTE: 32 bit IEC559 real has 24 bits for mantissa! */ - #define real32_t float + #define real32_tX float + #define real32_t float #define REAL32_MAX FLT_MAX #else #error Could not find a 32 bit floating point data type on this platform. Aborting... diff -r 18a39a545ed9 -r 39086e324665 stage1_2/iec_bison.yy --- a/stage1_2/iec_bison.yy Thu Mar 20 17:27:29 2014 +0100 +++ b/stage1_2/iec_bison.yy Wed May 28 11:32:09 2014 +0200 @@ -4116,7 +4116,7 @@ variable_name_symtable.insert($1, prev_declared_fb_name_token); } | global_var_name ':' ref_spec /* defined in IEC 61131-3 v3 (REF_TO ...)*/ - {$$ = new external_declaration_c($1, new fb_spec_init_c($3, NULL, locloc(@3)), locloc(@$)); + {$$ = new external_declaration_c($1, $3, locloc(@$)); variable_name_symtable.insert($1, prev_declared_fb_name_token); } /* ERROR_CHECK_BEGIN */ diff -r 18a39a545ed9 -r 39086e324665 stage3/constant_folding.cc --- a/stage3/constant_folding.cc Thu Mar 20 17:27:29 2014 +0100 +++ b/stage3/constant_folding.cc Wed May 28 11:32:09 2014 +0200 @@ -379,14 +379,14 @@ else ERROR; errno = 0; // since strtoXX() may legally return 0, we must set errno to 0 to detect errors correctly! - #if (real64_t == float) + #if (real64_tX == float) ret = strtof(str.c_str(), &endptr); - #elif (real64_t == double) + #elif (real64_tX == double) ret = strtod(str.c_str(), &endptr); - #elif (real64_t == long_double) + #elif (real64_tX == long_double) ret = strtold(str.c_str(), &endptr); #else - #error Could not determine which data type is being used for real64_t (defined in absyntax.hh). Aborting! + #error Could not determine which data type is being used for real64_t (defined in main.hh). Aborting! #endif if (overflow != NULL) *overflow = (errno == ERANGE); diff -r 18a39a545ed9 -r 39086e324665 stage3/declaration_check.cc --- a/stage3/declaration_check.cc Thu Mar 20 17:27:29 2014 +0100 +++ b/stage3/declaration_check.cc Wed May 28 11:32:09 2014 +0200 @@ -70,6 +70,162 @@ } + + + + + + + +#include +class check_extern_c: public iterator_visitor_c { + public: + + private: + int current_display_error_level; + symbol_c *current_pou_decl; + symbol_c *current_resource_decl; + static std::set checked_decl; // A set with all the declarations that have already been checked, so we don't recheck it again! + + + public: + static int error_count; + + check_extern_c(symbol_c *current_pou, symbol_c *current_resource) { + current_display_error_level = 0; + current_pou_decl = current_pou; + current_resource_decl = current_resource; + } + + ~check_extern_c(void) {} + + + + void check_global_decl(symbol_c *p_decl) { + if (NULL == current_pou_decl) ERROR; + + if (checked_decl.find(p_decl) != checked_decl.end()) return; // has already been checked! + checked_decl.insert(p_decl); + + search_var_instance_decl_c search_var_instance_pou_glo_decl(current_pou_decl); + search_var_instance_decl_c search_var_instance_res_glo_decl(current_resource_decl); + search_var_instance_decl_c search_var_instance_ext_decl(p_decl); + function_param_iterator_c fpi(p_decl); + + symbol_c *var_name; + while((var_name = fpi.next()) != NULL) { + if (fpi.param_direction() == function_param_iterator_c::direction_extref) { + /* found an external reference parameter. */ + symbol_c *ext_decl = search_var_instance_ext_decl.get_decl(var_name); + + // NOTE: Must check the POU first, and RESOURCE second! + symbol_c *glo_decl = search_var_instance_res_glo_decl.get_decl(var_name); + search_var_instance_decl_c *search_var_instance_glo_decl = &search_var_instance_res_glo_decl; + if (NULL == glo_decl) { + glo_decl = search_var_instance_pou_glo_decl.get_decl(var_name); + search_var_instance_glo_decl = &search_var_instance_pou_glo_decl; + } + + if (NULL == glo_decl) { + STAGE3_ERROR(0, ext_decl, ext_decl, "Declaration error. The external variable does not match with any global variable."); + continue; + } + + /* Check whether variable's constness (CONSTANT) is compatible. + * VAR_GLOBAL is contant => VAR_EXTERNAL must also be CONSTANT + * VAR_GLOBAL is not contant => VAR_EXTERNAL may be CONSTANT, or not! + */ + search_var_instance_decl_c::opt_t ext_opt = search_var_instance_ext_decl. get_option(var_name); + search_var_instance_decl_c::opt_t glo_opt = search_var_instance_glo_decl->get_option(var_name); + if ((glo_opt == search_var_instance_decl_c::constant_opt) && (ext_opt != search_var_instance_decl_c::constant_opt)) + STAGE3_ERROR(0, glo_decl, glo_decl, "Declaration error. The external variable must be declared as constant, as it maps to a constant global variable."); + + /* TODO: Check redefinition data type. + * We need a new class (like search_base_type class) to get type id by variable declaration. + * symbol_c *glo_type = ????; + * symbol_c *ext_type = fpi.param_type(); + */ + /* For the moment, we will just use search_base_type_c instead... */ + symbol_c *glo_type = search_base_type_c::get_basetype_decl(glo_decl); + symbol_c *ext_type = search_base_type_c::get_basetype_decl(ext_decl); + if (! get_datatype_info_c::is_type_equal(glo_type, ext_type)) + STAGE3_ERROR(0, ext_decl, ext_decl, "Declaration error. Data type mismatch between external and global variable declarations."); + } + } + } + + + + /********************************/ + /* B 1.3.3 - Derived data types */ + /********************************/ + /* function_block_type_name ASSIGN structure_initialization */ + /* structure_initialization -> may be NULL ! */ + //SYM_REF2(fb_spec_init_c, function_block_type_name, structure_initialization) + /* NOTE: This class is only used when declaring FB variables, as in: + * name_list ':' function_block_type_name ASSIGN structure_initialization + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * fb_spec_init_c + * Here, fb_spec_init_c is used whether it is an external, local, or global variable! + * Note too that we must also check the datatypes of external and global variables!! + */ + void *visit(fb_spec_init_c *symbol) { + symbol_c *fb_decl = function_block_type_symtable.find_value(symbol->function_block_type_name); + /* stage1_2 guarantees that we are sure to find a declaration in FB or Program symtable. */ + if (fb_decl == function_block_type_symtable.end_value()) + ERROR; + fb_decl->accept(*this); + return NULL; + } + + /*****************************/ + /* B 1.5.2 - Function Blocks */ + /*****************************/ + /* FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */ + // SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body) + void *visit(function_block_declaration_c *symbol) { + check_global_decl(symbol); + /* The following two lines of code are only valid for v3 of IEC 61131-3, that allows VAR_GLOBAL declarations inside FBs! + * current_pou_decl = symbol; + * current_resource_decl = NULL; + */ + /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */ + if (NULL != symbol->var_declarations) + symbol->var_declarations->accept(*this); // This will eventually call the visit(fb_spec_init_c *) method, if any FB are declared here! + return NULL; + } + + /******************************************/ + /* B 1.5.3 - Declaration & Initialisation */ + /******************************************/ + /* PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */ + // SYM_REF3(program_declaration_c, program_type_name, var_declarations, function_block_body) + void *visit(program_declaration_c *symbol) { + check_global_decl(symbol); + /* The following two lines of code are only valid for v3 of IEC 61131-3, that allows VAR_GLOBAL declarations inside PROGRAMs! + * current_pou_decl = symbol; + * current_resource_decl = NULL; + */ + /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */ + if (NULL != symbol->var_declarations) + symbol->var_declarations->accept(*this); // This will eventually call the visit(fb_spec_init_c *) method, if any FB are declared here! + return NULL; + } + +}; + +int check_extern_c::error_count = 0; +std::set check_extern_c::checked_decl; + + + + + + + + + + declaration_check_c::declaration_check_c(symbol_c *ignore) { current_display_error_level = 0; current_pou_decl = NULL; @@ -82,92 +238,26 @@ } int declaration_check_c::get_error_count() { - return error_count; -} - -void declaration_check_c::check_global_decl(symbol_c *p_decl) { - if (NULL == current_pou_decl) ERROR; - - search_var_instance_decl_c search_var_instance_pou_glo_decl(current_pou_decl); - search_var_instance_decl_c search_var_instance_res_glo_decl(current_resource_decl); - search_var_instance_decl_c search_var_instance_ext_decl(p_decl); - function_param_iterator_c fpi(p_decl); - - symbol_c *var_name; - while((var_name = fpi.next()) != NULL) { - if (fpi.param_direction() == function_param_iterator_c::direction_extref) { - /* found an external reference parameter. */ - symbol_c *ext_decl = search_var_instance_ext_decl.get_decl(var_name); - - // NOTE: Must check the POU first, and RESOURCE second! - symbol_c *glo_decl = search_var_instance_res_glo_decl.get_decl(var_name); - search_var_instance_decl_c *search_var_instance_glo_decl = &search_var_instance_res_glo_decl; - if (NULL == glo_decl) { - glo_decl = search_var_instance_pou_glo_decl.get_decl(var_name); - search_var_instance_glo_decl = &search_var_instance_pou_glo_decl; - } - - if (NULL == glo_decl) { - STAGE3_ERROR(0, ext_decl, ext_decl, "Declaration error. The external variable does not match with any global variable."); - continue; - } - - /* Check whether variable's constness (CONSTANT) is compatible. - * VAR_GLOBAL is contant => VAR_EXTERNAL must also be CONSTANT - * VAR_GLOBAL is not contant => VAR_EXTERNAL may be CONSTANT, or not! - */ - search_var_instance_decl_c::opt_t ext_opt = search_var_instance_ext_decl. get_option(var_name); - search_var_instance_decl_c::opt_t glo_opt = search_var_instance_glo_decl->get_option(var_name); - if ((glo_opt == search_var_instance_decl_c::constant_opt) && (ext_opt != search_var_instance_decl_c::constant_opt)) - STAGE3_ERROR(0, glo_decl, glo_decl, "Declaration error. The external variable must be declared as constant, as it maps to a constant global variable."); - - /* TODO: Check redefinition data type. - * We need a new class (like search_base_type class) to get type id by variable declaration. - * symbol_c *glo_type = ????; - * symbol_c *ext_type = fpi.param_type(); - */ - /* For the moment, we will just use search_base_type_c instead... */ - symbol_c *glo_type = search_base_type_c::get_basetype_decl(glo_decl); - symbol_c *ext_type = search_base_type_c::get_basetype_decl(ext_decl); - if (! get_datatype_info_c::is_type_equal(glo_type, ext_type)) - STAGE3_ERROR(0, ext_decl, ext_decl, "Declaration error. Data type mismatch between external and global variable declarations."); - } - } -} - - + return check_extern_c::error_count; +} /*****************************/ /* B 1.5.2 - Function Blocks */ /*****************************/ /* FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */ // SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body) -void *declaration_check_c::visit(function_block_declaration_c *symbol) { - /* The following two lines of code are only valid for v3 of IEC 61131-3, that allows VAR_GLOBAL declarations inside FBs! - * current_pou_decl = symbol; - * current_resource_decl = NULL; - */ - /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */ - if (NULL != symbol->var_declarations) - symbol->var_declarations->accept(*this); - return NULL; -} +void *declaration_check_c::visit(function_block_declaration_c *symbol) + {return NULL;} // We only check the declarations that are used to instantiate variables. This is done in the configuration! /******************************************/ /* B 1.5.3 - Declaration & Initialisation */ /******************************************/ /* PROGRAM program_type_name program_var_declarations_list function_block_body END_PROGRAM */ // SYM_REF3(program_declaration_c, program_type_name, var_declarations, function_block_body) -void *declaration_check_c::visit(program_declaration_c *symbol) { - /* The following two lines of code are only valid for v3 of IEC 61131-3, that allows VAR_GLOBAL declarations inside PROGRAMs! - * current_pou_decl = symbol; - * current_resource_decl = NULL; - */ - /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */ - if (NULL != symbol->var_declarations) - symbol->var_declarations->accept(*this); - return NULL; -} +void *declaration_check_c::visit(program_declaration_c *symbol) + {return NULL;} // We only check the declarations that are used to instantiate variables. This is done in the configuration! + + /********************************/ /* B 1.7 Configuration elements */ @@ -199,8 +289,11 @@ /* enumvalue_symtable is filled in by enum_declaration_check_c, during stage3 semantic verification, with a list of all enumerated constants declared inside this POU */ // SYM_REF4(resource_declaration_c, resource_name, resource_type_name, global_var_declarations, resource_declaration, enumvalue_symtable_t enumvalue_symtable;) void *declaration_check_c::visit(resource_declaration_c *symbol) { + // check if any FB instantiated inside this resource (in a VAR_GLOBAL) has any VAR_EXTERNAL declarations incompatible with the configuration's VAR_GLOBALs + check_extern_c check_extern(current_pou_decl, current_resource_decl); + symbol->global_var_declarations->accept(check_extern); + // Now check the Programs instantiated in this resource current_resource_decl = symbol; - /* check if any FB declared as a VAR has any incompatible VAR_EXTERNAL declarations */ symbol->resource_declaration->accept(*this); current_resource_decl = NULL; return NULL; @@ -211,10 +304,11 @@ symbol_c *p_decl = program_type_symtable.find_value(symbol->program_type_name); if (p_decl == program_type_symtable.end_value()) p_decl = function_block_type_symtable.find_value(symbol->program_type_name); - /* stage1_2 guarantees that we are sure to find a declaration in FB or Program symtable. */ if (p_decl == function_block_type_symtable.end_value()) - ERROR; - check_global_decl(p_decl); + ERROR; // Should never occur! stage1_2 guarantees that we are sure to find a declaration in FB or Program symtable. + + check_extern_c check_extern(current_pou_decl, current_resource_decl); + p_decl->accept(check_extern); return NULL; } diff -r 18a39a545ed9 -r 39086e324665 stage3/narrow_candidate_datatypes.cc --- a/stage3/narrow_candidate_datatypes.cc Thu Mar 20 17:27:29 2014 +0100 +++ b/stage3/narrow_candidate_datatypes.cc Wed May 28 11:32:09 2014 +0200 @@ -70,6 +70,7 @@ fake_prev_il_instruction = NULL; current_il_instruction = NULL; il_operand = NULL; + current_scope = NULL; } narrow_candidate_datatypes_c::~narrow_candidate_datatypes_c(void) { @@ -651,6 +652,7 @@ /*********************/ // SYM_REF1(symbolic_variable_c, var_name) void *narrow_candidate_datatypes_c::visit(symbolic_variable_c *symbol) { + symbol->scope = current_scope; // the scope in which this variable was declared! symbol->var_name->datatype = symbol->datatype; return NULL; } @@ -674,6 +676,8 @@ if (symbol->subscripted_variable->candidate_datatypes.size() == 1) symbol->subscripted_variable->datatype = symbol->subscripted_variable->candidate_datatypes[0]; // set the datatype + // the scope in which this variable was declared! It will be the same as the subscripted variable (a symbolic_variable_ !) + symbol->scope = symbol->subscripted_variable->scope; return NULL; } @@ -708,6 +712,7 @@ if (symbol->record_variable->candidate_datatypes.size() == 1) symbol->record_variable->datatype = symbol->record_variable->candidate_datatypes[0]; // set the datatype + symbol->scope = symbol->record_variable->datatype; // the scope in which this variable was declared! return NULL; } @@ -764,12 +769,14 @@ symbol->type_name->datatype = search_base_type_c::get_basetype_decl(symbol->type_name); symbol->datatype = symbol->type_name->datatype; + current_scope = symbol; search_varfb_instance_type = new search_varfb_instance_type_c(symbol); symbol->var_declarations_list->accept(*this); if (debug) printf("Narrowing candidate data types list in body of function %s\n", ((token_c *)(symbol->derived_function_name))->value); symbol->function_body->accept(*this); delete search_varfb_instance_type; search_varfb_instance_type = NULL; + current_scope = NULL; return NULL; } @@ -777,13 +784,15 @@ /* B 1.5.2 Function blocks */ /***************************/ void *narrow_candidate_datatypes_c::visit(function_block_declaration_c *symbol) { + current_scope = symbol; search_varfb_instance_type = new search_varfb_instance_type_c(symbol); symbol->var_declarations->accept(*this); if (debug) printf("Narrowing candidate data types list in body of FB %s\n", ((token_c *)(symbol->fblock_name))->value); symbol->fblock_body->accept(*this); delete search_varfb_instance_type; search_varfb_instance_type = NULL; - + current_scope = NULL; + // A FB declaration can also be used as a Datatype! We now do the narrow algorithm considering it as such! if (symbol->candidate_datatypes.size() == 1) symbol->datatype = symbol->candidate_datatypes[0]; @@ -794,12 +803,14 @@ /* B 1.5.3 Programs */ /********************/ void *narrow_candidate_datatypes_c::visit(program_declaration_c *symbol) { + current_scope = symbol; search_varfb_instance_type = new search_varfb_instance_type_c(symbol); symbol->var_declarations->accept(*this); if (debug) printf("Narrowing candidate data types list in body of program %s\n", ((token_c *)(symbol->program_type_name))->value); symbol->function_block_body->accept(*this); delete search_varfb_instance_type; search_varfb_instance_type = NULL; + current_scope = NULL; return NULL; } diff -r 18a39a545ed9 -r 39086e324665 stage3/narrow_candidate_datatypes.hh --- a/stage3/narrow_candidate_datatypes.hh Thu Mar 20 17:27:29 2014 +0100 +++ b/stage3/narrow_candidate_datatypes.hh Wed May 28 11:32:09 2014 +0200 @@ -65,6 +65,7 @@ private: search_varfb_instance_type_c *search_varfb_instance_type; + symbol_c *current_scope; symbol_c *il_operand; il_instruction_c *fake_prev_il_instruction; il_instruction_c *current_il_instruction; diff -r 18a39a545ed9 -r 39086e324665 stage4/generate_c/generate_c.cc --- a/stage4/generate_c/generate_c.cc Thu Mar 20 17:27:29 2014 +0100 +++ b/stage4/generate_c/generate_c.cc Wed May 28 11:32:09 2014 +0200 @@ -386,6 +386,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 print_getter_c: public search_visitor_c { + private: + static print_getter_c *singleton_; + + public: + print_getter_c(void) {}; + + static bool is_complex_type(symbol_c *symbol) { + if (NULL == symbol) ERROR; + if (!get_datatype_info_c::is_type_valid (symbol->datatype)) return false; + 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 print_getter_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; + } + + +}; + +print_getter_c *print_getter_c::singleton_ = NULL; + + + + + + /* A helper class that analyses if the datatype of a variable is 'complex'. */ /* 'complex' means that it is either a strcuture or an array! */ @@ -1573,7 +1698,7 @@ s4o.print(SET_VAR); s4o.print("("); s4o.print(FB_FUNCTION_PARAM); - s4o.print("->,ENO,__BOOL_LITERAL(FALSE));\n"); + s4o.print("->,ENO,,__BOOL_LITERAL(FALSE));\n"); s4o.print(s4o.indent_spaces + "return;\n"); s4o.indent_left(); s4o.print(s4o.indent_spaces + "}\n"); @@ -1583,7 +1708,7 @@ s4o.print(SET_VAR); s4o.print("("); s4o.print(FB_FUNCTION_PARAM); - s4o.print("->,ENO,__BOOL_LITERAL(TRUE));\n"); + s4o.print("->,ENO,,__BOOL_LITERAL(TRUE));\n"); s4o.indent_left(); s4o.print(s4o.indent_spaces + "}\n"); @@ -2403,7 +2528,7 @@ s4o.print(SET_VAR); s4o.print("("); current_task_name->accept(*this); - s4o.print("_R_TRIG.,CLK, *"); + s4o.print("_R_TRIG.,CLK,, *"); symbol->single_data_source->accept(*this); s4o.print(");}\n"); s4o.print(s4o.indent_spaces + "R_TRIG"); diff -r 18a39a545ed9 -r 39086e324665 stage4/generate_c/generate_c_base.cc --- a/stage4/generate_c/generate_c_base.cc Thu Mar 20 17:27:29 2014 +0100 +++ b/stage4/generate_c/generate_c_base.cc Wed May 28 11:32:09 2014 +0200 @@ -270,10 +270,9 @@ /* Do not use print_token() as it will change everything into uppercase */ void *visit(pragma_c *symbol) { - s4o.print(s4o.indent_spaces); s4o.print("#define GetFbVar(var,...) __GET_VAR(data__->var,__VA_ARGS__)\n"); s4o.print(s4o.indent_spaces); - s4o.print("#define SetFbVar(var,val,...) __SET_VAR(data__->,var,val,__VA_ARGS__)\n"); + s4o.print("#define SetFbVar(var,val,...) __SET_VAR(data__->,var,__VA_ARGS__,val)\n"); s4o.print(symbol->value); s4o.print("\n"); s4o.print(s4o.indent_spaces); diff -r 18a39a545ed9 -r 39086e324665 stage4/generate_c/generate_c_il.cc --- a/stage4/generate_c/generate_c_il.cc Thu Mar 20 17:27:29 2014 +0100 +++ b/stage4/generate_c/generate_c_il.cc Wed May 28 11:32:09 2014 +0200 @@ -445,8 +445,8 @@ wanted_variablegeneration = complextype_base_assignment_vg; else wanted_variablegeneration = assignment_vg; - symbol->accept(*this); +/* s4o.print(","); if (negative) { if (get_datatype_info_c::is_BOOL_compatible(this->current_operand->datatype)) @@ -464,6 +464,24 @@ s4o.print(")"); wanted_variablegeneration = expression_vg; return NULL; +*/ + s4o.print(","); + if (type_is_complex) { + wanted_variablegeneration = complextype_suffix_vg; + symbol->accept(*this); + } + s4o.print(","); + if (negative) { + if (get_datatype_info_c::is_BOOL_compatible(this->current_operand->datatype)) + s4o.print("!"); + else + s4o.print("~"); + } + wanted_variablegeneration = expression_vg; + print_check_function(type, value, fb_value); + s4o.print(")"); + wanted_variablegeneration = expression_vg; + return NULL; } public: diff -r 18a39a545ed9 -r 39086e324665 stage4/generate_c/generate_c_inlinefcall.cc --- a/stage4/generate_c/generate_c_inlinefcall.cc Thu Mar 20 17:27:29 2014 +0100 +++ b/stage4/generate_c/generate_c_inlinefcall.cc Wed May 28 11:32:09 2014 +0200 @@ -281,7 +281,7 @@ else s4o.print(SET_VAR); s4o.print("(,"); - +/* wanted_variablegeneration = complextype_base_vg; symbol->accept(*this); s4o.print(","); @@ -295,6 +295,20 @@ s4o.print(")"); wanted_variablegeneration = expression_vg; return NULL; +*/ + wanted_variablegeneration = complextype_base_vg; + symbol->accept(*this); + s4o.print(","); + if (analyse_variable_c::contains_complex_type(symbol)) { + wanted_variablegeneration = complextype_suffix_vg; + symbol->accept(*this); + } + s4o.print(","); + wanted_variablegeneration = expression_vg; + print_check_function(type, value, NULL, true); + s4o.print(")"); + wanted_variablegeneration = expression_vg; + return NULL; } /*********************/ diff -r 18a39a545ed9 -r 39086e324665 stage4/generate_c/generate_c_sfc.cc --- a/stage4/generate_c/generate_c_sfc.cc Thu Mar 20 17:27:29 2014 +0100 +++ b/stage4/generate_c/generate_c_sfc.cc Wed May 28 11:32:09 2014 +0200 @@ -136,7 +136,7 @@ s4o.print(SET_VAR); s4o.print("("); print_step_argument(step_name, "state", true); - s4o.print(",0);\n"); + s4o.print(",,0);\n"); } void print_set_step(symbol_c *step_name) { @@ -144,7 +144,7 @@ s4o.print(SET_VAR); s4o.print("("); print_step_argument(step_name, "state", true); - s4o.print(",1);\n" + s4o.indent_spaces); + s4o.print(",,1);\n" + s4o.indent_spaces); print_step_argument(step_name, "elapsed_time"); s4o.print(" = __time_to_timespec(1, 0, 0, 0, 0, 0);\n"); } @@ -299,7 +299,7 @@ print_variable_prefix(); s4o.print(",__transition_list["); print_transition_number(); - s4o.print("],0);\n"); + s4o.print("],,0);\n"); s4o.indent_left(); s4o.print(s4o.indent_spaces + "}\n"); break; @@ -358,7 +358,7 @@ s4o.print("__"); s4o.print("transition_list["); print_transition_number(); - s4o.print("],"); + s4o.print("],,"); generate_c_il->print_implicit_variable_back(); // generate_c_il->reset_default_variable_name(); // generate_c_il does not require his anymore s4o.print(");\n"); @@ -376,7 +376,7 @@ s4o.print("__"); s4o.print("transition_list["); print_transition_number(); - s4o.print("],"); + s4o.print("],,"); symbol->transition_condition_st->accept(*generate_c_st); s4o.print(");\n"); } @@ -389,7 +389,7 @@ print_variable_prefix(); s4o.print(",__debug_transition_list["); print_transition_number(); - s4o.print("],"); + s4o.print("],,"); s4o.print(GET_VAR); s4o.print("("); print_variable_prefix(); @@ -514,7 +514,7 @@ s4o.print(SET_VAR); s4o.print("("); print_action_argument(symbol->action_name, "state", true); - s4o.print(",1);\n"); + s4o.print(",,1);\n"); s4o.indent_left(); s4o.print(s4o.indent_spaces + "}"); } @@ -575,7 +575,7 @@ print_variable_prefix(); s4o.print(","); current_action->accept(*this); - s4o.print(",1);\n"); + s4o.print(",,1);\n"); s4o.indent_left(); s4o.print(s4o.indent_spaces + "}\n"); s4o.print(s4o.indent_spaces + "else if (active) {\n"); @@ -591,14 +591,14 @@ print_variable_prefix(); s4o.print(","); current_action->accept(*this); - s4o.print(",0);\n"); + s4o.print(",,0);\n"); } else { s4o.print(SET_VAR); s4o.print("("); print_action_argument(current_action, "state", true); - s4o.print(",1);\n"); + s4o.print(",,1);\n"); } } if (strcmp(qualifier, "S") == 0 || strcmp(qualifier, "SL") == 0) { @@ -773,7 +773,7 @@ s4o.print(SET_VAR); s4o.print("("); print_variable_prefix(); - s4o.print(",__action_list[i].state,0);\n"); + s4o.print(",__action_list[i].state,,0);\n"); s4o.print(s4o.indent_spaces); print_variable_prefix(); s4o.print("__action_list[i].set = 0;\n"); @@ -895,7 +895,7 @@ s4o.print(SET_VAR); s4o.print("("); print_variable_prefix(); - s4o.print(",__action_list[i].state,"); + s4o.print(",__action_list[i].state,,"); s4o.print(GET_VAR); s4o.print("("); print_variable_prefix(); @@ -932,7 +932,7 @@ print_variable_prefix(); s4o.print(","); pt->symbol->accept(*this); - s4o.print(",0);\n"); + s4o.print(",,0);\n"); s4o.indent_left(); s4o.print(s4o.indent_spaces + "}\n"); s4o.print(s4o.indent_spaces + "else if ("); @@ -953,7 +953,7 @@ print_variable_prefix(); s4o.print(","); pt->symbol->accept(*this); - s4o.print(",1);\n"); + s4o.print(",,1);\n"); s4o.indent_left(); s4o.print(s4o.indent_spaces + "}\n"); } diff -r 18a39a545ed9 -r 39086e324665 stage4/generate_c/generate_c_sfcdecl.cc --- a/stage4/generate_c/generate_c_sfcdecl.cc Thu Mar 20 17:27:29 2014 +0100 +++ b/stage4/generate_c/generate_c_sfcdecl.cc Wed May 28 11:32:09 2014 +0200 @@ -252,7 +252,7 @@ print_variable_prefix(); s4o.print(",__step_list["); s4o.print(step_number); - s4o.print("].state,1);\n"); + s4o.print("].state,,1);\n"); step_number++; break; case stepdef_sd: diff -r 18a39a545ed9 -r 39086e324665 stage4/generate_c/generate_c_st.cc --- a/stage4/generate_c/generate_c_st.cc Thu Mar 20 17:27:29 2014 +0100 +++ b/stage4/generate_c/generate_c_st.cc Wed May 28 11:32:09 2014 +0200 @@ -49,9 +49,7 @@ public: typedef enum { expression_vg, - assignment_vg, complextype_base_vg, - complextype_base_assignment_vg, complextype_suffix_vg, fparam_output_vg } variablegeneration_t; @@ -157,9 +155,10 @@ else s4o.print(GET_VAR); } + + variablegeneration_t old_wanted_variablegeneration = wanted_variablegeneration; s4o.print("("); - - variablegeneration_t old_wanted_variablegeneration = wanted_variablegeneration; + print_variable_prefix(); wanted_variablegeneration = complextype_base_vg; symbol->accept(*this); s4o.print(","); @@ -177,14 +176,14 @@ symbol_c* value, symbol_c* fb_symbol = NULL, symbol_c* fb_value = NULL) { - - bool type_is_complex = false; + if (fb_symbol == NULL) { unsigned int vartype = analyse_variable_c::first_nonfb_vardecltype(symbol, scope_); - type_is_complex = analyse_variable_c::contains_complex_type(symbol); + symbol_c *first_nonfb = analyse_variable_c::find_first_nonfb(symbol); + if (first_nonfb == NULL) ERROR; if (vartype == search_var_instance_decl_c::external_vt) { - if (!get_datatype_info_c::is_type_valid (symbol->datatype)) ERROR; - if ( get_datatype_info_c::is_function_block(symbol->datatype)) + if (!get_datatype_info_c::is_type_valid (first_nonfb->datatype)) ERROR; + if ( get_datatype_info_c::is_function_block(first_nonfb->datatype)) // handle situation where we are copying a complete fb -> fb1.fb2.fb3 := fb4 (and fb3 is external!) s4o.print(SET_EXTERNAL_FB); else s4o.print(SET_EXTERNAL); @@ -202,26 +201,29 @@ s4o.print(SET_VAR); } s4o.print("("); - + if (fb_symbol != NULL) { print_variable_prefix(); + // It is my (MJS) conviction that by this time the following will always be true... + // wanted_variablegeneration == expression_vg; fb_symbol->accept(*this); s4o.print(".,"); - } - else if (type_is_complex) - wanted_variablegeneration = complextype_base_assignment_vg; - else - wanted_variablegeneration = assignment_vg; - - symbol->accept(*this); - s4o.print(","); - wanted_variablegeneration = expression_vg; - print_check_function(type, value, fb_value); - if (type_is_complex) { + symbol->accept(*this); + s4o.print(","); + s4o.print(","); + } + else { + print_variable_prefix(); + s4o.print(","); + wanted_variablegeneration = complextype_base_vg; + symbol->accept(*this); s4o.print(","); wanted_variablegeneration = complextype_suffix_vg; symbol->accept(*this); - } + s4o.print(","); + } + wanted_variablegeneration = expression_vg; + print_check_function(type, value, fb_value); s4o.print(")"); wanted_variablegeneration = expression_vg; return NULL; @@ -264,14 +266,8 @@ /*********************/ void *visit(symbolic_variable_c *symbol) { switch (wanted_variablegeneration) { - case complextype_base_assignment_vg: - case assignment_vg: - this->print_variable_prefix(); - s4o.print(","); - symbol->var_name->accept(*this); - break; case complextype_base_vg: - generate_c_base_c::visit(symbol); + symbol->var_name->accept(*this); //generate_c_base_c::visit(symbol); break; case complextype_suffix_vg: break; @@ -321,8 +317,9 @@ } this->print_variable_prefix(); s4o.printlocation(symbol->value + 1); - if ((this->is_variable_prefix_null() && wanted_variablegeneration != fparam_output_vg) || - wanted_variablegeneration != assignment_vg) + if (( this->is_variable_prefix_null() && (wanted_variablegeneration != fparam_output_vg)) || + (!this->is_variable_prefix_null() && (wanted_variablegeneration == expression_vg )) || + (!this->is_variable_prefix_null() && (wanted_variablegeneration == fparam_output_vg))) s4o.print(")"); return NULL; } @@ -334,28 +331,26 @@ // SYM_REF2(structured_variable_c, record_variable, field_selector) void *visit(structured_variable_c *symbol) { TRACE("structured_variable_c"); - bool type_is_complex = analyse_variable_c::is_complex_type(symbol->record_variable); switch (wanted_variablegeneration) { case complextype_base_vg: - case complextype_base_assignment_vg: symbol->record_variable->accept(*this); - if (!type_is_complex) { + if ( get_datatype_info_c::is_function_block(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("->"); + else + s4o.print("."); + symbol->field_selector->accept(*this); + } + break; + case complextype_suffix_vg: + symbol->record_variable->accept(*this); + if (!get_datatype_info_c::is_function_block(symbol->record_variable->datatype)) { // if the record variable is not a FB, then it will certainly be a structure! s4o.print("."); symbol->field_selector->accept(*this); } break; - case complextype_suffix_vg: - symbol->record_variable->accept(*this); - if (type_is_complex) { - s4o.print("."); - symbol->field_selector->accept(*this); - } - break; - case assignment_vg: - symbol->record_variable->accept(*this); - s4o.print("."); - symbol->field_selector->accept(*this); - break; default: if (this->is_variable_prefix_null()) { symbol->record_variable->accept(*this); @@ -374,7 +369,6 @@ void *visit(array_variable_c *symbol) { switch (wanted_variablegeneration) { case complextype_base_vg: - case complextype_base_assignment_vg: symbol->subscripted_variable->accept(*this); break; case complextype_suffix_vg: @@ -482,6 +476,7 @@ variablegeneration_t old_wanted_variablegeneration = wanted_variablegeneration; s4o.print("("); wanted_variablegeneration = complextype_base_vg; + print_variable_prefix(); symbol->exp->accept(*this); s4o.print(","); wanted_variablegeneration = complextype_suffix_vg; diff -r 18a39a545ed9 -r 39086e324665 stage4/generate_c/generate_c_vardecl.cc --- a/stage4/generate_c/generate_c_vardecl.cc Thu Mar 20 17:27:29 2014 +0100 +++ b/stage4/generate_c/generate_c_vardecl.cc Wed May 28 11:32:09 2014 +0200 @@ -169,7 +169,7 @@ print_variable_prefix(); s4o.print(","); symbol->elements[i]->accept(*this); - s4o.print(",temp);\n"); + s4o.print(",,temp);\n"); } return NULL; } @@ -577,7 +577,7 @@ print_variable_prefix(); s4o.print(","); symbol->elements[i]->accept(*this); - s4o.print(",temp);\n"); + s4o.print(",,temp);\n"); } return NULL; } @@ -1000,7 +1000,7 @@ s4o.print("}\n"); } else if (wanted_varformat == init_vf) { - s4o.print(","); + s4o.print(",,"); this->current_var_init_symbol->accept(*this); s4o.print(");\n"); }