C言語入門(37) 実際にプログラムを読んで理解を深めよう ls編(11)

Posted: 2013年04月25日

前回まで、printstream関数を解説してきました。
今回は同じ表示処理のprintcol関数を解説していきます。

print.c printcol関数です。

プログラムプログラム:

void
printcol(const DISPLAY *dp)
{
    static FTSENT **array;
    static int lastentries = -1;
    FTSENT *p;
    FTSENT **narray;
    int base;
    int chcnt;
    int cnt;
    int col;
    int colwidth;
    int endcol;
    int num;
    int numcols;
    int numrows;
    int row;
    int tabwidth;

    if (f_notabs)
        tabwidth = 1;
    else
        tabwidth = 8;

    /*
     * Have to do random access in the linked list -- build a table
     * of pointers.
     */
    if (dp->entries > lastentries) {
        if ((narray =
            realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) {
            warn(NULL);
            printscol(dp);
            return;
        }
        lastentries = dp->entries;
        array = narray;
    }
    for (p = dp->list, num = 0; p; p = p->fts_link)
        if (p->fts_number != NO_PRINT)
            array[num++] = p;

    colwidth = dp->maxlen;
    if (f_inode)
        colwidth += dp->s_inode + 1;
    if (f_size)
        colwidth += dp->s_block + 1;
    if (f_type)
        colwidth += 1;

    colwidth = (colwidth + tabwidth) & ~(tabwidth - 1);
    if (termwidth < 2 * colwidth) {
        printscol(dp);
        return;
    }

解説解説:

表示データの領域を確保し、表示対象のみを詰めます。

領域は、足りなければ再確保、足りれば使いまわします。

また、領域が確保できない場合は、
printcolの処理は中断し
以前解説をいたしましたprintscolを呼び出します。

また、各フラグに応じた列幅を計算します。
計算した列幅*2が表示幅よりも長い場合は、
printcolの処理は中断し
printscolを呼び出します。

プログラムプログラム:

    numcols = termwidth / colwidth;
    numrows = num / numcols;
    if (num % numcols)
        ++numrows;

    if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) &&
        (f_longform || f_size)) {
        (void)printf("total %lun", howmany(dp->btotal, blocksize));
    }

    base = 0;
    for (row = 0; row < numrows; ++row) {
        endcol = colwidth;
        if (!f_sortacross)
            base = row;
        for (col = 0, chcnt = 0; col < numcols; ++col) {
            chcnt += printaname(array[base], dp->s_inode,
                dp->s_block);
            if (f_sortacross)
                base++;
            else
                base += numrows;
            if (base >= num)
                break;
            while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1)))
                <= endcol) {
                if (f_sortacross && col + 1 >= numcols)
                    break;
                (void)putchar(f_notabs ? ' ' : 't');
                chcnt = cnt;
            }
            endcol += colwidth;
        }
        (void)putchar('n');
    }
}

解説解説:

ここで、表示処理を行なっています。

  • トータルのブロック数
  • 対象のファイル、フォルダ名を

表示します。

ファイル名などは、
across(横並び)表示することが可能です。
下に実行結果を乗せたので
横並びがどのようになるかわかってもらえると思います。

表示幅の制限もあるため厳密には、違いますが

処理結果処理結果:

ls (通常表示の場合)

corder.xml magic.xml thresholds.xml type.xml
color.xml mime.xml type-dejavu.xml
delegates.xml policy.xml type-ghostscript.xml
log.xml quantization-table.xml type-window.xml

ls -x (横並び表示)

corder.xml colors.xml delegates.xml log.xml
amgic.xml mime.xml policy.xml quantization-table.xml
thresholds.xml type-dejavu.xml type-ghostscript.xml type-window.xml
type.xml

今回でlsの表示関数は異常です
次回はソート処理について書いていきます

カテゴリー: プログラム, 入門 | タグ: , , | コメント無し »

コメント