[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[FDclone-users:00804] Re: configure 時のエラーについて
- Subject: [FDclone-users:00804] Re: configure 時のエラーについて
- From: Takashi SHIRAI <shirai@unixusers.net>
- Date: Sun, 29 Jun 2008 21:29:29 +0900
しらいです。
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 の挙動には合わせられていません。
しらい たかし