文档章节

cTags源码分析(1) - 概要

htfy96
 htfy96
发布于 2015/02/26 15:26
字数 882
阅读 91
收藏 0

main.c开始。

extern int main (int __unused__ argc, char **argv)
{
    cookedArgs *args;
#ifdef VMS
    extern int getredirection (int *ac, char ***av);

    /* do wildcard expansion and I/O redirection */
    getredirection (&argc, &argv);
#endif

#ifdef AMIGA
    /* This program doesn't work when started from the Workbench */
    if (argc == 0)
        exit (1);
#endif

#ifdef __EMX__
    _wildcard (&argc, &argv);  /* expand wildcards in argument list */
#endif

#if defined (macintosh) && BUILD_MPW_TOOL == 0
    argc = ccommand (&argv);
#endif

    setCurrentDirectory ();
    setExecutableName (*argv++);
    checkRegex ();

    args = cArgNewFromArgv (argv);
    previewFirstOption (args);
    testEtagsInvocation ();
    initializeParsing ();
    initOptions ();
    readOptionConfiguration ();
    verbose ("Reading initial options from command line
");
    parseOptions (args);
    checkOptions ();
    makeTags (args);

    /*  Clean up.
     */
    cArgDelete (args);
    freeKeywordTable ();
    freeRoutineResources ();
    freeSourceFileResources ();
    freeTagFileResources ();
    freeOptionResources ();
    freeParserResources ();
    freeRegexResources ();

    exit (0);
    return 0;
}

一开始cTags维护了一个自己的cookedArgs类型的参数列表,args。之后根据不同系统的情况,重新定义了argcargv

第一个函数setCurrentDirectory()定义在routines.c中,根据系统不同,定义了CurrentDirectory一个全局变量(使用getcwd()),并在最后增加了OUTPUT_PATH_SEPARATOR

第二个函数setExecutableName (*argv++)定义了ExecutableProgram(主文件路径)和ExecutableName(主文件名)两个全局变量。

第三个函数checkRegex()regex库的内部函数,检查regex能否正常工作.

之后,args = cArgNewFromArgv (argv)将默认的选项格式加以处理转换到args中.

previewFirstOption (args)处理-v和没有选项的情况(直接退出)。

testEtagsInvocation ()检测是否有-e选项,若有,则初始化etags

initializeParsing()是重要的一步,它检查每一个内建的语言,它们的名称是否合法,它们的regex是否存在,如果是,则将它们插入LanguageTable[]数组中。这个数组的成员类型是parserDefinition*,而parserDefinition的定义如下:

typedef struct {
    /* defined by parser */
    char* name;                    /* name of language */
    kindOption* kinds;             /* tag kinds handled by parser */
    unsigned int kindCount;        /* size of `kinds' list */
    const char *const *extensions; /* list of default extensions */
    const char *const *patterns;   /* list of default file name patterns */
    parserInitialize initialize;   /* initialization routine, if needed (初始化的函数指针) */
    simpleParser parser;           /* simple parser (common case) */
    rescanParser parser2;          /* rescanning parser (unusual case) */
    boolean regex;                 /* is this a regex parser? */

    /* used internally */
    unsigned int id;               /* id assigned to language */
    boolean enabled;               /* currently enabled? */
    stringList* currentPatterns;   /* current list of file name patterns */
    stringList* currentExtensions; /* current list of extensions */
} parserDefinition;

之后initializeParsing调用initializeParsers (),即循环调用每个LanguageTable[]中语言的LanguageTable[i]->initialize(),进行语言初始化工作(建立hash表等)。

接下来的一大步是initOptions(),设置默认选项,建立默认语言映射,自动添加.git等控制文件到--exclude选项中。

readOptionConfiguration ()读取目录下的.ctags配置文件与环境变量。

parseOptions (args)把之前简单分拆的选项细分成longOptionsshortOptions,并设置Options结构的相应位。

checkOptions()是对选项的静态检查。

makeTags(args),是最重要的部分,代码如下:

static void makeTags (cookedArgs *args)
{
    clock_t timeStamps [3];
    boolean resize = FALSE;
    boolean files = (boolean)(! cArgOff (args) || Option.fileList != NULL
                              || Option.filter);

    if (! files)
    {
        if (filesRequired ())
            error (FATAL, "No files specified. Try "%s --help".",
                getExecutableName ());
        else if (! Option.recurse && ! etagsInclude ())
            return;
    }

#define timeStamp(n) timeStamps[(n)]=(Option.printTotals ? clock():(clock_t)0)
    if (! Option.filter)
        openTagFile ();

    timeStamp (0);

    if (! cArgOff (args))
    {
        verbose ("Reading command line arguments
");
        resize = createTagsForArgs (args);
    }
    if (Option.fileList != NULL)
    {
        verbose ("Reading list file
");
        resize = (boolean) (createTagsFromListFile (Option.fileList) || resize);
    }
    if (Option.filter)
    {
        verbose ("Reading filter input
");
        resize = (boolean) (createTagsFromFileInput (stdin, TRUE) || resize);
    }
    if (! files  &&  Option.recurse)
        resize = recurseIntoDirectory (".");

    timeStamp (1);

    if (! Option.filter)
        closeTagFile (resize);

    timeStamp (2);

    if (Option.printTotals)
        printTotals (timeStamps);
#undef timeStamp
}

简而言之,就是以下几步:

  1. openTagFile (resize)打开Tag文件;

  2. 根据选项不同,分别调用createTagsForArgs (args)createTagsFromListFile (Option.fileList)createTagsFromFileInput (stdin, TRUE)recurseIntoDirectory ("."),而它们都调用了createTagsForEntry(filename),经过检查后,最终调用了parse.c中的parseFile(filename);

  3. closeTagFile (resize)关闭Tag文件。

最终,通过如下几步,free掉前几步申请的动态内存,防止内存泄漏:

    cArgDelete (args);  //释放args[]
    freeKeywordTable ();  //释放KeywordTable[]
    freeRoutineResources ();  //释放CurrentDirectory
    freeSourceFileResources ();  //释放File(一个用于读取文件的变量)
    freeTagFileResources ();  //释放TagFile变量
    freeOptionResources ();  //释放Options变量
    freeParserResources ();  //释放LanguageTable[]
    freeRegexResources ();  //释放Regex库内存

© 著作权归作者所有

共有 人打赏支持
htfy96
粉丝 8
博文 5
码字总数 10027
作品 0
闵行
程序员
私信 提问
Linux源代码分析工具链

vim+ctags+cscope 源码阅读三剑客.vim配合ctags和cscope,足以在源代码里面自由翱翔,在函数和变量间自由跳转. 安装 1 sudo apt-get install vim ctags cscope 使用 vim vim的使用就略过了,网上...

CasparLi
2015/09/06
197
0
Vim编程之:tags,cscope,taglist

最近VIM用得比较多,所以在学了不少。在这里对收获到的东西做一个总结。 1.编程四要素vim,ctags,cscope,taglist vim配合这3件东西之后,极为强大。与SourceInsight有一拼。 1.1 ctags ctags叫...

临峰不畏
2013/06/20
0
0
ubuntu搭建C/C++环境附VIM的常用命令表

ubuntu搭建C/C++环境附VIM的常用命令表 发布于: January 25, 2012, 9:21 pm 分类: linux,web服务器 作者: Cyrec 1,配置gcc 刚装好的的gcc什么文件都不能编译,因为没有一些必须的头文件,所...

Start-up
2012/04/27
0
0
使用 vim + ctags + cscope + taglist 阅读源码

阅读源码的工具有很多,而且如今的集成开发环境(IDE)也很强大,但对于经常使用vim编辑器的程序员来说,对vim的强大绝对是“不抛弃,不放弃”的,况且我们只要安装一些插件配合vim的工作一样...

Julian_Wu
2013/06/27
0
4
Linux 平台下阅读源码的工具链

本文作者:伯乐在线 -肖汉松 。未经作者许可,禁止转载! 欢迎加入伯乐在线专栏作者。 前言 看源代码是一个程序员必须经历的事情,也是可以提升能力的一个捷径.个人认为: 要完全掌握一个软件的...

伯乐在线
2016/05/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

CSS 选择器参考手册

CSS 选择器参考手册 选择器 描述 [attribute] 用于选取带有指定属性的元素。 [attribute=value] 用于选取带有指定属性和值的元素。 [attribute~=value] 用于选取属性值中包含指定词汇的元素。...

Jack088
29分钟前
0
0
数据库篇一

数据库篇 第1章 数据库介绍 1.1 数据库概述  什么是数据库(DB:DataBase) 数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据...

stars永恒
40分钟前
2
0
Intellij IDEA中设置了jsp页面,但是在访问页面时却提示404

在Intellij IDEA中设置了spring boot的jsp页面,但是在访问时,却出现404,Not Found,经过查找资料后解决,步骤如下: 在Run/Debug Configurations面板中设置该程序的Working Directory选项...

uknow8692
昨天
2
0
day24:文档第五行增内容|每月1号压缩/etc/目录|过滤文本重复次数多的10个单词|人员分组|

1、在文本文档1.txt里第五行下面增加如下内容;两个方法; # This is a test file.# Test insert line into this file. 分析:给文档后增加内容,可以用sed 来搞定;也可以用while do done...

芬野de博客
昨天
2
0
深入理解JVM—JVM内存模型

深入理解JVM—JVM内存模型 我们知道,计算机CPU和内存的交互是最频繁的,内存是我们的高速缓存区,用户磁盘和CPU的交互,而CPU运转速度越来越快,磁盘远远跟不上CPU的读写速度,才设计了内存...

onedotdot
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部