Как я могу создать список значений #define из кода C? - PullRequest
5 голосов
/ 30 декабря 2010

У меня есть код, который содержит много сложных кодов ошибок #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)

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

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

Ответы [ 6 ]

7 голосов
/ 30 декабря 2010
Опция препроцессора

GCC -dM может дать вам то, что вы хотите.

4 голосов
/ 04 января 2011

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

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

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

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, поэтому я не проверял это ...

2 голосов
/ 01 января 2011

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

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

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

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

1 голос
/ 04 января 2011

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

Напишите программу, которая будет сопоставлять все ваши идентификаторы с регулярным выражением (например, \#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!

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

1 голос
/ 30 декабря 2010

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

#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 -d могут помочь отобразить этот список макросов.

0 голосов
/ 05 января 2011

Есть ли какой-нибудь элегантный способ получить список #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) ... не будет пойман - но стиль, который я видел, не подходит , ).

...