255 lines
8.7 KiB
C
255 lines
8.7 KiB
C
#include <stdio.h>
|
|||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
#include <ctype.h>
|
||
|
|
|
||
|
|
#define MAX_LINE_LEN 2048
|
||
|
|
#define MAX_PARAMS 16
|
||
|
|
#define MAX_NAME_LEN 64
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
char type[MAX_NAME_LEN];
|
||
|
|
char name[MAX_NAME_LEN];
|
||
|
|
} ParamInfo;
|
||
|
|
|
||
|
|
// 辅助函数:去除两端空格
|
||
|
|
void trim(char *str) {
|
||
|
|
char *end;
|
||
|
|
while (isspace((unsigned char)*str)) str++;
|
||
|
|
if (*str == 0) return;
|
||
|
|
end = str + strlen(str) - 1;
|
||
|
|
while (end > str && isspace((unsigned char)*end)) end--;
|
||
|
|
*(end + 1) = '\0';
|
||
|
|
memmove(str - (str - (str + (isspace((unsigned char)*str) ? 1 : 0))), str, strlen(str) + 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 辅助函数:精准提取类型强转
|
||
|
|
// 例如:"(int)(short)LOWORD(lParam)" -> 提取出 "int"
|
||
|
|
// 如果只是 "(hwnd)",由于 hwnd 是变量名而非合法类型,会通过 default_name 转换成 "HWND"
|
||
|
|
void extract_first_type(const char *src, char *dest, const char *default_name) {
|
||
|
|
dest[0] = '\0';
|
||
|
|
const char *p = src;
|
||
|
|
|
||
|
|
// 跳过前面的空格
|
||
|
|
while (*p && isspace((unsigned char)*p)) p++;
|
||
|
|
|
||
|
|
if (*p == '(') {
|
||
|
|
p++; // 进入第一个左括号
|
||
|
|
int i = 0;
|
||
|
|
while (*p && *p != ')') {
|
||
|
|
dest[i++] = *p++;
|
||
|
|
}
|
||
|
|
dest[i] = '\0';
|
||
|
|
trim(dest);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 关键修正:如果提取出来的“类型”和变量名一样(例如把 (hwnd) 误判为类型为 hwnd),或者为空
|
||
|
|
// 则通过名字来给它赋予 Windows 标准类型
|
||
|
|
if (strlen(dest) == 0 || strcmp(dest, default_name) == 0 || strcmp(dest, "fn") == 0) {
|
||
|
|
if (strstr(default_name, "hwnd")) strcpy(dest, "HWND");
|
||
|
|
else if (strstr(default_name, "lParam")) strcpy(dest, "LPARAM");
|
||
|
|
else if (strstr(default_name, "wParam")) strcpy(dest, "WPARAM");
|
||
|
|
else if (strstr(default_name, "vk")) strcpy(dest, "UINT");
|
||
|
|
else strcpy(dest, "int"); // 默认兜底
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 核心解析函数
|
||
|
|
void process_macros(const char *handle_line, const char *forward_line) {
|
||
|
|
char msg_name[MAX_NAME_LEN] = {0};
|
||
|
|
char return_type[MAX_NAME_LEN] = {0};
|
||
|
|
|
||
|
|
// 1. 提取 MsgName
|
||
|
|
char *msg_pos = strstr(handle_line, "HANDLE_WM_");
|
||
|
|
if (!msg_pos) return;
|
||
|
|
msg_pos += 10;
|
||
|
|
int len = 0;
|
||
|
|
while (isalnum((unsigned char)msg_pos[len]) || msg_pos[len] == '_') {
|
||
|
|
msg_name[len] = msg_pos[len];
|
||
|
|
len++;
|
||
|
|
}
|
||
|
|
msg_name[len] = '\0';
|
||
|
|
|
||
|
|
// 2. 提取 FORWARD_WM_xxx 宏括号定义中的所有参数名
|
||
|
|
char forward_search[MAX_NAME_LEN + 20];
|
||
|
|
sprintf(forward_search, "FORWARD_WM_%s(", msg_name);
|
||
|
|
char *f_param_start = strstr(forward_line, forward_search);
|
||
|
|
if (!f_param_start) return;
|
||
|
|
f_param_start += strlen(forward_search);
|
||
|
|
|
||
|
|
char f_params_buf[MAX_LINE_LEN] = {0};
|
||
|
|
int f_len = 0;
|
||
|
|
int f_depth = 1;
|
||
|
|
// 严格按括号匹配提取参数声明区间,避免被后续宏体干扰
|
||
|
|
while (f_param_start[f_len] && f_depth > 0) {
|
||
|
|
if (f_param_start[f_len] == '(') f_depth++;
|
||
|
|
if (f_param_start[f_len] == ')') f_depth--;
|
||
|
|
if (f_depth > 0) {
|
||
|
|
f_params_buf[f_len] = f_param_start[f_len];
|
||
|
|
f_len++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
f_params_buf[f_len] = '\0';
|
||
|
|
|
||
|
|
// 切分 FORWARD 宏头部的参数名
|
||
|
|
char f_param_names[MAX_PARAMS][MAX_NAME_LEN];
|
||
|
|
int f_param_count = 0;
|
||
|
|
|
||
|
|
// 修正点:手动切分逗号,不使用会破坏内部状态的 strtok
|
||
|
|
char *f_ptr = f_params_buf;
|
||
|
|
char *f_comma;
|
||
|
|
while ((f_comma = strchr(f_ptr, ',')) != NULL && f_param_count < MAX_PARAMS) {
|
||
|
|
*f_comma = '\0';
|
||
|
|
trim(f_ptr);
|
||
|
|
if (strcmp(f_ptr, "fn") != 0 && strlen(f_ptr) > 0) {
|
||
|
|
strcpy(f_param_names[f_param_count++], f_ptr);
|
||
|
|
}
|
||
|
|
f_ptr = f_comma + 1;
|
||
|
|
}
|
||
|
|
trim(f_ptr);
|
||
|
|
if (strcmp(f_ptr, "fn") != 0 && strlen(f_ptr) > 0) {
|
||
|
|
strcpy(f_param_names[f_param_count++], f_ptr);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 3. 解析 return_type
|
||
|
|
char *fn_pos = strstr(forward_line, "(fn)");
|
||
|
|
if (fn_pos) {
|
||
|
|
char *search_start = strstr(forward_line, forward_search);
|
||
|
|
if (search_start) {
|
||
|
|
char *body_start = strchr(search_start, ')');
|
||
|
|
if (body_start && body_start < fn_pos) {
|
||
|
|
char return_buf[MAX_LINE_LEN] = {0};
|
||
|
|
strncpy(return_buf, body_start + 1, fn_pos - (body_start + 1));
|
||
|
|
return_buf[fn_pos - (body_start + 1)] = '\0';
|
||
|
|
extract_first_type(return_buf, return_type, "");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (strlen(return_type) == 0 || strcmp(return_type, "void") == 0) {
|
||
|
|
strcpy(return_type, "void");
|
||
|
|
}
|
||
|
|
|
||
|
|
// 4 & 5 & 6. 解析 HANDLE_WM_xxx 中 fn(...) 内部调用
|
||
|
|
char *fn_call = strstr(handle_line, "(fn)(");
|
||
|
|
if (!fn_call) fn_call = strstr(handle_line, "fn(");
|
||
|
|
|
||
|
|
ParamInfo final_params[MAX_PARAMS];
|
||
|
|
int final_param_count = 0;
|
||
|
|
|
||
|
|
if (fn_call) {
|
||
|
|
if (strncmp(fn_call, "(fn)(", 5) == 0) {
|
||
|
|
fn_call += 5; // 移动到 (fn)( 之后的具体参数部分
|
||
|
|
} else {
|
||
|
|
fn_call += 3; // 移动到 fn( 之后的具体参数部分
|
||
|
|
}
|
||
|
|
|
||
|
|
// 匹配提取出整个括号内的参数段表达式
|
||
|
|
char h_body_buf[MAX_LINE_LEN] = {0};
|
||
|
|
int h_depth = 1;
|
||
|
|
int h_idx = 0;
|
||
|
|
while (fn_call[h_idx] && h_depth > 0) {
|
||
|
|
if (fn_call[h_idx] == '(') h_depth++;
|
||
|
|
if (fn_call[h_idx] == ')') h_depth--;
|
||
|
|
if (h_depth > 0) {
|
||
|
|
h_body_buf[h_idx] = fn_call[h_idx];
|
||
|
|
h_idx++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
h_body_buf[h_idx] = '\0';
|
||
|
|
|
||
|
|
// 核心修正:按照外层零嵌套深度的逗号切分出各个独立的传参表达式
|
||
|
|
char *expressions[MAX_PARAMS];
|
||
|
|
int exp_count = 0;
|
||
|
|
char *start = h_body_buf;
|
||
|
|
int depth_count = 0;
|
||
|
|
for (int i = 0; h_body_buf[i] != '\0'; i++) {
|
||
|
|
if (h_body_buf[i] == '(') depth_count++;
|
||
|
|
else if (h_body_buf[i] == ')') depth_count--;
|
||
|
|
else if (h_body_buf[i] == ',' && depth_count == 0) {
|
||
|
|
h_body_buf[i] = '\0';
|
||
|
|
expressions[exp_count++] = start;
|
||
|
|
start = &h_body_buf[i + 1];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
expressions[exp_count++] = start;
|
||
|
|
|
||
|
|
// 根据表达式与 FORWARD 的名字进行最终映射与插入
|
||
|
|
int f_idx = 0;
|
||
|
|
for (int i = 0; i < exp_count; i++) {
|
||
|
|
trim(expressions[i]);
|
||
|
|
if (strlen(expressions[i]) == 0) continue;
|
||
|
|
|
||
|
|
// 4. 对 HANDLE_WM_xxx 中 TRUE 所在位置,直接生成 fBool 参数名插入
|
||
|
|
if (strcmp(expressions[i], "TRUE") == 0 || strcmp(expressions[i], "FALSE") == 0) {
|
||
|
|
strcpy(final_params[final_param_count].name, "fBool");
|
||
|
|
strcpy(final_params[final_param_count].type, "WINBOOL");
|
||
|
|
final_param_count++;
|
||
|
|
} else {
|
||
|
|
if (f_idx < f_param_count) {
|
||
|
|
strcpy(final_params[final_param_count].name, f_param_names[f_idx]);
|
||
|
|
|
||
|
|
// 5 & 6. 提取每个参数对应的真实强转类型
|
||
|
|
char parsed_type[MAX_NAME_LEN] = {0};
|
||
|
|
extract_first_type(expressions[i], parsed_type, f_param_names[f_idx]);
|
||
|
|
|
||
|
|
strcpy(final_params[final_param_count].type, parsed_type);
|
||
|
|
final_param_count++;
|
||
|
|
f_idx++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 7. 生成格式化内容输出
|
||
|
|
printf("#define c_WinGUI_EventFn_WM_%s(fn) \\\n %s fn(", msg_name, return_type);
|
||
|
|
for (int i = 0; i < final_param_count; i++) {
|
||
|
|
printf("%s %s", final_params[i].type, final_params[i].name);
|
||
|
|
if (i < final_param_count - 1) {
|
||
|
|
printf(", ");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
printf(")\n\n");
|
||
|
|
}
|
||
|
|
|
||
|
|
int main(int argc, char *argv[]) {
|
||
|
|
if (argc < 2) {
|
||
|
|
fprintf(stderr, "使用方法: %s <windowsx.h 路径>\n", argv[0]);
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
FILE *fp = fopen(argv[1], "r");
|
||
|
|
if (!fp) {
|
||
|
|
perror("打不开文件");
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
char line[MAX_LINE_LEN];
|
||
|
|
char cached_handle[MAX_LINE_LEN] = {0};
|
||
|
|
char current_msg[MAX_NAME_LEN] = {0};
|
||
|
|
|
||
|
|
while (fgets(line, sizeof(line), fp)) {
|
||
|
|
line[strcspn(line, "\r\n")] = 0;
|
||
|
|
|
||
|
|
if (strstr(line, "#define HANDLE_WM_")) {
|
||
|
|
strcpy(cached_handle, line);
|
||
|
|
char *p = strstr(line, "HANDLE_WM_") + 10;
|
||
|
|
int idx = 0;
|
||
|
|
while (isalnum((unsigned char)p[idx]) || p[idx] == '_') {
|
||
|
|
current_msg[idx] = p[idx];
|
||
|
|
idx++;
|
||
|
|
}
|
||
|
|
current_msg[idx] = '\0';
|
||
|
|
}
|
||
|
|
else if (strstr(line, "#define FORWARD_WM_")) {
|
||
|
|
if (strlen(current_msg) > 0 && strstr(line, current_msg)) {
|
||
|
|
process_macros(cached_handle, line);
|
||
|
|
cached_handle[0] = '\0';
|
||
|
|
current_msg[0] = '\0';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fclose(fp);
|
||
|
|
return 0;
|
||
|
|
}
|