[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[FDclone-users:00804] Re: configure 時のエラーについて



 しらいです。

In Message-Id <20080626171009.ED0AF480662@yuka.unixusers.net>
        Takashi SHIRAI <shirai@unixusers.net>writes:
>  しらいです。

>  下記 patch は 3.00a に対するものなので、先の patch を一旦
> 破棄してから当て直して下さい。

 まずはこの 2 回目の patch から解説しておきます。引用部分が
出来るだけ短くなるように配慮しますが、余り削除し過ぎると判り
にくくなってしまうので、長文になることはご容赦下さい。
 技術的に興味の無い方は mail 全部読み飛ばして貰っても結構で
す。


◎pathname.c
> -	if (len >= 0) {
> -		if (!(flags & EA_EOLMETA) && ptr + 1 >= len) return(0);
> -# ifndef	BASHSTYLE
> -	/* bash does not treat "\" as \ */
> -		if (quote == '"' && s[ptr + 1] == quote && ptr + 2 >= len)
> -			return(0);
> -# endif
> +	if (flags & EA_EOLMETA) /*EMPTY*/;
> +	else if (len >= 0) {
> +		if (ptr + 1 >= len) return(0);
>  	}
>  	else {
> -		if (!(flags & EA_EOLMETA) && !s[ptr + 1]) return(0);
> -# ifndef	BASHSTYLE
> -	/* bash does not treat "\" as \ */
> -		if (quote == '"' && s[ptr + 1] == quote && !s[ptr + 2])
> -			return(0);
> -# endif
> +		if (!s[ptr + 1]) return(0);
>  	}

 元の code は comment にもあるとおり「"\"」を「\」と見なす
ために用意されていました。

 しかし実際には「"」で括られた中に「\"」という文字列が行末
として存在すると全て「\」に展開してしまっていたので、「"」で
括られた中の「"」を escape しようとして失敗していました。
 しかし、「"\"」と「"...\"」とを見分ける手段は現行の枠組で
は容易ではなく、どうしようかと悩んだのですが、そもそも「"\"」
を「\」と見なすルールの出自に疑問を持ちました。
 BSD4 の Bourne shell を compile して確認してみましたが、や
はりそんな仕様はありません。

 FDclone の古い source を紐解いてみたところ、どうやらこの仕
様は FDclone の独自仕様らしいことが見えて来ました。
 FDclone 1.xx の頃に bind コマンドで「\」に機能を割り当てる
際に「bind "\" "foo bar"」のように記述させていて、その「"\"」
のためだけに作られたルールだったと思います。
 当然 2.xx 以降では bsh 系 shell の書式に則れば「\」を記述
する方法など幾らでも存在しますから、この独自仕様自体を廃止す
ることで決着しています。


> -	else if (*s == '"') {
> +	else if (!(flags & EA_NOEVALDQ) && *s == '"') {
>  		*qp = *s;
>  		return(PC_OPQUOTE);
>  	}

>  			&& (*cp == '\'' || *cp == '"'))
> +				/*EMPTY*/;
> +			else if ((flags & EA_STRIPMETA) && *cp == PMETA)
>  				/*EMPTY*/;

 この辺りは here document の中の meta character の扱いがい
い加減だったので、Bourne shell や bash の挙動に合わせる形で
修正しています。


◎posixsh.c
>  			if (s) ret = (*s && Xstat(s, &st) >= 0
> -			&& (st.st_mode & S_IFMT) != S_IFDIR)
> +			&& (st.st_mode & S_IFMT) == S_IFREG)
>  				? RET_SUCCESS : RET_FAIL;
>  			break;

 これは builtin の test コマンドに関する解釈の相違によるも
ので、-f oprion の意味が今と昔では微妙に違うんですよ。
 BSD4 時代の /bin/test は -f で「directory ではない」ことを
検出していましたが、POSIX では「regular file である」ことを
検出することが要求されています。
 そもそも Bourne shell には builtin test など存在しないので、
どちらの仕様にあわせるべきかは微妙なところです。これに関して
は「BASHSTYLE」専用にするかも知れません。


◎system.c
>  	if (havetty()) {
>  		exectrapcomm();
> -		if (!noexit && (trapmode[0] & TR_STAT) == TR_TRAP) {
> +		if (mypid != orgpid) /*EMPTY*/;
> +		else if (!noexit && (trapmode[0] & TR_STAT) == TR_TRAP) {
>  			trapmode[0] = 0;
>  			if (trapcomm[0] && *(trapcomm[0]))
>  				_dosystem(trapcomm[0]);

 これは trap コマンドで終了時に割当てられた動作が複数回実行
されるという bug があったので、それを修正したものです。
 実際はこの修正では不十分だったので更に改良を加えていますが、
そちらの実装については後日 patch の展開を行なう予定です。こ
の「havetty()」の部分が条件として余計なんですね。


>  #endif
> +		exec_line(NULL);
> +		_dosystem(NULL);

 終了時の後片付けが足りなかったので追加しました。最後に一時
file を残したまま終了するケースが多かったので、$TMPDIR の下
のゴミに悩まされ続けてた方も多かったのではないでしょうか。


>  	if (argvar && argvar[0]) fprintf2(Xstderr, "%k: ", argvar[0]);
> +#ifndef	MINIMUMSHELL
> +	if (!interactive && shlineno > 0L)
> +		fprintf2(Xstderr, "%ld: ", shlineno);
> +#endif
>  	if (s) fprintf2(Xstderr, "%a: ",
>  		(*s && syntaxerrno != ER_UNEXPNL) ? s : "syntax error");

 これは単に syntax error に行番号を表示させただけです。


>  	if (!rp) return;
>  	closeredirect(rp -> next);
> +	if (rp -> type & MD_DUPL) return;

 これが [FDclone-users:00798] で報告のあった unknown 続出の
件に関する対処です。
 勿論、ここで跳ねる条件として別のところで MD_DUPL の設定も
している訳ですが、紹介する引用文としては代表してこの箇所だけ
にしておきます。


>  			for (i = 0; cp[i]; i++) {
> -				if (cp[i] == PMETA && !cp[i + 1]) break;
> +				if (cp[i] == PMETA) {
> +					if (!cp[i + 1]) break;
> +					i++;
> +				}
>  				else if (iskanji1(cp, i)) i++;

 here document の中の「\」の扱いが甘かったので修正してます。



>  #ifdef	CODEEUC
>  				else if (isekana(cp, i)) i++;
> @@ -3617,10 +3642,7 @@
>  
>  	if (pipein > (p_id_t)0) {
>  #ifndef	USEFAKEPIPE
> -		if (waitchild(pipein, NULL) != RET_SUCCESS) {
> -			closepipe2(fd, -1);
> -			return(seterrno(-1));
> -		}
> +		hdp -> pipein = pipein;
>  #endif
>  		safeclose(fdin);
>  		return(fd);

 これは非常に悩ましい bug でした。here document を展開する
ために、pipe() & fork() を使って child process からの書込み
を標準入力として渡していたんですが、思わぬ失敗が。
 OS 仕様にも依存するんですが、pipe に書込める文字数って上限
があって、出口から読み出されない限りはその上限数を越えて書込
もうとすると block されてしまうんですね。
 旧実装では child process が here document を出力し切って終
了するのを看取ってから、それを標準入力で受取る process を実
行していましたが、これだと block されると先に進みません。

 なので、看取るのは受取り側 process が終了した後にして、ま
た here document を吐く process の exit status は関知しない
ことにしました。
 なので子が異常終了するとややこしいことになるんですが、その
辺りは EPIPE の実装に任せることにして、余り深くは追求しない
ことにしています。


>  	size = c_allocsize(len + *tptrp + n + 2);
>  	if (size > *sp) cp = realloc2(cp, *sp = size);
>  	memmove(&(cp[len]), cp, *tptrp);
> -	strncpy2(cp, rp -> filename, len);
> +	memcpy(cp, rp -> filename, len);
>  	*tptrp += len;
>  	strncpy2(&(cp[*tptrp]), &(s[*ptrp]), n);
>  	*tptrp += n;

 これは 3.00 で embug した非常に大きな bug で、$() や $(())
が全く機能していなかったと思います。確認が甘くて大変申し訳あ
りませんでした。


>  				else if (s[*ptrp] == ')' || s[*ptrp] == '|')
>  					(*ptrp)--;
> +				else if (s[*ptrp] == PMETA
> +				&& (!s[*ptrp + 1] || s[*ptrp] == '\n'))
> +					(*ptrp)--;
>  				else syntaxerrno = ER_UNEXPTOK;

 これは case 文の中で「\」で escape した改行を error で弾い
ていた問題を修正したものです。「|」の前で改行するのは大丈夫
だったんですけど後ろ側だと error になってました。


> -	if ((opt = tinygetopt(trp, "nN", &n)) < 0) return(RET_FAIL);
> +	if ((opt = tinygetopt(trp, "-nN", &n)) < 0) return(RET_FAIL);

 これは buildin echo の挙動に関する修正です。「-」で始まる
引数は全て option 扱いにしていたんですが、「-n」以外は普通に
表示させるのが正しい仕様なんですね。


 さて、続いてこの後で見つかった支障の修正点です。これは後日
作成する patch で展開予定ですが、解説だけ先に行なっておきま
す。

◎bash の IFS の扱い

 変数や backquote の展開後文字列が変数 IFS に含まれる文字を
含む場合、bash はその文字を「 」に置換える仕様になっているよ
うです。
 なので BASHSTYLE 時はそういう仕様になるようにしました。

 あと、この際に「\n」は IFS 扱いになっていなかったので、IFS
扱いにしています。昔の bash は確かそういう仕様だったと思った
んですけどねー。


◎backquote 内の「\$」の扱い

 backquote に括られた文字列に「\$」が含まれていた場合、これ
は変数展開を表すメタ文字「$」の展開を抑制する意味なので、評
価する前に「\$」を「$」に置換える必要があります。
 これは bash 独自仕様ではなくて Bourne shell の仕様でもある
ので、「\$」のままにしてあった従来の仕様を改めて「$」に置換
えました。
 同様に「\\」は「\」に置換えてます。


◎bash builtin test の「==」

 bash の builtin test コマンドは「=」の意味で「==」も使える
ようですね。って言うか、「=」は POSIX 互換のために用意してあ
る読換えで man page 的には「==」が正解のようです。
 これも BASHSTYLE 時はそういう仕様になるようにしました。
 
 しかし、そんな方言を configure の中で使って欲しくないです
ねー。>davecot


◎BASHSTYLE 時の `` 展開ミス

 BASHSTYLE 時に `` の中に ${} を置くと syntax error になる
という bug があったので修正しました。


◎変数定義の解析ミス

 -k option が有効でない限りは、command line の先頭以外では
変数定義を行なえないのが仕様なんですが、実装ミスでたまに引数
文字列を変数定義と見なしてしまうことがありました。


◎bash builtin set の変数値出力

 bash の builtin set コマンドはメタ文字を含む変数値を「'」
で括って表示するようなので、BASHSTYLE 時にはそういう仕様にな
るようにしました。
 因みにこの時の quote のルールは bash の version によって微
妙に異なる筈なんですが、configure は割と最近の出力にしか対応
出来ていないようですね。


◎exit status 値の代入ミス

 exit status を引数に用いる際は正しく扱えるんですが、変数値
として代入しようとすると常に値が 0 になってしまうという bug
を修正しました。
 なんかわざとそうしていた気配があるんですが、理由が判らない
ので修正しています。


◎行番号表示の精度向上

 $LINENO を展開した後の行番号が実際の行番号と微妙にずれるこ
とがあります。これは、shell が構文解析のために先読みをしてい
るせいで、複雑な構文では随分先の行番号になっていました。
 configure のように巨大な script になると余りに大きく異なる
場合があるので、出来るだけ実際の行番号に合うように配慮しまし
た。
 お蔭で正確な行番号になったのはいいんですけど、逆に bash の
方が一行ずれた行番号を生成していて、どうして間違うのか判らな
いので bash の挙動には合わせられていません。

                                               しらい たかし