bug of lem ?

そうであるように doas を変換すると、そうであるようにってなるらしい。(by google)

今月号のSDの内容告知を見ていたら、sudoに変えて、安心安全なdoasを使おうなんて記事が出てたんだ。今頃になってLinux怪もOpenBSDの良さを認識したんだな。

で、リナでも動くと言うdoasは何処に?

Port of OpenBSD's doas(1) to Linux systems

これの事かな? まだ読んでいないんで、いまいち自信がない。

取り合えず取ってきて、コンパイルしてみるか。(on debian)

yaccが無いと言われてエラーになった。代替品のbisonでもエラー。それらしい奴って事で、byaccに乗り換えたら一応、doasが出来た。

誰からも侵害を受けないように、LDFLAGS='-static' で、作り上げるのがOpenBSD流ですね。

doas.confをちゃんと設置しないと、使えないぞ。後でOpenBSDから取ってきて、やってみよう。

debian:doas$ ls -l doas
-r-sr-xr-x 1 root root 958528 Dec 18 06:16 doas*

実際にOpenBSDで使ってる、元祖 doas.conf。見るにも変更するにもdoasを使えと言う代物です。

ob$ doas cat /etc/doas.conf
doas (sakae@ob.localdomain) password:
# $OpenBSD: doas.conf,v 1.1 2016/09/03 11:58:32 pirofti Exp $
# Configuration sample file for doas(1).
# See doas.conf(5) for syntax and examples.

# Non-exhaustive list of variables needed to build release(8) and ports(7)
#permit nopass setenv { \
#    FTPMODE PKG_CACHE PKG_PATH SM_PATH SSH_AUTH_SOCK \
#    DESTDIR DISTDIR FETCH_CMD FLAVOR GROUP MAKE MAKECONF \
#    MULTI_PACKAGES NOMAN OKAY_FILES OWNER PKG_DBDIR \
#    PKG_DESTDIR PKG_TMPDIR PORTSDIR RELEASEDIR SHARED_ONLY \
#    SUBPACKAGE WRKOBJDIR SUDO_PORT_V1 } :wsrc

# Allow wheel by default
permit keepenv :wheel
ob$ file /usr/bin/doas
/usr/bin/doas: ELF 64-bit LSB shared object, x86-64, version 1

本家のやつはsharedになってたから、staticうんぬんは余り気にしなくてもいいのかな。

dired-mode on editor lem ?

前回だったか、lemのdirectory-modeが使いづらいと書いた。臆面も無くdiredを作ってくれなんてほざいたけど、ちと恥ずかしい。で、反省を込めてカスタマイズしてみた。以下のコードをinit.lispに書き加える。

;; like emacs dired-mode
(in-package :lem.directory-mode)
(define-key *directory-mode-keymap* "v" 'directory-mode-read-file)
(define-key *directory-mode-keymap* "Space" 'directory-mode-next-line)
(define-key *directory-mode-keymap* "Backspace" 'directory-mode-previous-line)

Space/Backspace(有名なキーの名前はkey.lispで定義されてた)で、カーソルをターゲットのファイルに合わせる。そしてvすれば、read-onlyで開く。次のファイルに行く時は、C-x b RET(directory-modeのbufferが出てくる)。

120桁の文化

上記の設定を施し、大分使い易くなった。(相変わらずページの移動にPgUp/PgDnを使われるのには辟易するけど)

で、左側に行番号を付加してページを移動してると、おかしな事が分かる。例えば、ページの最下行が447行めで、次のページに行くと449行目になるとか。この現象、lispのコードを見ている時に顕著に発生する。

原因は、行が長くなって折り返し表示されちゃうから。論理行と物理行の整合が取れなくなる為だ。

オイラーは昔からUnix流に端末の幅は80桁と決めている。それ以上だと、眼が左右に泳いでしまって疲れるから。GUNのソースなんかは、この80桁ルールをいとも簡単に破ってくれる。

これもそれも大将のRMSがLisp文化に浸っていたからだな。Lispはインデントが(ほぼ)機械的に行われる。だから、コードの連なりで簡単に80桁を越えてしまう。Lisp界の重鎮によれば、120桁がデフォだと言う。

それを超えるような(深いネストの)場合、ソースが自ら警告を発しているんだとか。一つの関数に色々と詰め込み過ぎているぞと。一つの関数は一つの事をやれ。よってソースをリファクタリングするチャンスだよ。

UnixはC語主体で開発されてきたけど、80桁ルールってのは、C語で書かれた関数の複雑度を判定するスレッショルドとして機能してきたんだな。正に文化である。

120桁ルールに慣れるか否かはLisp界に身を置けるかどうかの試金石になるんだな。こればっかりは慣れるしかない。昔の人は上手い事を言った。郷に入っては郷に従えと。

gtags.lisp

lemのlib/coreを見てたら、上記を発見。そうか、globalかってんで、軽く使い方を復習。

ソースコードを快適に読むための GNU GLOBAL 入門

GNU GLOBAL(gtags)ソースコードタグシステムの使い方

で、C語とわずかな言語しか対応していなかったはずなんで、GLOBALの対応言語を大幅に増やすPygmentsパーサーを導入する。

pip install Pygments と exuberant-ctags を入れてから、globalを入れる。前記のpythonとctagsがconfigのログに出てきていれば(多分)OK。

/usr/local/share/gtags/gtags.conf を、~/.globalrc へコピーして、下記のように変更。

default:\
        :tc=native:tc=pygments:

これで多言語化されたはず。まずは小手調べで、ctagsのファイル群でやってみる。

(base) [sakae@c8 ctags-5.8]$ gtags -v
   :
 [85] extracting tags of args.c
 [86] extracting tags of argproc.c
 [87] extracting tags of ant.c
[Tue Dec 18 15:32:07 JST 2019] Done.

どうやら87個のファイルをスキャンしてくれたようだ。

(base) [sakae@c8 ctags-5.8]$ ls -l G*
-rw-r--r-- 1 sakae sakae  16384 Dec 18 15:32 GPATH
-rw-r--r-- 1 sakae sakae 532480 Dec 18 15:32 GRTAGS
-rw-r--r-- 1 sakae sakae 237568 Dec 18 15:32 GTAGS
(base) [sakae@c8 ctags-5.8]$ file GTAGS
GTAGS: Berkeley DB 1.85/1.86 (Btree, version 3, native byte-order)

3個のバークレーDBファイルが出来上がった。懐かしいなgdbmとどちらが性能が良いか、真剣に検討してた時代があったぞ。なんせ、SQLの世界ってかMySQLみたいな大掛かりな物は試せない環境でしたから。key-value storeって言う、先端を使わざるを得なかったんだ。

lem側の使い方

M-.  カーソル下の定義に飛ぶ
M-,  戻る
M-?  参照してる所を列挙する

例のlisp.cから

126 extern parserDefinition* LispParser (void)
127 {
128         static const char *const extensions [] = {
129                 "cl", "clisp", "el", "l", "lisp", "lsp", NULL

parseDefinentionは、他で使われてるか?

asm.c:365:extern parserDefinition* AsmParser (void)
asm.c:377:parserDefinition* def = parserNew ("Asm");
awk.c:70:extern parserDefinition* AwkParser ()
awk.c:73:parserDefinition* def = parserNew ("Awk");
  :

色々と出てきた。ファイル名にカーソルを合わせてRETを叩けば、参照してる所へ飛んで行く。戻りは勿論、M-, 。これであちこち気軽に回れる。

schemeのエクステンションがプチ気になったので、調べておく。

 98 extern parserDefinition* SchemeParser (void)
 99 {
100         static const char *const extensions [] = {
101                 "SCM", "SM", "sch", "scheme", "scm", "sm", NULL

ほぇー、ss とか rkt は、認識せずか。そういう目で見れば、 asd sld sls なんかは微妙だ。

bug of lem ?

まあ、兎に角 多言語globalを入れたんで、使ってみる。 試験場所は、lem/lib/core の所ね。

(base) [sakae@c8 core]$ gtags -v
[Thu Dec 19 06:44:56 JST 2019] Gtags started.
 Using configuration file '/home/sakae/.globalrc'.
 Using configuration label 'default'.
 Using plug-in parser.
[Thu Dec 19 06:44:56 JST 2019] Creating 'GTAGS' and 'GRTAGS'.
 [1] extracting tags of abbrev.lisp
 [2] extracting tags of attribute.lisp
  :
 [56] extracting tags of word-command.lisp
[Thu Dec 19 06:44:57 JST 2019] Done.

一応GTAGSとかがシンボル等を収集してるか確認。

(base) [sakae@c8 core]$ global -f gtags.lisp
:lem.gtags          1 gtags.lisp       (defpackage :lem.gtags
content            10 gtags.lisp       (defclass content ()
 :
find-definitions   78 gtags.lisp       (defun find-definitions (point)
find-references    83 gtags.lisp       (defun find-references (point)
 :

ファイル名を指定して、タグ内容を確認。次は、find-definetionsに付いて調査。

(base) [sakae@c8 core]$ global -x find-definitions
find-definitions   78 gtags.lisp       (defun find-definitions (point)
find-definitions  264 language-mode.lisp (define-command find-definitions () ()
(base) [sakae@c8 core]$ global -rx find-definitions

-r を付けてrefernceを出そうとしたけど、該当無しとなりました。

実際に使ってみると、開いているページ内しか検索対象にしないみたい。そんな物なのかな? まあ、無理して言語拡張してるからなあ。でも悔し紛れに色々と突いていたら、 gtags.lispの93行目、run-programに照準を合わせて、M-. すると

directory does not exist: /home/travis/build/roswell/sbcl_bin/sbcl/contrib/asdf/
Backtrace for: #<SB-THREAD:THREAD "editor" RUNNING {1002BB0CC3}>
0: ((LAMBDA NIL :IN UIOP/IMAGE:PRINT-BACKTRACE))
1: ((FLET "THUNK" :IN UIOP/STREAM:CALL-WITH-SAFE-IO-SYNTAX))
2: (SB-IMPL::%WITH-STANDARD-IO-SYNTAX #<CLOSURE (FLET "THUNK" :IN UIOP/STREAM:CA
:

こういうエラーに遭遇。誰かさんの家を訪ねてる。これって、Bug? それとも、そういう仕様? 素人には判断が付きませんです。

今度は清く正しく、C語に対して探してみます。題材はctags-5.8/内。インタラクティブで使えるコマンドが有ったのでお試し。

M-x gtags-definition-list

The value
  #P"/tmp/ctags-5.8/ant.c"
is not of type
  SEQUENCE
Backtrace for: #<SB-THREAD:THREAD "Anonymous thread" RUNNING {1003F89993}>
0: (LENGTH #P"/tmp/ctags-5.8/ant.c")
1: (SB-IMPL::PREPARE-ARGS ("global" "-f" #P"/tmp/ctags-5.8/ant.c"))
2: (SB-EXT:RUN-PROGRAM "global" ("-f" #P"/tmp/ctags-5.8/ant.c") :ENV NIL :ENVIR\
ONMENT NIL :WAIT NIL :SEARCH T :PTY NIL :INPUT NIL :IF-INPUT-DOES-NOT-EXIST :ER\
ROR :OUTPUT #<SB-IMPL::CHARACTER-STRING-OSTREAM {1003FDC8C3}> :IF-OUTPUT-EXISTS\
 :APPEND :ERROR NIL :IF-ERROR-EXISTS :APPEND :STATUS-HOOK NIL :EXTERNAL-FORMAT \
:UTF-8 :DIRECTORY "/tmp/ctags-5.8/")
3: (UIOP/LAUNCH-PROGRAM:LAUNCH-PROGRAM ("global" "-f" #P"/tmp/ctags-5.8/ant.c")\
 :INPUT NIL :OUTPUT #<SB-IMPL::CHARACTER-STRING-OSTREAM {1003FDC8C3}> :ERROR-OU\
TPUT NIL :DIRECTORY "/tmp/ctags-5.8/" :OUTPUT #<SB-IMPL::CHARACTER-STRING-OSTRE\
AM {1003FDC8C3}> :IGNORE-ERROR-STATUS T)
4: ((LAMBDA (UIOP/RUN-PROGRAM::REDUCED-INPUT UIOP/RUN-PROGRAM::INPUT-ACTIVITY) \
:IN UIOP/RUN-PROGRAM::%USE-LAUNCH-PROGRAM) NIL NIL)
5: (UIOP/RUN-PROGRAM::%USE-LAUNCH-PROGRAM ("global" "-f" #P"/tmp/ctags-5.8/ant.\
c") :DIRECTORY "/tmp/ctags-5.8/" :OUTPUT #<SB-IMPL::CHARACTER-STRING-OSTREAM {1\
003FDC8C3}> :IGNORE-ERROR-STATUS T)
6: (LEM.GTAGS::GLOBAL "/tmp/ctags-5.8/" "-f" #P"/tmp/ctags-5.8/ant.c")
7: (LEM.GTAGS::FETCH-GTAGS-DEFINITIONS "/tmp/ctags-5.8/")
:

ファイルってシーケンスの一種じゃないの?

どうも調子が悪いので、逃避します。

lemを自前でコンパイル

ros update lem とかやると、日々更新されてるのが分かって楽しい。でも、これだとrosが一枚噛んでいて歯痒い。自前でコンパイルしてみたいぞと。

lem ctags-5.8/ruby.c とかした時、CentOSにはどう認識されてるか、まずは調査します。

/home/sakae/.roswell/impls/x86-64/linux/sbcl-bin/1.5.9/bin/sbcl
  --core /home/sakae/.roswell/impls/x86-64/linux/sbcl-bin/1.5.9/dump/lem-ncurses.core
  --noinform
  --no-sysinit
  --no-userinit
  --disable-debugger
  --eval(progn #-ros.init(cl:load "/usr/local/etc/roswell/init.lisp"))
  --eval(ros:run '((:eval"(ros:quicklisp)")(:script "/home/sakae/.roswell/bin/lem-ncurses""ctags-5.8/ruby.c")(:quit ())))

本当に素なsbclを使ってlem-ncurses.coreって実体をメモリーに展開。そこで、S式を2つ評価してるとな。 肝はcoreの生成だな。

(base) [sakae@c8 ~]$ cd .roswell/local-projects/cxxxr/lem/
(base) [sakae@c8 lem]$ ./bootstrap
configure.ac:22: installing './compile'
configure.ac:2: installing './install-sh'
configure.ac:2: installing './missing'

ソースの在処に移動してbootします。これでconfigureが作成される。

-rwxrwxr-x  1 sakae sakae 163621 Dec 19 08:28 configure
(base) [sakae@c8 lem]$ ./configure --prefix=/home/sakae/.roswell

次はconfig、インストール場所を指定しておく

(base) [sakae@c8 lem]$ make
Making all in scripts/gen-contrib
 :
compressed 17203200 bytes into 5410250 at level -1
rm bin/lem-ncurses.ros
make[1]: Leaving directory '/home/sakae/.roswell/local-projects/cxxxr/lem'

コンパイル

(base) [sakae@c8 lem]$ make install
Making install in scripts/gen-contrib
  :

インストール。

(base) [sakae@c8 ~]$ ps a
  7833 pts/1    Sl+    0:00 /home/sakae/.roswell/bin/lem-ncurses ctags-5.8/pytho

実行。うだうだとコマンドラインが長かったけど、すっきりさっぱり。但し、lem-ncursesがさっぱりしすぎてサイズが小さい。元々使ってたやつのcoreと比べても小さすぎて、少々心配。

(base) [sakae@c8 bin]$ file lem-ncurses
lem-ncurses: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=7e9b2ba4b16cdbfb2baa14f7670bb04f25577efe, with debug_info, not stripped
(base) [sakae@c8 bin]$ ldd lem-ncurses
        linux-vdso.so.1 (0x00007ffc4d748000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f70dc10b000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f70dbeeb000)
        libz.so.1 => /lib64/libz.so.1 (0x00007f70dbcd4000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f70db952000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f70db58e000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f70dc30f000)

sbclとは縁が切れて、普通のアプリに変身してるよ。これでsbclも要らない。slimeで評価は出来なくなってるだろうけど。

何を惚けた事を言っている! slimeしたら控えのsbclがちゃんと起動してきて普通に使えた。

dumpされた奴って、大量にごみが混ざっているのかな?

using ros

rosを入れてlemしてるけど、rosってsbclの環境。ならばrosから見えるライブラリィーを使えるはず。某所に例が有ったので、swank-sbclする、2行のコードを書いてみた。

cat go.lisp
(require :swank)
(swank:create-server :port 4005)

ros -Q -L sbcl-bin dynamic-space-size=4096 run -l ./go.lisp

sbcl-binはrosが管理してるバージョンのやつね。 回りくどい感じがしないでもないけど、そこはros-scriptにまとめてしまえって事なのね。 佳き例のlem-ncursesが、lemのインストールで失くなってしまっているからなあ。