как получить объявление функции или определения с помощью регулярных выражений - PullRequest
4 голосов
/ 03 июня 2009

Я хочу получить только прототипы функций, такие как

int my_func(char, int, float)
void my_func1(void)
my_func2()

из файлов C с использованием регулярных выражений и Python.

Вот мой формат регулярных выражений: ".*\(.*|[\r\n]\)\n"

Ответы [ 7 ]

6 голосов
/ 03 июня 2009

Это удобный скрипт, который я написал для таких задач, но он не дает типы функций. Это только для имен функций и списка аргументов.

# Exctract routine signatures from a C++ module
import re

def loadtxt(filename):
    "Load text file into a string. I let FILE exceptions to pass."
    f = open(filename)
    txt = ''.join(f.readlines())
    f.close()
    return txt

# regex group1, name group2, arguments group3
rproc = r"((?<=[\s:~])(\w+)\s*\(([\w\s,<>\[\].=&':/*]*?)\)\s*(const)?\s*(?={))"
code = loadtxt('your file name here')
cppwords = ['if', 'while', 'do', 'for', 'switch']
procs = [(i.group(2), i.group(3)) for i in re.finditer(rproc, code) \
 if i.group(2) not in cppwords]

for i in procs: print i[0] + '(' + i[1] + ')'
2 голосов
/ 03 июня 2009

Посмотрите, есть ли у вашего компилятора C возможность вывести файл только прототипов того, что он компилирует. Для gcc это -aux-info FILENAME

1 голос
/ 03 июня 2009

Существует множество ловушек, пытающихся «проанализировать» код C (или, по крайней мере, извлечь некоторую информацию) только с помощью регулярных выражений. Я определенно позаимствую C для вашего любимого генератора синтаксического анализатора (скажем, Bison или любой другой альтернативы для Python, везде есть грамматика C в качестве примеров) и добавьте действия в соответствующие правила.

Кроме того, не забудьте запустить препроцессор C для файла перед синтаксическим анализом.

1 голос
/ 03 июня 2009

Я думаю, что этот должен сделать работу:

r"^\s*[\w_][\w\d_]*\s*.*\s*[\w_][\w\d_]*\s*\(.*\)\s*$"

, которое будет расширено до:

string begin:   
        ^
any number of whitespaces (including none):
        \s*
return type:
  - start with letter or _:
        [\w_]
  - continue with any letter, digit or _:
        [\w\d_]*
any number of whitespaces:
        \s*
any number of any characters 
  (for allow pointers, arrays and so on,
  could be replaced with more detailed checking):
        .*
any number of whitespaces:
        \s*
function name:
  - start with letter or _:
        [\w_]
  - continue with any letter, digit or _:
        [\w\d_]*
any number of whitespaces:
        \s*
open arguments list:
        \(
arguments (allow none):
        .*
close arguments list:
        \)
any number of whitespaces:
        \s*
string end:
        $

Это не совсем правильно для сопоставления всех возможных комбинаций, но должно работать в большем количестве случаев. Если вы хотите, чтобы он был более точным, просто дайте мне знать.

EDIT: Отказ от ответственности - я довольно плохо знаком с Python и Regex, так что будьте снисходительны

1 голос
/ 03 июня 2009

Я думаю, что регулярное выражение не лучшее решение в вашем случае. Существует много ловушек, таких как комментарии, текст в строке и т. Д., Но если у прототипов вашей функции общий стиль:

type fun_name(args);

тогда \w+ \w+\(.*\); должно работать в большинстве случаев:

mn> egrep "\w+ \w+\(.*\);" *.h
md5.h:extern bool md5_hash(const void *buff, size_t len, char *hexsum);
md5file.h:int check_md5files(const char *filewithsums, const char *filemd5sum);
0 голосов
/ 03 мая 2016

Я основывался на ответе Ника Дандулакиса для аналогичного варианта использования. Я хотел найти определение функции socket в glibc. Это находит набор функций с «сокетом» в названии, но socket не был найден, подчеркивая то, что говорили многие другие: возможно, есть лучшие способы извлечения этой информации, например, инструменты, предоставляемые компиляторами.

# find_functions.py
#
# Extract routine signatures from a C++ module
import re
import sys

def loadtxt(filename):
    # Load text file into a string. Ignore FILE exceptions.
    f = open(filename)
    txt = ''.join(f.readlines())
    f.close()
    return txt

# regex group1, name group2, arguments group3
rproc = r"((?<=[\s:~])(\w+)\s*\(([\w\s,<>\[\].=&':/*]*?)\)\s*(const)?\s*(?={))"
file = sys.argv[1]
code = loadtxt(file)

cppwords = ['if', 'while', 'do', 'for', 'switch']
procs = [(i.group(1)) for i in re.finditer(rproc, code) \
 if i.group(2) not in cppwords]

for i in procs: print file + ": " + i

Тогда

$ cd glibc
$ find . -name "*.c" -print0 | xargs -0 -n 1 python find_functions.py | grep ':.*socket'
./hurd/hurdsock.c: _hurd_socket_server (int domain, int dead)
./manual/examples/mkfsock.c: make_named_socket (const char *filename)
./manual/examples/mkisock.c: make_socket (uint16_t port)
./nscd/connections.c: close_sockets (void)
./nscd/nscd.c: nscd_open_socket (void)
./nscd/nscd_helper.c: wait_on_socket (int sock, long int usectmo)
./nscd/nscd_helper.c: open_socket (request_type type, const char *key, size_t keylen)
./nscd/nscd_helper.c: __nscd_open_socket (const char *key, size_t keylen, request_type type,
./socket/socket.c: __socket (int domain, int type, int protocol)
./socket/socketpair.c: socketpair (int domain, int type, int protocol, int fds[2])
./sunrpc/key_call.c: key_call_socket (u_long proc, xdrproc_t xdr_arg, char *arg,
./sunrpc/pm_getport.c: __get_socket (struct sockaddr_in *saddr)
./sysdeps/mach/hurd/socket.c: __socket (int domain, int type, int protocol)
./sysdeps/mach/hurd/socketpair.c: __socketpair (int domain, int type, int protocol, int fds[2])
./sysdeps/unix/sysv/linux/socket.c: __socket (int fd, int type, int domain)
./sysdeps/unix/sysv/linux/socketpair.c: __socketpair (int domain, int type, int protocol, int sv[2])

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

0 голосов
/ 19 октября 2015

Регулярное выражение ниже также учитывает определение деструкторов или константных функций:

^\s*\~{0,1}[\w_][\w\d_]*\s*.*\s*[\w_][\w\d_]*\s*\(.*\)\s*(const){0,1}$
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...