Как извлечь одну функцию из исходного файла - PullRequest
4 голосов
/ 17 июля 2009

Я работаю над небольшим академическим исследованием о чрезвычайно длинных и сложных функциях в ядре Linux . Я пытаюсь выяснить, есть ли веская причина написать функции длиной 600 или 800 строк.

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

Например, если у меня есть функция cifs_parse_mount_options() в файле connect.c, я ищу решение, которое примерно работает как:

extract /fs/cifs/connect.c cifs_parse_mount_options

и вернуть 523 строки кода (!) Функции от открывающих скобок до закрывающих скобок.

Конечно, любой способ манипулирования существующими программными пакетами, например gcc, также был бы наиболее полезным.

Спасибо

Уди

РЕДАКТИРОВАТЬ: Ответы на Regex для извлечения объявлений прототипов функции C? убедили меня, что сопоставление объявления функции с помощью regex далеко не тривиально.

Ответы [ 3 ]

3 голосов
/ 17 июля 2009

Почему бы вам не написать небольшой скрипт на PERL / PHP / Python или даже небольшую программу на C ++, Java или C #, которая это делает?

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

1 голос
/ 21 мая 2010

отступ -kr код -o code.out

awk -f split.awk code.out

Вы должны немного адаптировать split.awk, который несколько специфичен для моего кода и потребностей рефакторинга (например, у вас есть такая структура, которая не является typedefs

И я уверен, что вы можете сделать более хороший сценарий: -)

--
BEGIN   { line=0; FS="";
    out=ARGV[ARGC-1]  ".out";
    var=ARGV[ARGC-1]  ".var";
    ext=ARGV[ARGC-1]  ".ext";
    def=ARGV[ARGC-1]  ".def";
    inc=ARGV[ARGC-1]  ".inc";
    typ=ARGV[ARGC-1]  ".typ";
    system ( rm " " -f " " out " " var " " ext " " def " " inc " " typ );
    }
/^[     ]*\/\/.*/   { print "comment :" $0 "\n"; print $0 >> out ; next ;}
/^#define.*/        { print "define :" $0 ; print $0 >>def ; next;}
/^#include.*/       { print "define :" $0 ; print $0 >>inc ; next;}
/^typedef.*{$/      { print "typedef var :" $0 "\n"; decl="typedef";print $0 >> typ;infile="typ";next;}
/^extern.*$/        { print "extern :" $0 "\n"; print $0 >> ext;infile="ext";next;}
/^[^    }].*{$/     { print "init var :" $0 "\n";decl="var";print $0 >> var; infile="vars";
                print $0;
                fout=gensub("^([^    \\*])*[    ]*([a-zA-A0-9_]*)\\[.*","\\2","g") ".vars";
                     print "var decl : " $0 "in file " fout;
                     print $0 >fout;
                next;
                        }
/^[^    }].*)$/     { print "func  :" $0 "\n";decl="func"; infile="func";
                print $0;
                fout=gensub("^.*[    \\*]([a-zA-A0-9_]*)[   ]*\\(.*","\\1","g") ".func";
                     print "function : " $0 "in file " fout;
                     print $0 >fout;
                next;
            }
/^}[    ]*$/        { print "end of " decl ":" $0 "\n"; 
                if(infile=="typ") {
                    print $0 >> typ;
                }else if (infile=="ext"){
                    print $0 >> ext;
                }else if (infile=="var") {
                    print $0 >> var;
                }else if ((infile=="func")||(infile=="vars")) {
                    print $0 >> fout; 
                    fflush (fout);
                    close (fout);
                }else if (infile=="def") {
                    print $0 >> def;
                }else if (infile=="inc"){
                    print $0 >> inc;
                }else print $0 >> out;
                next;
            }
/^[a-zA-Z_]/        { print "extern :" $0 "\n"; print $0 >> var;infile="var";next;}
            { print "other :" $0 "\n" ; 
                if(infile=="typ") {
                    print $0 >> typ;
                }else if (infile=="ext"){
                    print $0 >> ext;
                }else if (infile=="var") {
                    print $0 >> var;
                }else if ((infile=="func")||(infile=="vars")){
                    print $0 >> fout;
                }else if (infile=="def") {
                    print $0 >> def;
                }else if (infile=="inc"){
                    print $0 >> inc;
                }else print $0 >> out;
               next;
               }
0 голосов
/ 15 марта 2015

на случай, если вам трудно извлечь имена функций:

1> использовать ctags (программу) для извлечения имен функций. ctags -x --c-types = fp path_to_file. 2> Как только вы получили имена функций, напишите простой Perl-скрипт для извлечения содержимого функции, передавая имя скрипта функции, как сказано выше.

...