標準愚痴出力

個人的なIT作業ログです。もしかしたら一般的に参考になることが書いているかもしれません(弱気

続・nyagos で lua53.dll のかわりに GopherLua を使おう

続・nyagos で lua53.dll のかわりに GopherLua を使おう - Qiitaより転載

続・nyagos で lua53.dll のかわりに GopherLua を使おう 「nyagos で lua53.dll のかわりに GopherLua を使おう - Qiita」の続き:


β2 を出しました。

リポート!

Luaスクリプトの互換性

GopherLua 起因と思われる不具合はありませんでした。。あったのは Lua のバージョンが 5.3 → 5.1 に変わることによる文法上の差異のみです。

nyagos.d/ 上のスクリプトと、自分の環境上のスクリプトの修正内容は下記のとおり。

  • 5.1 には table.unpack がない ⇒ unpack とする(どちらでも動くように (table.unpack or unpack) とするのが個人的には好き)【nyagos.d/aliases.lua
  • 5.1 では load("luaコマンド") がない ⇒ 変数 _VERSION"Lua 5.3" でなければ loadstring("luaコマンド") とする 【nyagos.d/aliases.lua
  • 5.1 にはビット操作演算子(&|)がない ⇒ 自前で関数 nyagos.bitandnyagos.bitorを用意した 【nyagos.d/box.lua
  • 5.1 には math.tointeger がない ⇒ 変数 _VERSION"Lua 5.3" でなければ、浮動小数点をそのまま渡す。受け取る利用側の Go 関数の方で値を整数化して使うようにした。【nyagos.d/trash.lua

実際の Lua コード修正内容は

cd nyagos.d
git diff 4.2.5_1 .

で確認できます。

ユーザの反応

思ったよりも肯定的。WindowsLua を LuaRocks などからパッケージをダウンロードしてまで使おうという人があまりいないためかもしれません(自分もやったことない)。

その他の影響

  • 目論見どおり、appveyor でのビルド失敗率は減った。ダウンロード先は github.com だけになったのが大きい
  • zipサイズは 300~400KB 程度、exeファイルは 1.3MB 程度増えた。
  • zipファイル作成時に lua53.dll が32bitと64bit取り違えてないか、心配する必要がなった。
  • Pure Go 言語になったため、panic が発生した時のスタックトレースが常に信頼できるようになった(気がする)。Go言語どおしなので、おそらく Lua に渡すコールバック関数で、トリッキーなことをしても大丈夫だろう(やってないけど)

ソース(参考)

です。

  • Lua に依存したコードは現在すべて gopherSh/mains/ 以下に封じ込めている
  • 将来的には mains/ を削除して gopherSh/mains/ にリネームするかもしれませんが、当面は維持

処理系変更時の工夫

nyagos開発の当初からやっていたこと

  • lua を使うコードは、メインパッケージ(mains/)だけに封じ込める(サブパッケージで lua 機能を使う時は、メインパッケージから依存部分をパラメータ等で与えるよう、徹底する(「依存性抽出」という表現でいいのかな?)
  • エイリアスや一行入力キーに Lua 関数をアサインする時も、Go の interface オブジェクトをテーブルに設定するようにし、決して Lua オブジェクトを関数プロトタイプに含めたものを直接使わないようにした。

しかしながら、この結果としてメインパッケージが全ての混沌を引き受け、肥大化したわけです。以下は、この肥大化したメインパッケージから、いかに Lua 成分を入れ替えるかという戦いが始まります。

コールバック関数を両方で使えるように

Lua へ渡すGoのコールバック関数の仕様は、

  • 自前の lua53.dll ラッパー:func(lua.Lua) int
  • GopherLua :func(*lua.LState) int

となっています。(※lua.Lua は、C言語lua_State* の値(uintptr)を type したもの)

一つ一つ書き換えてもよいのですが、あまりに量が多いため「書き換え中のビルドできない過渡期」が長くなりすぎてしまうおそれがありました(たぶん、途中で絶対心折れる)。そこで処理系に依存しない

  • func([]interface{})[]interface{}

という形式を、Lua へ渡すコールバック関数の標準形式とし、これを各 Lua 処理系に適した形に変換する関数:

  • func lua2cmd(f func([]interface{}) []interface{}) func(lua.Lua) int
  • func lua2cmd(f func([]interface{}) []interface{}) func(*lua.LState) int

を用意しました。(実際には、これだけだとリダイレクトされた標準入出力(io.Writer / io.Reader )の引き渡しができないので、もう一種類形式も用意)

こうした工夫の結果、func([]interface{})[]interface{}という形式への切り替えは 2017年4月に着手した※ものの、それは他の修正作業を妨げることなく「裏で」こっそり進めることができました。

(※追記:多分、本格的な裏着手は 2017年8月頃から。interface{} といちいち書いてられなかったので、Go 1.9 の型エイリアスで「type any_t = interface{}」で短く書けるようになってからのはず)

Lua 処理系を利用しないバージョン(ngs.exe)を一旦作成

appveyor でのビルドエラーが目立つようになってきた 4.2.5 リリース以降から、本腰を上げて、lua53.dll 脱却に着手しました。その第一ステップとして、メインパッケージを二つに分け、lua53.dll を使わないバージョンをまず作る事にしました。

  1. mains/ フォルダーを ngs/ というフォルダーにまるまるコピーして、lua に依存する箇所をカットしてゆく。
  2. カットするには大きい(明らかに後から作り直すのはしんどい)箇所は、別途フォルダー(functions/,framework/)を用意し、Lua へ依存する箇所をパラメータ等で引き渡す方式に変更してゆく
  3. 最終的に ngs/ でビルドしたバージョンが lua53.dll なしでエラーなく動作すれば成功

実際は、ここまでスムーズにやっているわけではなく、フォルダー構成を右往左往しながら変えてたりします。この作業では、Lua に依存したソースを mains パッケージからさらに絞る意味があったと思います。

GopherLua 組み込み開始

ngs.exe が出来た時点で「もう無理に Lua を差し替えなくても、Lisp とか別の言語系を組み込んでもよいかな」などという浮気心も出始めましたが、

  • Goに移植された有名な言語処理系で、適当なものが浮かばなかった
  • なんだかんだ言って lua53.dll と GopherLua は引数引き渡しの形式がスタックインターフェイスと同じなので、理論上 100% の差し替えが可能
  • GopherLua はexpect for Command Promptというツールで、一応、経験もあった

という理由で、結局、当初の目標である GopherLua へ立ち返ります。

Luaなしバージョン ngs/ 以下を、gopherSh/ (当初は gopher/) というフォルダーへ複写しました。そして、ngs/ と mains/ の差分を見ながら、少しづつ移植してゆきます。

  1. 最初の目標は、とりあえず .nyagosnyagos.d/ 以下を読むようにすること(エラー上等)
  2. 次の目標は、func([]interface{})[]interface{} という標準形式にしてあるコールバック関数群(nyagos.*****) を使えるようにすること(具体的には GopherLua 版の引数変換関数 lua2cmd を実装する)
  3. lua関数によるのエイリアスの実装
  4. ここまで来たら、GopherLua についての知識も十分付き、軌道にも乗ったので、気付いたところから以下を実行してゆく
    • func([]interface{})[]interface{}形式に直せていないコールバック関数の個別移植
    • コマンドラインフィルター(nyagos.argsfilter,nyagos.filter)の類の移植
    • 一行入力のキーへの Lua 関数の割り当て
    • えとせとらえとせとら

ここまでくると、結構ノリノリでコードを書いているので、障害らしい障害はほとんどありませんでした。で、nyagos.d の読み込みエラーも消えたところで、β1 のリリースというわけです。

最後に

しかし、まぁ、われながら、よくやったよ

以上

nyagos で lua53.dll のかわりに GopherLua を使おう

2018/04/25 付け記事:nyagos で lua53.dll のかわりに GopherLua を使おう - Qiitaより転載

nyagos で lua53.dll のかわりに GopherLua を使おう Using GopherLua instead of lua53.dll · Issue #300 · zetamatta/nyagos


lua53.dll にはいくつか問題があります。

  • MinGW gcc 6 でビルドされた lua53.dll は LIBGCC_S_DW2-1.DLL を必要とします。
    • luaBinaries でダウンロードできる lua53.dll は MinGW gcc 4 や Visual C++ でビルドされているようです。
    • GCC のstatic-linkオプションは、EXEファイルのビルドにおいて働くもので、DLL のビルドには効きません。
  • appveyor での自動ビルド時、luaBinaries から lua53.dll をダウンロードしていますが、度々失敗しています。

また、nyagos で lua53.dll を用いたサードパーティライブラリも滅多に必要とされないようです。

ならば、lua53.dll のかわりに GopherLua を使うべきではないでしょうか。 計画は始まっています。


ということで NYAGOS は今、Lua エンジンを lua53.dll から GopherLua へ切り替え中です。(完成したら NYAGOS 4.3 になるでしょう)

仕掛中のソースは develop ブランチの https://github.com/zetamatta/nyagos/tree/develop/gopherSh 以下にぶら下がっています。エンジン自体は既に GopherLua に変わっていますが、幾つかの機能(補完のフックと、OLE呼び出し)の移植が済んでいません。進捗的には 2018年5月の連休までにα版がリリースできたらいいなというところです。

ご期待ください (また、別途、lua53.dll と GopherLua の使い勝手の違いもリポートします)

連休中の作業メモ(4/30)

nyagos 4.3β

lua53.dll を GopherLua にリプレースしたバージョンの初バイナリ

Typing C-o looks to raise hang up until Enter or ESCAPE is typed (on 4.3beta)

出してからしばらくして、Lua とは関係ないreadline.Console の bufio.Writer 化した際の Flush 漏れが判明した。C-o を押下した時、選択肢がバッファリングされたまま画面に出ない。修正はしたので、明日か明後日、β2 として出す

Add type data for AutoCAD 2000 to 2018 (dwg) floyernick/fleep-go

ファイルのマジックナンバーを検出するライブラリfloyernick/fleep-go: File format determination package for Goに、DWGファイルに対応してもらおうというプルリク。ファイル頭の「AC10**」を、テーブルに足しただけ

file-go

ファイルのマジックナンバーを検出するライブラリfloyernick/fleep-go: File format determination package for Goと、EXEヘッダを読み取る hillu/go-pefile: Portable Executable (PE) parsing library for Go を組み合わせたコマンド file-go.exe を実験レポジトリに書いてみた。

fleep-go の結果に加え、もし EXE系ファイルだったら go-pefile の結果も表示するようにしただけ。 将来的には、もうちょっとしっかり読んで、32bit/64bit/AnyCPU くらいを判断できるようにしたいところだなぁ。

let のない Lisp で lambda を let のかわりにつかう

無いものを嘆いていても仕方がないので、できることを模索しよう。

autolisp系のLispでは let が使えず、ローカル変数は、関数の頭でしか宣言できない。また、use strict 相当のものがないため、関数が長くなるとローカル変数の宣言漏れがないかどうかをチェックするのも(宣言するところと使用する場所が離れているため)結構たいへんだ。

そんな折、let が lambda の糖衣構文である処理系もあるという話を聞いた。なるほど、let は lambda の変形なのか。ということで、lambda で let 相当のことをやってみよう。

(defun C:test-lambda (/ tmp)
  (setq tmp "hogehoge")
  (princ "\nbefore=")(prin1 tmp)
  ((lambda (tmp) ; instead of (let)
           (princ "\nin lambda=")(prin1 tmp)
           ) "uhauha")
  (princ "\nafter=")(prin1 tmp)
  (princ)
)

思ったほど、見づらくない。lambda と同じ行に「; instead of let」と書くようにすれば、他の読み手にも分かってもらえそう。動作結果はどうだろう。

: TEST-LAMBDA

before="hogehoge"
in lambda="uhauha"
after="hogehoge"

よしよし

F-Secureという Anti-virus が NYAGOS を誤検出したらしいので、誤検出を報告した

I am developing the Open Source Software: NYAGOS(Nihong Yet Another Going Shell).

https://github.com/zetamatta/nyagos

But, my software's user is troubled because your products reports it as a malware, and prevents from using it. It is the command-line shell and it can not be a malware.

Would you fix your product or tell me what I should do to avoid my software reported as a malware ?

これ、意味、通じるかな?

返信きた

件名:F-Secure: 01593886 I heard your product reports my open source so [ ref:00Db0JXpV.5000X1R6wQO:ref ]

Greetings,

Thank you for your submission. The file that you have submitted is clean and currently did not detect by our product. In case if our product detect your software again, please provide the detection name or the scanning report so that we can investigate the issue. If there is anything else we can help you with, please do not hesitate to contact us again.

「登録したファイルはクリーンで、我々の製品では検出できなかった。再び、我々の製品で検出される場合は、検出された名前とスキャンリポートを提供してほしい。そうすれば問題を調べることができるので。他になにかあれば、我々はヘルプできるので、ためらわず再びコンタクトしてくれ」

対して返信した

Thank you for your reply.

I am grad that the latest version of your product did not detect problem in my software. I would tell your answer to my user , and ask him to test in the latest version. If he or I contact you again, please support us.


Kaoru Hayama

最新バージョンで問題が検出されなくて喜ばしい。 ユーザに回答を伝えて、最新バージョンで試してもらうよう頼むつもりだ。 もし、彼もしくは私が再びコンタクトしたら、サポートお願いします。

(しかし、下手な英語だなぁ)

NYAGOS 4.2.5βが、いかにしてバッチファイルでの環境変数の変更取り込みを可能としたか

  1. 通常、環境変数は親プロセスから子プロセスへの一方通行で継承されるものであり、逆はありえない。
  2. CMD.EXE で「環境変数設定バッチ」というものが成り立つのは、バッチファイルを子プロセスではなく、バッチファイルを呼び出しているCMD.EXEプロセス自身でバッチファイルを読み取り、実行しているから
  3. 故に、バッチファイルを「子プロセスの CMD.EXE」で呼び出している NYAGOS では、CMD.EXEのような環境変数設定用のバッチファイルを期待通りに利用することはできないはず

だが、しかし:

set F=%TIME%
cd "%TEMP%"

このバッチファイルを実行する時、4.2.5βでは、かわりに次のようなバッチファイルを生成・実行する。

@call t\batchtst.cmd
@set "ERRORLEVEL_=%ERRORLEVEL%"
@(cd & set) > "C:\Users\(ユーザ名)\AppData\Local\Temp\nyagos-11428.tmp"
@exit /b "%ERRORLEVEL_%"

このテンポラリバッチは、本来実行すべきバッチファイル(t\batchtst.cmd)を呼び出した後、%TEMP%\nyagos-11428.tmp というファイルに

という内容を出力する。後は nyagos.exe でこれを読みだして反映するだけ!

多分、これで環境設定バッチバッチソだと思うんですが、どうでしょうか!

(正直、ひどい力業(ちからわざ)だとは思いますけどね)

この環境変数バッチを読み込む機能自体は、以前より source というコマンドに実装されていた。4.2.5βではそれに対し、以下のような修正を行った。

  • source と打たずとも、デフォルトのバッチファイル実行でも、反映機能が有効になるようにした。
  • %TEMP%\nyagos-(プロセスID).cmd生成の際、バッチへの引数が正しく引き渡されない以下の不具合を修正
    • UTF8 のまま引き渡され、CMD.EXE 側で正しく受け取れなかった(⇒ 現在のコードページ文字列(ANSI)へ変換)
    • "&"">" といった引数の二重引用符が外れてしまっていた(⇒ 元々の二重引用符をそのまま引き渡すように修正)

以上、開発の現場からでした。

Appveyor がまだ Go 1.10 をサポートしてなかったので、自前で取ってくるよう設定した

strings.Builder を使いたくて、ローカルの環境を Go 1.10 にしたが、Appveyor がまだ Go 1.9.2 のままだ。そのせいで、git push するたびに失敗マークがついてしまう。

Appveyor のサポートサイトを適当に見てみたら、Go 1.3 しか入っていない頃に書かれた 1.4 を使う手順があった。

Go 1.4 support / Problems / Discussion Area - AppVeyor Support

これの真似をして、Go 1.10 をダウンロードして使うように appveyer.xml を修正した。

diff --git a/appveyor.yml b/appveyor.yml
index dfe71e0..17fe0be 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -30,8 +30,10 @@ environment:
     - platform: i386
     - platform: amd64

-
 install:
+  - rd C:\Go /s /q
+  - appveyor DownloadFile https://dl.google.com/go/go1.10.windows-386.zip
+  - 7z x go1.10.windows-386.zip -oC:\ >nul
   - set INSTALL_DIR=%APPVEYOR_BUILD_FOLDER%\%DEST_DIR%\%PLATFORM%
   - ps: |
       if ($env:PLATFORM -eq "i386") {

Go はクロスコンパイルできるので、go1.10.windows-386.zip でも amd64 版を作れるはず。

一応、ビルドは通っているが、なぜか成果物のダウンロードができない(ネットワークエラーになる)。 エラーになってないから、まぁ、いいか。