代码之家  ›  专栏  ›  技术社区  ›  blak3r

为特定项目目录创建以下列表的脚本:<method name><num of times called>

  •  1
  • blak3r  · 技术社区  · 16 年前

    有没有人知道一个脚本来获得一个列表,这个列表可以告诉我C项目最常调用的函数?

    方法1 391
    方法2 23
    方法3 12

    更好的是,它可以定制为在方法名“get”中需要一个关键字。

    我试着不重新发明轮子,自己写一个简单的脚本来完成它。用grep或awk做这件事可能很简单。我可以编写一个正则表达式来匹配函数调用名。Eclipse插件是理想的。

    我不是在找档案员。我之所以需要这样的方法,是因为我需要为嵌入式项目优化程序空间。我倾向于用getter封装我的成员变量,但可能需要使用extern并直接访问使用最多的成员来减少空间。

    3 回复  |  直到 16 年前
        1
  •  1
  •   RBerteig Keith Adler    16 年前

    一种方法是运行 Doxygen 在震源基础上。除非已经在使用doxygen,否则需要将其配置为提取所有函数和类,因为默认情况下,它会忽略未记录的实体。

    如果您还有AT&T GraphViz 安装后,可以为每个函数绘制漂亮的调用图和调用图。但我不认为有一个表可以用调用的数量来总结这一点。

    但是,可以选择一些非文档输出格式,包括Perl模块和XML。你可以解析其中一个来开发你想要的列表,而且解析这个信息几乎比把C++的前端凑到一起用蛮力来得到正确答案更容易。

    还有一个gcc的XML后端在某个地方浮动,它基本上以XML格式转储语法树…我最近被它绊倒了,但不记得具体在哪里。

        2
  •  1
  •   blak3r    16 年前

    这里是一个简单的Java脚本,它提供了我正在寻找的输出。 通过定制文件顶部的两个regex,它也可以用来生成关于其他模式出现的统计信息。

    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    import java.util.regex.Pattern;
    
    public class MethodCallCount {
        // This is the regex which is applied to each line to test if there is a method call on it.
        private static String REGEX_METHODCALL = "(?:\\s*)([a-zA-Z0-9_]+)\\((.*)"; 
        // Only looks in files with .c extention
        private static String REGEX_FILEEXTS = ".*.c";
        private static boolean VERBOSE_OUTPUT = false;
        private static Map<String,Integer> patternMap = new HashMap<String,Integer>();
    
        // Process all files and directories under dir
        public static void visitAllDirsAndFiles(File dir) {
    
            if( !dir.isDirectory()) {
                if( dir.getName().matches(REGEX_FILEEXTS) ) {
                    if( VERBOSE_OUTPUT ) { System.out.println("Processing File: " + dir.getName() ); }
                    processFile(dir);
                }
            }
            else if( !dir.getName().equals(".svn") ) {
                String[] children = dir.list();
                for (int i=0; i<children.length; i++) {
                    visitAllDirsAndFiles(new File(dir, children[i]));
                }
            }
        }
    
        // Process only directories under dir
        public static void visitAllDirs(File dir) {
            if (dir.isDirectory()) {
                processFile(dir);
    
                String[] children = dir.list();
                for (int i=0; i<children.length; i++) {
                    visitAllDirs(new File(dir, children[i]));
                }
            }
        }
    
        // Process only files under dir
        public static void visitAllFiles(File dir) {
            if (dir.isDirectory()) {
                String[] children = dir.list();
                for (int i=0; i<children.length; i++) {
                    visitAllFiles(new File(dir, children[i]));
                }
            } else {
                processFile(dir);
            }
        }
    
        public static void processMethod( String pMethod ) {
            if( VERBOSE_OUTPUT ) { System.out.println("found: " + pMethod); }
            if( patternMap.containsKey( pMethod ) ) {
                Integer cnt = patternMap.get( pMethod );
                cnt = cnt + 1;
                patternMap.put(pMethod, cnt );
            }
            else {
                patternMap.put( pMethod.toString(), 1);
            }       
        }
    
    
        public static void processLine( String pLine ) {
            Pattern methodMatcher = Pattern.compile( REGEX_METHODCALL );
            java.util.regex.Matcher matcher = methodMatcher.matcher( pLine );
    
            if( matcher.matches() ) {
                if( VERBOSE_OUTPUT ) { System.out.println("processing " + matcher.group(1) ); }
                processMethod( matcher.group(1) );                  
                processLine( matcher.group(2) );
            }
        }
    
        public static void processFile( File pFile ) {
            BufferedReader fin;
            try {
                fin = new BufferedReader( new InputStreamReader( new FileInputStream(pFile) ) );
                String l = null;
                while( (l=fin.readLine()) != null ) {
                    processLine( l );
                }
            } 
            catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }       
        }
    
        /**
         * @param args[0] is the directory to run this on.  Otherwise current directory is used.
         */
        public static void main(String[] args) {
    
            String searchDirPath = System.getProperty("user.dir");
            if( args.length > 0 ) {
                searchDirPath = args[0];
            }
            else {
                System.out.println("No argument specified... searching for *.map in: " + searchDirPath );
            }
    
            File searchDir = new File( searchDirPath );
            visitAllDirsAndFiles(searchDir);
    
            // Print Stats.
            int callCnt = 0;
            Set<String> patternSet = patternMap.keySet();
            for( String p : patternSet ) {
                System.out.println( patternMap.get(p) + "\t" + p );
                callCnt += patternMap.get(p);
            }
            System.out.println("Unique Methods: " + patternMap.size());
            System.out.println("Calls Detected: " + callCnt );
            System.out.println("Copy and paste output above into excel and then sort columns");
            System.out.println("DONE.");
        }
    }
    
        3
  •  0
  •   Jouni K. Seppänen    16 年前

    如果“最频繁”是指程序某些运行中的实际调用数, DTrace 可能是您正在寻找的工具,假设您有一个用于开发工作的Solaris、FreeBSD或OSX盒。另请参见 Code Spelunking redux 为了更好地描述多西根和dtrace。