• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 探索 GCC 前端的內(nèi)部結(jié)構(gòu)(二)

    探索 GCC 前端的內(nèi)部結(jié)構(gòu)(二)

    ——
    作者: 時間:2007-04-17 來源:嵌入開發(fā)網(wǎng) 收藏
    Treelang 的代碼框架

    讀者朋友們在閱讀這一部分代碼分析的時候,手邊最好能準(zhǔn)備上一份 GCC 3.3 的源代碼。這個源代碼可以從 GCC 的站點 http://gcc.gnu.org上獲得。本文作者力圖做到把整個情況像說故事一樣娓娓道來,但是讀者朋友們?nèi)绻谶m當(dāng)?shù)臅r候能夠查閱一下源代碼,可能更能把問題了解的清楚透徹。 

    這個 treelang 語言的實現(xiàn),主要有兩個 C 語言文件,把整個代碼框架分成兩個部分。第一部分以 tree1.c 為主,帶上 parse.y 這個 YACC 源程序,組成了和 GCC 前端的接口;第二部分以 treetree.c 為主,組成了和 GCC 后端的接口。 

    這里首先說明一下 tree1.c 這個文件。它和上級目錄中的 GCC 框架文件 toplev.c 交互作用,實現(xiàn) tree1 這個執(zhí)行程序的主體部分。這個 tree1 就相當(dāng)于 GCC 的 C 語言前端中的 cc1 執(zhí)行程序,該程序是 C 語言前端的主體。 

    我們首先試圖說明從 toplev.c 到 tree1.c 的路徑。這樣我們就注意到 toplev.c 中這個引人注目的 lang_hooks 變量。當(dāng)然,接下來就注意到在 toplev.c 同一目錄下的 langhooks.c 這個文件。我們希望在其中發(fā)現(xiàn)一點有趣的東西。這一共是三個文件:langhooks.[ch] 和 langhooks-def.h 其中在 langhooks.h 中定義了一堆各式各樣的 struct lang_hooks_for_xxx 結(jié)構(gòu),以及最后還有一個 struct lang_hooks 結(jié)構(gòu)把前面的那些 for_xxx 的結(jié)構(gòu)都總括了起來。這每一個結(jié)構(gòu)都是若干個至少看上去像是回調(diào)函數(shù)的函數(shù)指針。看來這就是我們要尋找的東西。那么大概就是這樣了,前端向 GCC 主體部分注冊自己的 lang_hooks 來完成各樣的任務(wù)。接下來一個自然的問題就是這個注冊是如何進行的;另外一個問題就是要對這些回調(diào)函數(shù)指針進行分析了。 

    這個 langhooks.h 文件中關(guān)于 struct lang_hooks 結(jié)構(gòu)字段的注釋很詳細,這里我們暫時先跳過去。等到 treelang 中具體的注冊回調(diào)函數(shù)出現(xiàn)的時候,我們根據(jù)需要再做仔細說明。在 langhooks-def.h 文件中定義了一些這個 struct lang_hooks 結(jié)構(gòu)的默認值。 

    現(xiàn)在我們進入 treelang 目錄下的 treetree.c 這個文件。來察看一下在 treelang 中對 struct lang_hooks 這個結(jié)構(gòu)的初始化過程。這個過程不是按照我們通常所熟悉的 C 語言的 C99 標(biāo)準(zhǔn)或者是 GCC 擴展語法來進行的。而是采用了大量的 #define 和 #undef 并結(jié)合上層目錄中的 langhooks-def.h 來進行。細想一下,這是理所當(dāng)然的事情,因為這是在編譯 C 語言本身嘛。當(dāng)然就不好用到 C 語言的新的東西或者是自己做的擴展的東西。 

    注釋開始::::: 

    我們以初始化如下定義的 struct sample 結(jié)構(gòu)為例。



    struct sample {
            int member_int;
            char *member_str;
            void (*member_fun)(void);
    };

     


    在 C99 中,初始化一個 struct 結(jié)構(gòu)數(shù)據(jù),使用下面這樣的語法。 



    struct sample inst_c99 = {
            .member_int = 78,
            .member_str = "iloveqhq",
            .member_fun = real_fun,
    };

     


    在 C99 標(biāo)準(zhǔn)出現(xiàn)之前,GCC 定義了自己的擴展,下面的例子就是按照這個 GCC 對 C 語言的擴展,來初始化一個 struct 結(jié)構(gòu)數(shù)據(jù)。 



    struct sample inst_gcc = {
            member_int: 76,
            member_str: "zhaoway",
            member_fun: real_fun,
    };

     


    在 GCC 的源代碼中沒有使用上面的兩種辦法,而是大量使用了宏定義。這個辦法首先要申明一份輔助的宏定義。這些個輔助的宏定義,在一個軟件項目里面,針對一個 struct 結(jié)構(gòu),只需要一份即可。 



    #define MEMBER_INT 0
    #define MEMBER_STR ""
    #define MEMBER_FUN NULL
                                                                                          
    #define SAMPLE_INITIALIZER {   
            MEMBER_INT,            
            MEMBER_STR,            
            MEMBER_FUN,            
    }

     


    按照上面這樣的辦法申明了這些關(guān)于這個 struct sample 的輔助宏定義以后,在每次要初始化一個 struct sample 數(shù)據(jù)結(jié)構(gòu)的時候,只需要按照如下操作即可。除了要稍微多打一些字以外,這個方法的方便程度和以上兩種方法是差不多的。 



    #undef MEMBER_INT
    #define MEMBER_INT 12
    #undef MEMBER_STR
    #define MEMBER_STR "trtr"
    #undef MEMBER_FUN
    #define MEMBER_FUN real_fun
    struct sample inst_def = SAMPLE_INITIALIZER;

     


    這樣就也可以像 C99 標(biāo)準(zhǔn)或者 GCC 的擴展一樣,按照成員變量的名稱來初始化一個 struct 類型的數(shù)據(jù)結(jié)構(gòu)了。不過話又說回來,在我們一般的軟件項目中,還是應(yīng)該沿著 C99 標(biāo)準(zhǔn)這個 C 語言的發(fā)展方向來走的。 

    :::::注釋結(jié)束 

    接下來的線路很清楚,就是一個一個的分析這些個回調(diào)函數(shù)啦。 


    評論


    相關(guān)推薦

    技術(shù)專區(qū)

    關(guān)閉
    主站蜘蛛池模板: 池州市| 怀安县| 五家渠市| 简阳市| 民丰县| 阜城县| 房产| 惠东县| 茌平县| 天全县| 延边| 和平县| 漯河市| 德钦县| 宜宾县| 大冶市| 赤壁市| 淮阳县| 利川市| 唐河县| 桐城市| 上虞市| 开阳县| 永和县| 日喀则市| 普安县| 翁牛特旗| 嘉黎县| 汉阴县| 卓资县| 云浮市| 施秉县| 冕宁县| 仪陇县| 永州市| 绩溪县| 曲靖市| 土默特右旗| 阆中市| 台中县| 城口县|