cut 比べ

結城さんの本を苦労しながら読んでいる。球面幾何。普通の頭では意味不。脳に汗をかきながらね。巻末に参考資料が紹介されていた。

数学:物理を学び楽しむために

以前、ここに来た事あるぞ。確かipadに入れて読んだ記憶がある。調べてみたら2012版のものが入っていた。

それから幾年月。加筆訂正されて、更にはPDF内をあちこち飛び回れるようにリンクが縦横無尽に貼られている。ぼけた頭には嬉しい機能。そして年寄り向きに、拡大フォント版も用意されてる。図書館にある弱視用の本の作りだ。これはもう、最初からじっくり取り組むしか。

売られている電子書籍でも、索引が付いていなかったり、あちこちに飛べなかったりの粗悪品が沢山あるそうな。あの人が嘆いていた。彼の眼にはこのPDFはどう映るのかねぇ、是非聞いてみたいぞ。

会社を定年退職した元同僚と、たまには連絡してるんだけど、彼は分子工学とかにはまって、頭を捻っているらしい。大人の自由研究、大いに結構じゃないですか。

不幸は続く

メインで使ってるWindows10機が、この所不調。前回は、IMEが早とちり症候群に侵されて、どうしようもなく、WSLなんてのに走ってしまった。

今は、マウスが奔放に走り回ってしまい、手に負えない。マウスのポインターを見失ってしまうので、年寄り向きの大マウスポインターに切り替えた。これで少しは、何処にいるか分かり易くなるだろう。

不幸は続いてやってくる。突然にね。 試しで入れているVMWare上のUbuntuが起動しなくなった。

小さいコンソールなんで、メッセージが読めないよ。CMでやってるハズキルーペが欲しくなる。以前、ホームセンターで、もどきが売られているのを見たんで、こんな時用に一つ買っておくか。

虫眼鏡で拡大したら、fsckやれば直るかも、、、なんて言ってる。

普通にfsckって叩いてもエラーで撥ねられた。fsck /dev/sda1 としたら、認可されたよ。でも、永遠に続くかと思われる、祈ってyするか、すっ飛ばすかの質問。いやになる程ね。

で、やっと解放されて、動き出した。やられていたのは、カーネルのヘッダーの所だった。 こういう場合は、再度ヘッダー部分を入れ直した方がよいのだろうか?

まあ、行ける所まで行って、だめになったら縁の切れ目とばかり Kubuntuでも入れてみるか。(密かにダメになる事を期待してるオイラーが居る。悪魔の心を持った人だな)

で、少しこの不幸続きを考察しておくかな。

一番怪しそうなのは、SSDかな。どこ製だ。ウブが立ち上がっているので、dmesgしたけど、馬鹿dmesgで、ハード寄りな情報は出てこない。

sakae@ub:~$ sudo dmesg | grep sda
[    3.476829] sd 2:0:0:0: [sda] 83886080 512-byte logical blocks: (42.9 GB/40.0 GiB)
[    3.477012] sd 2:0:0:0: [sda] Write Protect is off
[    3.477016] sd 2:0:0:0: [sda] Mode Sense: 61 00 00 00
[    3.477226] sd 2:0:0:0: [sda] Cache data unavailable
[    3.477232] sd 2:0:0:0: [sda] Assuming drive cache: write through
[    3.479912]  sda: sda1
[    3.481106] sd 2:0:0:0: [sda] Attached SCSI disk
[    4.006302] EXT4-fs (sda1): mounted filesystem with ordered data mode. Opts: (null)
[    4.630005] EXT4-fs (sda1): re-mounted. Opts: errors=remount-ro

BSDに慣れた人には、違和感を感じるぞ。

sakae@ub:~$ sudo parted -l
Model: VMware, VMware Virtual S (scsi)
Disk /dev/sda: 42.9GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type     File system  Flags
 1      1049kB  42.9GB  42.9GB  primary  ext4         boot

実マシンにウブを入れていても、こうやってコマンドを叩くしかないのか? ああ、以前、FuguItaを動かした時の記録が残っていたな。

sd0 at scsibus1 targ 0 lun 0: <ATA, SAMSUNG MZ7LN256, EMT0> SCSI3 0/direct fixed naa.5002538d00000000
sd0: 244198MB, 512 bytes/sector, 500118192 sectors, thin

次に疑うのは、メモリーかな。宇宙人がいたずらに、強力な宇宙線を放射していたりして。 それで、メモリーがソフトエラーを起こした。でも、民生用のパソコンにECCなんて機能は 積んでいない。よって、エラーが見逃されてしまったとな。

spdmem0 at iic0 addr 0x50: 4GB DDR3 SDRAM PC3-12800 SO-DIMM
spdmem1 at iic0 addr 0x52: 4GB DDR3 SDRAM PC3-12800 SO-DIMM

これだけじゃ、メーカー名とかは特定出来ず。

症例も沢山集まった事だし、総合診療医に久しぶりに連絡を取ってみるかな。現在、先生は岩手の山奥で、隠遁生活をしてるとか。元気してるかな?

NetBSD 7.1.2

Debian機にNetBSDを入れてたのを思い出した。vboxでは途中でエラーになるんで (OpenBSDも同様)、qemuに入れた。複数のアプリが使えると、こういう場合は有り難い。 心配していた速度も面も、同じ石を利用するせいか、余り気にならない。この点、qemuでarmをやろうとすると、気が遠くなる程、待たされる。

nb712$ df
Filesystem   512-blocks       Used      Avail %Cap Mounted on
/dev/wd0a       1050478     172782     825174  17% /
/dev/wd0f        493918     124920     344304  26% /var
/dev/wd0e      23825004    6159360   16474396  27% /usr
/dev/wd0g      14735116         28   13998336   0% /home
tmpfs            845064          8     845056   0% /tmp
kernfs                2          2          0 100% /kern
ptyfs                 2          2          0 100% /dev/pts
procfs                8          8          0 100% /proc
tmpfs            130808          0     130808   0% /var/shm

インストールした時、お任せと言うか、スライスを切るのが面倒だったので、こんな風に分かれてしまった。これが正しい切り方なんだろうね。

pkgin install emacs とかすると、/varの下にpkgの素材がキャッシュされるんで、適時に クリアする事が肝要だ。

nb712$ ls /usr/src/sys/arch
CVS          atari        evbsh3       landisk      next68k      sparc
Makefile     bebox        evbsh5       luna68k      ofppc        sparc64
README       cats         ews4800mips  m68k         playstation2 sun2
aarch64      cesfic       hp300        mac68k       pmax         sun3
acorn26      cobalt       hpc          macppc       powerpc      sun68k
acorn32      dreamcast    hpcarm       mips         prep         usermode
algor        emips        hpcmips      mipsco       rs6000       vax
alpha        epoc32       hpcsh        mmeye        sandpoint    x68k
amd64        evbarm       hppa         mvme68k      sbmips       x86
amiga        evbarm64     i386         mvmeppc      sgimips      xen
amigappc     evbcf        ia64         netwinder    sh3          zaurus
arc          evbmips      ibmnws       news68k      sh5
arm          evbppc       iyonix       newsmips     shark

相変わらず、石の博物館状態。世間から忘れ去られた石が陳列されてる。これ全部、最新のカーネルが動いているのだろうか? NetBSDの人に聞いてみたいぞ。

手元にも置いておきたいと思って、64Bit機にも入れてみた。そろそろ8.0が秒読みみたいで、 近くにあるサーバーからはpkgが消えていた。そこで、下記のように集積地を探して設定(Install時)したよ。

nb$ cat /usr/pkg/etc/pkgin/repositories.conf
 :
http://cdn.netbsd.org/pub/pkgsrc/packages/NetBSD/amd64/7.1.2/All

Index of pub/pkgsrc/packages/index.html

から辿って行けば良い。

cut

前回の最後にちょろっと登場した、cut君。tasklistから必要なものを取り出すのに使った。 取り出したものを、ps風に並び変えようと、

cut -f2,1,5,6,7 -d','

とか、やっても、フィールドの並びは、-f1,2,5,6,7 のようになってしまう。こういう時は、四の五の言わずにソースに当たれ。ああ、その前に仕様書のmanが先か。 一番きちんとしてる、OpenBSDをみます。

     Column and field numbering starts from 1; output is in the same order as
     input, not in the order selected.

対訳

     列番号とフィールド番号は1から始まります。 出力は入力と同じ順序であり、
     選択された順序ではありません。

オイラーみたいに、そそっかしい人向けの説明が、きちんとなされている。結局、オイラーの早とちりだった訳ね。で、参考にawkをどうぞって紹介されてたぞ。親切だなあ。

STANDARDS
     The cut utility is compliant with the IEEE Std 1003.1-2008 ("POSIX.1")
     specification.

いにしえの昔から有るコマンドと思っていたら、そうでもないのね。

HISTORY
     A cut command appeared in AT&T System III UNIX.

FreeBSDには、こんな記述が有ったぞ。いきなりPOSIXに登場するはずは無いものね。色々な資料に当たるのは重要。

IEEE Std 1003.1-2008 (Revision of IEEE Std 1003.1-2004)

規格書は著作物で、購入してください。と、アメリカの団体は申しております。(US$240)日本もそだね。 だったら、規格書替わりにmanとソースを読むのさ。

ob6$ cut
usage: cut -b list [-n] [file ...]
       cut -c list [file ...]
       cut -f list [-s] [-d delim] [file ...]

なお、現場にmanもソースも無い場合、コマンドを思い出せるようにヒントが用意されてるよ。

あっ、うろうろしてたら、 POSIXの規格書(JIS版)なんてのに出会って、 このページをずっと下の方にスクロールしてくと、SFUなんてのが出て来る。 マイクロソフトは、今WSLを一生懸命に押しているけど、昔はSFUなんてのをやってたね。 懐かしいな。SFUみたいにWSLを投げ出すなよ。梯子を外すんじゃねーぞ。>MS。

SFU 3.5はなぜ無償化されたのか

source収集

折角なので、cutコマンドのソースを集めてきて、比べてみるかな。BSD系は、何の苦労もなく集められる。/usr/src/usr.bin/cut の中にあるからね。例えば、OpenBSDなら

sakae@ub:~/cut/ob$ ls
cut.1  cut.c  Makefile

こんな具合に、manの原稿、ソース、バイナリー作成自動化レシピ(Makefile)が、セットになって置いてある。ソースが複数になる場合は、ヘッダーファイルが(大体)付属してる。

問題は、Linuxだ。まあ、第二のWindowsを目指すOSとしては、ソース? 何それ、美味しいのって人が大半。目の前に美味しいソースが大量に有るのに、それを見ずして、OSS素晴らしいと言う人ばかりだからね。

cut.cが、どのモジュールに入っているか同定する所から始める。そのためには、ちょっとした下準備が必要。

sudo apt install apt-file
sudo apt-file update
sudo vi /etc/apt/source.list
  :
deb-src http://us.archive.ubuntu.com/ubuntu/ bionic main restricted
sudo apt update

何か所か、コメントされてるdev-srcのコメントを外す。 以上は、ソースと仲良くなる為の儀式と言うか、ソース倶楽部への登竜門。

早速、cutのソースを探してみる。

sakae@ub:/tmp$ apt-file search /usr/bin/cut
abinit: /usr/bin/cut3d
autocutsel: /usr/bin/cutsel
coreutils: /usr/bin/cut
  :

coreutilsに収納されてる事が分かったので、後はゴミがちらからないように適当なdirを作って、その中で、

sudo apt source coreutils

すれば良い。coreutils-8.26なんてdirの中にsrcが有り、その中にcut.cが入っている。他にも有名な所では、ls.cなんてのも有る。このlsを題材に本を一冊書いた方がおられたな。 lsを読まずにプログラマを名乗るな!

若干リナのソース集めに苦労したけど、下記のようになった。

sakae@ub:~/cut$ wc */*.c
  479  1775 11028 fb/cut.c
  609  2048 16866 li/cut.c
  306  1168  7500 nb/cut.c
   95   468  2953 nb/x_cut.c
  330  1153  7284 ob/cut.c

ざっと見、fb(FreeBSD)とli(Linux)の行数が大きいなあ。似た者同士? nb(NetBSD)は、ソースが二本立てだよ。ob(OpenBSD)が、一番すっきりしてる。

man 比べ

ソースがリナに集まってしまったものだから、文書を大事にするBSD系のmanは読めないな。 はて、どうする?

sakae@ub:~/cut$ mkdir -p man/man1
sakae@ub:~/cut$ mv fb/cut.1 man/man1/fb.1
sakae@ub:~/cut$ mv nb/cut.1 man/man1/nb.1
sakae@ub:~/cut$ mv ob/cut.1 man/man1/ob.1
sakae@ub:~/cut$ man -M /home/sakae/cut/man nb

一次的にman用の構造を作り、そこに原稿を放り込む。後は、manpathを指定して読む。

リナの場合は、manはもう古いしきたりとばかりに、余り大事にされていない模様。その代わり、バイナリーに説明が埋め込まれているな。

sakae@ub:~/cut$ cut --help
Usage: cut OPTION... [FILE]...
Print selected parts of lines from each FILE to standard output.
          :
  N     N'th byte, character or field, counted from 1
  N-    from N'th byte, character or field, to end of line
  N-M   from N'th to M'th (included) byte, character or field
  -M    from first to M'th (included) byte, character or field

GNU coreutils online help: <http://www.gnu.org/software/coreutils/>
Full documentation at: <http://www.gnu.org/software/coreutils/cut>
or available locally via: info '(coreutils) cut invocation'

GNU は、manよりinfoがお好みのようです。emacsのinfoを使う派が健在なんですかね。 オイラーは、infoだとsearchが面倒(と、思っているだけかも)なんで、余り使っていない。 この習性を修正せんとな。

2本立てのNetBSD

ざっくりwcした時、NetBSDは2本立てだった。行数からして、1本にしちゃっても何の問題も 無いと思うんだけど。。。ソースを見れば、何か分かるかも。

x_cut.cにその理由が述べられていた。

/*
 *  This file is #include'd twice from cut.c, to generate both
 *  single- and multibyte versions of the same code.
 *
 *  In cut.c #define:
 *   CUT_BYTE=0 to define b_cut (singlebyte), and
 *   CUT_BYTE=1 to define c_cut (multibyte).
 *
 */

#if (CUT_BYTE == 1)
#  define CUT_FN                b_cut
#  define CUT_CH_T              int
#  define CUT_GETC              getc
#  define CUT_EOF               EOF
#  define CUT_PUTCHAR           putchar
#else
#  define CUT_FN                c_cut
#  define CUT_CH_T              wint_t
#  define CUT_GETC              getwc
#  define CUT_EOF               WEOF
#  define CUT_PUTCHAR           putwchar
#endif

void
CUT_FN(FILE *fp, const char *fname __unused)
{
        CUT_CH_T ch;
        int col;
        char *pos;
  :

バイト単位でcutするのも文字単位でcutするのもやり方は同じ。ただ内部で使う関数とかが違うだけだよと。だったら、マクロ(風)にしちゃえ。なる程ね。

cut.c 内の、最後の所で、マクロ呼び出しが来ています。展開はincludeって事は、cppがやってるのね。なんか、lispみたいだな。面白いぞ、NetBSD!

/* make b_put(): */
#define CUT_BYTE 1
#include "x_cut.c"
#undef CUT_BYTE

/* make c_put(): */
#define CUT_BYTE 0
#include "x_cut.c"
#undef CUT_BYTE

Linuxのソースは外国語

みたいに思える。その一つに、コメントの丁寧さが有ると思うぞ。emacsで閲覧してると、色が 付くんで、コメント色は飛ばせば済む事なんだけど、ついつい目がトレースしちゃうんだよな。

どのぐらい、コメント入ってる? コメントをcutして行数を数えるか。まずは、コメントを削除するプログラムを探す。(他人任せですみません)

Cソースファイルからコメント行だけを削除する

Java や C/C++ のコード中のコメントを削除する

python版をコピペ。対象ファイルは埋め込んでます。コメントの有った所は、空行になるんで、 後で、空行を削除しました。

sakae@ub:~/cut/tmp$ ./del.py | wc
    610    1300   12472
sakae@ub:~/cut/tmp$ ./del.py | sed '/^$/d' | wc
    449    1300   12311

全体の1/4は、コメントでした。親切なんだな。

でも、コメントは英語。そしてソース内で使われている変数名とかも、どなたかのご指導により、英語の長ったらしいものが使われてる。ソース全体が黒っぽい英文に見えるんだ。インデントが、2に設定されてるんで、余計に拍車がかかっている。

英語ネイティブな人にはいいだろうけど、母語が日本語の人には辛い。 そこに眼を付けた人が居た。

スラスラ読める Pythonふりがなプログラミングなんてのや、Javascript版が出てる。こういう風に単語が母語で理解出来ると、嬉しいぞと。

source code 類似性

BSD系のソースは、似てると思うんだけど、どのぐらい似てる? diffでいいじゃんなんてのは駄目。そこで、上の検索語で聞いてみた。

出てきたのは、学術論文の類。大学ではコピペが流行っているんで、それを検出するために、先生方は、日夜研究に励んでおられるんだな。コードが公開されないのは、学生に裏をかかれないようにする為に違いない。

最近のトレンドは、人口知能で賢く検出しましょって事らしい。何とかしたいと言う、切実な現実的が有るんでしょうな。

で、下記の物が使えそう。

リファクタリングのお供に。ソースコードの類似点を検索する「Unique」

MariaDB と MySQL のソースコードの類似度を調べる

ソースコード同士の類似性評価ツールを作ってみた

たまには、手を動かしてみるかって事で、Windows用に作られているものをlinux用に移植してみる事にする。

#!/bin/sh
# Usage: copipeP.sh ref-file cmp-file

a=$1
b=$2

saa=`cat $a $a | wc -c`
zaa=`cat $a $a | gzip -c | wc -c`
faa=`echo "$zaa * 10000 / $saa" | bc`

sab=`cat $a $b | wc -c`
zab=`cat $a $b | gzip -c | wc -c`
fab=`echo "$zab * 10000 / $sab" | bc`

echo "Same file : 100,  Differ file : > 100"
echo "$fab * 100 / $faa" | bc

手を動かす程の事は無かった。コードを書いて、C-c C-x で検証しながらね。

sakae@ub:~/cut/tmp$ ./copipeP.sh li.c li.c
Same file : 100,  Differ file : > 100
100
sakae@ub:~/cut/tmp$ ./copipeP.sh li.c fb.c
Same file : 100,  Differ file : > 100
197
sakae@ub:~/cut/tmp$ ./copipeP.sh ob.c fb.c
Same file : 100,  Differ file : > 100
132

同一ファイルは、勿論100。リナとBSDは、似ていない。BSDでも、同族系なら似てると判定。 妥当な結果ですな。

もう少し、実例っぽいやつをやる。Javascriptを手元でガシガシ書いた。Webに上げる時、難読化と称して、コメントを外したりする事がある。そういうのと元ファイルの一致度は、どうなん?

sakae@ub:~/cut/tmp$ ./del.py >noc.c
sakae@ub:~/cut/tmp$ wc li.c noc.c
  609  2048 16866 li.c
  610  1300 12472 noc.c
sakae@ub:~/cut/tmp$ ./copipeP.sh li.c noc.c
Same file : 100,  Differ file : > 100
116
sakae@ub:~/cut/tmp$ ./copipeP.sh noc.c li.c
Same file : 100,  Differ file : > 100
130

コメントを外したnoc.cを作る。元ファイルを基準にすると、類似度は116で、非常に似ている判断(で、いいかな)。

逆のパターンもやった。想定は、コメントも何も無いファイルを落としてきて、それを解析、コメントを付けた。これで、ソースレベルでは、オリジナリティが出た。類似度は130で、元と似てない度が高まった。

そうか、色々なソースを解析して、これにコメントを追加していくと、誰からも文句を付けられないものが出来上がる。本を上に出て来た人のように出版出来るとな。

その元祖は、 2238クラブ に出てくるLions本。 それを近代化させた、 はじめてのOSコードリーディング なんかに、なるわけだ。

cutの肝

折角なので、cutのコードを見ておく。素直なFreeBSDでgdbを使って、要所を押さえる。

cut -b 10-20,24-28 cut.c

を実行。文字を拾い出すためのフラグをmainの中でget_listを呼び出して設定してる。 下記は、その設定が終了した時の図。

(gdb) x/30xb positions
0x800e17000:    0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x800e17008:    0x00    0x00    0x01    0x01    0x01    0x01    0x01    0x01
0x800e17010:    0x01    0x01    0x01    0x01    0x01    0x00    0x00    0x00
0x800e17018:    0x01    0x01    0x01    0x01    0x01    0x00

文字のポジションで拾うべき所が1に設定されている。拾わなくても良い所は、zeroになってる。needpos関数によって、この配列を拡張かつ初期値をzeroに設定。そのうち拾うべき所に1を書いて、目印を作っている。

それじゃ、10- のような無限大とも解釈出来る要求をどう解決する? そんな配列定義出来ないぞ。

そういう不都合を吸収する為に、大域変数 autostart, autostop, maxvalが使われています。これらの変数の設定条件によって、無限を上手く吸収してます。詳しくはsourceで。

OpenBSDでは、このpositions配列サイズが決め打ち。NetBSDでは、

static size_t autostart, autostop, maxval;

static char *positions = NULL;
static size_t numpositions = 0;
#define ALLOC_CHUNK     _POSIX2_LINE_MAX        /* malloc granularity */

static void
get_list(char *list)
{
        :
        if (positions == NULL) {
                numpositions = ALLOC_CHUNK;
                positions = ecalloc(numpositions, sizeof(*positions));
        }
        :

こんな風に確保してる。それにしても、_POSIX2_LINE_MAX って、何処で定義されてるのだろう? 強引にサイズを調べてみる。

ob6$ cc -E cut.c | grep positions
char positions[2048 + 1];
 :

cppによるマクロ展開(かな?)。Lisp屋さんの大好きな事だ。1行の長さが2048って、まあ実用的なサイズか。でも、デザイナーベビーを作る時に使う、遺伝子塩基の切り貼りだと、もっと長い場所から切り出す事が有るだろうね。そんな時は、OpenBSDのcutを諦めて、FreeBSDなりのそれを使ってください。

上のPOSIX2_LINE_MAXを大域的に探そうと、find /usr/src なんてやったんだ。そしたら、所々でエラーが発生。findがエラーを返してきた時は、その先を辿ってくれないみたい。それで、場所を特定出来なかったのだな。探すなら、あたりを付けてincludeの下だけを対象にしろ。知らなかったのは、オイラーだけ?

なお、 最初、linuxのソースの塊からcut.cを抜き出して、gdbにかけられるようにコンパイルしようと 思ったんだけど、殊のほか面倒そうだったので、BSDに逃げた。BSDはそれぞれのコマンドが独立してて、こういう時は非常に便利。やっぱり、リナでソースを見たり解析するのは、時間の無駄、ストレス無限大になると思うぞ。オイラーもすっかり、BSD小僧になっちまったな。

etc

これは、WSLの記事と言うか、Windows屋さんをLinuxへ誘う記事。wslでもvirtualboxでも、Linuxが動けばいいよね。そして、Windowsの貧弱なターミナルを便利なものに置き換えようという戦略。

ConEmuでコンソールエミュレータを見やすくする

続いて、Xを動かすとかやるのかしら?