Gauche:Bugs:log7
最新のもの: Gauche:Bugs
- possible typo in Scm_TypeError()
- main.c rev 1.90
- ViewVCのurl変更
- typo in condition variable slot description
- PORT_SAFE_CALL (cvs head)
- {lock,unlock}_class_redefinition (0.8.7)
- evalが末尾呼び出しにならない (0.8.8_pre1)
- applyが末尾呼び出しにならない (0.8.8_pre1)
- 循環リストとequalハッシュテーブル (0.8.8_pre1)
- マニュアルのタイポ
- typo in lib/Makefile.in (0.8.8_pre1)
- 0/0, (/ 1 0), (/ 0 0), etc. (0.8.8_pre1)
- IPv6のlocalhostの名前
- #include忘れ
- makeinfoとLANG
- Makefileの依存関係
- 数字のread
- tried_gc is boolean but compared as integer (port.c Revision 1.127)
- rfc.cookie construct-cookie-string (0.8.7)
- incomplete %-directive (0.8.7)
- リファレンスのtypo
- open-{input,output}-file の拡張
- コメントのタイポ (CVS Head) 2006/08/05 00:13:51 PDT
- cgi-get-parameter関数のキーワード引数defaultの使い方(0.8.7)
- text.csvの説明
- sxpath で ns-id:* をパスに含めるとエラー(0.8.7)
- dbi-parse-dsn (CVS HEAD)
- ScmConditionVariableRec と ScmMutexRec の最初のメンバが SCM_HEADER になっている。(0.8.7)
- RedHat EnterpriseLinux ES release 4でthreadのテストに失敗する (0.8.7)
- gauche-package が正しくないコンパイラ名を使用しようとする (0.8.7)
- http-post リクエストのメッセージボディの後に余分なCRLFが送信される(0.8.7)
- regexp-compile fails (0.8.7)
- let-args の説明文 (0.8.7)
- object-writeでwrite/ssを呼ぶとassertに引っかかる (0.8.7)
- ext/threads/threads.c (0.8.7)
- SO_RCVBUF Socket Option(0.8.7)
- digit->integer (0.8.7)
- with-module in syntax-rules (0.8.7)
- socket-recvfrom(0.8.6)
possible typo in Scm_TypeError()
2006/11/09 16:22:06 PST: got got は多分 but got ?
- Shiro:ども。直しました。
main.c rev 1.90
2006/11/03 14:08:31 PST: if (SCM_INTP(res)) が偽のとき、exit_code が未初期化のまま使われません?
- Shiro(2006/11/04 09:11:48 PST): 直しました。
ViewVCのurl変更
2006/11/02 16:12:12 PST: 大した事じゃないんですが、http://practical-scheme.net/gauche/index-j.html のCVSへのリンクが、古いままになってます。
(いつのまにか、sf.netのアップデートで、 http://gauche.cvs.sourceforge.net/gauche/ に移動していたみたいです。)
typo in condition variable slot description
2006/11/02 14:59:05 PST: doc/modgauche.texi の condition variable のスロットの説明の部分が
@defivar <mutex> name
のようになっています。
- Shiro(2006/11/04 09:11:48 PST): 直しました。
PORT_SAFE_CALL (cvs head)
2006/11/02 14:31:04 PST: port.h rev. 1.15 の変更に関して。 元の意味は PORT_LOCKED() but !SCM_PORT_PRIVATE なら unwind protect だと思うので、
if (p->lockOwner != Scm_VM()) {
は条件が逆で、常に真だからいらないのではないでしょうか?
- Shiro(2006/11/02 17:32:41 PST): あれ。ああそうか。必ずLOCKされた時に呼ばれてるんだから このチェックは妙ですね。PORT_PRIVATEかどうかをチェックするだけでいいのか。
また、portapi.c で PORT_SAFE_CALL() が一箇所直に呼び出されています。
{lock,unlock}_class_redefinition (0.8.7)
2006/11/02 14:47:25 PST: 二点、
- 初めて lock をとるときの class_redefinition_lock.count の初期値は 1 でないといけない? port の lockCount は最近の変更で初期値 1 になっています。
- unlock の際には class_redefinition_lock.owner を NULL にしないといけない?
- Shiro(2006/11/02 17:32:41 PST): そのとおり。もしくはunlockの時にpost incrementに するかですね。
- 2006/11/10 16:54:23 PST: やっぱり class_redefinition_lock.owner = NULL; も必要ですよね。例えば以下のような コードを実行すると、thread B が GC されるまで thread C が途中でとまっています。
(use gauche.threads) (define (load-some-class) (call-with-input-string "(define-class x () ())" load-from-port)) (define (thrmsg m) (format #t "thread ~a: ~a\n" (current-thread) m)) (let1 threads (map (lambda (name) (thread-start! (make-thread (lambda () (thrmsg "start") (load-some-class) (thrmsg "loaded") (sys-sleep 1) (thrmsg "exiting")) name))) '("A" "B" "C")) (sys-sleep 10) (display "call gc\n") (gc) (for-each thread-join! threads))
- Shiro(2006/11/11 00:13:04 PST): その通りです。修正しました。
evalが末尾呼び出しにならない (0.8.8_pre1)
Rui(2006/10/29 20:49:29 PST): applyと同様、末尾のevalが末尾呼び出しになりませんでした。
(define (loop) (eval '(loop) (current-module))) (loop)
- Shiro(2006/10/30 01:06:35 PST): えーとこっちは、VMの実装上は末尾呼出しになってる
と思います。但し、evalはモジュールを切り替えるので、eval中にエラーで抜けた場合
に対応するためにカレントモジュールを元にもどすダイナミックハンドラが挿入される
んですね。なのでこうやって再帰してゆくと、VMスタック自体は消費されないものの
ダイナミックハンドラのチェインがどんどん長くなっていってしまってる…のだと
思います。
モジュールが(current-module)であれば実質的にモジュール切り替えの必要が 無いはずなのでダイナミックハンドラの挿入をスキップするハックは入れられますが、 モジュールがカレントと別だったりするとそれは無理ですね。 R5RS的にはどうなんだろう。たとえばバッチコンパイルでネイティブに落とす 処理系で、evalの部分だけはインタプリトするようなやつだと、厳密な末尾再帰は 難しいような。 - Rui(2006/10/30 01:44:48 PST): なるほど、そうなってますね。しかしR5RSセクション3.5のeval must evaluate its argument as if it were in tail position within the eval procedure.という記述は、evalが第1引数を末尾呼び出ししていくらでも再帰できることを要求していると思ったのですが、実際には難しいということでしょうか。……うーむ、R5RSが要求するもののほうがおかしいかも。いま見てみるとR5.91RSからはevalについてのその記述がなくなってるし。
(2006/10/30 07:49:03 PST) 末尾のevalの再帰では、最終的に元に戻すモジュールは1つだけ覚えておけばいいので、原理的にはメモリを消費しなくてすむかも。 - Shiro(2006/10/30 16:49:01 PST): あーなるほど。でもそれだと素直にdynamic-windが使えない なあ。evalが戻すべきモジュールっていうのを別に持っといて、末尾再帰でevalが呼ばれた 場合はdynamic-windを使わずにその値だけ差し替える、というのは動くだろうけど醜い。 ここの節はR5RS authorsの意図がわからないです。
- Rui(2006/10/31 01:30:08 PST): そうですね。これは完了扱いでよいと思います。
applyが末尾呼び出しにならない (0.8.8_pre1)
Rui(2006/10/29 20:14:02 PST): 下記のコードがメモリを使い尽くそうとします。末尾のapplyが末尾呼び出しにならないようです。
(define (loop x) (apply loop (list x))) (loop 1)
- Shiro(2006/10/30 01:06:35 PST): Good catch. もともとtail positionのapplyは TAIL-APPLYという特別なインストラクションに展開するつもりだったんですが、 その後、同じインストラクションでも実行時にtail positionかどうかを判定して 継続フレームを入れるっていう処理を他のインストラクションで行って、 applyもそうしようと思って忘れていた…っぽいです。
- Shiro(2006/11/11 00:13:04 PST): 0.8.8リリース後にVMインストラクションを見直す予定なので その時についでに直すことにします。
循環リストとequalハッシュテーブル (0.8.8_pre1)
Rui(2006/10/26 02:20:42 PDT): 循環リストを"equal?"タイプのハッシュテーブルに足そうとすると、hash-table-put!が返ってきませんでした。ツリーをトラバースして要素のハッシュ値を求めているので、そこでループに入ってしまうようです。どちらかといえばこれはドキュメント化するだけの話かもしれませんが。
- Shiro: これは返って来ないのが仕様ですが、そもそも循環リストを与えて 発散する手続きはいくらでもあるので、いちいち書くのも煩わしいですねぇ。 (逆に、「発散しないもの」の方が特殊で、そっちを敢えて書く方が自然かもしれません)。
- Rui: まあそういうものですか。特に強い要望でもないのでそれで了解です。
マニュアルのタイポ
Rui(2006/10/18 02:31:07 PDT): doc/modutil.texiの10904行目の"varx"は"var"の間違いです。修正しないとmakeinfoできませんでした。
- Shiro: お、ども。はずみで入っちゃったみたいっすね。
2006/10/18 21:45:54 PDT:便乗。modsrfi.texi です。
-これは、Gauche の組み込み手続き @code{acon} の別名です。 +これは、Gauche の組み込み手続き @code{acons} の別名です。
- Shiro: 直しました。
2006/10/20 07:58:08 PDT: typo ではないかもしれないですが、ちょっと気になったこと:
- Vectors の章のタイトルだけ「ベクター」ですが、中身は「ベクタ」です。
- ジェネリックファンクション、ジェネリック関数、総称関数が混在してますが、意図して使い分けているわけではないですよね?
- Shiro: 「ベクタ」に統一。generic functionに関しては多分「総称関数」あたりで 統一すると思いますが、いずれチャンスがあった時に一括置換します。
Rui(2006/10/20 20:44:35 PDT): string-pointer-refがマニュアルにないようです。
- Shiro: string-pointerはフェードアウトさせる意図があります。 あんまり使わないで下さい。
- Rui(2006/10/22 05:30:38 PDT): なるほど。ただstring-pointerが提供している文字列へのシーケンシャルなアクセスはSRFI-13にはないので、たまにstring-pointerを使いたくなることがあります。予測型の再帰下降パーザを書こうとして、再帰する手続きに何を渡すか考えたのですが、(1)文字列とインデックス、(2)サブストリング、(3)u32ベクタとインデックスだと、(1)は遅いのでダメ、(2)は何となく遅そう、(3)はメモリを無駄使いしそうで、結局string-pointerを使おうと思ったのでした。文字列ポートだとバックトラックするとき1文字以上読み戻せないので使えないですし。
- しかし考えてみると、元の文字列とサブ文字列の実体は共有されるわけで、string-pointerを作るのとコストは同じくらいかもしれませんね。こういうとき他の方はどうしてるんでしょうか?
typo in lib/Makefile.in (0.8.8_pre1)
2006/10/20 14:41:34 PDT:
Index: lib/Makefile.in =================================================================== RCS file: /cvsroot/gauche/Gauche/lib/Makefile.in,v retrieving revision 1.140 diff -u -r1.140 Makefile.in --- lib/Makefile.in 16 Oct 2006 12:00:42 -0000 1.140 +++ lib/Makefile.in 20 Oct 2006 21:34:26 -0000 @@ -64,7 +64,7 @@ util/isomorph.scm util/toposort.scm util/queue.scm util/tree.scm util/digest.scm util/combinations.scm util/lcs.scm util/list.scm util/record.scm util/relation.scm util/stream.scm util/trie.scm - compat/jfilter.scm compat/stk.scm compat/norationa.scm + compat/jfilter.scm compat/stk.scm compat/norational.scm file/filter.scm rfc/822.scm rfc/mime.scm rfc/base64.scm rfc/uri.scm rfc/cookie.scm rfc/quoted-printable.scm rfc/http.scm rfc/hmac.scm
- Shiro: 直しました。
0/0, (/ 1 0), (/ 0 0), etc. (0.8.8_pre1)
leque(2006/10/20 12:50:38 PDT): 0/0 や 0 除算がおかしな値になります。
gosh> (/ -1 0) #<nan> gosh> (/ 2 0) #<nan> gosh> 0/0 #i1/0 gosh> -1/0 #i-1/0 gosh> 1/0 #i1/0
Index: number.c =================================================================== RCS file: /cvsroot/gauche/Gauche/src/number.c,v retrieving revision 1.130 diff -u -r1.130 number.c --- number.c 18 Oct 2006 10:59:52 -0000 1.130 +++ number.c 20 Oct 2006 19:45:44 -0000 @@ -1670,7 +1670,7 @@ } ANORMAL: { - int s = SCM_EXACT_ZERO_P(arg0); + int s = Scm_Sign(arg0); if (s == 0) return SCM_NAN; if (s < 0) return SCM_NEGATIVE_INFINITY; else return SCM_POSITIVE_INFINITY; @@ -3060,9 +3060,10 @@ if (SCM_EXACT_ZERO_P(denom)) { if (lensave > *lenp) { if (ctx->exactness == EXACT) { - return numread_error("(exact infinity is not supported.)", + return numread_error("(exact infinity/nan is not supported.)", ctx); } + if (SCM_EXACT_ZERO_P(intpart)) return SCM_NAN; return minusp? SCM_NEGATIVE_INFINITY:SCM_POSITIVE_INFINITY; } else { return SCM_FALSE;
- Shiro(2006/10/22 00:58:40 PDT): 直しました。
IPv6のlocalhostの名前
Rui(2006/10/19 01:42:02 PDT): 私の環境(Ubuntu 6.06)ではIPv6のループバックアドレスはip6-localhostという名前で、localhostという名前はIPv4にしか与えられていません。IPv6をサポートしているのにlocalhostが解決できないので、ext/net/test.scmの216行目のテストに失敗してしまいます。最初からそんな/etc/hostsになっていて、あまり変な環境でもないと思うのですが……。
- Shiro(2006/10/19 02:23:00 PDT): なるほど。このへんは綺麗なソリューションは無いと 思うので、泥縄的にありそうな名前を順に試してみるって感じでもいいかなと思います。
- Rui(2006/10/19 02:42:35 PDT): こんな感じのテストですかね。
(and-let* ((sock (any (lambda (name) (guard (e (else #f)) (make-client-socket (make (if (global-variable-bound? 'gauche.net '<sockaddr-in6>) <sockaddr-in6> <sockaddr-in>) :host name :port *inet-port*)))) '("localhost" "ip6-localhost" "ipv6-localhost")))) (test* "inet client socket" #t (call-with-client-socket sock (lambda (in out) (display (make-string *chunk-size* #\a) out) (newline out) (flush out) (string=? (read-line in) (make-string *chunk-size* #\A))))))
- び(2006/10/19 03:41:20 PDT): BSD系のOS(FreeBSD, NetBSD, OpenBSDそれにMac OS X)の/etc/hostsだと逆に::1にはlocalhostしか与えられていないですね。ipv6-localhostってどこ起源なのかなぁと思ってちょっとぐぐってみたんですが、よくわかりませんでした。
- ちなみにNetBSDはいつからかlocalhost.って感じで、 末尾に'.'がつくんですよね。cut-sea:2006/10/19 05:26:01 PDT
- び(2006/10/19 09:59:54 PDT): それはresolverがlocalhostを勝手にFQDNに補完して無駄なルックアップをしないための措置でしょうね。
#include忘れ
Rui(2006/10/19 00:03:07 PDT): ext/net/netlib.stubはScm_MakeBignumFromUIArrayを使っているのですが、gauche/bignum.hをインクルードしていません。
- Shiro(2006/10/22 00:58:40 PDT):直しました。
makeinfoとLANG
Rui(2006/10/18 23:17:54 PDT): LANGがja_JP.UTF-8な環境だと、makeinfoが「これは gauche-refj.info、gauche-refj.texi より makeinfoバージョン 4.8 によって作成されました。」というUTF-8な文字列をinfoの先頭に挿入するので、gauche-refj.infoのEUC-JPな文字列が壊れてしまいます。LANGをunsetしてmakeinfoするようにしてもらえないでしょうか。
- Shiro(2006/10/22 00:58:40 PDT): 試しにLANG=Cしてみました。 それにしても「成果物」にLANGが影響を与えるのって気持ち悪いすね。LANGみたいなもんは 成果物をユーザが使う、最後のインタフェースのところに作用すべきなんじゃ…
Makefileの依存関係
Rui(2006/10/18 22:30:01 PDT): ext/sxml/sxml-tools.cはsxml.sxpathに依存しているので、Makefileに依存関係を追加してください。クリーンな状態からのmakeに失敗しました。ext/sxml/Makefile.inの70行目にsxml-sxpath.$(SOEXT)を足せばよいと思います。
- Shiro(2006/10/22 00:58:40 PDT):直しました。
数字のread
Rui(2006/10/17 22:07:38 PDT): 指数部の大きな数字のreadに問題があるようです。
gosh> 1e1000 "number.c", line 2460 (iexpt10): Assertion failed: e < IEXPT10_TABLESIZ
tabe(2006/10/18 00:41:09 PDT): 別の境界の例です(0.8.7)。
gosh> 1e308 1.0e308 gosh> 1e309 *** ERROR: exact integer required, but got #t Stack Trace: _______________________________________
- Shiro(2006/10/18 04:05:40 PDT): inexact numberについては、指数部がむちゃに大きい
場合は無限大にするようにしました。あとexact rationalをサポートしたので
#e12.34とか#e1e-10みたいなのもサポートしました。#e1e1000000みたいなのは
理屈上はbignumでサポートできますが、メモリを馬鹿喰いするのでエラーに
します。
gosh> 1e309 #i1/0 gosh> -1e1000 #i-1/0 gosh> 1e-1000 0.0 gosh> #e12.34 617/50 gosh> #e1e-10 1/10000000000 gosh> #e1e100000 *** ERROR: bad number format (such an exact number is out of implementation limitation): #e1e100000
tried_gc is boolean but compared as integer (port.c Revision 1.127)
2006/10/10 21:01:31 PDT: tried_gc には TRUE/FALSE しか代入されていないので、tried_gc > 10 は変です。
- Shiro(2006/10/11 01:44:19 PDT): おお、ありがとうございます。テスト時のコードが 残ってました。
- 2006/10/11 03:01:52 PDT: ところで、その付近の code を眺めていて思ったのですが、Scm_FlushAllPorts() が呼ばれている間は register_buffered_port() が呼ばれないような仕組みになっているのでしょうか? mutex が unlock されている間に別な thread が新たな port を登録することで、 save されている port が restore されるべき slot が使われてしまわないか心配です。
- Shiro(2006/10/11 03:30:50 PDT): あーその心配は当たってます。 Scm_FlushAllPortsが基本的にクリーンアップ時にしか呼ばれてなかったために 顕在化していなかったと思われます。「処理中」を表す値として#tかなんかを 入れることにすれば大丈夫かな?
- 2006/10/11 16:50:34 PDT:最初はそうも思ったのですが、Scm_FlushAllPorts() によって save されているときに port が GC されると、 weak vector save[] のほうから除かれるのですよね? そうだとすると、#t を消す timing を逃してしまいます。restore するときに衝突したら slot 再計算かな。あるいは、save[] の要素の初期値を #t 等にしておけば区別がつくので restore できますね。
- Shiro(2006/10/18 12:46:42 PDT): save中にGCされてsaveベクタからエントリが除かれた ことは検出できます (fallback引数に#f以外を渡してやればよい)。でもよく考えたら、 saveベクタをweakにする必要は無い気がしてきました。ポートのGCのタイミングが 若干遅れる可能性はありますが、普通のベクタの方がオーバヘッドも少ないし、 いいかも。
- 2006/10/20 07:00:41 PDT: 確かに。どうして GC の code が知る由もない SCM_FALSE を埋めると思っちゃったんだろう。 ところで、ドキュメントには fallback 引数が使われるのは添字の range error の場合しか 言及されていないので、補足しておいた方がいいかもしれません。
rfc.cookie construct-cookie-string (0.8.7)
lib/rfc/cookie.scm 217行目付近ですが、
((eqv? :expires (car attr)) (if (> ver 0) (ignore) (next (make-expires-attr (cadr attr)))))
は
((eqv? :expires (car attr)) (if (> ver 0) (next (make-expires-attr (cadr attr))) (ignore)))
にしたら、正しく動きました。
ところで、make-expires-attrは、要素が整数の場合、自動的に日付に変換してくれますが、このあたりを<time>とかsrfi-19 dateとかもcookieの日付書法で変換してくれると嬉しいと思います。2006/09/30 19:10:50 PDT
- Shiro(2006/09/30 20:35:53 PDT): えーと、これは元のコードで意図通りです。
(> ver 0)の場合がset-cookie2、そうでない場合がset-cookieヘッダ用となっています。
で、RFC2965のSection 3.2.2によればset-cookie2はExpiresアトリビュートを
使わないことになっています (max-ageを使う)。何か私が読み違えているでしょうか?
<time>や<date>も扱えるようにするのは便利そうなので書いてみます。
- なにやら、すごい勘違いをしていたようで、すみません。お恥ずかしい、元の通りが正しいです。お手を煩わせてすみませんでした。max-age使います。(2006/10/01 00:57:33 PDT)
incomplete %-directive (0.8.7)
2006/09/18 23:54:42 PDT: src/write.c に二箇所ある
Scm_Error("incomplete %-directive in format string: %s", fmt);
は、Scm_Error() が結局 Scm_Vprintf() を呼ぶので %%-directive でないとまずそうです。
- Shiro(2006/09/30 19:27:43 PDT): 直しました。
リファレンスのtypo
2006/08/29 01:54:38 PDT: リファレンス中にtypoがありました。
Index: doc/modgauche.texi =================================================================== RCS file: /cvsroot/gauche/Gauche/doc/modgauche.texi,v retrieving revision 1.74 diff -u -r1.74 modgauche.texi --- doc/modgauche.texi 28 May 2006 02:31:14 -0000 1.74 +++ doc/modgauche.texi 29 Aug 2006 08:52:03 -0000 @@ -7947,7 +7947,7 @@ (@var{compare} @var{expected} @var{result-of-thunk}) @end example この手続きは、渡された結果が期待する値と合致する場合に@code{#t}を、 -そうでなければ@code{#t}を返さなければなりません。 +そうでなければ@code{#f}を返さなければなりません。 特別な比較手続きのひとつの用法は、不正確な数値を、多少の誤差を許して 比較するような場合です。 @c COMMON Index: doc/object.texi =================================================================== RCS file: /cvsroot/gauche/Gauche/doc/object.texi,v retrieving revision 1.40 diff -u -r1.40 object.texi --- doc/object.texi 11 Mar 2006 13:07:35 -0000 1.40 +++ doc/object.texi 29 Aug 2006 08:52:03 -0000 @@ -3140,7 +3140,7 @@ ディスパッチし呼び出すか、これらはすべてオブジェクトシステムによって、 定義されます。たとえば、クラスはジェネリックな構造と標準的クラスの 振舞いを定義する @code{<class>} クラスのインスタンスです。@code{<class>} -のサブクラス化すると、デフォルトのものとは違う振舞いをする、独自の +をサブクラス化すると、デフォルトのものとは違う振舞いをする、独自の クラス集合をつくることができます。これは結局、独自のオブジェクトシステムを つくることになります。
- Shiro(2006/09/30 19:27:43 PDT): 直しました。
open-{input,output}-file の拡張
び(2006/08/14 02:03:20 PDT): 現在の実装だと、指定したエンコーディングと内部エンコーディングの間で変換が不要であっても変換ポートを作ってしまいます。
Index: ext/charconv/convaux.scm =================================================================== RCS file: /cvsroot/gauche/Gauche/ext/charconv/convaux.scm,v retrieving revision 1.1 diff -u -r1.1 convaux.scm --- ext/charconv/convaux.scm 10 Sep 2005 09:04:04 -0000 1.1 +++ ext/charconv/convaux.scm 14 Aug 2006 08:48:58 -0000 @@ -184,7 +184,7 @@ ;; open-{input|output}-port when :encoding argument is given. (define (%open-input-file/conv name . args) (and-let* ((port (apply %open-input-file name args))) - (open-input-conversion-port + (wrap-with-input-conversion port (get-keyword :encoding args #f) :buffer-size (get-keyword :conversion-buffer-size args 0) @@ -192,7 +192,7 @@ (define (%open-output-file/conv name . args) (and-let* ((port (apply %open-output-file name args))) - (open-output-conversion-port + (wrap-with-output-conversion port (get-keyword :encoding args #f) :buffer-size (get-keyword :conversion-buffer-size args 0)
- Shiro(2006/10/07 20:54:59 PDT): 直しました。
コメントのタイポ (CVS Head) 2006/08/05 00:13:51 PDT
タイポだと思います.
--- src/compile.scm-orig 2006年 8月 5日 (土) +++ src/compile.scm 2006年 8月 5日 (土) @@ -64,7 +64,7 @@ ;;; ;;; Pass 2 (Optimization): ;;; - Traverses IFrom and modify the tree to optimize it. -;;; - Limited beta-sustitution (local variable substitution and +;;; - Limited beta-substitution (local variable substitution and ;;; inline local functions for the obvious cases). ;;; - Closure optimization (generates efficient code for truly local ;;; closures)
- Shiro(2006/09/30 19:27:43 PDT): 直しました。
cgi-get-parameter関数のキーワード引数defaultの使い方(0.8.7)
isi(2006/08/02 06:56:08 PDT): ユーザ・リファレンスに「...パラメータnameに対応する値が無ければ、defaultに与えられた値がそのまま返されます。...」と説明があるため、nameだけが定義されていて、値が定義されていない(name=value ではなく name となっている)場合のデフォルト値だと思ったのですが、実装は name そのものが定義されていない場合のデフォルト値となっています。どちらが正しいですか?
- Shiro(2006/08/02 10:10:22 PDT): 意図としては現在の実装のとおりです。 リファレンスの説明の方を直しておきます。
text.csvの説明
2006/07/09 20:40:47 PDT
CSV 形式は、「正式な」仕様が無さそうなのにも関わらず、 プレーン・テキストで表形式のデータを交換するために広く使われています。
現在ではRFC4180で定義されているようなのでその旨を追記しておいた方がよいのではないでしょうか?
- 2006/07/24 03:54:10 PDT: モジュール名もtext.csvよりもrfc.csvにした方がいいかもしれないですね。それとも、汎用的なバージョンをtext.csvにして、厳密にrfcに適合した版をrfc.csvにするとか。
- Shiro (2006/07/24 22:22:39 PDT): ふむ。 RFCの方はクオート文字、セパレータ固定なんですね。 それならtext.csvをRFCのスーパーセットにしとくんでいいんじゃないかな。 あんまりモジュールがぽこぽこ増えると覚えとくのも探すのも大変だし。
sxpath で ns-id:* をパスに含めるとエラー(0.8.7)
tabe(2006/06/22 03:00:12 PDT): 手続き string-rindex が定義されていないようです。
gosh> (use sxml.sxpath) #<undef> gosh> ((sxpath '((ns-id:* x))) '(*TOP* y)) *** ERROR: unbound variable: string-rindex Stack Trace: _______________________________________
- び(2006/06/26 00:14:22 PDT): Gauche的にはstring-index-rightを使えって話なのかなぁ...
- Shiro(2006/07/03 04:44:31 PDT): そうっすね。sxml-tools.scmは本家が更新される 可能性があるので、adaptor.scmの方で (define string-rindex string-index-right) しときました。
dbi-parse-dsn (CVS HEAD)
び(2006/06/11 22:23:55 PDT): dbi-parse-dsn はオプション文字列が存在しない場合、DSNとして"dbi:foo" は許容しますが "dbi:foo:" は許容しません。一方、「Older API」とコメントされている dbi-make-connection の実装では、オプションが空の時、"dbi:foo:" を引数として dbi-connect を(つまりその中でdbi-parse-dsn)呼び出しています。どちらを直すのがいいか判断に迷いますが、"dbi:foo:" も "dbi:foo" も同じと見なしても害はないように思いましたので、dbi-parse-dsn を直してみました。
Index: lib/dbi.scm =================================================================== RCS file: /cvsroot/gauche/Gauche/lib/dbi.scm,v retrieving revision 1.32 diff -u -r1.32 dbi.scm --- lib/dbi.scm 9 Mar 2006 21:53:06 -0000 1.32 +++ lib/dbi.scm 12 Jun 2006 05:17:41 -0000 @@ -204,14 +204,14 @@ ;; (define (dbi-parse-dsn data-source-name) (rxmatch-case data-source-name - (#/^dbi:([\w-]+)(?::(.+))?$/ (#f driver options) - (if options - (let1 alist (map (lambda (nv) - (receive (n v) (string-scan nv "=" 'both) - (if n (cons n v) (cons nv #t)))) - (string-split options #\;)) - (values driver options alist)) - (values driver "" '()))) + (#/^dbi:([\w-]+)(?::(.*))?$/ (#f driver options) + (if (and options (not (string-null? options))) + (let1 alist (map (lambda (nv) + (receive (n v) (string-scan nv "=" 'both) + (if n (cons n v) (cons nv #t)))) + (string-split options #\;)) + (values driver options alist)) + (values driver "" '()))) (else (error <dbi-error> "bad data source name spec:" data-source-name))))
- Shiro(2006/07/03 04:44:31 PDT): 直しときました
- び(2006/07/03 05:03:25 PDT): 直ってない気配。(.+)ではなくて(.*)にしないとだめだと思うのですが...
- Shiro(2006/07/04 03:42:21 PDT): あっほんとだ。目patch しくじった。
ScmConditionVariableRec と ScmMutexRec の最初のメンバが SCM_HEADER になっている。(0.8.7)
horii(2006/05/31 02:04:28 PDT): カテゴリが SCM_CLASS_BASE のクラスは、構造体の最初のメンバが ScmInstance でないといけないと思っているのですが、ScmConditionVariableRec と ScmMutexRec だけは、そうなっていません。
--- threads.h.orig 2006-05-31 17:54:51.266058922 +0900 +++ threads.h 2006-05-31 17:54:58.000000000 +0900 @@ -59,7 +59,7 @@ * Scheme condition variable. */ typedef struct ScmConditionVariableRec { - SCM_HEADER; + SCM_INSTANCE_HEADER; ScmInternalCond cv; ScmObj name; ScmObj specific; @@ -82,7 +82,7 @@ * locked=TRUE owner=terminated vm unlocked/abandoned */ typedef struct ScmMutexRec { - SCM_HEADER; + SCM_INSTANCE_HEADER; ScmInternalMutex mutex; ScmInternalCond cv; ScmObj name;
- Shiro(2006/10/07 22:02:55 PDT): 修正しました。たぶん、継承可能にすべきかどうかを 迷っていたんだと思います。とりあえず継承可能ってことで一貫性を取っておきます。
RedHat EnterpriseLinux ES release 4でthreadのテストに失敗する (0.8.7)
./configure --prefix=$HOME --enable-threads=pthreads~% make~% make check~% Testing threads ... /bin/sh: line 1: 5497 セグメンテーション違反です ../..//src/gosh -ftest -I. test.scm >test.log~%
test.logは
test write to file, buffered, expects #t ==>で終っています。
何度かやるとたまに成功します。
gdbで見たところ、
Program received signal SIGSEGV, Segmentation fault. [Switching to Thread -1229931600 (LWP 7331)] 0x00e6a957 in Scm_Write (obj=0x8759240, p=0x8a487e8, mode=1) at write.c:160 160 PORT_LOCK(port, vm);
となっていました。
環境は以下のとおりです。
uname -a 2.6.9-34.ELsmp #1 SMP Fri Feb 24 16:54:53 EST 2006 i686 i686 i386 GNU/Linux gcc -v /usr/lib/gcc/i386-redhat-linux/3.4.5/specs から spec を読み込み中 コンフィグオプション: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=i386-redhat-linux
追記:PORT_LOCKの
while (p->lockOwner != NULL) { if (p->lockOwner->state == SCM_VM_TERMINATED) {
この行の間でlockOwnerがNULLになることがあるようです。
- Shiro(2006/05/30 14:07:28 PDT): あーなるほど。PORT_UNLOCKと競合してしまうのか。 ポートのロックはもう少し何とかしたい点なので、全体的に見直してみます (とりあえずの対応としてはPORT_UNLOCK中でportの状態を変える時に mutexをロックすれば大丈夫だと思いますが、性能にかなり影響が出ると思います)。
- び(2006/05/30 18:34:19 PDT): 件の問題を回避するだけなら以下のパッチでもいけそうな気がします。RHELの環境がないので確認できませんが...
Index: src/gauche/port.h =================================================================== RCS file: /cvsroot/gauche/Gauche/src/gauche/port.h,v retrieving revision 1.11 diff -u -r1.11 port.h --- src/gauche/port.h 17 Oct 2004 10:29:39 -0000 1.11 +++ src/gauche/port.h 31 May 2006 01:25:05 -0000 @@ -79,9 +79,10 @@ do { \ if (!(p->flags&SCM_PORT_PRIVATE)) { \ if (p->lockOwner != vm) { \ + ScmVM *lockOwner = NULL; \ (void)SCM_INTERNAL_MUTEX_LOCK(p->mutex); \ - while (p->lockOwner != NULL) { \ - if (p->lockOwner->state == SCM_VM_TERMINATED) { \ + while ((lockOwner = p->lockOwner) != NULL) { \ + if (lockOwner->state == SCM_VM_TERMINATED) { \ break; \ } \ (void)SCM_INTERNAL_COND_WAIT(p->cv, p->mutex); \
- 2006/05/30 21:52:18 PDT:PORT_UNLOCKでmutex lockをかけたところ落ちなくなりました。びさんのpatchを当てた場合は時々デッドロックしてしまうようで、テストが終らないことがありました。
- び(2006/05/31 00:09:47 PDT): あ、そうか、SCM_INTERNAL_COND_WAIT()が呼ばれる前にSCM_INTERNAL_COND_SIGNAL()が呼ばれたら簡単にデッドロックしちゃいますね。失礼しました。やっぱり素直にmutexをロックするしかないのか...
- Shiro(2006/07/24 22:22:39 PDT): この問題に対応。unlockの操作をアトミックにしたんで ハザードは避けられてる…と思います。ついでにpthread_spinlockが使えるなら 使うようにして、I/O性能も当社比1.8倍に高速化 (read-byte/write-byteを繰り返す プログラムにて測定)。
- RHEL4上でcvshead確認しました。すべてのテストに成功しています。2006/08/02 19:22:16 PDT
gauche-package が正しくないコンパイラ名を使用しようとする (0.8.7)
yokota(2006/05/27 18:29:51 PDT): 最近の autoconf(Ver.2.59d) は可能な限り新しいC言語規格を使用しようとして C99 標準を使わせるオプションを設定しようとします。例えば gcc なら CC="gcc -std=gnu99" としようとします。 gauche-package は CC の値を引用符で囲んで使用しようとするために "gcc -std=gnu99" というコマンドは存在しないというエラーを出します。 結果として gauche-package を用いる全てのパッケージの構築に失敗します。 以下のパッチを当てて下さい。
--- Gauche-0.8.7/lib/gauche/package/compile.scm.orig 2005-08-01 13:24:03.000000000 +0900 +++ Gauche-0.8.7/lib/gauche/package/compile.scm 2006-05-28 10:19:02.000000000 +0900 @@ -87,7 +87,7 @@ (run #`"',GOSH' genstub ,stubfile")) (define (do-compile cc cfile ofile cppflags cflags) - (run #`"',cc' -c ,cppflags ,INCDIR ,cflags ,CFLAGS -o ',ofile' ',cfile'")) + (run #`",cc -c ,cppflags ,INCDIR ,cflags ,CFLAGS -o ',ofile' ',cfile'")) (define (gauche-package-link sofile ofiles . args) (let-keywords* args ((ldflags #f) @@ -100,7 +100,7 @@ (unless (and (file-exists? sofile) (every (cut file-mtime>? sofile <>) ofiles)) (let1 all-ofiles (string-join (map (lambda (f) #`"',f'") ofiles) " ") - (run #`"',(or ld CC)' ,(or ldflags \"\") ,LIBDIR ,LDFLAGS ,sofile ,all-ofiles ,LIBS ,(or libs \"\")")))))) + (run #`",(or ld CC) ,(or ldflags \"\") ,LIBDIR ,LDFLAGS ,sofile ,all-ofiles ,LIBS ,(or libs \"\")")))))) (define (gauche-package-compile-and-link module-name files . args) (let ((head.c #`",|module-name|_head.c")
- Shiro(2006/05/29 02:56:38 PDT): 修正しました。
http-post リクエストのメッセージボディの後に余分なCRLFが送信される(0.8.7)
2006/05/22 08:44:45 PDT 標準モジュール rfc.http の http-post を使用すると、 リクエストのメッセージボディの後に余分なCRLFが送信されます。 RFC2616( ftp://ftp.isi.edu/in-notes/rfc2616.txt )の 4.1 Message Types によると
Certain buggy HTTP/1.0 client implementations generate extra CRLF's after a POST request. To restate what is explicitly forbidden by the BNF, an HTTP/1.1 client MUST NOT preface or follow a request with an extra CRLF.
ということなのでCRLFは送信しないほうが正確な挙動だと思います。 http.scm のへのパッチ
--- Gauche-0.8.7/lib/rfc/http.scm.orig 2006-05-22 14:44:39.111930696 +0900 +++ Gauche-0.8.7/lib/rfc/http.scm 2006-05-22 23:08:03.393366544 +0900 @@ -177,7 +177,7 @@ out) (display "\r\n" out) (display body out) - (display "\r\n" out)) + (flush out)) ;; requests w/o body (begin (send-request-headers options out)
- Shiro(2006/05/29 02:56:38 PDT): 修正しました。
regexp-compile fails (0.8.7)
2006/05/19 20:40:44 PDT: leque いくつかのパターンで regexp-compile が失敗します。
gosh> (string->regexp "a+") #/a+/ gosh> (regexp-parse "a+") (0 #f (rep 1 #f #〓a)) gosh> (regexp-compile (regexp-parse "a+")) *** ERROR: internal error in regexp compilation: bad node: ((rep 1 #f ()))
gosh> (regexp-parse "a?+") (0 #f (once (rep 0 1 #〓a))) gosh> (regexp-compile (regexp-parse "a?+")) *** ERROR: invalid regexp AST: (once (rep 0 1 #〓a)) gosh> (regexp-parse "(a)〓〓1") (0 #f (1 #f #〓a) (backref . 1)) gosh> (regexp-compile (regexp-parse "(a)〓〓1")) *** ERROR: invalid regexp AST: (backref . 1) gosh> (regexp-parse "(?<hoge>a)〓〓k<hoge>") (0 #f (1 hoge #〓a) (backref . 1)) gosh> (regexp-compile (regexp-parse "(?<hoge>a)〓〓k<hoge>")) *** ERROR: invalid regexp AST: (backref . 1) gosh> (regexp-parse "(a)(?(1)b|c)") (0 #f (1 #f #〓a) (cpat 1 (#〓b) (#〓c))) gosh> (regexp-compile (regexp-parse "(a)(?(1)b|c)")) *** ERROR: invalid regexp AST: (cpat 1 (#〓b) (#〓c))
- Shiro(2006/05/29 02:56:38 PDT): 修正しました。 (パッチは長いのでコメントアウトしてあります)
let-args の説明文 (0.8.7)
2006/05/13 03:40:18 PDT: http://www.shiro.dreamhost.com/scheme/gauche/man/gauche-refj_84.html#SEC244 の let-args の説明で, 「束縛リストは、最後のcarにシンボルを持つ不完全なリストであっても良く」 は cdr の typo でしょうか?
- Shiro(2006/05/29 02:56:38 PDT): 修正しました。
object-writeでwrite/ssを呼ぶとassertに引っかかる (0.8.7)
Rui (2006/05/13 02:53:20 PDT): object-writeの中でwrite/ssを呼ぶと、assertionに引っかかってgoshが落ちます。write/ssが呼ぶScm_WriteCircularで、walk passを意識せずwrite_ssを呼んでしまっているのが問題のようです。
- Shiro(2006/10/07 20:54:59 PDT): 現在のwrite/ssの実装自体がkludgeなので 根本的に修正したいと思っていたのですが、しばらくかかりそうなので パッチを頂いておきます (長いのでコメントにしました)。
ext/threads/threads.c (0.8.7)
び(2006/05/09 02:46:56 PDT): Mac OS Xでスレッドを多用すると瞬く間に仮想メモリ使用量が膨れ上がるのに、Linuxでは何ともないので不思議に思っていました。
--- ext/threads/threads.c.orig 2006-04-07 11:07:46.000000000 +0900 +++ ext/threads/threads.c 2006-05-09 18:33:04.000000000 +0900 @@ -165,7 +165,7 @@ SCM_ASSERT(vm->thunk); vm->state = SCM_VM_RUNNABLE; pthread_attr_init(&thattr); - pthread_attr_setdetachstate(&thattr, TRUE); + pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_DETACHED); pthread_sigmask(SIG_SETMASK, &threadrec.defaultSigmask, &omask); if (pthread_create(&vm->thread, &thattr, thread_entry, vm) != 0) { vm->state = SCM_VM_NEW;
Linuxだと
enum { PTHREAD_CREATE_JOINABLE, #define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_DETACHED #define PTHREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED };
だからTRUEでも問題が起きないのだけど、Mac OS Xだと
#define PTHREAD_CREATE_JOINABLE 1 #define PTHREAD_CREATE_DETACHED 2
だからだめだったってことですね。
- Shiro(2006/07/03 04:45:46 PDT): 修正しました。
SO_RCVBUF Socket Option(0.8.7)
jingu(2006/05/01 00:33:05 PDT): ソケットオプションSO_RCVBUFが正しくエクスポートされていませんでした。 ついでに、SOL_SOCKETレベルでエクスポートされていないオプションも追加してみました。
diff -ru Gauche-0.8.7.orig/ext/net/netlib.stub Gauche-0.8.7/ext/net/netlib.stub --- Gauche-0.8.7.orig/ext/net/netlib.stub 2006-05-01 15:35:58.000000000 +0900 +++ Gauche-0.8.7/ext/net/netlib.stub 2006-05-01 15:38:15.000000000 +0900 @@ -265,9 +265,17 @@ (define-enum-conditionally SO_TYPE) (define-enum-conditionally SO_BROADCAST) (define-enum-conditionally SO_SNDBUF) -(define-enum-conditionally SO_RFCBUF) +(define-enum-conditionally SO_RCVBUF) (define-enum-conditionally SO_PRIORITY) (define-enum-conditionally SO_ERROR) +(define-enum-conditionally SO_DEBUG) +(define-enum-conditionally SO_DONTROUTE) +(define-enum-conditionally SO_LINGER) +(define-enum-conditionally SO_RCVLOWAT) +(define-enum-conditionally SO_SNDLOWAT) +(define-enum-conditionally SO_RCVTIMEO) +(define-enum-conditionally SO_SNDTIMEO) +(define-enum-conditionally SO_REUSEPORT) (define-enum-conditionally SOL_TCP) (define-enum-conditionally TCP_NODELAY) diff -ru Gauche-0.8.7.orig/ext/net/net.scm Gauche-0.8.7/ext/net/net.scm --- Gauche-0.8.7.orig/ext/net/net.scm 2006-05-01 15:35:58.000000000 +0900 +++ Gauche-0.8.7/ext/net/net.scm 2006-05-01 15:40:11.000000000 +0900 @@ -62,6 +62,8 @@ |IPPROTO_IP| |IPPROTO_ICMP| |IPPROTO_TCP| |IPPROTO_UDP| |IPPROTO_IPV6| |SOL_SOCKET| |SO_KEEPALIVE| |SO_OOBINLINE| |SO_REUSEADDR| |SO_TYPE| |SO_BROADCAST| |SO_SNDBUF| |SO_RCVBUF| |SO_PRIORITY| |SO_ERROR| |SOMAXCONN| + |SO_DEBUG| |SO_DONTROUTE| |SO_LINGER| |SO_RCVLOWAT| |SO_SNDLOWAT| + |SO_RCVTIMEO| |SO_SNDTIMEO| |SO_REUSEPORT| |SOL_TCP| |TCP_NODELAY| |TCP_MAXSEG| |TCP_CORK| |SOL_IP| |IP_OPTIONS| |MSG_CTRUNC| |MSG_DONTROUTE| |MSG_EOR| |MSG_OOB| |MSG_PEEK|
digit->integer (0.8.7)
2006/04/25 23:25:35 PDT: radix が 10 未満のときの digit->integer の挙動が変だと思います。
gosh> (digit->integer #\1 2) 1 gosh> (digit->integer #\2 2) 2 gosh> (digit->integer #\3 2) #f gosh> (digit->integer #\8 8) 8 gosh> (digit->integer #\9 8) #f gosh> (digit->integer #\a 10) #f
(digit->integer #\2 2) 等は #f になるべきではないでしょうか。
--- char.c.orig 2006-04-26 15:14:59.000000000 +0900 +++ char.c 2006-04-26 15:16:22.000000000 +0900 @@ -83,7 +83,7 @@ { if (ch < '0') return -1; if (radix <= 10) { - if (ch <= '0' + radix) return (ch - '0'); + if (ch < '0' + radix) return (ch - '0'); } else { if (ch <= '9') return (ch - '0'); if (ch < 'A') return -1;
- Shiro(2006/04/29 03:26:04 PDT): 直しました。
with-module in syntax-rules (0.8.7)
2006/04/19 03:01:46 PDT: 次のようなマクロを展開しようとすると無限ループになります。
gosh> (define-syntax let (syntax-rules () ((_ rest ...) ((with-module null let) rest ...)))) gosh> (let () 1) ^C *** ERROR: Compile Error: unhandled signal 2 (SIGINT) "(stdin)":15:(let () 1) Stack Trace: _______________________________________
マクロ展開中の with-module の処理に問題があるみたいです。
gosh> (define pi 3) pi gosh> pi 3 gosh> (require "math/const") #<undef> gosh> (with-module math.const pi) 3.141592653589793 gosh> (define-syntax bar (syntax-rules () ((_) (with-module math.const pi)))) #<undef> gosh> (bar) 3
- Shiro(2006/04/29 04:33:53 PDT): あーなるほど。原因はわかりました。が、
今のマクロ展開のアルゴリズムだとうまくサポートできないかもしれません。
(ある識別子が、マクロフォームの外から与えられのか、テンプレートから導入されたのかが、
マクロ展開後に区別できないため。
with-moduleは後者の識別子についてのみ作用する必要がある。)
この欠陥は、R5RSマクロを生成するR5RSマクロがGaucheでちゃんと動作しない
原因でもあるので、そろそろ腰を据えてfixする必要がありそうです。
当面の回避策としては、define-macroを使って下さい。
socket-recvfrom(0.8.6)
jingu 2006/04/09 01:14:22 PDT: IPv6の場合、socket-recvfromが送信者のソケットアドレスを
正しく返しませんでした。
--- net.c.orig 2006-04-09 16:13:38.000000000 +0900 +++ net.c 2006-04-09 17:33:17.000000000 +0900 @@ -360,18 +360,19 @@ { int r; char *buf; - struct sockaddr from; - socklen_t fromlen = sizeof(from); + const char from[SCM_SOCKADDR_MAXLEN]; + socklen_t fromlen = SCM_SOCKADDR_MAXLEN; + if (SOCKET_CLOSED(sock->fd)) { Scm_Error("attempt to recv from a closed socket: %S", sock); } buf = SCM_NEW_ATOMIC2(char*, bytes); - SCM_SYSCALL(r, recvfrom(sock->fd, buf, bytes, flags, &from, &fromlen)); + SCM_SYSCALL(r, recvfrom(sock->fd, buf, bytes, flags, (struct sockaddr *)&from, &fromlen)); if (r < 0) { Scm_SysError("recvfrom(2) failed"); } return Scm_Values2(Scm_MakeString(buf, r, r, SCM_MAKSTR_INCOMPLETE), - Scm_MakeSockAddr(NULL, &from, fromlen)); + Scm_MakeSockAddr(NULL, (struct sockaddr *)&from, fromlen)); } /* Low-level setsockopt() and getsockopt() interface. */
- Shiro(2006/04/09 22:35:51 PDT): 了解。0.8.7のリリース後に入れます。
- び(2006/04/10 15:00:46 PDT): 今時だと、char配列を使うより、struct sockaddr_storageを使った方がいいように思うのですが、まだ使えないプラットフォームって残ってますか? 他にもgauche.net関係で気になるところがあったので、ちょっと手を入れてみました。上記の修正相当も含んでいます。→ パッチ改変
- jingu(2006/04/11 07:41:49 PDT): struct sockaddr_storageのないシステムでも動くとありがたいです。
- び(2006/04/11 18:47:43 PDT): ではこんな感じではどうでしょうか。struct sockaddr_storageがないシステムが手許にないのですが、config.hを手でいじった限りではきちんとビルドできます。
Index: ext/net/addr.c =================================================================== RCS file: /cvsroot/gauche/Gauche/ext/net/addr.c,v retrieving revision 1.23 diff -u -r1.23 addr.c --- ext/net/addr.c 22 Jan 2006 00:52:54 -0000 1.23 +++ ext/net/addr.c 12 Apr 2006 01:43:07 -0000 @@ -77,9 +77,10 @@ /* creates sockaddr from struct sockaddr. */ ScmObj Scm_MakeSockAddr(ScmClass *klass, struct sockaddr *saddr, int len) { - ScmSockAddr *addr; - addr = SCM_NEW2(ScmSockAddr*, - sizeof(ScmSockAddr) - sizeof(struct sockaddr) + len); + ScmSockAddrStorage *addr; + SCM_ASSERT(sizeof(scm_sockaddr_storage) >= len); + SCM_ASSERT(saddr != NULL); + addr = SCM_NEW(ScmSockAddrStorage); if (klass == NULL) { switch (saddr->sa_family) { case AF_UNIX: @@ -100,7 +101,9 @@ } SCM_SET_CLASS(addr, klass); addr->addrlen = len; - memset(&addr->addr, 0, len); +#ifdef HAVE_SS_LEN + addr->addr.ss_len = len; +#endif memcpy(&addr->addr, saddr, len); return SCM_OBJ(addr); } @@ -109,7 +112,6 @@ * Unix domain socket */ -#define UNIX_ADDRESS_PATH_MAX 108 static ScmObj sockaddr_un_allocate(ScmClass *klass, ScmObj initargs); SCM_DEFINE_BUILTIN_CLASS(Scm_SockAddrUnClass, sockaddr_print, @@ -124,14 +126,17 @@ Scm_Error(":path parameter must be a string, but got %S", path); } addr = SCM_NEW(ScmSockAddrUn); - SCM_SET_CLASS(addr, &Scm_SockAddrUnClass); + SCM_SET_CLASS(addr, SCM_CLASS_SOCKADDR_UN); memset(&addr->addr, 0, sizeof(struct sockaddr_un)); +#ifdef HAVE_SUN_LEN + addr->addr.sun_len = sizeof(struct sockaddr_un); +#endif addr->addr.sun_family = AF_UNIX; if (SCM_STRINGP(path)) { u_int size; const char *cpath = Scm_GetStringContent(SCM_STRING(path), &size, NULL, NULL); - if (size >= UNIX_ADDRESS_PATH_MAX-1) { + if (size >= sizeof(addr->addr.sun_path)-1) { Scm_Error("path too long: %S", path); } memcpy(addr->addr.sun_path, cpath, size); @@ -161,7 +166,7 @@ port); } addr = SCM_NEW(ScmSockAddrIn); - SCM_SET_CLASS(addr, &Scm_SockAddrInClass); + SCM_SET_CLASS(addr, SCM_CLASS_SOCKADDR_IN); memset(&addr->addr, 0, sizeof(struct sockaddr_in)); #ifdef HAVE_SIN_LEN addr->addr.sin_len = sizeof(struct sockaddr_in); @@ -222,7 +227,7 @@ port); } addr = SCM_NEW(ScmSockAddrIn6); - SCM_SET_CLASS(addr, &Scm_SockAddrIn6Class); + SCM_SET_CLASS(addr, SCM_CLASS_SOCKADDR_IN6); memset(&addr->addr, 0, sizeof(struct sockaddr_in6)); #ifdef HAVE_SIN6_LEN addr->addr.sin6_len = sizeof(struct sockaddr_in6); Index: ext/net/net.ac =================================================================== RCS file: /cvsroot/gauche/Gauche/ext/net/net.ac,v retrieving revision 1.4 diff -u -r1.4 net.ac --- ext/net/net.ac 15 Jul 2004 07:10:05 -0000 1.4 +++ ext/net/net.ac 12 Apr 2006 01:43:07 -0000 @@ -37,11 +37,57 @@ fi dnl +dnl Check availability of struct sockaddr_storage +dnl +AC_CACHE_CHECK(struct sockaddr_storage is available, ac_cv_struct_sockaddr_storage, [ +AC_TRY_COMPILE([ +#include <sys/types.h> +#include <sys/socket.h> +], [ +struct sockaddr_storage ss; +], ac_cv_struct_sockaddr_storage=yes, ac_cv_struct_sockaddr_storage=no)]) + +if test "$ac_cv_struct_sockaddr_storage" = yes; then +AC_DEFINE(HAVE_SOCKADDR_STORAGE,1,[Define if struct sockaddr_storage is available]) +fi + +dnl dnl Checks if sockaddr_in and sockaddr_in6 has *_len field dnl +if test "$ac_cv_struct_sockaddr_storage" = yes; then +AC_CACHE_CHECK(struct sockaddr_storage has ss_len, ac_cv_struct_sockaddr_storage_len, [ +AC_TRY_COMPILE([ +#include <sys/types.h> +#include <sys/socket.h> +], [ +struct sockaddr_storage ss; +int z = ss.ss_len; +], ac_cv_struct_sockaddr_storage_len=yes, ac_cv_struct_sockaddr_storage_len=no)]) + +if test "$ac_cv_struct_sockaddr_storage_len" = yes; then +AC_DEFINE(HAVE_SS_LEN,1,[Define if struct sockaddr_storage has ss_len]) +fi +fi + +AC_CACHE_CHECK(struct sockaddr_un has sun_len, ac_cv_struct_sockaddr_un_len, [ +AC_TRY_COMPILE([ +#include <sys/types.h> +#include <sys/un.h> +], [ +struct sockaddr_un addr; +int z = addr.sun_len; +], ac_cv_struct_sockaddr_un_len=yes, ac_cv_struct_sockaddr_un_len=no)]) + +if test "$ac_cv_struct_sockaddr_un_len" = yes; then +AC_DEFINE(HAVE_SUN_LEN,1,[Define if struct sockaddr_un has sun_len]) +fi + AC_CACHE_CHECK(struct sockaddr_in has sin_len, ac_cv_struct_sockaddr_in_len, [ -AC_TRY_COMPILE([#include <netinet/in.h>], [ +AC_TRY_COMPILE([ +#include <sys/types.h> +#include <netinet/in.h> +], [ struct sockaddr_in addr; int z = addr.sin_len; ], ac_cv_struct_sockaddr_in_len=yes, ac_cv_struct_sockaddr_in_len=no)]) @@ -52,7 +98,10 @@ if test "$ac_cv_ipv6" = yes; then AC_CACHE_CHECK(struct sockaddr_in6 has sin6_len, ac_cv_struct_sockaddr_in6_len, [ -AC_TRY_COMPILE([#include <netinet/in.h>], [ +AC_TRY_COMPILE([ +#include <sys/types.h> +#include <netinet/in.h> +], [ struct sockaddr_in6 addr; int z = addr.sin6_len; ], ac_cv_struct_sockaddr_in6_len=yes, ac_cv_struct_sockaddr_in6_len=no)]) Index: ext/net/net.c =================================================================== RCS file: /cvsroot/gauche/Gauche/ext/net/net.c,v retrieving revision 1.42 diff -u -r1.42 net.c --- ext/net/net.c 7 Jan 2006 05:54:20 -0000 1.42 +++ ext/net/net.c 12 Apr 2006 01:43:07 -0000 @@ -244,16 +244,16 @@ ScmObj Scm_SocketAccept(ScmSocket *sock) { - const char addrbuf[SCM_SOCKADDR_MAXLEN]; + scm_sockaddr_storage addrbuf; int newfd; - socklen_t addrlen = SCM_SOCKADDR_MAXLEN; + socklen_t addrlen = sizeof(addrbuf); ScmSocket *newsock; ScmClass *addrClass = Scm_ClassOf(SCM_OBJ(sock->address)); if (SOCKET_CLOSED(sock->fd)) { Scm_Error("attempt to accept a closed socket: %S", sock); } - SCM_SYSCALL(newfd, accept(sock->fd, (struct sockaddr *)addrbuf, &addrlen)); + SCM_SYSCALL(newfd, accept(sock->fd, (struct sockaddr*)&addrbuf, &addrlen)); if (SOCKET_INVALID(newfd)) { if (errno == EAGAIN) { return SCM_FALSE; @@ -264,7 +264,7 @@ newsock = make_socket(newfd, sock->type); newsock->address = SCM_SOCKADDR(Scm_MakeSockAddr(addrClass, - (struct sockaddr *)addrbuf, + (struct sockaddr*)&addrbuf, addrlen)); newsock->status = SCM_SOCKET_STATUS_CONNECTED; return SCM_OBJ(newsock); @@ -287,34 +287,34 @@ ScmObj Scm_SocketGetSockName(ScmSocket *sock) { - const char addrbuf[SCM_SOCKADDR_MAXLEN]; + scm_sockaddr_storage addrbuf; int r; - socklen_t addrlen = SCM_SOCKADDR_MAXLEN; + socklen_t addrlen = sizeof(addrbuf); if (SOCKET_CLOSED(sock->fd)) { Scm_Error("attempt to get the name of a closed socket: %S", sock); } - SCM_SYSCALL(r, getsockname(sock->fd, (struct sockaddr *)addrbuf, &addrlen)); + SCM_SYSCALL(r, getsockname(sock->fd, (struct sockaddr*)&addrbuf, &addrlen)); if (r < 0) { Scm_SysError("getsockname(2) failed"); } - return SCM_OBJ(Scm_MakeSockAddr(NULL, (struct sockaddr *)addrbuf, addrlen)); + return SCM_OBJ(Scm_MakeSockAddr(NULL, (struct sockaddr*)&addrbuf, addrlen)); } ScmObj Scm_SocketGetPeerName(ScmSocket *sock) { - const char addrbuf[SCM_SOCKADDR_MAXLEN]; + scm_sockaddr_storage addrbuf; int r; - socklen_t addrlen = SCM_SOCKADDR_MAXLEN; + socklen_t addrlen = sizeof(addrbuf); if (SOCKET_CLOSED(sock->fd)) { Scm_Error("attempt to get the name of a closed socket: %S", sock); } - SCM_SYSCALL(r, getpeername(sock->fd, (struct sockaddr *)addrbuf, &addrlen)); + SCM_SYSCALL(r, getpeername(sock->fd, (struct sockaddr*)&addrbuf, &addrlen)); if (r < 0) { Scm_SysError("getpeername(2) failed"); } - return SCM_OBJ(Scm_MakeSockAddr(NULL, (struct sockaddr *)addrbuf, addrlen)); + return SCM_OBJ(Scm_MakeSockAddr(NULL, (struct sockaddr*)&addrbuf, addrlen)); } ScmObj Scm_SocketSend(ScmSocket *sock, ScmString *msg, int flags) @@ -368,18 +368,18 @@ { int r; char *buf; - struct sockaddr from; + scm_sockaddr_storage from; socklen_t fromlen = sizeof(from); if (SOCKET_CLOSED(sock->fd)) { Scm_Error("attempt to recv from a closed socket: %S", sock); } buf = SCM_NEW_ATOMIC2(char*, bytes); - SCM_SYSCALL(r, recvfrom(sock->fd, buf, bytes, flags, &from, &fromlen)); + SCM_SYSCALL(r, recvfrom(sock->fd, buf, bytes, flags, (struct sockaddr*)&from, &fromlen)); if (r < 0) { Scm_SysError("recvfrom(2) failed"); } return Scm_Values2(Scm_MakeString(buf, r, r, SCM_MAKSTR_INCOMPLETE), - Scm_MakeSockAddr(NULL, &from, fromlen)); + Scm_MakeSockAddr(NULL, (struct sockaddr*)&from, fromlen)); } /* Low-level setsockopt() and getsockopt() interface. */ Index: ext/net/gauche/net.h =================================================================== RCS file: /cvsroot/gauche/Gauche/ext/net/gauche/net.h,v retrieving revision 1.2 diff -u -r1.2 net.h --- ext/net/gauche/net.h 4 Sep 2005 23:59:54 -0000 1.2 +++ ext/net/gauche/net.h 12 Apr 2006 01:43:07 -0000 @@ -75,6 +75,20 @@ * Socket address */ +#ifdef HAVE_SOCKADDR_STORAGE +typedef struct sockaddr_storage scm_sockaddr_storage; +#else +#define SCM_SOCKADDR_MAXLEN 128 +typedef char scm_sockaddr_storage[SCM_SOCKADDR_MAXLEN]; +#endif + +/* Real Socket Address Storage. */ +typedef struct ScmSockAddrStorageRec { + SCM_HEADER; + socklen_t addrlen; + scm_sockaddr_storage addr; +} ScmSockAddrStorage; + typedef struct ScmSockAddrRec { SCM_HEADER; socklen_t addrlen; @@ -129,8 +143,6 @@ #endif /* HAVE_IPV6 */ -#define SCM_SOCKADDR_MAXLEN 128 - /*------------------------------------------------------------------ * Socket */ Index: src/gauche/config.h.in =================================================================== RCS file: /cvsroot/gauche/Gauche/src/gauche/config.h.in,v retrieving revision 1.49 diff -u -r1.49 config.h.in --- src/gauche/config.h.in 4 Mar 2006 09:17:31 -0000 1.49 +++ src/gauche/config.h.in 12 Apr 2006 01:43:07 -0000 @@ -194,6 +194,15 @@ /* Define if struct sockaddr_in has sin_len */ #undef HAVE_SIN_LEN +/* Define if struct sockaddr_un has sun_len */ +#undef HAVE_SUN_LEN + +/* Define if struct sockaddr_storage is available */ +#undef HAVE_SOCKADDR_STORAGE + +/* Define if struct sockaddr_storage has ss_len */ +#undef HAVE_SS_LEN + /* Define to 1 if you have the `srand48' function. */ #undef HAVE_SRAND48
- jingu(2006/04/24 10:54:34 PDT): 作成していただいたパッチをIPv4-onlyなホスト(FreeBSD 3.5.1)で
動作することを確認しました。遅くなり申しわけありませんでした。
それと、sockaddr_storageがない場合の対処についてですが、Rubyでは、
適切にアラインメントされるようにsockaddr_storageを自分で定義しているようです。
[Ruby 1.8.4 ext/socket/socket.c] #ifndef HAVE_SOCKADDR_STORAGE /* * RFC 2553: protocol-independent placeholder for socket addresses */ #define _SS_MAXSIZE 128 #define _SS_ALIGNSIZE (sizeof(double)) #define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(unsigned char) * 2) #define _SS_PAD2SIZE (_SS_MAXSIZE - sizeof(unsigned char) * 2 - \ _SS_PAD1SIZE - _SS_ALIGNSIZE) struct sockaddr_storage { #ifdef HAVE_SA_LEN unsigned char ss_len; /* address length */ unsigned char ss_family; /* address family */ #else unsigned short ss_family; #endif char __ss_pad1[_SS_PAD1SIZE]; double __ss_align; /* force desired structure storage alignment */ char __ss_pad2[_SS_PAD2SIZE]; }; #endif
- び(2006/04/24 20:57:23 PDT): なるほど。そういえばRFC2553(今だと3493)には参照実装が含まれていましたね。それを利用した方が確かにスマートだと思います。
- Shiro(2006/07/04 20:48:31 PDT): 遅くなりましたが対応しました。 ScmSockAddrStorageは他に用途無さそうだったので導入しませんでしたが… (sizeof(ScmSockAddr)を越えてmemcpyするのは確かに行儀が悪いですが、 それが気持ち悪いならむしろfamilyで分岐した後にScmSockAddrUn等適切な型を アロケートするべきでしょうね)
- び(2006/07/05 00:44:39 PDT): NetBSDではstruct sockaddr_storageの検出に失敗します。以下のパッチでいかがでしょうか。
Index: ext/net/net.ac =================================================================== RCS file: /cvsroot/gauche/Gauche/ext/net/net.ac,v retrieving revision 1.5 diff -u -r1.5 net.ac --- ext/net/net.ac 5 Jul 2006 03:35:54 -0000 1.5 +++ ext/net/net.ac 5 Jul 2006 07:44:17 -0000 @@ -39,7 +39,7 @@ dnl dnl Check to see if the system provides sockaddr_storage dnl -AC_CHECK_TYPES([struct sockaddr_storage],,,[#include <netinet/in.h>]) +AC_CHECK_TYPES([struct sockaddr_storage],,,[#include <sys/socket.h>]) dnl dnl Checks if sockaddr_in and sockaddr_in6 has *_len field
- Shiro(2006/07/05 02:31:21 PDT): おおそっちか。