--- a/stage4/generate_c/generate_c.cc Tue Aug 29 12:02:09 2017 +0100
+++ b/stage4/generate_c/generate_c.cc Wed Aug 30 21:57:18 2017 +0100
@@ -178,6 +178,7 @@
static int generate_line_directives__ = 0;
static int generate_pou_filepairs__ = 0;
+static int generate_plc_state_backup_fuctions__ = 1;
#ifdef __unix__
/* Parse command line options passed from main.c !! */
@@ -1572,6 +1573,7 @@
};
+
/***********************************************************************/
/***********************************************************************/
/***********************************************************************/
@@ -2108,6 +2110,261 @@
/***********************************************************************/
/***********************************************************************/
+/*******************************************************/
+/* Classes to generate the backup/restore functions... */
+/*******************************************************/
+
+#define RESTORE_ "_restore__"
+#define BACKUP_ "_backup__"
+
+/* class to generate the forward declaration of the XXXX_backup() and XXXX_restore()
+ * functions that will later (in the generated C source code) be defined
+ * to backup/restore the global state of each RESOURCE in the source code being compiled.
+ * The XXXX is actually the resource name!
+ */
+class generate_c_backup_resource_decl_c: public generate_c_base_and_typeid_c {
+ public:
+ generate_c_backup_resource_decl_c(stage4out_c *s4o_ptr)
+ : generate_c_base_and_typeid_c(s4o_ptr) {};
+
+ void *visit(resource_declaration_c *symbol) {
+ s4o.print(s4o.indent_spaces);
+ s4o.print("void ");
+ symbol->resource_name->accept(*this);
+ s4o.print("_backup__" "(void **buffer, int *maxsize);\n");
+ s4o.print(s4o.indent_spaces);
+ s4o.print("void ");
+ symbol->resource_name->accept(*this);
+ s4o.print("_restore__" "(void **buffer, int *maxsize);\n");
+ return NULL;
+ }
+};
+
+
+/* print out the begining of the generic backup/restore function */
+void print_backup_restore_function_beg(stage4out_c &s4o, const char *func_name, const char *operation) {
+ /* operation will be either "_backup__" or "_restore__" */
+ s4o.print("\n");
+ s4o.print("void ");
+ s4o.print(func_name);
+ s4o.print(operation);
+ s4o.print("(void **buffer, int *maxsize) {\n");
+ s4o.indent_right();
+ // Don't save/restore the __CURRENT_TIME variable, as 'plc controller' has easy access to it
+ // and can therefore do the save/restore by itself.
+//s4o.print(s4o.indent_spaces);
+//s4o.print(operation);
+//s4o.print("(&__CURRENT_TIME, sizeof(__CURRENT_TIME), buffer, maxsize);\n");
+ s4o.print(s4o.indent_spaces);
+ s4o.print("#define " DECLARE_GLOBAL "(vartype, domain, varname) \\\n ");
+ s4o.print(operation);
+ s4o.print("(&domain##__##varname, sizeof(domain##__##varname), buffer, maxsize);\n");
+ s4o.print(s4o.indent_spaces);
+ s4o.print("#define " DECLARE_GLOBAL_FB "(vartype, domain, varname) \\\n ");
+ s4o.print(operation);
+ s4o.print("(&domain##__##varname, sizeof(domain##__##varname), buffer, maxsize);\n");
+ s4o.print(s4o.indent_spaces);
+ s4o.print("#define " DECLARE_GLOBAL_LOCATION "(vartype, location) \\\n ");
+ s4o.print(operation);
+ s4o.print("(location, sizeof(*location), buffer, maxsize);\n");
+ s4o.print(s4o.indent_spaces);
+ s4o.print("#define " DECLARE_GLOBAL_LOCATED "(vartype, domain, varname) \\\n ");
+ s4o.print(operation);
+ s4o.print("(&domain##__##varname, sizeof(domain##__##varname), buffer, maxsize);\n");
+}
+
+/* print out the ending of the generic backup/restore function */
+void print_backup_restore_function_end(stage4out_c &s4o) {
+ s4o.print(s4o.indent_spaces); s4o.print("#undef " DECLARE_GLOBAL "\n");
+ s4o.print(s4o.indent_spaces); s4o.print("#undef " DECLARE_GLOBAL_FB "\n");
+ s4o.print(s4o.indent_spaces); s4o.print("#undef " DECLARE_GLOBAL_LOCATION "\n");
+ s4o.print(s4o.indent_spaces); s4o.print("#undef " DECLARE_GLOBAL_LOCATED "\n");
+ s4o.indent_left();
+ s4o.print("}\n");
+}
+
+
+/* generate the backup/restore function for a CONFIGURATION */
+/* the generated function will backup/restore the global variables declared in the
+ * configuration, and call the backup/restore functions of each embedded resource to do
+ * the same for the global variables declared inside each resource.
+ */
+class generate_c_backup_config_c: public generate_c_base_and_typeid_c {
+ private:
+ const char *func_to_call = NULL; // will later be set to either "_backup__" or "_restore__"
+
+ public:
+ generate_c_backup_config_c(stage4out_c *s4o_ptr)
+ : generate_c_base_and_typeid_c(s4o_ptr) {
+ };
+
+ virtual ~generate_c_backup_config_c(void) {}
+
+
+ public:
+ /********************/
+ /* 2.1.6 - Pragmas */
+ /********************/
+ void *visit(enable_code_generation_pragma_c * symbol) {s4o.enable_output(); return NULL;}
+ void *visit(disable_code_generation_pragma_c * symbol) {s4o.disable_output();return NULL;}
+
+
+ /********************************/
+ /* B 1.7 Configuration elements */
+ /********************************/
+ /*
+ SYM_REF6(configuration_declaration_c, configuration_name, global_var_declarations, resource_declarations, access_declarations, instance_specific_initializations, unused)
+ */
+ void *visit(configuration_declaration_c *symbol) {
+
+ s4o.print("\n\n\n");
+
+ s4o.print("void ");
+ s4o.print("_backup__");
+ s4o.print("(void *varptr, int varsize, void **buffer, int *maxsize) {\n");
+ s4o.print(" if (varsize <= *maxsize) {memmove(*buffer, varptr, varsize); *buffer += varsize;}\n");
+ s4o.print(" *maxsize -= varsize;\n");
+ s4o.print("}\n");
+
+ s4o.print("void ");
+ s4o.print("_restore__");
+ s4o.print("(void *varptr, int varsize, void **buffer, int *maxsize) {\n");
+ s4o.print(" if (varsize <= *maxsize) {memmove(varptr, *buffer, varsize); *buffer += varsize;}\n");
+ s4o.print(" *maxsize -= varsize;\n");
+ s4o.print("}\n");
+
+
+ generate_c_vardecl_c vardecl = generate_c_vardecl_c(&s4o,
+ generate_c_vardecl_c::local_vf,
+ generate_c_vardecl_c::global_vt,
+ symbol->configuration_name);
+
+ s4o.print("\n\n\n");
+ s4o.print("#undef " DECLARE_GLOBAL "\n");
+ s4o.print("#undef " DECLARE_GLOBAL_FB "\n");
+ s4o.print("#undef " DECLARE_GLOBAL_LOCATION "\n");
+ s4o.print("#undef " DECLARE_GLOBAL_LOCATED "\n");
+
+ generate_c_backup_resource_decl_c declare_functions = generate_c_backup_resource_decl_c(&s4o);
+ symbol->resource_declarations->accept(declare_functions);
+
+ print_backup_restore_function_beg(s4o, "config", "_backup__");
+ vardecl.print(symbol);
+ s4o.print("\n");
+ func_to_call = "_backup__";
+ symbol->resource_declarations->accept(*this);
+ func_to_call = NULL;
+ print_backup_restore_function_end(s4o);
+
+ print_backup_restore_function_beg(s4o, "config", "_restore__");
+ vardecl.print(symbol);
+ s4o.print("\n");
+ func_to_call = "_restore__";
+ symbol->resource_declarations->accept(*this);
+ func_to_call = NULL;
+ print_backup_restore_function_end(s4o);
+
+ return NULL;
+ }
+
+ void *visit(resource_declaration_c *symbol) {
+ if (symbol->global_var_declarations == NULL)
+ return NULL;
+ s4o.print(s4o.indent_spaces);
+ symbol->resource_name->accept(*this);
+ s4o.print(func_to_call);
+ s4o.print("(buffer, maxsize);\n");
+ return NULL;
+ }
+
+ void *visit(single_resource_declaration_c *symbol) {
+ /* A single resource never has global variables declared, so nothing to do! */
+ return NULL;
+ }
+
+};
+
+
+
+/* generate the backup/restore function for a RESOURCE */
+/* the backup/restore function generated here will be called by the backup/restore
+ * function generated for the configuration in which the resource is embedded
+ */
+class generate_c_backup_resource_c: public generate_c_base_and_typeid_c {
+ public:
+ generate_c_backup_resource_c(stage4out_c *s4o_ptr)
+ : generate_c_base_and_typeid_c(s4o_ptr) {
+ };
+
+ virtual ~generate_c_backup_resource_c(void) {}
+
+
+ public:
+ /********************/
+ /* 2.1.6 - Pragmas */
+ /********************/
+ void *visit(enable_code_generation_pragma_c * symbol) {s4o.enable_output(); return NULL;}
+ void *visit(disable_code_generation_pragma_c * symbol) {s4o.disable_output();return NULL;}
+
+
+ /********************************/
+ /* B 1.7 Configuration elements */
+ /********************************/
+ void *visit(resource_declaration_c *symbol) {
+ if (symbol->global_var_declarations == NULL)
+ return NULL;
+
+ char *resource_name = strdup(symbol->resource_name->token->value);
+ /* convert to upper case */
+ for (char *c = resource_name; *c != '\0'; *c = toupper(*c), c++);
+
+ generate_c_vardecl_c vardecl = generate_c_vardecl_c(&s4o,
+ generate_c_vardecl_c::local_vf,
+ generate_c_vardecl_c::global_vt,
+ symbol->resource_name);
+ s4o.print("\n\n\n");
+
+ s4o.print("void ");
+ s4o.print("_backup__");
+ s4o.print("(void *varptr, int varsize, void **buffer, int *maxsize);\n");
+ s4o.print("void ");
+ s4o.print("_restore__");
+ s4o.print("(void *varptr, int varsize, void **buffer, int *maxsize);\n");
+
+ s4o.print("\n\n\n");
+ s4o.print("#undef " DECLARE_GLOBAL "\n");
+ s4o.print("#undef " DECLARE_GLOBAL_FB "\n");
+ s4o.print("#undef " DECLARE_GLOBAL_LOCATION "\n");
+ s4o.print("#undef " DECLARE_GLOBAL_LOCATED "\n");
+
+ print_backup_restore_function_beg(s4o, resource_name, "_backup__");
+ vardecl.print(symbol->global_var_declarations);
+ print_backup_restore_function_end(s4o);
+
+ print_backup_restore_function_beg(s4o, resource_name, "_restore__");
+ vardecl.print(symbol->global_var_declarations);
+ print_backup_restore_function_end(s4o);
+
+ return NULL;
+ }
+
+ void *visit(single_resource_declaration_c *symbol) {
+ /* A single resource never has global variables declared, so nothing to do! */
+ return NULL;
+ }
+
+};
+
+
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+/***********************************************************************/
+
class generate_c_c: public iterator_visitor_c {
protected:
stage4out_c &s4o;
@@ -2329,6 +2586,11 @@
config_s4o.print("unsigned long greatest_tick_count__ = (unsigned long)");
config_s4o.print_long_integer(calculate_common_ticktime.get_greatest_tick_count());
config_s4o.print("; /*tick*/\n");
+
+ if (generate_plc_state_backup_fuctions__ > 0) {
+ generate_c_backup_config_c generate_backup = generate_c_backup_config_c(&config_s4o);
+ symbol->accept(generate_backup);
+ }
}
symbol->resource_declarations->accept(*this);
@@ -2344,6 +2606,10 @@
stage4out_c resources_s4o(current_builddir, current_name, "c");
generate_c_resources_c generate_c_resources(&resources_s4o, current_configuration, symbol, common_ticktime);
symbol->accept(generate_c_resources);
+ if (generate_plc_state_backup_fuctions__ > 0) {
+ generate_c_backup_resource_c generate_backup = generate_c_backup_resource_c(&resources_s4o);
+ symbol->accept(generate_backup);
+ }
return NULL;
}