coreutils4.5.1 wc.c程式碼分析
coreutils4.5.1 wc.c程式碼分析
再讀wc.c,看出了一點眉目,有些誇張了,我只是說,對程式的大體框架有些瞭解,離能修改程式碼的程度還差得遠呢。不過,正因為是新手,所以不妨把步子邁得大些,反正就是練手,不要太多的成見在裡面。
先看main()
其中對選項的處理很簡單,設定幾個全域性量,然後分析選項時,再對全域性量賦值。邏輯如下:
while ((optc = getopt_long (argc, argv, "clLmw", longopts, NULL)) != -1)
switch (optc)
{
case 0:
break;
case 'c':
print_bytes = 1;
break;
case 'm':
print_chars = 1;
break;
原諒我不能複製得太多,不然不如看原始碼呢。
作者用到了一個技巧,當沒有給任何選項時,是行數,字數,位元組數一起顯示,如何弄的呢?
if (print_lines + print_words + print_chars + print_bytes + print_linelength
== 0)
print_lines = print_words = print_bytes = 1;
看到沒,當沒有給任何引數時,就把這三項全部為1,也就是顯示行數,單詞數,和位元組數。哈哈!
下面進入正題,開始計數。
if (nfiles == 0)
{
have_read_stdin = 1;
wc (0, "");
}
當有多個檔案要wc時,用wc_file函式進行了封裝,其實還是呼叫wc
所以繼續進入 wc函式。
這個函式,看得就想吐了。
if (count_bytes && !count_chars && !print_lines && !count_complicated)
{
}
else if (!count_chars && !count_complicated)
{
}
else if (MB_CUR_MAX > 1)
{
}
else {}
write_counts (lines, words, chars, bytes, linelength, file);
total_lines += lines;
total_words += words;
total_chars += chars;
total_bytes += bytes;
}
看到沒,當前檔案的統計完了,就列印結果,如果有幾個檔案,還要把全部檔案的加起來。
所以對wc命令的總體執行就基本清楚了。
那究竟如何統計行數、單詞數、位元組數呢?
看
else if (MB_CUR_MAX > 1)
{
}
這一段。
while ((bytes_read = safe_read (fd, buf + prev, BUFFER_SIZE - prev)) > 0)
{
const char *p;
# if SUPPORT_OLD_MBRTOWC
mbstate_t backup_state;
# endif
bytes += bytes_read;
p = buf;
其中對位元組數的統計,很簡單,就是把每次數出來的進行彙總即可。上文中,
bytes += bytes_read
那如何統計行數呢?
switch (wide_char)
{
case '\n':
lines++;
/* Fall through. */
case '\r':
case '\f':
if (linepos > linelength)
linelength = linepos;
linepos = 0;
goto mb_word_separator;
case '\t':
linepos += 8 - (linepos % 8);
goto mb_word_separator;
case ' ':
linepos++;
/* Fall through. */
case '\v':
mb_word_separator:
if (in_word)
{
in_word = 0;
words++;
}
看到沒,當遇到回車時,就把行數累加。關鍵是如何計算單詞數,作者用了一個技巧:
case '\v':
mb_word_separator:
if (in_word)
{
in_word = 0;
words++;
}
反正大致意思是,如果出現了字母,設為單詞開始,再遇到非字母時,表示已經識別了一個單詞,words++,如此這樣,但程式碼真沒看明白。只是大致知道。
等心情好時,再慢慢看吧。
我把vim字型擴大,這樣看得清楚,但每屏顯示的程式碼行數就少了。也許我要把螢幕橫著放,這樣每屏顯示的行數多些。這麼多的if,看得頭暈了。
我要睡覺了,等清醒時,再看吧。