동적 소스 코드의 조건 컴파일링 매크로 제거
원본 코드에 '매크로 프로필' 에 나타나지 않은 조건이 있으면 매크로를 컴파일해야 합니다!
다음 코드는 창고 구조를 사용하여 완성됩니다. #ifdef 또는 #ifndef를 만나면 창고에 들어가고 #endif를 만나면 창고에서 나옵니다.
/**********************************************************************
* strip_macro.c
*
* Wang Dongquan <[email protected]>
* Time-stamp: <>
* Description:
*
* strip undefined macro parts according to config_macro file
*
* gcc - O2 - W - Wall strip_macro.c - o strip_macro
*
* 1. config_macro file format is line by line which likes 'variable = value',
* value must be 'y' or 'n', and 'y' means defined, 'n' means undefined
*
* 2. src_file contrains macro parts
*
* 3. dst_file is generated by stripping undefined macro parts of src_file
***********************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_STACK_LAYER 128
#define MAX_LINE_BUFFER 2048
#define MAX_MACRO_NUMBER 256
#define MAX_MACRO_CHAR 128
/* macro conf */
struct macro_def {
char macro[MAX_MACRO_CHAR];
unsigned char len;
unsigned char defined;
unsigned short value;
};
enum {
MACRO_PUSH = 0,
MACRO_POP,
MACRO_ELSE,
MACRO_SIMPLE,
};
enum {
MACRO_UNDEFINED = 0,
MACRO_DEFINED,
MACRO_IGNORED,
};
static inline char *pass_space(char *line, int len)
{
int i = 0;
for (i = 0;i < len;i++) {
if (line[i] != ' '
&& line[i] != '\t'
&& line[i] != '
'
&& line[i] != '\r'
&& line[i] != '\0')
break;
}
return line + i;
}
static inline char *pass_word(char *line, int len)
{
int i = 0;
for (i = 0;i < len;i++) {
if (line[i] == ' '
|| line[i] == '\t'
|| line[i] == '
'
|| line[i] == '\r'
|| line[i] == '\0')
break;
}
return line + i;
}
static int line_word(char *line, int len, char **word, int *word_len)
{
char *p = line;
*word_len = 0;
p = pass_space(line, len);
if (p > line + len)
return -1;
*word = p;
p = pass_word(p, line + len - p);
if (p > line + len)
return -1;
*word_len = p - *word;
return 0;
}
static void usage()
{
printf("strip_macro config_file src_file dst_file
");
printf("config_file: file format is line by line which likes 'variable = value'
");
printf("src_file : source file including variable macros defined or undefined in config_file
");
printf("dst_file : output file stripped according to config_file
");
}
static int config_macro(FILE *conf, struct macro_def **macro)
{
char *p = NULL;
char line[MAX_LINE_BUFFER];
int i = 0, len = 0;
char *v = NULL, *vv = NULL;
int v_len = 0, vv_len = 0;
while (fgets(line, MAX_LINE_BUFFER, conf)) {
len = strlen(line);
p = pass_space(line, len);
if (p >= line + len)
continue;
if (*p == '#')
continue;
p = strchr(line, '=');
if (p == NULL)
continue;
*p = '\0';
line_word(line, len, &v, &v_len);
line_word(p + 1, line + len - p - 1, &vv, &vv_len);
if (v_len > 0 && vv_len > 0 && v && vv) {
macro[i] = (struct macro_def *)calloc(1, sizeof(struct macro_def));
if (macro[i] == NULL)
return -1;
strncpy(macro[i]->macro, v, v_len);
macro[i]->len = v_len;
if (*vv == 'y')
macro[i]->defined = MACRO_DEFINED;
else
macro[i]->defined = MACRO_UNDEFINED;
if (++i > MAX_MACRO_NUMBER)
return -1;
}
}
return 0;
}
static int judge_macro_var(char *var, int var_len, struct macro_def **macro)
{
int defined = MACRO_IGNORED, i = 0;
for (i = 0;macro[i] != NULL;i++) {
if (var_len == macro[i]->len && memcmp(var, macro[i]->macro, var_len) == 0) {
defined = macro[i]->defined;
break;
}
}
return defined;
}
static int judge_macro(char *def, int def_len, char *var, int var_len, struct macro_def **macro, int *defined)
{
int ret = MACRO_SIMPLE;
if ((def_len == sizeof("#ifdef") - 1)
&& memcmp(def, "#ifdef", sizeof("#ifdef") - 1) == 0) {
*defined = judge_macro_var(var, var_len, macro);
ret = MACRO_PUSH;
}
else if ((def_len == sizeof("#ifndef") - 1)
&& memcmp(def, "#ifndef", sizeof("#ifndef") - 1) == 0) {
*defined = judge_macro_var(var, var_len, macro);
if (*defined != MACRO_IGNORED)
*defined = ((*defined == MACRO_DEFINED) ? MACRO_UNDEFINED : MACRO_DEFINED);
ret = MACRO_PUSH;
}
else if ((def_len == sizeof("#endif") - 1)
&& memcmp(def, "#endif", sizeof("#endif") - 1) == 0) {
ret = MACRO_POP;
}
else if ((def_len == sizeof("#else") - 1)
&& memcmp(def, "#else", sizeof("#else") - 1) == 0) {
ret = MACRO_ELSE;
}
return ret;
}
static void judge_printf_line(FILE *dst, char *line, char *stack, int curr_stack, int simple_string)
{
int i = 0;
if (simple_string == 1
|| stack[curr_stack] == MACRO_IGNORED) {
for (i = 1;i <= curr_stack;i++) {
if (stack[i] == MACRO_UNDEFINED)
break;
}
if (i > curr_stack)
fprintf(dst, "%s", line);
}
}
static int strip_macro(struct macro_def **macro, FILE *src, FILE *dst)
{
int ret = 0, defined = MACRO_IGNORED;
char line[MAX_LINE_BUFFER];
int len = 0;
char *def = NULL, *var = NULL;
int def_len = 0, var_len = 0;
char stack[MAX_STACK_LAYER];
int curr_stack = 0;
while (fgets(line, MAX_LINE_BUFFER, src)) {
len = strlen(line);
if (line_word(line, len, &def, &def_len))
return -1;
if (line_word(def + def_len, line + len - def - def_len, &var, &var_len))
return -1;
ret = judge_macro(def, def_len, var, var_len, macro, &defined);
switch (ret) {
case MACRO_PUSH:
if (curr_stack >= MAX_STACK_LAYER - 1)
return -1;
stack[++curr_stack] = defined;
judge_printf_line(dst, line, stack, curr_stack, 0);
break;
case MACRO_POP:
judge_printf_line(dst, line, stack, curr_stack, 0);
curr_stack--;
break;
case MACRO_ELSE:
judge_printf_line(dst, line, stack, curr_stack, 0);
if (stack[curr_stack] != MACRO_IGNORED)
stack[curr_stack] =
((stack[curr_stack] == MACRO_DEFINED) ? MACRO_UNDEFINED : MACRO_DEFINED);
break;
default:
judge_printf_line(dst, line, stack, curr_stack, 1);
break;
}
}
return 0;
}
int main(int argc, char *argv[])
{
int ret = -1;
struct macro_def **macro = NULL;
FILE *conf = NULL, *src = NULL, *dst = NULL;
if (argc != 4) {
usage();
return -1;
}
conf = fopen(argv[1], "r");
if (conf == NULL)
goto end;
src = fopen(argv[2], "r");
if (src == NULL)
goto end;
dst = fopen(argv[3], "w+");
if (dst == NULL)
goto end;
macro = (struct macro_def **)calloc(MAX_MACRO_NUMBER, sizeof(struct macro_def *));
if (macro == NULL)
goto end;
/* get all config macros */
ret = config_macro(conf, macro);
if (ret != 0) {
ret = -1;
goto end;
}
ret = strip_macro(macro, src, dst);
end:
if (conf)
fclose(conf);
if (src)
fclose(src);
if (dst)
fclose(dst);
if (macro) {
int i = 0;
for (i = 0;i < MAX_MACRO_NUMBER;i++) {
if (macro[i])
free(macro[i]);
else
break;
}
free(macro);
}
return ret;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Ruby의 구조체 클래스은 접근자 메서드가 있는 속성 모음입니다. 클래스를 명시적으로 작성할 필요 없이. Struct 클래스는 구성원 및 해당 값 집합을 포함하는 새 하위 클래스를 생성합니다. 각 멤버에 대해 #attr_accessor 와...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.