merge
authorEdouard Tisserant
Thu, 20 Mar 2014 10:29:39 +0100
changeset 881 e05d69c1ccb3
parent 880 599e88d12f9a (diff)
parent 871 878e9bf4c6ec (current diff)
child 882 18a39a545ed9
merge
lib/accessor.h
stage1_2/iec_bison.yy
stage1_2/iec_flex.ll
stage1_2/stage1_2.cc
stage1_2/stage1_2_priv.hh
--- 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/
--- 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)
--- 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
--- 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 <include_directory>] [-T <target_directory>] <input_file>\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 [<options>] [-O <output_options>] [-I <include_directory>] [-T <target_directory>] <input_file>\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;
--- 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  <ID>	prev_declared_array_type_name_token
 %token  <ID>	prev_declared_structure_type_name_token
 %token  <ID>	prev_declared_string_type_name_token
+%token  <ID>	prev_declared_ref_type_name_token  /* defined in IEC 61131-3 v3 */
 
 %type  <leaf>	prev_declared_simple_type_name
 %type  <leaf>	prev_declared_subrange_type_name
@@ -363,6 +364,7 @@
 %type  <leaf>	prev_declared_array_type_name
 %type  <leaf>	prev_declared_structure_type_name
 %type  <leaf>	prev_declared_string_type_name
+%type  <leaf>	prev_declared_ref_type_name  /* defined in IEC 61131-3 v3 */
 
 %token <ID>	prev_declared_derived_function_name_token
 %token <ID>	prev_declared_derived_function_block_name_token
@@ -412,6 +414,9 @@
 %type <leaf>	en_identifier
 %type <leaf>	eno_identifier
 
+/* Keyword in IEC 61131-3 v3 */
+%token	REF
+%token	REF_TO
 
 
 
@@ -759,6 +764,11 @@
 %token END_STRUCT
 
 
+%type  <leaf>	ref_spec      /* defined in IEC 61131-3 v3 */
+%type  <leaf>	ref_spec_init /* defined in IEC 61131-3 v3 */
+%type  <leaf>	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  <leaf>	ref_expression  /* an extension to the IEC 61131-3 v2 standard, based on the IEC 61131-3 v3 standard */ 
 %type  <leaf>	expression
 %type  <leaf>	xor_expression
 %type  <leaf>	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
--- 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);
 }
--- 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);
--- 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;
 
--- 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();
+
+
 
 /*************************************************************/
 /*************************************************************/
--- 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);}
--- 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);
--- 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 
--- 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);
--- 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);
--- 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);
--- 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 <stdlib.h> // 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) 
              );
--- 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);
     }
--- 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;
 }
 
--- 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;
--- 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;
 }
 
 /*********************************/
--- 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 ");}
--- 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 */