diff --git a/GlueGenerator.py b/GlueGenerator.py index fedcf6f9e..7096319f3 100644 --- a/GlueGenerator.py +++ b/GlueGenerator.py @@ -80,10 +80,10 @@ def __parse_line(self, line): return { "type": varType, "name": varName, - "glue_code": self.__glue_logic(varName), + # "glue_code": self.__glue_logic(varName), } - def generate_glue_variables(self, located_vars_lines): + def generate_glue_variables(self, located_vars_lines, template_file): """ Generate glue variables from the LOCATED_VARIABLES content. """ @@ -93,6 +93,11 @@ def generate_glue_variables(self, located_vars_lines): if entry is not None: parsed.append(entry) - env = Environment(loader=self.__loader) - template = env.get_template("glueVars.c.j2") + if template_file: + abs_template_file = os.path.abspath(template_file) + env = Environment(loader=FileSystemLoader(os.path.dirname(abs_template_file))) + template = env.get_template(os.path.basename(template_file)) + else: + env = Environment(loader=self.__loader) + template = env.get_template("glueVars.c.j2") return template.render(vars=parsed) diff --git a/PatchFiles.py b/PatchFiles.py new file mode 100644 index 000000000..d6dbb3022 --- /dev/null +++ b/PatchFiles.py @@ -0,0 +1,77 @@ +import os +import re +def PatchFiles(source_dir): + PatchLoacatedBit(source_dir) + PatchConfigHeader(source_dir) + + +def PatchLoacatedBit(source_dir): + file_path = os.path.join(source_dir, 'POUS.c') + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + # 正则替换 __INIT_LOCATED(BOOL,__IX..,...) 为 __INIT_LOCATED_BOOL(BOOL,__IX..,bit,...) + def replacer(match): + ix = match.group(1) + bit = match.group(2) + var = match.group(3) + var2 = match.group(4) + return f'__INIT_LOCATED_BOOL(BOOL, {ix}, {int(bit)+1}, {var}, {var2})' + # replacer = r'__INIT_LOCATED_BOOL(BOOL, \1, \2, \3, \4)' + pattern = r'__INIT_LOCATED\(\s*BOOL,\s*(__\wX\d+_(\d+)),\s*([^,]+),\s*(\w+)\)' + new_content = re.sub(pattern, replacer, content) + # print(new_content) + with open(file_path, 'w', encoding='utf-8') as f: + f.write(new_content) + +def PatchConfigHeader(source_dir): + file_path = os.path.join(source_dir, 'Config0.h') + with open(file_path, 'w', encoding='utf-8') as f: + f.write(config_header) + +config_header=r''' + +#ifndef __CONFIG_0_H +#define __CONFIG_0_H + +#define __INIT_LOCATED_BOOL(type, location, bit, name, retained) \ + { \ + extern type *location; \ + name.value = location; \ + name.flags = (bit << 4); \ + __INIT_RETAIN(name, retained) \ + } + +#undef __INIT_LOCATED_VALUE +// not init bool located value to false automatically +#define __INIT_LOCATED_VALUE(name, initial) _Generic(name.value, \ + BOOL *: ((initial && (name.flags & 0xf0)) && (*(name.value) |= (1 << ((name.flags >> 4) - 1)))), \ + default: *(name.value) = initial); + +#undef __GET_LOCATED +// #define __GET_LOCATED(name, ...) _Generic((name.value), \ +// BOOL *: (name.flags & __IEC_FORCE_FLAG) ? name.fvalue __VA_ARGS__ : ((name.flags & 0xf0) ? ((*(name.value))__VA_ARGS__) >> ((name.flags >> 4) - 1) & 1 : (*(name.value))__VA_ARGS__), \ +// default: ((name.flags & __IEC_FORCE_FLAG) ? name.fvalue __VA_ARGS__ : (*(name.value))__VA_ARGS__)) + +#define __GET_LOCATED(name, ...) _Generic((name.value), \ + BOOL *: ((name.flags & __IEC_FORCE_FLAG) ? name.fvalue __VA_ARGS__ : ((name.flags & 0xf0) ? ((*(name.value))__VA_ARGS__) >> ((name.flags >> 4) - 1) & 1 : (*(name.value))__VA_ARGS__)), \ + default: ((name.flags & __IEC_FORCE_FLAG) ? name.fvalue __VA_ARGS__ : (*(name.value))__VA_ARGS__)) + +#undef __SET_LOCATED +#define __SET_LOCATED(prefix, name, suffix, new_value) \ + if (!(prefix name.flags & __IEC_FORCE_FLAG)) \ + { \ + if (prefix name.flags & 0xf0) \ + { \ + *(prefix name.value)suffix = (*(prefix name.value)suffix & ~(1 << ((prefix name.flags >> 4) - 1))) | ((new_value & 1) << ((prefix name.flags >> 4) - 1)); \ + } \ + else \ + { \ + *(prefix name.value)suffix = new_value; \ + } \ + } + +#endif + + + +''' \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..02e8fc908 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +lxml +jinja2 \ No newline at end of file diff --git a/xml2st.py b/xml2st.py index 2fb0c6149..0299d4da1 100755 --- a/xml2st.py +++ b/xml2st.py @@ -8,7 +8,8 @@ from ProjectController import ProjectController from ComplexParser import ComplexParser from GlueGenerator import GlueGenerator -from SerialPortList import SerialPortList +#from SerialPortList import SerialPortList +from PatchFiles import PatchFiles def compile_xml_to_st(xml_file_path): @@ -84,7 +85,7 @@ def append_debugger_to_st(st_file, debug_text): f.write(c_debug) -def generate_gluevars(located_vars_file): +def generate_gluevars(located_vars_file, template_file, output): if not os.path.isfile(located_vars_file) or not located_vars_file.lower().endswith( ".h" ): @@ -100,14 +101,17 @@ def generate_gluevars(located_vars_file): # Create an instance of GlueGenerator generator = GlueGenerator() - glueVars = generator.generate_glue_variables(located_vars) + glueVars = generator.generate_glue_variables(located_vars, template_file) if glueVars is None: print("Error: Failed to generate glue variables.", file=sys.stderr) return None # Save the generated glue variables to a file - glue_vars_file = os.path.join(os.path.dirname(located_vars_file), "glueVars.c") + if output: + glue_vars_file = os.path.abspath(output) + else: + glue_vars_file = os.path.join(os.path.dirname(located_vars_file), "glueVars.c") with open(glue_vars_file, "w") as f: f.write(glueVars) @@ -138,6 +142,14 @@ def main(): parser.add_argument( "--list-ports", action="store_true", help="List all available serial ports" ) + parser.add_argument( + "--patch-files", + metavar=("SOURCE_DIR"), + type=str, + help="The path to the source directory containing files to patch", + ) + parser.add_argument("-o","--output", metavar=("OUTPUT_FILE"), type=str, help="The path to the output file") + parser.add_argument("-t","--template-file", metavar=("TEMPLATE_FILE"), type=str, help="The path to the template file for glue variables generation") args = parser.parse_args() @@ -150,8 +162,10 @@ def main(): raise Exception("Compilation failed, no program text generated.") print("Saving ST file...") - - st_file = os.path.abspath(args.generate_st).replace("plc.xml", "program.st") + if args.output: + st_file = os.path.abspath(args.output) + else: + st_file = os.path.abspath(args.generate_st).replace("plc.xml", "program.st") with open(st_file, "w") as file: file.write(program_text) @@ -177,18 +191,21 @@ def main(): sys.exit(1) elif args.generate_gluevars: - try: - print("Generating glue variables...") - generate_gluevars(args.generate_gluevars) + # try: + print("Generating glue variables...") + generate_gluevars(args.generate_gluevars, args.template_file, args.output) - except Exception as e: - print(f"Error generating glue variables: {e}", file=sys.stderr) - sys.exit(1) + # except Exception as e: + # print(f"Error generating glue variables: {e}", file=sys.stderr) + # sys.exit(1) + +# elif args.list_ports: +# port_list = SerialPortList() +# ports = port_list.get_ports() +# print(json.dumps(ports, indent=2)) - elif args.list_ports: - port_list = SerialPortList() - ports = port_list.get_ports() - print(json.dumps(ports, indent=2)) + elif args.patch_files: + PatchFiles(args.patch_files) else: print(