동적 소스 코드의 조건 컴파일링 매크로 제거

원본 코드에는 많은 조건의 매크로 코드 블록이 있는데 코드가 고객에게 발표될 때 고객의 설정에 따라 동적으로 정의되지 않은 매크로 코드 블록을 제거하고 정의된 매크로 코드 블록을 보존해야 한다.
원본 코드에 '매크로 프로필' 에 나타나지 않은 조건이 있으면 매크로를 컴파일해야 합니다!
다음 코드는 창고 구조를 사용하여 완성됩니다. #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; }

좋은 웹페이지 즐겨찾기