一、需求:获取下面头文件中所有的宏信息
#ifndef __USR_H__
#define __USR_H__
#include <stdio.h>
#define VERSION_STRING "2.05"
#define VERSION_STRING_LEN 32
#define SUCCESS 0x00
#define ERR_BASE 0x00
#define aTEST_ERR_BASE0 0x100
# define ERR_UNKNOWN 0x123
#define ERR_INVALID1 (1 + aTEST_ERR_BASE0)
#define ERR_INVALID2 ERR_BASE + 2
#define ERR_INVALID3 ERR_BASE + 3
#define ERR_INVALID4 4 + aTEST_ERR_BASE0
#define ERR_INVALID5 (ERR_BASE + 5)
#define BACKUP_DIR "/home/test"
#define RUN_DIR BACKUP_DIR"/.backup"
#define BASE_CONTENT "msgfrom"BACKUP_DIR
二、运行结果
三、具体程序(使用python)
# @Time : 2024/4/18 13:52
# @File : test.py
# @Author : 路人甲-甲
# @Version : 1.0
# @Site : https://blog.csdn.net/wankeng
# @Desc : 读取c语言中的.h头文件里定义的#define宏信息,并将其存入字典all_define_dict中
import os
import re
all_define_dict = {}
# 匹配格式为#define TEST_VALUE “ABC”的情况
def define_value_for_char(content):
global all_define_dict
m = re.match(r"([a-zA-Z0-9_]+)", content)
if m:
match_str = m.group(0)
match_str_len = len(match_str)
content = content[match_str_len:]
#去掉前面的空格
content = content.replace(" ", "").replace("\t","").replace("\n","")
# 匹配格式为#define TEST_VALUE “ABC”的情况
if content.startswith("\"") and content.endswith("\""):
m = re.search(r"[a-zA-Z0-9_/.]+", content)
if m:
return match_str, str(m.group(0))
elif content.startswith("\"") and not content.endswith("\""):
# 匹配格式为#define TEST_VALUE “ABC"/BASE_TEST_CHAR
m = re.search(r"[a-zA-Z0-9_/.]+", content)
if m:
before_str_len = len(m.group(0))
before_str = m.group(0)
var_name = content[before_str_len + 2:].strip()
if var_name in all_define_dict:
var_value = all_define_dict.get(var_name, None)
if var_value is not None:
return match_str, before_str + var_value
elif (not content.startswith("\"")) and content.endswith("\""):
# 匹配格式为#define TEST_VALUE BASE_TEST_CHAR“/test"
m = re.search(r"[a-zA-Z0-9_/.]+", content)
if m:
var_name_str_len = len(m.group(0))
var_name = m.group(0)
after_str = content[var_name_str_len + 1: -1].strip()
if var_name in all_define_dict:
var_value = all_define_dict.get(var_name, None)
if var_value is not None:
return match_str, var_value + after_str
return None, None
#匹配格式为#define TEST_VALUE (1 + TEST_VALUE)的情况
#匹配格式为#define TEST_VALUE (TEST_VALUE + 1)的情况
#匹配格式为TEST_VALUE + 1 没有括号的情况
def define_value_for_int_calculate(content):
global all_define_dict
m = re.match(r"([a-zA-Z0-9_]+)", content)
if m:
match_str = m.group(0)
match_str_len = len(match_str)
content = content[match_str_len:]
m = re.match(r"\s+(\([a-zA-Z0-9_])", content)
if m:
sub_match_len = len(m.group(0))
#去掉括号和换行符
temp_value = content[sub_match_len - 1: -2]
sub_m = re.match(r"\w+", temp_value)
before_var_value = None
final_int_value = None
if sub_m:
# 匹配格式为(TEST_VALUE + 1)的情况
before_var_name = sub_m.group(0)
before_var_value = all_define_dict.get(before_var_name, None)
if before_var_value is None:
# 匹配格式为(1 + TEST_VALUE)的情况
sub_m = re.match(r"(\d)+\s+", temp_value)
if sub_m:
sub_match_len = len(sub_m.group(0))
sub_content = temp_value[sub_match_len:]
search_m = re.search(r"(\w+)", sub_content)
if search_m:
before_var_name = search_m.group(0)
before_var_value = all_define_dict.get(before_var_name, None)
if before_var_value is not None:
#计算(TEST_VALUE+1)的值
final_int_value = eval(temp_value.replace(before_var_name, str(before_var_value)))
# print(f'{match_str}={final_int_value}={temp_value}={before_var_value}=end')
if final_int_value is not None:
return match_str, final_int_value
else:
#匹配格式为TEST_VALUE + 1 没有括号的情况
before_var_value = None
final_int_value = None
m = re.search(r"[a-zA-Z0-9_]+", content)
if m:
sub_match_len = len(m.group(0))
#去掉括号和换行符
temp_value = content[sub_match_len -2: -1]
if temp_value.startswith("\"") or temp_value.endswith("\""):
return None, None
before_var_name = m.group(0)
before_var_value = all_define_dict.get(before_var_name, None)
if before_var_value is not None:
#计算TEST_VALUE + 1的值
final_int_value = eval(temp_value.replace(before_var_name, str(before_var_value)))
# print(f'{match_str}={final_int_value}={temp_value}={before_var_value}=end')
if final_int_value is not None:
return match_str, final_int_value
return None, None
# 匹配格式为#define TEST_VALUE 1的情况
# 匹配格式为#define TEST_VALUE 1 + BEFORE_TEST_VALUE
def define_value_for_int(content):
global all_define_dict
m = re.match(r"([a-zA-Z0-9_]+)", content)
if m:
match_str = m.group(0)
match_str_len = len(match_str)
content = content[match_str_len:]
m = re.match(r"\s+(\d)", content)
# print(f'---{match_str}={m}={content}={match_str_len}=end')
if m:
sub_match_len = len(m.group(0))
value_contents = content[sub_match_len - 1: -1]
has_space_or_char = re.search(r"[a-zA-Z_]+", value_contents)
if has_space_or_char:
# 匹配格式为#define TEST_VALUE 1 + BEFORE_TEST_VALUE
before_var_name = value_contents[len(value_contents) - len(has_space_or_char.group(0)) - 1:]
# 去掉有可能的空格
before_var_name = before_var_name.strip()
if before_var_name in all_define_dict:
before_var_value = all_define_dict.get(before_var_name, None)
if before_var_value is not None:
# 计算1 + BEFORE_TEST_VALUE的值
final_int_value = eval(value_contents.replace(before_var_name, str(before_var_value)))
if final_int_value is not None:
return match_str, final_int_value
else:
# 匹配格式为#define TEST_VALUE 1 单纯的数字
final_int_value = int(content[sub_match_len - 1: -1])
if final_int_value is not None:
return match_str, final_int_value
return None, None
# 匹配格式为#define TEST_VALUE 0x1的情况
def define_value_for_hex(content):
m = re.match(r"([a-zA-Z0-9_]+)", content)
if m:
match_str = m.group(0)
match_str_len = len(match_str)
content = content[match_str_len:]
m = re.match(r"\s+0x", content)
if m:
sub_match_len = len(m.group(0))
dist_value_to_int = int(content[sub_match_len:sub_match_len + 8], 16)
if dist_value_to_int is not None and len(match_str) > 0:
return match_str, dist_value_to_int
return None, None
def get_define_dict(org_content):
key = None
value = None
m = re.match(r"(#define\s+|# define\s+)", org_content)
if m:
x = m.group(0)
s = len(x)
line = org_content[s:]
key, value = define_value_for_hex(line)
if key is None and value is None:
# 单纯的数字
key, value = define_value_for_int(line)
if key is None and value is None:
# 带有运算符的数字
key, value = define_value_for_int_calculate(line)
if key is None and value is None:
# 字符串
key, value = define_value_for_char(line)
return key, value
def loadFromC(fn):
global all_define_dict
with open(fn, "r",encoding='utf-8') as reg_file:
for line in reg_file.readlines():
if line is None or len(line) == 0 or line.startswith("\n") or line.startswith("\r\n" or line.startswith("^M")):
continue
key,value = get_define_dict(line)
if key is not None and value is not None:
all_define_dict[key] = value
reg_file.close()
return all_define_dict
fn = "./test.h"
ret_dict = loadFromC(fn)
print(len(ret_dict))
for k, v in ret_dict.items():
print(k, v)
四、后续
我们可以思考,根据上面的方法,可以获取此.h文件里定义的方法、结构体、枚举类等信息。我们可以将此信息拿到之后测试这些方法。具体实现方式请私信。