diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 1999-01-20 04:59:39 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 1999-01-20 04:59:39 +0000 |
commit | 210367ec889f5910e270d6ea2c7ddb8a8d939e61 (patch) | |
tree | feb35473da45947378fbc02defe39bcd79ef600e /ext | |
parent | 9c5b1986a36c7a700b4c76817e35aa874ba7907c (diff) | |
download | ruby-210367ec889f5910e270d6ea2c7ddb8a8d939e61.tar.gz |
This commit was generated by cvs2svn to compensate for changes in r372,
which included commits to RCS files with non-trunk default branches.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@373 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r-- | ext/Setup | 1 | ||||
-rw-r--r-- | ext/aix_ld.rb | 2 | ||||
-rw-r--r-- | ext/curses/curses.c | 107 | ||||
-rw-r--r-- | ext/curses/extconf.rb | 5 | ||||
-rw-r--r-- | ext/curses/hello.rb | 4 | ||||
-rw-r--r-- | ext/curses/view.rb | 1 | ||||
-rw-r--r-- | ext/dbm/dbm.c | 175 | ||||
-rw-r--r-- | ext/dbm/extconf.rb | 6 | ||||
-rw-r--r-- | ext/etc/etc.c | 91 | ||||
-rw-r--r-- | ext/etc/extconf.rb | 24 | ||||
-rw-r--r-- | ext/extmk.rb.in | 235 | ||||
-rw-r--r-- | ext/extmk.rb.nt | 6 | ||||
-rw-r--r-- | ext/fcntl/fcntl.c | 2 | ||||
-rw-r--r-- | ext/kconv/kconv.c | 89 | ||||
-rw-r--r-- | ext/md5/md5init.c | 14 | ||||
-rw-r--r-- | ext/socket/depend | 2 | ||||
-rw-r--r-- | ext/socket/extconf.rb | 12 | ||||
-rw-r--r-- | ext/socket/socket.c | 829 | ||||
-rw-r--r-- | ext/tcltklib/extconf.rb | 114 | ||||
-rw-r--r-- | ext/tcltklib/lib/tcltk.rb | 287 | ||||
-rw-r--r-- | ext/tcltklib/tcltklib.c | 293 |
21 files changed, 1480 insertions, 819 deletions
@@ -10,3 +10,4 @@ #socket #tkutil #tcltklib +#gtk diff --git a/ext/aix_ld.rb b/ext/aix_ld.rb index 1058977b88..42b2087a46 100644 --- a/ext/aix_ld.rb +++ b/ext/aix_ld.rb @@ -43,7 +43,7 @@ def extract(nm, out) else next end - }.sort! + }.compact!.sort! uniq(data) exp = open(out, "w") for line in data diff --git a/ext/curses/curses.c b/ext/curses/curses.c index 3ae8db192d..f3d1bc0970 100644 --- a/ext/curses/curses.c +++ b/ext/curses/curses.c @@ -2,7 +2,7 @@ * ext/curses/curses.c * * by MAEDA Shugo (ender@pic-internet.or.jp) - * modified by Yukihiro Matsumoto (matz@ruby.club.or.jp) + * modified by Yukihiro Matsumoto (matz@netlab.co.jp) */ #ifdef HAVE_NCURSES_H @@ -12,12 +12,18 @@ # include <ncurses/curses.h> # else # include <curses.h> -# if defined(__NetBSD__) && !defined(_maxx) +# if (defined(__bsdi__) || defined(__NetBSD__)) && !defined(_maxx) # define _maxx maxx # endif -# if defined(__NetBSD__) && !defined(_maxy) +# if (defined(__bsdi__) || defined(__NetBSD__)) && !defined(_maxy) # define _maxy maxy # endif +# if (defined(__bsdi__) || defined(__NetBSD__)) && !defined(_begx) +# define _begx begx +# endif +# if (defined(__bsdi__) || defined(__NetBSD__)) && !defined(_begy) +# define _begy begy +# endif # endif #endif @@ -32,14 +38,10 @@ struct windata { WINDOW *window; }; -#define NUM2CHAR(x) ((TYPE(x) == T_STRING)&&(RSTRING(x)->len>=1))?\ - RSTRING(x)->ptr[0]:(char)NUM2INT(x) -#define CHAR2FIX(x) INT2FIX((int)x) - static void no_window() { - Fail("already closed window"); + rb_raise(rb_eRuntimeError, "already closed window"); } #define GetWINDOW(obj, winp) {\ @@ -55,6 +57,7 @@ free_window(winp) { if (winp->window && winp->window != stdscr) delwin(winp->window); winp->window = 0; + free(winp); } static VALUE @@ -66,7 +69,7 @@ prep_window(class, window) struct windata *winp; if (window == NULL) { - Fail("failed to create window"); + rb_raise(rb_eRuntimeError, "failed to create window"); } obj = Data_Make_Struct(class, struct windata, 0, free_window, winp); @@ -83,7 +86,7 @@ curses_init_screen() { initscr(); if (stdscr == 0) { - Fail("cannot initialize curses"); + rb_raise(rb_eRuntimeError, "cannot initialize curses"); } clear(); rb_stdscr = prep_window(cWindow, stdscr); @@ -102,19 +105,33 @@ curses_stdscr() static VALUE curses_close_screen() { - endwin(); +#ifdef HAVE_ISENDWIN + if (!isendwin()) +#endif + endwin(); return Qnil; } +static void +curses_finalize() +{ + if (stdscr +#ifdef HAVE_ISENDWIN + && !isendwin() +#endif + ) + endwin(); +} + /* def closed? */ static VALUE curses_closed() { -#ifdef HAVE_ENDWIN +#ifdef HAVE_ISENDWIN if (isendwin()) { - return TRUE; + return Qtrue; } - return FALSE; + return Qfalse; #else rb_notimplement(); #endif @@ -138,12 +155,16 @@ curses_refresh(obj) return Qnil; } -/* def refresh */ +/* def doupdate */ static VALUE curses_doupdate(obj) VALUE obj; { +#ifdef HAVE_DOUPDATE doupdate(); +#else + refresh(); +#endif return Qnil; } @@ -235,7 +256,9 @@ static VALUE curses_flash(obj) VALUE obj; { +#ifdef HAVE_FLASH flash(); +#endif return Qnil; } @@ -287,7 +310,7 @@ static VALUE curses_inch(obj) VALUE obj; { - return CHAR2FIX(inch()); + return CHR2FIX(inch()); } /* def addch(ch) */ @@ -296,7 +319,7 @@ curses_addch(obj, ch) VALUE obj; VALUE ch; { - addch(NUM2CHAR(ch)); + addch(NUM2CHR(ch)); return Qnil; } @@ -306,7 +329,7 @@ curses_insch(obj, ch) VALUE obj; VALUE ch; { - insch(NUM2CHAR(ch)); + insch(NUM2CHR(ch)); return Qnil; } @@ -316,7 +339,9 @@ curses_addstr(obj, str) VALUE obj; VALUE str; { - addstr(RSTRING(str)->ptr); + if (!NIL_P(str)) { + addstr(STR2CSTR(str)); + } return Qnil; } @@ -325,7 +350,7 @@ static VALUE curses_getch(obj) VALUE obj; { - return CHAR2FIX(getch()); + return CHR2FIX(getch()); } /* def getstr */ @@ -335,7 +360,7 @@ curses_getstr(obj) { char rtn[1024]; /* This should be big enough.. I hope */ getstr(rtn); - return str_taint(str_new2(rtn)); + return rb_tainted_str_new2(rtn); } /* def delch */ @@ -352,7 +377,9 @@ static VALUE curses_deleteln(obj) VALUE obj; { +#ifdef HAVE_DELETELN deleteln(); +#endif return Qnil; } @@ -379,11 +406,15 @@ window_s_new(class, lines, cols, top, left) VALUE top; VALUE left; { + VALUE w; WINDOW *window; window = newwin(NUM2INT(lines), NUM2INT(cols), NUM2INT(top), NUM2INT(left)); wclear(window); - return prep_window(class, window); + w = prep_window(class, window); + rb_obj_call_init(w); + + return w; } /* def subwin(lines, cols, top, left) */ @@ -412,7 +443,8 @@ window_close(obj) struct windata *winp; GetWINDOW(obj, winp); - free_window(winp); + delwin(winp->window); + winp->window = 0; return Qnil; } @@ -453,7 +485,7 @@ window_box(obj, vert, hor) struct windata *winp; GetWINDOW(obj, winp); - box(winp->window, NUM2CHAR(vert), NUM2CHAR(hor)); + box(winp->window, NUM2CHR(vert), NUM2CHR(hor)); return Qnil; } @@ -622,7 +654,7 @@ window_inch(obj) struct windata *winp; GetWINDOW(obj, winp); - return CHAR2FIX(winch(winp->window)); + return CHR2FIX(winch(winp->window)); } /* def addch(ch) */ @@ -634,7 +666,7 @@ window_addch(obj, ch) struct windata *winp; GetWINDOW(obj, winp); - waddch(winp->window, NUM2CHAR(ch)); + waddch(winp->window, NUM2CHR(ch)); return Qnil; } @@ -648,7 +680,7 @@ window_insch(obj, ch) struct windata *winp; GetWINDOW(obj, winp); - winsch(winp->window, NUM2CHAR(ch)); + winsch(winp->window, NUM2CHR(ch)); return Qnil; } @@ -659,11 +691,12 @@ window_addstr(obj, str) VALUE obj; VALUE str; { - struct windata *winp; - - GetWINDOW(obj, winp); - waddstr(winp->window, RSTRING(str)->ptr); - + if (!NIL_P(str)) { + struct windata *winp; + + GetWINDOW(obj, winp); + waddstr(winp->window, STR2CSTR(str)); + } return Qnil; } @@ -685,7 +718,7 @@ window_getch(obj) struct windata *winp; GetWINDOW(obj, winp); - return CHAR2FIX(wgetch(winp->window)); + return CHR2FIX(wgetch(winp->window)); } /* def getstr */ @@ -698,7 +731,7 @@ window_getstr(obj) GetWINDOW(obj, winp); wgetstr(winp->window, rtn); - return str_taint(str_new2(rtn)); + return rb_tainted_str_new2(rtn); } /* def delch */ @@ -718,10 +751,12 @@ static VALUE window_deleteln(obj) VALUE obj; { +#ifdef HAVE_WDELETELN struct windata *winp; GetWINDOW(obj, winp); wdeleteln(winp->window); +#endif return Qnil; } @@ -764,7 +799,7 @@ Init_curses() rb_define_module_function(mCurses, "lines", curses_lines, 0); rb_define_module_function(mCurses, "cols", curses_cols, 0); - cWindow = rb_define_class_under(mCurses, "Window", cObject); + cWindow = rb_define_class_under(mCurses, "Window", rb_cObject); rb_define_singleton_method(cWindow, "new", window_s_new, 4); rb_define_method(cWindow, "subwin", window_subwin, 4); rb_define_method(cWindow, "close", window_close, 0); @@ -790,4 +825,6 @@ Init_curses() rb_define_method(cWindow, "getstr", window_getstr, 0); rb_define_method(cWindow, "delch", window_delch, 0); rb_define_method(cWindow, "deleteln", window_deleteln, 0); + + rb_set_end_proc(curses_finalize, 0); } diff --git a/ext/curses/extconf.rb b/ext/curses/extconf.rb index 9b28437843..442a9424a2 100644 --- a/ext/curses/extconf.rb +++ b/ext/curses/extconf.rb @@ -1,6 +1,9 @@ +require 'mkmf' $CFLAGS="-I/usr/include/ncurses -I/usr/local/include/ncurses" $LDFLAGS="-L/usr/local/lib" make=FALSE + +have_library("mytinfo", "tgetent") if /bow/ =~ PLATFORM if have_header("ncurses.h") and have_library("ncurses", "initscr") make=TRUE elsif have_header("ncurses/curses.h") and have_library("ncurses", "initscr") @@ -14,7 +17,7 @@ else end if make then - for f in ["isendwin", "ungetch", "beep"] + for f in %w(isendwin ungetch beep doupdate flash deleteln wdeleteln) have_func(f) end create_makefile("curses") diff --git a/ext/curses/hello.rb b/ext/curses/hello.rb index bed7779aac..a1915ce60d 100644 --- a/ext/curses/hello.rb +++ b/ext/curses/hello.rb @@ -10,6 +10,7 @@ def show_message(message) win.box(?|, ?=) win.setpos(2, 3) win.addstr(message) + win.refresh win.getch win.close end @@ -18,8 +19,9 @@ init_screen begin crmode # show_message("Hit any key") - setpos (lines - 5) / 2, (cols - 10) / 2 + setpos((lines - 5) / 2, (cols - 10) / 2) addstr("Hit any key") + refresh getch show_message("Hello, World!") refresh diff --git a/ext/curses/view.rb b/ext/curses/view.rb index e59a74ed44..5ba1a8413c 100644 --- a/ext/curses/view.rb +++ b/ext/curses/view.rb @@ -43,6 +43,7 @@ while TRUE addstr(data_lines[lptr + i]) #if data_lines[lptr + i] i += 1 end + refresh explicit = FALSE n = 0 diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c index b416802241..2764a325e1 100644 --- a/ext/dbm/dbm.c +++ b/ext/dbm/dbm.c @@ -6,7 +6,7 @@ $Date$ created at: Mon Jan 24 15:59:52 JST 1994 - Copyright (C) 1995 Yukihiro Matsumoto + Copyright (C) 1995-1998 Yukihiro Matsumoto ************************************************/ @@ -15,11 +15,12 @@ #include <ndbm.h> #include <fcntl.h> #include <errno.h> +#ifdef USE_CWGUSI +# include <sys/errno.h> +#endif VALUE cDBM; -extern VALUE mEnumerable; - struct dbmdata { int di_size; DBM *di_dbm; @@ -28,7 +29,7 @@ struct dbmdata { static void closed_dbm() { - Fail("closed DBM file"); + rb_raise(rb_eRuntimeError, "closed DBM file"); } #define GetDBM(obj, dbmp) {\ @@ -41,13 +42,14 @@ free_dbm(dbmp) struct dbmdata *dbmp; { if (dbmp->di_dbm) dbm_close(dbmp->di_dbm); + free(dbmp); } static VALUE -fdbm_s_open(argc, argv, class) +fdbm_s_open(argc, argv, klass) int argc; VALUE *argv; - VALUE class; + VALUE klass; { VALUE file, vmode; DBM *dbm; @@ -79,9 +81,10 @@ fdbm_s_open(argc, argv, class) rb_sys_fail(RSTRING(file)->ptr); } - obj = Data_Make_Struct(class,struct dbmdata,0,free_dbm,dbmp); + obj = Data_Make_Struct(klass,struct dbmdata,0,free_dbm,dbmp); dbmp->di_dbm = dbm; dbmp->di_size = -1; + rb_obj_call_init(obj); return obj; } @@ -118,23 +121,23 @@ fdbm_fetch(obj, keystr) if (value.dptr == 0) { return Qnil; } - return str_taint(str_new(value.dptr, value.dsize)); + return rb_tainted_str_new(value.dptr, value.dsize); } static VALUE -fdbm_indexes(obj, ag) - VALUE obj, ag; +fdbm_indexes(argc, argv, obj) + int argc; + VALUE *argv; + VALUE obj; { - VALUE *p, *pend; VALUE new; - int i = 0; - struct RArray *args = RARRAY(rb_Array(ag)); + int i; - new = ary_new2(args->len); - p = args->ptr; pend = p + args->len; - while (p < pend) { - ary_push(new, fdbm_fetch(obj, *p++)); + new = rb_ary_new2(argc); + for (i=0; i<argc; i++) { + rb_ary_push(new, fdbm_fetch(obj, argv[i])); } + return new; } @@ -156,13 +159,13 @@ fdbm_delete(obj, keystr) value = dbm_fetch(dbm, key); if (value.dptr == 0) { - if (iterator_p()) rb_yield(keystr); + if (rb_iterator_p()) rb_yield(keystr); return Qnil; } if (dbm_delete(dbm, key)) { dbmp->di_size = -1; - Fail("dbm_delete failed"); + rb_raise(rb_eRuntimeError, "dbm_delete failed"); } else if (dbmp->di_size >= 0) { dbmp->di_size--; @@ -188,9 +191,9 @@ fdbm_shift(obj) val = dbm_fetch(dbm, key); dbm_delete(dbm, key); - keystr = str_taint(str_new(key.dptr, key.dsize)); - valstr = str_taint(str_new(val.dptr, val.dsize)); - return assoc_new(keystr, valstr); + keystr = rb_tainted_str_new(key.dptr, key.dsize); + valstr = rb_tainted_str_new(val.dptr, val.dsize); + return rb_assoc_new(keystr, valstr); } static VALUE @@ -207,11 +210,11 @@ fdbm_delete_if(obj) dbm = dbmp->di_dbm; for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { val = dbm_fetch(dbm, key); - keystr = str_taint(str_new(key.dptr, key.dsize)); - valstr = str_taint(str_new(val.dptr, val.dsize)); - if (RTEST(rb_yield(assoc_new(keystr, valstr)))) { + keystr = rb_tainted_str_new(key.dptr, key.dsize); + valstr = rb_tainted_str_new(val.dptr, val.dsize); + if (RTEST(rb_yield(rb_assoc_new(keystr, valstr)))) { if (dbm_delete(dbm, key)) { - Fail("dbm_delete failed"); + rb_raise(rb_eRuntimeError, "dbm_delete failed"); } } } @@ -232,13 +235,72 @@ fdbm_clear(obj) dbmp->di_size = -1; for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { if (dbm_delete(dbm, key)) { - Fail("dbm_delete failed"); + rb_raise(rb_eRuntimeError, "dbm_delete failed"); } } return obj; } static VALUE +fdbm_invert(obj) + VALUE obj; +{ + datum key, val; + struct dbmdata *dbmp; + DBM *dbm; + VALUE keystr, valstr; + VALUE hash = rb_hash_new(); + + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + val = dbm_fetch(dbm, key); + keystr = rb_tainted_str_new(key.dptr, key.dsize); + valstr = rb_tainted_str_new(val.dptr, val.dsize); + rb_hash_aset(hash, valstr, keystr); + } + return obj; +} + +static VALUE +each_pair(obj) + VALUE obj; +{ + return rb_funcall(obj, rb_intern("each_pair"), 0, 0); +} + +static VALUE fdbm_store _((VALUE,VALUE,VALUE)); + +static VALUE +update_i(pair, dbm) + VALUE pair, dbm; +{ + Check_Type(pair, T_ARRAY); + if (RARRAY(pair)->len < 2) { + rb_raise(rb_eArgError, "pair must be [key, value]"); + } + fdbm_store(dbm, RARRAY(pair)->ptr[0], RARRAY(pair)->ptr[1]); + return Qnil; +} + +static VALUE +fdbm_update(obj, other) + VALUE obj, other; +{ + rb_iterate(each_pair, other, update_i, obj); + return obj; +} + +static VALUE +fdbm_replace(obj, other) + VALUE obj, other; +{ + fdbm_clear(obj); + rb_iterate(each_pair, other, update_i, obj); + return obj; +} + +static VALUE fdbm_store(obj, keystr, valstr) VALUE obj, keystr, valstr; { @@ -252,14 +314,14 @@ fdbm_store(obj, keystr, valstr) } rb_secure(4); - keystr = obj_as_string(keystr); + keystr = rb_obj_as_string(keystr); key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; if (NIL_P(valstr)) return fdbm_delete(obj, keystr); - valstr = obj_as_string(valstr); + valstr = rb_obj_as_string(valstr); val.dptr = RSTRING(valstr)->ptr; val.dsize = RSTRING(valstr)->len; @@ -267,9 +329,11 @@ fdbm_store(obj, keystr, valstr) dbmp->di_size = -1; dbm = dbmp->di_dbm; if (dbm_store(dbm, key, val, DBM_REPLACE)) { +#ifdef HAVE_DBM_CLAERERR dbm_clearerr(dbm); - if (errno == EPERM) rb_sys_fail(Qnil); - Fail("dbm_store failed"); +#endif + if (errno == EPERM) rb_sys_fail(0); + rb_raise(rb_eRuntimeError, "dbm_store failed"); } return valstr; @@ -316,8 +380,8 @@ fdbm_empty_p(obj) else { i = dbmp->di_size; } - if (i == 0) return TRUE; - return FALSE; + if (i == 0) return Qtrue; + return Qfalse; } static VALUE @@ -332,7 +396,7 @@ fdbm_each_value(obj) dbm = dbmp->di_dbm; for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { val = dbm_fetch(dbm, key); - rb_yield(str_taint(str_new(val.dptr, val.dsize))); + rb_yield(rb_tainted_str_new(val.dptr, val.dsize)); } return obj; } @@ -348,7 +412,7 @@ fdbm_each_key(obj) GetDBM(obj, dbmp); dbm = dbmp->di_dbm; for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { - rb_yield(str_taint(str_new(key.dptr, key.dsize))); + rb_yield(rb_tainted_str_new(key.dptr, key.dsize)); } return obj; } @@ -367,9 +431,9 @@ fdbm_each_pair(obj) for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { val = dbm_fetch(dbm, key); - keystr = str_taint(str_new(key.dptr, key.dsize)); - valstr = str_taint(str_new(val.dptr, val.dsize)); - rb_yield(assoc_new(keystr, valstr)); + keystr = rb_tainted_str_new(key.dptr, key.dsize); + valstr = rb_tainted_str_new(val.dptr, val.dsize); + rb_yield(rb_assoc_new(keystr, valstr)); } return obj; @@ -387,9 +451,9 @@ fdbm_keys(obj) GetDBM(obj, dbmp); dbm = dbmp->di_dbm; - ary = ary_new(); + ary = rb_ary_new(); for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { - ary_push(ary, str_taint(str_new(key.dptr, key.dsize))); + rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize)); } return ary; @@ -407,10 +471,10 @@ fdbm_values(obj) GetDBM(obj, dbmp); dbm = dbmp->di_dbm; - ary = ary_new(); + ary = rb_ary_new(); for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { val = dbm_fetch(dbm, key); - ary_push(ary, str_taint(str_new(val.dptr, val.dsize))); + rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize)); } return ary; @@ -431,8 +495,8 @@ fdbm_has_key(obj, keystr) GetDBM(obj, dbmp); dbm = dbmp->di_dbm; val = dbm_fetch(dbm, key); - if (val.dptr) return TRUE; - return FALSE; + if (val.dptr) return Qtrue; + return Qfalse; } static VALUE @@ -453,9 +517,9 @@ fdbm_has_value(obj, valstr) val = dbm_fetch(dbm, key); if (val.dsize == RSTRING(valstr)->len && memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0) - return TRUE; + return Qtrue; } - return FALSE; + return Qfalse; } static VALUE @@ -470,26 +534,29 @@ fdbm_to_a(obj) GetDBM(obj, dbmp); dbm = dbmp->di_dbm; - ary = ary_new(); + ary = rb_ary_new(); for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { val = dbm_fetch(dbm, key); - ary_push(ary, assoc_new(str_taint(str_new(key.dptr, key.dsize)), - str_taint(str_new(val.dptr, val.dsize)))); + rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize), + rb_tainted_str_new(val.dptr, val.dsize))); } return ary; } +void Init_dbm() { - cDBM = rb_define_class("DBM", cObject); - rb_include_module(cDBM, mEnumerable); + cDBM = rb_define_class("DBM", rb_cObject); + rb_include_module(cDBM, rb_mEnumerable); rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1); + rb_define_singleton_method(cDBM, "new", fdbm_s_open, -1); rb_define_method(cDBM, "close", fdbm_close, 0); rb_define_method(cDBM, "[]", fdbm_fetch, 1); rb_define_method(cDBM, "[]=", fdbm_store, 2); - rb_define_method(cDBM, "indexes", fdbm_indexes, -2); + rb_define_method(cDBM, "indexes", fdbm_indexes, -1); + rb_define_method(cDBM, "indices", fdbm_indexes, -1); rb_define_method(cDBM, "length", fdbm_length, 0); rb_define_alias(cDBM, "size", "length"); rb_define_method(cDBM, "empty?", fdbm_empty_p, 0); @@ -503,6 +570,10 @@ Init_dbm() rb_define_method(cDBM, "delete", fdbm_delete, 1); rb_define_method(cDBM, "delete_if", fdbm_delete_if, 0); rb_define_method(cDBM, "clear", fdbm_clear, 0); + rb_define_method(cDBM,"invert", fdbm_invert, 0); + rb_define_method(cDBM,"update", fdbm_update, 1); + rb_define_method(cDBM,"replace", fdbm_replace, 1); + rb_define_method(cDBM, "include?", fdbm_has_key, 1); rb_define_method(cDBM, "has_key?", fdbm_has_key, 1); rb_define_method(cDBM, "has_value?", fdbm_has_value, 1); diff --git a/ext/dbm/extconf.rb b/ext/dbm/extconf.rb index 4a5d41f275..3a96cee12f 100644 --- a/ext/dbm/extconf.rb +++ b/ext/dbm/extconf.rb @@ -1,5 +1,9 @@ +require 'mkmf' $LDFLAGS = "-L/usr/local/lib" -have_library("gdbm", "dbm_open") or have_library("dbm", "dbm_open") +have_library("gdbm", "dbm_open") or + have_library("db", "dbm_open") or + have_library("dbm", "dbm_open") if have_func("dbm_open") + have_func("dbm_clearerr") create_makefile("dbm") end diff --git a/ext/etc/etc.c b/ext/etc/etc.c index 20cd9295ed..c10680c7d3 100644 --- a/ext/etc/etc.c +++ b/ext/etc/etc.c @@ -37,7 +37,7 @@ etc_getlogin(obj) #endif if (login) - return str_new2(login); + return rb_tainted_str_new2(login); return Qnil; } @@ -47,34 +47,36 @@ setup_passwd(pwd) struct passwd *pwd; { if (pwd == 0) rb_sys_fail("/etc/passwd"); - return struct_new(sPasswd, - str_new2(pwd->pw_name), - str_new2(pwd->pw_passwd), - INT2FIX(pwd->pw_uid), - INT2FIX(pwd->pw_gid), - str_new2(pwd->pw_gecos), - str_new2(pwd->pw_dir), - str_new2(pwd->pw_shell), + return rb_struct_new(sPasswd, + rb_tainted_str_new2(pwd->pw_name), + rb_tainted_str_new2(pwd->pw_passwd), + INT2FIX(pwd->pw_uid), + INT2FIX(pwd->pw_gid), +#ifdef PW_GECOS + rb_tainted_str_new2(pwd->pw_gecos), +#endif + rb_tainted_str_new2(pwd->pw_dir), + rb_tainted_str_new2(pwd->pw_shell), #ifdef PW_CHANGE - INT2FIX(pwd->pw_change), + INT2FIX(pwd->pw_change), #endif #ifdef PW_QUOTA - INT2FIX(pwd->pw_quota), + INT2FIX(pwd->pw_quota), #endif #ifdef PW_AGE - INT2FIX(pwd->pw_age), + INT2FIX(pwd->pw_age), #endif #ifdef PW_CLASS - str_new2(pwd->pw_class), + rb_tainted_str_new2(pwd->pw_class), #endif #ifdef PW_COMMENT - str_new2(pwd->pw_comment), + rb_tainted_str_new2(pwd->pw_comment), #endif #ifdef PW_EXPIRE - INT2FIX(pwd->pw_expire), + INT2FIX(pwd->pw_expire), #endif - 0 /*dummy*/ - ); + 0 /*dummy*/ + ); } #endif @@ -96,7 +98,7 @@ etc_getpwuid(argc, argv, obj) uid = getuid(); } pwd = getpwuid(uid); - if (pwd == 0) Fail("can't find user for %d", uid); + if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %d", uid); return setup_passwd(pwd); #else return Qnil; @@ -112,7 +114,7 @@ etc_getpwnam(obj, nam) Check_Type(nam, T_STRING); pwd = getpwnam(RSTRING(nam)->ptr); - if (pwd == 0) Fail("can't find user for %s", RSTRING(nam)->ptr); + if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %s", RSTRING(nam)->ptr); return setup_passwd(pwd); #else return Qnil; @@ -123,10 +125,10 @@ static VALUE etc_passwd(obj) VALUE obj; { -#if defined(HAVE_GETPWENT) && !defined(__CYGWIN32__) +#if defined(HAVE_GETPWENT) struct passwd *pw; - if (iterator_p()) { + if (rb_iterator_p()) { setpwent(); while (pw = getpwent()) { rb_yield(setup_passwd(pw)); @@ -135,7 +137,7 @@ etc_passwd(obj) return obj; } pw = getpwent(); - if (pw == 0) Fail("can't fetch next -- /etc/passwd"); + if (pw == 0) rb_raise(rb_eRuntimeError, "can't fetch next -- /etc/passwd"); return setup_passwd(pw); #else return Qnil; @@ -150,17 +152,17 @@ setup_group(grp) VALUE mem; char **tbl; - mem = ary_new(); + mem = rb_ary_new(); tbl = grp->gr_mem; while (*tbl) { - ary_push(mem, str_new2(*tbl)); + rb_ary_push(mem, rb_tainted_str_new2(*tbl)); tbl++; } - return struct_new(sGroup, - str_new2(grp->gr_name), - str_new2(grp->gr_passwd), - INT2FIX(grp->gr_gid), - mem); + return rb_struct_new(sGroup, + rb_tainted_str_new2(grp->gr_name), + rb_tainted_str_new2(grp->gr_passwd), + INT2FIX(grp->gr_gid), + mem); } #endif @@ -174,7 +176,7 @@ etc_getgrgid(obj, id) gid = NUM2INT(id); grp = getgrgid(gid); - if (grp == 0) Fail("can't find group for %d", gid); + if (grp == 0) rb_raise(rb_eArgError, "can't find group for %d", gid); return setup_group(grp); #else return Qnil; @@ -190,7 +192,7 @@ etc_getgrnam(obj, nam) Check_Type(nam, T_STRING); grp = getgrnam(RSTRING(nam)->ptr); - if (grp == 0) Fail("can't find group for %s", RSTRING(nam)->ptr); + if (grp == 0) rb_raise(rb_eArgError, "can't find group for %s", RSTRING(nam)->ptr); return setup_group(grp); #else return Qnil; @@ -204,7 +206,7 @@ etc_group(obj) #ifdef HAVE_GETGRENT struct group *grp; - if (iterator_p()) { + if (rb_iterator_p()) { setgrent(); while (grp = getgrent()) { rb_yield(setup_group(grp)); @@ -235,32 +237,35 @@ Init_etc() rb_define_module_function(mEtc, "getgrnam", etc_getgrnam, 1); rb_define_module_function(mEtc, "group", etc_group, 0); - sPasswd = struct_define("Passwd", - "name", "passwd", "uid", "gid", - "gecos", "dir", "shell", + sPasswd = rb_struct_define("Passwd", + "name", "passwd", "uid", "gid", +#ifdef PW_GECOS + "gecos", +#endif + "dir", "shell", #ifdef PW_CHANGE - "change", + "change", #endif #ifdef PW_QUOTA - "quota", + "quota", #endif #ifdef PW_AGE - "age", + "age", #endif #ifdef PW_CLASS - "class", + "class", #endif #ifdef PW_COMMENT - "comment", + "comment", #endif #ifdef PW_EXPIRE - "expire", + "expire", #endif - 0); + 0); rb_global_variable(&sPasswd); #ifdef HAVE_GETGRENT - sGroup = struct_define("Group", "name", "passwd", "gid", "mem", 0); + sGroup = rb_struct_define("Group", "name", "passwd", "gid", "mem", 0); rb_global_variable(&sGroup); #endif } diff --git a/ext/etc/extconf.rb b/ext/etc/extconf.rb index 884de93ec8..4cf04a3ec3 100644 --- a/ext/etc/extconf.rb +++ b/ext/etc/extconf.rb @@ -1,7 +1,31 @@ +require 'mkmf' + +def etc_grep_header(field) + f = open("conftest.c", "w") + f.print <<EOF +#include <pwd.h> +EOF + f.close + begin + if xsystem("#{CPP} | egrep #{field}") + $defs.push(format("-D%s", field.upcase)) + end + ensure + system "rm -f conftest.c" + end +end + have_library("sun", "getpwnam") # NIS (== YP) interface for IRIX 4 a = have_func("getlogin") b = have_func("getpwent") c = have_func("getgrent") if a or b or c + etc_grep_header("pw_gecos") + etc_grep_header("pw_change") + etc_grep_header("pw_quota") + etc_grep_header("pw_age") + etc_grep_header("pw_class") + etc_grep_header("pw_comment") + etc_grep_header("pw_expire") create_makefile("etc") end diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in index e1d318d19c..058c144f94 100644 --- a/ext/extmk.rb.in +++ b/ext/extmk.rb.in @@ -1,12 +1,14 @@ #! /usr/local/bin/ruby -$".push 'mkmf.rb' +$".push 'mkmf.rb' #" +load '@top_srcdir@/lib/find.rb' if ARGV[0] == 'static' $force_static = TRUE ARGV.shift elsif ARGV[0] == 'install' $install = TRUE + $destdir = ARGV[1] || '' ARGV.shift elsif ARGV[0] == 'clean' $clean = TRUE @@ -19,8 +21,16 @@ $cache_mod = FALSE; $lib_cache = {} $func_cache = {} $hdr_cache = {} -$topdir = "@top_srcdir@" -if $topdir !~ "^/" +$top_srcdir = "@top_srcdir@" +if $top_srcdir !~ "^/" + # get absolute path + save = Dir.pwd + Dir.chdir $top_srcdir + $top_srcdir = Dir.pwd + Dir.chdir save +end +$topdir = ".." +if $topdir !~ "^/" # get absolute path save = Dir.pwd Dir.chdir $topdir @@ -59,23 +69,59 @@ end if PLATFORM == "m68k-human" CFLAGS = "@CFLAGS@".gsub(/-c..-stack=[0-9]+ */, '') -LINK = "@CC@ -o conftest -I#{$topdir} " + CFLAGS + " %s @LDFLAGS@ %s conftest.c @LIBS@ %s > nul 2>&1" -CPP = "@CPP@ @CPPFLAGS@ -I#{$topdir} " + CFLAGS + " %s conftest.c > nul 2>&1" else CFLAGS = "@CFLAGS@" -LINK = "@CC@ -o conftest -I#{$topdir} " + CFLAGS + " %s @LDFLAGS@ %s conftest.c %s > /dev/null 2>&1" -CPP = "@CPP@ @CPPFLAGS@ -I#{$topdir} " + CFLAGS + " %s conftest.c > /dev/null 2>&1" +end +LINK = "@CC@ -o conftest -I#$topdir -I#$top_srcdir -I@includedir@ #{CFLAGS} %s @LDFLAGS@ %s conftest.c @LIBS@ %s" +CPP = "@CPP@ @CPPFLAGS@ -I#$topdir -I#$top_srcdir -I@includedir@ #{CFLAGS} %s conftest.c" + +if /cygwin|mswin32|djgpp|mingw32|m68k-human/i =~ PLATFORM + $null = open("nul", "w") +else + $null = open("/dev/null", "w") +end + +$orgerr = $stderr.dup +$orgout = $stdout.dup +def xsystem command + if $DEBUG + return system(command) + end + $stderr.reopen($null) + $stdout.reopen($null) + r = system(command) + $stderr.reopen($orgerr) + $stdout.reopen($orgout) + return r end def try_link(libs) - system(format(LINK, $CFLAGS, $LDFLAGS, libs)) + xsystem(format(LINK, $CFLAGS, $LDFLAGS, libs)) end def try_cpp - system(format(CPP, $CFLAGS)) + xsystem(format(CPP, $CFLAGS)) +end + +def install_rb(mfile) + path = [] + dir = [] + Find.find("lib") do |f| + next unless /\.rb$/ =~ f + f = f[4..-1] + path.push f + dir |= File.dirname(f) + end + for f in dir + next if f == "." + mfile.printf "\t@test -d $(DESTDIR)$(pkglibdir)/%s || mkdir $(DESTDIR)$(pkglibdir)/%s\n", f, f + end + for f in path + mfile.printf "\t$(INSTALL_DATA) lib/%s $(DESTDIR)$(pkglibdir)/%s\n", f, f + end end -def have_library(lib, func) +def have_library(lib, func="main") if $lib_cache[lib] if $lib_cache[lib] == "yes" if $libs @@ -89,26 +135,34 @@ def have_library(lib, func) end end - cfile = open("conftest.c", "w") - cfile.printf "\ + if func && func != "" + cfile = open("conftest.c", "w") + cfile.printf "\ int main() { return 0; } int t() { %s(); return 0; } ", func - cfile.close + cfile.close - begin + begin + if $libs + libs = "-l" + lib + " " + $libs + else + libs = "-l" + lib + end + unless try_link(libs) + $lib_cache[lib] = 'no' + $cache_mod = TRUE + return FALSE + end + ensure + system "rm -f conftest*" + end + else if $libs libs = "-l" + lib + " " + $libs else libs = "-l" + lib end - unless try_link(libs) - $lib_cache[lib] = 'no' - $cache_mod = TRUE - return FALSE - end - ensure - system "rm -f conftest*" end $libs = libs @@ -206,9 +260,19 @@ def create_makefile(target) end $defs.push(format("-DEXTLIB='%s'", libs.join(","))) end - $libs = "" unless $libs - $srcdir = $topdir + "/ext/" + target + $DLDFLAGS = '@DLDFLAGS@' + + if PLATFORM =~ /beos/ + if $libs + $libs = $libs + " -lruby" + else + $libs = "-lruby" + end + $DLDFLAGS = $DLDFLAGS + " -L" + $topdir + end + + $srcdir = $top_srcdir + "/ext/" + target mfile = open("Makefile", "w") mfile.printf "\ SHELL = /bin/sh @@ -222,10 +286,11 @@ hdrdir = #{$topdir} CC = @CC@ -CFLAGS = %s -I#{$topdir} %s #$CFLAGS %s -DLDFLAGS = @DLDFLAGS@ #$LDFLAGS +prefix = @prefix@ +CFLAGS = %s -I#{$topdir} -I#{$top_srcdir} -I@includedir@ #{CFLAGS} #$CFLAGS %s +DLDFLAGS = #$DLDFLAGS @LDFLAGS@ #$LDFLAGS LDSHARED = @LDSHARED@ -", if $static then "" else "@CCDLFLAGS@" end, CFLAGS, $defs.join(" ") +", if $static then "" else "@CCDLFLAGS@" end, $defs.join(" ") mfile.printf "\ @@ -234,18 +299,20 @@ RUBY_INSTALL_NAME = `t='$(program_transform_name)'; echo ruby | sed $$t` prefix = @prefix@ exec_prefix = @exec_prefix@ -libdir = @libdir@/$(RUBY_INSTALL_NAME)/@arch@ +libdir = @libdir@ +pkglibdir = $(libdir)/$(RUBY_INSTALL_NAME) +archdir = $(pkglibdir)/@arch@ @SET_MAKE@ #### End of system configuration section. #### " - mfile.printf "LOCAL_LIBS = %s\n", $local_libs if $local_libs + mfile.printf "LOCAL_LIBS = %s\n", $local_libs unless $local_libs == "" mfile.printf "LIBS = %s\n", $libs mfile.printf "OBJS = " if !$objs then $objs = [] - for f in Dir["#{$topdir}/ext/#{target}/*.{c,cc}"] + for f in Dir["#{$top_srcdir}/ext/#{$mdir}/*.{c,cc}"] f = File.basename(f) f.sub!(/\.(c|cc)$/, ".o") $objs.push f @@ -254,42 +321,48 @@ libdir = @libdir@/$(RUBY_INSTALL_NAME)/@arch@ mfile.printf $objs.join(" ") mfile.printf "\n" - mfile.printf "\ -TARGET = %s.%s + mfile.printf <<EOS +TARGET = #{target}.#{$static ? "a" : "@DLEXT@"} -INSTALL = %s@INSTALL@ +INSTALL = #{$dots}@INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ binsuffix = @binsuffix@ all: $(TARGET) -clean:; @rm -f *.o *.so *.sl +clean:; @rm -f *.o *.a *.so *.sl @rm -f Makefile extconf.h conftest.* @rm -f core ruby$(binsuffix) *~ realclean: clean -", target, - if $static then "o" else "@DLEXT@" end, $dots +EOS - mfile.printf "\ + mfile.printf <<EOS install: -" + @test -d $(DESTDIR)$(libdir) || mkdir $(DESTDIR)$(libdir) + @test -d $(DESTDIR)$(pkglibdir) || mkdir $(DESTDIR)$(pkglibdir) + @test -d $(DESTDIR)$(archdir) || mkdir $(DESTDIR)$(archdir) +EOS if !$static - mfile.printf " - @test -d $(libdir) || mkdir $(libdir) - $(INSTALL) $(TARGET) $(libdir)/$(TARGET) + mfile.printf "\ + $(INSTALL) $(TARGET) $(DESTDIR)$(archdir)/$(TARGET) " end - for rb in Dir["lib/*.rb"] - mfile.printf "\t$(INSTALL) %s @libdir@/$(RUBY_INSTALL_NAME)\n", rb - end + install_rb(mfile) mfile.printf "\n" - if !$static && "@DLEXT@" != "o" + if $static + mfile.printf "\ +$(TARGET): $(OBJS) + @AR@ cru $(TARGET) $(OBJS) + @-@RANLIB@ $(TARGET) 2> /dev/null || true +" + elsif "@DLEXT@" != "o" mfile.printf "\ $(TARGET): $(OBJS) - $(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LOCAL_LIBS) $(LIBS) + $(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LIBS) $(LOCAL_LIBS) " elsif not File.exist?(target + ".c") and not File.exist?(target + ".cc") if PLATFORM == "m68k-human" @@ -297,16 +370,11 @@ $(TARGET): $(OBJS) $(TARGET): $(OBJS) ar cru $(TARGET) $(OBJS) " - elsif PLATFORM =~ "-nextstep" + elsif PLATFORM =~ "-nextstep" || PLATFORM =~ "-openstep" || PLATFORM =~ "-rhapsody" mfile.printf "\ $(TARGET): $(OBJS) cc -r $(CFLAGS) -o $(TARGET) $(OBJS) " - elsif $static - mfile.printf "\ -$(TARGET): $(OBJS) - ld -r -o $(TARGET) $(OBJS) -" else mfile.printf "\ $(TARGET): $(OBJS) @@ -324,6 +392,19 @@ $(TARGET): $(OBJS) dfile.close end mfile.close + + if PLATFORM =~ /beos/ + if PLATFORM =~ /^powerpc/ then + deffilename = "ruby.exp" + else + deffilename = "ruby.def" + end + print "creating ruby.def\n" + open(deffilename, "w") do |file| + file.print("EXPORTS\n") if PLATFORM =~ /^i/ + file.print("Init_#{target}\n") + end + end end def extmake(target) @@ -335,24 +416,25 @@ def extmake(target) return if $nodynamic and not $static - $local_libs = nil - $libs = nil $objs = nil - $CFLAGS = nil - $LDFLAGS = nil + $libs = PLATFORM =~ /cygwin|beos|openstep|nextstep|rhapsody/ ? nil : "-lc" + $local_libs = "" # to be assigned in extconf.rb + $CFLAGS = "" + $LDFLAGS = "" begin - system "mkdir " + target unless File.directory?(target) + system "mkdir", target unless File.directory?(target) Dir.chdir target + $mdir = target if $static_ext.size > 0 || !File.exist?("./Makefile") || - older("./Makefile", "#{$topdir}/ext/@setup@") || + older("./Makefile", "#{$top_srcdir}/ext/@setup@") || older("./Makefile", "../extmk.rb") || - older("./Makefile", "#{$topdir}/ext/#{target}/extconf.rb") + older("./Makefile", "#{$top_srcdir}/ext/#{target}/extconf.rb") then $defs = [] - if File.exist?("#{$topdir}/ext/#{target}/extconf.rb") - load "#{$topdir}/ext/#{target}/extconf.rb" + if File.exist?("#{$top_srcdir}/ext/#{target}/extconf.rb") + load "#{$top_srcdir}/ext/#{target}/extconf.rb" else create_makefile(target); end @@ -362,7 +444,7 @@ def extmake(target) $extlist.push [$static,target] end if $install - system "make install" + system "make install DESTDIR=#{$destdir}" elsif $clean system "make clean" else @@ -370,9 +452,10 @@ def extmake(target) end end if $static - $extlibs += " " + $LDFLAGS if $LDFLAGS - $extlibs += " " + $local_libs if $local_libs + $extlibs ||= "" + $extlibs += " " + $LDFLAGS unless $LDFLAGS == "" $extlibs += " " + $libs if $libs + $extlibs += " " + $local_libs unless $local_libs == "" end ensure Dir.chdir ".." @@ -381,11 +464,11 @@ end # get static-link modules $static_ext = {} -for setup in ["@setup@", "#{$topdir}/ext/@setup@"] +for setup in ["@setup@", "#{$top_srcdir}/ext/@setup@"] if File.file? setup f = open(setup) while f.gets() - $_.chop! + $_.chomp! sub!(/#.*$/, '') next if /^\s*$/ if /^option +nodynamic/ @@ -399,7 +482,7 @@ for setup in ["@setup@", "#{$topdir}/ext/@setup@"] end end -for d in Dir["#{$topdir}/ext/*"] +for d in Dir["#{$top_srcdir}/ext/*"] File.directory?(d) || next File.file?(d + "/MANIFEST") || next @@ -429,15 +512,16 @@ if $cache_mod end exit if $install or $clean -$extinit += "" +$extinit = "" unless $extinit if $extlist.size > 0 for s,t in $extlist - f = format("%s/%s.o", s, t) + f = format("%s/%s.a", s, t) if File.exist?(f) $extinit += format("\ \tInit_%s();\n\ \trb_provide(\"%s.o\");\n\ ", t, t) + $extobjs = "" unless $extobjs $extobjs += "ext/" $extobjs += f $extobjs += " " @@ -446,7 +530,7 @@ if $extlist.size > 0 end end - if older("extinit.c", "#{$topdir}/ext/@setup@") + if older("extinit.c", "#{$top_srcdir}/ext/@setup@") f = open("extinit.c", "w") f.printf "void Init_ext() {\n" f.printf $extinit @@ -461,17 +545,24 @@ if $extlist.size > 0 Dir.chdir ".." - if older("ruby@binsuffix@", "#{$topdir}/ext/@setup@") or older("ruby@binsuffix@", "miniruby@binsuffix@") + if older("ruby@binsuffix@", "#{$top_srcdir}/ext/@setup@") or older("ruby@binsuffix@", "miniruby@binsuffix@") `rm -f ruby@binsuffix@` end - $extobjs = "ext/extinit.o " + $extobjs + if $extobjs + $extobjs = "ext/extinit.o " + $extobjs + else + $extobjs = "ext/extinit.o " + end + if PLATFORM =~ /m68k-human|beos/ + $extlibs.gsub!("-L/usr/local/lib", "") if $extlibs + end system format('make ruby@binsuffix@ EXTOBJS="%s" EXTLIBS="%s"', $extobjs, $extlibs) else Dir.chdir ".." if older("ruby@binsuffix@", "miniruby@binsuffix@") `rm -f ruby@binsuffix@` - `cp miniruby@binsuffix@ ruby@binsuffix@` + system("make ruby@binsuffix@") end end diff --git a/ext/extmk.rb.nt b/ext/extmk.rb.nt index 6792f2717b..5836e5c681 100644 --- a/ext/extmk.rb.nt +++ b/ext/extmk.rb.nt @@ -1,5 +1,7 @@ #! /usr/local/bin/ruby +$".push 'mkmf.rb' #" + if ARGV[0] == 'static' $force_static = TRUE ARGV.shift @@ -379,7 +381,7 @@ def extmake(target) end end if $static - #$extlibs = " " + $extlibs = " " $extlibs += " " + $LDFLAGS if $LDFLAGS $extlibs += " " + $local_libs if $local_libs $extlibs += " " + $libs if $libs @@ -438,6 +440,8 @@ if $cache_mod end exit if $install or $clean +$extinit = " " unless $extinit +$extobjs = "" if $extlist.size > 0 for s,t in $extlist #for s,t in $static_ext diff --git a/ext/fcntl/fcntl.c b/ext/fcntl/fcntl.c index 17aacb13c3..186f9ac893 100644 --- a/ext/fcntl/fcntl.c +++ b/ext/fcntl/fcntl.c @@ -5,7 +5,7 @@ $Author$ created at: Mon Apr 7 18:53:05 JST 1997 - Copyright (C) 1997 Yukihiro Matsumoto + Copyright (C) 1997-1998 Yukihiro Matsumoto ************************************************/ diff --git a/ext/kconv/kconv.c b/ext/kconv/kconv.c index 6778afcfe6..a3349826f1 100644 --- a/ext/kconv/kconv.c +++ b/ext/kconv/kconv.c @@ -1780,12 +1780,30 @@ kconv_kconv(argc, argv) VALUE src, dst; VALUE in, out; int in_code, out_code; + char *codename = 0; rb_scan_args(argc, argv, "12", &src, &out, &in); Check_Type(src, T_STRING); if (NIL_P(out)) { - out_code = _JIS; + codename = rb_get_kcode(); + goto codeselect; + } + else if (TYPE(out) == T_STRING) { + codename = RSTRING(out)->ptr; + codeselect: + switch (codename[0]) { + case 'E': case 'e': + out_code = _EUC; + break; + case 'S': case 's': + out_code = _SJIS; + break; + case 'J': case 'j': + default: + out_code = _JIS; + break; + } } else { out_code = NUM2INT(out); @@ -1794,12 +1812,28 @@ kconv_kconv(argc, argv) if (NIL_P(in)) { in_code = _AUTO; } + else if (TYPE(in) == T_STRING) { + switch (RSTRING(in)->ptr[0]) { + case 'E': case 'e': + in_code = _EUC; + break; + case 'S': case 's': + in_code = _SJIS; + break; + case 'J': case 'j': + in_code = _JIS; + break; + default: + in_code = _AUTO; + break; + } + } else { in_code = NUM2INT(in); if (in_code == _NOCONV) return (VALUE)src; } - dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */ + dst = rb_str_new(0, RSTRING(src)->len*3+10); /* large enough? */ RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, out_code, in_code); return dst; @@ -1813,7 +1847,7 @@ kconv_tojis(obj, src) Check_Type(src, T_STRING); - dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */ + dst = rb_str_new(0, RSTRING(src)->len*3+10); /* large enough? */ RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, _JIS, _AUTO); return dst; @@ -1827,7 +1861,7 @@ kconv_toeuc(obj, src) Check_Type(src, T_STRING); - dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */ + dst = rb_str_new(0, RSTRING(src)->len*3+10); /* large enough? */ RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, _EUC, _AUTO); return (VALUE)dst; @@ -1841,7 +1875,7 @@ kconv_tosjis(obj, src) Check_Type(src, T_STRING); - dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */ + dst = rb_str_new(0, RSTRING(src)->len*3+10); /* large enough? */ RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, _SJIS, _AUTO); return dst; @@ -1857,10 +1891,29 @@ static VALUE kconv_guess(obj, src) VALUE obj, src; { - unsigned char *p = RSTRING(src)->ptr; - unsigned char *pend = p + RSTRING(src)->len; + unsigned char *p; + unsigned char *pend; + int sequence_counter = 0; + + Check_Type(src, T_STRING); + + p = RSTRING(src)->ptr; + pend = p + RSTRING(src)->len; + +#define INCR do {\ + p++;\ + if (p==pend) return INT2FIX(_UNKNOWN);\ + sequence_counter++;\ + if (sequence_counter % 2 == 1 && *p != 0xa4)\ + sequence_counter = 0;\ + if (6 <= sequence_counter) {\ + sequence_counter = 0;\ + return INT2FIX(_EUC);\ + }\ +} while (0) -#define INCR {p++;if (p==pend) return INT2FIX(_UNKNOWN);} + if (*p == 0xa4) + sequence_counter = 1; while (p<pend) { if (*p == '\033') { @@ -1874,37 +1927,41 @@ kconv_guess(obj, src) if (0x81 <= *p && *p <= 0x8d) { return INT2FIX(_SJIS); } - if (*p == 0x8e) { + if (0x8f <= *p && *p <= 0x9f) { + return INT2FIX(_SJIS); + } + if (*p == 0x8e) { /* SS2 */ INCR; if ((0x40 <= *p && *p <= 0x7e) || (0x80 <= *p && *p <= 0xa0) || (0xe0 <= *p && *p <= 0xfc)) return INT2FIX(_SJIS); } - if (0xa1 <= *p && *p <= 0xdf) { + else if (0xa1 <= *p && *p <= 0xdf) { INCR; if (0xf0 <= *p && *p <= 0xfe) return INT2FIX(_EUC); if (0xe0 <= *p && *p <= 0xef) { - while (*p >= 0x40) { + while (p < pend && *p >= 0x40) { if (*p >= 0x81) { - if (0x8d <= *p || (0x8f <= *p && *p <= 0x9f)) { + if (*p <= 0x8d || (0x8f <= *p && *p <= 0x9f)) { return INT2FIX(_SJIS); } else if (0xfd <= *p && *p <= 0xfe) { return INT2FIX(_EUC); } } + INCR; } } - if (*p <= 0x9f) { + else if (*p <= 0x9f) { return INT2FIX(_SJIS); } } - if (0xf0 <= *p && *p <= 0xfe) { + else if (0xf0 <= *p && *p <= 0xfe) { return INT2FIX(_EUC); } - if (0xe0 <= *p && *p <= 0xef) { + else if (0xe0 <= *p && *p <= 0xef) { INCR; if ((0x40 <= *p && *p <= 0x7e) || (0x80 <= *p && *p <= 0xa0)) { @@ -1914,7 +1971,7 @@ kconv_guess(obj, src) return INT2FIX(_EUC); } } - p++; + INCR; } return INT2FIX(_UNKNOWN); } diff --git a/ext/md5/md5init.c b/ext/md5/md5init.c index 47f913792f..a825f96d47 100644 --- a/ext/md5/md5init.c +++ b/ext/md5/md5init.c @@ -5,7 +5,7 @@ $Author$ created at: Fri Aug 2 09:24:12 JST 1996 - Copyright (C) 1995 Yukihiro Matsumoto + Copyright (C) 1995-1998 Yukihiro Matsumoto ************************************************/ /* This module provides an interface to the RSA Data Security, @@ -42,7 +42,7 @@ md5_digest(obj) ctx = *md5; MD5Final(digest, &ctx); - return str_new(digest, 16); + return rb_str_new(digest, 16); } static VALUE @@ -53,7 +53,7 @@ md5_clone(obj) MD5_CTX *md5, *md5_new; Data_Get_Struct(obj, MD5_CTX, md5); - obj = Data_Make_Struct(CLASS_OF(obj), MD5_CTX, 0, 0, md5_new); + obj = Data_Make_Struct(CLASS_OF(obj), MD5_CTX, 0, free, md5_new); *md5_new = *md5; return obj; @@ -61,6 +61,9 @@ md5_clone(obj) static VALUE md5_new(argc, argv, class) + int argc; + VALUE* argv; + VALUE class; { int i; VALUE arg, obj; @@ -69,18 +72,19 @@ md5_new(argc, argv, class) rb_scan_args(argc, argv, "01", &arg); if (!NIL_P(arg)) Check_Type(arg, T_STRING); - obj = Data_Make_Struct(class, MD5_CTX, 0, 0, md5); + obj = Data_Make_Struct(class, MD5_CTX, 0, free, md5); MD5Init(md5); if (!NIL_P(arg)) { md5_update(obj, arg); } + rb_obj_call_init(obj); return obj; } Init_md5() { - cMD5 = rb_define_class("MD5", cObject); + cMD5 = rb_define_class("MD5", rb_cObject); rb_define_singleton_method(cMD5, "new", md5_new, -1); diff --git a/ext/socket/depend b/ext/socket/depend index 3d54fa073c..6e8c3b7d97 100644 --- a/ext/socket/depend +++ b/ext/socket/depend @@ -1 +1 @@ -socket.o : socket.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h $(hdrdir)/io.h $(hdrdir)/sig.h +socket.o : socket.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h $(hdrdir)/rubyio.h $(hdrdir)/rubysig.h diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb index f719723864..449d5a2785 100644 --- a/ext/socket/extconf.rb +++ b/ext/socket/extconf.rb @@ -1,18 +1,22 @@ -$LDFLAGS = "-L/usr/local/lib" +require 'mkmf' +$LDFLAGS = "-L/usr/local/lib" if File.directory?("/usr/local/lib") case PLATFORM when /mswin32/ test_func = "WSACleanup" have_library("wsock32", "WSACleanup") when /cygwin32/ - test_func = "cygwin32_socket" + test_func = "socket" +when /beos/ + test_func = "socket" + have_library("net", "socket") else test_func = "socket" + have_library("nsl", "t_open") have_library("socket", "socket") - have_library("inet", "gethostbyname") - have_library("nsl", "gethostbyname") end have_header("sys/un.h") if have_func(test_func) + have_func("inet_aton") have_func("hsterror") unless have_func("gethostname") have_func("uname") diff --git a/ext/socket/socket.c b/ext/socket/socket.c index f5d191b056..e9bdbc9e8c 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -9,7 +9,8 @@ ************************************************/ #include "ruby.h" -#include "io.h" +#include "rubyio.h" +#include "rubysig.h" #include <stdio.h> #include <sys/types.h> #ifndef NT @@ -22,7 +23,14 @@ #include <sys/un.h> #endif -#if defined(THREAD) && defined(HAVE_FCNTL) +#ifdef USE_CWGUSI +extern int fileno(FILE *stream); /* <unix.mac.h> */ +extern int rb_thread_select(int, fd_set*, fd_set*, fd_set*, struct timeval*); /* thread.c */ +# include <sys/errno.h> +# include <GUSI.h> +#endif + +#if defined(USE_THREAD) && defined(HAVE_FCNTL) #ifdef HAVE_SYS_SELECT_H #include <sys/select.h> #endif @@ -34,30 +42,25 @@ #define EWOULDBLOCK EAGAIN #endif -extern VALUE cIO; -extern VALUE cInteger; - -VALUE cBasicSocket; -VALUE cIPsocket; -VALUE cTCPsocket; -VALUE cTCPserver; -VALUE cUDPsocket; +VALUE rb_cBasicSocket; +VALUE rb_cIPsocket; +VALUE rb_cTCPsocket; +VALUE rb_cTCPserver; +VALUE rb_cUDPsocket; #ifdef AF_UNIX -VALUE cUNIXsocket; -VALUE cUNIXserver; +VALUE rb_cUNIXsocket; +VALUE rb_cUNIXserver; #endif -VALUE cSocket; +VALUE rb_cSocket; -extern VALUE eException; -static VALUE eSocket; +static VALUE rb_eSocket; #ifdef SOCKS -VALUE cSOCKSsocket; +VALUE rb_cSOCKSsocket; void SOCKSinit(); int Rconnect(); #endif -FILE *rb_fdopen(); char *strdup(); #define INET_CLIENT 0 @@ -69,9 +72,12 @@ static void sock_finalize(fptr) OpenFile *fptr; { - SOCKET s = fileno(fptr->f); + SOCKET s; + + if (!fptr->f) return; + s = fileno(fptr->f); free(fptr->f); - free(fptr->f2); + if (fptr->f2) free(fptr->f2); closesocket(s); } #endif @@ -85,6 +91,7 @@ sock_new(class, fd) NEWOBJ(sock, struct RFile); OBJSETUP(sock, class, T_FILE); + rb_secure(4); MakeOpenFile(sock, fp); fp->f = rb_fdopen(fd, "r"); #ifdef NT @@ -92,7 +99,8 @@ sock_new(class, fd) #endif fp->f2 = rb_fdopen(fd, "w"); fp->mode = FMODE_READWRITE; - io_unbuffered(fp); + rb_io_unbuffered(fp); + rb_obj_call_init((VALUE)sock); return (VALUE)sock; } @@ -107,12 +115,15 @@ bsock_shutdown(argc, argv, sock) int how; OpenFile *fptr; + rb_secure(4); rb_scan_args(argc, argv, "01", &howto); if (howto == Qnil) how = 2; else { how = NUM2INT(howto); - if (how < 0 && how > 2) how = 2; + if (how < 0 || 2 < how) { + rb_raise(rb_eArgError, "`how' should be either 0, 1, 2"); + } } GetOpenFile(sock, fptr); if (shutdown(fileno(fptr->f), how) == -1) @@ -122,9 +133,57 @@ bsock_shutdown(argc, argv, sock) } static VALUE +bsock_close_read(sock) + VALUE sock; +{ + OpenFile *fptr; + + rb_secure(4); + GetOpenFile(sock, fptr); + if (fptr->f2 == 0) { + return rb_io_close(sock); + } + if (shutdown(fileno(fptr->f), 0) == -1) + rb_sys_fail(0); + fptr->mode &= ~FMODE_READABLE; +#ifdef NT + free(fptr->f); +#else + fclose(fptr->f); +#endif + fptr->f = fptr->f2; + fptr->f2 = 0; + + return Qnil; +} + +static VALUE +bsock_close_write(sock) + VALUE sock; +{ + OpenFile *fptr; + + rb_secure(4); + GetOpenFile(sock, fptr); + if (fptr->f2 == 0) { + return rb_io_close(sock); + } + if (shutdown(fileno(fptr->f), 1) == -1) + rb_sys_fail(0); + fptr->mode &= ~FMODE_WRITABLE; +#ifdef NT + free(fptr->f2); +#else + fclose(fptr->f2); +#endif + fptr->f2 = 0; + + return Qnil; +} + +static VALUE bsock_setsockopt(sock, lev, optname, val) - VALUE sock, lev, optname; - struct RString *val; + VALUE sock, lev, optname, val; { int level, option; OpenFile *fptr; @@ -148,8 +207,7 @@ bsock_setsockopt(sock, lev, optname, val) v = (char*)&i; vlen = sizeof(i); break; default: - Check_Type(val, T_STRING); - v = val->ptr; vlen = val->len; + v = rb_str2cstr(val, &vlen); } GetOpenFile(sock, fptr); @@ -163,6 +221,7 @@ static VALUE bsock_getsockopt(sock, lev, optname) VALUE sock, lev, optname; { +#if !defined(__BEOS__) int level, option, len; char *buf; OpenFile *fptr; @@ -176,7 +235,10 @@ bsock_getsockopt(sock, lev, optname) if (getsockopt(fileno(fptr->f), level, option, buf, &len) < 0) rb_sys_fail(fptr->path); - return str_new(buf, len); + return rb_str_new(buf, len); +#else + rb_notimplement(); +#endif } static VALUE @@ -190,7 +252,7 @@ bsock_getsockname(sock) GetOpenFile(sock, fptr); if (getsockname(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0) rb_sys_fail("getsockname(2)"); - return str_new(buf, len); + return rb_str_new(buf, len); } static VALUE @@ -204,7 +266,7 @@ bsock_getpeername(sock) GetOpenFile(sock, fptr); if (getpeername(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0) rb_sys_fail("getpeername(2)"); - return str_new(buf, len); + return rb_str_new(buf, len); } static VALUE @@ -213,31 +275,32 @@ bsock_send(argc, argv, sock) VALUE *argv; VALUE sock; { - struct RString *msg, *to; + VALUE msg, to; VALUE flags; OpenFile *fptr; FILE *f; int fd, n; + char *m, *t; + int mlen, tlen; rb_secure(4); rb_scan_args(argc, argv, "21", &msg, &flags, &to); - Check_Type(msg, T_STRING); - GetOpenFile(sock, fptr); - f = fptr->f2?fptr->f2:fptr->f; + f = GetWriteFile(fptr); fd = fileno(f); retry: -#ifdef THREAD - thread_fd_writable(fd); +#ifdef USE_THREAD + rb_thread_fd_writable(fd); #endif + m = rb_str2cstr(msg, &mlen); if (RTEST(to)) { - Check_Type(to, T_STRING); - n = sendto(fd, msg->ptr, msg->len, NUM2INT(flags), - (struct sockaddr*)to->ptr, to->len); + t = rb_str2cstr(to, &tlen); + n = sendto(fd, m, mlen, NUM2INT(flags), + (struct sockaddr*)t, tlen); } else { - n = send(fd, msg->ptr, msg->len, NUM2INT(flags)); + n = send(fd, m, mlen, NUM2INT(flags)); } if (n < 0) { switch (errno) { @@ -246,8 +309,8 @@ bsock_send(argc, argv, sock) #if EAGAIN != EWOULDBLOCK case EAGAIN: #endif -#ifdef THREAD - thread_schedule(); +#ifdef USE_THREAD + rb_thread_schedule(); #endif goto retry; } @@ -277,7 +340,6 @@ s_recv(sock, argc, argv, from) enum sock_recv_type from; { OpenFile *fptr; - FILE f; VALUE str; char buf[1024]; int fd, alen = sizeof buf; @@ -289,12 +351,12 @@ s_recv(sock, argc, argv, from) if (flg == Qnil) flags = 0; else flags = NUM2INT(flg); - str = str_new(0, NUM2INT(len)); + str = rb_str_new(0, NUM2INT(len)); GetOpenFile(sock, fptr); fd = fileno(fptr->f); -#ifdef THREAD - thread_wait_fd(fd); +#ifdef USE_THREAD + rb_thread_wait_fd(fd); #endif TRAP_BEG; retry: @@ -309,38 +371,35 @@ s_recv(sock, argc, argv, from) #if EAGAIN != EWOULDBLOCK case EAGAIN: #endif -#ifdef THREAD - thread_schedule(); +#ifdef USE_THREAD + rb_thread_schedule(); #endif goto retry; } rb_sys_fail("recvfrom(2)"); } - str_taint(str); + rb_obj_taint(str); switch (from) { case RECV_RECV: return (VALUE)str; case RECV_TCP: if (alen != sizeof(struct sockaddr_in)) { - TypeError("sockaddr size differs - should not happen"); + rb_raise(rb_eTypeError, "sockaddr size differs - should not happen"); } - return assoc_new(str, ipaddr((struct sockaddr_in *)buf)); + return rb_assoc_new(str, ipaddr((struct sockaddr_in *)buf)); case RECV_UDP: { VALUE addr = ipaddr((struct sockaddr_in *)buf); - return assoc_new(str, assoc_new(RARRAY(addr)->ptr[2], - RARRAY(addr)->ptr[1])); + return rb_assoc_new(str, rb_assoc_new(RARRAY(addr)->ptr[2], + RARRAY(addr)->ptr[1])); } #ifdef HAVE_SYS_UN_H case RECV_UNIX: - if (alen != sizeof(struct sockaddr_un)) { - TypeError("sockaddr size differs - should not happen"); - } - return assoc_new(str, unixaddr((struct sockaddr_un *)buf)); + return rb_assoc_new(str, unixaddr((struct sockaddr_un *)buf)); #endif case RECV_SOCKET: - return assoc_new(str, str_new(buf, alen)); + return rb_assoc_new(str, rb_str_new(buf, alen)); } } @@ -353,7 +412,96 @@ bsock_recv(argc, argv, sock) return s_recv(sock, argc, argv, RECV_RECV); } -#if defined(THREAD) && defined(HAVE_FCNTL) +static VALUE +mkipaddr(x) + unsigned long x; +{ + char buf[16]; + + x = ntohl(x); + sprintf(buf, "%d.%d.%d.%d", + (int) (x>>24) & 0xff, (int) (x>>16) & 0xff, + (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff); + return rb_str_new2(buf); +} + +static VALUE +ipaddr(sockaddr) + struct sockaddr_in *sockaddr; +{ + VALUE family, port, addr1, addr2; + VALUE ary; + struct hostent *hostent; + + family = rb_str_new2("AF_INET"); + hostent = gethostbyaddr((char*)&sockaddr->sin_addr.s_addr, + sizeof(sockaddr->sin_addr), + AF_INET); + addr1 = 0; + if (hostent) { + addr1 = rb_str_new2(hostent->h_name); + } + addr2 = mkipaddr(sockaddr->sin_addr.s_addr); + if (!addr1) addr1 = addr2; + + port = INT2FIX(ntohs(sockaddr->sin_port)); + ary = rb_ary_new3(4, family, port, addr1, addr2); + + return ary; +} + +#ifndef HAVE_INET_ATON +static unsigned long +inet_aton(host, inp) + char *host; + struct in_addr *inp; +{ + int d1, d2, d3, d4; + char ch; + + if (sscanf(host, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 && + 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 && + 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) { + inp->s_addr = htonl( + ((long) d1 << 24) | ((long) d2 << 16) | + ((long) d3 << 8) | ((long) d4 << 0)); + return 1; + } + return 0; +} +#endif + +static void +setipaddr(name, addr) + char *name; + struct sockaddr_in *addr; +{ + struct hostent *hp; + + if (name[0] == 0) { + addr->sin_addr.s_addr = INADDR_ANY; + } + else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) { + addr->sin_addr.s_addr = INADDR_BROADCAST; + } + else if (inet_aton(name, &addr->sin_addr) != 0) { + /* ok to set addr->sin_addr */ + } + else { + hp = gethostbyname(name); + if (!hp) { +#ifdef HAVE_HSTRERROR + extern int h_errno; + rb_raise(rb_eSocket, (char *)hstrerror(h_errno)); +#else + rb_raise(rb_eSocket, "host not found"); +#endif + } + memcpy((char *) &addr->sin_addr, hp->h_addr, hp->h_length); + } +} + +#if defined(USE_THREAD) && defined(HAVE_FCNTL) static int thread_connect(fd, sockaddr, len, type) int fd; @@ -396,7 +544,7 @@ thread_connect(fd, sockaddr, len, type) #endif FD_ZERO(&fds); FD_SET(fd, &fds); - thread_select(fd+1, 0, &fds, 0, 0, 0); + rb_thread_select(fd+1, 0, &fds, 0, 0); continue; #endif @@ -434,26 +582,25 @@ open_inet(class, h, serv, type) int hostaddr, hostaddrPtr[2]; int servport; char *syscall; - VALUE sock; if (h) { Check_SafeStr(h); host = RSTRING(h)->ptr; hostent = gethostbyname(host); if (hostent == NULL) { - hostaddr = inet_addr(host); - if (hostaddr == -1) { + if (!inet_aton(host, &sockaddr.sin_addr)) { if (type == INET_SERVER && !strlen(host)) hostaddr = INADDR_ANY; else { #ifdef HAVE_HSTRERROR extern int h_errno; - Raise(eSocket, (char *)hstrerror(h_errno)); + rb_raise(rb_eSocket, (char *)hstrerror(h_errno)); #else - Raise(eSocket, "host not found"); + rb_raise(rb_eSocket, "host not found"); #endif } } + hostaddr = sockaddr.sin_addr.s_addr; _hostent.h_addr_list = (char **)hostaddrPtr; _hostent.h_addr_list[0] = (char *)&hostaddr; _hostent.h_addr_list[1] = NULL; @@ -467,24 +614,30 @@ open_inet(class, h, serv, type) servport = FIX2UINT(serv); goto setup_servent; } - Check_Type(serv, T_STRING); - servent = getservbyname(RSTRING(serv)->ptr, "tcp"); + servent = getservbyname(STR2CSTR(serv), "tcp"); if (servent == NULL) { - servport = strtoul(RSTRING(serv)->ptr, 0, 0); - if (servport == -1) { - Raise(eSocket, "no such servce %s", RSTRING(serv)->ptr); + char *s = STR2CSTR(serv); + char *end; + + servport = strtoul(s, &end, 0); + if (*end != '\0') { + rb_raise(rb_eSocket, "no such servce %s", s); } setup_servent: _servent.s_port = htons(servport); _servent.s_proto = "tcp"; servent = &_servent; } +#ifdef __BEOS__ + fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); +#else protoent = getprotobyname(servent->s_proto); if (protoent == NULL) { - Raise(eSocket, "no such proto %s", servent->s_proto); + rb_raise(rb_eSocket, "no such proto %s", servent->s_proto); } fd = socket(AF_INET, SOCK_STREAM, protoent->p_proto); +#endif memset(&sockaddr, 0, sizeof(sockaddr)); sockaddr.sin_family = AF_INET; @@ -505,9 +658,9 @@ open_inet(class, h, serv, type) syscall = "bind(2)"; } else { -#if defined(THREAD) && defined(HAVE_FCNTL) +#if defined(USE_THREAD) && defined(HAVE_FCNTL) status = thread_connect(fd, (struct sockaddr*)&sockaddr, - sizeof(sockaddr), type); + sizeof(sockaddr), type); #else #ifdef SOCKS if (type == INET_SOCKS) { @@ -523,7 +676,7 @@ open_inet(class, h, serv, type) } if (status < 0) { - close (fd); + close(fd); rb_sys_fail(syscall); } if (type == INET_SERVER) listen(fd, 5); @@ -558,6 +711,49 @@ socks_s_open(class, host, serv) #endif static VALUE +tcp_s_gethostbyname(obj, host) + VALUE obj, host; +{ + struct sockaddr_in addr; + struct hostent *h; + char **pch; + VALUE ary, names; + + setipaddr(STR2CSTR(host), &addr); + h = gethostbyaddr((char *)&addr.sin_addr, + sizeof(addr.sin_addr), + AF_INET); + + if (h == NULL) { +#ifdef HAVE_HSTRERROR + extern int h_errno; + rb_raise(rb_eSocket, (char *)hstrerror(h_errno)); +#else + rb_raise(rb_eSocket, "host not found"); +#endif + } + ary = rb_ary_new(); + rb_ary_push(ary, rb_str_new2(h->h_name)); + names = rb_ary_new(); + rb_ary_push(ary, names); + for (pch = h->h_aliases; *pch; pch++) { + rb_ary_push(names, rb_str_new2(*pch)); + } + rb_ary_push(ary, NUM2INT(h->h_addrtype)); +#ifdef h_addr + for (pch = h->h_addr_list; *pch; pch++) { + memcpy((char *) &addr.sin_addr, *pch, h->h_length); + rb_ary_push(ary, mkipaddr(addr.sin_addr.s_addr)); + } +#else + memcpy((char *)&addr.sin_addr, h->h_addr, h->h_length); + rb_ary_push(ary, mkipaddr(addr.sin_addr.s_addr)); +#endif + + return ary; +} + +static VALUE tcp_svr_s_open(argc, argv, class) int argc; VALUE *argv; @@ -581,8 +777,8 @@ s_accept(class, fd, sockaddr, len) int fd2; retry: -#ifdef THREAD - thread_wait_fd(fd); +#ifdef USE_THREAD + rb_thread_wait_fd(fd); #endif TRAP_BEG; fd2 = accept(fd, sockaddr, len); @@ -594,8 +790,8 @@ s_accept(class, fd, sockaddr, len) #if EAGAIN != EWOULDBLOCK case EAGAIN: #endif -#ifdef THREAD - thread_schedule(); +#ifdef USE_THREAD + rb_thread_schedule(); #endif goto retry; } @@ -614,7 +810,7 @@ tcp_accept(sock) GetOpenFile(sock, fptr); fromlen = sizeof(struct sockaddr_in); - return s_accept(cTCPsocket, fileno(fptr->f), + return s_accept(rb_cTCPsocket, fileno(fptr->f), (struct sockaddr*)&from, &fromlen); } @@ -670,81 +866,6 @@ open_unix(class, path, server) } #endif -static void -setipaddr(name, addr) - char *name; - struct sockaddr_in *addr; -{ - int d1, d2, d3, d4; - char ch; - struct hostent *hp; - long x; - - if (name[0] == 0) { - addr->sin_addr.s_addr = INADDR_ANY; - } - else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) { - addr->sin_addr.s_addr = INADDR_BROADCAST; - } - else if (sscanf(name, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 && - 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 && - 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) { - addr->sin_addr.s_addr = htonl( - ((long) d1 << 24) | ((long) d2 << 16) | - ((long) d3 << 8) | ((long) d4 << 0)); - } - else { - hp = gethostbyname(name); - if (!hp) { -#ifdef HAVE_HSTRERROR - extern int h_errno; - Raise(eSocket, (char *)hstrerror(h_errno)); -#else - Raise(eSocket, "host not found"); -#endif - } - memcpy((char *) &addr->sin_addr, hp->h_addr, hp->h_length); - } -} - -static VALUE -mkipaddr(x) - unsigned long x; -{ - char buf[16]; - - x = ntohl(x); - sprintf(buf, "%d.%d.%d.%d", - (int) (x>>24) & 0xff, (int) (x>>16) & 0xff, - (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff); - return str_new2(buf); -} - -static VALUE -ipaddr(sockaddr) - struct sockaddr_in *sockaddr; -{ - VALUE family, port, addr1, addr2; - VALUE ary; - struct hostent *hostent; - - family = str_new2("AF_INET"); - hostent = gethostbyaddr((char*)&sockaddr->sin_addr.s_addr, - sizeof(sockaddr->sin_addr), - AF_INET); - addr1 = 0; - if (hostent) { - addr1 = str_new2(hostent->h_name); - } - addr2 = mkipaddr(sockaddr->sin_addr.s_addr); - if (!addr1) addr1 = addr2; - - port = INT2FIX(ntohs(sockaddr->sin_port)); - ary = ary_new3(4, family, port, addr1, addr2); - - return ary; -} - static VALUE ip_addr(sock) VALUE sock; @@ -781,13 +902,12 @@ ip_s_getaddress(obj, host) { struct sockaddr_in addr; - if (obj_is_kind_of(host, cInteger)) { + if (rb_obj_is_kind_of(host, rb_cInteger)) { int i = NUM2INT(host); addr.sin_addr.s_addr = htonl(i); } else { - Check_Type(host, T_STRING); - setipaddr(RSTRING(host)->ptr, &addr); + setipaddr(STR2CSTR(host), &addr); } return mkipaddr(addr.sin_addr.s_addr); @@ -805,37 +925,36 @@ udp_addrsetup(host, port, addr) VALUE host, port; struct sockaddr_in *addr; { - struct hostent *hostent; - memset(addr, 0, sizeof(struct sockaddr_in)); addr->sin_family = AF_INET; if (NIL_P(host)) { addr->sin_addr.s_addr = INADDR_ANY; } - else if (obj_is_kind_of(host, cInteger)) { + else if (rb_obj_is_kind_of(host, rb_cInteger)) { int i = NUM2INT(host); addr->sin_addr.s_addr = htonl(i); } else { - Check_Type(host, T_STRING); - setipaddr(RSTRING(host)->ptr, addr); + setipaddr(STR2CSTR(host), addr); } if (FIXNUM_P(port)) { - addr->sin_port = FIX2INT(port); + addr->sin_port = htons(FIX2INT(port)); } else { struct servent *servent; - Check_Type(port, T_STRING); - servent = getservbyname(RSTRING(port)->ptr, "udp"); + servent = getservbyname(STR2CSTR(port), "udp"); if (servent) { addr->sin_port = servent->s_port; } else { - int port = strtoul(RSTRING(port)->ptr, 0, 0); + char *s = STR2CSTR(port); + char *end; + int portno; - if (port == -1) { - Raise(eSocket, "no such servce %s", RSTRING(port)->ptr); + portno = strtoul(s, &end, 0); + if (*end != '\0') { + rb_raise(rb_eSocket, "no such servce %s", s); } addr->sin_port = htons(port); } @@ -859,8 +978,8 @@ udp_connect(sock, host, port) #if EAGAIN != EWOULDBLOCK case EAGAIN: #endif -#ifdef THREAD - thread_schedule(); +#ifdef USE_THREAD + rb_thread_schedule(); #endif goto retry; } @@ -896,19 +1015,21 @@ udp_send(argc, argv, sock) OpenFile *fptr; FILE *f; int n; + char *m; + int mlen; if (argc == 2) { return bsock_send(argc, argv, sock); } rb_scan_args(argc, argv, "4", &mesg, &flags, &host, &port); - Check_Type(mesg, T_STRING); udp_addrsetup(host, port, &addr); GetOpenFile(sock, fptr); - f = fptr->f2?fptr->f2:fptr->f; + f = GetWriteFile(fptr); + m = rb_str2cstr(mesg, &mlen); retry: - n = sendto(fileno(f), RSTRING(mesg)->ptr, RSTRING(mesg)->len, - NUM2INT(flags), (struct sockaddr*)&addr, sizeof(addr)); + n = sendto(fileno(f), m, mlen, NUM2INT(flags), + (struct sockaddr*)&addr, sizeof(addr)); if (n < 0) { switch (errno) { case EINTR: @@ -916,8 +1037,8 @@ udp_send(argc, argv, sock) #if EAGAIN != EWOULDBLOCK case EAGAIN: #endif -#ifdef THREAD - thread_schedule(); +#ifdef USE_THREAD + rb_thread_schedule(); #endif goto retry; } @@ -957,14 +1078,14 @@ unix_path(sock) rb_sys_fail(0); fptr->path = strdup(addr.sun_path); } - return str_new2(fptr->path); + return rb_str_new2(fptr->path); } static VALUE -unix_svr_s_open(class, path) - VALUE class, path; +unix_svr_s_open(sock, path) + VALUE sock, path; { - return open_unix(class, path, 1); + return open_unix(sock, path, 1); } static VALUE @@ -986,7 +1107,7 @@ unix_accept(sock) GetOpenFile(sock, fptr); fromlen = sizeof(struct sockaddr_un); - return s_accept(cUNIXsocket, fileno(fptr->f), + return s_accept(rb_cUNIXsocket, fileno(fptr->f), (struct sockaddr*)&from, &fromlen); } @@ -994,7 +1115,7 @@ static VALUE unixaddr(sockaddr) struct sockaddr_un *sockaddr; { - return assoc_new(str_new2("AF_UNIX"),str_new2(sockaddr->sun_path)); + return rb_assoc_new(rb_str_new2("AF_UNIX"),rb_str_new2(sockaddr->sun_path)); } static VALUE @@ -1055,8 +1176,10 @@ setup_domain_and_type(domain, dv, type, tv) else if (strcmp(ptr, "AF_IMPLINK") == 0) *dv = AF_IMPLINK; #endif +#ifdef PF_INET else if (strcmp(ptr, "PF_INET") == 0) *dv = PF_INET; +#endif #ifdef PF_UNIX else if (strcmp(ptr, "PF_UNIX") == 0) *dv = PF_UNIX; @@ -1076,7 +1199,7 @@ setup_domain_and_type(domain, dv, type, tv) *dv = PF_IPX; #endif else - Raise(eSocket, "Unknown socket domain %s", ptr); + rb_raise(rb_eSocket, "Unknown socket domain %s", ptr); } else { *dv = NUM2INT(domain); @@ -1104,7 +1227,7 @@ setup_domain_and_type(domain, dv, type, tv) *tv = SOCK_PACKET; #endif else - Raise(eSocket, "Unknown socket type %s", ptr); + rb_raise(rb_eSocket, "Unknown socket type %s", ptr); } else { *tv = NUM2INT(type); @@ -1121,6 +1244,7 @@ sock_s_open(class, domain, type, protocol) setup_domain_and_type(domain, &d, type, &t); fd = socket(d, t, NUM2INT(protocol)); if (fd < 0) rb_sys_fail("socket(2)"); + return sock_new(class, fd); } @@ -1135,15 +1259,14 @@ static VALUE sock_s_socketpair(class, domain, type, protocol) VALUE class, domain, type, protocol; { -#if !defined(__CYGWIN32__) && !defined(NT) - int fd; +#if !defined(NT) && !defined(__BEOS__) int d, t, sp[2]; setup_domain_and_type(domain, &d, type, &t); if (socketpair(d, t, NUM2INT(protocol), sp) < 0) rb_sys_fail("socketpair(2)"); - return assoc_new(sock_new(class, sp[0]), sock_new(class, sp[1])); + return rb_assoc_new(sock_new(class, sp[0]), sock_new(class, sp[1])); #else rb_notimplement(); #endif @@ -1156,7 +1279,7 @@ sock_connect(sock, addr) OpenFile *fptr; Check_Type(addr, T_STRING); - str_modify(addr); + rb_str_modify(addr); GetOpenFile(sock, fptr); retry: @@ -1167,8 +1290,8 @@ sock_connect(sock, addr) #if EAGAIN != EWOULDBLOCK case EAGAIN: #endif -#ifdef THREAD - thread_schedule(); +#ifdef USE_THREAD + rb_thread_schedule(); #endif goto retry; } @@ -1185,7 +1308,7 @@ sock_bind(sock, addr) OpenFile *fptr; Check_Type(addr, T_STRING); - str_modify(addr); + rb_str_modify(addr); GetOpenFile(sock, fptr); if (bind(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len) < 0) @@ -1226,9 +1349,9 @@ sock_accept(sock) int len = sizeof buf; GetOpenFile(sock, fptr); - sock2 = s_accept(cSocket,fileno(fptr->f),(struct sockaddr*)buf,&len); + sock2 = s_accept(rb_cSocket,fileno(fptr->f),(struct sockaddr*)buf,&len); - return assoc_new(sock2, str_new(buf, len)); + return rb_assoc_new(sock2, rb_str_new(buf, len)); } #ifdef HAVE_GETHOSTNAME @@ -1242,7 +1365,7 @@ sock_gethostname(obj) rb_sys_fail("gethostname"); buf[sizeof buf - 1] = '\0'; - return str_new2(buf); + return rb_str_new2(buf); } #else #ifdef HAVE_UNAME @@ -1256,7 +1379,7 @@ sock_gethostname(obj) struct utsname un; uname(&un); - return str_new2(un.nodename); + return rb_str_new2(un.nodename); } #else static VALUE @@ -1272,32 +1395,31 @@ static VALUE mkhostent(h) struct hostent *h; { - struct sockaddr_in addr; char **pch; VALUE ary, names; if (h == NULL) { #ifdef HAVE_HSTRERROR extern int h_errno; - Raise(eSocket, (char *)hstrerror(h_errno)); + rb_raise(rb_eSocket, (char *)hstrerror(h_errno)); #else - Raise(eSocket, "host not found"); + rb_raise(rb_eSocket, "host not found"); #endif } - ary = ary_new(); - ary_push(ary, str_new2(h->h_name)); - names = ary_new(); - ary_push(ary, names); + ary = rb_ary_new(); + rb_ary_push(ary, rb_str_new2(h->h_name)); + names = rb_ary_new(); + rb_ary_push(ary, names); for (pch = h->h_aliases; *pch; pch++) { - ary_push(names, str_new2(*pch)); + rb_ary_push(names, rb_str_new2(*pch)); } - ary_push(ary, INT2FIX(h->h_length)); + rb_ary_push(ary, NUM2INT(h->h_addrtype)); #ifdef h_addr for (pch = h->h_addr_list; *pch; pch++) { - ary_push(ary, str_new(*pch, h->h_length)); + rb_ary_push(ary, rb_str_new(*pch, h->h_length)); } #else - ary_push(ary, str_new(h->h_addr, h->h_length)); + rb_ary_push(ary, rb_str_new(h->h_addr, h->h_length)); #endif return ary; @@ -1310,13 +1432,12 @@ sock_s_gethostbyname(obj, host) struct sockaddr_in addr; struct hostent *h; - if (obj_is_kind_of(host, cInteger)) { + if (rb_obj_is_kind_of(host, rb_cInteger)) { int i = NUM2INT(host); addr.sin_addr.s_addr = htonl(i); } else { - Check_Type(host, T_STRING); - setipaddr(RSTRING(host)->ptr, &addr); + setipaddr(STR2CSTR(host), &addr); } h = gethostbyaddr((char *)&addr.sin_addr, sizeof(addr.sin_addr), @@ -1332,20 +1453,20 @@ sock_s_gethostbyaddr(argc, argv) { VALUE vaddr, vtype; int type; - - struct sockaddr_in *addr; + int alen; + char *addr; struct hostent *h; - rb_scan_args(argc, argv, "11", &addr, &type); - Check_Type(addr, T_STRING); - if (!NIL_P(type)) { + rb_scan_args(argc, argv, "11", &vaddr, &vtype); + addr = rb_str2cstr(vaddr, &alen); + if (!NIL_P(vtype)) { type = NUM2INT(vtype); } else { type = AF_INET; } - h = gethostbyaddr(RSTRING(addr)->ptr, RSTRING(addr)->len, type); + h = gethostbyaddr(addr, alen, type); return mkhostent(h); } @@ -1361,15 +1482,22 @@ sock_s_getservbyaname(argc, argv) int port; rb_scan_args(argc, argv, "11", &service, &protocol); - Check_Type(service, T_STRING); if (NIL_P(protocol)) proto = "tcp"; - else proto = RSTRING(protocol)->ptr; + else proto = STR2CSTR(protocol); - sp = getservbyname(RSTRING(service)->ptr, proto); - if (!sp) { - Raise(eSocket, "service/proto not found"); + sp = getservbyname(STR2CSTR(service), proto); + if (sp) { + port = ntohs(sp->s_port); + } + else { + char *s = STR2CSTR(service); + char *end; + + port = strtoul(s, &end, 0); + if (*end != '\0') { + rb_raise(rb_eSocket, "no such servce %s/%s", s, proto); + } } - port = ntohs(sp->s_port); return INT2FIX(port); } @@ -1377,225 +1505,240 @@ sock_s_getservbyaname(argc, argv) static VALUE mConst; static void -sock_define_const(name, value) +sock_rb_define_const(name, value) char *name; - INT value; + int value; { - rb_define_const(cSocket, name, INT2FIX(value)); + rb_define_const(rb_cSocket, name, INT2FIX(value)); rb_define_const(mConst, name, INT2FIX(value)); } Init_socket() { - eSocket = rb_define_class("SocketError", eException); - - cBasicSocket = rb_define_class("BasicSocket", cIO); - rb_undef_method(CLASS_OF(cBasicSocket), "new"); - rb_undef_method(CLASS_OF(cBasicSocket), "open"); - rb_define_method(cBasicSocket, "shutdown", bsock_shutdown, -1); - rb_define_method(cBasicSocket, "setsockopt", bsock_setsockopt, 3); - rb_define_method(cBasicSocket, "getsockopt", bsock_getsockopt, 2); - rb_define_method(cBasicSocket, "getsockname", bsock_getsockname, 0); - rb_define_method(cBasicSocket, "getpeername", bsock_getpeername, 0); - rb_define_method(cBasicSocket, "send", bsock_send, -1); - rb_define_method(cBasicSocket, "recv", bsock_recv, -1); - - cIPsocket = rb_define_class("IPsocket", cBasicSocket); - rb_define_method(cIPsocket, "addr", ip_addr, 0); - rb_define_method(cIPsocket, "peeraddr", ip_peeraddr, 0); - rb_define_singleton_method(cIPsocket, "getaddress", ip_s_getaddress, 1); - - cTCPsocket = rb_define_class("TCPsocket", cIPsocket); - rb_define_singleton_method(cTCPsocket, "open", tcp_s_open, 2); - rb_define_singleton_method(cTCPsocket, "new", tcp_s_open, 2); - rb_define_method(cTCPsocket, "recvfrom", tcp_recvfrom, -1); + rb_eSocket = rb_define_class("SocketError", rb_eStandardError); + + rb_cBasicSocket = rb_define_class("BasicSocket", rb_cIO); + rb_undef_method(CLASS_OF(rb_cBasicSocket), "new"); + rb_undef_method(CLASS_OF(rb_cBasicSocket), "open"); + rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0); + rb_define_method(rb_cBasicSocket, "close_write", bsock_close_write, 0); + rb_define_method(rb_cBasicSocket, "shutdown", bsock_shutdown, -1); + rb_define_method(rb_cBasicSocket, "setsockopt", bsock_setsockopt, 3); + rb_define_method(rb_cBasicSocket, "getsockopt", bsock_getsockopt, 2); + rb_define_method(rb_cBasicSocket, "getsockname", bsock_getsockname, 0); + rb_define_method(rb_cBasicSocket, "getpeername", bsock_getpeername, 0); + rb_define_method(rb_cBasicSocket, "send", bsock_send, -1); + rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1); + + rb_cIPsocket = rb_define_class("IPsocket", rb_cBasicSocket); + rb_define_method(rb_cIPsocket, "addr", ip_addr, 0); + rb_define_method(rb_cIPsocket, "peeraddr", ip_peeraddr, 0); + rb_define_singleton_method(rb_cIPsocket, "getaddress", ip_s_getaddress, 1); + + rb_cTCPsocket = rb_define_class("TCPsocket", rb_cIPsocket); + rb_define_singleton_method(rb_cTCPsocket, "open", tcp_s_open, 2); + rb_define_singleton_method(rb_cTCPsocket, "new", tcp_s_open, 2); + rb_define_singleton_method(rb_cTCPsocket, "gethostbyname", tcp_s_gethostbyname, 1); + rb_define_method(rb_cTCPsocket, "recvfrom", tcp_recvfrom, -1); #ifdef SOCKS - cSOCKSsocket = rb_define_class("SOCKSsocket", cTCPsocket); - rb_define_singleton_method(cSOCKSsocket, "open", socks_s_open, 2); - rb_define_singleton_method(cSOCKSsocket, "new", socks_s_open, 2); + rb_cSOCKSsocket = rb_define_class("SOCKSsocket", rb_cTCPsocket); + rb_define_singleton_method(rb_cSOCKSsocket, "open", socks_s_open, 2); + rb_define_singleton_method(rb_cSOCKSsocket, "new", socks_s_open, 2); #endif - cTCPserver = rb_define_class("TCPserver", cTCPsocket); - rb_define_singleton_method(cTCPserver, "open", tcp_svr_s_open, -1); - rb_define_singleton_method(cTCPserver, "new", tcp_svr_s_open, -1); - rb_define_method(cTCPserver, "accept", tcp_accept, 0); + rb_cTCPserver = rb_define_class("TCPserver", rb_cTCPsocket); + rb_define_singleton_method(rb_cTCPserver, "open", tcp_svr_s_open, -1); + rb_define_singleton_method(rb_cTCPserver, "new", tcp_svr_s_open, -1); + rb_define_method(rb_cTCPserver, "accept", tcp_accept, 0); - cUDPsocket = rb_define_class("UDPsocket", cIPsocket); - rb_define_singleton_method(cUDPsocket, "open", udp_s_open, 0); - rb_define_singleton_method(cUDPsocket, "new", udp_s_open, 0); - rb_define_method(cUDPsocket, "connect", udp_connect, 2); - rb_define_method(cUDPsocket, "bind", udp_bind, 2); - rb_define_method(cUDPsocket, "send", udp_send, -1); - rb_define_method(cUDPsocket, "recvfrom", udp_recvfrom, -1); + rb_cUDPsocket = rb_define_class("UDPsocket", rb_cIPsocket); + rb_define_singleton_method(rb_cUDPsocket, "open", udp_s_open, 0); + rb_define_singleton_method(rb_cUDPsocket, "new", udp_s_open, 0); + rb_define_method(rb_cUDPsocket, "connect", udp_connect, 2); + rb_define_method(rb_cUDPsocket, "bind", udp_bind, 2); + rb_define_method(rb_cUDPsocket, "send", udp_send, -1); + rb_define_method(rb_cUDPsocket, "recvfrom", udp_recvfrom, -1); #ifdef HAVE_SYS_UN_H - cUNIXsocket = rb_define_class("UNIXsocket", cBasicSocket); - rb_define_singleton_method(cUNIXsocket, "open", unix_s_sock_open, 1); - rb_define_singleton_method(cUNIXsocket, "new", unix_s_sock_open, 1); - rb_define_method(cUNIXsocket, "path", unix_path, 0); - rb_define_method(cUNIXsocket, "addr", unix_addr, 0); - rb_define_method(cUNIXsocket, "peeraddr", unix_peeraddr, 0); - rb_define_method(cUNIXsocket, "recvfrom", unix_recvfrom, -1); - - cUNIXserver = rb_define_class("UNIXserver", cUNIXsocket); - rb_define_singleton_method(cUNIXserver, "open", unix_svr_s_open, 1); - rb_define_singleton_method(cUNIXserver, "new", unix_svr_s_open, 1); - rb_define_method(cUNIXserver, "accept", unix_accept, 0); -#endif - - cSocket = rb_define_class("Socket", cBasicSocket); - rb_define_singleton_method(cSocket, "open", sock_s_open, 3); - rb_define_singleton_method(cSocket, "new", sock_s_open, 3); - rb_define_singleton_method(cSocket, "for_fd", sock_s_for_fd, 1); - - rb_define_method(cSocket, "connect", sock_connect, 1); - rb_define_method(cSocket, "bind", sock_bind, 1); - rb_define_method(cSocket, "listen", sock_listen, 1); - rb_define_method(cSocket, "accept", sock_accept, 0); - - rb_define_method(cSocket, "recvfrom", sock_recvfrom, -1); - - rb_define_singleton_method(cSocket, "socketpair", sock_s_socketpair, 3); - rb_define_singleton_method(cSocket, "pair", sock_s_socketpair, 3); - rb_define_singleton_method(cSocket, "gethostname", sock_gethostname, 0); - rb_define_singleton_method(cSocket, "gethostbyname", sock_s_gethostbyname, 1); - rb_define_singleton_method(cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1); - rb_define_singleton_method(cSocket, "getservbyname", sock_s_getservbyaname, -1); + rb_cUNIXsocket = rb_define_class("UNIXsocket", rb_cBasicSocket); + rb_define_singleton_method(rb_cUNIXsocket, "open", unix_s_sock_open, 1); + rb_define_singleton_method(rb_cUNIXsocket, "new", unix_s_sock_open, 1); + rb_define_method(rb_cUNIXsocket, "path", unix_path, 0); + rb_define_method(rb_cUNIXsocket, "addr", unix_addr, 0); + rb_define_method(rb_cUNIXsocket, "peeraddr", unix_peeraddr, 0); + rb_define_method(rb_cUNIXsocket, "recvfrom", unix_recvfrom, -1); + + rb_cUNIXserver = rb_define_class("UNIXserver", rb_cUNIXsocket); + rb_define_singleton_method(rb_cUNIXserver, "open", unix_svr_s_open, 1); + rb_define_singleton_method(rb_cUNIXserver, "new", unix_svr_s_open, 1); + rb_define_method(rb_cUNIXserver, "accept", unix_accept, 0); +#endif + + rb_cSocket = rb_define_class("Socket", rb_cBasicSocket); + rb_define_singleton_method(rb_cSocket, "open", sock_s_open, 3); + rb_define_singleton_method(rb_cSocket, "new", sock_s_open, 3); + rb_define_singleton_method(rb_cSocket, "for_fd", sock_s_for_fd, 1); + + rb_define_method(rb_cSocket, "connect", sock_connect, 1); + rb_define_method(rb_cSocket, "bind", sock_bind, 1); + rb_define_method(rb_cSocket, "listen", sock_listen, 1); + rb_define_method(rb_cSocket, "accept", sock_accept, 0); + + rb_define_method(rb_cSocket, "recvfrom", sock_recvfrom, -1); + + rb_define_singleton_method(rb_cSocket, "socketpair", sock_s_socketpair, 3); + rb_define_singleton_method(rb_cSocket, "pair", sock_s_socketpair, 3); + rb_define_singleton_method(rb_cSocket, "gethostname", sock_gethostname, 0); + rb_define_singleton_method(rb_cSocket, "gethostbyname", sock_s_gethostbyname, 1); + rb_define_singleton_method(rb_cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1); + rb_define_singleton_method(rb_cSocket, "getservbyname", sock_s_getservbyaname, -1); /* constants */ - mConst = rb_define_module_under(cSocket, "Constants"); - sock_define_const("SOCK_STREAM", SOCK_STREAM); - sock_define_const("SOCK_DGRAM", SOCK_DGRAM); - sock_define_const("SOCK_RAW", SOCK_RAW); + mConst = rb_define_module_under(rb_cSocket, "Constants"); + sock_rb_define_const("SOCK_STREAM", SOCK_STREAM); + sock_rb_define_const("SOCK_DGRAM", SOCK_DGRAM); +#ifdef SOCK_RAW + sock_rb_define_const("SOCK_RAW", SOCK_RAW); +#endif #ifdef SOCK_RDM - sock_define_const("SOCK_RDM", SOCK_RDM); + sock_rb_define_const("SOCK_RDM", SOCK_RDM); #endif #ifdef SOCK_SEQPACKET - sock_define_const("SOCK_SEQPACKET", SOCK_SEQPACKET); + sock_rb_define_const("SOCK_SEQPACKET", SOCK_SEQPACKET); #endif #ifdef SOCK_PACKET - sock_define_const("SOCK_PACKET", SOCK_PACKET); + sock_rb_define_const("SOCK_PACKET", SOCK_PACKET); #endif - sock_define_const("AF_INET", AF_INET); - sock_define_const("PF_INET", PF_INET); + sock_rb_define_const("AF_INET", AF_INET); +#ifdef PF_INET + sock_rb_define_const("PF_INET", PF_INET); +#endif #ifdef AF_UNIX - sock_define_const("AF_UNIX", AF_UNIX); - sock_define_const("PF_UNIX", PF_UNIX); + sock_rb_define_const("AF_UNIX", AF_UNIX); + sock_rb_define_const("PF_UNIX", PF_UNIX); #endif #ifdef AF_AX25 - sock_define_const("AF_AX25", AF_AX25); - sock_define_const("PF_AX25", PF_AX25); + sock_rb_define_const("AF_AX25", AF_AX25); + sock_rb_define_const("PF_AX25", PF_AX25); #endif #ifdef AF_IPX - sock_define_const("AF_IPX", AF_IPX); - sock_define_const("PF_IPX", PF_IPX); + sock_rb_define_const("AF_IPX", AF_IPX); + sock_rb_define_const("PF_IPX", PF_IPX); #endif #ifdef AF_APPLETALK - sock_define_const("AF_APPLETALK", AF_APPLETALK); - sock_define_const("PF_APPLETALK", PF_APPLETALK); + sock_rb_define_const("AF_APPLETALK", AF_APPLETALK); + sock_rb_define_const("PF_APPLETALK", PF_APPLETALK); #endif - sock_define_const("MSG_OOB", MSG_OOB); - sock_define_const("MSG_PEEK", MSG_PEEK); - sock_define_const("MSG_DONTROUTE", MSG_DONTROUTE); + sock_rb_define_const("MSG_OOB", MSG_OOB); +#ifdef MSG_PEEK + sock_rb_define_const("MSG_PEEK", MSG_PEEK); +#endif +#ifdef MSG_DONTROUTE + sock_rb_define_const("MSG_DONTROUTE", MSG_DONTROUTE); +#endif - sock_define_const("SOL_SOCKET", SOL_SOCKET); + sock_rb_define_const("SOL_SOCKET", SOL_SOCKET); #ifdef SOL_IP - sock_define_const("SOL_IP", SOL_IP); + sock_rb_define_const("SOL_IP", SOL_IP); #endif #ifdef SOL_IPX - sock_define_const("SOL_IPX", SOL_IPX); + sock_rb_define_const("SOL_IPX", SOL_IPX); #endif #ifdef SOL_AX25 - sock_define_const("SOL_AX25", SOL_AX25); + sock_rb_define_const("SOL_AX25", SOL_AX25); #endif #ifdef SOL_ATALK - sock_define_const("SOL_ATALK", SOL_ATALK); + sock_rb_define_const("SOL_ATALK", SOL_ATALK); #endif #ifdef SOL_TCP - sock_define_const("SOL_TCP", SOL_TCP); + sock_rb_define_const("SOL_TCP", SOL_TCP); #endif #ifdef SOL_UDP - sock_define_const("SOL_UDP", SOL_UDP); + sock_rb_define_const("SOL_UDP", SOL_UDP); #endif #ifdef SO_DEBUG - sock_define_const("SO_DEBUG", SO_DEBUG); + sock_rb_define_const("SO_DEBUG", SO_DEBUG); #endif - sock_define_const("SO_REUSEADDR", SO_REUSEADDR); + sock_rb_define_const("SO_REUSEADDR", SO_REUSEADDR); #ifdef SO_TYPE - sock_define_const("SO_TYPE", SO_TYPE); + sock_rb_define_const("SO_TYPE", SO_TYPE); #endif #ifdef SO_ERROR - sock_define_const("SO_ERROR", SO_ERROR); + sock_rb_define_const("SO_ERROR", SO_ERROR); #endif #ifdef SO_DONTROUTE - sock_define_const("SO_DONTROUTE", SO_DONTROUTE); + sock_rb_define_const("SO_DONTROUTE", SO_DONTROUTE); #endif #ifdef SO_BROADCAST - sock_define_const("SO_BROADCAST", SO_BROADCAST); + sock_rb_define_const("SO_BROADCAST", SO_BROADCAST); #endif #ifdef SO_SNDBUF - sock_define_const("SO_SNDBUF", SO_SNDBUF); + sock_rb_define_const("SO_SNDBUF", SO_SNDBUF); #endif #ifdef SO_RCVBUF - sock_define_const("SO_RCVBUF", SO_RCVBUF); + sock_rb_define_const("SO_RCVBUF", SO_RCVBUF); +#endif +#ifdef SO_KEEPALIVE + sock_rb_define_const("SO_KEEPALIVE", SO_KEEPALIVE); #endif - sock_define_const("SO_KEEPALIVE", SO_KEEPALIVE); #ifdef SO_OOBINLINE - sock_define_const("SO_OOBINLINE", SO_OOBINLINE); + sock_rb_define_const("SO_OOBINLINE", SO_OOBINLINE); #endif #ifdef SO_NO_CHECK - sock_define_const("SO_NO_CHECK", SO_NO_CHECK); + sock_rb_define_const("SO_NO_CHECK", SO_NO_CHECK); #endif #ifdef SO_PRIORITY - sock_define_const("SO_PRIORITY", SO_PRIORITY); + sock_rb_define_const("SO_PRIORITY", SO_PRIORITY); +#endif +#ifdef SO_LINGER + sock_rb_define_const("SO_LINGER", SO_LINGER); #endif - sock_define_const("SO_LINGER", SO_LINGER); #ifdef SOPRI_INTERACTIVE - sock_define_const("SOPRI_INTERACTIVE", SOPRI_INTERACTIVE); + sock_rb_define_const("SOPRI_INTERACTIVE", SOPRI_INTERACTIVE); #endif #ifdef SOPRI_NORMAL - sock_define_const("SOPRI_NORMAL", SOPRI_NORMAL); + sock_rb_define_const("SOPRI_NORMAL", SOPRI_NORMAL); #endif #ifdef SOPRI_BACKGROUND - sock_define_const("SOPRI_BACKGROUND", SOPRI_BACKGROUND); + sock_rb_define_const("SOPRI_BACKGROUND", SOPRI_BACKGROUND); #endif #ifdef IP_MULTICAST_IF - sock_define_const("IP_MULTICAST_IF", IP_MULTICAST_IF); + sock_rb_define_const("IP_MULTICAST_IF", IP_MULTICAST_IF); #endif #ifdef IP_MULTICAST_TTL - sock_define_const("IP_MULTICAST_TTL", IP_MULTICAST_TTL); + sock_rb_define_const("IP_MULTICAST_TTL", IP_MULTICAST_TTL); #endif #ifdef IP_MULTICAST_LOOP - sock_define_const("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP); + sock_rb_define_const("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP); #endif #ifdef IP_ADD_MEMBERSHIP - sock_define_const("IP_ADD_MEMBERSHIP", IP_ADD_MEMBERSHIP); + sock_rb_define_const("IP_ADD_MEMBERSHIP", IP_ADD_MEMBERSHIP); #endif #ifdef IP_DEFAULT_MULTICAST_TTL - sock_define_const("IP_DEFAULT_MULTICAST_TTL", IP_DEFAULT_MULTICAST_TTL); + sock_rb_define_const("IP_DEFAULT_MULTICAST_TTL", IP_DEFAULT_MULTICAST_TTL); #endif #ifdef IP_DEFAULT_MULTICAST_LOOP - sock_define_const("IP_DEFAULT_MULTICAST_LOOP", IP_DEFAULT_MULTICAST_LOOP); + sock_rb_define_const("IP_DEFAULT_MULTICAST_LOOP", IP_DEFAULT_MULTICAST_LOOP); #endif #ifdef IP_MAX_MEMBERSHIPS - sock_define_const("IP_MAX_MEMBERSHIPS", IP_MAX_MEMBERSHIPS); + sock_rb_define_const("IP_MAX_MEMBERSHIPS", IP_MAX_MEMBERSHIPS); #endif #ifdef IPX_TYPE - sock_define_const("IPX_TYPE", IPX_TYPE); + sock_rb_define_const("IPX_TYPE", IPX_TYPE); #endif #ifdef TCP_NODELAY - sock_define_const("TCP_NODELAY", TCP_NODELAY); + sock_rb_define_const("TCP_NODELAY", TCP_NODELAY); #endif #ifdef TCP_MAXSEG - sock_define_const("TCP_MAXSEG", TCP_MAXSEG); + sock_rb_define_const("TCP_MAXSEG", TCP_MAXSEG); #endif } diff --git a/ext/tcltklib/extconf.rb b/ext/tcltklib/extconf.rb index 26e7fe7b09..e34e549ca0 100644 --- a/ext/tcltklib/extconf.rb +++ b/ext/tcltklib/extconf.rb @@ -1,19 +1,27 @@ # extconf.rb for tcltklib +require 'mkmf' + +have_library("nsl", "t_open") have_library("socket", "socket") -have_library("nsl", "gethostbyname") +have_library("dl", "dlopen") +have_library("m", "log") -def search_file(var, include, *path) +$includes = [] +def search_header(include, *path) pwd = Dir.getwd begin - for i in path.reverse! + for i in path.sort!.reverse! dir = Dir[i] - for path in dir + for path in dir.sort!.reverse! + next unless File.directory? path Dir.chdir path files = Dir[include] if files.size > 0 - var << path - return files.pop + unless $includes.include? path + $includes << path + end + return end end end @@ -22,58 +30,56 @@ def search_file(var, include, *path) end end -$includes = [] -search_file($includes, - "tcl.h", - "/usr/include/tcl*", - "/usr/include", - "/usr/local/include/tcl*", - "/usr/local/include") -search_file($includes, - "tk.h", - "/usr/include/tk*", - "/usr/include", - "/usr/local/include/tk*", - "/usr/local/include") -search_file($includes, - "X11/Xlib.h", - "/usr/include", - "/usr/X11*/include", - "/usr/include", - "/usr/X11*/include") +search_header("tcl.h", + "/usr/include/tcl{,8*,7*}", + "/usr/include", + "/usr/local/include/tcl{,8*,7*}", + "/usr/local/include") +search_header("tk.h", + "/usr/include/tk{,8*,4*}", + "/usr/include", + "/usr/local/include/tk{,8*,4*}", + "/usr/local/include") +search_header("X11/Xlib.h", + "/usr/include/X11*", + "/usr/include", + "/usr/openwin/include", + "/usr/X11*/include") -$CFLAGS = "-Wall " + $includes.collect{|path| "-I" + path}.join(" ") +$CFLAGS = $includes.collect{|path| "-I" + path}.join(" ") $libraries = [] -tcllibfile = search_file($libraries, - "libtcl{,7*,8*}.{a,so}", - "/usr/lib", - "/usr/local/lib") -if tcllibfile - tcllibfile.sub!(/^lib/, '') - tcllibfile.sub!(/\.(a|so)$/, '') -end -tklibfile = search_file($libraries, - "libtk{,4*,8*}.{a,so}", - "/usr/lib", - "/usr/local/lib") -if tklibfile - tklibfile.sub!(/^lib/, '') - tklibfile.sub!(/\.(a|so)$/, '') +def search_lib(file, func, *path) + for i in path.reverse! + dir = Dir[i] + for path in dir.sort!.reverse! + $LDFLAGS = $libraries.collect{|p| "-L" + p}.join(" ") + " -L" + path + files = Dir[path+"/"+file] + if files.size > 0 + for lib in files.sort!.reverse! + lib = File::basename(lib) + lib.sub!(/^lib/, '') + lib.sub!(/\.(a|so)$/, '') + if have_library(lib, func) + unless $libraries.include? path + $libraries << path + end + return true + end + end + end + end + end + return false; end -search_file($libraries, - "libX11.{a,so}", - "/usr/lib", - "/usr/X11*/lib") -$LDFLAGS = $libraries.collect{|path| "-L" + path}.join(" ") - -have_library("dl", "dlopen") -if have_header("tcl.h") && - have_header("tk.h") && - have_library("X11", "XOpenDisplay") && - have_library("m", "log") && - have_library(tcllibfile, "Tcl_FindExecutable") && - have_library(tklibfile, "Tk_Init") +if have_header("tcl.h") && have_header("tk.h") && + search_lib("libX11.{so,a}", "XOpenDisplay", + "/usr/lib", "/usr/openwin/lib", "/usr/X11*/lib") && + search_lib("libtcl{8*,7*,}.{so,a}", "Tcl_FindExecutable", + "/usr/lib", "/usr/local/lib") && + search_lib("libtk{8*,4*,}.{so,a}", "Tk_Init", + "/usr/lib", "/usr/local/lib") + $LDFLAGS = $libraries.collect{|path| "-L" + path}.join(" ") create_makefile("tcltklib") end diff --git a/ext/tcltklib/lib/tcltk.rb b/ext/tcltklib/lib/tcltk.rb index 81d01f930d..54a00e8f3c 100644 --- a/ext/tcltklib/lib/tcltk.rb +++ b/ext/tcltklib/lib/tcltk.rb @@ -1,48 +1,44 @@ # tof -#### tcltk ライブラリ +#### tcltk library, more direct manipulation of tcl/tk #### Sep. 5, 1997 Y. Shigehiro require "tcltklib" ################ -# module TclTk: tcl/tk のライブラリ全体で必要になるものを集めたもの -# (主に, 名前空間の点から module にする使う.) +# module TclTk: collection of tcl/tk utilities (supplies namespace.) module TclTk - # 単にここに書けば最初に 1 度実行されるのか?? - - # 生成した一意な名前を保持しておく連想配列を初期化する. + # initialize Hash to hold unique symbols and such @namecnt = {} - # コールバックを保持しておく連想配列を初期化する. + # initialize Hash to hold callbacks @callback = {} end -# TclTk.mainloop(): TclTkLib.mainloop() を呼ぶ. +# TclTk.mainloop(): call TclTkLib.mainloop() def TclTk.mainloop() print("mainloop: start\n") if $DEBUG TclTkLib.mainloop() print("mainloop: end\n") if $DEBUG end -# TclTk.deletecallbackkey(ca): コールバックを TclTk module から取り除く. -# tcl/tk インタプリタにおいてコールバックが取り消されるわけではない. -# これをしないと, 最後に TclTkInterpreter が GC できない. -# (GC したくなければ, 別に, これをしなくても良い.) -# ca: コールバック(TclTkCallback) +# TclTk.deletecallbackkey(ca): remove callback from TclTk module +# this does not remove callbacks from tcl/tk interpreter +# without calling this method, TclTkInterpreter will not be GCed +# ca: callback(TclTkCallback) def TclTk.deletecallbackkey(ca) print("deletecallbackkey: ", ca.to_s(), "\n") if $DEBUG @callback.delete(ca.to_s) end -# TclTk.dcb(ca, wid, W): 配列に入っている複数のコールバックに対して -# TclTk.deletecallbackkey() を呼ぶ. -# トップレベルの <Destroy> イベントのコールバックとして呼ぶためのもの. -# ca: コールバック(TclTkCallback) の Array -# wid: トップレベルのウィジェット(TclTkWidget) -# w: コールバックに %W で与えられる, ウインドウに関するパラメータ(String) +# TclTk.dcb(ca, wid, W): call TclTk.deletecallbackkey() for each callbacks +# in an array. +# this is for callback for top-level <Destroy> +# ca: array of callbacks(TclTkCallback) +# wid: top-level widget(TclTkWidget) +# w: information about window given by %W(String) def TclTk.dcb(ca, wid, w) if wid.to_s() == w ca.each{|i| @@ -51,33 +47,33 @@ def TclTk.dcb(ca, wid, w) end end -# TclTk._addcallback(ca): コールバックを登録する. -# ca: コールバック(TclTkCallback) +# TclTk._addcallback(ca): register callback +# ca: callback(TclTkCallback) def TclTk._addcallback(ca) print("_addcallback: ", ca.to_s(), "\n") if $DEBUG @callback[ca.to_s()] = ca end -# TclTk._callcallback(key, arg): 登録したコールバックを呼び出す. -# key: コールバックを選択するキー (TclTkCallback が to_s() で返す値) -# arg: tcl/tk インタプリタからのパラメータ +# TclTk._callcallback(key, arg): invoke registered callback +# key: key to select callback (to_s value of the TclTkCallback) +# arg: parameter from tcl/tk interpreter def TclTk._callcallback(key, arg) print("_callcallback: ", @callback[key].inspect, "\n") if $DEBUG @callback[key]._call(arg) - # コールバックからの返り値はどうせ捨てられる. - # String を返さないと, rb_eval_string() がエラーになる. + # throw out callback value + # should return String to satisfy rb_eval_string() return "" end -# TclTk._newname(prefix): 一意な名前(String)を生成して返す. -# prefix: 名前の接頭語 +# TclTk._newname(prefix): generate unique name(String) +# prefix: prefix of the unique name def TclTk._newname(prefix) - # 生成した名前のカウンタは @namecnt に入っているので, 調べる. + # generated name counter is stored in @namecnt if !@namecnt.key?(prefix) - # 初めて使う接頭語なので初期化する. + # first appearing prefix, initialize @namecnt[prefix] = 1 else - # 使ったことのある接頭語なので, 次の名前にする. + # already appeared prefix, generate next name @namecnt[prefix] += 1 end return "#{prefix}#{@namecnt[prefix]}" @@ -85,51 +81,48 @@ end ################ -# class TclTkInterpreter: tcl/tk のインタプリタ +# class TclTkInterpreter: tcl/tk interpreter class TclTkInterpreter - # initialize(): 初期化. + # initialize(): def initialize() - # インタプリタを生成する. + # generate interpreter object @ip = TclTkIp.new() - # インタプリタに ruby_fmt コマンドを追加する. - # ruby_fmt コマンドとは, 後ろの引数を format コマンドで処理して - # ruby コマンドに渡すものである. - # (なお, ruby コマンドは, 引数を 1 つしかとれない.) + # add ruby_fmt command to tcl interpreter + # ruby_fmt command format arguments by `format' and call `ruby' command + # (notice ruby command receives only one argument) if $DEBUG @ip._eval("proc ruby_fmt {fmt args} { puts \"ruby_fmt: $fmt $args\" ; ruby [format $fmt $args] }") else @ip._eval("proc ruby_fmt {fmt args} { ruby [format $fmt $args] }") end - # @ip._get_eval_string(*args): tcl/tk インタプリタで評価する - # 文字列(String)を生成して返す. - # *args: tcl/tk で評価するスクリプト(に対応するオブジェクト列) + # @ip._get_eval_string(*args): generate string to evaluate in tcl interpreter + # *args: script which is going to be evaluated under tcl/tk def @ip._get_eval_string(*args) argstr = "" args.each{|arg| argstr += " " if argstr != "" - # もし to_eval() メソッドが + # call to_eval if it is defined if (arg.respond_to?(:to_eval)) - # 定義されていればそれを呼ぶ. argstr += arg.to_eval() else - # 定義されていなければ to_s() を呼ぶ. + # call to_s unless defined argstr += arg.to_s() end } return argstr end - # @ip._eval_args(*args): tcl/tk インタプリタで評価し, - # その結果(String)を返す. - # *args: tcl/tk で評価するスクリプト(に対応するオブジェクト列) + # @ip._eval_args(*args): evaluate string under tcl/tk interpreter + # returns result string. + # *args: script which is going to be evaluated under tcl/tk def @ip._eval_args(*args) - # インタプリタで評価する文字列を求める. + # calculate the string to eval in the interpreter argstr = _get_eval_string(*args) - # インタプリタで評価する. + # evaluate under the interpreter print("_eval: \"", argstr, "\"") if $DEBUG res = _eval(argstr) if $DEBUG @@ -137,219 +130,205 @@ class TclTkInterpreter elsif _return_value() != 0 print(res, "\n") end - fail(%Q/can't eval "#{argstr}"/) if _return_value() != 0 + fail(%Q/can't eval "#{argstr}"/) if _return_value() != 0 #' return res end - # tcl/tk のコマンドに対応するオブジェクトを生成し, 連想配列に入れておく. + # generate tcl/tk command object and register in the hash @commands = {} - # tcl/tk インタプリタに登録されているすべてのコマンドに対して, + # for all commands registered in tcl/tk interpreter: @ip._eval("info command").split(/ /).each{|comname| if comname =~ /^[.]/ - # コマンドがウィジェット(のパス名)の場合は - # TclTkWidget のインスタンスを作って連想配列に入れる. + # if command is a widget (path), generate TclTkWidget, + # and register it in the hash @commands[comname] = TclTkWidget.new(@ip, comname) else - # そうでない場合は - # TclTkCommand のインスタンスを作って連想配列に入れる. + # otherwise, generate TclTkCommand @commands[comname] = TclTkCommand.new(@ip, comname) end } end - # commands(): tcl/tk のコマンドに対応するオブジェクトを Hash に - # 入れたものを返す. + # commands(): returns hash of the tcl/tk commands def commands() return @commands end - # rootwidget(): ルートウィジェット(TclTkWidget)を返す. + # rootwidget(): returns root widget(TclTkWidget) def rootwidget() return @commands["."] end - # _tcltkip(): @ip(TclTkIp) を返す. + # _tcltkip(): returns @ip(TclTkIp) def _tcltkip() return @ip end - # method_missing(id, *args): 未定義のメソッドは tcl/tk のコマンドとみなして - # 実行し, その結果(String)を返す. - # id: メソッドのシンボル - # *args: コマンドの引数 + # method_missing(id, *args): execute undefined method as tcl/tk command + # id: method symbol + # *args: method arguments def method_missing(id, *args) - # もし, メソッドの tcl/tk コマンドが + # if command named by id registered, then execute it if @commands.key?(id.id2name) - # あれば, 実行して結果を返す. return @commands[id.id2name].e(*args) else - # 無ければもともとの処理. + # otherwise, exception super end end end -# class TclTkObject: tcl/tk のオブジェクト -# (基底クラスとして使う. -# tcltk ライブラリを使う人が TclTkObject.new() することはないはず.) +# class TclTkObject: base class of the tcl/tk objects class TclTkObject - # initialize(ip, exp): 初期化. - # ip: インタプリタ(TclTkIp) - # exp: tcl/tk での表現形 + # initialize(ip, exp): + # ip: interpreter(TclTkIp) + # exp: tcl/tk representation def initialize(ip, exp) fail("type is not TclTkIp") if !ip.kind_of?(TclTkIp) @ip = ip @exp = exp end - # to_s(): tcl/tk での表現形(String)を返す. + # to_s(): returns tcl/tk representation def to_s() return @exp end end -# class TclTkCommand: tcl/tk のコマンド -# (tcltk ライブラリを使う人が TclTkCommand.new() することはないはず. -# TclTkInterpreter:initialize() から new() される.) +# class TclTkCommand: tcl/tk commands +# you should not call TclTkCommand.new() +# commands are created by TclTkInterpreter:initialize() class TclTkCommand < TclTkObject - # e(*args): コマンドを実行し, その結果(String)を返す. - # (e は exec または eval の e.) - # *args: コマンドの引数 + # e(*args): execute command. returns String (e is for exec or eval) + # *args: command arguments def e(*args) return @ip._eval_args(to_s(), *args) end end -# class TclTkLibCommand: tcl/tk のコマンド -# (ライブラリにより実現されるコマンドで, tcl/tk インタプリタに最初から -# 存在しないものは, インタプリタの commands() では生成できない. -# そのようなものに対し, コマンドの名前から TclTkCommand オブジェクトを -# 生成する. +# class TclTkLibCommand: tcl/tk commands in the library class TclTkLibCommand < TclTkCommand - # initialize(ip, name): 初期化 - # ip: インタプリタ(TclTkInterpreter) - # name: コマンド名 (String) + # initialize(ip, name): + # ip: interpreter(TclTkInterpreter) + # name: command name (String) def initialize(ip, name) super(ip._tcltkip, name) end end -# class TclTkVariable: tcl/tk の変数 +# class TclTkVariable: tcl/tk variable class TclTkVariable < TclTkObject - # initialize(interp, dat): 初期化. - # interp: インタプリタ(TclTkInterpreter) - # dat: 設定する値(String) - # nil なら, 設定しない. + # initialize(interp, dat): + # interp: interpreter(TclTkInterpreter) + # dat: the value to set(String) + # if nil, not initialize variable def initialize(interp, dat) - # tcl/tk での表現形(変数名)を自動生成する. + # auto-generate tcl/tk representation (variable name) exp = TclTk._newname("v_") - # TclTkObject を初期化する. + # initialize TclTkObject super(interp._tcltkip(), exp) - # set コマンドを使うのでとっておく. + # safe this for `set' command @set = interp.commands()["set"] - # 値を設定する. + # set value set(dat) if dat end - # tcl/tk の set を使えば, 値の設定/参照はできるが, - # それだけではなんなので, 一応, メソッドをかぶせたものも用意しておく. + # although you can set/refer variable by using set in tcl/tk, + # we provide the method for accessing variables - # set(data): tcl/tk の変数に set を用いて値を設定する. - # data: 設定する値 + # set(data): set tcl/tk variable using `set' + # data: new value def set(data) @set.e(to_s(), data.to_s()) end - # get(): tcl/tk の変数の値(String)を set を用いて読みだし返す. + # get(): read tcl/tk variable(String) using `set' def get() return @set.e(to_s()) end end -# class TclTkWidget: tcl/tk のウィジェット +# class TclTkWidget: tcl/tk widget class TclTkWidget < TclTkCommand - # initialize(*args): 初期化. - # *args: パラメータ + # initialize(*args): + # *args: parameters def initialize(*args) if args[0].kind_of?(TclTkIp) - # 最初の引数が TclTkIp の場合: + # in case the 1st argument is TclTkIp: - # 既に tcl/tk に定義されているウィジェットに TclTkWidget の構造を - # かぶせる. (TclTkInterpreter:initialize() から使われる.) + # Wrap tcl/tk widget by TclTkWidget + # (used in TclTkInterpreter#initialize()) - # パラメータ数が 2 でなければエラー. + # need two arguments fail("illegal # of parameter") if args.size != 2 - # ip: インタプリタ(TclTkIp) - # exp: tcl/tk での表現形 + # ip: interpreter(TclTkIp) + # exp: tcl/tk representation ip, exp = args - # TclTkObject を初期化する. + # initialize TclTkObject super(ip, exp) elsif args[0].kind_of?(TclTkInterpreter) - # 最初の引数が TclTkInterpreter の場合: + # in case 1st parameter is TclTkInterpreter: - # 親ウィジェットから新たなウィジェトを生成する. + # generate new widget from parent widget - # interp: インタプリタ(TclTkInterpreter) - # parent: 親ウィジェット - # command: ウィジェットを生成するコマンド(label 等) - # *args: command に渡す引数 + # interp: interpreter(TclTkInterpreter) + # parent: parent widget + # command: widget generating tk command(label 等) + # *args: argument to the command interp, parent, command, *args = args - # ウィジェットの名前を作る. + # generate widget name exp = parent.to_s() exp += "." if exp !~ /[.]$/ exp += TclTk._newname("w_") - # TclTkObject を初期化する. + # initialize TclTkObject super(interp._tcltkip(), exp) - # ウィジェットを生成する. + # generate widget res = @ip._eval_args(command, exp, *args) # fail("can't create Widget") if res != exp - # tk_optionMenu では, ボタン名を exp で指定すると - # res にメニュー名を返すので res != exp となる. + # for tk_optionMenu, it is legal res != exp else fail("first parameter is not TclTkInterpreter") end end end -# class TclTkCallback: tcl/tk のコールバック +# class TclTkCallback: tcl/tk callbacks class TclTkCallback < TclTkObject - # initialize(interp, pr, arg): 初期化. - # interp: インタプリタ(TclTkInterpreter) - # pr: コールバック手続き(Proc) - # arg: pr のイテレータ変数に渡す文字列 - # tcl/tk の bind コマンドではパラメータを受け取るために % 置換を - # 用いるが, pr の内部で % を書いてもうまくいかない. - # arg に文字列を書いておくと, その置換結果を, pr で - # イテレータ変数を通して受け取ることができる. - # scrollbar コマンドの -command オプションのように - # 何も指定しなくてもパラメータが付くコマンドに対しては, - # arg を指定してはならない. + # initialize(interp, pr, arg): + # interp: interpreter(TclTkInterpreter) + # pr: callback procedure(Proc) + # arg: string to pass as block parameters of pr + # bind command of tcl/tk uses % replacement for parameters + # pr can receive replaced data using block parameter + # its format is specified by arg string + # You should not specify arg for the command like + # scrollbar with -command option, which receives parameters + # without specifying any replacement def initialize(interp, pr, arg = nil) - # tcl/tk での表現形(変数名)を自動生成する. + # auto-generate tcl/tk representation (variable name) exp = TclTk._newname("c_") - # TclTkObject を初期化する. + # initialize TclTkObject super(interp._tcltkip(), exp) - # パラメータをとっておく. + # save parameters @pr = pr @arg = arg - # モジュールに登録しておく. + # register in the module TclTk._addcallback(self) end - # to_eval(): @ip._eval_args で評価するときの表現形(String)を返す. + # to_eval(): retuens string representation for @ip._eval_args def to_eval() if @arg - # %s は ruby_fmt より前に bind により置換されてしまうので - # %%s としてある. したがって, これは bind 専用. + # bind replaces %s before calling ruby_fmt, so %%s is used s = %Q/{ruby_fmt {TclTk._callcallback("#{to_s()}", "%%s")} #{@arg}}/ else s = %Q/{ruby_fmt {TclTk._callcallback("#{to_s()}", "%s")}}/ @@ -358,28 +337,28 @@ class TclTkCallback < TclTkObject return s end - # _call(arg): コールバックを呼び出す. - # arg: コールバックに渡されるパラメータ + # _call(arg): invoke callback + # arg: callback parameter def _call(arg) @pr.call(arg) end end -# class TclTkImage: tcl/tk のイメージ +# class TclTkImage: tcl/tk images class TclTkImage < TclTkCommand - # initialize(interp, t, *args): 初期化. - # イメージの生成は TclTkImage.new() で行うが, - # 破壊は image delete で行う. (いまいちだけど仕方が無い.) - # interp: インタプリタ(TclTkInterpreter) - # t: イメージのタイプ (photo, bitmap, etc.) - # *args: コマンドの引数 + # initialize(interp, t, *args): + # generating image is done by TclTkImage.new() + # destrying is done by image delete (inconsistent, sigh) + # interp: interpreter(TclTkInterpreter) + # t: image type (photo, bitmap, etc.) + # *args: command argument def initialize(interp, t, *args) - # tcl/tk での表現形(変数名)を自動生成する. + # auto-generate tcl/tk representation exp = TclTk._newname("i_") - # TclTkObject を初期化する. + # initialize TclTkObject super(interp._tcltkip(), exp) - # イメージを生成する. + # generate image res = @ip._eval_args("image create", t, exp, *args) fail("can't create Image") if res != exp end diff --git a/ext/tcltklib/tcltklib.c b/ext/tcltklib/tcltklib.c index e7fe77d2b7..625fe61ccc 100644 --- a/ext/tcltklib/tcltklib.c +++ b/ext/tcltklib/tcltklib.c @@ -5,22 +5,31 @@ */ #include "ruby.h" -#include "sig.h" +#include "rubysig.h" #include <stdio.h> #include <string.h> #include <tcl.h> #include <tk.h> -/* for debug */ +#ifdef __MACOS__ +# include <tkMac.h> +# include <Quickdraw.h> +#endif -#define DUMP1(ARG1) if (debug) { fprintf(stderr, "tcltklib: %s\n", ARG1);} -#define DUMP2(ARG1, ARG2) if (debug) { fprintf(stderr, "tcltklib: ");\ +/* for rb_debug */ + +#define DUMP1(ARG1) if (rb_debug) { fprintf(stderr, "tcltklib: %s\n", ARG1);} +#define DUMP2(ARG1, ARG2) if (rb_debug) { fprintf(stderr, "tcltklib: ");\ fprintf(stderr, ARG1, ARG2); fprintf(stderr, "\n"); } /* #define DUMP1(ARG1) #define DUMP2(ARG1, ARG2) */ +/* for callback break & continue */ +VALUE eTkCallbackBreak; +VALUE eTkCallbackContinue; + /* from tkAppInit.c */ /* @@ -33,26 +42,52 @@ int *tclDummyMathPtr = (int *) matherr; /*---- module TclTkLib ----*/ -static VALUE thread_safe = Qnil; +/* Tk_ThreadTimer */ +typedef struct { + Tcl_TimerToken token; + int flag; +} Tk_TimerData; + +/* timer callback */ +void _timer_for_tcl (ClientData clientData) +{ + Tk_TimerData *timer = (Tk_TimerData*)clientData; + + timer->flag = 0; + CHECK_INTS; +#ifdef USE_THREAD + if (!rb_thread_critical) rb_thread_schedule(); +#endif + + timer->token = Tk_CreateTimerHandler(200, _timer_for_tcl, + (ClientData)timer); + timer->flag = 1; +} /* execute Tk_MainLoop */ static VALUE lib_mainloop(VALUE self) { - int old_trapflg; - int flags = RTEST(thread_safe)?TCL_DONT_WAIT:0; + Tk_TimerData *timer; + + timer = (Tk_TimerData *) ckalloc(sizeof(Tk_TimerData)); + timer->flag = 0; + timer->token = Tk_CreateTimerHandler(200, _timer_for_tcl, + (ClientData)timer); + timer->flag = 1; DUMP1("start Tk_Mainloop"); while (Tk_GetNumMainWindows() > 0) { - old_trapflg = trap_immediate; - trap_immediate = 1; - Tcl_DoOneEvent(flags); - trap_immediate = old_trapflg; - CHECK_INTS; - flags = (thread_safe == 0 || thread_safe == Qnil)?0:TCL_DONT_WAIT; + Tcl_DoOneEvent(0); } DUMP1("stop Tk_Mainloop"); +#ifdef USE_THREAD + if (timer->flag) { + Tk_DeleteTimerHandler(timer->token); + } +#endif + return Qnil; } @@ -71,27 +106,49 @@ ip_eval_rescue(VALUE *failed, VALUE einfo) } static int +#if TCL_MAJOR_VERSION >= 8 +ip_ruby(ClientData clientData, Tcl_Interp *interp, + int argc, Tcl_Obj *CONST argv[]) +#else ip_ruby(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) +#endif { VALUE res; int old_trapflg; VALUE failed = 0; + char *arg; + int dummy; /* ruby command has 1 arg. */ if (argc != 2) { - ArgError("wrong # of arguments (%d for 1)", argc); + rb_raise(rb_eArgError, "wrong # of arguments (%d for 1)", argc); } + /* get C string from Tcl object */ +#if TCL_MAJOR_VERSION >= 8 + arg = Tcl_GetStringFromObj(argv[1], &dummy); +#else + arg = argv[1]; +#endif + /* evaluate the argument string by ruby */ - DUMP2("rb_eval_string(%s)", argv[1]); - old_trapflg = trap_immediate; - trap_immediate = 0; - res = rb_rescue(rb_eval_string, argv[1], ip_eval_rescue, &failed); - trap_immediate = old_trapflg; + DUMP2("rb_eval_string(%s)", arg); + old_trapflg = rb_trap_immediate; + rb_trap_immediate = 0; + res = rb_rescue(rb_eval_string, (VALUE)arg, ip_eval_rescue, (VALUE)&failed); + rb_trap_immediate = old_trapflg; + Tcl_ResetResult(interp); if (failed) { - Tcl_AppendResult(interp, RSTRING(failed)->ptr, (char*)NULL); - return TCL_ERROR; + VALUE eclass = CLASS_OF(failed); + Tcl_AppendResult(interp, STR2CSTR(failed), (char*)NULL); + if (eclass == eTkCallbackBreak) { + return TCL_BREAK; + } else if (eclass == eTkCallbackContinue) { + return TCL_CONTINUE; + } else { + return TCL_ERROR; + } } /* result must be string or nil */ @@ -99,12 +156,11 @@ ip_ruby(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) DUMP1("(rb_eval_string result) nil"); return TCL_OK; } - Check_Type(res, T_STRING); /* copy result to the tcl interpreter */ - DUMP2("(rb_eval_string result) %s", RSTRING(res)->ptr); + DUMP2("(rb_eval_string result) %s", STR2CSTR(res)); DUMP1("Tcl_AppendResult"); - Tcl_AppendResult(interp, RSTRING(res)->ptr, (char *)NULL); + Tcl_AppendResult(interp, STR2CSTR(res), (char *)NULL); return TCL_OK; } @@ -115,6 +171,7 @@ ip_free(struct tcltkip *ptr) { DUMP1("Tcl_DeleteInterp"); Tcl_DeleteInterp(ptr->ip); + free(ptr); } /* create and initialize interpreter */ @@ -135,20 +192,26 @@ ip_new(VALUE self) /* from Tcl_AppInit() */ DUMP1("Tcl_Init"); if (Tcl_Init(ptr->ip) == TCL_ERROR) { - Fail("Tcl_Init"); + rb_raise(rb_eRuntimeError, "Tcl_Init"); } DUMP1("Tk_Init"); if (Tk_Init(ptr->ip) == TCL_ERROR) { - Fail("Tk_Init"); + rb_raise(rb_eRuntimeError, "Tk_Init"); } DUMP1("Tcl_StaticPackage(\"Tk\")"); Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init, (Tcl_PackageInitProc *) NULL); /* add ruby command to the interpreter */ +#if TCL_MAJOR_VERSION >= 8 + DUMP1("Tcl_CreateObjCommand(\"ruby\")"); + Tcl_CreateObjCommand(ptr->ip, "ruby", ip_ruby, (ClientData *)NULL, + (Tcl_CmdDeleteProc *)NULL); +#else DUMP1("Tcl_CreateCommand(\"ruby\")"); Tcl_CreateCommand(ptr->ip, "ruby", ip_ruby, (ClientData *)NULL, (Tcl_CmdDeleteProc *)NULL); +#endif return obj; } @@ -157,6 +220,7 @@ ip_new(VALUE self) static VALUE ip_eval(VALUE self, VALUE str) { + char *s; char *buf; /* Tcl_Eval requires re-writable string region */ struct tcltkip *ptr; /* tcltkip data struct */ @@ -164,18 +228,162 @@ ip_eval(VALUE self, VALUE str) Data_Get_Struct(self, struct tcltkip, ptr); /* call Tcl_Eval() */ - Check_Type(str, T_STRING); - buf = ALLOCA_N(char,RSTRING(str)->len+1); - strcpy(buf, RSTRING(str)->ptr); + s = STR2CSTR(str); + buf = ALLOCA_N(char, strlen(s)+1); + strcpy(buf, s); DUMP2("Tcl_Eval(%s)", buf); ptr->return_value = Tcl_Eval(ptr->ip, buf); if (ptr->return_value == TCL_ERROR) { - Fail(ptr->ip->result); + rb_raise(rb_eRuntimeError, ptr->ip->result); } DUMP2("(TCL_Eval result) %d", ptr->return_value); /* pass back the result (as string) */ - return(str_new2(ptr->ip->result)); + return(rb_str_new2(ptr->ip->result)); +} + + +static VALUE +ip_toUTF8(VALUE self, VALUE str, VALUE encodename) +{ +#ifndef TCL_UTF_MAX + return str; +#else + Tcl_Interp *interp; + Tcl_Encoding encoding; + Tcl_DString dstr; + struct tcltkip *ptr; + char *buff1,*buff2; + + Data_Get_Struct(self,struct tcltkip, ptr); + interp = ptr->ip; + + encoding = Tcl_GetEncoding(interp,STR2CSTR(encodename)); + buff1 = ALLOCA_N(char,strlen(STR2CSTR(str))+1); + strcpy(buff1,STR2CSTR(str)); + + Tcl_DStringInit(&dstr); + Tcl_DStringFree(&dstr); + Tcl_ExternalToUtfDString(encoding,buff1,strlen(buff1),&dstr); + buff2 = ALLOCA_N(char,Tcl_DStringLength(&dstr)+1); + strcpy(buff2,Tcl_DStringValue(&dstr)); + + Tcl_FreeEncoding(encoding); + Tcl_DStringFree(&dstr); + + return rb_str_new2(buff2); +#endif +} + +static VALUE +ip_fromUTF8(VALUE self, VALUE str, VALUE encodename) +{ +#ifndef TCL_UTF_MAX + return str; +#else + Tcl_Interp *interp; + Tcl_Encoding encoding; + Tcl_DString dstr; + struct tcltkip *ptr; + char *buff1,*buff2; + + Data_Get_Struct(self,struct tcltkip, ptr); + interp = ptr->ip; + + encoding = Tcl_GetEncoding(interp,STR2CSTR(encodename)); + buff1 = ALLOCA_N(char,strlen(STR2CSTR(str))+1); + strcpy(buff1,STR2CSTR(str)); + + Tcl_DStringInit(&dstr); + Tcl_DStringFree(&dstr); + Tcl_UtfToExternalDString(encoding,buff1,strlen(buff1),&dstr); + buff2 = ALLOCA_N(char,Tcl_DStringLength(&dstr)+1); + strcpy(buff2,Tcl_DStringValue(&dstr)); + + Tcl_FreeEncoding(encoding); + Tcl_DStringFree(&dstr); + + return rb_str_new2(buff2); +#endif +} + + +static VALUE +ip_invoke(int argc, VALUE *argv, VALUE obj) +{ + struct tcltkip *ptr; /* tcltkip data struct */ + int i; + int object = 0; + Tcl_CmdInfo info; + char *cmd; + char **av = (char **)NULL; +#if TCL_MAJOR_VERSION >= 8 + Tcl_Obj **ov = (Tcl_Obj **)NULL; + Tcl_Obj *resultPtr; +#endif + + /* get the data struct */ + Data_Get_Struct(obj, struct tcltkip, ptr); + + /* get the command name string */ + cmd = STR2CSTR(argv[0]); + + /* map from the command name to a C procedure */ + if (!Tcl_GetCommandInfo(ptr->ip, cmd, &info)) { + rb_raise(rb_eNameError, "invalid command name `%s'", cmd); + } +#if TCL_MAJOR_VERSION >= 8 + object = info.isNativeObjectProc; +#endif + + /* memory allocation for arguments of this command */ + if (object) { +#if TCL_MAJOR_VERSION >= 8 + /* object interface */ + ov = (Tcl_Obj **)ALLOCA_N(Tcl_Obj *, argc+1); + for (i = 0; i < argc; ++i) { + char *s = STR2CSTR(argv[i]); + ov[i] = Tcl_NewStringObj(s, strlen(s)); + } + ov[argc] = (Tcl_Obj *)NULL; +#endif + } else { + /* string interface */ + av = (char **)ALLOCA_N(char *, argc+1); + for (i = 0; i < argc; ++i) { + char *s = STR2CSTR(argv[i]); + + av[i] = ALLOCA_N(char, strlen(s)+1); + strcpy(av[i], s); + } + av[argc] = (char *)NULL; + } + + Tcl_ResetResult(ptr->ip); + + /* Invoke the C procedure */ + if (object) { +#if TCL_MAJOR_VERSION >= 8 + int dummy; + ptr->return_value = (*info.objProc)(info.objClientData, + ptr->ip, argc, ov); + + /* get the string value from the result object */ + resultPtr = Tcl_GetObjResult(ptr->ip); + Tcl_SetResult(ptr->ip, Tcl_GetStringFromObj(resultPtr, &dummy), + TCL_VOLATILE); +#endif + } else { + ptr->return_value = (*info.proc)(info.clientData, + ptr->ip, argc, av); + } + + if (ptr->return_value == TCL_ERROR) { + rb_raise(rb_eRuntimeError, ptr->ip->result); + } + + /* pass back the result (as string) */ + return(rb_str_new2(ptr->ip->result)); } /* get return code from Tcl_Eval() */ @@ -190,27 +398,44 @@ ip_retval(VALUE self) return (INT2FIX(ptr->return_value)); } +#ifdef __MACOS__ +static void +_macinit() +{ + tcl_macQdPtr = &qd; /* setup QuickDraw globals */ + Tcl_MacSetEventProc(TkMacConvertEvent); /* setup event handler */ +} +#endif + /*---- initialization ----*/ void Init_tcltklib() { extern VALUE rb_argv0; /* the argv[0] */ VALUE lib = rb_define_module("TclTkLib"); - VALUE ip = rb_define_class("TclTkIp", cObject); + VALUE ip = rb_define_class("TclTkIp", rb_cObject); + + eTkCallbackBreak = rb_define_class("TkCallbackBreak", rb_eStandardError); + eTkCallbackContinue = rb_define_class("TkCallbackContinue",rb_eStandardError); rb_define_module_function(lib, "mainloop", lib_mainloop, 0); rb_define_singleton_method(ip, "new", ip_new, 0); rb_define_method(ip, "_eval", ip_eval, 1); + rb_define_method(ip, "_toUTF8",ip_toUTF8,2); + rb_define_method(ip, "_fromUTF8",ip_fromUTF8,2); + rb_define_method(ip, "_invoke", ip_invoke, -1); rb_define_method(ip, "_return_value", ip_retval, 0); rb_define_method(ip, "mainloop", lib_mainloop, 0); +#ifdef __MACOS__ + _macinit(); +#endif + /*---- initialize tcl/tk libraries ----*/ /* from Tk_Main() */ DUMP1("Tcl_FindExecutable"); Tcl_FindExecutable(RSTRING(rb_argv0)->ptr); - - rb_define_variable("$tk_thread_safe", &thread_safe); } /* eof */ |