移植するぞ

ちい散歩じゃなくて雄三散歩でもなくて、早朝sakae散歩です。

普段は猫なんて見かける事は無いんだけど、どうした事か3匹の猫達に出会ってしまったよ。 きっと前夜は、この地区の年次猫集会でも有ったんだろうな。話合われた内容は、領土(なわばり) 問題、食料(ねずみ)の年間取得量問題、そして子猫に対する交通安全確保問題ぐらいかな。 これ以上の事は、宮沢賢治さんの本でも参照かな。

猫会議は人目に付かないように深夜行われる。猫社会でもきっと会議の後は宴会になるんだろな。 猫の場合は酒よりも、またたびが好物のはずだから、またたびパーティが開かれたに違いない。 泥酔状態では家に帰れないだろうから、あちこちで興奮を鎮めていたと思われる。

そんな彼(彼女)らに出会ったんだろうな。三毛猫は、りんご畑の下でうずくまっていた。もう一匹は、 茶トラ模様君、畑の畝の間で寝てた。最後の奴は、よろよろと道を横切る黒猫だった。 あれ? 黒猫が目の前を横切ると、何とかって迷信が有ったようだけど、今は思いだせんぞ。

おいらの家でも昔、猫を飼っていた事がある。引越しをした時、新しい家に馴染まず、女房が 手を焼いて、実家に預けたなあ。両親にかわいがられて幸せだったんだけど(きっと猫総会にも 新参猫として出席したに違いない)、りんご畑と道路の区別が付かなかったみたいで、交通事故 にあって亡くなってしまった。冬はゆたんぽがわりで、重宝した事を今になって思い出したよ。

そう言えば、友人も猫を飼っているそうなんだけど、隣家の猫と大喧嘩の果てに(名誉の?) 重症を負ってしまい、病院へ入院したとか。治療費が10万円を超えたとぼやいていたぞ。

それだけで済めば良かったんだけど、退院して家に戻った猫君。気がたっていたらしくて、 ご主人様の足の親指を噛んだとか。爪が剥がれる重症で、人間様も大事になったらしい。

たかが猫、されど猫。

sasagawa888さんのschemeを試す

SECDマシンに魅せられて、自分の勉強の為に、Simpleと言うSchemeコンパイラを開発されている 人が居る。

その開発記録が公開 されていて、興味深く読ませてもらっている。

Windows上で開発されているとの事なので、おいらも試しに、FreeBSDで動くか(野次馬根性丸だし) やってみたい。実を言うと、ソースが公開された直後に、一度トライした事が有るんだけど、 コンパイルでエラーを喰らって、投げ出していたんだ。

今回は旨くいくか、早速やってみる。

[sakae@secd ~/Simple-eed5d5d]$ make
gcc -c main.c
main.c:10:21: error: windows.h: No such file or directory
In file included from main.c:14:
simp.h:1: error: stray '\357' in program
simp.h:1: error: stray '\273' in program
simp.h:1: error: stray '\277' in program
main.c: In function 'main':
main.c:26: warning: return type of 'main' is not 'int'
*** Error code 1

Stop in /usr/home/sakae/Simple-eed5d5d.

ありゃ、エラーですよ。

\xef\xbb\xbf
/* simple (simple Scheme compiler)
written by kenichi sasagawa 2012/1
*/
  :

vimでは見えないけど、viで開くと、simp.hの行頭にゴミ文字が見えたので、消す。それから、 ここは、FreeBSDなので、windows.hも消した。で、どうかな?

[sakae@secd ~/Simple-eed5d5d]$ make
gcc -c main.c
main.c: In function 'main':
main.c:26: warning: return type of 'main' is not 'int'
gcc -c cell.c
cell.c:361:2: warning: no newline at end of file
gcc -c list.c
list.c:546:2: warning: no newline at end of file
gcc -c function.c
gcc -c compute.c
gcc main.o cell.o list.o function.o compute.o -o simp
main.o: In function `printflt':
main.c:(.text+0x52b9): undefined reference to `floor'
cell.o: In function `norm_comp':
cell.c:(.text+0xb78): undefined reference to `floor'
function.o: In function `f_integerp':
function.c:(.text+0x45c): undefined reference to `ceil'
 :

まだエラーだ。でも、floorとかcellとか、数学関係者が居ないって事だな。ならば、makefileに、-lm を 追加しよう。ついでに、軟弱になって、-g も付けてgdbで追えるようにしておこう。

[sakae@secd ~/Simple-eed5d5d]$ make
gcc -g -c main.c
main.c: In function 'main':
main.c:26: warning: return type of 'main' is not 'int'
gcc -g -c cell.c
cell.c:361:2: warning: no newline at end of file
gcc -g -c list.c
list.c:546:2: warning: no newline at end of file
gcc -g -c function.c
gcc -g -c compute.c
gcc main.o cell.o list.o function.o compute.o -o simp -lm

コンパイル完了! こんなに簡単に移植できんの?

[sakae@secd ~/Simple-eed5d5d]$ ./simp
educational Scheme compiler Simple Ver0.17.4 (written by sasagawa888)
セグメンテーション違反: 11 (コアダンプ)

甘かったわい。さて、何処で落ちてるのかな?

[sakae@secd ~/Simple-eed5d5d]$ gdb simp simp.core
GNU gdb (GDB) 7.4 [GDB v7.4 for FreeBSD]
  :
Program terminated with signal 11, Segmentation fault.
#0  0x0804fe60 in cdr (lis=675593984) at list.c:30
30              return(GET_CDR(lis));
(gdb) bt
#0  0x0804fe60 in cdr (lis=675593984) at list.c:30
#1  0x080510e7 in macronamep (sym=644) at list.c:457
#2  0x08049bf6 in comp (expr=733, env=757, code=762, tail=1) at main.c:245
#3  0x080490a7 in comp (expr=740, env=757, code=761, tail=1) at main.c:116
#4  0x08049126 in comp (expr=746, env=757, code=756, tail=1) at main.c:120
#5  0x08049eb9 in comp_body (body=747, env=757, code=756) at main.c:282
#6  0x08049325 in comp (expr=749, env=0, code=755, tail=5) at main.c:139
#7  0x0804951d in comp (expr=752, env=0, code=753, tail=5) at main.c:154
#8  0x08048eea in compile (expr=752) at main.c:88
#9  0x08055070 in f_load (lvar=580) at function.c:1514
#10 0x08048c63 in main () at main.c:33

cdrに渡される値が、どうも範囲外のようだ。得意のvimとgdbの合わせ技で、ソースを見ながら 追ってみるか。と、思ったんだけど、貴重なコメントが、SJISのようで、ことごとく文字化け しちゃう。ここは、将来の事を考えて、utf8に変換しておこう。インデントが4tabだったり8tab だったりして落ち着かないので整頓しておく。ついでに、ctagsで、すいすい tag-jump出来るようにしておこう。

for f in *.[ch]
do
        nkf  -w $f >$$
        cat $$ | sed -e 's%//\(.*\)%/*\1*/%' >$f
        #indent $f -i4
        gindent $f -kr
done
rm -f *.BAK $$ *~
#ctags *.[ch]
exctags *.[ch]

これ、上記の贅沢な要求を叶えるスクリプト。最初、indentはFreeBSD備え付けのやつを使って いたんだけど、// comment を、2行に分解しちゃうんで、GNU製のやつにした。ctagsも機能豊富 なやつに取り替えた。

ctags と indent

ちょいと寄り道して、ctagsとindentを調べてみた。

ctagsって、vi(m)で、CTRL+] と CTRL+t で、関数間をすいすい飛び回るやつ。ソース閲覧ツール だ。これの対抗馬は、globalなんだけど、vimを使うようになってからは、もっぱらctagsを 使ってる。

最近は、私の心代わりを察知したかどうかか知らないけど、 globalを解説した本が、出版されたようだ。 いろいろ出来るようで、面白そう。でもまあ、ctagsだって、いろいろな言語をサポートして 元気一杯みたいだしなあ。

[sakae@secd /usr/ports/devel/ctags]$ cat pkg-descr
Exuberant Ctags generates an index (or tag) file of source language
objects in source files that allows these items to be quickly and
easily located by a text editor or other utility.

Alternatively, it can generate a cross reference file which lists,
in human-readable form, information about the various objects found
in a set of source code files.

Supported languages include: Assembler, ASP, AWK, BETA, C, C++, C#,
COBOL, Eiffel, Fortran, HTML, Java, Javascript, Lisp, Lua, Make,
Pascal, Perl, PHP, PL/SQL, Python, REXX, Ruby, S-Lang, Scheme, Shell
(Bourne/Korn/Z), Standard ML, Tcl, Vera, Verilog, Vim and Yacc.

WWW:    http://ctags.sourceforge.net/

まあ、これぐらいの言語をサポートしてくれていたら、不自由する事は無いわな。 FreeBSDでは、自分で入れないと恩恵に与れないけど、GNUで出来ているLinuxだと、デフォで 使えるはず。(最近の軟弱なDesktopバージョンだと、入っていないかな?)

indentは、Cのソース用の整形ツールだ。FreeBSDではデフォで入っているけど、ちょっと融通が 利かない。(上の例みたいに、一行コメントを旨く扱えないとか)そこで、GNU版に頼る事に なる。

さすが、GNU版って事で、GNUがお勧めする(行稼ぎに貢献?)スタイルに整形するってのがデフォ の挙動だけど、Kernighan & Ritchie style とか、original Berkeley風とか、 Linux風とかも オプション一発で指定出来るようになっている。おいらは、勿論、 "The C Programming Language"本 風ですよ。それ以外は有り得ないっていう老人風頑固ささ。

上で、vimを使って、すいすい飛び回るって書いたけど、それを加速するvimのプラグインを 発見したよ。 taglistがそうなんだ。 何とvim語で4500ラインもある超大作です。よく書くわと感心せまそう。

てけとーにソースファイルを読み込んだ後こやつを起動すると(:Tlistで)、画面が左右に割れて、左側に変数名とか関数名のリストが 出て来る。CTRL+w で、左側に移動してからカーソルを合せてENTERを叩けば、飛んでく。 matzさんじゃないけど、名は体を表すんで、大体どんな風になってるかソースの構造を想像 出来て便利ですたい。

比較法

さてどうやってデバッグしよう。ものは試しと言う事で、Linuxで動くか確認してみる。だって、 オリジナルは、Windows上のMinGW環境なんだから、これほとんどLinuxと看做せるよね。

ArchBangへ持って行ったら動いちゃったよ。ちょいとおかしな事はあるけど。

educational Scheme compiler Simple Ver0.17.4 (written by sasagawa888)
Simp> (car '(a b c))
a
Simp> (exit)
Segmentation fault

macronamep(って、Cじゃ?が使えないからLisp風ネーミング)で止めて、比較してみる。 最初は、FreeBSDの場合

 (gdb) where
  #0  macronamep (sym=644) at list.c:507
  #1  0x08049bf6 in comp (expr=733, env=757, code=762, tail=1) at main.c:283
  #2  0x080490a7 in comp (expr=740, env=757, code=761, tail=1) at main.c:145
  #3  0x08049126 in comp (expr=746, env=757, code=756, tail=1) at main.c:149
  #4  0x08049eb9 in comp_body (body=747, env=757, code=756) at main.c:325
  #5  0x08049325 in comp (expr=749, env=0, code=755, tail=5) at main.c:166
  #6  0x0804951d in comp (expr=752, env=0, code=753, tail=5) at main.c:184
  #7  0x08048eea in compile (expr=752) at main.c:116
  #8  0x08055070 in f_load (lvar=580) at function.c:1626
  #9  0x08048c63 in main () at main.c:35

こちらは、ArchLinuxの場合

  (gdb) where
  #0  macronamep (sym=646) at list.c:507
  #1  0x08049a33 in comp (expr=735, env=759, code=764, tail=1) at main.c:283
  #2  0x08048f3e in comp (expr=742, env=759, code=763, tail=1) at main.c:145
  #3  0x08048fbb in comp (expr=748, env=759, code=758, tail=1) at main.c:149
  #4  0x08049cc6 in comp_body (body=749, env=759, code=758) at main.c:325
  #5  0x080491a9 in comp (expr=751, env=0, code=757, tail=5) at main.c:166
  #6  0x0804938f in comp (expr=754, env=0, code=755, tail=5) at main.c:184
  #7  0x08048d9b in compile (expr=754) at main.c:116
  #8  0x08054116 in f_load (lvar=580) at function.c:1626
  #9  0x08048b17 in main () at main.c:35

見て分かるように、compileに渡る引数がずれてる。これが不幸の始まりなのね。さて、この後 どうしよう? しばし、作戦会議だな。困ったら、猫の手でも借り手くるか。 たまには、猫の肉球、ぐりぐりして、癒されたいぞ。