[#21338] $SAFE=4 での autoload — Hidetoshi NAGAI <nagai@...>

永井@知能.九工大です.

21 messages 2003/09/04
[#21346] Re: $SAFE=4 での autoload — nobu.nakada@... 2003/09/04

なかだです。

[#21359] Re: $SAFE=4 での autoload — Hidetoshi NAGAI <nagai@...> 2003/09/05

永井@知能.九工大です.

[#21419] Makefile.inのlex.c — Kazuhiro NISHIYAMA <zn@...>

西山和広です。

15 messages 2003/09/28

[ruby-dev:21444] Re: break from block yielded in until

From: Tietew <tietew-ml-ruby-dev@...>
Date: 2003-09-30 09:32:12 UTC
List: ruby-dev #21444
On Tue, 30 Sep 2003 17:58:59 +0900
In article <1064912338.483378.13743.nullmailer@picachu.netlab.jp>
[[ruby-dev:21442] Re: break from block yielded in until]
matz@ruby-lang.org (Yukihiro Matsumoto) wrote:

> |これに関連すると思うのですが,拡張ライブラリで rb_catch してから 
> |rb_yield していると,つまり,以下のようなコードを C で書いてある
> |と,break がブロックを抜けずに rb_catch で止まってしまいます。
> |
> |Ruby で書いてあると大丈夫で,C で書いてあると止まるようです。
> |rb_iterate の場合だとどうなるのかは試していません。
> 
> 実際に問題を起こすCコードを見せてもらえませんか。こっちで試
> 行錯誤してC化して、再現しなかったら無駄な手間ですから。

すみません。Linux上で再現するコードにしました。

$ ruby1.8 -v -rcatch -e 'find { |e| p e; break; }'
ruby 1.8.0 (2003-09-30) [i686-linux]
"extconf.rb\\"
"catch.c\\"
"Makefile\\"
"catch.o\\"
"catch.so\\"
"core\\"

期待する出力は,最初の一行のみです。

$ ruby1.8 -v -rfind -e 'Find.find(".") { |e| p e; break; }'
ruby 1.8.0 (2003-09-30) [i686-linux]
"."



—[ Tietew ]——————————————————————————
 メ : tietew@tietew.net / tietew@raug.net / tietew@masuclub.net
ホペ: http://www.tietew.net/     Tietew Windows Lab.
      http://www.masuclub.net/   鱒倶楽部
指紋: 26CB 71BB B595 09C4 0153  81C4 773C 963A D51B 8CAA

Attachments (1)

catch.c (1.39 KB, text/x-csrc)
#include <sys/types.h>
#include <dirent.h>
#include "ruby.h"


static VALUE enum_folder_child(VALUE path)
{
	VALUE ary, elt;
	int i;
	DIR *dir;
	struct dirent *ent;
	
	ary = rb_ary_new();
	dir = opendir(StringValueCStr(path));
	if(!dir) rb_sys_fail(StringValueCStr(path));
	while((ent = readdir(dir))) {
		if(ent->d_name[0] == '.')
			continue;
		rb_ary_push(ary, rb_str_new2(ent->d_name));
	}
	closedir(dir);
	return ary;
}

struct find_t {
	VALUE folder;
	VALUE datadir;
	VALUE id;
};
typedef struct find_t find_t;

static void find_0(VALUE datadir, VALUE path);

static VALUE find_yield(VALUE val, find_t *find)
{
	rb_yield(find->folder);
	find_0(find->datadir, find->id);
	return Qnil;
}

void find_0(VALUE datadir, VALUE path)
{
	VALUE glob, ary, id;
	find_t find;
	int i;
	
	glob = rb_str_buf_new(RSTRING(datadir)->len
		+ RSTRING(path)->len + 1);
	rb_str_buf_append(glob, datadir);
	rb_str_buf_append(glob, path);
	/*rb_str_buf_cat(glob, "*", 1);*/
	
	ary = enum_folder_child(glob);
	for(i = 0; i < RARRAY(ary)->len; ++i) {
		id = RARRAY(ary)->ptr[i];
		id = rb_str_plus(path, id);
		rb_str_cat(id, "\\", 1);
		
		find.folder = id;
		find.datadir = datadir;
		find.id = id;
		rb_catch("prune", RUBY_METHOD_FUNC(find_yield), (VALUE)&find);
	}
}

static VALUE mbox_find(VALUE self)
{
	find_0(rb_str_new2("./"), rb_str_new2(""));
	return Qnil;
}

void Init_catch()
{
	rb_define_global_function("find", mbox_find, 0);
}

In This Thread