structure of typedef and constant of #define can be solve now.
This commit is contained in:
parent
aadb2bf692
commit
3322c4cdda
34
Inc/Config.hpp
Normal file
34
Inc/Config.hpp
Normal file
@ -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
|
22
Inc/Core_Functions.hpp
Normal file
22
Inc/Core_Functions.hpp
Normal file
@ -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
|
25
Inc/Global_Variables.hpp
Normal file
25
Inc/Global_Variables.hpp
Normal file
@ -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
|
42
Inc/Tool_Functions.hpp
Normal file
42
Inc/Tool_Functions.hpp
Normal file
@ -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
|
91
Inc/Type_Descriptions.hpp
Normal file
91
Inc/Type_Descriptions.hpp
Normal file
@ -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
|
157
Makefile
Normal file
157
Makefile
Normal file
@ -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)
|
1014
Src/Core_Functions.cpp
Normal file
1014
Src/Core_Functions.cpp
Normal file
File diff suppressed because it is too large
Load Diff
21
Src/Global_Variables.cpp
Normal file
21
Src/Global_Variables.cpp
Normal file
@ -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;
|
37
Src/Main.cpp
Normal file
37
Src/Main.cpp
Normal file
@ -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;
|
||||
}
|
616
Src/Tool_Functions.cpp
Normal file
616
Src/Tool_Functions.cpp
Normal file
@ -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);
|
||||
}
|
688
main.cpp
688
main.cpp
@ -1,688 +0,0 @@
|
||||
#include <iostream>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user