gnu awk1.01源碼編譯安裝——續
這個雙休日又把時間耗在了gawk1.01的編譯安裝了,我原來好象曾編譯過,但當時對代碼的理解不深刻,編譯過後,就沒如何讀代碼了。而且我的機器環境又多,當時好像是在windows下安裝bison,不知如何在ubuntu下編譯成功了。
今天接着開始在ubuntu下安裝。
還是像原來一樣,報了無數的錯誤,因爲根本生成不了可執行程序,於是,我就把gcc進行降級安裝,還是不行。
後來,歸結到bison編譯不了。
於是,我單獨把bison的編譯拿出來。
bison -v awk.y
發現報了一堆錯誤。網上百度,對移進是歸約錯誤,也沒有人回答。
我總是想,這個程序,作者肯定曾編譯過的,不然,作者不會發布。因爲,我總是想,應該不需要對awk.y的語法進行修改,只是加某個選項,就能順利編譯的。網上有人說,對awk.output文件進行分析,我打開一看,果然有一堆錯誤。
於是就逐個分析。
State 2 conflicts: 1 shift/reduce
State 23 conflicts: 3 shift/reduce
State 33 conflicts: 1 shift/reduce
State 42 conflicts: 2 shift/reduce
State 44 conflicts: 2 shift/reduce
State 76 conflicts: 19 shift/reduce
State 104 conflicts: 1 shift/reduce
State 107 conflicts: 2 shift/reduce
State 112 conflicts: 1 shift/reduce
State 129 conflicts: 19 shift/reduce
State 136 conflicts: 1 shift/reduce
State 147 conflicts: 2 shift/reduce
State 148 conflicts: 2 shift/reduce
State 156 conflicts: 2 shift/reduce
State 168 conflicts: 1 shift/reduce
State 174 conflicts: 2 shift/reduce
State 175 conflicts: 2 shift/reduce
State 176 conflicts: 2 shift/reduce
State 182 conflicts: 2 shift/reduce
我把這個歸約衝突彙總起來,恰好等於make時報的shift/reduce錯誤總數。
網上找不到資料,於是就讀書《flex and bison》,書上發現有一個選項
%glr-parser
%expect 67
其中那個67是來自於移進歸約的衝突總數。
然後就總算生成了awk.y的編譯文件。但其它的程序編譯時,總是不斷的報錯。
象使用bcopy,bzero等過期函數的問題,象函數沒有先定義,就使用的問題,象缺乏相關庫函數的問題,像NULL重複定義的問題,等等。
有一段時間,我甚至想,重新把庫函數的定義也複製一份放在源代碼中,因爲包含庫的話,有時會引起衝突,而且作者用了一個obstack.h,obstack.c這兩個文件來實現malloc,free之類功能,而我包含stdlib.h後,裏面也有malloc,free這兩個函數,就有衝突了,後來,我乾脆就把obstack.h中,自帶的malloc,free禁用。
改動的地方太多,我想,或許把修改後的源碼放上去較好。
最終,總算,編譯出gawk可執行程序了。
但一執行
./gawk --version
就報錯:
yang@DESKTOP-V9HS3B6:~/gawk101/gawk$ ./gawk --version
./gawk: Segmentation fault (core dumped)
因爲我是在win10下應用商站中安裝ubuntu,我實驗過,沒法生成core文件,我又卡住了。於是,心想,不是還有幾百個編譯警告嗎,於是,把這些警告信息全部去掉,或許可以執行呢。於是又開始折騰,其中一個最有名的警告是:
obstack.h中有
struct obstack /* control current object in current chunk */
{
long chunk_size; /* preferred size to allocate chunks in */
_Ll* chunk; /* address of current struct obstack_chunk */
char *object_base; /* address of object we are building */
char *next_free; /* where to add next char to current object */
char *chunk_limit; /* address of char after current chunk */
unsigned long long int temp; /* Temporary for some macros. */
int alignment_mask; /* Mask of alignment for each object. */
};
其中temp原來是int型,
#define obstack_finish(h) \
((h)->temp = (unsigned long long int ) (h)->object_base,
上面把一個指針傳爲整數後,存儲到temp中,而我的系統是win10
64位系統,存儲一個指針是8位。於是寫了幾個測試程序,如下:
yang@DESKTOP-V9HS3B6:~/gawk101$ cat t4.c
#include<stdio.h>
int main()
{
int i;
printf("%p\n",&i);
unsigned long long dizi=&i;
printf("%lld,%p\n",dizi,dizi);
return 0;
}
yang@DESKTOP-V9HS3B6:~/gawk101$ cat t5.c
#include<stdio.h>
int main()
{
unsigned long long int i=100;
printf("%lld\n",i);
printf("%llx\n",i);
return 0;
}
於是,就把temp由int改爲unsigned long long int,這樣,就好了。
還有許多。逐一去掉後。再一執行
./gawk --version
還是錯誤。後來,我腦洞大開,是否我沒有--version選項,果然。我再試下。
./gawk
./gawk: usage: ./gawk {-f progfile | program } [-F{c} -R{c}] file . . .
yang@DESKTOP-V9HS3B6:~/gawk101/gawk$ echo "hello world" | ./gawk '$1 ~ /ll/'
hello world
可稍複雜的例子,就報錯了:
yang@DESKTOP-V9HS3B6:~/gawk101/gawk$ echo "hello world" | ./gawk '{print $0 }'
Ambiguity detected.
Option 1,
statements -> <Rule 24, tokens 2 .. 5>
statements -> <Rule 22, empty>
statement -> <Rule 41, tokens 2 .. 5>
LEX_PRINT <tokens 2 .. 2>
$@3 -> <Rule 40, empty>
expression_list -> <Rule 59, tokens 3 .. 4>
exp -> <Rule 69, tokens 3 .. 4>
variable -> <Rule 98, tokens 3 .. 4>
'$' <tokens 3 .. 3>
v_exp -> <Rule 88, tokens 4 .. 4>
NUMBER <tokens 4 .. 4>
redirection -> <Rule 54, empty>
statement_term -> <Rule 25, tokens 5 .. 5>
NEWLINE <tokens 5 .. 5>
optional_newlines -> <Rule 52, empty>
Option 2,
statements -> <Rule 23, tokens 2 .. 5>
statement -> <Rule 41, tokens 2 .. 5>
LEX_PRINT <tokens 2 .. 2>
$@3 -> <Rule 40, empty>
expression_list -> <Rule 59, tokens 3 .. 4>
exp -> <Rule 69, tokens 3 .. 4>
variable -> <Rule 98, tokens 3 .. 4>
'$' <tokens 3 .. 3>
v_exp -> <Rule 88, tokens 4 .. 4>
NUMBER <tokens 4 .. 4>
redirection -> <Rule 54, empty>
statement_term -> <Rule 25, tokens 5 .. 5>
NEWLINE <tokens 5 .. 5>
optional_newlines -> <Rule 52, empty>
Error near line 1, '{print $0 }'
syntax is ambiguous
yang@DESKTOP-V9HS3B6:~/gawk101/gawk$
天啦,看來,還是我要對bison進行深入的學習,前面加了glr分析選項,是讓其可以繼續分析下去,但衝突終究是存在的。可惜的是,我看不懂這個衝突呀,我怎麼看,好像都沒有衝突的樣子。
網上找資源,其中有一位翻譯了bison中文操作手冊,但也沒有速成辦法。還是要對awk.y進行深入分析。我想用高一版本的gawk中,awk.y的內容進行替換,但發現gawk2中,awk.y的內容就完全不相同了。
這些大師爲何會對awk.y進行如此大修改呢。
真的,我發現編譯老版本程序太麻煩,真想放棄算了,直接讀高版本代碼不是更好嗎。但下載了gawk最新版本的源程序,安裝起來,真是無比順暢,可一打開源碼,太多了,和gawk1.01比起來,多了不少。心想,我看gawk1.01都這麼熟悉了,還是看1.01吧。於是,又接着分析bison,心想,別人都能寫出來,我難道還看不出來嗎。
另外,英語不懂,就安裝必應翻譯後,把obstack.h改爲obstack.txt,在翻譯軟件中打開文件後,一邊讀翻譯後的內容,一邊讀源碼。
發現,C語言的問題好解決,但bison的問題不好解決。
本來,想,自己這半瓶水,就不寫博客了,但心想,反正是自己看着玩的,還是寫下來吧。今天要上班,也不能花太多時間去讀源碼。
我這回有了成功編譯gawk1.01的經驗,下次估計真能把ruby049也搞成功。
我還是堅信,讀最老版本的源碼,收穫大於讀最新版本的程序。因爲讀老版本程序,會有一種大局觀,而讀新版本的程序,量太大,你只能就某個細節進行學習,你沒時間,也沒能力把全部源碼讀通。
而一旦對程序有一種大局觀後,我就不怕了。麻雀雖小,五臟俱全呀。繼續努力!