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,看得头晕了。
我要睡觉了,等清醒时,再看吧。