Lisp/Scheme and OpenBSD 6.1
いつもお世話になってる、MobaXterm なんだけど、ふとHelpを見たら、新バージョンの 確認メニューが有った。アクセスしてみると、新しいのが出てた。据え置き版を 取ってきて入れた。(一度目のインストールは失敗、二度目に成功)
前の版のやつは、すっかり消してしまっているので、良く使うmakeをインストール。で、最中に 何とかファイルが無いとか言ってたけど、インストール完了。本当に動くか、確認。
[atom] ➤ make -v ~/DOCUME~1/MOBAXT~1/slash/bin/make.exe: error while loading shared libraries: cygguile-17.dll: cannot open shared object file: No such file or directory
無いファイルをどこからか落としてきてもいいんだけど、やばそうなサイトばかり候補に出て くるので、止めた。makeは大した事に使っていないので、代わりのbatでも、考えて みるかな。 と思って、 バッチファイルの基本的な使い方なんてのを見たけど、余りに貧弱過ぎる。 Windowsで喜んでバッチを書く人は、真正なMに違いない。オイラーは、虐められて喜ぶような 人ではないので、unix流の shellコマンドを書こう。
cd C:/mine/piki case $1 in aa) ./piki template.html aa.piki > aa.html ;; : ee) ./piki template.html ee.piki > ee.html ;; *) ls -l [a-e]*.html ;; esac
今まで使っていたMakefileをちょいと改造しただけ。これで動いているって事は、makeらしい 働きをさっぱり、させていなかったって事だな。引数をファイル名に置き換える方法を取れば もっとすっきりするけど、それは危険と隣合わせなので止めておいた。
Lisp/Scheme
64Bitマシンになってから、カッコまみれになっていない気がするので、それっぽい所を 見てたんだ。そしたら、CLで機械学習をやってる方に出会った。結構かっこよいグラフを 表示されてたので、どうされてるかと思ったら、
Common LispからGnuplotでグラフ表示するライブラリを作った
Gnuplotを呼ぶそうです。
(ql:quickload :clgplot) (clgp:plot '(3 1 2 3 2 4))
こんなんで、グラフが書けるって楽すぎ。パラメータが色々あるけど、eldocが先導してくれる ので、簡単に思い出せるとの事。そんなのどういう設定すれば良い?
こちらにヒントが有った。久しぶりに Steel Bank Common Lispと slime を入れてみたぞ。
そして、ラケットの設定も出てた。そうか、drracketは起動に 時間がかかるんだよな。入れてみるか。Racket
binの下に色々入ってるけど、CUI中心の人はracketを起動するだけでよいみたい。 そして、ちょっと図形とか出したい時は、下記のようにディレクティブを設定するとな。
[debian tmp]$ cat aaa.rkt #lang slideshow (rectangle 10 20)
scheme-complete
schemeでコードを書こうとすると、資料豊富なgaucheが良さそう。補完が強く効いて欲しいな。 そんな時は、 scheme-complete がよさそう。最近忘れたように手が入っているからね。入れてみた。試してみた。
(define (a x) (string-reTAB ;; => Can't find completion for "string-re" on *Messages* buf
あれ、候補が無いと言ってるぞ。世界中の好き者から愛されていて文句が出てない所をみると、 オイラー側の問題だろうね。何かヒントが無いかな? ぐぐる先生に聞いてみたけど、皆無。 自分で何とか、解決策を見つけ出すんだ!
で思ったね。裏側ではelispが動いてるじゃん。これって、schemeから地続きなLispの世界。 Lispの虫取りはどうやるってのに帰結するだろう。debuggerかな? その前にtraceかな?
elispでtraceはどうやるか調べたよ。そしたら、M-x trace-function して、traceしたい 関数を登録するとな。scheme-complate.elを眺めて、人間traceしてみた。呼ばれそうな 関数を登録した。下記は、その結果。(関数を登録しといて、普通に補完してみる)
1 -> (scheme-complete-or-indent nil) | 2 -> (scheme-smart-complete nil) | | 3 -> (scheme-do-completion "string-re" (("import") ("a"))) | | | 4 -> (try-completion "string-re" (("import") ("a")) nil) | | | 4 <- try-completion: nil | | 3 <- scheme-do-completion: nil | 2 <- scheme-smart-complete: nil 1 <- scheme-complete-or-indent: nil
scheme-do-complation に候補として出てるのは何だ? この文脈での候補はこれしか 無いと言う事か。と言う事は、C語で言うヘッダーファイルを元に、補完候補を出しているに 違いない。
(import (scheme base)) (define (a x) (string-TAB =================================================================== In this buffer, type RET to select the completion near point. Possible completions are: string->list string->number string->symbol string->utf8 string->vector string-append string-copy string-copy! string-fill! string-for-each string-length string-map string-ref string-set!
こんな風に、候補が出てきた。さすがプロが使う道具だなあ。
なお、下記はgauche用の設定。ウナギのたれみたいに、秘伝の設定が混じっています。 (infoを引くやつ)
;; gauche smart-complete (setq scheme-program-name "gosh -i -r7") (autoload 'scheme-smart-complete "scheme-complete" nil t) (eval-after-load 'scheme '(define-key scheme-mode-map "\t" 'scheme-complete-or-indent)) (autoload 'scheme-get-current-symbol-info "scheme-complete" nil t) (add-hook 'scheme-mode-hook (lambda () (make-local-variable 'eldoc-documentation-function) (setq eldoc-documentation-function 'scheme-get-current-symbol-info) (eldoc-mode))) (setq lisp-indent-function 'scheme-smart-indent-function) ;; info lookup (define-key global-map "\C-c\C-i" 'info-lookup-symbol) (eval-after-load "info-look" '(progn (info-lookup-add-help :topic 'symbol :mode 'scheme-mode :regexp "[^()`',\"\t\n]+" :ignore-case t :doc-spec '(("(gauche-refj.info)Index - 手続きと構文索引" nil "^ -+ [^:]+: *" "[\n ]") ("(gauche-refj.info)Index - モジュール索引" nil "^ -+ [^:]+: *" "[\n ]") ("(gauche-refj.info)Index - クラス索引" nil "^ -+ [^:]+: *" "[\n ]") ("(gauche-refj.info)Index - 変数索引" nil "^ -+ [^:]+: *" "[\n ]")) :parse-rule "[^()`',\" \t\n]+" :other-modes nil) (info-lookup-add-help :mode 'inferior-scheme-mode :other-modes '(scheme-mode)) ))
そして、サンプル。折角なのでr7rsとやらを使ってます。上の設定でも、goshを起動する時に、 r7rs用のreplが回るようにしてます。そうしておかないと、定義した手続きがrepl上から見えません。これも、shiroさんがきちんと書いてくれた取説のおかげです。記して感謝します。
こういうの全部英語のマニュアルから読み取れじゃ、荷が重すぎますよ。
[fb11: tmp]$ cat aa.scm (import (scheme base) (scheme write)) (import (srfi 1)) (display "Hello, world!\n") (define (foo x) (number->string x)) (foo 1234) (display (iota 10))
下記は、emacsのgosh-bufferの結果。これで土台が出来たな。
gosh[r7rs.user]> (load "./aa") Hello, world! (0 1 2 3 4 5 6 7 8 9)#t
OpenBSD on CentOS
速いCUPの恩恵確認に、昔やったOpenBSD 探検 を、再度やってみます。
なんでも、qemu-kvm が、良いらしいので、CentOS上です。qemu-kvmを入れると、qemu-imgも 付属で付いてきましたよ。(armとかの石をやる時は、えっちらおっちらと、qemuを自前で、 コンパイルするんだろうね。あれは、付属品が沢山必要で面倒なんだよな。)
[cent tmp]$ qemu-img create -f qcow2 disk 1G Formatting 'disk', fmt=qcow2 size=1073741824 encryption=off cluster_size=65536 lazy_refcounts=off
して、小さいdiskを作成。qemu-kvmは、昔有った、qemu-system-x86_64の代替品らしい。 裸で使う物ではないそうで、変な所に置いてある。
まずは、インストール。
[cent tmp]$ /usr/libexec/qemu-kvm -m 256M -net nic -net user -cdrom install61.iso disk VNC server running on `::1:5900'
普通なら、新たなターミナルが開いて、起動画面が流れてくるはずなんだけど、そういうのは 無し。VNCで眺めるようだ。しかも、IPv6のアドレスを提示してきたぞ。じわじわとIPv6化が 進んでいるんでしょうかね。
[cent tmp]$ sudo yum install tigervnc [cent tmp]$ vncviewer localhost:5900 TigerVNC Viewer 64-bit v1.3.1 (20161116) Built on Nov 16 2016 at 13:37:43 Copyright (C) 1999-2011 TigerVNC Team and many others (see README.txt) See http://www.tigervnc.org for information on TigerVNC. :
慌てて、一番簡単そうなvnc-clientを入れ、IPv4で接続。その画面から、OpenBSDを インストールしましたよ。
そして、起動スクリプトを作成。ここに 手回しよく、-sを混ぜておいて、何時でもとgdbが使えるようにしておきました。
[cent ob61]$ cat boot /usr/libexec/qemu-kvm -m 256M -net nic -net user -s \ -redir tcp:2022::22 disk
Cent側から、OpenBSDに乗り入れてみた。
[cent tmp]$ ssh -p 2022 localhost sakae@localhost's password: $ uname -a OpenBSD ob61.my.domain 6.1 GENERIC#19 amd64 $ df -h Filesystem Size Used Avail Capacity Mounted on /dev/wd0a 991M 395M 546M 42% /
要らないプロセスを止める設定。
[ob: ~]$ cat /etc/rc.conf.local smtpd_flags=NO sndiod_flags=NO ntpd_flags=NO pflogd_flags=NO
gdbにかけられるようにカーネルをコンパイル
# cd /usr/src/sys/arch/amd64/conf # cp GENERIC DEBUG # vi DEBUG makeoptions DEBUG="-g" ## <-- ADD this line # config DEBUG # cd ../compile/DEBUG # make depend # COPTS="-O0" make
text data bss dec hex 12193124 288360 671744 13153228 c8b3cc mv bsd bsd.gdb strip -S -o bsd bsd.gdb 2m32.98s real 1m40.25s user 0m34.57s system
随分速いな。これ、qemu-kvmの恩恵かな? 起動も38秒ぐらいだったから、待ち時間としては ぎりぎりの許容範囲だな。
仮想のPC側に出来た、bsd.gdbをCentOSに持ってきます。そしてそれを、~/ob61/sys/arch/amd64/compile/DEBUG/ の中に鎮座させました。(CentOS側にも、OpenBSDのソースツリーを展開し、その中にDEBUG-dirを作成しときます)
いよいよ、gdbの試運転。先にOpenBSDを起動しておきます。(38秒の忍耐) 次に、CentOS側のDEBUG/の下で、gdb bsd.gdbして、gdbを起動。target remore :1234 して、 OpenBSDにアタッチします。
で、問題発生。該当ソースが見つからんと文句を垂れてきましたよ。どうも、ソースの在処は、 絶対PATHになってて、OpenBSD側のソースツリーそのものの、/usr/src/sys/amd64/... とかに なってました。
これはもう、その場所をCentOSでも用意するしかないかな。 /home/sakae/ob61/sys の、sys-dirを、強引に、/usr/src/の下に移動しましたよ。 (/usr/src/の下には、先客がいましたけど、sysは幸いな事に空いてました。)
でも、私事のために、/usr/srcにツリーを置くのは、なんとなく美意識に反する。 コンパイルも速い事なので、OpenBSD側のソースツリーの置き場所を、CentOS側と同一に しておこう。そして再コンパイル。再び、bsd.gdbをCentOS側に持ってくる。
ああ、再コンパイルに際して、いらないUSBの検出をしないように、コントローラの類を 取り除いておいた。そうでないと、
Apr 28 15:15:34 ob61 /bsd: iic0 at piixpm0 Apr 28 15:15:34 ob61 /bsd: iic0: addr 0x18 00=00 01=00 02=00 03=00 04=00 05=00 06=00 07=00 08=00 words 00=0000 01=0000 02=0000 03=0000 04=0000 05=0000 06=0000 07=0000 :
こんなのをずっと見せられるからね。
[cent ~]$ strings ob61/sys/arch/amd64/compile/DEBUG/bsd.gdb | grep /home/sakae sakae@ob61.hoge.net:/home/sakae/ob61/sys/arch/amd64/compile/DEBUG /home/sakae/ob61/sys/dev/ic/vga.c : /home/sakae/ob61/sys/arch/amd64/amd64/acpi_wakecode.S /home/sakae/ob61/sys/arch/amd64/amd64/vmm_support.S
こちらは、ソースツリーを変更した後、カーネルを作った時の埋め込み状況。ちゃんと出目を 記憶してるな。今回はツリーの場所を変えちゃったけど、gdbでツリーの探索場所を変更 出来たはず。
ソースが存在するディレクトリの指定を見ると、ファイル名しか埋め込んでないとなってるけど、OpenBSDのkernelは、 特別仕様なのかな?
OpenBSD 6.0で、qemu-systemo-x86_64 というアクセラレーションが利かない趣味れーたを 使って、昔作ったやつを起動したら、promptが出てくるまで、72秒かかっていた。 やっぱり、qemu-kvmだと速いな。
これから、探検してくけど、実施は/tmp(と言うRAMDISK)に置いたdisk上でやろう。これなら、しくじってパニクっても、元からコピーしてくれば簡単に初期状態に戻りますからね。 特製スナップショットみたいなものだな。
そして、こんな資料を見つけた。後で見て桶。