或曰

……と、ある人は言った。

-- 2000年8月下旬 --

Sat, 21 Dec 2002 20:13:07 JST / hina.di
powered by tds-1.3.0
<issei@issei.org>



検索式: [検索方法]

表示件数: 表示形式: ソート:

[最新版] << == >> [一覧]

2000/8/20(Sun)

或曰

タイトルの「或曰」ですが、漢文です。書き下すと「或(ある)いは曰(いわ) く」、現代語で「……と、ある人は言った」程度の意味です。

へッドホン

閉店まぎわの秋葉原の街で、Sony のインナーイヤー型ノイズキャンセリング・ へッドホン MDR-NC10を買おうとしたところ、寄った店には在庫なし。ぐぅ。

散財

CVS本ですが、リファレンス的に使うにはイマイチですね。本文で長々と説明し ているので、パッと開いて必要な個所だけ拾い読みできません。

[Programming] C言語と例外

ひさしぶりに「素のC言語」を使ってプログラムを書いていて、エラー処理の面 倒さに疲れる。

こうなると、関数の戻り値をいちいちチェックしては上位の関数に渡すという C言語方式では面倒になってきて、Java や C++ で提供されている try - catch 式の例外処理スキームが欲しくなります。

以前、誰か *1の Web 日記で「Cプリプロセッサで try, catch 風のマクロを定義して使ってる」 というのを見かけた記憶があるのですが、ちょっと探してみたところ発見できな かったので、自分で書いてみます。

ヒープ上に確保したメモリを無視すれば、要は

  1. try する段階でスタック環境と実行状態を待避しておく。
  2. 例外が throw されたら、catch のあるところまでスタックを遡る。

だけで良いはず。C言語には、標準ライブラリでスタック環境と実行状態の待避・ 復元を行う setjmp (3), longjump (3) 関数が提供されていますから、そう苦労 せずに書けそうです。

……ということで、あっさり書けました *2

C言語の文法に合わせるために、同名のローカル変数とグローバル変数を定義し て、現在実行中のコードが例外ハンドラ中にあるかどうかをチェックするなど、 いくつか小細工を弄していますが、本質的に難しいことは何もなく。

_ もっとも

C++ で実現されているの例外処理と比べると、機能は圧倒的に低いですけど。


*1:AoiMoeさんだったかな?
*2:デバッグでちょっとハマりました。そこかしこに埋まっている assert() に、苦 戦した痕が窺えます(苦笑)


2000/8/21(Mon)

日記環境再構築

_ 日記システム

タイトル横にも書いてありますが、今回は日記システムとして TDS を使わせて頂いてます。今使ってるサーバ www.issei.org は、CGI, SSI の利用 に多少制限があるので、静的モードで HTML ファイルを作っておいて Web サーバ に転送してます。

_ アクセス解析

Web 日記を書いたら、他からのリンク(Referer)をチェックするのが一つの楽 しみですが、この処理は CGI + JavaScript で行っています。CGI を IMG タグ に埋め込み、引数に JavaScript の document.referer を渡すというのは、SSI が使えない環境で独立したアクセス解析処理プログラムを作成するための常套手 段 *1ですね。

手元には、自作の Referer 解析 CGI プログラムもあるのですが、敢えてネット 上から拾ってきてみたり。あぁ、やっぱり排他制御の処理間違ってるよ、とか。

_ ファイル転送

TDS の静的モードで作成した HTML ファイルを転送するには、今月の UNIX Magazine で取り上げられていた sitecopyを使っています。以前はローカルのディスクと Web サーバ上のファイルの同期 は rsync + ssh で行っていたのですが、今回のように ssh が使えない環境で Web ページ の更新を行うには、FTP 対応の sitecopy はなかなか便利ですね。

ちょっと驚いたことがひとつ。sitecopy は、最初に FTP サーバ上のファイルに 関する情報を ~/.sitecopy/ ディレクトリに保存しておいて、以降はローカルに 更新されたファイルのみ再転送します。この ~/.sitecopy/ 置いてあるファイル の形式が XML になってます。ソースファイルを眺めてみたところ、XML パーサに は expatを使ってるみたいですね。


*1:アクセス解析処理用の CGI を HTML ファイルの IMG タグに記述した場合、その ままだと CGI には HTTP_REFERER として HTML ファイルの URL が渡されてしま います。JavaScript を使って、ブラウザに HTML ファイルを動的に作成させる ことで、望む referer の情報を CGI に渡すことができます。

[Opinion] 医師を選ぶ権利

「ホームドクターを探しておくべきではないでしょうか」という意見ですが、 私は、現状では患者が医師を選ぶためには、医師各人に関する情報が不足して いると思います。もう少し、医者個人の業績や、得手不得手、同業者内での評 価を気軽に調べられる環境が整わないと、選択の余地が広がらないのでは?

_ と思って

ちょっと調べてみたのですが、日本の「医師」はあくまで一般名詞の医師とし て振る舞うことを義務づけられており、個人を前面に押し出すことは徹底的に 禁止されているようですね *1。これだと、医師の側から情報を出すのも難しいのか。

_ 法令リポジトリ

法令の文面は分かっても、意図が分からず。法令は、改変履歴や審議過程とと もに CVSリポジトリにでも入れておいて欲しいものだ。


*1:たとえば、医師の広告行為に関しては医療法第69条で厳しく制限される。

[Book] 縛られたプロメテウス

アイスキュロスの手になる、古代ギリシアの代表的な悲劇の第一幕。劇は全三幕 構成だが、第二幕、第三幕のテキストは、その大半が失われてしまっているとの こと。

ゼウスが父クロノスを打ち倒して神々の王の座に就き、その権勢を極めていた頃 の話。古き神ティタン一族の生き残りにして人類の庇護者を自認するプロメテウ スは、ゼウスに背いて人類に「火」を与え、その怒りを買う。ゼウスは、鍛冶と 技術を司る息子ヘパイストスを、権力・暴力を具象化した神とともに遣わし、プ ロメテウスを捕らえて世界の果ての岩山に磔りつける。

第一幕は、その非業の神プロメテウスと、ゼウスの寵愛を得たがために、その妻 ヘラに憎まれ、牛に姿を変えられて故国を追われて世界を流浪する王女イオの二 人を軸に展開する。

現存するものは劇の台本である以上、そこに小説風の情景描写は一切なく、登場 人物の台詞が全て。にもかかわらず、一読して、広大無辺にして荘厳なる神々の 世界が目に浮かぶよう。私が読んだのは邦訳されたテキスト *1ですが、その文章にして、これだけの力を感じさせるのですから、まさにギリシ ア文学おそるべし。

その後、アイスキュロスの時代から下ること数百年。やがて古代ギリシアは政治 的に没落し、国内抗争に諸外国を率いれて周辺地域の不安定化に多大な貢献をし た後に、紀元前二世紀に時の覇権国家ローマに征服されるわけですが、ローマは 国を征服しても、文化的にはギリシアに征服されたと言われるほど、ギリシア文 化が浸透しました。

現在の学問にしても、累を辿れば古代ギリシアに行き着くものが少なくないわけ ですが、「縛られたプロメテウス」のようなものを見せ付けられると、なるほど と納得せざるをえません。

_ 死すべき定めのもの

「或曰」――或いは曰く。

なるほど、面白いものだな

「縛られたプロメテウス」では、永遠の寿命と強大な力を持つ神々と、死すべき 定めにあり、力も知恵も神には到底敵わぬ人間とが鋭く対比されている。

ギリシア神話における神の存在は、東洋思想の「道」(タオ)、現代風に自然法 則と言い換えても良いかもしれない。それは、いかに表象が移ろい変わろうとも、 変わらずに在り続ける永遠なるもの、そして人間を支配し、規定するものの象徴 だ *2

死すべき定めにある人間は、いかに永遠に想いを馳せようとも、やがてその短い 一生に幕を下ろさねばならない。だからといって人間が無力で、永遠なる者に抗 し得ない存在かというと、そんなことはない。アイスキュロスの悲劇は、二千有 余年の時を越えて、今なおその輝きを放ち続け、ギリシア哲学は現代科学に至る 知の営みの中に、確かに引き継がれているのだから。

韜々と受け継がれる人類の営み。その流れを継承し、そこにわずかでも己が足跡 を残すことが、或いは、死すべき定めにある人間にとっての「永遠」を意味する のかもしれないな。

と、その或る人は言った。


*1:「ギリシア悲劇 (1)」アイスキュロス(ちくま学芸文庫)
*2:もっともギリシア神話世界には、神々の王ゼウスでさえも抗えぬ「運命」の流れ があり、それを司る女神が存在するという形で、更にもう一段の階層構造が存在 している。


2000/8/22(Tue)

良い医師の探し方

良い医師というのは、どんなふうに探すのが良いんでしょう? 私は、あま り病院に行かない方なので、医師の診察を受ける機会も少ないのですが(最 後に病院に行ったのは何年前だ?)、健康診断なんかでたまに行ってみると 良いのかな。

_ ところで、君はどうやって医師を選んでる?

或曰――或いは曰く。

私は病気や怪我は、しないことにしている。

と、その或る人は言った。

……参考にならない。

[Book] 散財

おや、活字本は文芸春秋社のものばかりだ。

_ 立花隆といえば

医学・生物学において最近ホットな領域の一つ、再生医学をとりあつかった「人 体再生」という本 *1がありますが、物理学から生物・医学系に転向した知人T氏が「人体再生」で取 材を受けていた研究室にいることが判明。T氏帰省の折、研究テーマである体性 刺激への反応や微小循環に関して講義されてみたり。

専門的な話は、私の知識不足のためあまり踏み込めませんでしたが、マウスに噛 まれて大変だった話や、医学系と物理学系での研究対象に対する姿勢や気風の違 いなど、楽しませていただきました。また機会があったら、立ち寄ってください ね。>T氏


*1:「人体再生」 立花隆 (中央公論新社)

ゼロ金利と資産代替効果

日銀のゼロ金利政策解除に関するレポートを読んでいたところ、ゼロ金利政策は 当事者が期待していた「貸し出し促進効果」は発揮しなかったものの、「資産代 替効果」という予期せぬ経路を通じて、経済底上げの役割を果たしたとの分析。

資産代替効果――経済学の書物を紐解くと「高い流動性を持ちリスクの少ない預 金に滞留していた資金が、金利低下に伴い、債権や株券などのリスクを伴う資産 に移動すること」とのこと。

そんなものかなと思っていた矢先、相次いで、両親が株式や株価に連動した金融 商品に投資していた *1との話を耳にする。なるほど、父母もこの流れに乗っていたのか。


*1:投資といっても、ほんの小額ですけど。

Ssh2 非商用利用ライセンス

Patrik Andersin という方からメールで知らせていただいたのですが、8月24 日に公開される ssh 2.3 からライセンスが変更になるとのこと。詳しくは Press Releaseにありますが、 特にフリーの UNIX 関係者に影響が大きい項目を抜粋しておき ます。

以下、私訳。

リリースされ次第、FreeBSD の ports/security/ssh2 もアップデートします。


2000/8/23(Wed)

フルーツパスケット

昨日購入してきた 「フルーツバスケット」をまとめて読む。……ダメ(誉め言葉)な 話だ。

_ 次は

連載を読んでいなかった「カードキャプターさくら」を探してくるか。


2000/8/25(Fri)

ssh2

*BSD のユーザが、わざわざ OpenSSH を ssh2 に入れ替える意味は「ない」と思 います。敢えていえば sftp?

_ ただ

ssh2 関係では、よく個人宛てに英語でメールがやってきます。私がメンテナンス している port の中でも、もっとも頻繁に質問を受けるのが ssh2 で、実は結構ユー ザがいるのかもしれません *1


*1:私は OpenSSH 使ってますが(ぉぃ

[Comics] 読書記録

うーむ、こんな話だったのか。

コンパイラ

コンパイラにハマり中。Pascal のサブセットを作れば良いということで、言語仕 様を決め、実装を始めてから二週間。やっと中間コード生成と、中間コード用イン タプリタの動作まで到達。

これで、プログラムを中間コードにコンパイルしてインタプリタ上で動作させら れるようになったので *1、スタックダンプを眺めつつ、中間コード生成ルーチンのバグ取りに勤しむ(目 が痛いぞ)。

_ ソースコードを入手できるコンパイラ達

参考文献……かな?

prestruct-c
D. M. Ritchie の手になる初期のコンパイラ。さすがにコーディングスタイルが古くて、今ソースコードを読むのは辛い。 UNIX V5, V6 の標準コンパイラは、この流れを継いだもので、ソースコード が /usr/c に置いてあります *2。対応するアーキテクチャは PDP-11。
Portable C Compiler
UNIX V7 以降の UNIX 標準コンパイラで、PDP-11 に加えて VAX にも対応。それ以前のコンパイラと比較すると、機種依存部と非依存部の区分が明確で、 コードも読みやすい。ソースコードは UNIX V7 なら /usr/src/cmd/mip, /usr/src/cmd/pcc に、System III なら /usr/src/cmd/cc にあります。
A Tour Through the Portable C Compiler
lcc 4.1
ANSI C 準拠のコンパイラで、設計と実装に関する書籍*3も出ているようです。FreeBSD の port に含まれている lcc 3.6 は残念ながら現在 の FreeBSD ではまともに動きませんが、lcc 4.1 を入手して自分でコンパイルして やれば動きます *4。対応するアーキテクチャは Alpha, SPARC, MIPS, R3000, x86。
gcc 2.95.2
いわずと知れた GNU Compiler Collection ですが、あまりのコード量の多さに、私は読む前に力尽きました。

あと、Sybase 社が Watcom C/C++ コンパイラの ソースコードを公開する らしいので、これも出てきたら見てみたいですね。


*1:べつに中間コードを直接実行する必要はないんですが、経験上、ソフトウェアは 早めに動かしてデバッグしておいた方が身のためなので。
*2:古い UNIX 関連のソースコードは PDP Unix Preservation Society から入手しました。
*3:`A Retargetable C Compiler: Design and Implementation' (Addison-Wesley, 1995, ISBN 0-8053-1670-1)
この本、読んでみたいのですが、周囲で見かけません。取り寄せてしまおうかな。
*4:Driver のホスト依存部 (host.o) を作るのに必要なコードは こんな感じ。原因は調べてませんが、lcc でコンパイルしたバイナリから putchar() など、いくつかの関数を呼び出すと落ちます。アセンブラコードを見てみれば、 何か分かるか?

プログラムが動くまで

ソースコードから、実際にプログラムが実行されるまでの過程を概略すると、 次のようになっている。

  1. コンパイラがソースコードを解析し、マシン固有のアセンブラコードに変換する。
  2. アセンブラは、アセンブラコードからリロケータブル(再配置可能)なオブジェクトを作成する。オブジェクトは実行コードに近い形式だが、変数や関数を割り当て るアドレスは確定しておらず、未解決のシンボル名(変数とか関数の名前)も残して ある。このため、オブジェクトコードのままでは実行できない。
  3. ローダがオブジェクトコードとライブラリを結合し、未定義シンボル名を解決してアドレスに置き換える。これにスタートアップルーチンや、必要なヘッダを付け加え ることで、最終的な実行ファイルが生成される。
  4. オペレーティングシステムがユーザからのプログラム実行要求 (execve(2)) を受け取ると、ファイルヘッダの情報に従って、ファイルからコードと静的データを メモリに読み込み、ページ属性の設定やスタックなどの準備を整えた上で、コード の開始番地に制御を移す *1
  5. C 言語で書かれたプログラムでは、スタートアップルーチンが引数 argc, argv を設定した上で main 関数に制御が移される。あとは自分の書いたコードが実行さ れ、プログラムが exit(), abort() したり main() から return するまで実行が続 く。 この間、システムコールの処理、プロセスコンテクストスイッチやメモリ割り当て、 非同期ハンドラの起動など、OS が陰に陽にプログラムの実行を支援する。

1, 4, 5 に関しては、具体的な処理内容を把握できる目処が立ったので、あとは 2, 3 を押さえたいところですが、GNU binutils のソースコードを眺めて5秒で メゲました。GNU binutils のコードは、ひどく読みにくい気がするんですけど、 私だけ?


*1:最近は、実行に先立ってダイナミックリンク処理が行われることも多い。また、コー ド領域はプロセスごとに仮想記憶領域に割り当てられるのではなくプロセス間で共有 されるのが一般的だが、これは OS の側でやってくれるので、個々のプログラムが特 別な処理を行う必要はない。


2000/8/26(Sat)

[Book] 散財

友人に借りて以来、ずっと買おうと思っていた「恋愛的瞬間」をまとめ買い。

[Book] 読書記録

現代日本の不安を的確に掬い上げていると思うし、話としても面白い。にも関わ らず「だから、どうしたの?」という気がしてしまうのは、提示されている世界 観に私が馴染めないせいかな。

[Computer] lcc 4.1 で putchar() が動かないわけ

lcc 4.1/FreeBSD 4.1-RELEASE で putchar() を呼び出すコードを実行すると core dump してしまう問題の続き。

int
main(void)
{
	printf("Hello, World");
	putchar('\n');
	return 0;
}

たとえば、上のコードを lcc 4.1 でコンパイルして実行すると、putchar を呼 び出した時点で異常終了する。

man page を読んでみると、概略

putchar(), putc() は、出力ストリームに文字を書き出す。同じ結果をもたらす 関数に fputc() があるが、fputc() が関数として実装されているのに対して、 putchar(), putc() はインライン展開されているマクロとして実装されている点 が異なる。

と書いてある。<stdio.h> を読んでみたところ、gcc を使っているかどうかでマ クロの実装が異なる *1ことが分かったので、試しに putchar() を使うのをやめて fputc() で書き換え てみると……やっぱり core dump。むむ?

アセンブラコードを書き出して調べてみる。

% lcc -S putchar.c -o putchar-lcc.s
% gcc -S putchar.c -o putchar-gcc.s

putchar-lcc.s

main:
	pushl	%ebp
	pushl	%ebx
	pushl	%esi
	pushl	%edi
	movl	%esp,%ebp
	pushl	$.LC2
	call	printf
	addl	$4,%esp
	pushl	$__sF+84	; ←
	pushl	$10
	call	fputc
	addl	$8,%esp
	movl	$0,%eax
.LC1:
	movl	%ebp,%esp
	popl	%edi
	popl	%esi
	popl	%ebx
	popl	%ebp
	ret
.Lf4:

putchar-gcc.s

main:
	pushl	%ebp
	movl	%esp,%ebp
	subl	$8,%esp
	addl	$-12,%esp
	pushl	$.LC0
	call	printf
	addl	$16,%esp
	addl	$-8,%esp
	pushl	$__sF+88	; ←
	pushl	$10
	call	fputc
	addl	$16,%esp
	xorl	%eax,%eax
	jmp	.L6
	.p2align 2,0x90
.L6:
	leave
	ret

気になるのは矢印で示した部分。fputc() を call する直前にスタックに積んで いるということは fputc() の引数。FreeBSD/i386 環境では、右側の引数から順 にスタックに積むので、この部分は stdout に相当するが、gcc と lcc とで値 が $__sF+88, $__sF+84 と異なっている。そもそも、$__sF って何者?

<stdio.h> から抜粋

extern FILE __sF[];
#define stdin	(&__sF[0])
#define stdout	(&__sF[1])
#define stderr	(&__sF[2])

ふむ、stdin, stdout, stderr は FILE 構造体の配列として宣言されているのか。 で、stdout は配列 __sF の 1 番目ということで、そのアドレスが 「配列 __sF の先頭アドレス + FILE 型のサイズ」として計算されている。 どうも gcc と lcc で、FILE 構造体のサイズ計算が食い違っているらしい。

#include <stdio.h>

int
main(void)
{
	printf("sizeof(long long) = %d\n", sizeof(long long));
	return 0;
}

このコードをコンパイルして実行してみると、結果は gcc 2.95.2 では 8, lcc 4.1 では 4 となっている。gcc と lcc で long long 型のサイズが違うん だね。ビンゴ!

FILE 構造体のどこで long long が使われているのか見てみると、最後の _offset という要素が fpos_t 型で、fpos_t は最終的に long long 型の別名と して定義されている。 このために __sF[1] のアドレス計算が狂ってしまい、fputc() に stdout に対 応する FILE 構造体のアドレスの代わりに予期せぬデータがわたって、結果とし て core dump となったわけだ。

_ 解決するには?

lcc でも long long 型を 64bit 型整数として扱わせれば良い。lcc では機種依 存のコード生成処理は src/*.md というファイルに記述されており、型と対応す るサイズなどの情報は src/c.h で定義された Interface, Metrics という構造 体を用いて記述されている。

typedef struct metrics {
	unsigned char size, align, outofline;
} Metrics;
typedef struct interface {
	Metrics charmetric;
	Metrics shortmetric;
	Metrics intmetric;
	Metrics longmetric;
	Metrics longlongmetric;
	Metrics floatmetric;
	Metrics doublemetric;
	Metrics longdoublemetric;
	Metrics ptrmetric;
	Metrics structmetric;
.. (以下略)

今回のバイナリを生成するのに用いた x86linux.md を見てみると、次のように なっていた。

Interface x86linuxIR = {
        1, 1, 0,  /* char */
        2, 2, 0,  /* short */
        4, 4, 0,  /* int */
        4, 4, 0,  /* long */
        4, 4, 0,  /* long long */
        4, 4, 1,  /* float */
        8, 4, 1,  /* double */
        8, 4, 1,  /* long double */
        4, 4, 0,  /* T * */
        0, 4, 0,  /* struct; so that ARGB keeps stack aligned */

確かに long long 型が 4 バイトと宣言されているので、ここを 8 に書き直し て再コンパイル。できた lcc を使って putchar('\n'); を実行させると、今度 は core dump せずに完了。良し良し。

_ long long の旅は続く

これで long long のサイズは gcc と一致したが、まだ long long 型の変数を 使うことはできない。たとえば、次のコードをコンパイルすると、コンパイラが assertion に引っかかって落ちる。

int
main(void)
{
	long long n = 0;
	return 0;
}

これは 64 bit 変数への代入を行うアセンブラルーチンが存在しないためで、こ れに対して正しいアセンブラコードを出力するには、x86linux.md に出力するア センブラコードを記述する必要がある。

1, 2, 4 バイトの代入処理がどうなっているか探してみると、x86linux.md の 520 行目付近に次のようなものを見つける。

stmt: ASGNI1(addr,rc)           "movb %1,%0\n"   1
stmt: ASGNI2(addr,rc)           "movw %1,%0\n"   1
stmt: ASGNI4(addr,rc)           "movl %1,%0\n"   1

ということは、ここに次のような記述を追加すれば良いわけだ。

ASGNI8(addr,rc) "対応するアセンブラコードの雛形" 1

もう少しコンパイラの中身を調べないと書くのが難しそうなので、とりあえず棚 上げして、lcc のコード読み読み。


*1:gcc の場合には gcc 拡張機能(__inline)を用いて、インライン関数を定義し ている。


2000/8/27(Sun)

ドラゴンクエスト VII 入手できてません

近所のショップでは、売りきれとのこと。予約しておくんだったかな。

[FreeBSD] port security/ssh2 update

send-pr 済。

_ OpenSSH と SSH

OpenSSH は現在では SSH Protocol 1, 2 ともにサポートしていますが、どうも、SSH Communications Corp. の ssh2 と相互に通信できないことがあるようです。 詳しく調べてないので、原因は不明。

OpenSSH の ssh クライアントから SSH の sshd2 に接続したときのログ

% issei ssh -2 -v localhost
debug: len 55 datafellows 0
debug: dsa_verify: signature correct
debug: Wait SSH2_MSG_NEWKEYS.
debug: GOT SSH2_MSG_NEWKEYS.
debug: send SSH2_MSG_NEWKEYS.
debug: done: send SSH2_MSG_NEWKEYS.
debug: done: KEX2.
debug: send SSH2_MSG_SERVICE_REQUEST
Disconnecting: Corrupted HMAC on input.
debug: Calling cleanup 0x80573f0(0x0)

ドラゴンクエスト VII 入手

再入荷の時刻を見切って購入成功。


2000/8/28(Mon)

ドラクエ三昧

昼夜を問わず。

合間に

動的リンクの計算方法が間違ってるというコンパイラのバグを潰したり、x86 の 命令セットリファレンスを読んだり。


以上、8日分です。

[最新版] [一覧] << == >>

Copyright © 2000 - 2000
Issei Suzuki <issei@issei.org>