summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>1999-01-20 04:59:39 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>1999-01-20 04:59:39 +0000
commit210367ec889f5910e270d6ea2c7ddb8a8d939e61 (patch)
treefeb35473da45947378fbc02defe39bcd79ef600e /ext
parent9c5b1986a36c7a700b4c76817e35aa874ba7907c (diff)
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/Setup1
-rw-r--r--ext/aix_ld.rb2
-rw-r--r--ext/curses/curses.c107
-rw-r--r--ext/curses/extconf.rb5
-rw-r--r--ext/curses/hello.rb4
-rw-r--r--ext/curses/view.rb1
-rw-r--r--ext/dbm/dbm.c175
-rw-r--r--ext/dbm/extconf.rb6
-rw-r--r--ext/etc/etc.c91
-rw-r--r--ext/etc/extconf.rb24
-rw-r--r--ext/extmk.rb.in235
-rw-r--r--ext/extmk.rb.nt6
-rw-r--r--ext/fcntl/fcntl.c2
-rw-r--r--ext/kconv/kconv.c89
-rw-r--r--ext/md5/md5init.c14
-rw-r--r--ext/socket/depend2
-rw-r--r--ext/socket/extconf.rb12
-rw-r--r--ext/socket/socket.c829
-rw-r--r--ext/tcltklib/extconf.rb114
-rw-r--r--ext/tcltklib/lib/tcltk.rb287
-rw-r--r--ext/tcltklib/tcltklib.c293
21 files changed, 1480 insertions, 819 deletions
diff --git a/ext/Setup b/ext/Setup
index c92ac53e00..9e3a2474c3 100644
--- a/ext/Setup
+++ b/ext/Setup
@@ -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 */