Определение типов всех переменных в проекте C - PullRequest
7 голосов
/ 22 апреля 2009

Я пытаюсь написать программу для проверки того, что некоторый исходный код на C соответствует соглашению об именовании переменных. Для этого мне нужно проанализировать исходный код и определить тип всех локальных и глобальных переменных.

Конечным результатом почти наверняка будет программа на Python, но инструментом для анализа кода может быть либо модуль Python, либо приложение, которое выдает отчет, который легко анализировать. В качестве альтернативы (подробнее об этом ниже) это может быть способ извлечения информации из компилятора (в виде отчета или подобного). В случае, если это будет полезно, по всей вероятности, это будет компилятор Keil ARM.

Я экспериментировал с ctags , и это очень полезно для нахождения всех определений типов, определений макросов и т. Д., Но он не дает прямого способа найти тип переменных, особенно когда определение разбито на несколько строк (что, я надеюсь, не будет!).

Примеры могут включать в себя:

static volatile u8 var1; // should be flagged as static and volatile and a u8 (typedef of unsigned 8-bit integer)
volatile   /* comments */   
    static /* inserted just to make life */
        u8 /* difficult! */   var2 =
        (u8) 72
           ; // likewise (nasty syntax, but technically valid C)
const uint_16t *pointer1;  // flagged as a pointer to a constant uint_16t
int * const pointer2; // flagged as a constant pointer to an int
const char * const pointer3; // flagged as a constant pointer to a constant char
static MyTypedefTYPE var3; // flagged as a MyTypedefTYPE variable
u8 var4, var5, var6 = 72;
int *array1[SOME_LENGTH]; // flagged as an array of pointers to integers
char array2[FIRST_DIM][72]; // flagged as an array of arrays of type char

и т. Д. И т. Д.

Также необходимо определить, являются ли они локальными или глобальными переменными / областью действия файла (что могут делать ctags), и если они локальные, в идеале мне бы хотелось, чтобы имя функции, в которой они были объявлены .

Кроме того, я хотел бы сделать то же самое с функциями: определить тип возвращаемого значения, являются ли они статическими, а также тип и имя всех их аргументов.

К сожалению, это довольно сложно с синтаксисом языка Си, поскольку существует определенная гибкость в порядке расположения параметров и большая гибкость в количестве пустого пространства, которое допускается между параметрами. Я поиграл с использованием некоторых причудливых регулярных выражений для выполнения работы, но это далеко от идеала, поскольку существует так много разных ситуаций, которые можно применять, поэтому регулярные выражения быстро становятся неуправляемыми. Я не могу не думать, что компиляторы должны быть в состоянии сделать это (чтобы работать!), Поэтому мне было интересно, можно ли было извлечь эту информацию. Компилятор Keil создает файл «.crf» для каждого скомпилированного исходного файла, и он содержит все переменные, объявленные в этом файле, но это двоичный формат, и я не могу найти никакой информации о том, как это проанализировать. файл. В качестве альтернативы был бы идеален способ получения информации из ctags.

Буду признателен за любую помощь, которую может предложить каждый.

Спасибо

Al

Ответы [ 5 ]

5 голосов
/ 22 апреля 2009

Существует несколько пакетов синтаксического анализатора Python, которые можно использовать для описания синтаксиса, а затем он сгенерирует код Python для синтаксического анализа этого синтаксиса.

Нед Бэтчелдер написал очень хорошее резюме

Из них Ply использовался в проекте под названием pycparser , который анализирует исходный код на языке C. Я бы рекомендовал начать с этого.

Некоторые из этих других проектов синтаксических анализаторов могут также иметь образцы синтаксических анализаторов C.

Редактировать : только что заметил, что pycparser даже имеет пример скрипта Python, чтобы просто анализировать объявления типа C , как старая программа cdecl.

3 голосов
/ 23 апреля 2009

Как насчет того, чтобы подойти к нему с другой стороны полностью? У вас уже есть анализатор, который полностью понимает все нюансы системы типов C: сам компилятор. Итак, скомпилируйте проект с полной поддержкой отладки и приступайте к отладке данных отладки.

Для системы, основанной на форматах, поддерживаемых binutils , большинство необходимых деталей можно узнать с помощью библиотеки BFD .

Форматы отладки Microsoft (в некоторой степени) поддерживаются библиотеками и документами на MSDN, но мой Google-фу сегодня слаб, и я не кладу руки на статьи, которые, как я знаю, существуют, чтобы ссылаться здесь.

Компилятор Keil 8051 (здесь я не использовал их компилятор ARM) использует формат Intel OMF или OMF2 и документирует, что символы отладки предназначены для их отладчика или «любых совместимых с Intel эмуляторов». Спецификации для OMF , используемые Keil C51, доступны по адресу Keil , поэтому я думаю, что аналогичные спецификации доступны и для других их компиляторов.

Быстрое сканирование веб-сайта Keil, похоже, указывает на то, что они отказались от своего проприетарного ARM-компилятора в пользу лицензирования ARM-компилятора RealView, который, похоже, использует объекты ELF с отладочной информацией формата DWARF. Dwarf должен поддерживаться BFD и давать вам все, что вам нужно знать, чтобы убедиться, что типы и имена совпадают.

2 голосов
/ 22 апреля 2009

То, что вы пытаетесь сделать, - это облегченная форма статического анализа. Возможно, вам повезет, глядя на инструменты, на которые указывает Wikipedia .

Сам анализ кода C звучит для меня как неправильное направление: в этом и заключается безумие. Если вы настаиваете, то [f] lex и yacc (bison) - это инструменты, которые, вероятно, используют ваши авторы компиляторов.

Или, если ctags или cscope дадут вам 80% пути, исходный код для обоих широко доступен. Последние 20% - это просто вопрос программирования. :)

2 голосов
/ 22 апреля 2009

Проверьте ANTLR. Это генератор парсеров с привязками для python. Сайт ANTLR предоставляет целую кучу грамматик для распространенных языков, включая C. Вы можете скачать грамматику для C и добавить действия в соответствующих местах для сбора интересующей вас информации. Есть даже удобный графический инструмент для создания и отладки грамматик. (Я знаю, что это кажется странным, но на самом деле это довольно удобно и не противно)

Я только что сделал что-то подобное, кроме как для получения информации о моих символах, я фактически извлекаю ее из GDB.

0 голосов
/ 22 апреля 2009

Я сделал нечто подобное для проекта, над которым работал несколько лет назад. В итоге я написал первую половину компилятора Си. Не пугайтесь этой перспективы. На самом деле это намного проще, чем кажется, особенно если вы ищете только определенные токены (в данном случае определения переменных).

Найдите в Интернете документацию о том, как сканировать исходный код на языке C, обнаруживать интересующие токены и анализировать результаты. Хорошее место для начала - статья Википедии по лексическому анализу .

...