# HG changeset patch # User Edouard Tisserant # Date 1395307779 -3600 # Node ID e05d69c1ccb35725e2f07e79ba454c3f49de83f5 # Parent 599e88d12f9a99e705c80e6907dbaa00e46ef369# Parent 878e9bf4c6ec0e043412f4190cfb2054c8420ef7 merge diff -r 878e9bf4c6ec -r e05d69c1ccb3 .hgignore --- a/.hgignore Fri Feb 28 11:27:53 2014 +0100 +++ b/.hgignore Thu Mar 20 10:29:39 2014 +0100 @@ -3,13 +3,17 @@ .project *~ *.a +*.orig .dep *.Po autom4te.cache Makefile +Makefile.in config.log stamp-h1 config.status +configure +aclocal.m4 @@ -22,4 +26,5 @@ ^stage1_2/iec_bison.cc ^stage1_2/iec_bison.h ^stage1_2/iec_flex.cc -^config/config.h \ No newline at end of file +^config/config.h +^test/ diff -r 878e9bf4c6ec -r e05d69c1ccb3 absyntax/absyntax.def --- a/absyntax/absyntax.def Fri Feb 28 11:27:53 2014 +0100 +++ b/absyntax/absyntax.def Thu Mar 20 10:29:39 2014 +0100 @@ -468,6 +468,30 @@ SYM_REF2(fb_spec_init_c, function_block_type_name, structure_initialization) +/* Taken fron IEC 61131-3 v3 + * // Table 14 - Reference operations + * Ref_Type_Decl : Ref_Type_Name ':' Ref_Spec_Init ; + * Ref_Spec_Init : Ref_Spec ( ':=' Ref_Value )? ; + * Ref_Spec : 'REF_TO' Non_Gen_Type_Name ; + * Ref_Type_Name : Identifier ; + * Ref_Name : Identifier ; + * Ref_Value : Ref_Addr | 'NULL' ; + * Ref_Addr : 'REF' '(' (Symbolic_Variable | FB_Name | Class_Instance_Name ) ')' ; + * Ref_Assign : Ref_Name ':=' (Ref_Name | Ref_Deref | Ref_Value ) ; + * Ref_Deref : 'DREF' '(' Ref_Name ')' ; + */ + +/* ref_spec: REF_TO (non_generic_type_name | function_block_type_name) */ +SYM_REF1(ref_spec_c, type_name) + +/* For the moment, we do not support initialising reference data types */ +/* ref_spec_init: ref_spec; */ +/* SYM_REF0(ref_spec_init_c) */ + +/* ref_type_decl: identifier ':' ref_spec_init */ +SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init) + + /*********************/ /* B 1.4 - Variables */ /*********************/ @@ -1090,6 +1114,7 @@ /***********************/ /* B 3.1 - Expressions */ /***********************/ +SYM_REF1(ref_expression_c, exp) /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */ SYM_REF2(or_expression_c, l_exp, r_exp) SYM_REF2(xor_expression_c, l_exp, r_exp) SYM_REF2(and_expression_c, l_exp, r_exp) diff -r 878e9bf4c6ec -r e05d69c1ccb3 lib/accessor.h --- a/lib/accessor.h Fri Feb 28 11:27:53 2014 +0100 +++ b/lib/accessor.h Thu Mar 20 10:29:39 2014 +0100 @@ -92,6 +92,7 @@ __GET_VAR(((*name) __VA_ARGS__)) #define __GET_LOCATED(name, ...)\ ((name.flags & __IEC_FORCE_FLAG) ? name.fvalue __VA_ARGS__ : (*(name.value)) __VA_ARGS__) + #define __GET_VAR_BY_REF(name, ...)\ ((name.flags & __IEC_FORCE_FLAG) ? &(name.fvalue __VA_ARGS__) : &(name.value __VA_ARGS__)) #define __GET_EXTERNAL_BY_REF(name, ...)\ @@ -101,6 +102,16 @@ #define __GET_LOCATED_BY_REF(name, ...)\ ((name.flags & __IEC_FORCE_FLAG) ? &(name.fvalue __VA_ARGS__) : &((*(name.value)) __VA_ARGS__)) +#define __GET_VAR_REF(name, ...)\ + (&(name.value __VA_ARGS__)) +#define __GET_EXTERNAL_REF(name, ...)\ + (&((*(name.value)) __VA_ARGS__)) +#define __GET_EXTERNAL_FB_REF(name, ...)\ + (&(__GET_VAR(((*name) __VA_ARGS__)))) +#define __GET_LOCATED_REF(name, ...)\ + (&((*(name.value)) __VA_ARGS__)) + + // variable setting macros #define __SET_VAR(prefix, name, new_value, ...)\ if (!(prefix name.flags & __IEC_FORCE_FLAG)) prefix name.value __VA_ARGS__ = new_value diff -r 878e9bf4c6ec -r e05d69c1ccb3 main.cc --- a/main.cc Fri Feb 28 11:27:53 2014 +0100 +++ b/main.cc Thu Mar 20 10:29:39 2014 +0100 @@ -109,10 +109,10 @@ static void printusage(const char *cmd) { - printf("\nsyntax: %s [-h] [-v] [-f] [-s] [-c] [-I ] [-T ] \n", cmd); - printf(" h : show this help message\n"); - printf(" v : print version number\n"); - printf(" f : display full token location on error messages\n"); + printf("\nsyntax: %s [] [-O ] [-I ] [-T ] \n", cmd); + printf(" -h : show this help message\n"); + printf(" -v : print version number\n"); + printf(" -f : display full token location on error messages\n"); /******************************************************/ /* whether we are supporting safe extensions */ /* as defined in PLCopen - Technical Committee 5 */ @@ -120,11 +120,14 @@ /* Part 1: Concepts and Function Blocks, */ /* Version 1.0 is Official Release */ /******************************************************/ - printf(" s : allow use of safe extensions (e.g. SAFExxx data types))\n"); - printf(" n : allow use of nested comments\n"); - printf(" c : create conversion functions for enumerated data types\n"); + printf(" -s : allow use of safe extensions (e.g. SAFExxx data types))\n"); + printf(" -n : allow use of nested comments (an IEC 61131-3 v3 feature)\n"); + printf(" -r : allow use of REF() operator (an IEC 61131-3 v3 feature)\n"); + printf(" -c : create conversion functions for enumerated data types\n"); + printf(" -O : options for output (code generation) stage. Available options for %s are...\n", cmd); + stage4_print_options(); printf("\n"); - printf("%s - Copyright (C) 2003-2011 \n" + printf("%s - Copyright (C) 2003-2014 \n" "This program comes with ABSOLUTELY NO WARRANTY!\n" "This is free software licensed under GPL v3, and you are welcome to redistribute it under the conditions specified by this license.\n", PACKAGE_NAME); } @@ -143,20 +146,20 @@ stage1_2_options.full_token_loc = false; /* error messages specify full token location */ stage1_2_options.conversion_functions = false; /* Create a conversion function for derived datatype */ stage1_2_options.nested_comments = false; /* Allow the use of nested comments. */ + stage1_2_options.ref_operator = false; /* Allow the use of REF() operator. */ stage1_2_options.includedir = NULL; /* Include directory, where included files will be searched for... */ /******************************************/ /* Parse command line options... */ /******************************************/ - while ((optres = getopt(argc, argv, ":nhvfscI:T:")) != -1) { + while ((optres = getopt(argc, argv, ":nhvfrscI:T:O:")) != -1) { switch(optres) { case 'h': printusage(argv[0]); return 0; case 'v': - fprintf(stdout, "%s version %s\n" - "changeset id: %s\n", PACKAGE_NAME, PACKAGE_VERSION, HGVERSION); + fprintf(stdout, "%s version %s\n" "changeset id: %s\n", PACKAGE_NAME, PACKAGE_VERSION, HGVERSION); return 0; case 'f': @@ -167,6 +170,10 @@ stage1_2_options.safe_extensions = true; break; + case 'r': + stage1_2_options.ref_operator = true; + break; + case 'c': stage1_2_options.conversion_functions = true; break; @@ -193,7 +200,11 @@ builddir = optarg; break; - case ':': /* -I or -T without operand */ + case 'O': + if (stage4_parse_options(optarg) < 0) errflg++; + break; + + case ':': /* -I, -T, or -O without operand */ fprintf(stderr, "Option -%c requires an operand\n", optopt); errflg++; break; diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage1_2/iec_bison.yy --- a/stage1_2/iec_bison.yy Fri Feb 28 11:27:53 2014 +0100 +++ b/stage1_2/iec_bison.yy Thu Mar 20 10:29:39 2014 +0100 @@ -356,6 +356,7 @@ %token prev_declared_array_type_name_token %token prev_declared_structure_type_name_token %token prev_declared_string_type_name_token +%token prev_declared_ref_type_name_token /* defined in IEC 61131-3 v3 */ %type prev_declared_simple_type_name %type prev_declared_subrange_type_name @@ -363,6 +364,7 @@ %type prev_declared_array_type_name %type prev_declared_structure_type_name %type prev_declared_string_type_name +%type prev_declared_ref_type_name /* defined in IEC 61131-3 v3 */ %token prev_declared_derived_function_name_token %token prev_declared_derived_function_block_name_token @@ -412,6 +414,9 @@ %type en_identifier %type eno_identifier +/* Keyword in IEC 61131-3 v3 */ +%token REF +%token REF_TO @@ -759,6 +764,11 @@ %token END_STRUCT +%type ref_spec /* defined in IEC 61131-3 v3 */ +%type ref_spec_init /* defined in IEC 61131-3 v3 */ +%type ref_type_decl /* defined in IEC 61131-3 v3 */ + + /*********************/ /* B 1.4 - Variables */ @@ -1290,6 +1300,7 @@ * are not required. Their values are integrated * directly into other rules... */ +%type ref_expression /* an extension to the IEC 61131-3 v2 standard, based on the IEC 61131-3 v3 standard */ %type expression %type xor_expression %type and_expression @@ -1559,6 +1570,7 @@ | prev_declared_array_type_name | prev_declared_structure_type_name | prev_declared_string_type_name +| prev_declared_ref_type_name /* defined in IEC 61131-3 v3 */ | prev_declared_derived_function_name | prev_declared_derived_function_block_name | prev_declared_program_type_name @@ -1569,19 +1581,20 @@ ; -prev_declared_variable_name: prev_declared_variable_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_fb_name: prev_declared_fb_name_token {$$ = new identifier_c($1, locloc(@$));}; - -prev_declared_simple_type_name: prev_declared_simple_type_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_subrange_type_name: prev_declared_subrange_type_name_token {$$ = new identifier_c($1, locloc(@$));}; +prev_declared_variable_name : prev_declared_variable_name_token {$$ = new identifier_c($1, locloc(@$));}; +prev_declared_fb_name : prev_declared_fb_name_token {$$ = new identifier_c($1, locloc(@$));}; + +prev_declared_simple_type_name : prev_declared_simple_type_name_token {$$ = new identifier_c($1, locloc(@$));}; +prev_declared_subrange_type_name : prev_declared_subrange_type_name_token {$$ = new identifier_c($1, locloc(@$));}; prev_declared_enumerated_type_name: prev_declared_enumerated_type_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_array_type_name: prev_declared_array_type_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_structure_type_name: prev_declared_structure_type_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_string_type_name: prev_declared_string_type_name_token {$$ = new identifier_c($1, locloc(@$));}; - -prev_declared_derived_function_name: prev_declared_derived_function_name_token {$$ = new identifier_c($1, locloc(@$));}; +prev_declared_array_type_name : prev_declared_array_type_name_token {$$ = new identifier_c($1, locloc(@$));}; +prev_declared_structure_type_name : prev_declared_structure_type_name_token {$$ = new identifier_c($1, locloc(@$));}; +prev_declared_string_type_name : prev_declared_string_type_name_token {$$ = new identifier_c($1, locloc(@$));}; +prev_declared_ref_type_name : prev_declared_ref_type_name_token {$$ = new identifier_c($1, locloc(@$));}; /* defined in IEC 61131-3 v3 */ + +prev_declared_derived_function_name : prev_declared_derived_function_name_token {$$ = new identifier_c($1, locloc(@$));}; prev_declared_derived_function_block_name: prev_declared_derived_function_block_name_token {$$ = new identifier_c($1, locloc(@$));}; -prev_declared_program_type_name: prev_declared_program_type_name_token {$$ = new identifier_c($1, locloc(@$));}; +prev_declared_program_type_name : prev_declared_program_type_name_token {$$ = new identifier_c($1, locloc(@$));}; @@ -2479,6 +2492,7 @@ | prev_declared_array_type_name | prev_declared_structure_type_name | prev_declared_string_type_name +| prev_declared_ref_type_name /* as defined in IEC 61131-3 v3 */ ; single_element_type_name: @@ -2550,6 +2564,7 @@ simple_type_declaration | subrange_type_declaration | enumerated_type_declaration +| ref_type_decl /* defined in IEC 61131-3 v3 */ ; simple_type_declaration: @@ -3155,6 +3170,57 @@ ; +/* Taken fron IEC 61131-3 v3 + * // Table 14 - Reference operations + * Ref_Type_Decl : Ref_Type_Name ':' Ref_Spec_Init ; + * Ref_Spec_Init : Ref_Spec ( ':=' Ref_Value )? ; + * Ref_Spec : 'REF_TO' Non_Gen_Type_Name ; + * Ref_Type_Name : Identifier ; + * Ref_Name : Identifier ; + * Ref_Value : Ref_Addr | 'NULL' ; + * Ref_Addr : 'REF' '(' (Symbolic_Variable | FB_Name | Class_Instance_Name ) ')' ; + * Ref_Assign : Ref_Name ':=' (Ref_Name | Ref_Deref | Ref_Value ) ; + * Ref_Deref : 'DREF' '(' Ref_Name ')' ; + */ + +/* NOTE: in IEC 61131-3 v3, the formal syntax definition does not define non_generic_type_name to include FB type names. + * However, in section "6.3.4.10 References", example 4 includes a REF_TO a FB type! + * We have therefore explicitly added the "REF_TO function_block_type_name" to this rule! + */ +ref_spec: /* defined in IEC 61131-3 v3 */ + REF_TO non_generic_type_name + {$$ = new ref_spec_c($2, locloc(@$));} +| REF_TO function_block_type_name + {$$ = new ref_spec_c($2, locloc(@$));} +/* The following line is actually not included in IEC 61131-3, but we add it anyway otherwise it will not be possible to + * define a REF_TO datatype as an alias to an already previously declared REF_TO datatype. + * For example: + * TYPE + * ref1: REF_TO INT; + * ref2: ref1; <-- without the following rule, this would not be allowed!! + * END_TYPE + * + * This extra rule also makes it possible to declare variables using a previously declared REF_TO datatype + * For example: + * VAR refvar: ref1; END_VAR + */ +| prev_declared_ref_type_name +; + + +ref_spec_init: /* defined in IEC 61131-3 v3 */ + ref_spec /* For the moment, we do not support initialising reference data types */ +; + +ref_type_decl: /* defined in IEC 61131-3 v3 */ + identifier ':' ref_spec_init + {$$ = new ref_type_decl_c($1, $3, locloc(@$)); + library_element_symtable.insert($1, prev_declared_ref_type_name_token); + } +; + + + /*********************/ /* B 1.4 - Variables */ @@ -3497,6 +3563,8 @@ {$$ = new var1_init_decl_c($1, $3, locloc(@$));} | var1_list ':' enumerated_spec_init {$$ = new var1_init_decl_c($1, $3, locloc(@$));} +| var1_list ':' ref_spec_init /* defined in IEC 61131-3 v3 (REF_TO ...)*/ + {$$ = new var1_init_decl_c($1, $3, locloc(@$));} /* ERROR_CHECK_BEGIN */ | var1_list simple_spec_init {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and simple specification."); yynerrs++;} @@ -3816,6 +3884,8 @@ {$$ = new var1_init_decl_c($1, $3, locloc(@$));} | var1_list ':' enumerated_specification {$$ = new var1_init_decl_c($1, $3, locloc(@$));} +| var1_list ':' ref_spec /* defined in IEC 61131-3 v3 (REF_TO ...)*/ + {$$ = new var1_init_decl_c($1, $3, locloc(@$));} /* ERROR_CHECK_BEGIN */ | var1_list simple_specification {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between variable list and simple specification."); yynerrs++;} @@ -4045,6 +4115,10 @@ {$$ = new external_declaration_c($1, new fb_spec_init_c($3, NULL, locloc(@3)), locloc(@$)); 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(@$)); + variable_name_symtable.insert($1, prev_declared_fb_name_token); + } /* ERROR_CHECK_BEGIN */ | global_var_name simple_specification {$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing between external variable name and simple specification."); yynerrs++;} @@ -4173,6 +4247,7 @@ | initialized_structure | single_byte_string_spec | double_byte_string_spec +| ref_spec_init /* defined in IEC 61131-3 v3 (REF_TO ...) */ ; @@ -7057,6 +7132,7 @@ /***********************/ expression: xor_expression +| ref_expression /* an extension to the IEC 61131-3 v2 standard, based on the IEC 61131-3 v3 standard */ | expression OR xor_expression {$$ = new or_expression_c($1, $3, locloc(@$));} /* ERROR_CHECK_BEGIN */ @@ -7069,6 +7145,14 @@ /* ERROR_CHECK_END */ ; +/* REF(var_name) */ +/* This is an extension to the IEC 61131-3 standard. It is actually defined in the IEC 61131-3 v3 standard */ +/* The REF() operator returns the adrress of the variable. Basically, it returns a pointer to the variable */ +ref_expression: + REF '(' symbolic_variable ')' + {$$ = new ref_expression_c($3, locloc(@$));} +; + xor_expression: and_expression | xor_expression XOR and_expression diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage1_2/iec_flex.ll --- a/stage1_2/iec_flex.ll Fri Feb 28 11:27:53 2014 +0100 +++ b/stage1_2/iec_flex.ll Thu Mar 20 10:29:39 2014 +0100 @@ -179,17 +179,6 @@ } -/* A counter to track the order by which each token is processed. - * NOTE: This counter is not exactly linear (i.e., it does not get incremented by 1 for each token). - * i.e.. it may get incremented by more than one between two consecutive tokens. - * This is due to the fact that the counter gets incremented every 'user action' in flex, - * however not every user action will result in a token being passed to bison. - * Nevertheless this is still OK, as we are only interested in the relative - * ordering of tokens... - */ -static long int current_order = 0; - - /* Macro that is executed for every action. * We use it to pass the location of the token * back to the bison parser... @@ -207,6 +196,8 @@ current_order++; \ } + + /* Since this lexical parser we defined only works in ASCII based * systems, we might as well make sure it is being compiled on * one... @@ -510,8 +501,17 @@ %{ -#define MAX_INCLUDE_DEPTH 16 - + +/* A counter to track the order by which each token is processed. + * NOTE: This counter is not exactly linear (i.e., it does not get incremented by 1 for each token). + * i.e.. it may get incremented by more than one between two consecutive tokens. + * This is due to the fact that the counter gets incremented every 'user action' in flex, + * however not every user action will result in a token being passed to bison. + * Nevertheless this is still OK, as we are only interested in the relative + * ordering of tokens... + */ +static long int current_order = 0; + typedef struct { int eof; int lineNumber; @@ -522,6 +522,12 @@ FILE *in_file; } tracking_t; +/* A forward declaration of a function defined at the end of this file. */ +void FreeTracking(tracking_t *tracking); + + +#define MAX_INCLUDE_DEPTH 16 + typedef struct { YY_BUFFER_STATE buffer_state; tracking_t *env; @@ -984,7 +990,7 @@ */ if (include_stack_ptr == 0) { // fclose(yyin); // Must not do this!! - // free(current_tracking); // Must not do this!! + // FreeTracking(current_tracking); // Must not do this!! /* yyterminate() terminates the scanner and returns a 0 to the * scanner's caller, indicating "all done". * @@ -996,7 +1002,7 @@ yyterminate(); } else { fclose(yyin); - free(current_tracking); + FreeTracking(current_tracking); --include_stack_ptr; yy_delete_buffer(YY_CURRENT_BUFFER); yy_switch_to_buffer((include_stack[include_stack_ptr]).buffer_state); @@ -1245,6 +1251,9 @@ /******************************************************/ +REF {if (get_opt_ref_operator()) return REF; else unput(0);} /* Keyword in IEC 61131-3 v3 */ +REF_TO {/*if (get_opt_ref_operator()) return REF_TO; else */unput(0);} /* Keyword in IEC 61131-3 v3 */ + EN return EN; /* Keyword */ ENO return ENO; /* Keyword */ @@ -1771,7 +1780,7 @@ /* Tracking Functions... */ /*************************/ -#define MAX_BUFFER_LENGTH 1000 +#define MAX_LINE_LENGTH 1024 tracking_t *GetNewTracking(FILE* in_file) { tracking_t* new_env = new tracking_t; @@ -1780,12 +1789,18 @@ new_env->currentChar = 0; new_env->lineLength = 0; new_env->currentTokenStart = 0; - new_env->buffer = (char*)malloc(MAX_BUFFER_LENGTH); + new_env->buffer = (char*)malloc(MAX_LINE_LENGTH); new_env->in_file = in_file; return new_env; } +void FreeTracking(tracking_t *tracking) { + free(tracking->buffer); + delete tracking; +} + + /* GetNextChar: reads a character from input */ int GetNextChar(char *b, int maxBuffer) { char *p; @@ -1798,7 +1813,7 @@ current_tracking->currentTokenStart = 1; current_tracking->eof = false; - p = fgets(current_tracking->buffer, MAX_BUFFER_LENGTH, current_tracking->in_file); + p = fgets(current_tracking->buffer, MAX_LINE_LENGTH, current_tracking->in_file); if ( p == NULL ) { if ( ferror(current_tracking->in_file) ) return 0; @@ -1806,8 +1821,12 @@ return 0; } - current_tracking->lineNumber++; current_tracking->lineLength = strlen(current_tracking->buffer); + + /* only increment line number if the buffer was big enough to read the whole line! */ + char last_char = current_tracking->buffer[current_tracking->lineLength - 1]; + if (('\n' == last_char) || ('\r' == last_char)) // '\r' ---> CR, '\n' ---> LF + current_tracking->lineNumber++; } b[0] = current_tracking->buffer[current_tracking->currentChar]; @@ -1917,12 +1936,13 @@ * We therefore determine how many newlines are in the text we are returning, * and decrement the line counter acordingly... */ - /*unsigned int i; + /* + unsigned int i; for (i = n; i < strlen(yytext); i++) if (yytext[i] == '\n') - current_tracking->lineNumber--;*/ - + current_tracking->lineNumber--; + */ /* now return all the text back to the input stream... */ yyless(n); } diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage1_2/stage1_2.cc --- a/stage1_2/stage1_2.cc Fri Feb 28 11:27:53 2014 +0100 +++ b/stage1_2/stage1_2.cc Thu Mar 20 10:29:39 2014 +0100 @@ -69,6 +69,13 @@ bool nested_comments_ = false; bool get_opt_nested_comments() {return nested_comments_;} +/************************************/ +/* whether to allow REF() operator */ +/************************************/ +bool ref_operator_ = false; +bool get_opt_ref_operator() {return ref_operator_;} + + /******************************************************/ /* whether we are supporting conversion functions */ /* for enumerate data types */ @@ -248,6 +255,7 @@ */ nested_comments_ = options.nested_comments; + ref_operator_ = options.ref_operator; safe_extensions_ = options.safe_extensions; conversion_functions_ = options.conversion_functions; return stage2__(filename, options.includedir, tree_root_ref, options.full_token_loc); diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage1_2/stage1_2.hh --- a/stage1_2/stage1_2.hh Fri Feb 28 11:27:53 2014 +0100 +++ b/stage1_2/stage1_2.hh Thu Mar 20 10:29:39 2014 +0100 @@ -60,6 +60,7 @@ bool full_token_loc; /* error messages specify full token location */ bool conversion_functions; /* Create a conversion function for derived datatype */ bool nested_comments; /* Allow the use of nested comments. */ + bool ref_operator; /* Allow the use of REF() operator. */ const char *includedir; /* Include directory, where included files will be searched for... */ } stage1_2_options_t; diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage1_2/stage1_2_priv.hh --- a/stage1_2/stage1_2_priv.hh Fri Feb 28 11:27:53 2014 +0100 +++ b/stage1_2/stage1_2_priv.hh Thu Mar 20 10:29:39 2014 +0100 @@ -93,6 +93,12 @@ /************************************/ bool get_opt_nested_comments(); +/************************************/ +/* whether to allow REF() operator */ +/************************************/ +bool get_opt_ref_operator(); + + /*************************************************************/ /*************************************************************/ diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage3/fill_candidate_datatypes.cc --- a/stage3/fill_candidate_datatypes.cc Fri Feb 28 11:27:53 2014 +0100 +++ b/stage3/fill_candidate_datatypes.cc Thu Mar 20 10:29:39 2014 +0100 @@ -1832,6 +1832,15 @@ /***********************/ /* B 3.1 - Expressions */ /***********************/ +/* SYM_REF1(ref_expression_c, exp) --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */ +void *fill_candidate_datatypes_c::visit( ref_expression_c *symbol) { + symbol->exp->accept(*this); + /* we should really check whether the expression is merely a variable. For now, leave it for the future! */ + /* For now, we handle references (i.e. pointers) as ULINT datatypes! */ + add_datatype_to_candidate_list(symbol, &get_datatype_info_c::ulint_type_name); + return NULL; +} + void *fill_candidate_datatypes_c::visit( or_expression_c *symbol) {return handle_binary_expression (widen_OR_table, symbol, symbol->l_exp, symbol->r_exp);} void *fill_candidate_datatypes_c::visit( xor_expression_c *symbol) {return handle_binary_expression (widen_XOR_table, symbol, symbol->l_exp, symbol->r_exp);} void *fill_candidate_datatypes_c::visit( and_expression_c *symbol) {return handle_binary_expression (widen_AND_table, symbol, symbol->l_exp, symbol->r_exp);} diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage3/fill_candidate_datatypes.hh --- a/stage3/fill_candidate_datatypes.hh Fri Feb 28 11:27:53 2014 +0100 +++ b/stage3/fill_candidate_datatypes.hh Thu Mar 20 10:29:39 2014 +0100 @@ -327,6 +327,7 @@ /***********************/ /* B 3.1 - Expressions */ /***********************/ + void *visit(ref_expression_c *symbol); void *visit(or_expression_c *symbol); void *visit(xor_expression_c *symbol); void *visit(and_expression_c *symbol); diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage3/narrow_candidate_datatypes.cc --- a/stage3/narrow_candidate_datatypes.cc Fri Feb 28 11:27:53 2014 +0100 +++ b/stage3/narrow_candidate_datatypes.cc Thu Mar 20 10:29:39 2014 +0100 @@ -1337,6 +1337,17 @@ /***********************/ /* B 3.1 - Expressions */ /***********************/ +/* SYM_REF1(ref_expression_c, exp) --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */ +void *narrow_candidate_datatypes_c::visit( ref_expression_c *symbol) { + if (symbol->exp->candidate_datatypes.size() > 0) { + symbol->exp->datatype = symbol->exp->candidate_datatypes[0]; /* just use the first possible datatype */ + symbol->exp->accept(*this); + } + return NULL; +} + + + /* allow_enums is FALSE by default!! * deprecated_operation is NULL by default!! * if (allow_enums) then consider that we are ectually processing an equ_expression or notequ_expression, where two enums of the same data type may also be legally compared diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage3/narrow_candidate_datatypes.hh --- a/stage3/narrow_candidate_datatypes.hh Fri Feb 28 11:27:53 2014 +0100 +++ b/stage3/narrow_candidate_datatypes.hh Thu Mar 20 10:29:39 2014 +0100 @@ -303,6 +303,7 @@ /***********************/ /* B 3.1 - Expressions */ /***********************/ + void *visit(ref_expression_c *symbol); void *visit(or_expression_c *symbol); void *visit(xor_expression_c *symbol); void *visit(and_expression_c *symbol); diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage3/print_datatypes_error.cc --- a/stage3/print_datatypes_error.cc Fri Feb 28 11:27:53 2014 +0100 +++ b/stage3/print_datatypes_error.cc Thu Mar 20 10:29:39 2014 +0100 @@ -1032,6 +1032,15 @@ /***********************/ /* B 3.1 - Expressions */ /***********************/ +/* SYM_REF1(ref_expression_c, exp) --> an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */ +void *print_datatypes_error_c::visit( ref_expression_c *symbol) { + symbol->exp->accept(*this); + /* we should really check whether the expression is merely a variable. For now, leave it for the future! */ + if ((symbol->candidate_datatypes.size() == 0) && (symbol->exp->candidate_datatypes.size() > 0)) + STAGE3_ERROR(0, symbol, symbol, "REF operator must be used with a variable."); + return NULL; +} + void *print_datatypes_error_c::print_binary_expression_errors(const char *operation, symbol_c *symbol, symbol_c *l_expr, symbol_c *r_expr, bool deprecated_operation) { l_expr->accept(*this); diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage3/print_datatypes_error.hh --- a/stage3/print_datatypes_error.hh Fri Feb 28 11:27:53 2014 +0100 +++ b/stage3/print_datatypes_error.hh Thu Mar 20 10:29:39 2014 +0100 @@ -283,6 +283,7 @@ /***********************/ /* B 3.1 - Expressions */ /***********************/ + void *visit(ref_expression_c *symbol); void *visit(or_expression_c *symbol); void *visit(xor_expression_c *symbol); void *visit(and_expression_c *symbol); diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage4/generate_c/generate_c.cc --- a/stage4/generate_c/generate_c.cc Fri Feb 28 11:27:53 2014 +0100 +++ b/stage4/generate_c/generate_c.cc Thu Mar 20 10:29:39 2014 +0100 @@ -132,6 +132,12 @@ #define GET_EXTERNAL "__GET_EXTERNAL" #define GET_EXTERNAL_FB "__GET_EXTERNAL_FB" #define GET_LOCATED "__GET_LOCATED" + +#define GET_VAR_REF "__GET_VAR_REF" +#define GET_EXTERNAL_REF "__GET_EXTERNAL_REF" +#define GET_EXTERNAL_FB_REF "__GET_EXTERNAL_FB_REF" +#define GET_LOCATED_REF "__GET_LOCATED_REF" + #define GET_VAR_BY_REF "__GET_VAR_BY_REF" #define GET_EXTERNAL_BY_REF "__GET_EXTERNAL_BY_REF" #define GET_EXTERNAL_FB_BY_REF "__GET_EXTERNAL_FB_BY_REF" @@ -164,6 +170,41 @@ /***********************************************************************/ /***********************************************************************/ +/* Parse command line options passed from main.c !! */ +#include // for getsybopt() + +static int generate_line_directives__ = 0; + +int stage4_parse_options(char *options) { + enum { LINE_OPT = 0 /*, SOME_OTHER_OPT, YET_ANOTHER_OPT */}; + char *const token[] = { /*[LINE_OPT]=*/(char *)"l" /*, SOME_OTHER_OPT, ... */, NULL }; + /* unfortunately, the above commented out syntax for array initialization is valid in C, but not in C++ */ + + char *subopts = options; + char *value; + int opt; + + while (*subopts != '\0') { + switch (getsubopt(&subopts, token, &value)) { + case LINE_OPT: generate_line_directives__ = 1; break; + default : fprintf(stderr, "Unrecognized option: -O %s\n", value); return -1; break; + } + } + return 0; +} + + +void stage4_print_options(void) { + printf(" (options must be separated by commas. Example: 'l,w,x')\n"); + printf(" l : insert '#line' directives in generated C code.\n"); +} + + +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ + #include "generate_c_base.cc" #include "generate_c_typedecl.cc" #include "generate_c_sfcdecl.cc" @@ -351,7 +392,7 @@ static bool is_complex_type(symbol_c *symbol) { if (NULL == symbol) ERROR; - if (!get_datatype_info_c::is_type_valid (symbol->datatype)) 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) ); diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage4/generate_c/generate_c_base.cc --- a/stage4/generate_c/generate_c_base.cc Fri Feb 28 11:27:53 2014 +0100 +++ b/stage4/generate_c/generate_c_base.cc Thu Mar 20 10:29:39 2014 +0100 @@ -90,6 +90,15 @@ s4o.print(variable_prefix_); } + void print_line_directive(symbol_c *symbol) { + if (!generate_line_directives__) return; /* global variable generate_line_directives__ is defined in generate_c.cc */ + s4o.print("#line "); + s4o.print(symbol->first_line); + s4o.print(" \""); + s4o.print(symbol->first_file); + s4o.print("\"\n"); + } + void *print_token(token_c *token, int offset = 0) { return s4o.printupper((token->value)+offset); } diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage4/generate_c/generate_c_il.cc --- a/stage4/generate_c/generate_c_il.cc Fri Feb 28 11:27:53 2014 +0100 +++ b/stage4/generate_c/generate_c_il.cc Thu Mar 20 10:29:39 2014 +0100 @@ -704,12 +704,13 @@ /* Declare the backup to the IL implicit variable, that will store the result of the IL operations executed inside a parenthesis... */ declare_implicit_variable_back(); - /* - s4o.print(s4o.indent_spaces); - this->implicit_variable_result_back.accept(*this); - s4o.print(".INTvar = 0;\n\n"); - */ - print_list(symbol, s4o.indent_spaces, ";\n" + s4o.indent_spaces, ";\n"); + + for(int i = 0; i < symbol->n; i++) { + print_line_directive(symbol->elements[i]); + s4o.print(s4o.indent_spaces); + symbol->elements[i]->accept(*this); + s4o.print(";\n"); + } return NULL; } diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage4/generate_c/generate_c_inlinefcall.cc --- a/stage4/generate_c/generate_c_inlinefcall.cc Fri Feb 28 11:27:53 2014 +0100 +++ b/stage4/generate_c/generate_c_inlinefcall.cc Thu Mar 20 10:29:39 2014 +0100 @@ -416,6 +416,11 @@ return NULL; } + /* il_jump_operator label */ + // SYM_REF2(il_jump_operation_c, il_jump_operator, label) + void *visit(il_jump_operation_c *symbol) { + return NULL; + } void *visit(il_function_call_c *symbol) { symbol_c* function_type_prefix = NULL; diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage4/generate_c/generate_c_st.cc --- a/stage4/generate_c/generate_c_st.cc Fri Feb 28 11:27:53 2014 +0100 +++ b/stage4/generate_c/generate_c_st.cc Thu Mar 20 10:29:39 2014 +0100 @@ -456,6 +456,47 @@ /***********************/ /* B 3.1 - Expressions */ /***********************/ +void *visit(ref_expression_c *symbol) { + s4o.print("((IEC_UDINT)"); + 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... */ + 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; + if ( get_datatype_info_c::is_function_block(symbol->exp->datatype)) + s4o.print(GET_EXTERNAL_FB_REF); + else + s4o.print(GET_EXTERNAL_REF); + } + else if (vartype == search_var_instance_decl_c::located_vt) + s4o.print(GET_LOCATED_REF); + else + s4o.print(GET_VAR_REF); + + variablegeneration_t old_wanted_variablegeneration = wanted_variablegeneration; + s4o.print("("); + wanted_variablegeneration = complextype_base_vg; + symbol->exp->accept(*this); + s4o.print(","); + wanted_variablegeneration = complextype_suffix_vg; + symbol->exp->accept(*this); + s4o.print(")"); + wanted_variablegeneration = old_wanted_variablegeneration; + + s4o.print(")"); + } + s4o.print(")"); + + return NULL; +} + + void *visit(or_expression_c *symbol) { if (get_datatype_info_c::is_BOOL_compatible(symbol->datatype)) return print_binary_expression(symbol->l_exp, symbol->r_exp, " || "); @@ -833,7 +874,13 @@ /* B 3.2 Statements */ /********************/ void *visit(statement_list_c *symbol) { - return print_list(symbol, s4o.indent_spaces, ";\n" + s4o.indent_spaces, ";\n"); + for(int i = 0; i < symbol->n; i++) { + print_line_directive(symbol->elements[i]); + s4o.print(s4o.indent_spaces); + symbol->elements[i]->accept(*this); + s4o.print(";\n"); + } + return NULL; } /*********************************/ diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage4/generate_iec/generate_iec.cc --- a/stage4/generate_iec/generate_iec.cc Fri Feb 28 11:27:53 2014 +0100 +++ b/stage4/generate_iec/generate_iec.cc Thu Mar 20 10:29:39 2014 +0100 @@ -61,8 +61,23 @@ - - +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ + +/* Parse command line options passed from main.c !! */ + +int stage4_parse_options(char *options) {return 0;} + +void stage4_print_options(void) { + printf(" (no options available when generating IEC 61131-3 code)\n"); +} + +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ +/***********************************************************************/ //class generate_iec_c: public iterator_visitor_c { @@ -646,6 +661,35 @@ +/* ref_spec: REF_TO (non_generic_type_name | function_block_type_name) */ +// SYM_REF1(ref_spec_c, type_name) +void *visit(ref_spec_c *symbol) { + s4o.print("REF_TO "); + symbol->type_name->accept(*this); + return NULL; +} + + +/* For the moment, we do not support initialising reference data types */ +/* ref_spec_init: ref_spec; */ +/* SYM_REF0(ref_spec_init_c) */ + +/* ref_type_decl: identifier ':' ref_spec_init */ +// SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init) +void *visit(ref_type_decl_c *symbol) { + symbol->ref_type_name->accept(*this); + s4o.print(" : "); + symbol->ref_spec_init->accept(*this); + return NULL; +} + + + + + + + + /*********************/ /* B 1.4 - Variables */ /*********************/ @@ -1856,6 +1900,7 @@ /***********************/ /* B 3.1 - Expressions */ /***********************/ +void *visit(ref_expression_c *symbol) {return s4o.print("REF("); symbol->exp->accept(*this); s4o.print(")");} /* an extension to the IEC 61131-3 standard - based on the IEC 61131-3 v3 standard. Returns address of the varible! */ void *visit(or_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " OR ");} void *visit(xor_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " XOR ");} void *visit(and_expression_c *symbol) {return print_binary_expression(symbol, symbol->l_exp, symbol->r_exp, " AND ");} diff -r 878e9bf4c6ec -r e05d69c1ccb3 stage4/stage4.hh --- a/stage4/stage4.hh Fri Feb 28 11:27:53 2014 +0100 +++ b/stage4/stage4.hh Thu Mar 20 10:29:39 2014 +0100 @@ -104,4 +104,8 @@ int stage4(symbol_c *tree_root, const char *builddir); +/* Functions to be implemented by each generate_XX version of stage 4 */ +int stage4_parse_options(char *options); +void stage4_print_options(void); + #endif /* _STAGE4_HH */