1. 程式人生 > >coreutils4.5.1 wc.c程式碼分析

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,看得頭暈了。
我要睡覺了,等清醒時,再看吧。