Как извлечь одну функцию из исходного файла

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

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

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

extract /fs/cifs/connect.c cifs_parse_mount_options

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

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

Спасибо,

Уди

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


person Adam Matan    schedule 17.07.2009    source источник


Ответы (3)


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

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

person Mike Dinescu    schedule 17.07.2009
comment
Это была моя первая идея, но комментарии немного усложняют ситуацию. Впрочем, если я напишу такой сценарий. Думаю, опубликую - может быть, другим пригодится. - person Adam Matan; 17.07.2009
comment
Я согласен ... возможно, вам нужно принять во внимание комментарии на тот случай, если они могут содержать несовпадающие фигурные скобки внутри. Тем не менее, это не должно быть слишком сложно кодировать! - person Mike Dinescu; 17.07.2009
comment
Мне нужно вырезать их, получить местоположение конца функции, а затем извлечь код с комментариями. Еще одна проблема - подпись функции вверху - она ​​может быть длиннее одной строки. Как я упоминал ранее, это не имеет большого значения, но я лучше сосредоточусь на своих исследованиях и воспользуюсь готовым инструментом. Если это невозможно, я решу проблему на Python! - person Adam Matan; 17.07.2009
comment
Серьезно, написание этого сценария должно занять меньше часа. Вы, вероятно, уже потратили больше времени на поиски инструмента для этого, чем на то, чтобы делать это самостоятельно. - person muusbolla; 17.07.2009
comment
Вы должны запустить препроцессор (например, gcc -E) перед синтаксическим анализом источника. После предварительной обработки это должно быть легко. - person Frunsi; 21.05.2010
comment
Предварительная обработка - плохая идея, если вы хотите сохранить комментарии или макет кода. Если вы не обрабатываете препроцессор, то вам может быть очень плохо подбирать функцию, чей заголовок или хвост определяется / модифицируется условными выражениями препроцессора или макросами. Хотя это редко, в больших системах все происходит, поэтому ожидайте столкнуться с этим. Правильный ответ заключается в том, что любое хакерское решение, которое кажется работающим, будет работать только на вид; это не сработает ни при каких обстоятельствах. Если OP не заботится об этом, тогда хорошо. Если он это сделает, ему нужно будет изменить инструмент, который по сути содержит препроцессор и синтаксический анализатор. - person Ira Baxter; 15.03.2015

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

awk -f split.awk code.out

вам нужно немного адаптировать split.awk, который несколько специфичен для моего кода и потребностей в рефакторинге (например, y have so struct, которая не является 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;
               }
person Patrick Sinz    schedule 21.05.2010

если вам сложно извлечь имена функций:

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

person sherelock    schedule 15.03.2015