oz grep.c源碼閱讀有感想

oz grep.c源碼閱讀有感想
我最早開始讀源碼,就是讀了有一個人分析oz的grep.c源碼的文章,我讀了博客後,感覺不過隱,繼續下載了oz的源碼,自此,就再開始讀coreutils等源碼。但陸續讀代碼,其中grep.c中的正則表達式大體邏輯懂了,但其中關於位圖的一些操作,一直沒有弄明白。
昨天,我想,再回過頭來讀grep.c的源碼,開始下載,使用wget總是下載不了。於是,直接使用網頁打開,再複製。
再進行編譯,報了幾個錯,修改完後,編譯成功。再回頭讀代碼,感覺作者的代碼寫得真好。真的。
我原來遇到位操作的處理時,知道其大意,今天就沉下心來,再回憶。發現真是很好玩的。
如[a-z]要變成abcdefghijklmnopqrstuvwxyz
那如何處理呢?
#define MAXCHR    128
#define CHRBIT    8
#define BITBLK    MAXCHR/CHRBIT
#define BLKIND    0170
//0170===1 111 000
#define BITIND    07
//07=====0 000 000
#define ASCIIB    0177
因爲[a-z]展開後,是個集合,於是作者使用位圖來存儲。
如下所示,
static CHAR bittab[BITBLK];        /* bit table for CCL */
用16個字節的數組bittab來存儲,其中每個字符佔一位,而16*8=128可以存儲128個字符。
我當初的設想是,這128個字符一個一個排起來,用某個字符代表bittab中的某位,但作者如何實現的呢?
static void
chset(CHAR c)
{
  //取第4,5,6,7這幾位的值。
  //BLKIND=1 111 000
  //BITIND=0 000 111
  //CHAR bitarr[] = {1,2,4,8,16,32,64,128};
    bittab[(CHAR) ((c) & BLKIND) >> 3] |= bitarr[(c) & BITIND];
}
當要存儲時,用函數chset(),我對位操作不熟悉,開始看到8進制數0170,我以爲是
011110呢?我寫了測試程序,看它到底是幾?結果是01 111 000
爲此,把幾個8進制數用二進制數表示出來。
作者的想法是,要存儲128個字符,這些字符共有7個二進制位。如
1111 111
在數組bittab[]中共16個字節,某字符的第4,第5,第6,第7位共4位,這4位是幾,就存儲在bittab[]數據的第幾個字節中。而某字符的第1,2,3位,共能表示
000,001,010,011,100,101,110,111
8種字符,剛好能放到一個字節中,於是,該字符的低三位是幾,就用數組
CHAR bitarr[] = {1,2,4,8,16,32,64,128};
中bitarr[幾]的某一位置1來表示。
有些玄,我有些懂,但說不清。反正,一個ASCII字符總共有用的就是低7位,我把這低7位,全部都使用上了。就把這個字符保存起來了。

讀懂這個,基本這個程序原來不明白的地方都明白了。快速的瀏覽程序,把一些細微的地方聯繫起來,真是爽呀。
比如,在函數中
re_exec(char *lp)
{
    register CHAR c;
    register char *ep = 0;
    register CHAR *ap = nfa;

    bol = lp;

    bopat[0] = 0;
    bopat[1] = 0;
  //bopat[1..9]好象沒有用到,爲什麼進行定義呢?
  //原來它們是在pmatch()函數中使用了。
    bopat[2] = 0;
    bopat[3] = 0;
    bopat[4] = 0;
    bopat[5] = 0;
    bopat[6] = 0;
    bopat[7] = 0;
    bopat[8] = 0;
    bopat[9] = 0;
當時我在re_exec函數中,只看到對bopat[0]的使用,而bopat[1]等則沒使用就提了問題?
我理解時,只是侷限在一個函數re_exec中,其實,bopat[]是全局變量,在pmatch()函數中,有對bopat[1..9]的使用。這些元素用於存儲
(ab)(ac)(ad)\1\2\3
中\1存儲bopat[1]中
等。因此 ,要跨越函數來理解。

這個grep的實現終於理解了,讀完後,感覺作者寫得就是巧妙。寫得通俗易懂。我發現bsd的風格和gnu的風格是很不同的。bsd提倡簡明,真想再讀一些bsd相關的源碼。
不過,我的英語不好,現在只能找到gnu的源碼。
而gnu的源碼呢,那個sed1.8中的正則表達式把我難住了,而awk1.01的源碼呢,也一樣難懂。真是感覺頭痛。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章