--- a/absyntax/absyntax.def Tue Nov 20 21:06:55 2012 +0100
+++ b/absyntax/absyntax.def Thu Nov 22 19:26:56 2012 +0000
@@ -114,7 +114,8 @@
/***************************/
/* B 0 - Programming Model */
/***************************/
-SYM_LIST(library_c)
+/* 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_LIST(library_c, enumvalue_symtable_t enumvalue_symtable;)
/*************************/
@@ -701,7 +702,8 @@
/***********************/
/* B 1.5.1 - Functions */
/***********************/
-SYM_REF4(function_declaration_c, derived_function_name, type_name, var_declarations_list, function_body)
+/* 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(function_declaration_c, derived_function_name, type_name, var_declarations_list, function_body, enumvalue_symtable_t enumvalue_symtable;)
/* intermediate helper symbol for
* - function_declaration
@@ -721,7 +723,8 @@
/* 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)
+/* 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_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body, enumvalue_symtable_t enumvalue_symtable;)
/* intermediate helper symbol for function_declaration */
/* { io_var_declarations | other_var_declarations } */
@@ -743,7 +746,8 @@
/* B 1.5.3 - Programs */
/**********************/
/* 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)
+/* 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_REF3(program_declaration_c, program_type_name, var_declarations, function_block_body, enumvalue_symtable_t enumvalue_symtable;)
/* intermediate helper symbol for program_declaration_c */
/* { io_var_declarations | other_var_declarations } */
@@ -826,7 +830,8 @@
optional_instance_specific_initializations
END_CONFIGURATION
*/
-SYM_REF5(configuration_declaration_c, configuration_name, global_var_declarations, resource_declarations, access_declarations, instance_specific_initializations)
+/* 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_REF5(configuration_declaration_c, configuration_name, global_var_declarations, resource_declarations, access_declarations, instance_specific_initializations, enumvalue_symtable_t enumvalue_symtable;)
/* helper symbol for configuration_declaration */
SYM_LIST(resource_declaration_list_c)
@@ -837,7 +842,8 @@
single_resource_declaration
END_RESOURCE
*/
-SYM_REF4(resource_declaration_c, resource_name, resource_type_name, global_var_declarations, resource_declaration)
+/* 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;)
/* task_configuration_list program_configuration_list */
SYM_REF2(single_resource_declaration_c, task_configuration_list, program_configuration_list)
--- a/absyntax/absyntax.hh Tue Nov 20 21:06:55 2012 +0100
+++ b/absyntax/absyntax.hh Thu Nov 22 19:26:56 2012 +0000
@@ -48,6 +48,7 @@
#include <stdio.h> // required for NULL
#include <vector>
+#include <map>
#include <string>
#include <stdint.h> // required for uint64_t, etc...
#include "../main.hh" // required for uint8_t, real_64_t, ..., and the macros INT8_MAX, REAL32_MAX, ... */
@@ -72,6 +73,28 @@
+/* Case insensitive string compare */
+ /* Case insensitive string compare copied from
+ * "The C++ Programming Language" - 3rd Edition
+ * by Bjarne Stroustrup, ISBN 0201889544.
+ */
+class nocasecmp_c {
+ public:
+ bool operator() (const std::string& x, const std::string& y) const {
+ std::string::const_iterator ix = x.begin();
+ std::string::const_iterator iy = y.begin();
+
+ for(; (ix != x.end()) && (iy != y.end()) && (toupper(*ix) == toupper(*iy)); ++ix, ++iy);
+ if (ix == x.end()) return (iy != y.end());
+ if (iy == y.end()) return false;
+ return (toupper(*ix) < toupper(*iy));
+ };
+ };
+
+
+
+
+
@@ -99,7 +122,7 @@
/*
* Annotations produced during stage 3
- */
+ */
/*** Data type analysis ***/
std::vector <symbol_c *> candidate_datatypes; /* All possible data types the expression/literal/etc. may take. Filled in stage3 by fill_candidate_datatypes_c class */
/* Data type of the expression/literal/etc. Filled in stage3 by narrow_candidate_datatypes_c
@@ -138,6 +161,12 @@
} const_value_t;
const_value_t const_value;
+ /*** Enumeration datatype checking ***/
+ /* Not all symbols will contain the following anotations, which is why they are not declared here in symbol_c
+ * They will be declared only inside the symbols that require them (have a look at absyntax.def)
+ */
+ typedef std::multimap<std::string, symbol_c *, nocasecmp_c> enumvalue_symtable_t;
+
public:
/* default constructor */
@@ -153,6 +182,8 @@
};
+
+
class token_c: public symbol_c {
public:
/* WARNING: only use this method for debugging purposes!! */
@@ -169,6 +200,8 @@
};
+
+
/* a list of symbols... */
class list_c: public symbol_c {
public:
@@ -200,6 +233,11 @@
+
+
+
+
+
#define SYM_LIST(class_name_c, ...) \
class class_name_c: public list_c { \
public: \
--- a/absyntax/visitor.cc Tue Nov 20 21:06:55 2012 +0100
+++ b/absyntax/visitor.cc Thu Nov 22 19:26:56 2012 +0000
@@ -70,7 +70,7 @@
null_visitor_c::~null_visitor_c(void) {return;}
-#define SYM_LIST(class_name_c) \
+#define SYM_LIST(class_name_c, ...) \
void *null_visitor_c::visit(class_name_c *symbol) {return NULL;}
#define SYM_TOKEN(class_name_c, ...) \
@@ -174,7 +174,7 @@
}
-#define SYM_LIST(class_name_c) \
+#define SYM_LIST(class_name_c, ...) \
void *iterator_visitor_c::visit(class_name_c *symbol) {return visit_list(symbol);}
#define SYM_TOKEN(class_name_c, ...) \
@@ -318,7 +318,7 @@
}
-#define SYM_LIST(class_name_c) \
+#define SYM_LIST(class_name_c, ...) \
void *search_visitor_c::visit(class_name_c *symbol) {return visit_list(symbol);}
#define SYM_TOKEN(class_name_c, ...) \
--- a/absyntax_utils/debug_ast.cc Tue Nov 20 21:06:55 2012 +0100
+++ b/absyntax_utils/debug_ast.cc Thu Nov 22 19:26:56 2012 +0000
@@ -100,8 +100,9 @@
fprintf(stderr, " datatype=");
if (NULL == symbol->datatype)
fprintf(stderr, "NULL\t\t");
- else
- fprintf(stderr, symbol->datatype->absyntax_cname());
+ else {
+ fprintf(stderr, "%s", symbol->datatype->absyntax_cname());
+ }
fprintf(stderr, "\t<-{");
if (symbol->candidate_datatypes.size() == 0) {
fprintf(stderr, "\t\t\t\t\t");
@@ -112,12 +113,12 @@
else
fprintf(stderr, "\t\t\t");
} else {
- fprintf(stderr, "(%d)\t\t\t\t\t", symbol->candidate_datatypes.size());
+ fprintf(stderr, "(%lu)\t\t\t\t\t", (unsigned long int)symbol->candidate_datatypes.size());
}
fprintf(stderr, "}\t");
/* print the const values... */
- fprintf(stderr, " constv{f=%f, i=%lld, u=%llu, b=%d}\t", symbol->const_value._real64.value, symbol->const_value._int64.value, symbol->const_value._uint64.value, symbol->const_value._bool.value);
+ fprintf(stderr, " constv{f=%f, i=%"PRId64", u=%"PRIu64", b=%d}\t", symbol->const_value._real64.value, symbol->const_value._int64.value, symbol->const_value._uint64.value, symbol->const_value._bool.value?1:0);
}
@@ -126,8 +127,9 @@
void *print_symbol_c::visit(il_instruction_c *symbol) {
dump_symbol(symbol);
- fprintf(stderr, " next_il_=%d ", symbol->next_il_instruction.size());
- fprintf(stderr, " prev_il_=%d ", symbol->prev_il_instruction.size());
+ /* NOTE: std::map.size() returns a size_type, whose type is dependent on compiler/platform. To be portable, we need to do an explicit type cast. */
+ fprintf(stderr, " next_il_=%lu ", (unsigned long int)symbol->next_il_instruction.size());
+ fprintf(stderr, " prev_il_=%lu ", (unsigned long int)symbol->prev_il_instruction.size());
if (symbol->prev_il_instruction.size() == 0)
fprintf(stderr, "(----,");
--- a/lib/iec_std_lib.h Tue Nov 20 21:06:55 2012 +0100
+++ b/lib/iec_std_lib.h Thu Nov 22 19:26:56 2012 +0000
@@ -26,6 +26,10 @@
* $gcc -E iec_std_lib.h
*/
+#ifndef _IEC_STD_LIB_H
+#define _IEC_STD_LIB_H
+
+
#include <limits.h>
#include <float.h>
#include <math.h>
@@ -2157,3 +2161,5 @@
/********************************************/
/* Do we support this? */
+
+#endif /* _IEC_STD_LIB_H */
--- a/lib/iec_types.h Tue Nov 20 21:06:55 2012 +0100
+++ b/lib/iec_types.h Thu Nov 22 19:26:56 2012 +0000
@@ -32,7 +32,7 @@
typedef struct {
long int tv_sec; /* Seconds. */
long int tv_nsec; /* Nanoseconds. */
-}__attribute__((packed)) IEC_TIMESPEC;
+} /* __attribute__((packed)) */ IEC_TIMESPEC; /* packed is gcc specific! */
typedef IEC_TIMESPEC IEC_TIME;
typedef IEC_TIMESPEC IEC_DATE;
@@ -51,6 +51,6 @@
typedef struct {
__strlen_t len;
uint8_t body[STR_MAX_LEN];
-} __attribute__((packed)) IEC_STRING;
+} /* __attribute__((packed)) */ IEC_STRING; /* packed is gcc specific! */
#endif /*IEC_TYPES_H*/
--- a/lib/iec_types_all.h Tue Nov 20 21:06:55 2012 +0100
+++ b/lib/iec_types_all.h Thu Nov 22 19:26:56 2012 +0000
@@ -62,8 +62,10 @@
/* Include non windows.h clashing typedefs */
#include "iec_types.h"
-#define TRUE 1
-#define FALSE 0
+#ifndef TRUE
+ #define TRUE 1
+ #define FALSE 0
+#endif
#define __IEC_DEBUG_FLAG 0x01
#define __IEC_FORCE_FLAG 0x02
--- a/stage1_2/iec_flex.ll Tue Nov 20 21:06:55 2012 +0100
+++ b/stage1_2/iec_flex.ll Thu Nov 22 19:26:56 2012 +0000
@@ -416,7 +416,7 @@
/* we are parsing a function, program or function block declaration */
%s decl_state
-/* we will be parsing a function body. Whether il/st is remains unknown */
+/* we will be parsing a function body. Whether il/st/sfc remains to be determined */
%x body_state
/* we are parsing il code -> flex must return the EOL tokens! */
@@ -924,8 +924,7 @@
* calling yyterminate() is equivalent to doing that.
*/
yyterminate();
- }
- else {
+ } else {
--include_stack_ptr;
yy_delete_buffer(YY_CURRENT_BUFFER);
yy_switch_to_buffer((include_stack[include_stack_ptr]).buffer_state);
@@ -1735,12 +1734,10 @@
* return 0;
*/
- /* to we stop processing...
- *
+ /* to stop processing...
* return 1;
*/
-
return 1; /* Stop scanning at end of input file. */
}
--- a/stage3/Makefile.am Tue Nov 20 21:06:55 2012 +0100
+++ b/stage3/Makefile.am Thu Nov 22 19:26:56 2012 +0000
@@ -13,5 +13,6 @@
lvalue_check.cc \
array_range_check.cc \
constant_folding.cc \
- declaration_check.cc
+ declaration_check.cc \
+ enum_declaration_check.cc
--- a/stage3/Makefile.in Tue Nov 20 21:06:55 2012 +0100
+++ b/stage3/Makefile.in Thu Nov 22 19:26:56 2012 +0000
@@ -83,7 +83,8 @@
forced_narrow_candidate_datatypes.$(OBJEXT) \
print_datatypes_error.$(OBJEXT) datatype_functions.$(OBJEXT) \
lvalue_check.$(OBJEXT) array_range_check.$(OBJEXT) \
- constant_folding.$(OBJEXT) declaration_check.$(OBJEXT)
+ constant_folding.$(OBJEXT) declaration_check.$(OBJEXT) \
+ enum_declaration_check.$(OBJEXT)
libstage3_a_OBJECTS = $(am_libstage3_a_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/config
depcomp = $(SHELL) $(top_srcdir)/config/depcomp
@@ -209,7 +210,8 @@
lvalue_check.cc \
array_range_check.cc \
constant_folding.cc \
- declaration_check.cc
+ declaration_check.cc \
+ enum_declaration_check.cc
all: all-am
@@ -291,6 +293,7 @@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/constant_folding.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/datatype_functions.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/declaration_check.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/enum_declaration_check.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fill_candidate_datatypes.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flow_control_analysis.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/forced_narrow_candidate_datatypes.Po@am__quote@
--- a/stage3/constant_folding.cc Tue Nov 20 21:06:55 2012 +0100
+++ b/stage3/constant_folding.cc Thu Nov 22 19:26:56 2012 +0000
@@ -253,7 +253,7 @@
int64_t ret;
std::string str = "";
char *endptr;
- const char *value;
+ const char *value = NULL;
int base;
integer_c *integer;
hex_integer_c *hex_integer;
@@ -285,7 +285,7 @@
uint64_t ret;
std::string str = "";
char *endptr;
- const char *value;
+ const char *value = NULL;
int base;
integer_c *integer;
hex_integer_c *hex_integer;
--- a/stage3/fill_candidate_datatypes.cc Tue Nov 20 21:06:55 2012 +0100
+++ b/stage3/fill_candidate_datatypes.cc Thu Nov 22 19:26:56 2012 +0000
@@ -75,29 +75,6 @@
-#define FIRST_(symbol1, symbol2) (((symbol1)->first_order < (symbol2)->first_order) ? (symbol1) : (symbol2))
-#define LAST_(symbol1, symbol2) (((symbol1)->last_order > (symbol2)->last_order) ? (symbol1) : (symbol2))
-
-
-#define STAGE3_ERROR(error_level, symbol1, symbol2, ...) { \
- fprintf(stderr, "%s:%d-%d..%d-%d: error: ", \
- FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column,\
- LAST_(symbol1,symbol2) ->last_line, LAST_(symbol1,symbol2) ->last_column);\
- fprintf(stderr, __VA_ARGS__); \
- fprintf(stderr, "\n"); \
-}
-
-
-#define STAGE3_WARNING(symbol1, symbol2, ...) { \
- fprintf(stderr, "%s:%d-%d..%d-%d: warning: ", \
- FIRST_(symbol1,symbol2)->first_file, FIRST_(symbol1,symbol2)->first_line, FIRST_(symbol1,symbol2)->first_column,\
- LAST_(symbol1,symbol2) ->last_line, LAST_(symbol1,symbol2) ->last_column);\
- fprintf(stderr, __VA_ARGS__); \
- fprintf(stderr, "\n"); \
-}
-
-
-
/* set to 1 to see debug info during execution */
static int debug = 0;
@@ -161,7 +138,6 @@
for (; lower != upper; lower++)
if (lower->second == current_enumerated_type) {
/* The same identifier is used more than once as an enumerated value/constant inside the same enumerated datat type! */
- STAGE3_ERROR(0, symbol, symbol, "Duplicate identifier in enumerated data type.");
return NULL; /* No need to insert it! It is already in the table! */
}
@@ -229,13 +205,13 @@
static enumerated_value_symtable_t local_enumerated_value_symtable;
-class populate_enumvalue_symtable_c: public iterator_visitor_c {
+class populate_localenumvalue_symtable_c: public iterator_visitor_c {
private:
symbol_c *current_enumerated_type;
public:
- populate_enumvalue_symtable_c(void) {current_enumerated_type = NULL;};
- ~populate_enumvalue_symtable_c(void) {}
+ populate_localenumvalue_symtable_c(void) {current_enumerated_type = NULL;};
+ ~populate_localenumvalue_symtable_c(void) {}
public:
/*************************/
@@ -271,7 +247,6 @@
for (; lower != upper; lower++)
if (lower->second == current_enumerated_type) {
/* The same identifier is used more than once as an enumerated value/constant inside the same enumerated datat type! */
- STAGE3_ERROR(0, symbol, symbol, "Duplicate identifier in enumerated data type.");
return NULL; /* No need to insert it! It is already in the table! */
}
@@ -281,7 +256,7 @@
}
}; // class populate_enumvalue_symtable_c
-static populate_enumvalue_symtable_c populate_enumvalue_symtable;
+static populate_localenumvalue_symtable_c populate_enumvalue_symtable;
@@ -935,7 +910,7 @@
void *fill_candidate_datatypes_c::visit(enumerated_value_c *symbol) {
symbol_c *global_enumerated_type;
symbol_c *local_enumerated_type;
- symbol_c *enumerated_type;
+ symbol_c *enumerated_type = NULL;
if (NULL != symbol->type) {
/* NOTE: This code must take into account the following situation:
--- a/stage3/stage3.cc Tue Nov 20 21:06:55 2012 +0100
+++ b/stage3/stage3.cc Thu Nov 22 19:26:56 2012 +0000
@@ -43,6 +43,15 @@
#include "array_range_check.hh"
#include "constant_folding.hh"
#include "declaration_check.hh"
+#include "enum_declaration_check.hh"
+
+
+static int enum_declaration_check(symbol_c *tree_root){
+ enum_declaration_check_c enum_declaration_check(NULL);
+ tree_root->accept(enum_declaration_check);
+ return enum_declaration_check.get_error_count();
+}
+
static int declaration_safety(symbol_c *tree_root){
declaration_check_c declaration_check(tree_root);
@@ -107,6 +116,7 @@
int stage3(symbol_c *tree_root){
int error_count = 0;
+ error_count += enum_declaration_check(tree_root);
error_count += declaration_safety(tree_root);
error_count += flow_control_analysis(tree_root);
error_count += constant_folding(tree_root);