I know I believe in nothing but it is my sweet nothing.:2008年03月分

2008/03/03(Mon)

週末

Hi-Maticのピント調整がイマイチだったのでバラして組み直したり。

最近買ったもの

[NetBSD] Citrus iconv

すっかり忘れてたのだが、 この問題も直さないとな。

前回の ISO-2022-JP問題の対応がいまいちいちイケてないわけですな。

もうちょいコード整理しないとアレだけどこんな感じ?

Index: citrus_iconv_std.c
===================================================================
RCS file: /cvs/cvsroot/src/lib/libc/citrus/modules/citrus_iconv_std.c,v
retrieving revision 1.15
diff -u -r1.15 citrus_iconv_std.c
--- citrus_iconv_std.c	13 Nov 2006 19:08:19 -0000	1.15
+++ citrus_iconv_std.c	3 Mar 2008 09:30:48 -0000
@@ -477,6 +477,57 @@
 	if (in==NULL || *in==NULL) {
 		/* special cases */
 		if (out!=NULL && *out!=NULL) {
+			for (;;) {
+				ret = get_state_desc_gen(
+				    &sc->sc_src_encoding, &state);
+				if (ret)
+					goto err;
+				if (state == _STDENC_SDGEN_INITIAL ||
+				    state == _STDENC_SDGEN_STABLE)
+					break;
+				save_encoding_state(&sc->sc_src_encoding);
+				save_encoding_state(&sc->sc_dst_encoding);
+
+				/* XXX FIXME, need to heavily rework. */
+				tmpin = "";
+				szrin = 0;
+				ret = mbtocsx(&sc->sc_src_encoding,
+				      &csid, &idx, &tmpin, 1, &szrin);
+
+				if (ret)
+					goto err;
+				if (szrin == (size_t)-2) {
+					ret = EINVAL;
+					goto err;
+				}
+				/* convert the character */
+				ret = do_conv(is, sc, &csid, &idx);
+				if (ret) {
+					if (ret != E_NO_CORRESPONDING_CHAR)
+						goto err;
+					++inval;
+					szrout = 0;
+					if ((flags & _CITRUS_ICONV_F_HIDE_INVALID) == 0 &&
+					    is->is_use_invalid) {
+						ret = wctombx(
+						    &sc->sc_dst_encoding,
+						    *out, *outbytes,
+						    is->is_invalid,
+						    &szrout);
+						if (ret)
+							goto err;
+					}
+				} else {
+					ret = cstombx(&sc->sc_dst_encoding,
+					      *out, *outbytes,
+					      csid, idx, &szrout);
+					if (ret)
+						goto err;
+				}
+				*outbytes -= szrout;
+				*out += szrout;
+			}
+
 			/* init output state and store the shift sequence */
 			save_encoding_state(&sc->sc_src_encoding);
 			save_encoding_state(&sc->sc_dst_encoding);
@@ -505,12 +556,8 @@
 
 	/* normal case */
 	for (;;) {
-		if (*inbytes==0) {
-			ret = get_state_desc_gen(&sc->sc_src_encoding, &state);
-			if (state == _STDENC_SDGEN_INITIAL ||
-			    state == _STDENC_SDGEN_STABLE)
-				break;
-		}
+		if (*inbytes == 0)
+			break;
 
 		/* save the encoding states for the error recovery */
 		save_encoding_state(&sc->sc_src_encoding);
@@ -524,22 +571,8 @@
 		if (ret)
 			goto err;
 
-		if (szrin == (size_t)-2) {
-			/* incompleted character */
-			ret = get_state_desc_gen(&sc->sc_src_encoding, &state);
-			if (ret) {
-				ret = EINVAL;
-				goto err;
-			}
-			switch (state) {
-			case _STDENC_SDGEN_INITIAL:
-			case _STDENC_SDGEN_STABLE:
-				/* fetch shift sequences only. */
-				goto next;
-			}
-			ret = EINVAL;
-			goto err;
-		}
+		if (szrin == (size_t)-2)
+			goto next;
 		/* convert the character */
 		ret = do_conv(is, sc, &csid, &idx);
 		if (ret) {

以前のエントリではdst(cs/idx -> wc -> mb)側のstate objectを初期化するput_state_reset()と同様に
src(mb -> wc -> cs/idx)側のstate objectも初期化する必要があるよね、と書いたのだけども
ここではmbtocsx()で代用してる(XXX FIXMEの部分)。

この部分どうしようかね、mbtocs()が内部で呼ぶmbrtowc_priv()は

mb = NULL;
mbrtowc_priv(ei, &wc, &mb, 0, ps, &nr);

という呼出をした場合、mbrtowc(3)の仕様である

If s is a null pointer, the mbrtowc() function shall be equivalent to the call:
mbrtowc(NULL, "", 1, ps)

通りの動作をするので、wcを無視してpsを初期化しちまうのだが
DR#288のケースをうまく扱おうとするとここは
「psの中にまだ変換可能なwchar_tがある場合、それを吐き出す」
という動作をして貰いたいよな。

今は緊急避難で"", 1を喰わせて回避してるのだが、ちとkludge過ぎる。
というのも、VIQRならこれでも解決するんだが、UTF-5のバヤイそもそも""はillegal byte sequenceだ罠。

2008/03/04(Tue)

[NetBSD] one-shot translations problem

hubertf氏よりblogに 私のtech-userlevelへのpostについての指摘を書いたとのメールを頂いた *1
英誤書くのがアレで返事まだなのと、氏が(多分)読めない言語でtrackbackすんのもアレなので
直リンせずに以下引用。

Maybe that's of interest for parties who want to help out in translating
those parts of the NetBSD operating system.
BTW, while here: at www@, we receive regular inquiries about help with
translating NetBSD's website and the NetBSD Guide into other languages.
Unfortunately doing one-shot translations is one thing, maintaining them is
quite a different beast.
Experiences from the past have shown that those translations are usually not
maintained after an initial translation effort, and stay outdated.
As a consequence, the NetBSD project has decided that we will not put efforts
into maintaining translations in the future.
People who want to translate parts of NetBSD's website or any of the guides
(NetBSD Guide, pkgsrc guide)
are welcome to do so when they are also hosting them at their site. Please talk
to www@NetBSD.org for linking to those external translations then. Thanks!

ちょwwww2chの某スレといい翻訳ネタは鬼門すぐるwwwww
ところでwww@ *2のmail-archiveってどこで読めるのだろう、 NetBSD guideには
まだこういう方針は書かれていないようなのだけども。

これまでの議論、そしてwww@チームがしてきた努力について申し訳ないが全く知らんのと
www.netbsd.orgのl10nとlibcのnls(7)の話をゴッチャにするのも嫌なんだけど
私がこのone-shot translations problemについてつらつら思うことを無責任風味で書き連ねてみると:

ってとこかな *3

メモ

まあencoding modules/{locale,iconv} databaseそしてmessage catalogについては
NetBSDのsrc treeからはいっそのことサックリ全部消しちまって
pkgsrc.orgのように別プロジェクトとして独立 *4した方がいいんじゃね?
とは昔から漠然と思ってるのだけれども *5
baseにある必要は全く無い *6しね。
まあ自分が手を上げるかってーと、そんなモチベーションも体力も全くありませんが。

さすがにmessage catalogまでとなると難しいけどね、あれ実装依存だし。
GNU-coreutilsに倣って、BSD-coreutilsとかで共通の実装を使うなら話は別だけど
まあ天地がひっくり返ってもアリエナサス。

*1:なぜtech-userlevelに流さんのかはよく判らんw
*2:wwwって氏はvipperか!とオモタ俺はもうダメかもしれん。

*3:戸田奈津子口調ってけっこう難しいな
*4:openi18n.orgのOpenLocale/LDMLなんてのもあるわけだけど、あれはあれで(以下略
つーかソレナンテ Citrus?
…元々localedef/charmapはOS非依存なものだし、今のrune(3)形式にしたって
Citrusの元々の目的としては*BSDで共通のPOSIX localeの実装を
というのがあったわけでして。

*5:そうすっとlocaledef(1)をtoolchain化する必要もなくなるしね。
*6:おっと、ISO-8859-1とUTF-8だけはbaseに入れろとか差別は認めん、C/POSIXだけなwww

2008/03/07(Fri)

今日

昨日の打ち上げの酒が残ってて気持ち悪い、もうおちゃけやめゆ。

月末にAsiaBSDconあるのな。
今回はスケジュールが本業の資産凍結とリリースの合間なので
参加できないこともないのだけれども、金無し君 + モチ枯れ中なのだ。

んでその金無し君の原因であるThinkPad X61は明日届くとlenovoから連絡キター。
っても元々 これ買うつもりでいた予算を
ThinkPad s30の不調で急遽振り替えたのであんまし嬉しくないのだ orz
まああと10万足りないのと(AF28-70/F2.8Gは10万台前半で買えたのに…)
うちのボディは全部SSM非対応なので、ほとんど買う気は喪失してたのだけどもな。

そいやα-350って今日発売か、お触りだけわしてこよう。

2008/03/11(Tue)

今日

昼飯喰いに外でようとして、今日は自分がネクタイを「2本」締めてることに気づく。
俺はもうダメかもしれん。

週末は届いたThinkPad X61を封も切らずに放置、お外ぶらぶら。
AFK48(Away From Keyoard 48hour=土日はコンピーター触るな)運動実施中。

α-350売れてるみたいだね、α-7000ショックまでとは流石に無理か。
あとは今のいびつなレンズラインナップをなんとかしちくり。

某楽器店、HOHNERのPianet Tが15万、高くね?
でも音はいいなー、RhodesとかWulitzerとはまた違うけど「本物」のエレピの音。
これでトレモロかけてパンさせたらネクタイ3本締めたくなりそうだな。
何がいいたいかというと、サンプラーなぞ窓から投げ捨てちまえ!ということです。

昔バイトしてた某スタジオで、Rhodes MarkI 73 Suitcaseを1万5千円(相場の1/20)
ちゅー格安で売ってもらうチャンスがあったのだけども、置き場が無くて
泣く泣く友達にゆずった経験がトラウマです。

コンボオルガン、Hammond XK-3cもRoland VK-8もダメだこりゃ。
XB-2を全鍵ポリフォニック化するだけでよかったんに、要らん機能をゴテゴテと。
そいやレスリースピーカーのエミュで電源入/断によるピッチアップ/ダウンまで
きっちり再現したやつってどっかないのかな?
あれがないとAl Kooperごっこができんので大変困る(普通困らない)。

通信教育の教材でおなじみRoland SH-101が5万…なんてこったい(AA略)
ケタ1つ間違ってね? アナログだったら何でも大金積むんだな>>テクノ厨
あんなんより今がカス値(5kくらい)D-5/10/20系の第2世代LA音源買って
真面目に音作り勉強したほうがよっぽど正しい金の使い方だと思われ。
あれハイブリッドだけどアナログ部はPWMとかリングあるし結構強力よ?

鍵盤楽器はデジタル化ですっかりつまらなくなったよな。
カメラも同じことにならないように祈ってます。

2008/03/17(Mon)

先週

会社帰り@川崎駅、映画 Controlのポスター貼ってあるじゃないの。
観て帰んべーとUターンしてチネチッタへGo。
…3/22から上映らしい、残念。
まあ 原作サントラは発売されども本編の日本公開時期は
ずーと音沙汰ないなーと思ってたので、よかった。
Anton Corbijnの映像美はスクリーンで堪能したいわな。

まだThinkPad X61セットアップしてないや、i386かamd64どっちにすんべ。

xvmwareのコード変換部をXutf8*でなくXmb* + iconv(3)で書き直したいんだよな。
vmwareだとテストとかでXFree86-4.0.2以前の環境で動かしたい場合もあるしね。
ただ-DX_LOCALEでbuildしたXlibのことを考えるとnl_langinfo(CODESET)使えないのが困る。
#厳密にいえばiconv(3)にnl_langinfo(CODESET)渡すのも微妙ではあるが。
まあこれは_XGetLCValues()使ってsetlocale/_Xsetlocaleに対するnl_langinfo/_Xnl_langinfo実装するしかないかな。

2008/03/18(Tue)

[NetBSD] tech-userlevel

それはttyドxtermが\x00をzero widthで表示してるだけでわ(汗 。

less/LESSCHARSETも

と書き直した方がいいんだろけどな。
ちゅうかUNIXのpipe思想からすると、iconv(1) + CSI more(1) or less -rが正しいような希ガス。

その点を踏まえると、iconv(1)の-tオプションは省略可能な方がいいのだけども
SUSv2の仕様では省略不可なんだよな、GNU libiconvは拡張されてるけど。

うお SUSv3で改定されて省略可能なのな。
じゃぁそのうちに対応しちまおう、 patch
それとiconvが持つ変換テーブルって実装依存だったのだけど
charmapを使う可能性についても言及されてるのね。

charmapをiconv(3)でも使うとなると、やっぱりyamtさんが昔書かれてた
jil(jikken locale、bsd-locale-ja@から探してちょ)みたいな実装が一番いいのだろうね。
charmapはCitrus iconvみたいにCES(esdb)/CSS(csmapper)の分離できてないけども
同じ文字には同じ名前がついてるはずなので

で済むのよな、ある意味今のCitrusよか効率だけは良い可能性がある。

ただcharmapってそもそも

  1. ↓なんかの扱いがムリムリムリムリかたつむりよ!
    • HZ-GB2312のようなlocking shiftするようなstateful encoding
      (ISO-2022はTR14652でなんとか)
    • UTF-7のような7/16という変則的なmultibyte
  2. 包摂規準の異なる文字集合同士とかの変換がヤバイ
    つまり同じ文字に同じ名前がつけられない事もあるわけですよ。 例えば
     CP864とかCP1046のアラビア表示形B <-> ISO-8859-6の同基本形
    
    の変換考えた場合とっても頭が痛い。
    そもそもの話ですまんけど、これlocaledefからcharmap使う場合も微妙だよな。
    それこそJIS2004 <-> UCS4の1:N変換とか考えた場合
    ja_JP.Shift_JIS-2004とja_JP.UTF-8は同じja_JPなlocaledef srcを定義可能なのかとか。
    (まあwchar_t=ucs4のバヤイ1:Nがあること自体が矛盾なので、glibc方面では 無視してるようですが *1)
  3. GNU libiconvの//TRANSLITやUnicode Normalizationのような換字情報どうするよ?
    換字情報をwctrans(3)のuser-defined classで実装できたりするといろいろ矛盾ないのだけど
    //TRANSLITは1:N変換なのにtowctrans(3)は1:1変換だしね。
  4. Unicode Language TagにUnicode Variation Selectorどうするよ
    すでに IVDの登録始まってんのねぇ、 前も書いたRAW変換が必要なら
    iconv -f utf-8 -t adobe-japan1-6
    
    つーのもありうるんだよな、gkbr。

げげげ、今のCitrusってUTF-16/32(endian指定なし)を変換後に指定した場合
動作してるMACHINE_ARCHのendian + BOM無しで出力するんだが
GNU libiconvとかPerl iconv(piconv)はbig endian + BOM有りで吐きよるのな。
glibc2 iconvはMACHINE_ARCHのendian + BOM有りみたいだし、
せめてBOMだけでも吐いといた方がいいのかも知れん、 patch

*1:Unicode Named Character Sequenceとwchar_tの32bit目使うとか考えてたりして、gkbr。

2008/03/19(Wed)

昨日

来年度のねんぼう(何故か変換ry 交渉。
裁量労働契約が導入されるらしいがどーでもよろし。
そもそも残業代なんて(以下検閲

ボイコットって語源は人名だったのか。
多分どっかの国の新聞に

『アタシ、もうボイコットしちゃおうかな』という言葉があちこちで聞こえる~

という記事が載ったんだな(それ違

先日書いた通り、 xvmwareをCSIに書き直したので、4.0.2より前のバージョンの
XFree86でも動くはず(未検証ですが)、xorg?なにそれ?
あとはamd64対応くらいで終わりにすっか。
ほんとはテキスト以外のコピペや、ドラッグエーンドドロップ(by XDND)に
対応してみるもの、Selection APIのサンプルにちょうど良いのだけども
いかんせんbackdoorだけでは実装は無理げるげ。

2008/03/20(Thu)

[NetBSD] またlibstdc++か

うーむ、またしてもspamprobeが落ちるようになってる。

Program received signal SIGSEGV, Segmentation fault.
0x08093f80 in std::operator+<char, std::char_traits<char>, std::allocator<char> > ()

current-userに報告あるのと同件ですな。
なんでこう頻繁に後方互換壊すのだろう(そしてgcc people達は平気なのだろう)。
やぱり自前のlibstdc++欲しいやね。

2008/03/21(Fri)

[NetBSD] nl_langinfo(CODESET) ? locale_chartset() ?

CSIに書き直した xvmwareだけんど、またまた非常にダメぽなバグあった *1んと
libc builtinのiconv(3)を使わずにGNU libiconvを使う必要がある場合
対策が必要なのを忘れてたので修正しますた。
#まだバグあるかも。

GNU libiconvを使う場合、nl_langinfo(CODESET)が返す文字列を解釈できるかは
保障されないので、この場合同梱のlibcharsetのlocale_charset()を使えとなっているのよね
(例えばNetBSDはC/POSIXロケールでは"646"を返すけど、GNU libiconvはこれを解釈できない)。

んで、locale_charset()はsetlocale(LC_CTYPE, NULL)の戻り値を元に
現在のlocaleのCESを調べ、GNU libiconvが解釈できるよにcanonicalizeする。
#つかそーゆーことはlibiconvの中で閉じてやって欲しいよ orz

ちなみに-DX_LOCALEつきでXlibをcompileした場合のケアは無いもより。
やるなら<locale.h>の代わりに<X11/Xlocale.h>をinclude、
んで定義ファイルを書いてlibcharsetを再コンパイルだ罠。
まあ今更-DX_LOCALEなんぞ使うべからず、が正解。
#まだOpenBSDあたりで使ってる人はいるかもしれんけど。

*1:必殺テストしてませんが何か?

GNU libiconv

locale_charset() + libcharsetネタに補足。
GNU libiconvは

iconv_open("", "UTF-8");

のように、""を引数に渡すと、現在のlocaleのCESが指定されたものと解釈し
内部的にlocale_charset()を呼ぶようになってます(って今知ったwww)が
当然移植性は**まったく無い**ので注意ね、ったくもう。

2008/03/22(Sat)

今日

映画 コントロール観てきたぜ。

2008/03/24(Mon)

[NetBSD] tech-userlevel

64bit time_tに合せてNetBSDでもlibcのmajorをcrunkとゆー話でてるな。

matt氏提案の、libc.so.12をlibc.so.13を呼ぶwapperにするちゅーのは意味あんのかね。
この先majorがcrunkするたびに数珠繋ぎになるんだけども

$ldd /lib/libc.so.12
/lib/libc.so.12:
	-lc.13 => /usr/lib/libc.so.13
$ldd /lib/libc.so.13
/lib/libc.so.13:
	-lc.14 => /usr/lib/libc.so.14
$ldd /lib/libc.so.14
/lib/libc.so.14:
	-lc.15 => /usr/lib/libc.so.15
…
$ldd /lib/libc.so.99
/lib/libc.so.99:
	-lc.100 => /usr/lib/libc.so.100

これは嫌だwwww

例えばsetlocale(3) *1に関してだけでも

つーようにlibc13がlibc12をemulateする為には
これまでlibcのmajor crunkした場合に捨てられるはずだったコードの
かなりの部分を残さないとならんのよな。

これが単純なcrunkなら

で済むので、こっちの方が幸せでしょ。

私は「sonameのmajorによるバージョン管理なんて時代遅れっしょ」派なので
__RENAME()のまま継続して、ゆくゆくはELF symbol versioning実装しよーぜー
と思ってるのだけども(思ってるだけー)。

まあcrunkするならするでいいんじゃないかな、個人的には
OpenBSDのpors再コンパイル(通称:賽の河原)祭りで感覚麻痺してるし。

何故再コンパイルが必要なのかの理由は ここ読んで頂戴。

例えばgtk2だったら

をファイルシステム上共存できればいいんだけどね。

例えば /usr/pkg に直接インスコするのはもう止めにして
/usr/pkg/opt/gtk2-2.12.9nb1と /usr/pkg/opt/gtk2-2.12.9nb2 のように別ディレクトリにインスコするとか。
(REVISION使うとと-current以外や他のOSも巻き添え食うので、gtk2-2.12.9nb1-${ABI_VERSION}とか?)
どーせ-rpath付でビルドしてるのでLD_LIBRARY_PATH地獄にはならんし
PATH地獄についてはpkg_alternativeあたりで/usr/pkg/binにsymlinkで何とかなるっしょ。

そいやXFree86のlibXawはmajor6と7を同じソースツリーから作れてたけど
libcもあんなかんじにしたいのかな? 確かにそうでないと-currentの途中でcrunkになるので
pkgsrc/emulator/compat40をreleng4の配布物から作るじゃぁダメなんだけども。
普通にCVSで枝切るでいいよなぁ。

そいやctypeのbitが足りない件もドサクサに紛れて直すチャンスかも試練>>libc crunk

*1:前も書いたけど今のsetlocale(3)の__RENAME()周りはあれは実はABI保ててないよな。

週末

わりと数の少ないHi-Matic Eの黒モデルをオクで入手したのだが
前玉の状態がクラックありにバル剥がれにで俺涙目、落下品だわこりゃ。
さすがジャンクを生業とする人は写真の撮り方うまいわ、負けた、負け。

しょうがないので別の腐りかけジャンクげとして
どうにもならん前玉と、大きく歪んだフィルターリング交換して復活。

この機種もすでに生産中止のHM-N(NR52)電池なので
マグライトから引っこ抜いたLR44x2 & アルミホイルでショートさせてテスト。
100円ショップのノーブラLR44だとシャッター切れどもランプ点灯せずどうにも不安定。
メーカー製(SONY)だと問題ないみたい、cdsの調整はまた今度。

しかしプログラムEEでしか使えんのでやっぱHi-Matic7sII欲しい罠。
でもebay眺めてても(海外モデルだからね)結構いいお値段なので手が出ない。

ついでに小学生時分使ってたCanonet QL-17も分解清掃。
レンズのカビにはEEクリーナーなんかより食器用中性洗剤、これ豆知識な。
今になって気づくクイックローディングの作りの良さ。
同じ40mm/F1.7なので撮り比べでもしてみっか。

んでまだX61セットアップしてねーよwwww買った意味ナサスwwwww
NetBSDをPXEでnetbootしてHDDをバクアプしときたいのだが
bootp鯖建てるのがおっくうなのよね。

ぐぇ、ThinkPad s30、9セルのバッテリ買ったので6セルの方を外して
保管しといたのが過放電でダメになっとる orz
これだから 蓄電池は嫌いなんだよな、rechargeable battery hell, i won't be there.

2008/03/25(Tue)

[NetBSD] \(←なぜか円記号に見える)

Citrus iconvのことかー >> 地雷実装

$ printf \\x5c | iconv -f shift_jis -t euc-jp
iconv: warning: invalid characters: 1
〓$
$ printf \\x5c | iconv -f euc-jp -t shift_jis
iconv: iconv(): Illegal byte sequence

Shift_JIS(JISX0208の附属書1)はJISX0201-Romanなのよね。

一方eucJP( UI-OSF 日本語環境実装規約の付属書C)はANS X3.4(ASCII)。

これらを忠実に実装してるCitrusのバヤイ
0x5cが代替文字に置換されるのは「仕様です」なのよね *1

かたやLegacy Encoding Projectのpatch適用したGNU libiconvやperl iconvの場合

$ printf \\x5c | /usr/pkg/bin/iconv -f shift_jis -t euc-jp | od -x
0000000     005c
0000001
$ printf \\x5c | /usr/pkg/bin/iconv -f shift_jis -t utf-8 | od -x
0000000     005c
0000001

ちゅー変換するのよね、すなわちJISX0208は大間違いで
JISX0201-RomanでなくASCIIだ、ということだと思われ。
nkfやqkcなんかのlegacy converterと同じ動作をするようになってる訳やね。
#まあJISX0208で規格化されたのは後からだしなぁ。

ちなみにTOG/JVCでは代替文字に置換されると困る人は(eucJP-MSと同様に)
明示的にeucJP-0201を指定しろ(そいやCitrusに実装なかったな)ということだった記憶がある。

そいとMS932だと問題が起きないのは、Unicode.orgの 変換表では
0x5CはREVERSE SOLIDUS、つまりISO646-USだから。
最新の変換表だと REVERSE SOLIDUS (YEN SIGN) 。
TOG/JVCによると

Windows 3.1/NT/95 では, この問題に対して 
 ・ 0x5C は UCS の 0x005C (REVERSE SOLIDUS: 逆斜線) に変換する. 
 ・ にもかかわらず, 0x5C のグリフは「¥」とする. 
という解決を取っている.

解決というか開き直りwwwwだがそれが正しい。

あとこの問題については、ISO-2022-JPのバヤイ
ASCIIもJISX0201-Romanもどっちもイケるくちなので

$ printf \\x5c | iconv -f shift_jis -t iso-2022-jp
ESC(J\ESC(B

となるので変換可能だし無問題

...いやサニタ(略) で (略) な気もするけど、そんなヘボい(略) と思いたい。

*1:euc-jp -> shift_jisでEILSEQになるのはバグや…直さんと。

[NetBSD] pkg_view(1)

obacheさんより、そっかpkg_view(1)って同一パッケージの別バージョンを共存する仕組みでしたっけ。
あとは同一パッケージの同一バージョンを別ABIで共存できるようにすればいいわけだ。

2008/03/27(Thu)

[NetBSD] tech-userlevel

なんかmajor crunkしたライブラリをmark as obsoleteしてしまったみたいだね。

共有ライブラリの前方互換性が壊れる時

以前のエントリで、共有ライブラリの「後方」互換について説明しましたが、今度は「前方」互換について。

共有ライブラリの前方互換とは

ことを保障するということです。

よく似た言葉である後方互換についておさらいすると

ことを保障するものでした、前方互換とは視点が逆になってます。
この両者を混同しないようによーく注意してください。

どのような変更を行うとこの前方互換が損なわれるのでしょうか?
それは共有ライブラリに新しい関数や変数(=グローバルシンボル)が追加された場合などです *1

foo.h

extern void foo(void);

foo.c

#include <stdio.h>
#include "foo.h"

void
foo()
{
	printf("foo\n");
}

これをlibfoo.so.0.0としてコンパイルします。

$ gcc -shared -Wl,-soname,libfoo.so.0 -o libfoo.so.0.0 foo.c
$ ln -sf libfoo.so.0.0 libfoo.so.0
$ ln -sf libfoo.so.0 libfoo.so

次にlibfoo.so.0をリンクするアプリケーション、test_fooを作成します。
test_foo.c

#include "foo.h"
int
main(void)
{
	foo();
}

コンパイルして実行します。

$ gcc -Wl,-rpath,. -L. -lfoo -o test_foo test_foo.c
$ ./test_foo
foo

次にこのlibfooに新しい関数を追加します。
foo.h

--- foo.h.orig	2008-03-27 19:13:43.000000000 +0900
+++ foo.h	2008-03-27 19:14:00.000000000 +0900
@@ -1 +1,2 @@
 extern void foo(void);
+extern void bar(void);

foo.c

--- foo.c.orig	2008-03-27 19:13:50.000000000 +0900
+++ foo.c	2008-03-27 19:14:35.000000000 +0900
@@ -6,3 +6,9 @@
 {
 	printf("foo\n");
 }
+
+void
+bar()
+{
+	printtf("bar\n");
+}

これをマイナーバージョンを1つ上げ、libfoo.so.0.1としてコンパイルします。

$ gcc -shared -Wl,-soname,libfoo.so.0 -o libfoo.so.0.1 foo.c
$ ln -sf libfoo.so.0.1 libfoo.so.0
$ ln -sf libfoo.so.0 libfoo.so

先ほど作成したtest_fooを再コンパイルなしで実行してみましょう

$ ./test_foo
foo

後方互換は壊れていませんので、何のトラブルも無く実行可能です。

では、先ほどマイナーバージョンを変更した時に追加した
関数bar()を呼び出すようにアプリケーションを変更します。

--- foobar.c.orig       2008-03-27 19:26:47.000000000 +0900
+++ foobar.c    2008-03-27 19:26:59.000000000 +0900
@@ -3,4 +3,5 @@
 main(void)
 {
        foo();
+       bar();
 }

コンパイルして実行してみましょう。

$ gcc -Wl,-rpath,. -L. -lfoo -o test_foo test_foo.c
$ ./test_foo
foo
bar

こちらも当然ですが、何のトラブルも無く実行可能です。

ではシンボリックリンクであるlibfoo.so.0の実体を
新しいlibfoo.so.0.1から古いlibfoo.so.0.0に巻き戻すとどうなるでしょうか?

$ ls -l libfoo.so.0
lrwxr-xr-x  1 tnozaki  tnozaki  13 Mar 27 19:31 libfoo.so.0 -> libfoo.so.0.1
$ rm -f libfoo.so.0
$ ln -sf libfoo.so.0.0 libfoo.so.0
$ ls -l libfoo.so.0
lrwxr-xr-x  1 tnozaki  tnozaki  13 Mar 27 19:37 libfoo.so.0 -> libfoo.so.0.0

先ほど作成したtest_fooを再コンパイルなしで実行してみましょう

$ ./test_foo
foo
./test_foo: Undefined PLT symbol "bar" (symnum = 15)

barシンボルを解決できず、実行時エラーになってしまいました。
これが「前方互換性がない」状態という訳です。

他にも、構造体の最後に新規にメンバが追加された場合なんかも
後方互換はOKでも前方互換は失われます、例えば このエントリ
struct lconvの変更がこのケースに該当します *2

通常UNIX系OSではライブラリのバージョン管理は

として扱いますが、メジャーとマイナーの使い分けは

です、ライブラリ開発者の皆様におかれましては
その日の機嫌や語呂合わせなんかで適当に変えたり変えなかったり
しないように切にお願いする次第です。

後方互換性が壊れた場合には、新旧のメジャーを持つライブラリは残しておく必要があります *3

しかし前方互換性に関しては最新のマイナーを持つものがありさえすればノートラブルです
古いものは消しちゃっても構いません *4、しかし

ということだけは記憶の片隅に置いといてください。
#でないと前方互換性の問題でトラブる可能性が。

ってもFreeBSDなんかだとobjformatをELF化した時、SysV系の真似?して
マイナーを廃止してしまい新旧の区別が判らんようですが *6

ここまで書いてsource-changesに tsutsuiさんの解説発見、わーいダブった。

*1:外部公開が目的ではなく実装内部でのみ使う関数(libcなどでは_をprefixに持つ)
を追加した場合はminor crunkは不要です。

*2:こちらも外部公開せず内部でのみ使う構造体の場合は不要でしょう、私も
NetBSDのlibcの struct _RuneLocaleにメンバ追加した時にはminor crunkはしてません。

*3:ですのでNetBSDの場合、古いメジャーの共有ライブラリをsrc/distrib/sets/lists/base/mi他で obsoleteにマークしてはいけません。
*4:NetBSDでは古いマイナーはmark as obsoletedとしてpostinstall(8) fix obsolete時に消しちゃいます。
*5:pkgsrcのbinary distributionは@pkgdep、@blddepと2つの依存関係をチェックしてるので
問題なし、厳密にはlibc他のバージョンも見る必要があるけど
そこはuname -rのバージョンで代用してるはずです。

*6:NetBSDもPAM(8)すなわち/usr/lib/security/*はminor持ってないですが
あれはpluginだから必ずmajor crunkする必要があるから。
ま、同じpluginでもCitrusすなわち/usr/lib/i18n/*はminorまで持ってますが
あれはABI_VERSIONとかfallback functionで、major crunkしなくて済むように工夫してるからね。

2008/03/28(Fri)

今日

週末は花見いくよとMagic Bus運行のお知らせが、天気晴れるかな。

外人さんには「さくらさくら」のメロディーは
不気味に聴こえるという都市伝説はホントだろか?
参考CD: the colour of the sky / pale saints

さくら[植物] G-G-A
さくら[人名] G-E♭-D

社会的しおり経由で CDの音質について
デジタルの場合ピーク越え即音割れだからねぇ、昔スタジオでバイトしてた頃よく泣かされた。
アナログだとレンジは狭いけど「コンプ状態→歪み→割れ」だからちょっとぐらいの
ピーク越えは救えるのでとても楽なのだけども。

音量差の大きいアコースティック楽器なんかだと、fffの部分にゲイン合わせると
pppの個所ではメーターがほとんど振れない状態になり聴感上これはおいしくない。

こういう場合前時代的エンジニアリングの常道だとコンプをかますことで
レベルを平均化するのだけども、これは原音から変わってしまう副作用がある。
よって、忠実さを求める音楽には不向き *1

そんな時は折角のデジタルレコーディングなんだし
入力ゲインを変えたセッティングの複数トラックで同時録音し *2
後からおいしいレベルで録れてる部分を繋ぎ合わせて編集すると良かったり *3

まあ継ぎ目の部分で違和感ないようにするのは腕なんだけど。
割れたとこだけパッチあてるくらいならすぐできるようになると思う。
多重録音なら雑に接いでも他の楽器でマスクされるから問題なし。

最近はデジカメ写真でも明暗差の激しい場合には
露出を変えて撮影(オートブラケット)したものを合成するソフトとかありますな。
カメラ本体の機能にもなってるみたい(Sony αのDynamic Range Optimizerなど)。

最近のハードディスクレコーダーってそのへんお任せでやってくんないのかな?
写真におけるフォトショのスタンプツールみたいな機能とか。
#もう何年もサンレコとか読んでないからよう知らんけど。
#つか未だにAKAI DR4d使ってる人だからね…

まあこの手の方法は原音に忠実とはいえ、音量差はデフォルメされるので
嫌いな人は嫌いかもしれない、そういう人は量子化ビット数増えるのを待つか
(家で出せる音量考えるともう十分だと思うけど)
コンサート行って脳味噌という最強の記録メディア使うかですな。

ノイズについては16kHzに限らず、根本的な対策をしようとすると
機材買い替えどころかスタジオ建て直しの世界までいってしまう
偏執狂さんいらっしゃいな世界だからなぁ。
まあポストプロ作業である程度隠すことのできるものではあるけど
ノイズが聴こえてない耳が悪いエンジニアも当然いると思うのだけど
ノイズに対する考え方って、これはもうエンジニアの趣味の世界なのよね。
イコライザー等で削らずに楽曲によるマスキングで由とする人もいる訳でして *4
これについてはアーティストは拒否できる立場にある(無いのもいるけど)ので
彼らがOKしたのだから、それも作品の一つとして受け入れるしかないと思うんだな。
まあ問題にしてるCDの中身聴いてみると、これはひどいと同意せざるを得ないかもしれんけど。

ちなみに私はリマスター版 Raw Power / Iggy Pop & The Stoogesとか聴いて
音がいい *5と思う人なので、クリッピングにもノイズにも
耐性高いからあんま参考にはならんなw

まあこだわる人がいなかったとしたら、私達は未だにエジソンの蝋管聴いてる訳で
未来の為にはこだわる人は必要なんだろう。

*1:まあ80~90'sな音楽には必須ですがwww>>コンプ
*2:マイクものはちょいセッティング苦労するかもね。
*3:知り合いはステレオのL-Rでしか録ってなくても
Lだけ割れてたらRをうまいこと加工してLに貼るとかやってた。

*4:リマスタなんかでも、The BandやDoorsのリマスタはCDに相応しい新しい音を目指したけど
Little Featのそれはアナログ盤の音をCDでも再現することだったとか、何かで読んだ気がする。

*5:リマスタ作業中、Iggyが音圧を求めるあまりフェーダーを上げまくるので
高価な機材のメーターが全て赤に染まり、付き添いのエンジニアが悲鳴を上げた逸品

2008/03/29(Sat)

[NetBSD] tech-userlevel

64bit time_t化に伴うlibc major crunkネタ。

dholland氏のポストを超訳してみた。

まず第一に、僕らは共有ライブラリをビルドするする時
リンカに-lcフラグを与えて依存関係を記録していないんだよね。
だからこの共有ライブラリはどのlibcのバージョンとの組み合わせで
まともに動作するかなんて簡単には言えないのさ。
もっと悪いのは、正にこのことが原因で、libcのメジャー繰上げの後で
(新しいlibcで再コンパイルしてない)古いライブラリと新しいlibcをリンクして
コンパイルしたプログラムは、一見まともなようで実は壊れてるんだ。

僕らは絶対にこれは直さなきゃ、例えtime_tに関連する修正以外
なにもしないとしても、この修正は5.0に(できれば4.1も)つっこまないとダメ。
なんだけれどそれをしたからといって、この古いライブラリの
は続けて事にあたらなきゃならない。
僕らがどんな対策を(ソースツリーや配布物に)したとしても
こういうの(=古いライブラリ)は/usr/local/libなんかにもあるかもしれなくて
ユーザやシステム管理者は例えそれらを再コンパイル*できる*(できないかも)
としたって、彼らが必要性に気づかなければ忘れてそののままかもしれないじゃないか。

だから(libcを使わないので)libcへの依存関係を記録してないことが
正しいライブラリ -- 例えば何かのアプリケーションのプラグインかも
しれないけど -- なんかもあるけど、libcのメジャー繰上げ後には
これらも実際にはlibc.so.12に依存してるけど同じように記録のない
安全ではない共有ライブラリたちと、まったく同一に扱うしかなくなってしまうんだ。

続きはめんどくさいのでパス、ツール作るとか現実的でないし。

共有ライブラリが-lcなしでビルドされてようがいまいが
major crunkは賽の河原だから、本来は芋蔓で全てのshlibのmajorをcrunkしないとダメ(通称:親亀子亀)。
# libcの昨日を一切使わないshlibなら別だけども。
#それに/lib, /usr/libはまだしも/usr/pkg/libなんかは事実上無理なんだけどさ…)
だから-lcの有無は*全く*関係ないことに注意しよう。
#問題のあるライブラリの捜索には役に立つけどね。
(2008/05/29 追記)
libcやlibpthreadのようにどの共有ライブラリよりも先に.iniセクションを実行する
必要がある特別なライブラリの為に、DF_1_INITFIRSTフラグを使うような場合は
依存関係を記録しておく必要があるみたいです。
このへん参照。

そんで共有ライブラリに-lcをつけない理由はむしろウイークシンボルを使った
名前空間保護を有効にするため、libcは常に最後にリンクしないとならないから。
ここ参照。

だからdholland氏やjoerg氏が「これはバグ」といってる通りにして
共有ライブラリも-lcつきでビルドした場合、ld(1)がそれを意識して
libcのリンク順を常に最後に持ってきてくれないとおっかないことになる。
でもGNU ld(1)ってその辺だいじょうぶなんだろか?
手元で試したらダメっぽいのだが。
(2008/05/29 追記)
-lcが最初に表示されてしまうのはどうやらNetBSDのldd(1)のバグです、 ここ参照。

$ ldd libfoo.so
libfoo.so:
        -lc.12 => /usr/lib/libc.so.12
$ ldd libbar.so
libbar.so:
        -lc.12 => /usr/lib/libc.so.12
$ gcc -Wl,-rpath,./ -L. -lfoo -lbar test_foobar test_foobar.c
$ ldd test_foobar
test_foobar:
        -lc.12 => /usr/lib/libc.so.12
        -lfoo.0 => ./libfoo.so.0
        -lbar.0 => ./libbar.so.0

まあ面倒くさいことしないで__RENAME()続行 or
ELF symbol versioningでいいと思うんだけど。
# ELF化されてないportsもgcc4化でさよならしたよね?

まあ最悪

とでもすればCOMPAT_AOUTと同じ、あるいはexecveいじって
linux emulationのようなchroot環境で動かせば、問題なく
共存できる気はするけど移行手順がとてつもなく面倒くさい罠。

そろそろ

Only one ABI change in libc, in more than 15 years!

のバナー貼らね? # 1回はaout -> ELFね。

2008/03/30(Sun)

今日

花見中止、しょぼーん。

[NetBSD] shared library with -lc

ふむ、Linuxだと-shared付けても暗黙でlibcがリンクされるのね。

$ cd /usr/pkgsrc/wip/suse100_devel; make install
$ /usr/pkg/emul/bin/bash
bash-3.00$ ld -v
GNU ld version 2.16.91.0.2 20050720 (SuSE Linux)
bash-3.00$ gcc -shared -Wl,-soname,libfoo.so.0 -o libfoo.so.0.0 foo.c
bash-3.00$ ldd libfoo.so.0.0
libfoo.so.0.0:
        libc.so.6 => /lib/libc.so.6 (0xbbad8000)
        /lib/ld-linux.so.2 (0x00000000)
bash-3.00$ ln -sf libfoo.so.0.0 libfoo.so.0
bash-3.00$ ln -sf libfoo.so.0 libfoo.so
bash-3.00$ gcc -shared -Wl,-soname,libbar.so.0 -o libbar.so.0.0 bar.c
bash-3.00$ ldd libbar.so.0.0
libbar.so.0.0:
        libc.so.6 => /lib/libc.so.6 (0xbbad8000)
        /lib/ld-linux.so.2 (0x00000000)
bash-3.00$ ln -sf libbar.so.0.0 libbar.so.0
bash-3.00$ ln -sf libbar.so.0 libbar.so
bash-3.00$ gcc -Wl,-rpath,. -L. -lfoo -lbar test_foobar test_foobar.c
bash-3.00$ ldd test_foobar
        libfoo.so.0 => ./libfoo.so.0 (0xbbbe6000)
        libbar.so.0 => ./libfoo.so.0 (0xbbbe3000)
        libc.so.6 => /lib/libc.so.6 (0xbbad8000)
        /lib/ld-linux.so.2 (0x00000000)

ちゃんとプログラムのlibcのリンク順も最後になるみたい。

まあ問題のあるアプリのチェックにしか使えんけど
ちゃんとGNU ld(1)でlibcのリンク順を面倒見てくれるならそうした方がいい罠。

GNU ld

ldscriptなんて書いたことないのでちと勉強しよかな。
info日本語訳(ちと古い)

2008/03/31(Mon)

[C言語] JTC1/SC22/WG14ヲチ

C1Xに向けて少しづつ 活発になってきたようで。

まあ テム・レイ回路DTL以外は痒いとこに手が届く感じになりそうだ >>C1X

しかしC++仕様なみのmulti locale(libstdc++って実装してるんだっけ?)の話は出ないのな。
Thread-Aware Locale ExtensionのドラフトってAustin Groupで
Widthrawnしたまんま音沙汰無いやね。
読もうと思ったら消えてたので中身見てないけど。

懐かしのTOGによる Distributed I18N Framework、今読むとお腹一杯胃もたれすんなこりゃ。

TR24731-1(Bounds-checking interfaces)は今回は動きなしか。
VC++の/GS(*_s)でもgcc -fstack-protector(libsspの*_chk)でも
どっちでもいいんだけどね、外野としては。
あっとCERT Managed Stringだけは勘弁な?