From 3322c4cddaf9a17bceb803749267b0be42b07e66 Mon Sep 17 00:00:00 2001 From: LuChiChick <1084116302@qq.com> Date: Fri, 4 Jul 2025 13:46:24 +0800 Subject: [PATCH] structure of typedef and constant of #define can be solve now. --- Inc/Config.hpp | 34 ++ Inc/Core_Functions.hpp | 22 + Inc/Global_Variables.hpp | 25 + Inc/Tool_Functions.hpp | 42 ++ Inc/Type_Descriptions.hpp | 91 ++++ Makefile | 157 ++++++ Src/Core_Functions.cpp | 1014 +++++++++++++++++++++++++++++++++++++ Src/Global_Variables.cpp | 21 + Src/Main.cpp | 37 ++ Src/Tool_Functions.cpp | 616 ++++++++++++++++++++++ main.cpp | 688 ------------------------- 11 files changed, 2059 insertions(+), 688 deletions(-) create mode 100644 Inc/Config.hpp create mode 100644 Inc/Core_Functions.hpp create mode 100644 Inc/Global_Variables.hpp create mode 100644 Inc/Tool_Functions.hpp create mode 100644 Inc/Type_Descriptions.hpp create mode 100644 Makefile create mode 100644 Src/Core_Functions.cpp create mode 100644 Src/Global_Variables.cpp create mode 100644 Src/Main.cpp create mode 100644 Src/Tool_Functions.cpp delete mode 100644 main.cpp diff --git a/Inc/Config.hpp b/Inc/Config.hpp new file mode 100644 index 0000000..05d5bdc --- /dev/null +++ b/Inc/Config.hpp @@ -0,0 +1,34 @@ +#ifndef __CONFIG_HPP__ +#define __CONFIG_HPP__ + +#define VARIABLE_NAME_LENGTH_MAX 100 +#define ELEMENT_NAME_LENGTH_MAX 100 +#define TYPE_NAME_LENGTH_MAX 100 + +#define A2L_TYPE_STR_LENGTH_MAX 100 +#define A2L_LIMIT_STR_LENGTH_MAX 100 + +#define SEGMENT_BUFF_LENGTH 5000 + +// 输出文件默认前缀 +#define OUTPUT_A2L_DEFAULT_PREFIX "[NEW]" +// 中间件尾缀 +#define OUTPUT_MIDDLEWARE_SUFFIX ".middleware.txt" + +// 相关识别串 +const char measurement_begin[] = "/*Start_Measurements*/"; +const char measurement_end[] = "/*End_Measurements*/"; +const char calibration_begin[] = "/*Start_Calibration*/"; +const char calibration_end[] = "/*End_Calibration*/"; +const char typedef_begin[] = "/*Start_TypeDef*/"; +const char typedef_end[] = "/*End_TypeDef*/"; + +const char a2l_module_end[] = "/end MODULE"; + +// 段输出标识串 +const char auto_generated_measurement_start[] = "\r\n/*********** Start of auto generated measurement blocks ***********/\r\n\r\n"; +const char auto_generated_measurement_end[] = "\r\n/*********** End of auto generated measurement blocks ***********/\r\n\r\n"; +const char auto_generated_calibration_start[] = "\r\n/*********** Start of auto generated calibration blocks ***********/\r\n\r\n"; +const char auto_generated_calibration_end[] = "\r\n/*********** End of auto generated calibration blocks ***********/\r\n\r\n"; + +#endif \ No newline at end of file diff --git a/Inc/Core_Functions.hpp b/Inc/Core_Functions.hpp new file mode 100644 index 0000000..505cb08 --- /dev/null +++ b/Inc/Core_Functions.hpp @@ -0,0 +1,22 @@ +#ifndef __CORE_FUNCTIONS_HPP__ +#define __CORE_FUNCTIONS_HPP__ + +#include "Global_Variables.hpp" +#include "Config.hpp" + +// 参数解析 +void solve_args(int argc, char *argv[]); + +// 解析宏定义 +void solve_defines(void); + +// 类型解析 +void solve_types(void); + +// 处理中间件 +void solve_middleware(void); + +// 处理最终A2L输出 +void solve_A2L_output(void); + +#endif \ No newline at end of file diff --git a/Inc/Global_Variables.hpp b/Inc/Global_Variables.hpp new file mode 100644 index 0000000..8823c38 --- /dev/null +++ b/Inc/Global_Variables.hpp @@ -0,0 +1,25 @@ +#ifndef __GLOBAL_VARIABLES_HPP__ +#define __GLOBAL_VARIABLES_HPP__ + +#include "Type_Descriptions.hpp" +extern "C" +{ +#include "stdio.h" +} + +// 类型列表 +extern type_node *type_list_head; + +// 宏定义列表 +extern define_node *define_list_head; + +// 源文件列表 +extern file_node *source_file_list_head; + +// 文件指针 +extern FILE *input_reference_A2L_file; +extern FILE *input_map_file; +extern FILE *output_target_A2L_file; +extern FILE *output_middleware_file; + +#endif \ No newline at end of file diff --git a/Inc/Tool_Functions.hpp b/Inc/Tool_Functions.hpp new file mode 100644 index 0000000..bcfc720 --- /dev/null +++ b/Inc/Tool_Functions.hpp @@ -0,0 +1,42 @@ +#ifndef __TOOL_FUNCTIONS_HPP__ +#define __TOOL_FUNCTIONS_HPP__ + +extern "C" +{ +#include "stdint.h" +#include "stdio.h" +} + +#include "Type_Descriptions.hpp" + +// 读取文件一行行 +error_type_enum f_getline(FILE *file, char *buffer, const size_t buffer_len, size_t *seek_len = nullptr); + +// 读取下一个有效词组 +error_type_enum f_getword(FILE *file, char *buffer, const size_t buffer_len, size_t *seek_len = nullptr); + +// 获取文件代码行(以;为分界的代码逻辑行,忽略中途的注释) +error_type_enum f_get_codeline(FILE *file, char *buffer, const size_t buffer_len, size_t *seek_len = nullptr); + +// 前进到下一行 +size_t f_seek_nextline(FILE *file); + +// 跳转到下一个非空字符 +size_t f_seek_skip_blank(FILE *file); + +// 基础变量类型解析 +variable_type_enum get_variable_base_type(const char *str); + +// 基础变量解析 +variable_info solve_base_variable(const char *str); + +// 解析变量类型 +variable_type_enum get_variable_type(const char *str); + +// 变量解析 +variable_info solve_variable(const char *str); + +// 日志输出 +void print_log(log_type_enum log_type, const char *p_format_str, ...); + +#endif \ No newline at end of file diff --git a/Inc/Type_Descriptions.hpp b/Inc/Type_Descriptions.hpp new file mode 100644 index 0000000..815d909 --- /dev/null +++ b/Inc/Type_Descriptions.hpp @@ -0,0 +1,91 @@ +#ifndef __TYPE_DESCRIPTIONS_HPP__ +#define __TYPE_DESCRIPTIONS_HPP__ + +extern "C" +{ +#include "stdint.h" +} + +#include "Config.hpp" + +// 宏定义链表 +typedef struct define_node_struct +{ + char define_str[VARIABLE_NAME_LENGTH_MAX] = {'\0'}; // define 名串 + char context_str[VARIABLE_NAME_LENGTH_MAX] = {'\0'}; // define 内容串 + define_node_struct *p_next = nullptr; +} define_node; + +// 文件链表 +typedef struct file_node_struct +{ + char *file_name_str = nullptr; + file_node_struct *p_next = nullptr; +} file_node; + +// 错误类型枚举 +typedef enum +{ + ERROR_NONE, // 无错误 + ERROR_OUT_OF_LENGTH, // 超出长度 + ERROR_ILLEGAL_POINTER, // 非法指针 + ERROR_ILLEGAL_WORD_SECTION, // 非法词段 + ERROR_END_OF_FILE, // 文件结尾 +} error_type_enum; + +// 变量类型枚举 +typedef enum +{ + TYPE_UNKNOWN, // 未知类型 + TYPE_NOT_SUPPORTED, // 不支持的类型 + STRUCTURE, // 结构体类型 + UBYTE, // uint8_t,bool + UWORD, // uint16_t + ULONG, // uint32_t + SBYTE, // int8_t + SWORD, // int16_t + SLONG, // int32_t + FLOAT32, // float + FLOAT64, // double +} variable_type_enum; + +// 变量信息结构体 +typedef struct +{ + char name_str[VARIABLE_NAME_LENGTH_MAX] = {'\0'}; // 变量名 + const char *type_name_str = nullptr; // 变量类型字符串 + size_t element_count = 0; // 子元素计数(仅数组>1,单个变量该值为1) + size_t single_element_size = 0; // 单个子元素大小(单位字节) + uint32_t start_addr_32 = 0x00000000; // 变量起始地址(32位地址,4字节) + variable_type_enum type = TYPE_NOT_SUPPORTED; // 变量类型 + char A2L_type_str[A2L_TYPE_STR_LENGTH_MAX] = {'\0'}; // 类型字符串 + char A2L_max_limit_str[A2L_LIMIT_STR_LENGTH_MAX] = {'\0'}; // 上限字符串 + char A2L_min_limit_str[A2L_LIMIT_STR_LENGTH_MAX] = {'\0'}; // 下限字符串 +} variable_info; + +// 元素信息记录链表 +typedef struct sub_element_node_struct +{ + variable_info element_info; // 元素信息 + struct sub_element_node_struct *p_next = nullptr; // 链表指针 +} sub_element_node; + +// 复合类型记录链表 +typedef struct type_node_struct +{ + char type_name_str[TYPE_NAME_LENGTH_MAX] = {'\0'}; // 类型名 + sub_element_node *element_list_head = nullptr; // 子成员链表 + variable_type_enum type = TYPE_UNKNOWN; // 类型标记 + struct type_node_struct *p_next = nullptr; // 链表指针 +} type_node; + +// 日志类型记录 +typedef enum +{ + LOG_NORMAL, // 常规类型 + LOG_SUCCESS, // 成功类型 + LOG_FAILURE, // 失败类型 + LOG_ERROR, // 错误类型 + LOG_WARN, // 警告类型 +} log_type_enum; +#endif \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7f673f0 --- /dev/null +++ b/Makefile @@ -0,0 +1,157 @@ +# 目标文件名称 +TARGET_FILE_NAME = SrcToA2L + +# 编译路径 +BUILD_DIR = Build + +# 工具链前缀 +PREFIX = \ + +# 调试选项 +DEBUG = 1 + +# GUI或CUI编译选项 +GUI = 0 + +# C编译标准,等号后面不能有空格 +C_STD =c17 + +# C++编译标准,等号后面不能有空格 +CXX_STD =c++17 + +#输入源文件字符编码定义,等号后不能有空格 +INPUT_CHAR_CODING =UTF-8 + +#输出单字节字符编码定义,等号后不能有空格 +OUTPUT_CHAR_CODING =GBK + +#输出宽字符编码定义,等号后不能有空格 +OUTPUT_WCHAR_CODING =UTF-16LE + +# 优化等级 +OPT = -Og + +# C编译工具 +CC = $(PREFIX)gcc + +# C++编译工具 +CXX = $(PREFIX)g++ + +# Win32 资源文件编译工具 +WIN32_RES = windres + +# 链接库 +LIB_LINK = \ + +# C定义 +C_DEFS = \ +-D_UNICODE \ +-DUNICODE + +# C头文件目录 +C_INCLUDES = \ + +# C源文件 +C_SOURCES = \ + +# C++定义 +CXX_DEFS = \ + +# C++ 头文件目录 +CXX_INCLUDES = \ +-IInc \ + +# C++源文件 +CXX_SOURCES = \ +Src/Main.cpp \ +Src/Tool_Functions.cpp \ +Src/Core_Functions.cpp \ +Src/Global_Variables.cpp \ + +# 资源文件 +WIN32_RES_LISTS = \ + +# C编译选项 +CFLAGS = $(C_DEFS) $(C_INCLUDES) $(OPT) -std=$(C_STD) \ + -finput-charset=$(INPUT_CHAR_CODING) \ + -fexec-charset=$(OUTPUT_CHAR_CODING) \ + -fwide-exec-charset=$(OUTPUT_WCHAR_CODING) \ + -static \ + -Wall \ + +# 生成依赖相关信息 +CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)" + +# 调试选项 +ifeq ($(DEBUG), 1) +CFLAGS += -g +endif + +# GUI与CUI选项 +ifeq ($(GUI), 1) +CFLAGS += -mwindows +else +CFLAGS += -mconsole +endif + +# C++编译选项 +CXXFLAGS = -lstdc++ $(CFLAGS:$(C_STD)=$(CXX_STD)) $(CXX_DEFS) $(CXX_INCLUDES) + +# C目标文件目录关联 +OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o))) +vpath %.c $(sort $(dir $(C_SOURCES))) + +# C++目标文件目录关联 +OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(CXX_SOURCES:.cpp=.o))) +vpath %.cpp $(sort $(dir $(CXX_SOURCES))) + +# 资源文件目录关联 +OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(WIN32_RES_LISTS:.rc=.o))) +vpath %.rc $(sort $(dir $(WIN32_RES_LISTS))) + +# Make编译任务 +all: $(BUILD_DIR)/$(TARGET_FILE_NAME).exe + +# C目标文件编译 +$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) + @echo ====== C Source File "$<" Compiling... ====== + $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@ + +# C++ 目标文件编译编译 +$(BUILD_DIR)/%.o: %.cpp Makefile | $(BUILD_DIR) + @echo ====== C++ Source File "$<" Compiling... ====== + $(CXX) -c $(CXXFLAGS) -Wa,-a,-ad,-ahlms=$(BUILD_DIR)/$(notdir $(<:.cpp=.lst)) $< -o $@ + +# 资源文件编译编译 +$(BUILD_DIR)/%.o: %.rc Makefile | $(BUILD_DIR) + @echo ====== Win32 Resources File "$<" Compiling... ====== + $(WIN32_RES) $< -o $@ + +# 生成可执行文件 +$(BUILD_DIR)/$(TARGET_FILE_NAME).exe: $(OBJECTS) Makefile + @echo ====== All File Compiled. Now Linking... ====== + $(CXX) $(CXXFLAGS) $(OBJECTS) $(LDFLAGS) -o $@ $(LIB_LINK) + @echo ====== Program Link Finished ====== + +# 生成编译目录 +$(BUILD_DIR): + mkdir $@ + +# 清除任务 +clean:$(BUILD_DIR) + powershell rm -r $(BUILD_DIR) + +# 运行任务 +run:all + $(BUILD_DIR)/$(TARGET_FILE_NAME).exe + +# 发行编译 +release:$(BUILD_DIR) $(RELEASE_DIR) + powershell rm -r $(BUILD_DIR) + make DEBUG=0 + powershell rm $(BUILD_DIR)/*.o + powershell rm $(BUILD_DIR)/*.d + powershell rm $(BUILD_DIR)/*.lst + +# 依赖关系 +-include $(wildcard $(BUILD_DIR)/*.d) \ No newline at end of file diff --git a/Src/Core_Functions.cpp b/Src/Core_Functions.cpp new file mode 100644 index 0000000..f41a73b --- /dev/null +++ b/Src/Core_Functions.cpp @@ -0,0 +1,1014 @@ +#include "Core_Functions.hpp" +#include "Tool_Functions.hpp" +#include "Config.hpp" + +extern "C" +{ +#include "stdio.h" +#include "string.h" +#include "stdlib.h" +} + +// 参数解析 +void solve_args(int argc, char *argv[]) +{ + // 处理输入部分 + { + const char *reference_A2L_name_str = nullptr; // 参考文件名 + const char *output_name = nullptr; // 输出文件名 + + // 循环处理指令 + for (int count = 1; count < argc; count++) + { + // 匹配到参考a2l文件 + if (!strcmp(argv[count], "-r")) + { + if (count + 1 >= argc) + { + print_log(LOG_FAILURE, "No reference .a2l file input.\n"); + break; + } + input_reference_A2L_file = fopen(argv[count + 1], "rb"); + if (input_reference_A2L_file == nullptr) + { + print_log(LOG_FAILURE, "Input reference .a2l file <%s> open failed.\n", argv[count + 1]); + break; + } + + // 获取参考文件文件名 + reference_A2L_name_str = argv[count + 1]; + + print_log(LOG_SUCCESS, "%-31s %s\n", "Input reference .a2l file:", argv[count + 1]); + count++; + continue; + } + + // 匹配到链接map文件 + else if (!strcmp(argv[count], "-l")) + { + if (count + 1 >= argc) + break; + input_map_file = fopen(argv[count + 1], "rb"); + if (input_map_file == nullptr) + { + print_log(LOG_FAILURE, "Input link file <%s> open failed.\n", argv[count + 1]); + break; + } + + print_log(LOG_SUCCESS, "%-31s %s\n", "Input link .map file:", argv[count + 1]); + count++; + continue; + } + + // 匹配到自定义输出文件名 + else if (!strcmp(argv[count], "-o")) + { + if (count + 1 >= argc) + break; + output_name = argv[count + 1]; + print_log(LOG_SUCCESS, "%-31s %s\n", "Set output filename:", argv[count + 1]); + count++; + continue; + } + + // 其它输入作为源文件输入 + print_log(LOG_SUCCESS, "%-31s %s\n", "Input source filename:", argv[count]); + + // 处理源文件链表 + { + static file_node *target_node = nullptr; + if (source_file_list_head == nullptr) + { + source_file_list_head = (file_node *)malloc(sizeof(file_node)); + source_file_list_head->file_name_str = nullptr; + source_file_list_head->p_next = nullptr; + target_node = source_file_list_head; + } + else + { + target_node->p_next = (file_node *)malloc(sizeof(file_node)); + target_node = target_node->p_next; + target_node->file_name_str = nullptr; + target_node->p_next = nullptr; + } + + // 记录文件名 + target_node->file_name_str = argv[count]; + } + } + + // 检查文件列表状态 + if (source_file_list_head == nullptr) + { + print_log(LOG_FAILURE, "No source file input.\n"); + free(source_file_list_head); + fcloseall(); + exit(0); + } + + // 检查参考文件输入文件状态 + if (input_reference_A2L_file == nullptr) + { + fcloseall(); + exit(0); + } + + // 处理输出文件名称 + if (output_name != nullptr) + { + output_target_A2L_file = fopen(output_name, "wb+"); + char *buff = (char *)malloc(strlen(output_name) + strlen(OUTPUT_MIDDLEWARE_SUFFIX) + 1); + sprintf(buff, "%s%s", output_name, OUTPUT_MIDDLEWARE_SUFFIX); + output_middleware_file = fopen(buff, "wb+"); + free(buff); + } + else if (reference_A2L_name_str != nullptr) + { + // 拼接默认的输出文件名 + const char *prefix = OUTPUT_A2L_DEFAULT_PREFIX; + char *buffer = (char *)malloc(strlen(reference_A2L_name_str) + strlen(prefix) + strlen(OUTPUT_MIDDLEWARE_SUFFIX) + 1); + + // 获取路径部分长度和不带路径的文件名起始位置 + int path_length = strlen(reference_A2L_name_str); + const char *file_name_no_dir = reference_A2L_name_str + path_length - 1; + + // 遍历指针没有回到起始位置且没有遇到正反斜杠 + while (file_name_no_dir + 1 != reference_A2L_name_str && *file_name_no_dir != '\\' && *file_name_no_dir != '/') + { + path_length--; + file_name_no_dir--; + } + file_name_no_dir++; + + // 开始拼接 + for (int count = 0; count < path_length; count++) + buffer[count] = reference_A2L_name_str[count]; + sprintf(buffer + path_length, "%s%s", prefix, file_name_no_dir); + + print_log(LOG_NORMAL, "%-31s %s\n", "Default output filename:", buffer); + + // 打开输出文件 + output_target_A2L_file = fopen(buffer, "wb+"); + + // 打开中间件文件 + sprintf(buffer + path_length + strlen(prefix) + strlen(file_name_no_dir), OUTPUT_MIDDLEWARE_SUFFIX); + output_middleware_file = fopen(buffer, "wb+"); + + // 释放临时指针 + free(buffer); + } + // 检查map链接文件文件状态 + if (input_map_file == nullptr) + print_log(LOG_WARN, "%-31s %s\n", "No link .map file input.", "Address will be set to 0x00000000"); + } +} + +// 解析宏定义 +void solve_defines(void) +{ + file_node *target_node = source_file_list_head; + + // 循环处理文件链表 + while (target_node != nullptr) + { + + FILE *target_file = nullptr; + target_file = fopen(target_node->file_name_str, "rb"); + // 处理无效的文件输入 + if (target_file == nullptr) + { + print_log(LOG_FAILURE, "Source file \"%s\" open failed.\n", target_node->file_name_str); + target_node = target_node->p_next; + continue; + } + + // 成功打开文件 + print_log(LOG_NORMAL, "%-31s %s\n\n", "Start define solving:", target_node->file_name_str); + + char segment_buff[SEGMENT_BUFF_LENGTH] = {'\0'}; + + // 循环按行解析 + while (true) + { + error_type_enum err = f_getline(target_file, segment_buff, sizeof(segment_buff)); + if (err != ERROR_NONE) + break; + + // 查找到define + if (strstr(segment_buff, "#define")) + { + printf("#define%s", segment_buff + strlen("#define")); + + // 分配节点空间 + static define_node *target_node; + if (define_list_head == nullptr) + { + define_list_head = (define_node *)malloc(sizeof(define_node)); + target_node = define_list_head; + memset(target_node->define_str, '\0', sizeof(target_node->define_str)); + memset(target_node->context_str, '\0', sizeof(target_node->context_str)); + target_node->p_next = nullptr; + } + else + { + target_node->p_next = (define_node *)malloc(sizeof(define_node)); + target_node = target_node->p_next; + memset(target_node->define_str, '\0', sizeof(target_node->define_str)); + memset(target_node->context_str, '\0', sizeof(target_node->context_str)); + target_node->p_next = nullptr; + } + + // 记录信息 + sscanf(segment_buff, "%*s%s%s", target_node->define_str, target_node->context_str); + } + } + + fclose(target_file); + target_node = target_node->p_next; + } +} + +// 类型解析 +void solve_types(void) +{ + file_node *target_node = source_file_list_head; + + // 循环处理文件链表 + while (target_node != nullptr) + { + + FILE *target_file = nullptr; + target_file = fopen(target_node->file_name_str, "rb"); + // 处理无效的文件输入 + if (target_file == nullptr) + { + print_log(LOG_FAILURE, "Source file \"%s\" open failed.\n", target_node->file_name_str); + target_node = target_node->p_next; + continue; + } + + // 成功打开文件 + print_log(LOG_NORMAL, "%-31s %s\n\n", "Start type solving:", target_node->file_name_str); + + char segment_buff[SEGMENT_BUFF_LENGTH] = {'\0'}; + + // 循环按行解析 + while (true) + { + error_type_enum err = f_getline(target_file, segment_buff, sizeof(segment_buff)); + if (err != ERROR_NONE) + break; + + // 检测到类型定义起始 + if (strstr(segment_buff, typedef_begin)) + { + + printf("\n%s\n\n", typedef_begin); + + // 循环处理 + while (true) + { + size_t seek_len = 0; + error_type_enum err = f_getline(target_file, segment_buff, sizeof(segment_buff), &seek_len); + if (err != ERROR_NONE) + break; + + // 类型定义结束行 + if (strstr(segment_buff, typedef_end)) + { + printf("\n%s\n\n", typedef_end); + break; + } + + // 检测到typedef + if (strstr(segment_buff, "typedef")) + { + static type_node *target_type_node; + + // 类型链表头为空时初始化类型链表头 + if (type_list_head == nullptr) + { + type_list_head = (type_node *)malloc(sizeof(type_node)); + type_list_head->element_list_head = nullptr; + type_list_head->p_next = nullptr; + memset(type_list_head->type_name_str, '\0', sizeof(type_list_head->type_name_str)); + target_type_node = type_list_head; + } + else + { + // 扩展到下一张链表 + type_node *temp_node = (type_node *)malloc(sizeof(type_node)); + target_type_node->p_next = temp_node; + target_type_node = temp_node; + } + + // 回退文件指针到typedef结尾 + fseek(target_file, -(seek_len - ((strstr(segment_buff, "typedef") - segment_buff) + strlen("typedef"))), SEEK_CUR); + + // 读取下一个有效词组 + f_getword(target_file, segment_buff, sizeof(segment_buff), &seek_len); + // 表示struct起始 + if (!strcmp(segment_buff, "struct")) + { + target_type_node->type = STRUCTURE; + // 直接结构体类型名 + if (f_getword(target_file, segment_buff, sizeof(segment_buff), &seek_len) == ERROR_NONE) + sprintf(target_type_node->type_name_str, segment_buff); + } + // 跳转到定义内 + while (fgetc(target_file) != '{') + ; + + // 新建第一个子元素节点 + sub_element_node *element_node = (sub_element_node *)malloc(sizeof(sub_element_node)); + element_node->p_next = nullptr; + target_type_node->element_list_head = element_node; + + // 复合类型解析 + while (true) + { + f_seek_skip_blank(target_file); + f_get_codeline(target_file, segment_buff, sizeof(segment_buff), &seek_len); + + // 解析成员类型 + element_node->element_info = solve_base_variable(segment_buff); + + /** + * @todo + * 去掉临时输出,改用制表符输出 + */ + if (element_node->element_info.element_count == 1) + printf(".%s\n", element_node->element_info.name_str); + else + printf(".%s[%d]\n", element_node->element_info.name_str, element_node->element_info.element_count); + + f_seek_skip_blank(target_file); + if (fgetc(target_file) == '}') + break; + else + { + fseek(target_file, -1, SEEK_CUR); + element_node->p_next = (sub_element_node *)malloc(sizeof(sub_element_node)); + element_node = element_node->p_next; + element_node->p_next = nullptr; + } + } + + // 处理类型别名(一个或多个) + while (true) + { + if (f_getword(target_file, segment_buff, sizeof(segment_buff), &seek_len) == ERROR_NONE) + { + // 当前还没有类型名 + if (target_type_node->type_name_str[0] == '\0') + { + sprintf(target_type_node->type_name_str, segment_buff); + } + else + { + target_type_node->p_next = (type_node *)malloc(sizeof(type_node)); + memset(target_type_node->p_next->type_name_str, '\0', sizeof(target_type_node->type_name_str)); + target_type_node->p_next->element_list_head = target_type_node->element_list_head; + target_type_node->p_next->type = target_type_node->type; + target_type_node->p_next->p_next = nullptr; + sprintf(target_type_node->p_next->type_name_str, segment_buff); + target_type_node = target_type_node->p_next; + } + } + f_seek_skip_blank(target_file); + if (fgetc(target_file) == ';') + break; + } + } + } + } + } + + fclose(target_file); + target_node = target_node->p_next; + } +} + +// 处理中间件 +void solve_middleware(void) +{ + file_node *target_node = source_file_list_head; + + // 循环处理输入文件链表 + while (target_node != nullptr) + { + FILE *target_file = nullptr; + target_file = fopen(target_node->file_name_str, "rb"); + if (target_file == nullptr) + { + print_log(LOG_FAILURE, "Source file \"%s\" load failed.\n", target_node->file_name_str); + target_node = target_node->p_next; + continue; + } + + print_log(LOG_NORMAL, "%-31s %s\n\n", "Start variable solving:", target_node->file_name_str); + char segment_buff[SEGMENT_BUFF_LENGTH] = {'\0'}; + + // 循环获取输入文件行 + while (f_getline(target_file, segment_buff, sizeof(segment_buff)) == ERROR_NONE) + { + // 当前行为观测量起始位行 + if (strstr(segment_buff, measurement_begin)) + { + printf("\n%s\n\n", measurement_begin); + fprintf(output_middleware_file, auto_generated_measurement_start); + + // 清空段缓冲区 + memset(segment_buff, '\0', sizeof(segment_buff)); + + while (true) + { + // 获取下一行 + size_t seek_len = 0; + f_getline(target_file, segment_buff, sizeof(segment_buff), &seek_len); + + // 观测量结束行 + if (strstr(segment_buff, measurement_end)) + { + printf("\n%s\n\n", measurement_end); + fprintf(output_middleware_file, auto_generated_measurement_end); + break; + } + // 非结束行,使用代码行进行处理,先回退,跳过空行后再重新读 + fseek(target_file, -seek_len, SEEK_CUR); + f_seek_skip_blank(target_file); + memset(segment_buff, '\0', sizeof(segment_buff)); + f_get_codeline(target_file, segment_buff, sizeof(segment_buff), &seek_len); + + // 解析元素变量信息 + { + variable_info info = solve_variable(segment_buff); + + // 成功解析 + if (info.type != TYPE_NOT_SUPPORTED) + { + // 结构体解析 + if (info.type == STRUCTURE) + { + // 匹配类型描述链表位置 + type_node *target_type = type_list_head; + while (target_type != nullptr) + { + if (!strcmp(target_type->type_name_str, info.type_name_str)) + { + info.type_name_str = target_type->type_name_str; + break; + } + target_type = target_type->p_next; + } + + sub_element_node *sub_element_list = target_type->element_list_head; + + // 获取地址 + // info = get_element_addr(info, Input_Map); + + // 调试信息 + if (info.start_addr_32 != 0) + { + if (info.element_count == 1) + print_log(LOG_SUCCESS, "0x%08x %-20s %s;\n", info.start_addr_32, info.A2L_type_str, info.name_str); + else + print_log(LOG_SUCCESS, "0x%08x %-20s %s[%d];\n", info.start_addr_32, info.A2L_type_str, info.name_str, info.element_count); + } + else + { + if (info.element_count == 1) + print_log(LOG_WARN, "0x%08x %-20s %s;\n", info.start_addr_32, info.A2L_type_str, info.name_str); + else + print_log(LOG_WARN, "0x%08x %-20s %s[%d];\n", info.start_addr_32, info.A2L_type_str, info.name_str, info.element_count); + } + + // 单变量 + if (info.element_count == 1) + { + int addr_offset = 0; + while (sub_element_list != nullptr) + { + // 计算地址偏移 + if (addr_offset % sub_element_list->element_info.single_element_size != 0) + addr_offset += sub_element_list->element_info.single_element_size - (addr_offset % sub_element_list->element_info.single_element_size); + + // 子元素非数组 + if (sub_element_list->element_info.element_count == 1) + { + fprintf(output_middleware_file, "%s\r\n\r\n", "/begin MEASUREMENT"); // 观测量头 + + fprintf(output_middleware_file, " %s.%s\r\n", info.name_str, sub_element_list->element_info.name_str); // 名称 + fprintf(output_middleware_file, " \"auto generated\"\r\n"); // 描述 + fprintf(output_middleware_file, " %s\r\n", sub_element_list->element_info.A2L_type_str); // 数据类型 + fprintf(output_middleware_file, " %s\r\n", "NO_COMPU_METHOD"); // 转换式(保留原始值) + fprintf(output_middleware_file, " %s\r\n", "0"); // 分辨率 + fprintf(output_middleware_file, " %s\r\n", "0"); // 精度误差 + fprintf(output_middleware_file, " %s\r\n", sub_element_list->element_info.A2L_min_limit_str); // 下限 + fprintf(output_middleware_file, " %s\r\n", sub_element_list->element_info.A2L_max_limit_str); // 上限 + fprintf(output_middleware_file, " %s 0x%08x\r\n\r\n", "ECU_ADDRESS", info.start_addr_32 + addr_offset); // ECU 地址 + + fprintf(output_middleware_file, "%s\r\n\r\n", "/end MEASUREMENT"); // 观测量尾 + + addr_offset += sub_element_list->element_info.single_element_size; + } + // 子元素是数组 + else + { + // 计算地址偏移 + if (addr_offset % sub_element_list->element_info.single_element_size != 0) + addr_offset += sub_element_list->element_info.single_element_size - (addr_offset % sub_element_list->element_info.single_element_size); + + for (size_t count = 0; count < sub_element_list->element_info.element_count; count++) + { + + fprintf(output_middleware_file, "%s\r\n\r\n", "/begin MEASUREMENT"); // 观测量头 + + fprintf(output_middleware_file, " %s.%s[%d]\r\n", info.name_str, sub_element_list->element_info.name_str, count); // 名称 + fprintf(output_middleware_file, " \"auto generated\"\r\n"); // 描述 + fprintf(output_middleware_file, " %s\r\n", sub_element_list->element_info.A2L_type_str); // 数据类型 + fprintf(output_middleware_file, " %s\r\n", "NO_COMPU_METHOD"); // 转换式(保留原始值) + fprintf(output_middleware_file, " %s\r\n", "0"); // 分辨率 + fprintf(output_middleware_file, " %s\r\n", "0"); // 精度误差 + fprintf(output_middleware_file, " %s\r\n", sub_element_list->element_info.A2L_min_limit_str); // 下限 + fprintf(output_middleware_file, " %s\r\n", sub_element_list->element_info.A2L_max_limit_str); // 上限 + fprintf(output_middleware_file, " %s 0x%08x\r\n\r\n", "ECU_ADDRESS", info.start_addr_32 + addr_offset + count * sub_element_list->element_info.single_element_size); // ECU 地址 + + fprintf(output_middleware_file, "%s\r\n\r\n", "/end MEASUREMENT"); // 观测量尾 + } + addr_offset += sub_element_list->element_info.element_count * sub_element_list->element_info.single_element_size; + } + + sub_element_list = sub_element_list->p_next; + } + } + // 类型是数组 + else + { + int addr_offset = 0; + + for (size_t outter_count = 0; outter_count < info.element_count; outter_count++) + { + sub_element_node *list = sub_element_list; + while (list != nullptr) + { + // 计算地址偏移 + if (addr_offset % list->element_info.single_element_size != 0) + addr_offset += list->element_info.single_element_size - (addr_offset % list->element_info.single_element_size); + + // 子元素非数组 + if (list->element_info.element_count == 1) + { + fprintf(output_middleware_file, "%s\r\n\r\n", "/begin MEASUREMENT"); // 观测量头 + + fprintf(output_middleware_file, " %s[%d].%s\r\n", info.name_str, outter_count, list->element_info.name_str); // 名称 + fprintf(output_middleware_file, " \"auto generated\"\r\n"); // 描述 + fprintf(output_middleware_file, " %s\r\n", list->element_info.A2L_type_str); // 数据类型 + fprintf(output_middleware_file, " %s\r\n", "NO_COMPU_METHOD"); // 转换式(保留原始值) + fprintf(output_middleware_file, " %s\r\n", "0"); // 分辨率 + fprintf(output_middleware_file, " %s\r\n", "0"); // 精度误差 + fprintf(output_middleware_file, " %s\r\n", list->element_info.A2L_min_limit_str); // 下限 + fprintf(output_middleware_file, " %s\r\n", list->element_info.A2L_max_limit_str); // 上限 + fprintf(output_middleware_file, " %s 0x%08x\r\n\r\n", "ECU_ADDRESS", info.start_addr_32 + addr_offset); // ECU 地址 + + fprintf(output_middleware_file, "%s\r\n\r\n", "/end MEASUREMENT"); // 观测量尾 + + addr_offset += list->element_info.single_element_size; + } + // 子元素是数组 + else + { + // 计算地址偏移 + if (addr_offset % list->element_info.single_element_size != 0) + addr_offset += list->element_info.single_element_size - (addr_offset % list->element_info.single_element_size); + + for (size_t count = 0; count < list->element_info.element_count; count++) + { + + fprintf(output_middleware_file, "%s\r\n\r\n", "/begin MEASUREMENT"); // 观测量头 + + fprintf(output_middleware_file, " %s[%d].%s[%d]\r\n", info.name_str, outter_count, list->element_info.name_str, count); // 名称 + fprintf(output_middleware_file, " \"auto generated\"\r\n"); // 描述 + fprintf(output_middleware_file, " %s\r\n", list->element_info.A2L_type_str); // 数据类型 + fprintf(output_middleware_file, " %s\r\n", "NO_COMPU_METHOD"); // 转换式(保留原始值) + fprintf(output_middleware_file, " %s\r\n", "0"); // 分辨率 + fprintf(output_middleware_file, " %s\r\n", "0"); // 精度误差 + fprintf(output_middleware_file, " %s\r\n", list->element_info.A2L_min_limit_str); // 下限 + fprintf(output_middleware_file, " %s\r\n", list->element_info.A2L_max_limit_str); // 上限 + fprintf(output_middleware_file, " %s 0x%08x\r\n\r\n", "ECU_ADDRESS", info.start_addr_32 + addr_offset + count * list->element_info.single_element_size); // ECU 地址 + + fprintf(output_middleware_file, "%s\r\n\r\n", "/end MEASUREMENT"); // 观测量尾 + } + addr_offset += list->element_info.element_count * list->element_info.single_element_size; + } + + list = list->p_next; + } + } + } + } + else + { + // 获取地址 + // info = get_element_addr(info, Input_Map); + + // 调试信息 + if (info.start_addr_32 != 0) + { + if (info.element_count == 1) + print_log(LOG_SUCCESS, "0x%08x %-20s %s;\n", info.start_addr_32, info.A2L_type_str, info.name_str); + else + print_log(LOG_SUCCESS, "0x%08x %-20s %s[%d];\n", info.start_addr_32, info.A2L_type_str, info.name_str, info.element_count); + } + else + { + if (info.element_count == 1) + print_log(LOG_WARN, "0x%08x %-20s %s;\n", info.start_addr_32, info.A2L_type_str, info.name_str); + else + print_log(LOG_WARN, "0x%08x %-20s %s[%d];\n", info.start_addr_32, info.A2L_type_str, info.name_str, info.element_count); + } + + // 单变量 + if (info.element_count == 1) + { + fprintf(output_middleware_file, "%s\r\n\r\n", "/begin MEASUREMENT"); // 观测量头 + + fprintf(output_middleware_file, " %s\r\n", info.name_str); // 名称 + fprintf(output_middleware_file, " \"auto generated\"\r\n"); // 描述 + fprintf(output_middleware_file, " %s\r\n", info.A2L_type_str); // 数据类型 + fprintf(output_middleware_file, " %s\r\n", "NO_COMPU_METHOD"); // 转换式(保留原始值) + fprintf(output_middleware_file, " %s\r\n", "0"); // 分辨率 + fprintf(output_middleware_file, " %s\r\n", "0"); // 精度误差 + fprintf(output_middleware_file, " %s\r\n", info.A2L_min_limit_str); // 下限 + fprintf(output_middleware_file, " %s\r\n", info.A2L_max_limit_str); // 上限 + fprintf(output_middleware_file, " %s 0x%08x\r\n\r\n", "ECU_ADDRESS", info.start_addr_32); // ECU 地址 + + fprintf(output_middleware_file, "%s\r\n\r\n", "/end MEASUREMENT"); // 观测量尾 + } + else + { + for (size_t count = 0; count < info.element_count; count++) + { + fprintf(output_middleware_file, "%s\r\n\r\n", "/begin MEASUREMENT"); // 观测量头 + + fprintf(output_middleware_file, " %s[%d]\r\n", info.name_str, count); // 名称 + fprintf(output_middleware_file, " \"auto generated\"\r\n"); // 描述 + fprintf(output_middleware_file, " %s\r\n", info.A2L_type_str); // 数据类型 + fprintf(output_middleware_file, " %s\r\n", "NO_COMPU_METHOD"); // 转换式(保留原始值) + fprintf(output_middleware_file, " %s\r\n", "0"); // 分辨率 + fprintf(output_middleware_file, " %s\r\n", "0"); // 精度误差 + fprintf(output_middleware_file, " %s\r\n", info.A2L_min_limit_str); // 下限 + fprintf(output_middleware_file, " %s\r\n", info.A2L_max_limit_str); // 上限 + fprintf(output_middleware_file, " %s 0x%08x\r\n\r\n", "ECU_ADDRESS", info.start_addr_32 + count * info.single_element_size); // ECU 地址 + + fprintf(output_middleware_file, "%s\r\n\r\n", "/end MEASUREMENT"); // 观测量尾 + } + } + } + } + else if (info.name_str[0] != '\0') // 解析失败且变量名不为空 + { + if (info.element_count == 1) + print_log(LOG_FAILURE, "0x%08x %-20s %s;\n", info.start_addr_32, info.A2L_type_str, info.name_str); + else + print_log(LOG_FAILURE, "0x%08x %-20s %s[%d];\n", info.start_addr_32, info.A2L_type_str, info.name_str, info.element_count); + } + } + + // 先跳行,防止段尾位注释引起异常 + f_seek_nextline(target_file); + // 跳过空白段 + f_seek_skip_blank(target_file); + // 清空段缓冲区 + memset(segment_buff, '\0', sizeof(segment_buff)); + } + } + + // 当前行为标定量起始位行 + if (strstr(segment_buff, calibration_begin)) + { + printf("\n%s\n\n", calibration_begin); + fprintf(output_middleware_file, auto_generated_calibration_start); + + // 清空段缓冲区 + memset(segment_buff, '\0', sizeof(segment_buff)); + + while (true) + { + // 获取下一行 + size_t seek_len = 0; + f_getline(target_file, segment_buff, sizeof(segment_buff), &seek_len); + + // 标定量结束行 + if (strstr(segment_buff, calibration_end)) + { + printf("\n%s\n\n", calibration_end); + fprintf(output_middleware_file, auto_generated_calibration_end); + break; + } + + // 非结束行,使用代码行进行处理,先回退,跳过空行后再重新读 + fseek(target_file, -seek_len, SEEK_CUR); + f_seek_skip_blank(target_file); + memset(segment_buff, '\0', sizeof(segment_buff)); + f_get_codeline(target_file, segment_buff, sizeof(segment_buff), &seek_len); + + // 解析元素变量信息 + { + variable_info info = solve_variable(segment_buff); + + // 成功解析 + if (info.type != TYPE_NOT_SUPPORTED) + { + + if (info.type == STRUCTURE) + { + // 匹配类型描述链表位置 + type_node *target_type = type_list_head; + while (target_type != nullptr) + { + if (!strcmp(target_type->type_name_str, info.type_name_str)) + { + info.type_name_str = target_type->type_name_str; + break; + } + target_type = target_type->p_next; + } + + sub_element_node *sub_element_list = target_type->element_list_head; + + // 获取地址 + // info = get_element_addr(info, Input_Map); + + // 调试信息 + if (info.start_addr_32 != 0) + { + if (info.element_count == 1) + print_log(LOG_SUCCESS, "0x%08x %-20s %s;\n", info.start_addr_32, info.A2L_type_str, info.name_str); + else + print_log(LOG_SUCCESS, "0x%08x %-20s %s[%d];\n", info.start_addr_32, info.A2L_type_str, info.name_str, info.element_count); + } + else + { + if (info.element_count == 1) + print_log(LOG_WARN, "0x%08x %-20s %s;\n", info.start_addr_32, info.A2L_type_str, info.name_str); + else + print_log(LOG_WARN, "0x%08x %-20s %s[%d];\n", info.start_addr_32, info.A2L_type_str, info.name_str, info.element_count); + } + + // 单变量 + if (info.element_count == 1) + { + int addr_offset = 0; + while (sub_element_list != nullptr) + { + // 计算地址偏移 + if (addr_offset % sub_element_list->element_info.single_element_size != 0) + addr_offset += sub_element_list->element_info.single_element_size - (addr_offset % sub_element_list->element_info.single_element_size); + + // 子元素非数组 + if (sub_element_list->element_info.element_count == 1) + { + fprintf(output_middleware_file, "%s\r\n\r\n", "/begin CHARACTERISTIC"); // 标定量头 + + fprintf(output_middleware_file, " %s.%s\r\n", info.name_str, sub_element_list->element_info.name_str); // 名称 + fprintf(output_middleware_file, " \"auto generated\"\r\n"); // 描述 + fprintf(output_middleware_file, " %s\r\n", "VALUE"); // 值类型(数值、数组、曲线) + fprintf(output_middleware_file, " 0x%08x\r\n", info.start_addr_32 + addr_offset); // ECU 地址 + fprintf(output_middleware_file, " Scalar_%s\r\n", sub_element_list->element_info.A2L_type_str); // 数据类型 + fprintf(output_middleware_file, " %s\r\n", "0"); // 允许最大差分 + fprintf(output_middleware_file, " %s\r\n", "NO_COMPU_METHOD"); // 转换式(保留原始值) + fprintf(output_middleware_file, " %s\r\n", sub_element_list->element_info.A2L_min_limit_str); // 下限 + fprintf(output_middleware_file, " %s\r\n\r\n", sub_element_list->element_info.A2L_max_limit_str); // 上限 + + fprintf(output_middleware_file, "%s\r\n\r\n", "/end CHARACTERISTIC"); // 标定量尾 + + addr_offset += sub_element_list->element_info.single_element_size; + } + // 子元素是数组 + else + { + // 计算地址偏移 + if (addr_offset % sub_element_list->element_info.single_element_size != 0) + addr_offset += sub_element_list->element_info.single_element_size - (addr_offset % sub_element_list->element_info.single_element_size); + + for (size_t count = 0; count < sub_element_list->element_info.element_count; count++) + { + fprintf(output_middleware_file, "%s\r\n\r\n", "/begin CHARACTERISTIC"); // 标定量头 + + fprintf(output_middleware_file, " %s.%s[%d]\r\n", info.name_str, sub_element_list->element_info.name_str, count); // 名称 + fprintf(output_middleware_file, " \"auto generated\"\r\n"); // 描述 + fprintf(output_middleware_file, " %s\r\n", "VALUE"); // 值类型(数值、数组、曲线) + fprintf(output_middleware_file, " 0x%08x\r\n", info.start_addr_32 + addr_offset + count * sub_element_list->element_info.single_element_size); // ECU 地址 + fprintf(output_middleware_file, " Scalar_%s\r\n", sub_element_list->element_info.A2L_type_str); // 数据类型 + fprintf(output_middleware_file, " %s\r\n", "0"); // 允许最大差分 + fprintf(output_middleware_file, " %s\r\n", "NO_COMPU_METHOD"); // 转换式(保留原始值) + fprintf(output_middleware_file, " %s\r\n", sub_element_list->element_info.A2L_min_limit_str); // 下限 + fprintf(output_middleware_file, " %s\r\n\r\n", sub_element_list->element_info.A2L_max_limit_str); // 上限 + + fprintf(output_middleware_file, "%s\r\n\r\n", "/end CHARACTERISTIC"); // 标定量尾 + } + addr_offset += sub_element_list->element_info.element_count * sub_element_list->element_info.single_element_size; + } + + sub_element_list = sub_element_list->p_next; + } + } + // 类型是数组 + else + { + int addr_offset = 0; + + for (size_t outter_count = 0; outter_count < info.element_count; outter_count++) + { + sub_element_node *list = sub_element_list; + while (list != nullptr) + { + // 计算地址偏移 + if (addr_offset % list->element_info.single_element_size != 0) + addr_offset += list->element_info.single_element_size - (addr_offset % list->element_info.single_element_size); + + // 子元素非数组 + if (list->element_info.element_count == 1) + { + fprintf(output_middleware_file, "%s\r\n\r\n", "/begin CHARACTERISTIC"); // 标定量头 + + fprintf(output_middleware_file, " %s[%d].%s\r\n", info.name_str, outter_count, list->element_info.name_str); // 名称 + fprintf(output_middleware_file, " \"auto generated\"\r\n"); // 描述 + fprintf(output_middleware_file, " %s\r\n", "VALUE"); // 值类型(数值、数组、曲线) + fprintf(output_middleware_file, " 0x%08x\r\n", info.start_addr_32 + addr_offset); // ECU 地址 + fprintf(output_middleware_file, " Scalar_%s\r\n", list->element_info.A2L_type_str); // 数据类型 + fprintf(output_middleware_file, " %s\r\n", "0"); // 允许最大差分 + fprintf(output_middleware_file, " %s\r\n", "NO_COMPU_METHOD"); // 转换式(保留原始值) + fprintf(output_middleware_file, " %s\r\n", list->element_info.A2L_min_limit_str); // 下限 + fprintf(output_middleware_file, " %s\r\n\r\n", list->element_info.A2L_max_limit_str); // 上限 + + fprintf(output_middleware_file, "%s\r\n\r\n", "/end CHARACTERISTIC"); // 标定量尾 + + addr_offset += list->element_info.single_element_size; + } + // 子元素是数组 + else + { + // 计算地址偏移 + if (addr_offset % list->element_info.single_element_size != 0) + addr_offset += list->element_info.single_element_size - (addr_offset % list->element_info.single_element_size); + + for (size_t count = 0; count < list->element_info.element_count; count++) + { + + fprintf(output_middleware_file, "%s\r\n\r\n", "/begin CHARACTERISTIC"); // 标定量头 + + fprintf(output_middleware_file, " %s[%d].%s[%d]\r\n", info.name_str, outter_count, list->element_info.name_str, count); // 名称 + fprintf(output_middleware_file, " \"auto generated\"\r\n"); // 描述 + fprintf(output_middleware_file, " %s\r\n", "VALUE"); // 值类型(数值、数组、曲线) + fprintf(output_middleware_file, " 0x%08x\r\n", info.start_addr_32 + addr_offset + count * list->element_info.single_element_size); // ECU 地址 + fprintf(output_middleware_file, " Scalar_%s\r\n", list->element_info.A2L_type_str); // 数据类型 + fprintf(output_middleware_file, " %s\r\n", "0"); // 允许最大差分 + fprintf(output_middleware_file, " %s\r\n", "NO_COMPU_METHOD"); // 转换式(保留原始值) + fprintf(output_middleware_file, " %s\r\n", list->element_info.A2L_min_limit_str); // 下限 + fprintf(output_middleware_file, " %s\r\n\r\n", list->element_info.A2L_max_limit_str); // 上限 + + fprintf(output_middleware_file, "%s\r\n\r\n", "/end CHARACTERISTIC"); // 标定量尾 + } + addr_offset += list->element_info.element_count * list->element_info.single_element_size; + } + + list = list->p_next; + } + } + } + } + else + { + // 获取地址 + // info = get_element_addr(info, Input_Map); + + // 调试信息 + if (info.start_addr_32 != 0) + { + if (info.element_count == 1) + print_log(LOG_SUCCESS, "0x%08x %-20s %s;\n", info.start_addr_32, info.A2L_type_str, info.name_str); + else + print_log(LOG_SUCCESS, "0x%08x %-20s %s[%d];\n", info.start_addr_32, info.A2L_type_str, info.name_str, info.element_count); + } + else + { + if (info.element_count == 1) + print_log(LOG_WARN, "0x%08x %-20s %s;\n", info.start_addr_32, info.A2L_type_str, info.name_str); + else + print_log(LOG_WARN, "0x%08x %-20s %s[%d];\n", info.start_addr_32, info.A2L_type_str, info.name_str, info.element_count); + } + + // 单变量 + if (info.element_count == 1) + { + fprintf(output_middleware_file, "%s\r\n\r\n", "/begin CHARACTERISTIC"); // 标定量头 + + fprintf(output_middleware_file, " %s\r\n", info.name_str); // 名称 + fprintf(output_middleware_file, " \"auto generated\"\r\n"); // 描述 + fprintf(output_middleware_file, " %s\r\n", "VALUE"); // 值类型(数值、数组、曲线) + fprintf(output_middleware_file, " 0x%08x\r\n", info.start_addr_32); // ECU 地址 + fprintf(output_middleware_file, " Scalar_%s\r\n", info.A2L_type_str); // 数据类型 + fprintf(output_middleware_file, " %s\r\n", "0"); // 允许最大差分 + fprintf(output_middleware_file, " %s\r\n", "NO_COMPU_METHOD"); // 转换式(保留原始值) + fprintf(output_middleware_file, " %s\r\n", info.A2L_min_limit_str); // 下限 + fprintf(output_middleware_file, " %s\r\n\r\n", info.A2L_max_limit_str); // 上限 + + fprintf(output_middleware_file, "%s\r\n\r\n", "/end CHARACTERISTIC"); // 标定量尾 + } + else + { + for (size_t count = 0; count < info.element_count; count++) + { + fprintf(output_middleware_file, "%s\r\n\r\n", "/begin CHARACTERISTIC"); // 标定量头 + + fprintf(output_middleware_file, " %s[%d]\r\n", info.name_str, count); // 名称 + fprintf(output_middleware_file, " \"auto generated\"\r\n"); // 描述 + fprintf(output_middleware_file, " %s\r\n", "VALUE"); // 值类型(数值、数组、曲线) + fprintf(output_middleware_file, " 0x%08x\r\n", info.start_addr_32 + count * info.single_element_size); // ECU 地址 + fprintf(output_middleware_file, " Scalar_%s\r\n", info.A2L_type_str); // 数据类型 + fprintf(output_middleware_file, " %s\r\n", "0"); // 允许最大差分 + fprintf(output_middleware_file, " %s\r\n", "NO_COMPU_METHOD"); // 转换式(保留原始值) + fprintf(output_middleware_file, " %s\r\n", info.A2L_min_limit_str); // 下限 + fprintf(output_middleware_file, " %s\r\n\r\n", info.A2L_max_limit_str); // 上限 + + fprintf(output_middleware_file, "%s\r\n\r\n", "/end CHARACTERISTIC"); // 标定量尾 + } + } + } + } + else if (info.name_str[0] != '\0') // 解析失败且变量名不为空 + { + if (info.element_count == 1) + printf("[< FAIL >] 0x%08x %-20s %s;\n", info.start_addr_32, info.A2L_type_str, info.name_str); + else + printf("[< FAIL >] 0x%08x %-20s %s[%d];\n", info.start_addr_32, info.A2L_type_str, info.name_str, info.element_count); + } + } + + // 先跳行,防止段尾位注释引起异常 + f_seek_nextline(target_file); + // 跳过空白段 + f_seek_skip_blank(target_file); + // 清空段缓冲区 + memset(segment_buff, '\0', sizeof(segment_buff)); + } + } + } + + fclose(target_file); + target_node = target_node->p_next; + } +} + +// 处理最终A2L输出 +void solve_A2L_output(void) +{ + // 段缓冲区 + char segment_buff[SEGMENT_BUFF_LENGTH] = {'\0'}; + + // 读取并复制参考文件直到 a2l MODULE 结尾 + while (f_getline(input_reference_A2L_file, segment_buff, sizeof(segment_buff)) == ERROR_NONE) + { + // 当前行为 a2l MODULE 结尾 + if (strstr(segment_buff, a2l_module_end)) + { + // 回退文件指针到上一行结尾 + fseek(input_reference_A2L_file, -2, SEEK_CUR); + while (fgetc(input_reference_A2L_file) != '\n') + fseek(input_reference_A2L_file, -2, SEEK_CUR); + break; + } + + // 输出行到文件 + // fprintf(Output_Target, segment_buff); // 太大300会段溢出 + for (int count = 0; count < SEGMENT_BUFF_LENGTH; count++) // 逐个输出 + { + fputc(segment_buff[count], output_target_A2L_file); + if (segment_buff[count] == '\n') + break; + } + + // 清空段缓冲区 + memset(segment_buff, '\0', sizeof(segment_buff)); + } + fseek(output_middleware_file, 0, SEEK_SET); + + char ch = fgetc(output_middleware_file); + while (ch != EOF) + { + fputc(ch, output_target_A2L_file); + ch = fgetc(output_middleware_file); + } + + // 输出参考文件的剩余部分 + while (f_getline(input_reference_A2L_file, segment_buff, sizeof(segment_buff)) == ERROR_NONE) + { + // 输出行到文件 + fprintf(output_target_A2L_file, segment_buff); + // 清空段缓冲区 + memset(segment_buff, '\0', sizeof(segment_buff)); + } +} +// end \ No newline at end of file diff --git a/Src/Global_Variables.cpp b/Src/Global_Variables.cpp new file mode 100644 index 0000000..b78b97e --- /dev/null +++ b/Src/Global_Variables.cpp @@ -0,0 +1,21 @@ +#include "Global_Variables.hpp" + +extern "C" +{ +#include "stdio.h" +} + +// 类型列表 +type_node *type_list_head = nullptr; + +// 宏定义列表 +define_node *define_list_head = nullptr; + +// 源文件列表 +file_node *source_file_list_head = nullptr; + +// 文件列表 +FILE *input_reference_A2L_file = nullptr; +FILE *input_map_file = nullptr; +FILE *output_target_A2L_file = nullptr; +FILE *output_middleware_file = nullptr; diff --git a/Src/Main.cpp b/Src/Main.cpp new file mode 100644 index 0000000..e1827e8 --- /dev/null +++ b/Src/Main.cpp @@ -0,0 +1,37 @@ +extern "C" +{ +#include "stdint.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +} + +#include "Config.hpp" +#include "Tool_Functions.hpp" +#include "Global_Variables.hpp" +#include "Core_Functions.hpp" + +int main(int argc, char *argv[]) +{ + // 处理输入部分 + solve_args(argc, argv); + + printf("\n\n"); + + // 进行宏定义解析 + solve_defines(); + + printf("\n\n"); + + // 进行类型解析 + solve_types(); + + // 处理中间件 + solve_middleware(); + + // 处理最终输出 + solve_A2L_output(); + + print_log(LOG_SUCCESS, "Done.\nVer0.3"); + return 0; +} \ No newline at end of file diff --git a/Src/Tool_Functions.cpp b/Src/Tool_Functions.cpp new file mode 100644 index 0000000..a3f1d84 --- /dev/null +++ b/Src/Tool_Functions.cpp @@ -0,0 +1,616 @@ +#include "Tool_Functions.hpp" +#include "Global_Variables.hpp" + +extern "C" +{ +#include "string.h" +#include "ctype.h" +#include "stdarg.h" +} + +// 读取文件下一行 +error_type_enum f_getline(FILE *file, char *buffer, const size_t buffer_len, size_t *seek_len) +{ + if (buffer == nullptr || file == nullptr) + { + *seek_len = 0; + return ERROR_ILLEGAL_POINTER; + } + + memset(buffer, '\0', buffer_len); + + size_t count = 0; + + while (true) + { + char ch = fgetc(file); + + if (count >= buffer_len) // 超长 + { + fseek(file, -count, SEEK_CUR); + if (seek_len != nullptr) + *seek_len = 0; + return ERROR_OUT_OF_LENGTH; + } + + if (ch == EOF && count == 0) // 仅文件结尾时 + { + if (seek_len != nullptr) + *seek_len = 0; + return ERROR_END_OF_FILE; + } + + if (ch == '\n' || ch == EOF) // 成功换行or文件结尾 + { + buffer[count] = '\n'; + if (seek_len != nullptr) + *seek_len = count + 1; + return ERROR_NONE; + } + + buffer[count] = ch; + count++; + } +} + +// 获取文件代码行(以;为分界的代码逻辑行,忽略中途的注释) +error_type_enum f_get_codeline(FILE *file, char *buffer, const size_t buffer_len, size_t *seek_len) +{ + if (buffer == nullptr || file == nullptr) + { + *seek_len = 0; + return ERROR_ILLEGAL_POINTER; + } + + memset(buffer, '\0', buffer_len); + + size_t skip_count = 0; + + // 跳过空白内容和注释 + while (true) + { + skip_count += f_seek_skip_blank(file); + + // 忽略注释内容 + if (fgetc(file) == '/') + { + skip_count++; + // 是单行注释,连续遇到两个'/' + if (fgetc(file) == '/') + { + skip_count++; + skip_count += f_seek_nextline(file); + } + // 是多行注释,直接跳过中间内容直到遇到下一个'/' + else + { + while (fgetc(file) != '/') + skip_count++; + skip_count++; + } + } + else + { + fseek(file, -1, SEEK_CUR); + break; + } + } + + size_t code_line_count = 0; + while (true) + { + char ch = fgetc(file); + + if (code_line_count >= buffer_len) // 超长 + { + fseek(file, -(skip_count + code_line_count), SEEK_CUR); + if (seek_len != nullptr) + *seek_len = 0; + return ERROR_OUT_OF_LENGTH; + } + + if (ch == EOF && code_line_count == 0) // 仅文件结尾时 + { + if (seek_len != nullptr) + *seek_len = 0; + return ERROR_END_OF_FILE; + } + + if (ch == ';') // 代码结尾 + { + buffer[code_line_count] = ';'; + if (seek_len != nullptr) + *seek_len = code_line_count + skip_count + 1; + return ERROR_NONE; + } + + if (ch == EOF) // 文件结尾 + { + buffer[code_line_count] = '\0'; + if (seek_len != nullptr) + *seek_len = code_line_count + skip_count; + return ERROR_NONE; + } + + buffer[code_line_count] = ch; + code_line_count++; + } +} + +// 读取下一个有效词组 +error_type_enum f_getword(FILE *file, char *buffer, const size_t buffer_len, size_t *seek_len) +{ + if (buffer == nullptr || file == nullptr) + { + *seek_len = 0; + return ERROR_ILLEGAL_POINTER; + } + + size_t read_count = 0; + // 过滤空白 + while (true) + { + char ch = fgetc(file); + if (read_count >= buffer_len) // 超长 + { + fseek(file, -read_count, SEEK_CUR); + if (seek_len != nullptr) + *seek_len = 0; + return ERROR_OUT_OF_LENGTH; + } + + if (ch == EOF && read_count == 0) // 仅文件结尾时 + { + if (seek_len != nullptr) + *seek_len = 0; + return ERROR_END_OF_FILE; + } + + // 过滤空白 + if (ch == ' ' || ch == '\r' || ch == '\n') + { + read_count++; + continue; + } + + // 遇到非空格非换行的有效字符 + fseek(file, -1, SEEK_CUR); + break; + } + + size_t count = 0; + memset(buffer, '\0', buffer_len); + + while (true) + { + char ch = fgetc(file); + + if (read_count >= buffer_len) // 超长 + { + fseek(file, -read_count, SEEK_CUR); + if (seek_len != nullptr) + *seek_len = 0; + return ERROR_OUT_OF_LENGTH; + } + + if (ch == EOF && count == 0) // 仅文件结尾时 + { + if (seek_len != nullptr) + *seek_len = 0; + return ERROR_END_OF_FILE; + } + + if (!isalnum(ch) && ch != '_' && count == 0) // 遇到的第一个就是非有效字符 + { + fseek(file, -(read_count + 1), SEEK_CUR); + if (seek_len != nullptr) + *seek_len = 0; + return ERROR_ILLEGAL_WORD_SECTION; + } + + if (!isalnum(ch) && ch != '_') // 非字符类 + { + // 回退指针后正常返回 + fseek(file, -1, SEEK_CUR); + if (seek_len != nullptr) + *seek_len = read_count; + return ERROR_NONE; + } + + buffer[count] = ch; + count++; + read_count++; + } +} + +// 前进到下一行 +size_t f_seek_nextline(FILE *file) +{ + size_t count = 0; + while (true) + { + char ch = fgetc(file); + if (ch == '\n' || ch == EOF) + break; + + count++; + } + + return count; +} + +// 跳转到下一个非空字符 +size_t f_seek_skip_blank(FILE *file) +{ + size_t count = 0; + while (true) + { + char ch = fgetc(file); + if (ch == ' ' || ch == '\r' || ch == '\n') + { + count++; + continue; + } + + if (ch == EOF) + return count; + + break; + } + + // 回退指针 + fseek(file, -1, SEEK_CUR); + return count; +} + +// 基础变量类型解析 +variable_type_enum get_variable_base_type(const char *str) +{ + if (!strcmp(str, "bool")) + return UBYTE; + if (!strcmp(str, "boolean_t")) + return UBYTE; + + if (!strcmp(str, "uint8_t")) + return UBYTE; + if (!strcmp(str, "uint16_t")) + return UWORD; + if (!strcmp(str, "uint32_t")) + return ULONG; + + if (!strcmp(str, "int8_t")) + return SBYTE; + if (!strcmp(str, "int16_t")) + return SWORD; + if (!strcmp(str, "int32_t")) + return SLONG; + + if (!strcmp(str, "float")) + return FLOAT32; + if (!strcmp(str, "double")) + return FLOAT64; + + return TYPE_NOT_SUPPORTED; +} + +// 基础变量解析 +variable_info solve_base_variable(const char *str) +{ + variable_info info; + + // 读取前段内容并获取元素类型 + char buff[VARIABLE_NAME_LENGTH_MAX] = {'\0'}; + size_t offset = 0; + + // 跳过前方的修饰段 + while (true) + { + sscanf(str + offset, "%s", buff); + + // 不是下列任何的前置修饰符号时跳出 + if (!(!strcmp("const", buff) || !strcmp("static", buff) || !strcmp("volatile", buff))) + break; + + // 是修饰段 + while (str[offset] != ' ' && str[offset] != '\0') // 跳过当前词组段 + offset++; + while (!isalnum(str[offset]) && str[offset] != '\0') // 前进到有效字符 + offset++; + + memset(buff, '\0', sizeof(buff)); + } + + info.type = get_variable_base_type(buff); + + // 更新字符串信息 + switch (info.type) + { + case UBYTE: + sprintf(info.A2L_type_str, "UBYTE"); + sprintf(info.A2L_min_limit_str, "0"); + sprintf(info.A2L_max_limit_str, "255"); + info.single_element_size = 1; + break; + case UWORD: + sprintf(info.A2L_type_str, "UWORD"); + sprintf(info.A2L_min_limit_str, "0"); + sprintf(info.A2L_max_limit_str, "65535"); + info.single_element_size = 2; + break; + case ULONG: + sprintf(info.A2L_type_str, "ULONG"); + sprintf(info.A2L_min_limit_str, "0"); + sprintf(info.A2L_max_limit_str, "4294967295"); + info.single_element_size = 4; + break; + case SBYTE: + sprintf(info.A2L_type_str, "SBYTE"); + sprintf(info.A2L_min_limit_str, "-128"); + sprintf(info.A2L_max_limit_str, "127"); + info.single_element_size = 1; + case SWORD: + sprintf(info.A2L_type_str, "SWORD"); + sprintf(info.A2L_min_limit_str, "-32768"); + sprintf(info.A2L_max_limit_str, "32767"); + info.single_element_size = 2; + break; + case SLONG: + sprintf(info.A2L_type_str, "SLONG"); + sprintf(info.A2L_min_limit_str, "-2147483648"); + sprintf(info.A2L_max_limit_str, "2147483647"); + info.single_element_size = 4; + break; + case FLOAT32: + sprintf(info.A2L_type_str, "FLOAT32_IEEE"); + sprintf(info.A2L_min_limit_str, "-3.4E+38"); + sprintf(info.A2L_max_limit_str, "3.4E+38"); + info.single_element_size = 4; + break; + case FLOAT64: + sprintf(info.A2L_type_str, "FLOAT64_IEEE"); + sprintf(info.A2L_min_limit_str, "-1.7E+308"); + sprintf(info.A2L_max_limit_str, "1.7E+308"); + info.single_element_size = 8; + break; + default: + sprintf(info.A2L_type_str, "UNSUPPORTED"); + sprintf(info.A2L_min_limit_str, "0"); + sprintf(info.A2L_max_limit_str, "0"); + info.single_element_size = 0; + } + + // 读取后段内容 + sscanf(str + offset + strlen(buff), "%s", buff); + + // 获取名字和长度 + for (int count = 0; count < VARIABLE_NAME_LENGTH_MAX; count++) + { + if (buff[count] == '[') // 识别到数组 + { + for (int n = count + 1; n < VARIABLE_NAME_LENGTH_MAX; n++) + { + if (buff[n] == ']') + break; + if (isdigit(buff[n])) + info.element_count = info.element_count * 10 + buff[n] - '0'; + else + { + /** + * @todo + * 添加宏定义识别,先暂时将不支持的量定义为1 + */ + // 处理宏定义常量 + char define_str[VARIABLE_NAME_LENGTH_MAX] = {'\0'}; + for (int count = 0; count < VARIABLE_NAME_LENGTH_MAX; count++) + if (buff[n + count] == ']') + break; + else + define_str[count] = buff[n + count]; + + // 进行匹配 + define_node *target_define_node = define_list_head; + while (target_define_node != nullptr) + { + // 找到宏定义了 + if (!strcmp(target_define_node->define_str, define_str)) + { + int value = 1; + sscanf(target_define_node->context_str, "%d", &value); + info.element_count = value; + break; + } + target_define_node = target_define_node->p_next; + } + // 完全匹配但没有找到 + if (target_define_node == nullptr) + { + printf("\n"); + print_log(LOG_WARN, "%s [%s -> 1]\n", "Unknown value context,set to default:", define_str); + printf("\n"); + info.element_count = 1; + } + break; + } + } + + break; + } + + if (buff[count] == ' ' || buff[count] == '=' || buff[count] == ';') // 是单个变量 + { + if (info.element_count == 0) + info.element_count = 1; + break; + } + + info.name_str[count] = buff[count]; // 复制变量名 + } + + return info; +} + +// 解析变量类型 +variable_type_enum get_variable_type(const char *str) +{ + variable_type_enum type = get_variable_base_type(str); + if (type != TYPE_NOT_SUPPORTED) + return type; + + // 遍历复合类型 + type_node *target_node = type_list_head; + while (target_node != nullptr) + { + if (!strcmp(str, target_node->type_name_str)) + return target_node->type; + target_node = target_node->p_next; + } + + return TYPE_NOT_SUPPORTED; +} + +// 变量解析 +variable_info solve_variable(const char *str) +{ + variable_info info; + + char buff[VARIABLE_NAME_LENGTH_MAX] = {'\0'}; + size_t offset = 0; + + // 跳过前方的修饰段 + while (true) + { + sscanf(str + offset, "%s", buff); + + // 不是下列任何的前置修饰符号时跳出 + if (!(!strcmp("const", buff) || !strcmp("static", buff) || !strcmp("volatile", buff))) + break; + + // 是修饰段 + while (str[offset] != ' ' && str[offset] != '\0') // 跳过当前词组段 + offset++; + while (!isalnum(str[offset]) && str[offset] != '\0') // 前进到有效字符 + offset++; + + memset(buff, '\0', sizeof(buff)); + } + + // 读取前段内容并获取元素类型 + info.type = get_variable_type(buff); + + // 判断是否为结构体类型 + if (info.type == STRUCTURE) + { + sprintf(info.A2L_type_str, "STRUCTURE"); + + // 匹配类型描述链表位置 + type_node *target_type = type_list_head; + while (target_type != nullptr) + { + if (!strcmp(target_type->type_name_str, buff)) + { + info.type_name_str = target_type->type_name_str; + break; + } + target_type = target_type->p_next; + } + + // 读取后段内容 + sscanf(str + offset + strlen(buff), "%s", buff); + + // 获取名字和长度 + for (int count = 0; count < VARIABLE_NAME_LENGTH_MAX; count++) + { + if (buff[count] == '[') // 识别到数组 + { + for (int n = count + 1; n < VARIABLE_NAME_LENGTH_MAX; n++) + { + if (buff[n] == ']') + break; + if (isdigit(buff[n])) + info.element_count = info.element_count * 10 + buff[n] - '0'; + else + { + + /** + * @todo + * 添加宏定义识别,先暂时将不支持的量定义为1 + */ + // 处理宏定义常量 + char define_str[VARIABLE_NAME_LENGTH_MAX] = {'\0'}; + for (int count = 0; count < VARIABLE_NAME_LENGTH_MAX; count++) + if (buff[n + count] == ']') + break; + else + define_str[count] = buff[n + count]; + + // 进行匹配 + define_node *target_define_node = define_list_head; + while (target_define_node != nullptr) + { + // 找到宏定义了 + if (!strcmp(target_define_node->define_str, define_str)) + { + int value = 1; + sscanf(target_define_node->context_str, "%d", &value); + info.element_count = value; + break; + } + target_define_node = target_define_node->p_next; + } + // 完全匹配但没有找到 + if (target_define_node == nullptr) + { + printf("\n"); + print_log(LOG_WARN, "%s [%s -> 1]\n", "Unknown value context,set to default:", define_str); + printf("\n"); + info.element_count = 1; + } + break; + } + } + + break; + } + + if (buff[count] == ' ' || buff[count] == '=' || buff[count] == ';') // 是单个变量 + { + if (info.element_count == 0) + info.element_count = 1; + break; + } + + info.name_str[count] = buff[count]; // 复制变量名 + } + + return info; + } + return solve_base_variable(str); +} + +// 日志输出 +void print_log(log_type_enum log_type, const char *p_format_str, ...) +{ + switch (log_type) + { + case LOG_SUCCESS: + printf("[- OK -] "); + break; + case LOG_WARN: + printf("[+ WARN +] "); + break; + case LOG_FAILURE: + printf("[< FAIL >] "); + break; + case LOG_NORMAL: + printf("[ INFO ] "); + break; + case LOG_ERROR: + printf("[# ERRO #] "); + break; + } + + // 传递不定参数 + va_list args; + va_start(args, p_format_str); + vprintf(p_format_str, args); +} \ No newline at end of file diff --git a/main.cpp b/main.cpp deleted file mode 100644 index 0f0a6a0..0000000 --- a/main.cpp +++ /dev/null @@ -1,688 +0,0 @@ -#include - -extern "C" -{ -#include -#include -#include -#include -} - -#define SEGMENT_BUFF_LENGTH 1000 // 行段长度 -#define ELEMENT_INFO_NAME_LENGTH 50 // 变量名长度上限 -#define ELEMENT_INFO_TYPE_STR_LENTH 20 // 变量类型字符串长度上限 -#define ELEMENT_INFO_LIMIT_STR_LENTH 20 // 变量上下限字符串长度上限 - -// 输入输出文件指针 -FILE *Input_Source = nullptr; -FILE *Input_Reference = nullptr; -FILE *Input_Map = nullptr; -FILE *Output_Target = nullptr; - -// 相关识别串 -const char measurement_begin[] = "// ##begin_measurement"; -const char measurement_end[] = "// ##end_measurement"; -const char calibration_begin[] = "// ##begin_calibration"; -const char calibration_end[] = "// ##end_calibration"; -const char a2l_module_end[] = "/end MODULE"; - -// 段输出标识串 -const char auto_generated_measurement_start[] = "\r\n/*********** Start of auto generated measurement blocks ***********/\r\n\r\n"; -const char auto_generated_measurement_end[] = "\r\n/*********** End of auto generated measurement blocks ***********/\r\n\r\n"; -const char auto_generated_calibration_start[] = "\r\n/*********** Start of auto generated calibration blocks ***********/\r\n\r\n"; -const char auto_generated_calibration_end[] = "\r\n/*********** End of auto generated calibration blocks ***********/\r\n\r\n"; - -// 变量类型枚举 -typedef enum -{ - TYPE_NOT_SUPPORTED, // 不支持的类型 - UBYTE, // uint8_t,bool - UWORD, // uint16_t - ULONG, // uint32_t - SBYTE, // int8_t - SWORD, // int16_t - SLONG, // int32_t - FLOAT32, // float - FLOAT64, // double - -} Element_Type_Enum; - -// 元素信息结构体 -typedef struct -{ - char name[ELEMENT_INFO_NAME_LENGTH] = {'\0'}; // 变量名 - size_t count = 0; // 变量成员数(仅数组>1) - size_t element_len = 0; // 单元素长度(单位:字节) - uint32_t addr = 0x00000000; // 元素起始地址 - Element_Type_Enum type = TYPE_NOT_SUPPORTED; // 变量类型 - char type_str[ELEMENT_INFO_TYPE_STR_LENTH] = {'\0'}; // 类型字符串 - char max_limit_str[ELEMENT_INFO_LIMIT_STR_LENTH] = {'\0'}; // 上限字符串 - char min_limit_str[ELEMENT_INFO_LIMIT_STR_LENTH] = {'\0'}; // 下限字符串 -} Element_Info; - -// 文件链表 -typedef struct File_List_Struct -{ - const char *file_name = nullptr; // 文件名 - File_List_Struct *p_next = nullptr; // 下一表 - -} File_List; - -// 获取文件的一行,成功时返回字符串指针,失败(文件结尾or超出长度)时回退文件指针 -char *f_getline(FILE *file, char *s, size_t len) -{ - size_t count = 0; - while (true) - { - char ch = fgetc(file); - - if (count >= len) // 超长 - { - fseek(file, -count, SEEK_CUR); - printf("[- WARN -] single line out of length\n"); - return nullptr; - } - - if (ch == EOF && count == 0) // 仅文件结尾 - return nullptr; - - if (ch == '\n' || ch == EOF) // 成功换行or文件结尾 - { - s[count] = '\n'; - return s; - } - - s[count] = ch; - count++; - } -} - -// 获取类型 -Element_Type_Enum get_element_type(const char *str) -{ - if (!strcmp(str, "bool")) - return UBYTE; - - if (!strcmp(str, "uint8_t")) - return UBYTE; - if (!strcmp(str, "uint16_t")) - return UWORD; - if (!strcmp(str, "uint32_t")) - return ULONG; - - if (!strcmp(str, "int8_t")) - return SBYTE; - if (!strcmp(str, "int16_t")) - return SWORD; - if (!strcmp(str, "int32_t")) - return SLONG; - - if (!strcmp(str, "float")) - return FLOAT32; - if (!strcmp(str, "double")) - return FLOAT64; - - return TYPE_NOT_SUPPORTED; -} - -// 解析元素类型 -Element_Info solve_element(const char *str) -{ - Element_Info info; - - // 读取前段内容并获取元素类型 - char buff[ELEMENT_INFO_NAME_LENGTH] = {'\0'}; - sscanf(str, "%s", buff); - info.type = get_element_type(buff); - - // 更新字符串信息 - switch (info.type) - { - case UBYTE: - sprintf(info.type_str, "UBYTE"); - sprintf(info.min_limit_str, "0"); - sprintf(info.max_limit_str, "255"); - info.element_len = 1; - break; - case UWORD: - sprintf(info.type_str, "UWORD"); - sprintf(info.min_limit_str, "0"); - sprintf(info.max_limit_str, "65535"); - info.element_len = 2; - break; - case ULONG: - sprintf(info.type_str, "ULONG"); - sprintf(info.min_limit_str, "0"); - sprintf(info.max_limit_str, "4294967295"); - info.element_len = 4; - break; - case SBYTE: - sprintf(info.type_str, "SBYTE"); - sprintf(info.min_limit_str, "-128"); - sprintf(info.max_limit_str, "127"); - info.element_len = 1; - case SWORD: - sprintf(info.type_str, "SWORD"); - sprintf(info.min_limit_str, "-32768"); - sprintf(info.max_limit_str, "32767"); - info.element_len = 2; - break; - case SLONG: - sprintf(info.type_str, "SLONG"); - sprintf(info.min_limit_str, "-2147483648"); - sprintf(info.max_limit_str, "2147483647"); - info.element_len = 4; - break; - case FLOAT32: - sprintf(info.type_str, "FLOAT32_IEEE"); - sprintf(info.min_limit_str, "-3.4E+38"); - sprintf(info.max_limit_str, "3.4E+38"); - info.element_len = 4; - break; - case FLOAT64: - sprintf(info.type_str, "FLOAT64_IEEE"); - sprintf(info.min_limit_str, "-1.7E+308"); - sprintf(info.max_limit_str, "1.7E+308"); - info.element_len = 8; - break; - default: - sprintf(info.type_str, "UNSUPPORTED"); - sprintf(info.min_limit_str, "0"); - sprintf(info.max_limit_str, "0"); - info.element_len = 0; - } - - // 读取后段内容 - sscanf(str + strlen(buff), "%s", buff); - - // 获取名字和长度 - for (int count = 0; count < ELEMENT_INFO_NAME_LENGTH; count++) - { - if (buff[count] == '[') // 识别到数组 - { - for (int n = count; n < ELEMENT_INFO_NAME_LENGTH; n++) - { - if (buff[n] == ']') - break; - if (isdigit(buff[n])) - info.count = info.count * 10 + buff[n] - '0'; - } - - break; - } - - if (buff[count] == ' ' || buff[count] == '=' || buff[count] == ';') // 是单个变量 - break; - - info.name[count] = buff[count]; // 复制变量名 - } - - return info; -} - -// 获取元素地址 -Element_Info get_element_addr(Element_Info info, FILE *map_file) -{ - // 回到文件头 - fseek(map_file, 0, SEEK_SET); - // 段缓冲区 - char segment_buff[SEGMENT_BUFF_LENGTH] = {'\0'}; - - bool find = false; - - // 读取并复制参考文件直到 a2l MODULE 结尾 - while (f_getline(map_file, segment_buff, sizeof(segment_buff)) != nullptr && !find) - { - - // 匹配到变量名称 - if (strstr(segment_buff, info.name)) - { - char *lpTarget = strstr(segment_buff, info.name); - size_t len = strlen(info.name); - - // 匹配到的名称是后段中的子段内容---> xxxxx[name]xx - if (lpTarget[len] != ' ' && lpTarget[len] != '\r' && lpTarget[len] != '\n') - continue; - // 匹配到的名称是前段中的字段内容---> xx[name]xxxxx - if (*(lpTarget - 1) != '_' && *(lpTarget - 1) != ' ' && *(lpTarget - 1) != '@') - continue; - - find = true; - - char buff[20]; - sscanf(segment_buff, "%*s%s", &buff); - - // 16进制转换 - for (int count = 0; count < 20; count++) - { - if (buff[count] == '+') - break; - - if (isalpha(buff[count])) - info.addr = info.addr * 16 + toupper(buff[count]) - 'A' + 10; - else - info.addr = info.addr * 16 + buff[count] - '0'; - } - } - - // 清空段缓冲区 - memset(segment_buff, '\0', sizeof(segment_buff)); - } - - return info; -} - -// 入口 -int main(int m_argc, char *m_argv[]) -{ - - // int m_argc = 9; - // char str[m_argc][20] = { - // {".\\new.exe"}, - // {".\\input.c"}, - // {".\\inputB.c"}, - // {"-r"}, - // {".\\PVER.a2l"}, - // {"-l"}, - // {".\\PVER.map"}, - // // {"-o"}, - // // {".\\[NEW]PVER.a2l"}, - // }; - // char *(m_argv[m_argc]); - // for (int count = 0; count < m_argc; count++) - // m_argv[count] = str[count]; - - // 文件列表初始 - File_List *list = (File_List *)malloc(sizeof(File_List)); - list->file_name = nullptr; - list->p_next = nullptr; - File_List *listHead = list; - - // 处理输入部分 - { - const char *reference_name = nullptr; // 参考文件名 - const char *output_name = nullptr; // 输出文件名 - - // 循环处理指令 - for (int count = 1; count < m_argc; count++) - { - // 匹配到参考a2l文件 - if (!strcmp(m_argv[count], "-r")) - { - if (count + 1 >= m_argc) - break; - Input_Reference = fopen(m_argv[count + 1], "rb"); - if (Input_Reference == nullptr) - { - printf("[- FAIL -] Input reference file <%s> open failed.\n", m_argv[count + 1]); - break; - } - - // 获取不带路径的文件名 - reference_name = m_argv[count + 1] + strlen(m_argv[count + 1]); - while (reference_name + 1 != m_argv[count + 1] && *reference_name != '\\' && *reference_name != '/') - reference_name--; - reference_name++; - - printf("[- OK -] %-31s %s\n", "Input reference .a2l file:", m_argv[count + 1]); - count++; - continue; - } - - // 匹配到链接map文件 - else if (!strcmp(m_argv[count], "-l")) - { - if (count + 1 >= m_argc) - break; - Input_Map = fopen(m_argv[count + 1], "rb"); - if (Input_Map == nullptr) - { - printf("[- FAIL -] Input link file <%s> open failed.\n", m_argv[count + 1]); - break; - } - - printf("[- OK -] %-31s %s\n", "Input link .map file:", m_argv[count + 1]); - count++; - continue; - } - - // 匹配到自定义输出文件名 - else if (!strcmp(m_argv[count], "-o")) - { - if (count + 1 >= m_argc) - break; - output_name = m_argv[count + 1]; - printf("[- OK -] %-31s %s\n", "Set output filename:", m_argv[count + 1]); - count++; - continue; - } - - // 其它输入作为源文件输入 - printf("[- OK -] %-31s %s\n", "Input source filename:", m_argv[count]); - list->file_name = m_argv[count]; - list->p_next = (File_List *)malloc(sizeof(File_List)); - list = list->p_next; - list->file_name = nullptr; - list->p_next = nullptr; - } - - // 检查文件列表状态 - if (listHead->file_name == nullptr) - { - printf("[- FAIL -] No source file input.\n"); - free(listHead); - fcloseall(); - return 0; - } - - // 检查参考文件输入文件状态 - if (Input_Reference == nullptr) - { - printf("[- FAIL -] No reference .a2l file input.\n"); - fcloseall(); - return 0; - } - - // 检查map链接文件文件状态 - if (Input_Map == nullptr) - printf("[- WARN -] No link .map file input.\n"); - - // 处理输出文件名称 - if (output_name != nullptr) - Output_Target = fopen(output_name, "wb+"); - else if (reference_name != nullptr) - { - // 拼接默认的输出文件名 - const char *prefix = "[NEW]"; - char *buffer = (char *)malloc(strlen(reference_name) + strlen(prefix) + 1); - sprintf(buffer, "%s%s", prefix, reference_name); - - printf("[> NOTE <] %-31s %s\n", "Default output filename:", buffer); - - Output_Target = fopen(buffer, "wb+"); - - // 释放临时指针 - free(buffer); - } - } - - // 打开输入源文件(二进制形式,否则RF/CRLF引发计数问题) - Input_Source = fopen("./input.c", "rb"); - - // 段缓冲区 - char segment_buff[SEGMENT_BUFF_LENGTH] = {'\0'}; - - // 读取并复制参考文件直到 a2l MODULE 结尾 - while (f_getline(Input_Reference, segment_buff, sizeof(segment_buff)) != nullptr) - { - // 当前行为 a2l MODULE 结尾 - if (strstr(segment_buff, a2l_module_end)) - { - // 回退文件指针到上一行结尾 - fseek(Input_Reference, -2, SEEK_CUR); - while (fgetc(Input_Reference) != '\n') - fseek(Input_Reference, -2, SEEK_CUR); - break; - } - - // 输出行到文件 - // fprintf(Output_Target, segment_buff); // 太大300会段溢出 - for (int count = 0; count < SEGMENT_BUFF_LENGTH; count++) // 逐个输出 - { - fputc(segment_buff[count], Output_Target); - if (segment_buff[count] == '\n') - break; - } - - // 清空段缓冲区 - memset(segment_buff, '\0', sizeof(segment_buff)); - } - - list = listHead; - // 循环处理输入文件链表 - while (list->p_next != nullptr) - { - Input_Source = fopen(list->file_name, "rb"); - if (Input_Source == nullptr) - { - printf("[< FAIL >] Soure file \"%s\" load failed.\n", list->file_name); - - fclose(Input_Source); - list = (File_List *)list->p_next; - continue; - } - - printf("\n\n[- OK -] Soure file \"%s\" load succeed.\n", list->file_name); - - // 循环获取输入文件行 - while (f_getline(Input_Source, segment_buff, sizeof(segment_buff)) != nullptr) - { - // 当前行为观测量起始位行 - if (strstr(segment_buff, measurement_begin)) - { - printf("\n%s\n\n", measurement_begin); - fprintf(Output_Target, auto_generated_measurement_start); - - // 清空段缓冲区 - memset(segment_buff, '\0', sizeof(segment_buff)); - - while (true) - { - // 获取下一行 - f_getline(Input_Source, segment_buff, sizeof(segment_buff)); - - // 观测量结束行 - if (strstr(segment_buff, measurement_end)) - { - printf("\n%s\n\n", measurement_end); - fprintf(Output_Target, auto_generated_measurement_end); - break; - } - // 解析元素变量信息 - { - Element_Info info = solve_element(segment_buff); - - // 成功解析 - if (info.type != TYPE_NOT_SUPPORTED) - { - // 获取地址 - info = get_element_addr(info, Input_Map); - - // 调试信息 - if (info.addr != 0) - { - if (info.count == 0) - printf("[- OK -] 0x%08x %-20s %s;\n", info.addr, info.type_str, info.name); - else - printf("[- OK -] 0x%08x %-20s %s[%d];\n", info.addr, info.type_str, info.name, info.count); - } - else - { - if (info.count == 0) - printf("[< WARN >] 0x%08x %-20s %s;\n", info.addr, info.type_str, info.name); - else - printf("[< WARN >] 0x%08x %-20s %s[%d];\n", info.addr, info.type_str, info.name, info.count); - } - - // 单变量 - if (info.count == 0) - { - fprintf(Output_Target, "%s\r\n\r\n", "/begin MEASUREMENT"); // 观测量头 - - fprintf(Output_Target, " %s\r\n", info.name); // 名称 - fprintf(Output_Target, " \"auto generated\"\r\n"); // 描述 - fprintf(Output_Target, " %s\r\n", info.type_str); // 数据类型 - fprintf(Output_Target, " %s\r\n", "NO_COMPU_METHOD"); // 转换式(保留原始值) - fprintf(Output_Target, " %s\r\n", "0"); // 分辨率 - fprintf(Output_Target, " %s\r\n", "0"); // 精度误差 - fprintf(Output_Target, " %s\r\n", info.min_limit_str); // 下限 - fprintf(Output_Target, " %s\r\n", info.max_limit_str); // 上限 - fprintf(Output_Target, " %s 0x%08x\r\n\r\n", "ECU_ADDRESS", info.addr); // ECU 地址 - - fprintf(Output_Target, "%s\r\n\r\n", "/end MEASUREMENT"); // 观测量尾 - } - else - { - for (int count = 0; count < info.count; count++) - { - fprintf(Output_Target, "%s\r\n\r\n", "/begin MEASUREMENT"); // 观测量头 - - fprintf(Output_Target, " %s[%d]\r\n", info.name, count); // 名称 - fprintf(Output_Target, " \"auto generated\"\r\n"); // 描述 - fprintf(Output_Target, " %s\r\n", info.type_str); // 数据类型 - fprintf(Output_Target, " %s\r\n", "NO_COMPU_METHOD"); // 转换式(保留原始值) - fprintf(Output_Target, " %s\r\n", "0"); // 分辨率 - fprintf(Output_Target, " %s\r\n", "0"); // 精度误差 - fprintf(Output_Target, " %s\r\n", info.min_limit_str); // 下限 - fprintf(Output_Target, " %s\r\n", info.max_limit_str); // 上限 - fprintf(Output_Target, " %s 0x%08x\r\n\r\n", "ECU_ADDRESS", info.addr + count * info.element_len); // ECU 地址 - - fprintf(Output_Target, "%s\r\n\r\n", "/end MEASUREMENT"); // 观测量尾 - } - } - } - else if (info.name[0] != '\0') // 解析失败且变量名不为空 - { - if (info.count == 0) - printf("[< FAIL >] 0x%08x %-20s %s;\n", info.addr, info.type_str, info.name); - else - printf("[< FAIL >] 0x%08x %-20s %s[%d];\n", info.addr, info.type_str, info.name, info.count); - } - } - - // 清空段缓冲区 - memset(segment_buff, '\0', sizeof(segment_buff)); - } - } - - // 当前行为标定量起始位行 - if (strstr(segment_buff, calibration_begin)) - { - printf("\n%s\n\n", calibration_begin); - fprintf(Output_Target, auto_generated_calibration_start); - - // 清空段缓冲区 - memset(segment_buff, '\0', sizeof(segment_buff)); - - while (true) - { - // 获取下一行 - f_getline(Input_Source, segment_buff, sizeof(segment_buff)); - - // 标定量结束行 - if (strstr(segment_buff, calibration_end)) - { - printf("\n%s\n\n", calibration_end); - fprintf(Output_Target, auto_generated_calibration_end); - break; - } - // 解析元素变量信息 - { - Element_Info info = solve_element(segment_buff); - - // 成功解析 - if (info.type != TYPE_NOT_SUPPORTED) - { - // 获取地址 - info = get_element_addr(info, Input_Map); - - // 调试信息 - if (info.addr != 0) - { - if (info.count == 0) - printf("[- OK -] 0x%08x %-20s %s;\n", info.addr, info.type_str, info.name); - else - printf("[- OK -] 0x%08x %-20s %s[%d];\n", info.addr, info.type_str, info.name, info.count); - } - else - { - if (info.count == 0) - printf("[< WARN >] 0x%08x %-20s %s;\n", info.addr, info.type_str, info.name); - else - printf("[< WARN >] 0x%08x %-20s %s[%d];\n", info.addr, info.type_str, info.name, info.count); - } - - // 单变量 - if (info.count == 0) - { - fprintf(Output_Target, "%s\r\n\r\n", "/begin CHARACTERISTIC"); // 标定量头 - - fprintf(Output_Target, " %s\r\n", info.name); // 名称 - fprintf(Output_Target, " \"auto generated\"\r\n"); // 描述 - fprintf(Output_Target, " %s\r\n", "VALUE"); // 值类型(数值、数组、曲线) - fprintf(Output_Target, " 0x%08x\r\n", info.addr); // ECU 地址 - fprintf(Output_Target, " Scalar_%s\r\n", info.type_str); // 数据类型 - fprintf(Output_Target, " %s\r\n", "0"); // 允许最大差分 - fprintf(Output_Target, " %s\r\n", "NO_COMPU_METHOD"); // 转换式(保留原始值) - fprintf(Output_Target, " %s\r\n", info.min_limit_str); // 下限 - fprintf(Output_Target, " %s\r\n\r\n", info.max_limit_str); // 上限 - - fprintf(Output_Target, "%s\r\n\r\n", "/end CHARACTERISTIC"); // 标定量尾 - } - else - { - for (int count = 0; count < info.count; count++) - { - fprintf(Output_Target, "%s\r\n\r\n", "/begin CHARACTERISTIC"); // 标定量头 - - fprintf(Output_Target, " %s[%d]\r\n", info.name, count); // 名称 - fprintf(Output_Target, " \"auto generated\"\r\n"); // 描述 - fprintf(Output_Target, " %s\r\n", "VALUE"); // 值类型(数值、数组、曲线) - fprintf(Output_Target, " 0x%08x\r\n", info.addr + count * info.element_len); // ECU 地址 - fprintf(Output_Target, " Scalar_%s\r\n", info.type_str); // 数据类型 - fprintf(Output_Target, " %s\r\n", "0"); // 允许最大差分 - fprintf(Output_Target, " %s\r\n", "NO_COMPU_METHOD"); // 转换式(保留原始值) - fprintf(Output_Target, " %s\r\n", info.min_limit_str); // 下限 - fprintf(Output_Target, " %s\r\n\r\n", info.max_limit_str); // 上限 - - fprintf(Output_Target, "%s\r\n\r\n", "/end CHARACTERISTIC"); // 标定量尾 - } - } - } - else if (info.name[0] != '\0') // 解析失败且变量名不为空 - { - - if (info.count == 0) - printf("[< FAIL >] 0x%08x %-20s %s;\n", info.addr, info.type_str, info.name); - else - printf("[< FAIL >] 0x%08x %-20s %s[%d];\n", info.addr, info.type_str, info.name, info.count); - } - } - - // 清空段缓冲区 - memset(segment_buff, '\0', sizeof(segment_buff)); - } - } - } - - fclose(Input_Source); - list = (File_List *)list->p_next; - } - - // 清空段缓冲区 - memset(segment_buff, '\0', sizeof(segment_buff)); - - // 输出参考文件的剩余部分 - // 读取并复制参考文件直到 a2l MODULE 结尾 - while (f_getline(Input_Reference, segment_buff, sizeof(segment_buff)) != nullptr) - { - // 输出行到文件 - fprintf(Output_Target, segment_buff); - // 清空段缓冲区 - memset(segment_buff, '\0', sizeof(segment_buff)); - } - - // 关闭文件 - fcloseall(); - - // 释放文件指针 - list = listHead; - while (list != nullptr) - { - File_List *next = (File_List *)list->p_next; - free(list); - list = next; - } - - return 0; -} \ No newline at end of file