diff options
Diffstat (limited to 'io.c')
-rw-r--r-- | io.c | 1041 |
1 files changed, 758 insertions, 283 deletions
@@ -6,13 +6,14 @@ $Date$ created at: Fri Oct 15 18:08:59 JST 1993 - Copyright (C) 1993-1998 Yukihiro Matsumoto + Copyright (C) 1993-1999 Yukihiro Matsumoto ************************************************/ #include "ruby.h" #include "rubyio.h" #include "rubysig.h" +#include "env.h" #include <ctype.h> #include <errno.h> @@ -20,8 +21,10 @@ #if !defined(DJGPP) && !defined(NT) && !defined(__human68k__) #include <sys/ioctl.h> #endif -#if defined(HAVE_FCNTL) +#if defined(HAVE_FCNTL_H) || defined(NT) #include <fcntl.h> +#elif defined(HAVE_SYS_FCNTL_H) +#include <sys/fcntl.h> #endif #ifdef HAVE_SYS_TIME_H @@ -40,7 +43,8 @@ struct timeval { #include <sys/stat.h> -#ifdef HAVE_SYS_PARAM_H +/* EMX has sys/parm.h, but.. */ +#if defined(HAVE_SYS_PARAM_H) && !defined(__EMX__) # include <sys/param.h> #else # define NOFILE 64 @@ -55,9 +59,17 @@ struct timeval { #include <unix.mac.h> #include <compat.h> #endif + +#ifndef strdup +char *strdup(); +#endif + extern void Init_File _((void)); #ifdef __BEOS__ +# ifdef _X86_ +# define NOFILE (OPEN_MAX) +# endif #include <net/socket.h> #endif @@ -68,6 +80,7 @@ VALUE rb_eEOFError; VALUE rb_eIOError; VALUE rb_stdin, rb_stdout, rb_stderr, rb_defout; +static VALUE orig_stdin, orig_stdout, orig_stderr; VALUE rb_fs; VALUE rb_output_fs; @@ -81,9 +94,9 @@ static ID id_write; extern char *ruby_inplace_mode; -struct timeval rb_time_timeval _((VALUE)); +struct timeval rb_time_interval _((VALUE)); -static VALUE filename, file; +static VALUE filename, current_file; static int gets_lineno; static int init_p = 0, next_p = 0; static VALUE lineno; @@ -99,20 +112,19 @@ static VALUE lineno; #elif defined(__BEOS__) # define ReadDataPending(fp) (fp->_state._eof == 0) #elif defined(USE_CWGUSI) -# define ReadDataPending(fp) (fp->state.eof == 0) +# define READ_DATA_PENDING(fp) (fp->state.eof == 0) #else /* requires systems own version of the ReadDataPending() */ extern int ReadDataPending(); # define READ_DATA_PENDING(fp) ReadDataPending(fp) #endif -#ifndef USE_THREAD -# define READ_CHECK(fp) 0 -#else -# define READ_CHECK(fp) do {\ - if (!READ_DATA_PENDING(fp)) rb_thread_wait_fd(fileno(fp));\ +#define READ_CHECK(fp) do {\ + if (!READ_DATA_PENDING(fp)) {\ + rb_thread_wait_fd(fileno(fp));\ + rb_io_check_closed(fptr);\ + }\ } while(0) -#endif void rb_eof_error() @@ -124,6 +136,9 @@ void rb_io_check_closed(fptr) OpenFile *fptr; { + if (!fptr) { + rb_raise(rb_eIOError, "uninitialized stream"); + } if (fptr->f == NULL && fptr->f2 == NULL) rb_raise(rb_eIOError, "closed stream"); } @@ -146,9 +161,18 @@ rb_io_check_writable(fptr) } } +void +rb_read_check(fp) + FILE *fp; +{ + if (!READ_DATA_PENDING(fp)) { + rb_thread_wait_fd(fileno(fp)); + } +} + /* writing functions */ -VALUE -rb_io_write(io, str) +static VALUE +io_write(io, str) VALUE io, str; { OpenFile *fptr; @@ -182,7 +206,7 @@ rb_io_write(io, str) rb_sys_fail(fptr->path); #else n = fwrite(RSTRING(str)->ptr, 1, RSTRING(str)->len, f); - if (n == 0 || ferror(f)) { + if (ferror(f)) { rb_sys_fail(fptr->path); } #endif @@ -193,6 +217,13 @@ rb_io_write(io, str) return INT2FIX(n); } +VALUE +rb_io_write(io, str) + VALUE io, str; +{ + return rb_funcall(io, id_write, 1, str); +} + static VALUE rb_io_addstr(io, str) VALUE io, str; @@ -226,7 +257,7 @@ rb_io_tell(io) GetOpenFile(io, fptr); pos = ftell(fptr->f); - if (ferror(fptr->f) != 0) rb_sys_fail(fptr->path); + if (ferror(fptr->f)) rb_sys_fail(fptr->path); return rb_int2inum(pos); } @@ -290,11 +321,8 @@ rb_io_eof(io) GetOpenFile(io, fptr); rb_io_check_readable(fptr); - if (READ_DATA_PENDING(fptr->f)) return Qfalse; -#if 0 if (feof(fptr->f)) return Qtrue; - return Qfalse; -#else + if (READ_DATA_PENDING(fptr->f)) return Qfalse; READ_CHECK(fptr->f); TRAP_BEG; ch = getc(fptr->f); @@ -305,7 +333,6 @@ rb_io_eof(io) return Qfalse; } return Qtrue; -#endif } static VALUE @@ -375,13 +402,17 @@ read_all(port) GetOpenFile(port, fptr); rb_io_check_readable(fptr); + if (feof(fptr->f)) return Qnil; if (fstat(fileno(fptr->f), &st) == 0 && S_ISREG(st.st_mode) #ifdef __BEOS__ && (st.st_dev > 3) #endif ) { - if (st.st_size == 0) return rb_str_new(0, 0); + if (st.st_size == 0) { + getc(fptr->f); /* force EOF */ + return rb_str_new(0, 0); + } else { long pos = ftell(fptr->f); if (st.st_size > pos && pos >= 0) { @@ -395,9 +426,9 @@ read_all(port) TRAP_BEG; n = fread(RSTRING(str)->ptr+bytes, 1, siz-bytes, fptr->f); TRAP_END; - if (n <= 0) { - if (ferror(fptr->f)) rb_sys_fail(fptr->path); - return rb_str_new(0,0); + if (n == 0) { + if (feof(fptr->f)) return Qnil; + rb_sys_fail(fptr->path); } bytes += n; if (bytes < siz) break; @@ -412,7 +443,7 @@ read_all(port) } static VALUE -rb_io_read(argc, argv, io) +io_read(argc, argv, io) int argc; VALUE *argv; VALUE io; @@ -430,15 +461,16 @@ rb_io_read(argc, argv, io) GetOpenFile(io, fptr); rb_io_check_readable(fptr); + if (feof(fptr->f)) return Qnil; str = rb_str_new(0, len); READ_CHECK(fptr->f); TRAP_BEG; n = fread(RSTRING(str)->ptr, 1, len, fptr->f); TRAP_END; - if (n <= 0) { - if (ferror(fptr->f)) rb_sys_fail(fptr->path); - return Qnil; + if (n == 0) { + if (feof(fptr->f)) return Qnil; + rb_sys_fail(fptr->path); } RSTRING(str)->len = n; RSTRING(str)->ptr[n] = '\0'; @@ -522,7 +554,7 @@ rb_io_gets_internal(argc, argv, io) c = getc(f); TRAP_END; if (c == EOF) { - if (errno == EINTR) continue; + if (ferror(f) && errno == EINTR) continue; break; } if ((*bp++ = c) == newline) break; @@ -611,7 +643,7 @@ rb_io_gets(io) c = getc(f); TRAP_END; if (c == EOF) { - if (errno == EINTR) continue; + if (ferror(f) && errno == EINTR) continue; break; } if ((*bp++ = c) == '\n') break; @@ -691,6 +723,21 @@ lineno_setter(val, id, var) } static VALUE +argf_set_lineno(argf, val) + VALUE argf, val; +{ + gets_lineno = NUM2INT(val); + lineno = INT2FIX(gets_lineno); + return Qnil; +} + +static VALUE +argf_lineno() +{ + return lineno; +} + +static VALUE rb_io_readline(argc, argv, io) int argc; VALUE *argv; @@ -730,7 +777,7 @@ rb_io_each_line(argc, argv, io) while (!NIL_P(str = rb_io_gets_internal(argc, argv, io))) { rb_yield(str); } - return Qnil; + return io; } static VALUE @@ -753,7 +800,7 @@ rb_io_each_byte(io) if (c == EOF) break; rb_yield(INT2FIX(c & 0xff)); } - if (ferror(f) != 0) rb_sys_fail(fptr->path); + if (ferror(f)) rb_sys_fail(fptr->path); return Qnil; } @@ -775,12 +822,28 @@ rb_io_getc(io) TRAP_END; if (c == EOF) { - if (ferror(f) != 0) rb_sys_fail(fptr->path); + if (ferror(f)) rb_sys_fail(fptr->path); return Qnil; } return INT2FIX(c & 0xff); } +int +rb_getc(f) + FILE *f; +{ + int c; + + if (!READ_DATA_PENDING(f)) { + rb_thread_wait_fd(fileno(f)); + } + TRAP_BEG; + c = getc(f); + TRAP_END; + + return c; +} + static VALUE rb_io_readchar(io) VALUE io; @@ -830,18 +893,17 @@ fptr_finalize(fptr) if (fptr->f2 != NULL) { fclose(fptr->f2); } - if (fptr->pid) { - rb_syswait(fptr->pid); - fptr->pid = 0; - } } static void rb_io_fptr_close(fptr) OpenFile *fptr; { + int fd; + if (fptr->f == NULL && fptr->f2 == NULL) return; + fd = fileno(fptr->f); if (fptr->finalize) { (*fptr->finalize)(fptr); } @@ -849,6 +911,7 @@ rb_io_fptr_close(fptr) fptr_finalize(fptr); } fptr->f = fptr->f2 = NULL; + rb_thread_fd_close(fd); } void @@ -870,6 +933,10 @@ rb_io_close(io) GetOpenFile(io, fptr); rb_io_fptr_close(fptr); + if (fptr->pid) { + rb_syswait(fptr->pid); + fptr->pid = 0; + } return Qnil; } @@ -898,6 +965,7 @@ rb_io_close_read(io) VALUE io; { OpenFile *fptr; + int n; rb_secure(4); GetOpenFile(io, fptr); @@ -907,10 +975,11 @@ rb_io_close_read(io) if (fptr->f2 == 0) { return rb_io_close(io); } - fclose(fptr->f); + n = fclose(fptr->f); fptr->mode &= ~FMODE_READABLE; fptr->f = fptr->f2; fptr->f2 = 0; + if (n != 0) rb_sys_fail(fptr->path); return Qnil; } @@ -920,6 +989,7 @@ rb_io_close_write(io) VALUE io; { OpenFile *fptr; + int n; rb_secure(4); GetOpenFile(io, fptr); @@ -929,9 +999,10 @@ rb_io_close_write(io) if (fptr->f2 == 0) { return rb_io_close(io); } - fclose(fptr->f2); + n = fclose(fptr->f2); fptr->f2 = 0; fptr->mode &= ~FMODE_WRITABLE; + if (n != 0) rb_sys_fail(fptr->path); return Qnil; } @@ -952,9 +1023,9 @@ rb_io_syswrite(io, str) rb_io_check_writable(fptr); f = GetWriteFile(fptr); -#ifdef USE_THREAD - rb_thread_fd_writable(fileno(f)); -#endif + if (!rb_thread_fd_writable(fileno(f))) { + rb_io_check_closed(fptr); + } n = write(fileno(f), RSTRING(str)->ptr, RSTRING(str)->len); if (n == -1) rb_sys_fail(fptr->path); @@ -976,15 +1047,15 @@ rb_io_sysread(io, len) str = rb_str_new(0, ilen); -#ifdef USE_THREAD rb_thread_wait_fd(fileno(fptr->f)); -#endif TRAP_BEG; n = read(fileno(fptr->f), RSTRING(str)->ptr, RSTRING(str)->len); TRAP_END; if (n == -1) rb_sys_fail(fptr->path); - if (n == 0) rb_eof_error(); + if (n == 0 && ilen > 0) { + rb_eof_error(); + } RSTRING(str)->len = n; RSTRING(str)->ptr[n] = '\0'; @@ -997,7 +1068,8 @@ VALUE rb_io_binmode(io) VALUE io; { -#if defined(NT) || defined(DJGPP) || defined(__CYGWIN32__) || defined(__human68k__) || defined(USE_CWGUSI) +#if defined(NT) || defined(DJGPP) || defined(__CYGWIN32__)\ + || defined(__human68k__) || defined(USE_CWGUSI) || defined(__EMX__) OpenFile *fptr; GetOpenFile(io, fptr); @@ -1014,9 +1086,9 @@ rb_io_binmode(io) rb_sys_fail(fptr->path); # else /* USE_CWGUSI */ if (fptr->f) - fptr->f->mode.binrb_ary_io = 1; + fptr->f->mode.binary_io = 1; if (fptr->f2) - fptr->f2->mode.binrb_ary_io = 1; + fptr->f2->mode.binary_io = 1; # endif /* USE_CWGUSI */ #endif @@ -1027,7 +1099,7 @@ rb_io_binmode(io) int rb_io_mode_flags(mode) - char *mode; + const char *mode; { int flags = 0; @@ -1042,7 +1114,8 @@ rb_io_mode_flags(mode) flags |= FMODE_WRITABLE; break; default: - rb_raise(rb_eArgError, "illegal access mode"); + error: + rb_raise(rb_eArgError, "illegal access mode %s", mode); } if (mode[1] == 'b') { @@ -1052,48 +1125,193 @@ rb_io_mode_flags(mode) if (mode[1] == '+') { flags |= FMODE_READWRITE; + if (mode[2] != 0) goto error; + } + else if (mode[1] != 0) goto error; + + return flags; +} + +static int +rb_io_mode_flags2(mode) + int mode; +{ + int flags; + + switch (mode & (O_RDONLY|O_WRONLY|O_RDWR)) { + case O_RDONLY: + flags = FMODE_READABLE; + break; + case O_WRONLY: + flags = FMODE_WRITABLE; + break; + case O_RDWR: + flags = FMODE_WRITABLE|FMODE_READABLE; + break; } +#ifdef O_BINARY + if (mode & O_BINARY) { + flags |= FMODE_BINMODE; + } +#endif + return flags; } +static char* +rb_io_flags_mode(flags) + int flags; +{ + static char mode[4]; + char *p = mode; + + switch (flags & (O_RDONLY|O_WRONLY|O_RDWR)) { + case O_RDONLY: + *p++ = 'r'; + break; + case O_WRONLY: + *p++ = 'w'; + break; + case O_RDWR: + *p++ = 'w'; + *p++ = '+'; + break; + } + *p++ = '\0'; +#ifdef O_BINARY + if (flags & O_BINARY) { + if (mode[1] == '+') { + mode[1] = 'b'; mode[2] = '+'; mode[3] = '\0'; + } + else { + mode[1] = 'b'; mode[2] = '\0'; + } + } +#endif + return mode; +} + +static int +rb_open(fname, flag, mode) + char *fname; + int flag; + unsigned int mode; +{ + int fd; + + fd = open(fname, flag, mode); + if (fd < 0) { + if (errno == EMFILE || errno == ENFILE) { + rb_gc(); + fd = open(fname, flag, mode); + } + if (fd < 0) { + rb_sys_fail(fname); + } + } + return fd; +} + FILE * rb_fopen(fname, mode) - char *fname; - char *mode; + const char *fname; + const char *mode; { - FILE *f; + FILE *file; - f = fopen(fname, mode); - if (f == NULL) { + file = fopen(fname, mode); + if (file == NULL) { if (errno == EMFILE || errno == ENFILE) { rb_gc(); - f = fopen(fname, mode); + file = fopen(fname, mode); } - if (f == NULL) { + if (file == NULL) { rb_sys_fail(fname); } } - return f; + return file; } FILE * rb_fdopen(fd, mode) int fd; - char *mode; + const char *mode; { - FILE *f; + FILE *file; - f = fdopen(fd, mode); - if (f == NULL) { - if (errno == EMFILE) { - f = fdopen(fd, mode); + file = fdopen(fd, mode); + if (file == NULL) { + if (errno == EMFILE || errno == ENFILE) { + rb_gc(); + file = fdopen(fd, mode); } - if (f == NULL) { + if (file == NULL) { rb_sys_fail(0); } } - return f; + return file; +} + +static VALUE +rb_file_open_internal(klass, fname, mode) + VALUE klass; + const char *fname, *mode; +{ + OpenFile *fptr; + NEWOBJ(port, struct RFile); + OBJSETUP(port, klass, T_FILE); + MakeOpenFile(port, fptr); + + fptr->mode = rb_io_mode_flags(mode); + fptr->f = rb_fopen(fname, mode); + fptr->path = strdup(fname); + + return (VALUE)port; +} + +VALUE +rb_file_open(fname, mode) + const char *fname, *mode; +{ + return rb_file_open_internal(rb_cFile, fname, mode); +} + +VALUE +rb_file_sysopen_internal(klass, fname, flags, mode) + VALUE klass; + char *fname; + int flags, mode; +{ +#ifdef USE_CWGUSI + if (mode != 0666) { + rb_warn("can't specify file mode on this platform"); + } + return rb_file_open_internal(klass, fname, rb_io_flags_mode(flags)); +#else + OpenFile *fptr; + int fd; + char *m; + NEWOBJ(port, struct RFile); + OBJSETUP(port, klass, T_FILE); + MakeOpenFile(port, fptr); + + fd = rb_open(fname, flags, mode); + m = rb_io_flags_mode(flags); + fptr->mode = rb_io_mode_flags2(flags); + fptr->f = rb_fdopen(fd, m); + fptr->path = strdup(fname); + + return (VALUE)port; +#endif +} + +VALUE +rb_file_sysopen(fname, flags, mode) + const char *fname; + int flags, mode; +{ + return rb_file_sysopen_internal(rb_cFile, fname, flags, mode); } #if defined (NT) || defined(DJGPP) || defined(__CYGWIN32__) || defined(__human68k__) @@ -1205,7 +1423,6 @@ pipe_open(pname, mode) fptr->f2 = f; rb_io_unbuffered(fptr); } - rb_obj_call_init((VALUE)port); return (VALUE)port; } #else @@ -1242,8 +1459,6 @@ pipe_open(pname, mode) } if (doexec) { - extern char *ruby_sourcefile; - extern int ruby_sourceline; int fd; for (fd = 3; fd < NOFILE; fd++) @@ -1257,11 +1472,7 @@ pipe_open(pname, mode) case -1: /* fork failed */ if (errno == EAGAIN) { -#ifdef USE_THREAD rb_thread_sleep(1); -#else - sleep(1); -#endif goto retry; } close(pr[0]); close(pw[1]); @@ -1293,7 +1504,6 @@ pipe_open(pname, mode) fptr->finalize = pipe_finalize; pipe_add_fptr(fptr); #endif - rb_obj_call_init((VALUE)port); return (VALUE)port; } } @@ -1311,7 +1521,7 @@ rb_io_s_popen(argc, argv, self) VALUE self; { char *mode; - VALUE pname, pmode; + VALUE pname, pmode, port; if (rb_scan_args(argc, argv, "11", &pname, &pmode) == 1) { mode = "r"; @@ -1325,19 +1535,45 @@ rb_io_s_popen(argc, argv, self) rb_raise(rb_eArgError, "illegal access mode"); } Check_SafeStr(pname); - return pipe_open(RSTRING(pname)->ptr, mode); + port = pipe_open(RSTRING(pname)->ptr, mode); + if (NIL_P(port)) return Qnil; + return port; } static VALUE -rb_io_open(fname, mode) - char *fname, *mode; +rb_file_s_open(argc, argv, klass) + int argc; + VALUE *argv; + VALUE klass; { - if (fname[0] == '|') { - return pipe_open(fname+1, mode); + VALUE fname, vmode, file, perm; + char *path, *mode; + + rb_scan_args(argc, argv, "12", &fname, &vmode, &perm); + Check_SafeStr(fname); + path = RSTRING(fname)->ptr; + + if (FIXNUM_P(vmode)) { + int flags = FIX2INT(vmode); + int fmode = NIL_P(perm) ? 0666 : FIX2INT(perm); + + file = rb_file_sysopen_internal(klass, path, flags, fmode); } else { - return rb_file_open(fname, mode); + if (!NIL_P(vmode)) { + mode = STR2CSTR(vmode); + } + else { + mode = "r"; + } + file = rb_file_open_internal(klass, RSTRING(fname)->ptr, mode); + } + + if (rb_iterator_p()) { + return rb_ensure(rb_yield, file, rb_io_close, file); } + + return file; } static VALUE @@ -1346,24 +1582,32 @@ rb_f_open(argc, argv) VALUE *argv; { char *mode; - VALUE pname, pmode; + VALUE pname, pmode, perm; VALUE port; - rb_scan_args(argc, argv, "11", &pname, &pmode); + rb_scan_args(argc, argv, "12", &pname, &pmode, &perm); Check_SafeStr(pname); + if (RSTRING(pname)->ptr[0] != '|') /* open file */ + return rb_file_s_open(argc, argv, rb_cFile); + + /* open pipe */ if (NIL_P(pmode)) { mode = "r"; } + else if (FIXNUM_P(pmode)) { + mode = rb_io_flags_mode(FIX2INT(pmode)); + } else { int len; mode = STR2CSTR(pmode); len = strlen(mode); if (len == 0 || len > 3) - rb_raise(rb_eArgError, "illegal access mode"); + rb_raise(rb_eArgError, "illegal access mode %s", mode); } - port = rb_io_open(RSTRING(pname)->ptr, mode); + port = pipe_open(RSTRING(pname)->ptr+1, mode); + if (NIL_P(port)) return Qnil; if (rb_iterator_p()) { return rb_ensure(rb_yield, port, rb_io_close, port); } @@ -1372,6 +1616,18 @@ rb_f_open(argc, argv) } static VALUE +rb_io_open(fname, mode) + char *fname, *mode; +{ + if (fname[0] == '|') { + return pipe_open(fname+1, mode); + } + else { + return rb_file_open(fname, mode); + } +} + +static VALUE rb_io_get_io(io) VALUE io; { @@ -1393,7 +1649,7 @@ rb_io_mode_string(fptr) } } -VALUE +static VALUE rb_io_reopen(io, nfile) VALUE io, nfile; { @@ -1406,12 +1662,14 @@ rb_io_reopen(io, nfile) nfile = rb_io_get_io(nfile); GetOpenFile(nfile, orig); + if (fptr == orig) return io; if (orig->f2) { fflush(orig->f2); } else if (orig->mode & FMODE_WRITABLE) { fflush(orig->f); } + rb_thread_fd_close(fileno(fptr->f)); /* copy OpenFile structure */ fptr->mode = orig->mode; @@ -1458,6 +1716,56 @@ rb_io_reopen(io, nfile) } static VALUE +rb_file_reopen(argc, argv, file) + int argc; + VALUE *argv; + VALUE file; +{ + VALUE fname, nmode; + char *mode; + OpenFile *fptr; + + rb_secure(4); + if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 1) { + if (TYPE(fname) == T_FILE) { /* fname must be IO */ + return rb_io_reopen(file, fname); + } + } + + Check_SafeStr(fname); + if (!NIL_P(nmode)) { + mode = STR2CSTR(nmode); + } + else { + mode = "r"; + } + + GetOpenFile(file, fptr); + if (fptr->path) free(fptr->path); + fptr->path = strdup(RSTRING(fname)->ptr); + fptr->mode = rb_io_mode_flags(mode); + if (!fptr->f) { + fptr->f = rb_fopen(RSTRING(fname)->ptr, mode); + if (fptr->f2) { + fclose(fptr->f2); + fptr->f2 = NULL; + } + return file; + } + + if (freopen(RSTRING(fname)->ptr, mode, fptr->f) == NULL) { + rb_sys_fail(fptr->path); + } + if (fptr->f2) { + if (freopen(RSTRING(fname)->ptr, "w", fptr->f2) == NULL) { + rb_sys_fail(fptr->path); + } + } + + return file; +} + +static VALUE rb_io_clone(io) VALUE io; { @@ -1466,7 +1774,7 @@ rb_io_clone(io) char *mode; NEWOBJ(obj, struct RFile); - OBJSETUP(obj, CLASS_OF(io), T_FILE); + CLONESETUP(obj, io); GetOpenFile(io, orig); MakeOpenFile(obj, fptr); @@ -1601,7 +1909,7 @@ rb_io_putc(io, ch) rb_io_check_writable(fptr); f = GetWriteFile(fptr); - if (fputc(c, f) == EOF || ferror(f)) + if (fputc(c, f) == EOF) rb_sys_fail(fptr->path); if (fptr->mode & FMODE_SYNC) fflush(f); @@ -1725,38 +2033,135 @@ rb_io_defset(val, id) VALUE val; ID id; { - if (TYPE(val) == T_STRING) { - val = rb_io_open(RSTRING(val)->ptr, "w"); - } if (!rb_respond_to(val, id_write)) { - rb_raise(rb_eTypeError, "$< must have write method, %s given", + rb_raise(rb_eTypeError, "$> must have write method, %s given", rb_class2name(CLASS_OF(val))); } rb_defout = val; } +static int +rb_dup(orig) + int orig; +{ + int fd; + + fd = dup(orig); + if (fd < 0) { + if (errno == EMFILE || errno == ENFILE) { + rb_gc(); + fd = dup(orig); + } + if (fd < 0) { + rb_sys_fail(0); + } + } + return fd; +} + static void -rb_io_stdio_set(val, id, var) +set_stdin(val, id, var) VALUE val; ID id; VALUE *var; { OpenFile *fptr; int fd; + char *mode; + if (val == *var) return; if (TYPE(val) != T_FILE) { - rb_raise(rb_eTypeError, "%s must be IO object", rb_id2name(id)); + *var = val; + return; } + if (TYPE(*var) != T_FILE) { + *var = orig_stdin; + } + + GetOpenFile(val, fptr); + rb_io_check_readable(fptr); + GetOpenFile(*var, fptr); - fd = fileno(fptr->f); + mode = rb_io_mode_string(fptr); + fd = rb_dup(fileno(fptr->f)); + if (fileno(fptr->f) > 2) { + fclose(fptr->f); + } + fptr->f = rb_fdopen(fd, mode); + GetOpenFile(val, fptr); - if (fd == 0) { - rb_io_check_readable(fptr); + dup2(fileno(fptr->f), 0); + fclose(fptr->f); + fptr->f = stdin; + + *var = val; +} + +static void +set_outfile(val, var, orig, stdf) + VALUE val; + VALUE *var; + VALUE orig; + FILE *stdf; +{ + OpenFile *fptr; + FILE *f; + int fd; + char *mode; + + if (val == *var) return; + + if (TYPE(*var) == T_FILE) { + rb_io_flush(*var); } - else { - rb_io_check_writable(fptr); + if (TYPE(val) != T_FILE) { + *var = val; + return; + } + if (TYPE(*var) != T_FILE) { + *var = orig; + } + + GetOpenFile(val, fptr); + rb_io_check_writable(fptr); + + GetOpenFile(*var, fptr); + mode = rb_io_mode_string(fptr); + f = GetWriteFile(fptr); + fd = rb_dup(fileno(f)); + if (fileno(f) > 2) { + fclose(fptr->f); } - rb_io_reopen(*var, val); + f = rb_fdopen(fd, mode); + if (fptr->f2) fptr->f2 = f; + else fptr->f = f; + + GetOpenFile(val, fptr); + f = GetWriteFile(fptr); + dup2(fileno(f), fileno(stdf)); + fclose(f); + if (fptr->f2) fptr->f2 = stdf; + else fptr->f = stdf; + + *var = val; +} + +static void +set_stdout(val, id, var) + VALUE val; + ID id; + VALUE *var; +{ + set_outfile(val, var, orig_stdout, stdout); +} + +static void +set_stderr(val, id, var) + VALUE val; + ID id; + VALUE *var; +{ + set_outfile(val, var, orig_stderr, stderr); } static VALUE @@ -1772,7 +2177,6 @@ prep_stdio(f, mode, klass) MakeOpenFile(io, fp); fp->f = f; fp->mode = mode; - rb_obj_call_init((VALUE)io); return (VALUE)io; } @@ -1793,6 +2197,28 @@ rb_io_s_new(argc, argv, klass) return prep_stdio(rb_fdopen(NUM2INT(fnum), m), rb_io_mode_flags(m), klass); } +static int binmode = 0; + +static VALUE +argf_forward() +{ + return rb_funcall3(current_file, ruby_frame->last_func, + ruby_frame->argc, ruby_frame->argv); +} + +static VALUE +argf_binmode() +{ + if (TYPE(current_file) != T_FILE) { + argf_forward(); + } + else { + rb_io_binmode(current_file); + } + binmode = 1; + return argf; +} + static int next_argv() { @@ -1805,7 +2231,7 @@ next_argv() } else { next_p = -1; - file = rb_stdin; + current_file = rb_stdin; } init_p = 1; gets_lineno = 0; @@ -1816,9 +2242,9 @@ next_argv() next_p = 0; if (RARRAY(rb_argv)->len > 0) { filename = rb_ary_shift(rb_argv); - fn = RSTRING(filename)->ptr; - if (RSTRING(filename)->len == 1 && fn[0] == '-') { - file = rb_stdin; + fn = STR2CSTR(filename); + if (strlen(fn) == 1 && fn[0] == '-') { + current_file = rb_stdin; if (ruby_inplace_mode) { rb_defout = rb_stdout; } @@ -1843,7 +2269,7 @@ next_argv() rb_str_cat(str, ruby_inplace_mode, strlen(ruby_inplace_mode)); #endif -#if defined(MSDOS) || defined(__BOW__) || defined(__CYGWIN32__) || defined(NT) || defined(__human68k__) +#if defined(MSDOS) || defined(__BOW__) || defined(__CYGWIN32__) || defined(NT) || defined(__human68k__) || defined(__EMX__) (void)fclose(fr); (void)unlink(RSTRING(str)->ptr); (void)rename(fn, RSTRING(str)->ptr); @@ -1870,8 +2296,7 @@ next_argv() #endif } fw = rb_fopen(fn, "w"); -#if !defined(MSDOS) && !defined(__CYGWIN32__) && !(NT) && !defined(__human68k__)\ - && !defined(USE_CWGUSI) && !defined(__BEOS__) +#if !defined(MSDOS) && !defined(__CYGWIN32__) && !(NT) && !defined(__human68k__) && !defined(USE_CWGUSI) && !defined(__BEOS__) && !defined(__EMX__) fstat(fileno(fw), &st2); fchmod(fileno(fw), st.st_mode); if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) { @@ -1880,8 +2305,9 @@ next_argv() #endif rb_defout = prep_stdio(fw, FMODE_WRITABLE, rb_cFile); } - file = prep_stdio(fr, FMODE_READABLE, rb_cFile); + current_file = prep_stdio(fr, FMODE_READABLE, rb_cFile); } + if (binmode) rb_io_binmode(current_file); } else { init_p = 0; @@ -1891,6 +2317,16 @@ next_argv() return Qtrue; } +static void +any_close(file) + VALUE file; +{ + if (TYPE(file) == T_FILE) + rb_io_close(file); + else + rb_funcall3(file, rb_intern("close"), 0, 0); +} + static VALUE rb_f_gets_internal(argc, argv) int argc; @@ -1900,9 +2336,17 @@ rb_f_gets_internal(argc, argv) retry: if (!next_argv()) return Qnil; - line = rb_io_gets_internal(argc, argv, file); + if (TYPE(current_file) != T_FILE) { + line = rb_funcall3(current_file, rb_intern("gets"), argc, argv); + } + if (argc == 0 && rb_rs == rb_default_rs) { + line = rb_io_gets(current_file); + } + else { + line = rb_io_gets_internal(argc, argv, current_file); + } if (NIL_P(line) && next_p != -1) { - rb_io_close(file); + any_close(current_file); next_p = 1; goto retry; } @@ -1919,7 +2363,7 @@ rb_f_gets(argc, argv) { VALUE line = rb_f_gets_internal(argc, argv); - if (!NIL_P(line)) rb_lastline_set(line); + rb_lastline_set(line); return line; } @@ -1928,16 +2372,20 @@ rb_gets() { VALUE line; + if (rb_rs != rb_default_rs) { + return rb_f_gets(0, 0); + } + retry: if (!next_argv()) return Qnil; - line = rb_io_gets(file); + line = rb_io_gets(current_file); if (NIL_P(line) && next_p != -1) { - rb_io_close(file); + any_close(current_file); next_p = 1; goto retry; } + rb_lastline_set(line); if (!NIL_P(line)) { - rb_lastline_set(line); gets_lineno++; lineno = INT2FIX(gets_lineno); } @@ -1960,76 +2408,13 @@ rb_f_readline(argc, argv) } static VALUE -rb_f_tell() -{ - return rb_io_tell(file); -} - -static VALUE -rb_f_seek(self, offset, ptrname) - VALUE self, offset, ptrname; -{ - if (!next_argv()) { - rb_raise(rb_eArgError, "no stream to seek"); - } - - return rb_io_seek(file, offset, ptrname); -} - -static VALUE -rb_f_set_pos(self, offset) - VALUE self, offset; -{ - if (!next_argv()) { - rb_raise(rb_eArgError, "no stream to pos"); - } - - return rb_io_set_pos(file, offset); -} - -static VALUE -rb_f_rewind() -{ - return rb_io_rewind(file); -} - -static VALUE -rb_f_eof() -{ - if (init_p == 0 && !next_argv()) - return Qtrue; - if (rb_io_eof(file)) { - next_p = 1; - return Qtrue; - } - return Qfalse; -} - -static VALUE rb_f_getc() { + rb_warn("getc is obsolete; use STDIN.getc instead"); return rb_io_getc(rb_stdin); } static VALUE -rb_f_ungetc(self, c) - VALUE self, c; -{ - return rb_io_ungetc(rb_stdin, c); -} - -static VALUE -rb_f_readchar() -{ - VALUE c = rb_f_getc(); - - if (NIL_P(c)) { - rb_eof_error(); - } - return c; -} - -static VALUE rb_f_readlines(argc, argv) int argc; VALUE *argv; @@ -2064,6 +2449,7 @@ rb_f_backquote(obj, str) Check_SafeStr(str); port = pipe_open(RSTRING(str)->ptr, "r"); + if (NIL_P(port)) return rb_str_new(0,0); result = read_all(port); rb_io_close(port); @@ -2075,9 +2461,6 @@ rb_f_backquote(obj, str) #ifdef HAVE_SYS_SELECT_H #include <sys/select.h> #endif -#ifdef NT -#define select(v, w, x, y, z) (-1) /* anytime fail */ -#endif static VALUE rb_f_select(argc, argv, obj) @@ -2099,7 +2482,7 @@ rb_f_select(argc, argv, obj) tp = NULL; } else { - timerec = rb_time_timeval(timeout); + timerec = rb_time_interval(timeout); tp = &timerec; } @@ -2109,9 +2492,7 @@ rb_f_select(argc, argv, obj) rp = &rset; FD_ZERO(rp); for (i=0; i<RARRAY(read)->len; i++) { - VALUE io = rb_io_get_io(RARRAY(read)->ptr[i]); - - GetOpenFile(io, fptr); + GetOpenFile(rb_io_get_io(RARRAY(read)->ptr[i]), fptr); FD_SET(fileno(fptr->f), rp); if (READ_DATA_PENDING(fptr->f)) { /* check for buffered data */ pending++; @@ -2132,9 +2513,7 @@ rb_f_select(argc, argv, obj) wp = &wset; FD_ZERO(wp); for (i=0; i<RARRAY(write)->len; i++) { - VALUE io = rb_io_get_io(RARRAY(write)->ptr[i]); - - GetOpenFile(io, fptr); + GetOpenFile(rb_io_get_io(RARRAY(write)->ptr[i]), fptr); FD_SET(fileno(fptr->f), wp); if (max < fileno(fptr->f)) max = fileno(fptr->f); if (fptr->f2) { @@ -2151,9 +2530,7 @@ rb_f_select(argc, argv, obj) ep = &eset; FD_ZERO(ep); for (i=0; i<RARRAY(except)->len; i++) { - VALUE io = rb_io_get_io(RARRAY(except)->ptr[i]); - - GetOpenFile(io, fptr); + GetOpenFile(rb_io_get_io(RARRAY(except)->ptr[i]), fptr); FD_SET(fileno(fptr->f), ep); if (max < fileno(fptr->f)) max = fileno(fptr->f); if (fptr->f2) { @@ -2167,24 +2544,10 @@ rb_f_select(argc, argv, obj) max++; -#ifdef USE_THREAD n = rb_thread_select(max, rp, wp, ep, tp); if (n < 0) { rb_sys_fail(0); } -#else - retry: - TRAP_BEG; - n = select(max, rp, wp, ep, tp); - TRAP_END; - if (n < 0) { - if (errno != EINTR) { - rb_sys_fail(0); - } - if (tp == NULL) goto retry; - interrupt_flag = 1; - } -#endif if (!pending && n == 0) return Qnil; /* returns nil on timeout */ res = rb_ary_new2(3); @@ -2196,7 +2559,7 @@ rb_f_select(argc, argv, obj) if (rp) { list = RARRAY(res)->ptr[0]; for (i=0; i< RARRAY(read)->len; i++) { - GetOpenFile(RARRAY(read)->ptr[i], fptr); + GetOpenFile(rb_io_get_io(RARRAY(read)->ptr[i]), fptr); if (FD_ISSET(fileno(fptr->f), rp) || FD_ISSET(fileno(fptr->f), &pset)) { rb_ary_push(list, RARRAY(read)->ptr[i]); @@ -2207,7 +2570,7 @@ rb_f_select(argc, argv, obj) if (wp) { list = RARRAY(res)->ptr[1]; for (i=0; i< RARRAY(write)->len; i++) { - GetOpenFile(RARRAY(write)->ptr[i], fptr); + GetOpenFile(rb_io_get_io(RARRAY(write)->ptr[i]), fptr); if (FD_ISSET(fileno(fptr->f), wp)) { rb_ary_push(list, RARRAY(write)->ptr[i]); } @@ -2220,7 +2583,7 @@ rb_f_select(argc, argv, obj) if (ep) { list = RARRAY(res)->ptr[2]; for (i=0; i< RARRAY(except)->len; i++) { - GetOpenFile(RARRAY(except)->ptr[i], fptr); + GetOpenFile(rb_io_get_io(RARRAY(except)->ptr[i]), fptr); if (FD_ISSET(fileno(fptr->f), ep)) { rb_ary_push(list, RARRAY(except)->ptr[i]); } @@ -2430,8 +2793,8 @@ rb_f_syscall(argc, argv) #endif /* atarist */ } TRAP_END; - if (retval == -1) rb_sys_fail(0); - return INT2FIX(0); + if (retval < 0) rb_sys_fail(0); + return INT2NUM(retval); #else rb_notimplement(); return Qnil; /* not reached */ @@ -2452,8 +2815,8 @@ rb_io_s_pipe() #endif rb_sys_fail(0); - r = prep_stdio(fdopen(pipes[0], "r"), FMODE_READABLE, rb_cIO); - w = prep_stdio(fdopen(pipes[1], "w"), FMODE_WRITABLE, rb_cIO); + r = prep_stdio(rb_fdopen(pipes[0], "r"), FMODE_READABLE, rb_cIO); + w = prep_stdio(rb_fdopen(pipes[1], "w"), FMODE_WRITABLE, rb_cIO); ary = rb_ary_new2(2); rb_ary_push(ary, r); @@ -2498,6 +2861,7 @@ rb_io_s_foreach(argc, argv, io) arg.argc = argc - 1; arg.io = rb_io_open(RSTRING(fname)->ptr, "r"); + if (NIL_P(arg.io)) return Qnil; return rb_ensure(rb_io_foreach_line, (VALUE)&arg, rb_io_close, arg.io); } @@ -2529,37 +2893,103 @@ rb_io_s_readlines(argc, argv, io) arg.argc = argc - 1; arg.io = rb_io_open(RSTRING(fname)->ptr, "r"); + if (NIL_P(arg.io)) return Qnil; return rb_ensure(rb_io_readline_line, (VALUE)&arg, rb_io_close, arg.io); } static VALUE -arg_fileno() +argf_tell() { - return rb_io_fileno(file); + if (!next_argv()) { + rb_raise(rb_eArgError, "no stream to tell"); + } + + if (TYPE(current_file) != T_FILE) { + return argf_forward(); + } + return rb_io_tell(current_file); } static VALUE -arg_to_io() +argf_seek(self, offset, ptrname) + VALUE self, offset, ptrname; { - return file; + if (!next_argv()) { + rb_raise(rb_eArgError, "no stream to seek"); + } + + if (TYPE(current_file) != T_FILE) { + return argf_forward(); + } + return rb_io_seek(current_file, offset, ptrname); +} + +static VALUE +argf_set_pos(self, offset) + VALUE self, offset; +{ + if (!next_argv()) { + rb_raise(rb_eArgError, "no stream to pos"); + } + + if (TYPE(current_file) != T_FILE) { + return argf_forward(); + } + return rb_io_set_pos(current_file, offset); +} + +static VALUE +argf_rewind() +{ + if (!next_argv()) { + rb_raise(rb_eArgError, "no stream to rewind"); + } + if (TYPE(current_file) != T_FILE) { + return argf_forward(); + } + return rb_io_rewind(current_file); +} + +static VALUE +argf_fileno() +{ + if (!next_argv()) { + rb_raise(rb_eArgError, "no stream"); + } + if (TYPE(current_file) != T_FILE) { + return argf_forward(); + } + return rb_io_fileno(current_file); } static VALUE -arg_read(argc, argv) +argf_to_io() +{ + return current_file; +} + +static VALUE +argf_read(argc, argv) int argc; VALUE *argv; { VALUE tmp, str; - size_t len; + int len; if (argc == 1) len = NUM2INT(argv[0]); str = Qnil; retry: if (!next_argv()) return str; - tmp = rb_io_read(argc, argv, file); + if (TYPE(current_file) != T_FILE) { + tmp = argf_forward(); + STR2CSTR(tmp); + } + else { + tmp = io_read(argc, argv, current_file); + } if (NIL_P(tmp) && next_p != -1) { - rb_io_close(file); + any_close(current_file); next_p = 1; goto retry; } @@ -2579,15 +3009,20 @@ arg_read(argc, argv) } static VALUE -arg_getc() +argf_getc() { VALUE byte; retry: if (!next_argv()) return Qnil; - byte = rb_io_getc(file); + if (TYPE(current_file) != T_FILE) { + byte = rb_funcall3(current_file, rb_intern("getc"), 0, 0); + } + else { + byte = rb_io_getc(current_file); + } if (NIL_P(byte) && next_p != -1) { - rb_io_close(file); + any_close(current_file); next_p = 1; goto retry; } @@ -2596,9 +3031,9 @@ arg_getc() } static VALUE -arg_readchar() +argf_readchar() { - VALUE c = rb_io_getc(file); + VALUE c = argf_getc(); if (NIL_P(c)) { rb_eof_error(); @@ -2607,7 +3042,22 @@ arg_readchar() } static VALUE -arg_each_line(argc, argv) +argf_eof() +{ + if (init_p == 0 && !next_argv()) + return Qtrue; + if (TYPE(current_file) != T_FILE) { + return argf_forward(); + } + if (rb_io_eof(current_file)) { + next_p = 1; + return Qtrue; + } + return Qfalse; +} + +static VALUE +argf_each_line(argc, argv) int argc; VALUE *argv; { @@ -2616,46 +3066,46 @@ arg_each_line(argc, argv) while (RTEST(str = rb_f_gets_internal(argc, argv))) { rb_yield(str); } - return Qnil; + return argf; } static VALUE -arg_each_byte() +argf_each_byte() { VALUE byte; - while (!NIL_P(byte = arg_getc())) { + while (!NIL_P(byte = argf_getc())) { rb_yield(byte); } return Qnil; } static VALUE -arg_filename() +argf_filename() { return filename; } static VALUE -arg_file() +argf_file() { - return file; + return current_file; } static VALUE -arg_skip() +argf_skip() { if (next_p != -1) { - rb_io_close(file); + any_close(current_file); next_p = 1; } return argf; } static VALUE -arg_close() +argf_close() { - rb_io_close(file); + any_close(current_file); if (next_p != -1) { next_p = 1; } @@ -2664,9 +3114,12 @@ arg_close() } static VALUE -arg_closed() +argf_closed() { - return rb_io_closed(file); + if (TYPE(current_file) != T_FILE) { + return argf_forward(); + } + return rb_io_closed(current_file); } static VALUE @@ -2704,20 +3157,12 @@ Init_IO() rb_define_global_function("puts", rb_f_puts, -1); rb_define_global_function("gets", rb_f_gets, -1); rb_define_global_function("readline", rb_f_readline, -1); - rb_define_global_function("tell", rb_f_tell, 0); - rb_define_global_function("seek", rb_f_seek, 2); - rb_define_global_function("rewind", rb_f_rewind, 0); - rb_define_global_function("eof", rb_f_eof, 0); - rb_define_global_function("eof?", rb_f_eof, 0); rb_define_global_function("getc", rb_f_getc, 0); - rb_define_global_function("readchar", rb_f_readchar, 0); rb_define_global_function("select", rb_f_select, -1); - rb_define_global_function("ungetc", rb_f_ungetc, 1); rb_define_global_function("readlines", rb_f_readlines, -1); rb_define_global_function("`", rb_f_backquote, 1); - rb_define_global_function("pipe", rb_io_s_pipe, 0); rb_define_global_function("p", rb_f_p, -1); rb_define_method(rb_mKernel, "display", rb_obj_display, -1); @@ -2730,6 +3175,7 @@ Init_IO() rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1); rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1); rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1); + rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, 0); rb_fs = rb_output_fs = Qnil; rb_define_hooked_variable("$;", &rb_fs, 0, rb_str_setter); @@ -2773,8 +3219,8 @@ Init_IO() rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1); - rb_define_method(rb_cIO, "read", rb_io_read, -1); - rb_define_method(rb_cIO, "write", rb_io_write, 1); + rb_define_method(rb_cIO, "read", io_read, -1); + rb_define_method(rb_cIO, "write", io_write, 1); rb_define_method(rb_cIO, "gets", rb_io_gets_method, -1); rb_define_method(rb_cIO, "readline", rb_io_readline, -1); rb_define_method(rb_cIO, "getc", rb_io_getc, 0); @@ -2805,12 +3251,12 @@ Init_IO() rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1); rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1); - rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO); - rb_define_hooked_variable("$stdin", &rb_stdin, 0, rb_io_stdio_set); - rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO); - rb_define_hooked_variable("$stdout", &rb_stdout, 0, rb_io_stdio_set); - rb_stderr = prep_stdio(stderr, FMODE_WRITABLE, rb_cIO); - rb_define_hooked_variable("$stderr", &rb_stderr, 0, rb_io_stdio_set); + rb_stdin = orig_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO); + rb_define_hooked_variable("$stdin", &rb_stdin, 0, set_stdin); + rb_stdout = orig_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO); + rb_define_hooked_variable("$stdout", &rb_stdout, 0, set_stdout); + rb_stderr = orig_stderr = prep_stdio(stderr, FMODE_WRITABLE, rb_cIO); + rb_define_hooked_variable("$stderr", &rb_stderr, 0, set_stderr); rb_defout = rb_stdout; rb_define_hooked_variable("$>", &rb_defout, 0, rb_io_defset); @@ -2824,40 +3270,43 @@ Init_IO() rb_define_readonly_variable("$<", &argf); rb_define_global_const("ARGF", argf); - rb_define_singleton_method(argf, "fileno", arg_fileno, 0); - rb_define_singleton_method(argf, "to_i", arg_fileno, 0); - rb_define_singleton_method(argf, "to_io", arg_to_io, 0); - rb_define_singleton_method(argf, "each", arg_each_line, -1); - rb_define_singleton_method(argf, "each_line", arg_each_line, -1); - rb_define_singleton_method(argf, "each_byte", arg_each_byte, 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", arg_read, -1); + rb_define_singleton_method(argf, "read", argf_read, -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", arg_getc, 0); - rb_define_singleton_method(argf, "readchar", arg_readchar, 0); - rb_define_singleton_method(argf, "tell", rb_f_tell, 0); - rb_define_singleton_method(argf, "seek", rb_f_seek, 2); - rb_define_singleton_method(argf, "rewind", rb_f_rewind, 0); - rb_define_singleton_method(argf, "pos", rb_f_tell, 0); - rb_define_singleton_method(argf, "pos=", rb_f_set_pos, 1); - rb_define_singleton_method(argf, "eof", rb_f_eof, 0); - rb_define_singleton_method(argf, "eof?", rb_f_eof, 0); - rb_define_singleton_method(argf, "ungetc", rb_f_ungetc, 1); - - rb_define_singleton_method(argf, "to_s", arg_filename, 0); - rb_define_singleton_method(argf, "filename", arg_filename, 0); - rb_define_singleton_method(argf, "file", arg_file, 0); - rb_define_singleton_method(argf, "skip", arg_skip, 0); - rb_define_singleton_method(argf, "close", arg_close, 0); - rb_define_singleton_method(argf, "closed?", arg_closed, 0); - + rb_define_singleton_method(argf, "getc", argf_getc, 0); + rb_define_singleton_method(argf, "readchar", argf_readchar, 0); + rb_define_singleton_method(argf, "tell", argf_tell, 0); + rb_define_singleton_method(argf, "seek", argf_seek, 2); + 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, 0); + + rb_define_singleton_method(argf, "to_s", argf_filename, 0); + rb_define_singleton_method(argf, "filename", 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, 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); + + current_file = rb_stdin; + rb_global_variable(¤t_file); filename = rb_str_new2("-"); rb_define_readonly_variable("$FILENAME", &filename); - file = rb_stdin; - rb_global_variable(&file); rb_define_virtual_variable("$-i", opt_i_get, opt_i_set); @@ -2866,4 +3315,30 @@ Init_IO() #endif Init_File(); + + rb_define_method(rb_cFile, "reopen", rb_file_reopen, -1); + + rb_define_singleton_method(rb_cFile, "new", rb_file_s_open, -1); + rb_define_singleton_method(rb_cFile, "open", rb_file_s_open, -1); + + rb_file_const("RDONLY", INT2FIX(O_RDONLY)); + rb_file_const("WRONLY", INT2FIX(O_WRONLY)); + rb_file_const("RDWR", INT2FIX(O_RDWR)); + rb_file_const("APPEND", INT2FIX(O_APPEND)); + rb_file_const("CREAT", INT2FIX(O_CREAT)); + rb_file_const("EXCL", INT2FIX(O_EXCL)); +#if defined(O_NDELAY) || defined(O_NONBLOCK) +# ifdef O_NONBLOCK + rb_file_const("NONBLOCK", INT2FIX(O_NONBLOCK)); +# else + rb_file_const("NONBLOCK", INT2FIX(O_NDELAY)); +# endif +#endif + rb_file_const("TRUNC", INT2FIX(O_TRUNC)); +#ifdef O_NOCTTY + rb_file_const("NOCTTY", INT2FIX(O_NOCTTY)); +#endif +#ifdef O_BINARY + rb_file_const("BINARY", INT2FIX(O_BINARY)); +#endif } |