Cでバイトコード文字列を実行する

自分用のメモです。

特にこれといって意味がないものですが、Cでバイトコード文字列を実行します。

ソースコード

仮引数 v の中身を直に書き替えているので、あまり行儀の良いコードではないのです。 本来、関数ポインタを渡す qsort() の第4引数にコンパイルした関数のバイト列を文字列(つまりchar*)として記述し、そのバイト列を const void*, const void* を引数にとって int 型を返す関数ポインタにキャストして、qsort() 内からコールバックされます。

インライン・アセンブラならぬ、インライン・バイトコードといったところでしょうか。ハードコーディングされた文字列も、ポインタとして抽象的な解釈がなされるため、よく理にかなった動きをしていると言えます。

このコードを実行すると、引数に与えられた文字列をソートして印字します。

また、上記のようなバイトコード文字列を即時実行させるには、

int n = 10;
int m = 20;
printf("%d\n",
  ((int(*)(int,int))
    "\x55\x89\xe5\x8b\x55\x08\x8b\x45\x0c\x39\xd0\x7d\x02\x89\xd0\x5d\xc3"
  )(n, m));

という記述で、関数名(つまり関数ポインタ)に関数呼び出しであることを示す()をつければ、通常の関数と同様に呼び出すことができます。 上のコードは、渡された n, m を評価し、大きい方を返す関数のバイトコード文字列を実行しています。

バイトコード文字列は、

int max(int a, int b)
{
  return a > b ? a : b;
}

という内容のmax.cがあった場合、

gcc -c max.c
objdump -D max.o

して得られる、関数 max() の部分から得られます。

00000000 <max>:
  0:   55                      push   %ebp
  1:   89 e5                   mov    %esp,%ebp
  3:   8b 55 08                mov    0x8(%ebp),%edx
  6:   8b 45 0c                mov    0xc(%ebp),%eax
  9:   39 d0                   cmp    %edx,%eax
  b:   7d 02                   jge    f <max+0xf>
  d:   89 d0                   mov    %edx,%eax
  f:   5d                      pop    %ebp
 10:   c3                      ret    

バイトコードという表現だと、Java や Ruby の VM に対する中間コードのように聞こえて語弊があるかもしれません。この記事で扱っているのは、あくまでもコンパイル時にコンパイル済みのバイトコードが埋め込まれるようにしているだけであって、実行時評価はされませんし、プラットフォームに依存しています。

シェルスクリプトによる簡易Wikiシステム

以前、PQI Air Card でも動く簡易 Wiki を書いてみました。PQI Air Card 自体、標準で Perl が動いていますし実用性はあんまりないですが、シェルスクリプトベースでも簡単に出来てしまいます。

wiki.sh

メインスクリプトです。

#!/bin/bash

dir=p
#BASENAME="/mnt/sd/DCIM/122_TREK/busybox basename"
BASENAME="basename"
tmp=`$BASENAME $QUERY_STRING`
page=${tmp:-index}

if [ "$REQUEST_METHOD" = "POST" ]; then
  read text
  echo "$text" | sed -f www.sed > $dir/$page
fi

if [ -f $dir/$page ]; then
  body=`cat $dir/$page`
else
  body='This is new page.
Please write body and push the save button.'
fi

title=`echo "$page" | sed 's/_/ /g'`

cat<<EOF
Content-Type: text/html

<TITLE>$title - Wiki</TITLE>
<H1>$title</H1>
<HR>
<H2>CONTENT:</H2>
<PRE>
$body
</PRE>
<HR>
<H2>EDITOR:</H2>
<FORM action=wiki.sh?$page method=post>
<TEXTAREA cols=60 rows=7 name=text>$body</TEXTAREA>
<INPUT type=submit value=SAVE></FORM>
EOF

cat<<EOF
<HR>
<H2>PAGE LIST:</H2>
EOF

for item in `ls $dir`;
do
  echo "<dt><a href=wiki.sh?$item>" $item "</a>"
done

echo "<HR>"
echo "my wiki system by dyama &lt;dyama@member.fsf.org&gt;"

www.sed

URL文字列デコード用 sed ファイル。

#!/bin/sed

s/^text=//
s/+/ /g

s/%0D%0A/\n/g
s/%0A/\n/g
s/%0D/\n/g

s/%21/!/g
s/%3F/?/g
s/%2B/+/g
s/%3D/=/g
s/%7C/|/g
s/%23/#/g
s/%24/$/g
s/%5E/^/g
s/%26/\&/g
s/%28/(/g
s/%29/)/g
s/%5C/\\/g
s/%60/`/g
s/%7E/~/g
s/%5B/[/g
s/%5D/]/g
s/%7B/{/g
s/%7D/}/g
s/%3B/;/g
s/%27/'/g
s/%3A/:/g
s/%22/"/g
s/%3C/</g
s/%3E/>/g
s/%2C/,/g
s/%2F/\//g
s/%09/\t/g

s/%25/%/g

wiki.sh に +rx して、ページ保存用のディレクトリ「./p」を 777 で作成し、wiki.sh にアクセスすると次のように表示されます。

wiki

新規ページを作成するには、URL文字列に?pagenameをつけてアクセスします。wiki.sh の URL がhttp://localhost/wiki.shの場合、http://localhost/wiki.sh?pagenameになります。 ページの削除機能はないので、端末からログインして、ディレクトリ p 以下の対象ファイルを削除すればOKです。

また、SVN などに噛ませてページの更新時毎にディレクトリ p 以下をコミットしてやれば、ヒストリー機能も実現できそうです。楽チンですね。

タミヤ ウォーターラインシリーズ 1/700 駆逐艦 吹雪

数年前に椎間板ヘルニアになってずっと腰痛持ちだったのですが、ここ数日、ひどくなっていて困っています。 椎間板(背骨)の背中側が圧迫されて軟骨がはみ出てて、それが神経を圧迫して腰痛と足のしびれが来ているようです。 なので、ここのところ背中を丸めた猫背状態が一番楽な姿勢になっています。

だからと言うワケでもないのですが、ここ数日、数年ぶりにプラモデルを作っています。全体作ったのは人工衛星はやぶさが地球に機関した後の「はやぶさ」。その前は子供の頃、という状態なのでほとんど素人なのですが、素人なりに作っていて楽しいです。

さて、「艦これ」ブームもあいまってか艦船模型が売れているのは良い傾向です。休日に「西海模型」さんに行くと、店内では大柄なアメリカ海兵たちが独戦艦「ビスマルク」の模型を手にとって何やら話していました。その日は昼と夕方の二度、店に訪ずれたんですが、どちらとも別の海兵たちがいました。こういう光景が日常的なのは、佐世保っていう土地柄なのかもしれません。

今年の2月に亡くなった祖父は、潜水母艦「長鯨」に乗った後、航空母艦「隼鷹」のケップガンをしていて、終戦後、駆逐艦「楠」の副長として幅員作業に従事していたようです。 「隼鷹」は空母として有名だったので、タミヤの1/700を箱のまま持っていましたが、たまたまピットロードの「長鯨」を見つけたので買ってしまいました。この二つはちゃんと作ってみたいのでとりあえずキープということで、練習台としてタミヤの駆逐艦「吹雪」と駆逐艦「桜」を購入。

吹雪「私がやっつけちゃうんだから!」

あんまり気合を入れて作ろうとすると挫折しそうだったので、早速「吹雪」から気軽に作り始めることにしました。 この記事を書いている段階で、装載艇の設置以外はほとんど済ませました。

IJN Destroyer Fubuki 大きいサイズ IJN Destroyer Fubuki 大きいサイズ

自分レベルですので、素組みするだけでも一苦労…。他の人は水偵のフロートとか、どうやって垂直に接着してるんだろうなあ。

  • Mr.Colorのスプレーを使用。スプレーを吹いているくせにムラがはんぱない。塗り直し時した挙句、かなり近くから噴霧したのが原因か…。
  • 細かなところは瞬間接着剤を利用するも、垂らす量がコントロールできずにびしゃびしゃに。
  • 煙突の白ラインなど、一応マスキングしているけれど全体的に雑。主砲の付け値もマスキングすべきだった。
  • 鉄ヤスリじゃなくて紙ヤスリを買ってきて、もっと丁寧にヤスリをかけなければ。

ウェザリング用の塗料も準備しているものの、先が不安で波高しです。あとは装載艇を積んで、クリア吹いて、気持ちばかり空中線をつけて(萎えないうちに)完成までこぎつけたいところです。 練習なのでツッコミを入れていたらキリがないのですが、実際に組んでみて分かったことがあるので、それだけでも儲けということで納得しようと思います。

ちなみに、同じモデルでもこんなに素晴しい感じに作られる人もいます! いいな〜!自分もガンバロウ。

mruby で自作クラスをごにょごにょする

siren では、mruby を組み込んでコマンドドリブンなインタプリタを実装していたので、クラスをまともに使っていませんでしたが、コマンドが多くなるにつれ管理が煩雑になった事や、Ruby のクラスとして強力な機能を実装する目的もあり、改めて mruby のクラスまわりの実装を調べてみました。

C コード上で Ruby クラスを作成

クラスの新規作成

mrb_define_class() を使います。引数は mrb_state*, クラス名, 親クラス。

RClass* prclass = mrb_define_class(mrb, "Myclass", mrb->object_class);

RClass*が返ってきます。C コード中では、このポインタでクラスを指定します。

クラスにメソッドを突っ込む

新規作成したクラス Myclass の中身は空っぽなので、メソッドを突っ込んでみます。

mrb_define_method(mrb, prclass, "myfunc", myfunc, ARGS_NONE());

引数は mrb_state*, ターゲットとなるクラスの RClass*, メソッド名, 実体のC関数, 引数定義です。 RClass* を mrb->kernel_module にすると、Kernel 名前空間に入ってグローバル関数のように使えます。

引数定義

ARGS_NONE() ... 引数なし
MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1) ... 必須引数が2個、省略可能引数が1個

実体の関数

インターフェイスは、戻り値と引数の型に注意するだけでOKです。

mrb_value myfunc(mrb_state* mrb, mrb_value self)
{ 
    mrb_int a;
    mrb_int b;
    int argc = mrb_get_args(mrb, "ii", &a, &b);

    return mrb_fixnum_value(a + b);
}

引数は mrb_get_args() で取得します。

定義済みのクラスを文字列から取得する

名前が分かっているなら RClass* を保持しておく必要はありません。

RClass* prclass2 = mrb_class_get(mrb, "Myclass");

クラスのインスタンス変数を設定・取得する

mrb_obj_iv_set() と mrb_obj_iv_get() を使用します。

RClass* my_class = mrb_define_class(mrb, "Test", mrb->object_class);
mrb_value obj = mrb_class_new_instance(mrb, 0, NULL, my_class);

RObject* pobj = mrb_obj_ptr(obj);
mrb_sym sym = mrb_intern(mrb, "asdf", strlen("asdf"));
mrb_obj_iv_set(mrb, pobj, sym, mrb_fixnum_value(1244));

return mrb_obj_iv_get(mrb, pobj, sym);

クラスからインスタンスを作成

定義したクラスからインスタンスを作成するには mrb_class_new_instance() を使うようです。 引数は mrb_state*, コンストラクタの引数の数、引数、RClass* です。

mrb_value obj = mrb_class_new_instance(mrb, 0, NULL, prclass2);

引数がない場合、0, NULL で良いみたいです。引数は

mrb_value args[3];
args[0] = mrb_fixnum_value(123);
args[1] = mrb_float_value(mrb, 10.4);
args[2] = mrb_nil_value();

のようにこしらえます。

メソッドの削除

コーディングして試してみていませんが、mruby.h に

void mrb_undef_class_method(mrb_state*, struct RClass*, const char*);

がありました。

メソッドを実行する

mrb_funcall(), mrb_funcall_argv(), mrb_funcall_with_block() の3種類が mruby.h に定義されています。

mrb_funcall(mrb, obj, "myfunc", 0);

Ruby スクリプトとして書いたクラスを C プログラムに組み込む

C コードで動的に Ruby のクラスを作れるのは便利なんですが、動的に生成する必要もないものは、普通の Ruby スクリプトとして書いたりデバッグしたりする方が効率的です。

mruby をビルドすると bin ディレクトリに生成される mrbc を使うと、Ruby のスクリプトファイルをバイトコードに変換し、C の配列として扱える C ソースコードファイルに変換してくれます。

Ruby スクリプトから C ソースコードへ変換

次のような内容の vector.rb を準備します。

class Vector
  attr_accessor :x, :y, :z
end

mrbc を使ってコンパイルします。

mrbc -BVector -ovector.c vector.rb
# -B<バイトコード配列名> -o<出力ファイル名> <入力ファイル名>

次のような内容の vector.c が生成されます。

#include <stdint.h>
const uint8_t Vector[] = {
0x52,0x49,0x54,0x45,0x30,0x30,0x30,0x32,0xe8,0xe5,0x00,0x00,0x00,0xa7,0x4d,0x41,
0x54,0x5a,0x30,0x30,0x30,0x30,0x49,0x52,0x45,0x50,0x00,0x00,0x00,0x89,0x30,0x30,
0x30,0x30,0x00,0x00,0x00,0x33,0x00,0x01,0x00,0x03,0x00,0x01,0x00,0x00,0x00,0x05,
0x00,0x80,0x00,0x05,0x01,0x00,0x00,0x05,0x00,0x80,0x00,0x43,0x00,0x80,0x00,0x45,
0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x06,0x56,0x65,
0x63,0x74,0x6f,0x72,0x00,0x00,0x00,0x00,0x4a,0x00,0x01,0x00,0x06,0x00,0x00,0x00,
0x00,0x00,0x06,0x00,0x80,0x00,0x06,0x01,0x00,0x00,0x84,0x01,0x80,0x01,0x04,0x02,
0x00,0x01,0x84,0x00,0x80,0x01,0xa0,0x00,0x80,0x00,0x29,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x04,0x00,0x0d,0x61,0x74,0x74,0x72,0x5f,0x61,0x63,0x63,0x65,0x73,0x73,
0x6f,0x72,0x00,0x00,0x01,0x78,0x00,0x00,0x01,0x79,0x00,0x00,0x01,0x7a,0x00,0x45,
0x4e,0x44,0x00,0x00,0x00,0x00,0x08,
};

アプリケーションをビルドするたびに変換するのもなんですので、ここまでの手順を Makefile なんかに書いておけば良いでしょう。

バイトコード配列を使う

アプリケーションの Makefile やプロジェクト設定で vector.c をビルド対象にして、このバイトコード配列を使っていきます。vector.c は、スクリプト側に変更をかけるたびに上書きで済ませたいので、使うコードは別のファイルがいいでしょう。

別ファイルにて

extern const uint8_t Vector[];

しておくと安心です。

実際の使い方はかなり簡単で、

mrb_load_irep(mrb, Vector);

だけでバイトコードが mrb_state* 空間にロードされます。 あとは、前述のとおり

RClass* prclass = mrb_class_get(mrb, "Vector");

という具合に、名前文字列から RClass* を取得できます。

オマケ

クラスとは関係ありませんが、随所に仕込んでおきたい例外とエラーの表現。

未実装例外

return mrb_exc_new(mrb, E_NOTIMP_ERROR, NULL, 0);

引数エラー例外(メッセージ付)

static const char m[] = "No such specified object.";
return mrb_exc_new(mrb, E_ARGUMENT_ERROR, m, sizeof(m) - 1);

今のところ分かってないこと

new したインスタンスを mrb_state 空間から動的に取得してくる方法が分かりません。インスタンスを取得するにしても、C コード側からは結局は RObject のポインタとしてしか表現されない(名前文字列みたいな「ラベル」もないですし)ので、後から使いたいオブジェクトはどこかにポインタを覚えさせておく必要があるのかもと予想してます。
あんまりよくコードを読んでませんが mrb_state の宣言に RObject* メンバがぶらさがっているんですが、このあたりが実体なのかも。

さようなら Ubuntu、こんにちは Linux Mint

ここ5年ほどメイン機で使っていた Ubuntu にとうとう別れを告げました。 Ubuntu の採用を辞める理由として挙げるとすれば以下の点です。

重い?

ハードウェアは 2012 年の暮れに SONY の公式オンラインストアで購入した VAIO Z で、Core i7 の 8GB RAM、SSD 搭載機です。 購入から1年半が経ちますが、まだまだ陳腐化していないスペックだと思います。グラフィックはインテルのHDグラフィックス…とオンボードのものですが、一昔前の安物グラボに比べれば、よっぽど安定していて高速なハズです。

なので、特に処理能力の限界を感じていたわけではありませんでした。もちろん、無駄に○○しているな〜と感じる点はありましたが、ハードウェア的なボトルネックが顕著になる以前に、私の自宅の WiFi の不安定さであったり、ファイル置き場になっている自宅サーバーのスペック不足でひっかかったりしていました。

Unity デスクトップ環境な Ubuntu 自体は大手ディストリの中でもかなり「重い」部類ではあると思いますが、そんなに苦になることはなかったと思います。

Unity まわりのUI設計のマズさ

動作の軽快さよりも、こちらの方がネックでした。使い勝手が悪いと悪評の高い Unity をやめようと思い、Classic デスクトップ環境に切り替えていた時期もありましたが、やはりしっくり来ず。 特に問題だったのが、タスクバーとメインメニューの統合です。これは登場した当初から叩かれていたので今更詳しく書くのもアレですので、要点だけを書いておきます。

  • 広いデスクトップ上でウィンドウ表示していると、左上のタスクバーにメインメニューがあると、その持ち主であるウィンドウから遠い。これは Mac なんかもそうかな?
  • GIMP などの複数ウィンドウで構成されているアプリケーションの場合、メインウィンドウがアクティブじゃないとメインメニューが表示されなくてかなり困る。つまりツールウィンドウを選択している時にタスクバーにカーソルを持っていっても、期待したメニュー項目がないんですよ。
  • タスクバーにマウス・ホバーさせないとメニューが表示されない。メニューが常に表示されていればマウスをダイレクトにポインティングできますが、一度タスクバーに盲目状態でカーソルを持っていく→表示される→改めて目的のメニュー項目までカーソルを持っていく、のパターンになって、マウス操作主体のアプリケーションだと軽く死ねます。

もともと、「ウィンドウごとにタイトルバーの下にメニュー領域を確保するのがスペース的な無駄だ」という発想だったのか、Mac の UI を真似したのか分かりませんが、使いづらく感じる人のほうが多そうですよね。前者の理由だった場合、Unity デスクトップ環境の左側に表示されているアプリケーションアイコンのほうがよっぽど邪魔です。自動的に隠すこともできますが、それでもアイコンサイズの設定できる最小値が大きすぎます。 最近のディスプレイは、ほとんどがワイド画面であるため、縦方向に領域を占有するメインメニューよりも、横方向に領域を占有するアプリケーションアイコンの方が犠牲になるコストは小さいかもしれませんが、なんだかよく分かりません。また、タブレット PC やスマホなど、タッチ操作をしなければならない端末でも、標準のマウス環境でも、どちらでも対応できるような UI 設計にしている戦略的な意味合いがありそうな気がします。どちらでも対応、と書くと聞こえが良いですが、言い替えると、どちらも中途半端ってことでしょう。こういうデザインのごり押しを見ていると、もはや商売戦略ありきの設計である Windows と何も変わらない気がします。

しかし非標準を許さない

Linux なんかの良いところは、自分の好きな環境を自分で組み合わせて最適なモノに囲まれてコンピュータ・ライフを楽しめるところだと思うんですが、ここまで時代が変わってくると、いろんなフレームワークやらライブラリやら、それを動かすためのフレームワークやら、ちょっとした事でもバックエンドの巨大なものをずるずるとひっぱってきたり、そうしているうちに整合性が取れなくなって、ちょっとした事でも意図したとおりの事ができなくなっちゃったりと、もう訳が分からなくなる事も多いです。

Ubuntu はその良い例で、標準的な考え方と Ubuntu 独自の考え方の相性が悪い印象です。ちょっとしたカスタマイズを施して使っていると、次のメジャーアップデートの際に決まって不整合となってしまい、面倒なことが発生していました。ユーザーに自由という権限を与えない変わりに、ある程度責任を持って「ユーザーが何も考えなくても快適な環境が提供されるシステム」だったら良いのですが、そこまで力及ばず、といったところでしょうかね。

カノニカルが以前、「我々のライバルは Windows ではなく、Mac OS だ。」と宣言していた気がしますが、UNIX を Mac OS にしちゃった Apple と カノニカルの大きな違いは、やっぱり力の強さ(資本や行動力)じゃないでしょうか。UNIX 系 OS でいわゆる非 UNIX ユーザも幸せになれるような環境を提供するには、Mac OS や Android といった、もはや UNIX 系とは思えないくらいの商業的かつパーソナルユーザ視点での作り込み、あるいは作り替えが必要になるんじゃないかなと。

まあ、Ubuntu コミュニティやカノニカルも含め、パーソナルユースの Linux、UNIX 環境に大きく貢献しているのは大きな事実ですので、感謝していますし、これからも発展して欲しいと思っています。

細かいところ

Nautilus が 0 バイトの画像や動画のサムネイルを生成する時にすとんと落ちてしまいます。これは致命的に痛いです。totemか何かでサムネイルを生成しているっぽいですが、Nautilus の設定等々をいじるよりも thunar に切り替えて使うケースが多かったです。また、thunar では、SSHFS でマウントしているネットワークストレージも、動画サムネイルを生成しつつもそこそこ素早くファイル一覧を表示できていたのですが、Nautilus では時間がかかった上にタイムアウトするケースも多く見られました。

うちの環境も原因の一つかもしれませんが、ファイラを替えただけでストレスなくオペレーションができている以上、Nautilus の挙動に問題があるような気もします。

これだけ不安定かつぽこぽこと強制終了していたらネモ船長もたまったもんじゃないです。

Linux Mint

Ubuntu の「かゆいところ」はまだ他にもいろいろありますが、Ubuntu の良いところを引き継ぎつつ、悪いところを排除する目標を掲げている Linux Mint に興味を持ちました。

WiFi の設定

まずはともあれ、ネットにつながってないと困ります。最近の先進的なディストリでは、デフォルトで WiFi が有効になっているので嬉しい限りです。自宅のアクセスポイントを選んでパスワードを入れるだけで繋りました。

Firefox syncの同期

次に、ウェブで情報を得たり、動画を見たりしながらセットアップをするので Firefox syncを同期します。自宅、職場、スマホと同期できるってのは本当に助かりますね。

(2014/5/15追記・最新の Firefox では sync の認証方式が変更されたようです。端末によって新方式と旧方式を同時に運用することはできず、全て新しい Firefox にアップデートして新方式にしないと同期が出来ない模様…。Windows 以外のマシンではしっかりしたバージョン管理システムの自動アプデに任せているから色々面倒だなぁ。
ちなみに、Bluetooth のハードウェア認証のような旧方式は、リカバリーキーやらペアコードやら意味が分からないものが多く、どちらがマスターデータでどちらがスレーブなのか分かりづらかったので、予想していたとおり大不評だったんでしょう。
今回の一般的なアカウントによるサーバ認証方式が採用理由は分かりますが、一度同期して運用しちゃってる設定をバージョンアップで変更しなければならないのは労力ですね)

また、宗教上の理由により検索バーのデフォルトは DuckDuckGo っていうアヒルになっていますが、

http://www.linuxmint.com/searchengines.php

の下部にある「Commercial engines(営利目的の検索エンジン)」の Google のアイコンをクリック後、検索バーのアイコンをクリックして出てくるプルダウンメニューより「”Google”を追加」をクリックすれば追加することができます。
さらに「検索バーの管理…」から Google の優先度を上げてやれば、晴れて Google に監視されっぱなし状態になれます。

Ctrl キーと Caps Lock キーの入れ替え

システム設定の「地域と言語の設定」より、キーボードレイアウト→オプションから変更しました。
Xの設定ファイルをいじって、いじっている途中に Caps Lockを押してしまってイライラしていた時代が懐しい…(でも、もはやGUIなしじゃすぐに設定できない体になってしまいそうです)

ちなみにうちは、日本語環境、日本時刻、英語配列キーボードっていう環境です。

uim と skk の導入

Mint にはデフォルトで日本語 IM が入ってないらしいんですが、SKK 使いの自分としては 使いもしない Anthy などが入っているより好都合です。

sudo aptitude install uim uim-gtk3 uim-skk

としてサクっと入れます。
一度、ログアウトしてセッションを開始し直せば、C-j で日本語入力ができるようになりました。

sshfs の導入

以前のファイルは、別のサーバーマシンに預けているので、sshfs を導入。

sudo aptitude install sshfs

で、一般権限でも fuse できるようにします。

sudo chmod o+rw /dev/fuse
sudo chmod 4755 /bin/fusermount

これでマウント可能になりました。簡単すぎる…!

自分コマンドのパスを通す

HOMEの.ファイルを移す

Dropbox のセットアップ

$ mkdir ~/bin
$ wget -O ~/bin/dropbox.py http://www.dropbox.com/download?dl=packages/dropbox.py
$ chmod a+x ~/bin/dropbox.py
$ dropbox.py start -i

Skype

http://download.skype.com/linux/skype-debian_4.2.0.13-1_i386.deb

DraftSight

http://www.3ds.com/ja/products-services/draftsight/download-draftsight/

libgtk2.0-0:i386
/opt/dassault-systemes/DraftSight/Linux/DraftSight
/opt/dassault-systemes/DraftSight/Linux/DraftSight: error while loading shared libraries: libGLU.so.1: cannot open shared object file: No such file or directory

$ sudo apt-file search libGLU.so.1
libglu1-mesa: /usr/lib/x86_64-linux-gnu/libGLU.so.1
libglu1-mesa: /usr/lib/x86_64-linux-gnu/libGLU.so.1.3.1

sudo aptitude install libglu1-mesa:i386

デスクレットの追加

「システム設定」の「デスクレット」より、デスクレットとよばれるウィジェットをデスクトップに追加できます。
Ubuntu では天気とカレンダーを表示していたのですが、カレンダーがなかったので AccuWeather Desklet だけを入れてみました。

Monodevelop

sudo aptitude install libmono-cairo2.0-cil

virtualbox

sudo aptitude install virtualbox-qt virtualbox-dkms 

gvim

JQuery覚書その1

JQueryをまともに使わなければなー、ということで自分用の覚え書きを書いておきます。

セットアップ

通常の JavaScript のようにホストに設置しても良いし、JQuery の公式や Google が提供している API 経由で読み込ませてもOK。

<script src="jquery-1.11.0.min.js"></script>

基本

エレメントには、$() でアクセスする。

<div id="hoge"></div>

$("#hoge").text("hello, world");
$("#hoge").css("background", "#FFFF00");

getElementById をとってきて innerHTML をいじくるような面倒くさいことはない。

#hogeid="hoge".hogeclass="hoge" というふうに ID や Class で指定可能。
タグで指定する場合は $('div') となる。また、複数のエレメントを指定するには、$('#foo,#bar') のようにカンマ区切りも可能。

メソッド

引数なしで呼ぶと取得、引数を渡せばその引数で設定。

  • text()
    div内などのプレーンテキスト
  • html()
    生HTML
  • val()
    input タグなどの保持している値
  • css(属性名, [値])
    css だけ属性名は必須。値は設定時のみ。

エレメントつくるよー

作るだけなら $('<p>hoge</p>') と HTML 直書きで良い。
突っ込むには、

  • elementA.append(elementB)
    elementAの中にelementBを突っ込む。
  • elementA.wrap(elementB)
    elementAをelementBで囲む。elementAが複数要素だったら個別に囲む。
  • elementA.wrapAll(elementB)
    elementAをelementBでまとめて囲む。
  • elementA.before(elementB)
    elementAの前にelementBをおく。
  • elementB.after(elementB)
    elementAの後にelementBをおく。

データを保持させとくよー

element.data(キー, 値)
var = element.data(キー)

エレメント自身にデータを持たせておいて、必要な時に使える。ページが更新されるまで生きてる。

イベント

エフェクト

非同期通信

var param = {key:”value”};
element.load(“hoge.txt”[, param])

これで element.text に結果を突っ込める。
post/getメソッドを使って、取得後の処理を行いたい場合は

$.get(“hoge.cgi”, param, func);
$.post(“hoge.cgi”, param, func);
function func(result) { … }

funcのようにコールバック関数を指定する。result にとってきた値が入る。この場合生テキスト。

$.getJSON(“hoge.json”, param, func)

で JSON 形式で取得。result は JSON オブジェクトとして使えるので、

{ "foo": "bar" }

が内容だった場合、var str = result.foo; とすると str に “bar” が入る。

シリアライズ

フォームの内容をまとめてシリアライズ!

var param = $('#form1').serialize();

こいつをpost()とかget()とかに投げる。べんり。

ANSI エスケープシーケンスについて

端末の色やカーソル制御を行うには、curses を利用するのが一般的ですが、ライブラリを利用しなくとも、シェル経由である決まりのエスケープシーケンス文字列を端末に投げることにより、色やカーソル制御を行うことができます。

次のページに詳しく記載があります。

Bash Prompt HOWTO: ANSI エスケープシーケンス: 色とカーソル操作

  • 昨今の bash では\033\eに設定されているため、例えば\033[\0m\e[0mと記述できます。
  • また色指定の\e[31mなどを\[\]で囲む記述がありますが、囲まなくても大丈夫のようです。
    • 例) \[\033[41m\]\[\033[1;37m\] string \[\033[0m\]\e[41;1;37m string \e[0m
    • だいぶすっきり。

前景色・背景色の指定

xtermなど、一般的な端末でサポートされている ANSI カラーの 8 色です。太字設定をすると、それぞれの色が高輝度・低輝度な 2 種類の色になるため、事実上 16 色になります。

0 1 2 3 4 5 6 7

赤の前景なら\e[31m、青の背景なら\e[44という風に、それぞれ30番台と40番台の1の位が上の表となります。また、太字(強調文字・高輝度な文字)表現にするには、\e[32;1mのようにセミコロン区切りで属性を加えてやります。この1桁の属性値は順番は問わないようで\e[1;32mでも同じ意味になります。 属性値は 1.太字、4.下線、5.点滅、7.反転、8.非表示 らしいです。

色の見え具合は端末によって結構変動します。上の表は原色のビビットカラーで表現していますが、最近のオサレな端末なんかは、色がギラギラして見えづらいことに対する配慮のためだろうと思いますが、デフォルトでは抑えた色で表現するよう定義されています。端末によっては色のバインドを変更することも出来ますし、見え具合はあんまり保証されていません。

また、xterm の拡張256色サポートをしている端末も結構あります。こちらはRGB値を数値指定して端末上に表現しているものですから、見え具合の差異は少ないと思われます。 256色サポートについては、5年ほど前に2chの「コンソールゲーム」スレに書き込んでいたログに書いていた内容がまだ残っているようです。

vim で簡単ドット絵エディタ

前に作っていたコンソールベースのゲームは、0から7をひたすら書いたテキストファイルをグラフィックファイルとして用いています。 シンタックスハイライトに次のように定義してやると、vim が簡単ドット絵エディタになります。

let b:current_syntax = "amap"
syn match g0 /0/
syn match g1 /1/
syn match g2 /2/
syn match g3 /3/
syn match g4 /4/
syn match g5 /5/
syn match g6 /6/
syn match g7 /7/
hi g0 ctermfg=gray ctermbg=black
hi g1 ctermfg=gray ctermbg=red
hi g2 ctermfg=gray ctermbg=green
hi g3 ctermfg=gray ctermbg=yellow
hi g4 ctermfg=gray ctermbg=blue
hi g5 ctermfg=gray ctermbg=magenta
hi g6 ctermfg=gray ctermbg=cyan
hi g7 ctermfg=gray ctermbg=white

前景色を見やすいように gray に設定しているので、set t_Co=256を設定しておかないといけないかもしれません。 あとは対象のファイルを開いてset syntax=amapしてやるだけです。

00000400000
00004440000
00444444400
44407440744
44411111444
04444444440

こういうテキストファイルが

you know what

例のアレのように表現されます。

作図っていうと、ビジュアルモードの矩形選択や一括置換が力を発揮しますね。

端末に表示するスクリプト

最近、ruby が楽しくて仕方ありません。上記のファイルを端末に表示するスクリプトです。libcaca の img2text の劣化みたいですね。

#!/usr/bin/env ruby
# -*- mode:ruby; coding:utf-8 -*- 

class String
  def number?
    self =~ /\A-?\d+(.\d+)?\Z/
  end
end

def printimg(file)
  File.open(file) do |f|
    buf = f.read
    cur = nil
    buf.each_char do |c|
      if c.number?
        if cur != c
          print "\e[4" + c + ";1m "
          cur = c
        else
          print " "
        end
      else
        print "\n"
      end
    end
    print "\e[0m"
  end
end

ARGV.each do |file|
  printimg file
  puts "---"
end

このスクリプトに

66666666666666666666607777707770777077777707707777777077777777777777777077700777
66666666666666666666077777077707770777777707770770777077777777777777777707077777
66666666666666666666607777077077770777077707777070777007777777777777777770777777
66666666666666666666660077077077770777077077777707077070777707770777777777077777
66666666666666666666666607077077770777077000077777707077077000770777777777077777
66666666666666666666666666607077707777077077700777770770000707070777077777077700
66666666666666666666666666607077707770707077777077777707707707707070707777707077
66666666666666666666666666660077707770707077777777777777770707777070770777700707
66666666666666666666666666666077707700000000007777777777000000000000000777707707
66666666666666666666666666666077707770777711177777777777777777111177770777707707
66666666666666666666666666666077707707077711117777777777777777111117707077707707
66666666666666666666666666666077770707777777777777777777777777777777777077707707
67774747477747774746677747774707770707171777777777777777777777771717777077070707
67466747474747474746674746746007770707777777777770777777777777777777770777070770
67466777477747746746674746746007770707777777777777777777777777777777770777070770
67466747474747474746674746740707770770777777777777777777777777777777707770770770
67774747474747474777477746707700777077077777711111111111111111111111111707111117
66666666666666666666666666077070777701111111111111111111111111117770111111711111
67474747477747774746677740700711111111111111111111111111111111177777011111111711
67474747474667466746674660040701111111111111111111111111111111117770111111111171
67774747474747774746667406740701111111111111111111111111111111111111111111111110
67474747474747466746666746740700111111111111111111111111111111111117770111111000
67474777477747774777477746707770011111111111110000000000111111111177777011110001
66666666666666666666666666077777000111111110000000000000000001111117770111110001

という内容のテキストを食わせてやると

charlot

こんな感じになります。

さらに、拡張256色モードを駆使すると

xterm-256-map

こんな具合に!

enter image description here

こんな具合に!!!

…ゲームなんかで多様する茶色や肌色みたいな非原色が使えるのは嬉しいんですが、256種類も色があると

  • vim で描けない
  • 管理したり作ったりするのが大変
  • 色のバインドに迷う

と、色々弊害も出てきます。

今回はすべて背景色だけで描画していますが、前景色付きの文字を組み合わせて微妙な色を表現したり、さらにはUnicode文字の網掛けなどを駆使しつつ広大な縦横文字数を持つ端末を必須にするなどすれば、事実上、なんでも表現ができてしまいそうな気がします。

表現力にこだわりたいなら、SDL でも GL でもフレームバッファでも何でも使えばいいと思うので、色のつかいすぎは「端末だってここまでできるんだよ!」的なデモ用途にしか使う意味がないのかもしれません。で、そうなると、前述の libcaca などの高品位なデモを見ていればいいわけで・・・。

ゲーム用途には、大小アルファベットと数字で表現できる64色+RGBバインドくらいがちょうどいいのかなーと思うこの頃です。
ちなみに、モノクロでダンプできる rogue はいろんな意味で美しいです。

伊能図にみる佐世保

inoh0190-trimmed

伊能忠敬が作成した「大日本沿海輿地全図」、通称「伊能図」に掲載されている19世紀初頭の佐世保市の地図です。分かりやすいように着色をしていますが、今からちょうど200年前の地図とは思えないほど正確ですね。

佐世保市民の方ならご存知の方も多いと思いますが、明治時代に佐世保に鎮守府が置かれるまで、佐世保は小さな漁村でした。そのため、明治より前の佐世保に関する史料は他の大きな街に比べれば乏しいようで、今なお研究が進められています。

白形浦

佐世保の人に「白形浦」と言っても誰もピンと来ないと思います。位置的に考えると鎮守府施設が置かれた場所のため、後世に地名が残らなかったと思われます。港湾設備を整えるために、明治初期に測量した図が実家にあったはずなので、今度帰った際に確認したいと思います。

横尾

今では影が薄い横尾町ですが、佐世保が市になるずっと昔からあったようです。私の家系の本家と分家は、横尾町一帯にあるので、市になる前から住んでいた一族なのかもしれません。だったらちょっと嬉しいな。(ほとんどの佐世保市民は、明治以降に佐賀などから移住してきた方々らしいです。)

山中

現在の山の田浄水場付近が「山中」という地名になっています。桜木町、赤木町付近だと思いますが、山中山という地名までありますね。浄水場が作られたのは1908年(明治42年)なので、その頃には山の田と呼ばれるようになっていた模様です。

早岐

早岐の古い町並みを見ると分かると思いますが、昔は早岐のほうが都会でした。江戸時代には既に100軒を越える集落があったらしく、平戸方面・長崎方面・太宰府といった福岡方面、さらには海路へとつながる地理的な理由もあったと思われます。400年続く早岐茶市がその繁栄っぷりを物語っているのではないでしょうか。また、早岐の名前の由来ともなった速来津姫伝説が収録されている「肥前国風土記」にも登場しています。

相神浦

最近、離島防衛の要となる「水陸機動団(日本版海兵隊)」が陸上自衛隊相浦駐屯地に拠点を置くことになりました。その基地がある相浦一帯は、以前は相神浦(あいこのうら)と呼ばれていたようです。相浦川流域全体のようで、柚木までカバーしています。佐世保村との境界は、今の春日町、西海学園近くにある堺木バス停留所付近だったらしく、松浦郡と彼杵郡の境界にもなっていたようです。 地図では小さくて分かりづらいかもしれませんが、愛宕山付近に飯盛城のことだと思われる「古城跡」の記載も見てとれます。

こういう風に地図を眺めているだけでも楽しいので、時間ができたら市立図書館の郷土資料室に行っていろいろと調べてみたいです。

ASP.NET を初体験

Web アプリケーションといえばもっぱら Perl, Ruby, Python あと少しだけ PHP な自分なのですが、仕事でちょっとした ASP ベースの API を書かなければならなくなりました。うちは90年代に育った小さな会社ということもあり、ネットワークは Windows ドメインネットワーク、Web サーバーも IIS ベースという(自分にとっては)息が詰まるような環境です。

ASP が書けるプログラマーがほとんどいない状況で、ASP ベースの API を担当していた先輩が事故で入院してしまい、その後釜を任された同僚のサポートという形で扱うことになりました。元々の API は無印の ASP ですので、いわゆる Visual Basic 6 的な構文。仕事の内容なので、あまり具体的には書きませんが、90年代半ばの機能を駆使してわざわざ面倒かつ煩雑なシステムにしてしまっているように思えて仕方ありません。UNIX における枯れた技術と Microsoft の政略が絡んだ枯れた技術では意味が違うと思いました・・・。

IIS の意味が分からない

Apache, lighttpd, nginx などの Web サーバーの考え方がベースになっている自分にとって、Microsoft の Web サーバー Internet Information Service の意味が分かりませんでした。実装した API の不具合がスクリプトサイドにあるのか、Web サーバーにあるのか、DB サーバーにあるのか、構造から理解するのに苦しみました。UNIX 生まれのインターネット技術をパクった挙句、ユーザーのためではなく自分らのために無駄なものをたくさん乗っけて、挙句、複雑怪奇な環境を提供しているようにしか思えません。Microsoft が出している開発環境をお金を出して買えば、トータルで面倒を見てくれるように商売戦略上設計されているんでしょうが、非 Web 環境で毎日 Visual Studio を使っている UNIX ユーザーとしてみれば、それも眉唾ものだと思いました。

Visual Studio の意味が分からない

Microsoft が提供している環境というのは往々にして、「ユーザーが自分でモノを考えて何かをやろうとすると墓穴を掘る」みたいなので、大人しく Visual Studio の Web デベロッパーツールを使用することにしました。うちは VS2008 ベースですので必然的に ASP.NET になります。Microsoft の技術にコードを投入してしまうと、過去の遺産とかそういうものは諦めないといけません。 VS2008 をインストールした時点で、まさか ASP.NET をすることになるとは思ってもいなかったので、追加インストールが必要になりました。追加インストールのためインストーラを起動してみると、嫌がらせのようにインストーラがエラーで落ちます。私の環境には、VS2010 と 2013 も入っているのですが、それが影響しているんでしょうか・・・。調べる手口もありません。 オープンソースなソフトウェアならば、調べてバグレポートのひとつも送らねば!と思うのですが、お金を払った上にこれだとそんなにマゾにもなれません。さっさと諦めてしまいました。

オープンソースの .NET 環境 Mono が素晴しい

平日、家に帰った後と休日はもっぱら Linux ベースで作業しています。職場では Windows と Visual Studio を使っています。どちらも時間的には半々なので、自身では盲目的な信者のつもりはないのですが、やっぱりオープンソースの方がユーザーフレンドリーです。

自宅の Linux 環境にも Mono を入れているので、もしかしたら ASP.NET も Linux 上で上手い具合に開発ができるのかなーなんて思って調べてみると、やはりありました。オープンソース万歳!信者とでも何とでも言ってくれ!

aspnet_on_monodevelop

Mono Develop にも最初から ASP.NET ソリューションを作成するのがついてました。もう「これでいいじゃん」感がハンパないです。さて、実際に開発をするには ASP.NET を動かすための Web サーバーを導入する必要がありますが、これも Mono 開発環境の一つとして XPS サーバーが準備されています。こいつも例のごとく、コマンド一つで導入できるのがクールです。

sudo aptitude install mono-xsp

Mono Develop のサンプルの ASP.NET ソリューションをデバッグ実行すると、次のようにちゃんと動きました。ハラショー。

asp_net_running

互換性についても C# は確か ECMA だか ISO だかで規格化されていますし、Visual Studio や IIS といった環境に左右されまくる Windows ベースでの開発よりもよっぽど安心して出来そうです。ちなみに、うちの環境では .NET は 4.0、C# は ISO-2 までサポートされています。

mono40

MonoDevelop が Vi キーバインドできるようになって、C++/CLI を使わずに済むプロジェクトをやるようになったら、本気で MonoDevelop で仕事しようと思いました。

追記

デフォルトで Vi キーバインドできました。快適すぎて涙が出てきそうです。

WordPress の記事投稿を Markdown に変更しました。

タイトルのとおり、WordPress の記事投稿を WP-Markdown というプラグインを入れて Markdown に変更しました。HTML のビジュアルエディタだと、コード中の <> 記号との相性が悪かったり、ドキュメントの文字情報とレイアウト情報がごちゃごちゃになってしまう HTML というものの、情報の入れ物としての素質的にどうなのかなあ、と思うところがあっての変更です。

シンタックスハイライターと衝突

これまで、コードのシンタックスハイライトには「SyntaxHighlighter Evolved」というプラグインを利用していましたが、Markdown プラグインと相性が悪いのか、レイアウトが崩れてしまいました。 現在は SyntaxHighlighter Evolved を無効にして、WP-Markdown の pretify syntax highlighter を有効にしています。これは pretify.js というライブラリでハイライトしてくれるらしいモノで、SyntaxHighlighter Evolved のように行番号表示や言語を指定する機能はありませんが、軽快かつ適当に色をつけてくれます。

なお、wp-markdown-syntaxhighlighter というプラグインを入れれば SyntaxHighlighter Evolved との衝突を防げるといった記事を見かけましたが、自分の環境ではムリでした。