Как я могу создать список значений #define из кода C?

У меня есть код, который содержит много сложных кодов ошибок #define, которые нелегко декодировать, поскольку они вложены в несколько уровней.

Есть ли какой-нибудь элегантный способ получить список #defines с их окончательными числовыми значениями (или какими бы то ни было еще)?

В качестве примера:

<header1.h>
#define CREATE_ERROR_CODE(class, sc, code) ((class << 16) & (sc << 8) & code)
#define EMI_MAX 16

<header2.h>
#define MI_1 EMI_MAX

<header3.h>
#define MODULE_ERROR_CLASS MI_1
#define MODULE_ERROR_SUBCLASS 1
#define ERROR_FOO CREATE_ERROR_CODE(MODULE_ERROR_CLASS, MODULE_ERROR_SUBCLASS, 1)

У меня было бы большое количество #defines, совпадающих с ERROR_[\w_]+, которые я хотел бы перечислить, чтобы у меня всегда был текущий список кодов ошибок, которые программа может вывести. Мне нужно числовое значение, потому что это все, что программа распечатает (и нет, вместо этого нельзя распечатать строку).

Предложения для gcc или любого другого компилятора были бы полезны.

6 ответов

Решение

Я думаю, что решение - это комбинация ответов @nmichaels и @ aschepler.

Используйте опцию -cc для gcc, чтобы получить список макросов. Используйте perl или awk или что-то еще, чтобы создать 2 файла из этого списка:

1) Macros.h, содержащий только #defines.

2) Codes.c, который содержит

#include "Macros.h"

ERROR_FOO = "ERROR_FOO"
ERROR_BAR = "ERROR_BAR"

(т.е. извлекать каждый #define ERROR_x в строку с макросом и строкой.

сейчас беги gcc -E Codes.c, Это должно создать файл со всеми расширенными макросами. Вывод должен выглядеть примерно так

1 = "ERROR_FOO"
2 = "ERROR_BAR"

У меня нет gcc под рукой, так что не проверял это...

ССЗ -dM Вариант препроцессора может получить то, что вы хотите.

Программа "Coan" выглядит как инструмент, который вы ищете. У него есть подкоманда defs, которая описывается как:

defs [ОПЦИЯ...] [файл...] [каталог...]

Выбрать #define а также #undef директивы из входных файлов в соответствии с параметрами и сообщать о них на стандартный вывод в соответствии с параметрами.

Смотрите цитируемый URL для получения дополнительной информации о параметрах. Получить код здесь.

Если у вас есть полный список макросов, которые вы хотите увидеть, и все они числовые, вы можете скомпилировать и запустить короткую программу только для этой цели:

#include <header3.h>
#include <stdio.h>

#define SHOW(x) printf(#x " = %lld\n", (long long int) x)

int main(void) {
    SHOW(ERROR_FOO);
    /*...*/
    return 0;
}

Как уже упоминалось @nmichaels, GCC's -d флаги могут помочь отобразить этот список макросов.

Есть ли какой-нибудь элегантный способ получить список #defines с их окончательными числовыми значениями?

Для разных уровней элегантности, вроде.

#!/bin/bash

file="mount.c";
for macro in $(grep -Po '(?<=#define)\s+(\S+)' "$file"); do
    echo -en "$macro: ";
    echo -en '#include "'"$file"'"\n'"$macro\n" | \
    cpp -E -P -x c ${CPPFLAGS} - | tail -n1;
done;

Не надежный (#define \ \n macro(x) ... не был бы пойман - но никакой стиль, который я видел, делает это).

Вот небольшое креативное решение:

Напишите программу, которая сопоставит все ваши идентификаторы с регулярным выражением (например, \#define :b+(?<NAME>[0-9_A-Za-z]+):b+(?<VALUE>[^(].+)$ в.NET), а затем создайте еще один файл C с совпадающими именами:

void main() {
    /*my_define_1*/ my_define_1;
    /*my_define_2*/ my_define_2;
    //...
}

Затем предварительно обработайте файл, используя параметр /C /P (для VC++), и вы должны заменить все эти значения значениями. Затем используйте другое регулярное выражение, чтобы поменять местами, и поместите комментарии перед значениями в #define формат - теперь у вас есть список #define"S!

(Вы можете сделать что-то подобное с GCC.)

Другие вопросы по тегам