From b8a733d0b87ae6b1425375a0cdeec37406f6e2f6 Mon Sep 17 00:00:00 2001 From: nobu Date: Sat, 1 Mar 2008 08:59:04 +0000 Subject: * io.c (struct argf): packed ARGF stuffs. * ruby.c (proc_options): use ruby_set_inplace_mode(). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@15663 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- io.c | 371 +++++++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 250 insertions(+), 121 deletions(-) (limited to 'io.c') diff --git a/io.c b/io.c index 964d0cd121..dad62a45bc 100644 --- a/io.c +++ b/io.c @@ -125,14 +125,20 @@ static VALUE argf; static ID id_write, id_read, id_getc, id_flush, id_encode; -extern char *ruby_inplace_mode; - struct timeval rb_time_interval(VALUE); -static VALUE filename, current_file; -static int gets_lineno; -static int init_p = 0, next_p = 0; -static VALUE lineno = INT2FIX(0); +struct argf { + VALUE filename, current_file; + int gets_lineno; + int init_p, next_p; + VALUE lineno; + VALUE argv; + char *inplace; + int binmode; + rb_encoding *enc, *enc2; +}; + +#define ARGF (*(struct argf *)DATA_PTR(argf)) #ifdef _STDIO_USES_IOSTREAM /* GNU libc */ # ifdef _IO_fpos_t @@ -235,7 +241,7 @@ rb_io_check_closed(rb_io_t *fptr) static int io_fflush(rb_io_t *); -static VALUE +VALUE rb_io_get_io(VALUE io) { return rb_convert_type(io, T_FILE, "IO", "to_io"); @@ -691,9 +697,8 @@ io_fwrite(VALUE str, rb_io_t *fptr) fptr->wbuf_capa = 8192; fptr->wbuf = ALLOC_N(char, fptr->wbuf_capa); } - if ((fptr->mode & FMODE_SYNC) || - (fptr->wbuf && fptr->wbuf_capa <= fptr->wbuf_len + len) || - (fptr->mode & FMODE_TTY)) { + if ((fptr->mode & (FMODE_SYNC|FMODE_TTY)) || + (fptr->wbuf && fptr->wbuf_capa <= fptr->wbuf_len + len)) { /* xxx: use writev to avoid double write if available */ if (fptr->wbuf_len && fptr->wbuf_len+len <= fptr->wbuf_capa) { if (fptr->wbuf_capa < fptr->wbuf_off+fptr->wbuf_len+len) { @@ -990,8 +995,8 @@ rb_io_rewind(VALUE io) GetOpenFile(io, fptr); if (io_seek(fptr, 0L, 0) < 0) rb_sys_fail(fptr->path); - if (io == current_file) { - gets_lineno -= fptr->lineno; + if (io == ARGF.current_file) { + ARGF.gets_lineno -= fptr->lineno; } fptr->lineno = 0; @@ -1841,7 +1846,7 @@ rb_io_getline_fast(rb_io_t *fptr) str = io_enc_str(str, fptr); if (!fptr->enc2) ENC_CODERANGE_SET(str, cr); fptr->lineno++; - lineno = INT2FIX(fptr->lineno); + ARGF.lineno = INT2FIX(fptr->lineno); return str; } @@ -1972,7 +1977,7 @@ rb_io_getline_1(VALUE rs, long limit, VALUE io) if (!NIL_P(str)) { if (!nolimit) { fptr->lineno++; - lineno = INT2FIX(fptr->lineno); + ARGF.lineno = INT2FIX(fptr->lineno); } } @@ -2088,27 +2093,6 @@ rb_io_set_lineno(VALUE io, VALUE lineno) return lineno; } -static void -lineno_setter(VALUE val, ID id, VALUE *var) -{ - gets_lineno = NUM2INT(val); - *var = INT2FIX(gets_lineno); -} - -static VALUE -argf_set_lineno(VALUE argf, VALUE val) -{ - gets_lineno = NUM2INT(val); - lineno = INT2FIX(gets_lineno); - return Qnil; -} - -static VALUE -argf_lineno(void) -{ - return lineno; -} - /* * call-seq: * ios.readline(sep=$/) => string @@ -4727,7 +4711,8 @@ prep_stdio(FILE *f, int mode, VALUE klass, const char *path) return io; } -FILE *rb_io_stdio_file(rb_io_t *fptr) +FILE * +rb_io_stdio_file(rb_io_t *fptr) { if (!fptr->stdio_file) { fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_flags_mode(fptr->mode)); @@ -4903,22 +4888,85 @@ rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass) return io; } -static int argf_binmode = 0; -static rb_encoding *argf_enc, *argf_enc2; +static void +argf_mark(void *ptr) +{ + struct argf *p = ptr; + rb_gc_mark(p->filename); + rb_gc_mark(p->current_file); + rb_gc_mark(p->lineno); + rb_gc_mark(p->argv); +} + +static void +argf_free(void *ptr) +{ + struct argf *p = ptr; + free(p->inplace); +} + +static VALUE +argf_alloc(VALUE klass) +{ + struct argf *p; + VALUE argf = Data_Make_Struct(klass, struct argf, argf_mark, argf_free, p); + + p->filename = Qnil; + p->current_file = Qnil; + p->lineno = Qnil; + p->argv = Qnil; + return argf; +} + +#define filename ARGF.filename +#define current_file ARGF.current_file +#define gets_lineno ARGF.gets_lineno +#define init_p ARGF.init_p +#define next_p ARGF.next_p +#define lineno ARGF.lineno +#define ruby_inplace_mode ARGF.inplace +#define argf_binmode ARGF.binmode +#define argf_enc ARGF.enc +#define argf_enc2 ARGF.enc2 +#define rb_argv ARGF.argv static VALUE -argf_forward(int argc, VALUE *argv) +argf_initialize(VALUE argf, VALUE argv) +{ + rb_argv = argv; + return argf; +} + +static VALUE +argf_set_lineno(VALUE argf, VALUE val) +{ + gets_lineno = NUM2INT(val); + lineno = INT2FIX(gets_lineno); + return Qnil; +} + +static VALUE +argf_lineno(VALUE argf) +{ + return lineno; +} + +static VALUE +argf_forward(int argc, VALUE *argv, VALUE argf) { return rb_funcall3(current_file, rb_frame_this_func(), argc, argv); } +#define next_argv() argf_next_argv(argf) +#define ARGF_GENERIC_INPUT_P() \ + (current_file == rb_stdin && TYPE(current_file) != T_FILE) #define ARGF_FORWARD(argc, argv) do {\ - if (current_file == rb_stdin && TYPE(current_file) != T_FILE)\ - return argf_forward(argc, argv);\ + if (ARGF_GENERIC_INPUT_P())\ + return argf_forward(argc, argv, argf);\ } while (0) #define NEXT_ARGF_FORWARD(argc, argv) do {\ - if (!next_argv()) return Qnil;\ - ARGF_FORWARD(argc, argv);\ + if (!next_argv()) return Qnil;\ + ARGF_FORWARD(argc, argv);\ } while (0) static void @@ -4928,9 +4976,8 @@ argf_close(VALUE file) } static int -next_argv(void) +argf_next_argv(VALUE argf) { - extern VALUE rb_argv; char *fn; rb_io_t *fptr; int stdout_binmode = 0; @@ -4942,7 +4989,7 @@ next_argv(void) } if (init_p == 0) { - if (RARRAY_LEN(rb_argv) > 0) { + if (!NIL_P(rb_argv) && RARRAY_LEN(rb_argv) > 0) { next_p = 1; } else { @@ -5062,7 +5109,7 @@ argf_getline(int argc, VALUE *argv) retry: if (!next_argv()) return Qnil; - if (current_file == rb_stdin && TYPE(current_file) != T_FILE) { + if (ARGF_GENERIC_INPUT_P()) { line = rb_funcall3(current_file, rb_intern("gets"), argc, argv); } else { @@ -5085,6 +5132,22 @@ argf_getline(int argc, VALUE *argv) return line; } +static VALUE +argf_lineno_getter(ID id, VALUE *var) +{ + VALUE argf = *var; + return lineno; +} + +static void +argf_lineno_setter(VALUE val, ID id, VALUE *var) +{ + VALUE argf = *var; + int n = NUM2INT(val); + gets_lineno = n; + lineno = INT2FIX(n); +} + /* * call-seq: * gets(sep=$/) => string or nil @@ -6101,19 +6164,19 @@ rb_io_set_encoding(int argc, VALUE *argv, VALUE io) } static VALUE -argf_external_encoding(void) +argf_external_encoding(VALUE argf) { return rb_io_external_encoding(current_file); } static VALUE -argf_internal_encoding(void) +argf_internal_encoding(VALUE argf) { return rb_io_internal_encoding(current_file); } static VALUE -argf_set_encoding(int argc, VALUE *argv, VALUE io) +argf_set_encoding(int argc, VALUE *argv, VALUE argf) { rb_io_t *fptr; @@ -6124,7 +6187,7 @@ argf_set_encoding(int argc, VALUE *argv, VALUE io) GetOpenFile(current_file, fptr); argf_enc = fptr->enc; argf_enc2 = fptr->enc2; - return io; + return argf; } static VALUE @@ -6199,7 +6262,7 @@ argf_eof(void) } static VALUE -argf_read(int argc, VALUE *argv) +argf_read(int argc, VALUE *argv, VALUE argf) { VALUE tmp, str, length; long len = 0; @@ -6218,8 +6281,8 @@ argf_read(int argc, VALUE *argv) if (!next_argv()) { return str; } - if (current_file == rb_stdin && TYPE(current_file) != T_FILE) { - tmp = argf_forward(argc, argv); + if (ARGF_GENERIC_INPUT_P()) { + tmp = argf_forward(argc, argv, argf); } else { tmp = io_read(argc, argv, current_file); @@ -6246,18 +6309,19 @@ argf_read(int argc, VALUE *argv) struct argf_call_arg { int argc; VALUE *argv; + VALUE argf; }; static VALUE argf_forward_call(VALUE arg) { struct argf_call_arg *p = (struct argf_call_arg *)arg; - argf_forward(p->argc, p->argv); + argf_forward(p->argc, p->argv, p->argf); return Qnil; } static VALUE -argf_readpartial(int argc, VALUE *argv) +argf_readpartial(int argc, VALUE *argv, VALUE argf) { VALUE tmp, str, length; @@ -6271,10 +6335,11 @@ argf_readpartial(int argc, VALUE *argv) rb_str_resize(str, 0); rb_eof_error(); } - if (current_file == rb_stdin && TYPE(current_file) != T_FILE) { + if (ARGF_GENERIC_INPUT_P()) { struct argf_call_arg arg; arg.argc = argc; arg.argv = argv; + arg.argf = argf; tmp = rb_rescue2(argf_forward_call, (VALUE)&arg, RUBY_METHOD_FUNC(0), Qnil, rb_eEOFError, (VALUE)0); } @@ -6303,7 +6368,7 @@ argf_getc(void) retry: if (!next_argv()) return Qnil; - if (current_file == rb_stdin && TYPE(current_file) != T_FILE) { + if (ARGF_GENERIC_INPUT_P()) { ch = rb_funcall3(current_file, rb_intern("getc"), 0, 0); } else { @@ -6388,9 +6453,9 @@ argf_each_line(int argc, VALUE *argv, VALUE self) } static VALUE -argf_each_byte(VALUE self) +argf_each_byte(VALUE argf) { - RETURN_ENUMERATOR(self, 0, 0); + RETURN_ENUMERATOR(argf, 0, 0); for (;;) { if (!next_argv()) return Qnil; rb_block_call(current_file, rb_intern("each_byte"), 0, 0, rb_yield, 0); @@ -6399,21 +6464,27 @@ argf_each_byte(VALUE self) } static VALUE -argf_filename(void) +argf_filename(VALUE argf) { next_argv(); return filename; } static VALUE -argf_file(void) +argf_filename_getter(ID id, VALUE *var) +{ + return argf_filename(*var); +} + +static VALUE +argf_file(VALUE argf) { next_argv(); return current_file; } static VALUE -argf_binmode_m(void) +argf_binmode_m(VALUE argf) { argf_binmode = 1; next_argv(); @@ -6423,7 +6494,7 @@ argf_binmode_m(void) } static VALUE -argf_skip(void) +argf_skip(VALUE argf) { if (next_p != -1) { argf_close(current_file); @@ -6433,7 +6504,7 @@ argf_skip(void) } static VALUE -argf_close_m(void) +argf_close_m(VALUE argf) { next_argv(); argf_close(current_file); @@ -6445,7 +6516,7 @@ argf_close_m(void) } static VALUE -argf_closed(void) +argf_closed(VALUE argf) { next_argv(); ARGF_FORWARD(0, 0); @@ -6453,32 +6524,80 @@ argf_closed(void) } static VALUE -argf_to_s(void) +argf_to_s(VALUE argf) { return rb_str_new2("ARGF"); } static VALUE -opt_i_get(void) +argf_inplace_mode_get(VALUE argf) { if (!ruby_inplace_mode) return Qnil; return rb_str_new2(ruby_inplace_mode); } -static void -opt_i_set(VALUE val) +static VALUE +opt_i_get(ID id, VALUE *var) +{ + return argf_inplace_mode_get(*var); +} + +static VALUE +argf_inplace_mode_set(VALUE argf, VALUE val) { if (!RTEST(val)) { if (ruby_inplace_mode) free(ruby_inplace_mode); ruby_inplace_mode = 0; - return; } - StringValue(val); + else { + StringValue(val); + if (ruby_inplace_mode) free(ruby_inplace_mode); + ruby_inplace_mode = 0; + ruby_inplace_mode = strdup(RSTRING_PTR(val)); + } + return argf; +} + +static void +opt_i_set(VALUE val, ID id, VALUE *var) +{ + argf_inplace_mode_set(*var, val); +} + +const char * +ruby_get_inplace_mode(void) +{ + return ruby_inplace_mode; +} + +void +ruby_set_inplace_mode(const char *suffix) +{ if (ruby_inplace_mode) free(ruby_inplace_mode); ruby_inplace_mode = 0; - ruby_inplace_mode = strdup(StringValueCStr(val)); + if (suffix) ruby_inplace_mode = strdup(suffix); } +static VALUE +argf_argv(VALUE argf) +{ + return rb_argv; +} + +static VALUE +argf_argv_getter(ID id, VALUE *var) +{ + return argf_argv(*var); +} + +VALUE +rb_get_argv(void) +{ + return rb_argv; +} + +#undef rb_argv + /* * Class IO is the basis for all input and output in Ruby. * An I/O stream may be duplexed (that is, bidirectional), and @@ -6558,6 +6677,7 @@ opt_i_set(VALUE val) void Init_IO(void) { + VALUE rb_cARGF; #ifdef __CYGWIN__ #include static struct __cygwin_perfile pf[] = @@ -6627,7 +6747,6 @@ Init_IO(void) rb_define_hooked_variable("$-0", &rb_rs, 0, rb_str_setter); rb_define_hooked_variable("$\\", &rb_output_rs, 0, rb_str_setter); - rb_define_hooked_variable("$.", &lineno, 0, lineno_setter); rb_define_virtual_variable("$_", rb_lastline_get, rb_lastline_set); rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1); @@ -6722,58 +6841,68 @@ Init_IO(void) rb_define_global_const("STDOUT", rb_stdout); rb_define_global_const("STDERR", rb_stderr); + argf = argf_alloc(rb_cObject); + argf_initialize(argf, rb_ary_new()); + rb_cARGF = rb_singleton_class(argf); + + rb_include_module(rb_cARGF, rb_mEnumerable); + + rb_define_method(rb_cARGF, "initialize", argf_initialize, 1); + rb_define_method(rb_cARGF, "to_s", argf_to_s, 0); + rb_define_method(rb_cARGF, "argv", argf_argv, 0); + + rb_define_method(rb_cARGF, "fileno", argf_fileno, 0); + rb_define_method(rb_cARGF, "to_i", argf_fileno, 0); + rb_define_method(rb_cARGF, "to_io", argf_to_io, 0); + rb_define_method(rb_cARGF, "each", argf_each_line, -1); + rb_define_method(rb_cARGF, "each_line", argf_each_line, -1); + rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0); + + rb_define_method(rb_cARGF, "read", argf_read, -1); + rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1); + rb_define_method(rb_cARGF, "readlines", rb_f_readlines, -1); + rb_define_method(rb_cARGF, "to_a", rb_f_readlines, -1); + rb_define_method(rb_cARGF, "gets", rb_f_gets, -1); + rb_define_method(rb_cARGF, "readline", rb_f_readline, -1); + rb_define_method(rb_cARGF, "getc", argf_getc, 0); + rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0); + rb_define_method(rb_cARGF, "readchar", argf_readchar, 0); + rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0); + rb_define_method(rb_cARGF, "tell", argf_tell, 0); + rb_define_method(rb_cARGF, "seek", argf_seek_m, -1); + rb_define_method(rb_cARGF, "rewind", argf_rewind, 0); + rb_define_method(rb_cARGF, "pos", argf_tell, 0); + rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1); + rb_define_method(rb_cARGF, "eof", argf_eof, 0); + rb_define_method(rb_cARGF, "eof?", argf_eof, 0); + rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0); + + rb_define_method(rb_cARGF, "filename", argf_filename, 0); + rb_define_method(rb_cARGF, "path", argf_filename, 0); + rb_define_method(rb_cARGF, "file", argf_file, 0); + rb_define_method(rb_cARGF, "skip", argf_skip, 0); + rb_define_method(rb_cARGF, "close", argf_close_m, 0); + rb_define_method(rb_cARGF, "closed?", argf_closed, 0); + + rb_define_method(rb_cARGF, "lineno", argf_lineno, 0); + rb_define_method(rb_cARGF, "lineno=", argf_set_lineno, 1); + + rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0); + rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1); + + rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0); + rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0); + rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1); + rb_define_readonly_variable("$<", &argf); - argf = rb_obj_alloc(rb_cObject); - rb_extend_object(argf, rb_mEnumerable); rb_define_global_const("ARGF", argf); - rb_define_singleton_method(argf, "to_s", argf_to_s, 0); - - rb_define_singleton_method(argf, "fileno", argf_fileno, 0); - rb_define_singleton_method(argf, "to_i", argf_fileno, 0); - rb_define_singleton_method(argf, "to_io", argf_to_io, 0); - rb_define_singleton_method(argf, "each", argf_each_line, -1); - rb_define_singleton_method(argf, "each_line", argf_each_line, -1); - rb_define_singleton_method(argf, "each_byte", argf_each_byte, 0); - - rb_define_singleton_method(argf, "read", argf_read, -1); - rb_define_singleton_method(argf, "readpartial", argf_readpartial, -1); - rb_define_singleton_method(argf, "readlines", rb_f_readlines, -1); - rb_define_singleton_method(argf, "to_a", rb_f_readlines, -1); - rb_define_singleton_method(argf, "gets", rb_f_gets, -1); - rb_define_singleton_method(argf, "readline", rb_f_readline, -1); - rb_define_singleton_method(argf, "getc", argf_getc, 0); - rb_define_singleton_method(argf, "getbyte", argf_getbyte, 0); - rb_define_singleton_method(argf, "readchar", argf_readchar, 0); - rb_define_singleton_method(argf, "readbyte", argf_readbyte, 0); - rb_define_singleton_method(argf, "tell", argf_tell, 0); - rb_define_singleton_method(argf, "seek", argf_seek_m, -1); - rb_define_singleton_method(argf, "rewind", argf_rewind, 0); - rb_define_singleton_method(argf, "pos", argf_tell, 0); - rb_define_singleton_method(argf, "pos=", argf_set_pos, 1); - rb_define_singleton_method(argf, "eof", argf_eof, 0); - rb_define_singleton_method(argf, "eof?", argf_eof, 0); - rb_define_singleton_method(argf, "binmode", argf_binmode_m, 0); - - rb_define_singleton_method(argf, "filename", argf_filename, 0); - rb_define_singleton_method(argf, "path", argf_filename, 0); - rb_define_singleton_method(argf, "file", argf_file, 0); - rb_define_singleton_method(argf, "skip", argf_skip, 0); - rb_define_singleton_method(argf, "close", argf_close_m, 0); - rb_define_singleton_method(argf, "closed?", argf_closed, 0); - - rb_define_singleton_method(argf, "lineno", argf_lineno, 0); - rb_define_singleton_method(argf, "lineno=", argf_set_lineno, 1); - - rb_define_singleton_method(argf, "external_encoding", argf_external_encoding, 0); - rb_define_singleton_method(argf, "internal_encoding", argf_internal_encoding, 0); - rb_define_singleton_method(argf, "set_encoding", argf_set_encoding, -1); - - rb_global_variable(¤t_file); - rb_define_readonly_variable("$FILENAME", &filename); + rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter); + rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, 0); filename = rb_str_new2("-"); - rb_define_virtual_variable("$-i", opt_i_get, opt_i_set); + rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set); + rb_define_hooked_variable("$*", &argf, argf_argv_getter, 0); #if defined (_WIN32) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__) atexit(pipe_atexit); -- cgit v1.2.3