summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYukihiro Matsumoto <matz@ruby-lang.org>1995-04-10 09:36:06 (GMT)
committerTakashi Kokubun <takashikkbn@gmail.com>2019-08-17 13:09:32 (GMT)
commitb2420d8ffa4d347a75efbbdc376f4ce65c0eb172 (patch)
treebd40c44d9155d9cb10232a0e962dc1cc221c2c8b
parent11e21a36bc935088f88a7cd1548f8c74c3bf6099 (diff)
version 0.73v0_73
https://cache.ruby-lang.org/pub/ruby/1.0/ruby-0.73.tar.gz Mon Apr 10 18:36:06 1995 Yukihiro Matsumoto (matz@ix-02) * version 0.73 Fri Apr 7 13:51:08 1995 Yukihiro Matsumoto (matz@ix-02) * cons.c->assoc.c: consの余計な機能は外してpairとしての機能だけを 残した.enumerableをincludeするのもやめた. * string.c(esub): 文字列置換イテレータ.perlのs///eの相当する.
-rw-r--r--ChangeLog11
-rw-r--r--MANIFEST2
-rw-r--r--Makefile.in2
-rw-r--r--array.c8
-rw-r--r--assoc.c150
-rw-r--r--bignum.c2
-rw-r--r--configure.in5
-rw-r--r--cons.c270
-rw-r--r--error.c2
-rw-r--r--ext/MANIFEST6
-rw-r--r--ext/Makefile.in40
-rw-r--r--ext/dbm.c441
-rw-r--r--ext/dbm.doc107
-rw-r--r--ext/socket.c761
-rw-r--r--ext/socket.doc227
-rw-r--r--gc.c10
-rw-r--r--hash.c38
-rw-r--r--inits.c2
-rw-r--r--ruby.h10
-rwxr-xr-x[-rw-r--r--]sample/from.rb8
-rw-r--r--spec125
-rw-r--r--string.c46
-rw-r--r--struct.c6
-rw-r--r--version.h4
24 files changed, 1910 insertions, 373 deletions
diff --git a/ChangeLog b/ChangeLog
index fefd5a3..f7ab446 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Mon Apr 10 18:36:06 1995 Yukihiro Matsumoto (matz@ix-02)
+
+ * version 0.73
+
+Fri Apr 7 13:51:08 1995 Yukihiro Matsumoto (matz@ix-02)
+
+ * cons.c->assoc.c: cons;פʵǽϳpairȤƤεǽ
+ ĤenumerableincludeΤ᤿
+
+ * string.c(esub): ʸִƥ졼perls///e롥
+
Wed Apr 5 11:35:21 1995 Yukihiro Matsumoto (matz@ix-02)
* version 0.72
diff --git a/MANIFEST b/MANIFEST
index 5fc8fa8..3320fc6 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -6,12 +6,12 @@ Makefile.in
README
ToDo
array.c
+assoc.c
bignum.c
class.c
compar.c
configure
configure.in
-cons.c
defines.h
dict.c
dir.c
diff --git a/Makefile.in b/Makefile.in
index 35efe60..c992bae 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -26,10 +26,10 @@ bindir = $(exec_prefix)/bin
#### End of system configuration section. ####
OBJS = array.o \
+ assoc.o \
bignum.o \
class.o \
compar.o \
- cons.o \
dir.o \
dln.o \
enum.o \
diff --git a/array.c b/array.c
index a15f053..93390d6 100644
--- a/array.c
+++ b/array.c
@@ -803,8 +803,8 @@ Fary_assoc(ary, key)
p = ary->ptr; pend = p + ary->len;
while (p < pend) {
- if (TYPE(*p) == T_CONS
- && rb_equal(RCONS(*p)->car, key))
+ if (TYPE(*p) == T_ASSOC
+ && rb_equal(RASSOC(*p)->car, key))
return *p;
}
return Qnil;
@@ -819,8 +819,8 @@ Fary_rassoc(ary, value)
p = ary->ptr; pend = p + ary->len;
while (p < pend) {
- if (TYPE(*p) == T_CONS
- && rb_equal(RCONS(*p)->cdr, value))
+ if (TYPE(*p) == T_ASSOC
+ && rb_equal(RASSOC(*p)->cdr, value))
return *p;
}
return Qnil;
diff --git a/assoc.c b/assoc.c
new file mode 100644
index 0000000..ef20c02
--- /dev/null
+++ b/assoc.c
@@ -0,0 +1,150 @@
+/************************************************
+
+ assoc.c -
+
+ $Author: matz $
+ $Date: 1995/01/10 10:30:37 $
+ created at: Fri Jan 6 10:10:36 JST 1995
+
+ Copyright (C) 1995 Yukihiro Matsumoto
+
+************************************************/
+
+#include "ruby.h"
+
+static VALUE C_Assoc;
+
+static ID eq;
+
+VALUE rb_to_a();
+
+VALUE
+assoc_new(car, cdr)
+ VALUE car, cdr;
+{
+ NEWOBJ(assoc, struct RAssoc);
+ OBJSETUP(assoc, C_Assoc, T_ASSOC);
+
+ assoc->car = car;
+ assoc->cdr = cdr;
+
+ return (VALUE)assoc;
+}
+
+static VALUE
+Fassoc_car(assoc)
+ struct RAssoc *assoc;
+{
+ return assoc->car;
+}
+
+static VALUE
+Fassoc_cdr(assoc)
+ struct RAssoc *assoc;
+{
+ return assoc->cdr;
+}
+
+static VALUE
+Fassoc_set_car(assoc, val)
+ struct RAssoc *assoc;
+ VALUE val;
+{
+ return assoc->car = val;
+}
+
+static VALUE
+Fassoc_set_cdr(assoc, val)
+ struct RAssoc *assoc;
+ VALUE val;
+{
+ return assoc->cdr = val;
+}
+
+static VALUE
+Fassoc_equal(assoc1, assoc2)
+ struct RAssoc *assoc1, *assoc2;
+{
+ if (TYPE(assoc2) != T_ASSOC) return FALSE;
+ if (!rb_equal(assoc1->car, assoc2->car)) return FALSE;
+ return rb_equal(assoc1->cdr, assoc2->cdr);
+}
+
+static VALUE
+Fassoc_hash(assoc)
+ struct RAssoc *assoc;
+{
+ static ID hash;
+ int key;
+
+ if (!hash) hash = rb_intern("hash");
+ key = rb_funcall(assoc->car, hash, 0, 0);
+ key ^= rb_funcall(assoc->cdr, hash, 0, 0);
+ return INT2FIX(key);
+}
+
+static VALUE
+Fassoc_to_s(assoc)
+ struct RAssoc *assoc;
+{
+ VALUE str1, str2;
+ static ID to_s;
+
+ if (!to_s) to_s = rb_intern("to_s");
+
+ str1 = rb_funcall(assoc->car, to_s, 0);
+ assoc = RASSOC(assoc->cdr);
+ while (assoc) {
+ if (TYPE(assoc) != T_ASSOC) {
+ str2 = rb_funcall(assoc, to_s, 0);
+ str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len);
+ break;
+ }
+ str2 = rb_funcall(assoc->car, to_s, 0);
+ str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len);
+ assoc = RASSOC(assoc->cdr);
+ }
+
+ return str1;
+}
+
+static VALUE
+Fassoc_inspect(assoc)
+ struct RAssoc *assoc;
+{
+ VALUE str1, str2;
+ static ID inspect;
+
+ if (!inspect) inspect = rb_intern("_inspect");
+
+ str1 = rb_funcall(assoc->car, inspect, 0, 0);
+ str2 = rb_funcall(assoc->cdr, inspect, 0, 0);
+ str_cat(str1, "::", 2);
+ str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len);
+
+ return str1;
+}
+
+extern VALUE C_Kernel;
+
+Init_Assoc()
+{
+ C_Assoc = rb_define_class("Assoc", C_Object);
+
+ rb_undef_method(CLASS_OF(C_Assoc), "new");
+ rb_undef_method(C_Assoc, "clone");
+
+ rb_define_method(C_Assoc, "car", Fassoc_car, 0);
+ rb_define_method(C_Assoc, "cdr", Fassoc_cdr, 0);
+
+ rb_define_method(C_Assoc, "car=", Fassoc_set_car, 1);
+ rb_define_method(C_Assoc, "cdr=", Fassoc_set_cdr, 1);
+
+ rb_define_method(C_Assoc, "==", Fassoc_equal, 1);
+ rb_define_method(C_Assoc, "hash", Fassoc_hash, 0);
+
+ rb_define_method(C_Assoc, "to_s", Fassoc_to_s, 0);
+ rb_define_method(C_Assoc, "_inspect", Fassoc_inspect, 0);
+
+ rb_define_method(C_Kernel, "::", assoc_new, 1);
+}
diff --git a/bignum.c b/bignum.c
index ef76fc5..f4f3b18 100644
--- a/bignum.c
+++ b/bignum.c
@@ -13,7 +13,7 @@
#include <math.h>
extern VALUE C_Integer;
-VALUE C_Bignum;
+static VALUE C_Bignum;
#define BDIGITS(x) RBIGNUM(x)->digits
#define BITSPERDIG (sizeof(USHORT)*CHAR_BIT)
diff --git a/configure.in b/configure.in
index 1dd4404..1346831 100644
--- a/configure.in
+++ b/configure.in
@@ -55,7 +55,10 @@ AC_MSG_CHECKING(whether matz's dln works)
cp confdefs.h config.h
if test $ac_cv_header_a_out_h = yes; then
AC_CACHE_VAL(rb_cv_mydln,
- [AC_TRY_COMPILE([#include "config.h"],
+ [AC_TRY_COMPILE([
+#define USE_MY_DLN
+#include "dln.c"
+],
[],
rb_cv_mydln=yes,
rb_cv_mydln=no)])
diff --git a/cons.c b/cons.c
deleted file mode 100644
index 42df8cb..0000000
--- a/cons.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/************************************************
-
- cons.c -
-
- $Author: matz $
- $Date: 1995/01/10 10:30:37 $
- created at: Fri Jan 6 10:10:36 JST 1995
-
- Copyright (C) 1995 Yukihiro Matsumoto
-
-************************************************/
-
-#include "ruby.h"
-
-VALUE C_Cons;
-
-static ID eq;
-
-VALUE rb_to_a();
-
-VALUE
-assoc_new(car, cdr)
- VALUE car, cdr;
-{
- NEWOBJ(cons, struct RCons);
- OBJSETUP(cons, C_Cons, T_CONS);
-
- cons->car = car;
- cons->cdr = cdr;
-
- return (VALUE)cons;
-}
-
-#define cons_new assoc_new
-
-static VALUE
-Fcons_car(cons)
- struct RCons *cons;
-{
- return cons->car;
-}
-
-static VALUE
-Fcons_cdr(cons)
- struct RCons *cons;
-{
- return cons->cdr;
-}
-
-static VALUE
-Fcons_set_car(cons, val)
- struct RCons *cons;
- VALUE val;
-{
- return cons->car = val;
-}
-
-static VALUE
-Fcons_set_cdr(cons, val)
- struct RCons *cons;
- VALUE val;
-{
- return cons->cdr = val;
-}
-
-static int
-cons_length(list)
- struct RCons *list;
-{
- int len = 1;
-
- while (TYPE(list) == T_CONS) {
- len++;
- list = RCONS(list->cdr);
- }
- return len;
-}
-
-static VALUE
-Fcons_length(list)
- struct RCons *list;
-{
- int len = cons_length(list);
- return INT2FIX(len);
-}
-
-static VALUE
-cons_aref(list, nth)
- struct RCons *list;
- int nth;
-{
- if (nth == 0) return list->car;
- list = RCONS(list->cdr);
- if (TYPE(list) != T_CONS) {
- if (nth == 1) return (VALUE)list;
- return Qnil;
- }
-
- return cons_aref(list, nth-1);
-}
-
-static VALUE
-Fcons_aref(list, nth)
- struct RCons *list;
- VALUE nth;
-{
- int n = NUM2INT(nth);
-
- if (n < 0) {
- n = cons_length(list)+n;
- if (n < 0) return Qnil;
- }
- return cons_aref(list, n);
-}
-
-static VALUE
-cons_aset(list, nth, val)
- struct RCons *list;
- int nth;
- VALUE val;
-{
- if (nth == 0) return list->car = val;
- if (TYPE(list->cdr) != T_CONS) {
- if (nth > 2) {
- Fail("list too short");
- }
- if (nth == 1)
- list->cdr = val;
- else
- list->cdr = cons_new(list->cdr, val);
- return val;
- }
- return cons_aset(list->cdr, nth-1, val);
-}
-
-static VALUE
-Fcons_aset(list, nth, val)
- struct RCons *list;
- VALUE nth, val;
-{
- int n = NUM2INT(nth);
-
- if (n < 0) {
- n = cons_length(list)+n;
- if (n < 0) {
- Fail("negative offset too big");
- }
- }
- return cons_aset(list, n, val);
-}
-
-static VALUE
-Fcons_each(list)
- struct RCons *list;
-{
- rb_yield(list->car);
- if (TYPE(list->cdr) != T_CONS) {
- rb_yield(list->cdr);
- return Qnil;
- }
- return Fcons_each(list->cdr);
-}
-
-static VALUE
-Fcons_equal(cons1, cons2)
- struct RCons *cons1, *cons2;
-{
- if (TYPE(cons2) != T_CONS) return FALSE;
- if (!rb_equal(cons1->car, cons2->car)) return FALSE;
- return rb_equal(cons1->cdr, cons2->cdr);
-}
-
-static ID hash;
-
-static VALUE
-Fcons_hash(cons)
- struct RCons *cons;
-{
- int key;
-
- if (!hash) hash = rb_intern("hash");
- key = rb_funcall(cons->car, hash, 0, 0);
- key ^= rb_funcall(cons->cdr, hash, 0, 0);
- return INT2FIX(key);
-}
-
-static VALUE
-Fcons_to_s(cons)
- struct RCons *cons;
-{
- VALUE str1, str2;
- ID to_s = rb_intern("to_s");
-
- str1 = rb_funcall(cons->car, to_s, 0);
- cons = RCONS(cons->cdr);
- while (cons) {
- if (TYPE(cons) != T_CONS) {
- str2 = rb_funcall(cons, to_s, 0);
- str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len);
- break;
- }
- str2 = rb_funcall(cons->car, to_s, 0);
- str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len);
- cons = RCONS(cons->cdr);
- }
-
- return str1;
-}
-
-static VALUE
-Fcons_inspect(cons)
- struct RCons *cons;
-{
- VALUE str1, str2;
- ID inspect = rb_intern("_inspect");
-
- str1 = rb_funcall(cons->car, inspect, 0, 0);
- str2 = rb_funcall(cons->cdr, inspect, 0, 0);
- str_cat(str1, "::", 2);
- str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len);
-
- return str1;
-}
-
-static VALUE
-Fcons_copy(list)
- struct RCons *list;
-{
- VALUE cdr = list->cdr;
-
- if (TYPE(cdr) == T_CONS)
- return cons_new(list->car, Fcons_copy(list->cdr));
- else
- return cons_new(list->car, cdr);
-}
-
-extern VALUE C_Kernel;
-extern VALUE M_Enumerable;
-
-Init_Cons()
-{
- C_Cons = rb_define_class("Cons", C_Object);
-
- rb_undef_method(CLASS_OF(C_Cons), "new");
- rb_undef_method(C_Cons, "clone");
-
- rb_include_module(C_Cons, M_Enumerable);
-
- rb_define_method(C_Cons, "car", Fcons_car, 0);
- rb_define_method(C_Cons, "cdr", Fcons_cdr, 0);
-
- rb_define_method(C_Cons, "car=", Fcons_set_car, 1);
- rb_define_method(C_Cons, "cdr=", Fcons_set_cdr, 1);
-
- rb_define_method(C_Cons, "==", Fcons_equal, 1);
- rb_define_method(C_Cons, "hash", Fcons_hash, 0);
- rb_define_method(C_Cons, "length", Fcons_length, 0);
-
- rb_define_method(C_Cons, "to_s", Fcons_to_s, 0);
- rb_define_method(C_Cons, "_inspect", Fcons_inspect, 0);
-
- /* methods to access as list */
- rb_define_method(C_Cons, "[]", Fcons_aref, 1);
- rb_define_method(C_Cons, "[]=", Fcons_aset, 2);
- rb_define_method(C_Cons, "each", Fcons_each, 0);
-
- rb_define_method(C_Cons, "copy", Fcons_copy, 0);
-
- rb_define_method(C_Kernel, "::", assoc_new, 1);
-}
diff --git a/error.c b/error.c
index 89c3806..5040705 100644
--- a/error.c
+++ b/error.c
@@ -171,7 +171,7 @@ static char *builtin_types[] = {
"Method",
"Struct",
"Bignum",
- "Cons",
+ "Assoc",
"Data",
};
diff --git a/ext/MANIFEST b/ext/MANIFEST
new file mode 100644
index 0000000..881a97c
--- /dev/null
+++ b/ext/MANIFEST
@@ -0,0 +1,6 @@
+MANIFEST
+Makefile.in
+dbm.c
+dbm.doc
+socket.c
+socket.doc
diff --git a/ext/Makefile.in b/ext/Makefile.in
new file mode 100644
index 0000000..20d8c5c
--- /dev/null
+++ b/ext/Makefile.in
@@ -0,0 +1,40 @@
+2SHELL = /bin/sh
+
+#### Start of system configuration section. ####
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+CC = @CC@
+
+CFLAGS = -I.. @CCDLFLAGS@ @CFLAGS@
+LIBS = @LIBS@
+EXT = @EXT@
+
+prefix = @prefix@
+binprefix =
+exec_prefix = @exec_prefix@
+bindir = $(exec_prefix)/bin
+
+#### End of system configuration section. ####
+
+.SUFFIXES: .so $(SUFFIXES)
+
+OBJS = dbm.$(EXT) \
+ socket.$(EXT)
+
+all: $(OBJS)
+
+clean:; @rm -f *.o *.so
+
+realclean:; @rm -f *.o *.so
+ @rm -f core ruby *~ Makefile
+
+.o.so:
+ ld -o $*.so $*.o
+
+# Prevent GNU make v3 from overflowing arg limit on SysV.
+.NOEXPORT:
+###
+dbm.o: dbm.c ../ruby.h ../config.h ../defines.h
+socket.o: socket.c ../ruby.h ../config.h ../defines.h ../io.h
diff --git a/ext/dbm.c b/ext/dbm.c
new file mode 100644
index 0000000..f3e8295
--- /dev/null
+++ b/ext/dbm.c
@@ -0,0 +1,441 @@
+/************************************************
+
+ dbm.c -
+
+ $Author: matz $
+ $Date: 1995/01/10 10:42:24 $
+ created at: Mon Jan 24 15:59:52 JST 1994
+
+ Copyright (C) 1995 Yukihiro Matsumoto
+
+************************************************/
+
+#include "ruby.h"
+
+#ifdef USE_DBM
+
+#include <ndbm.h>
+#include <fcntl.h>
+#include <errno.h>
+
+VALUE C_DBM;
+static ID id_dbm;
+
+extern VALUE M_Enumerable;
+
+static void
+closeddbm()
+{
+ Fail("closed DBM file");
+}
+
+#define GetDBM(obj, dbmp) {\
+ DBM **_dbm;\
+ Get_Data_Struct(obj, id_dbm, DBM*, _dbm);\
+ dbmp = *_dbm;\
+ if (dbmp == Qnil) closeddbm();\
+}
+
+static void
+free_dbm(dbmp)
+ DBM **dbmp;
+{
+ if (*dbmp) dbm_close(*dbmp);
+}
+
+#define MakeDBM(obj, dp) {\
+ DBM **_dbm;\
+ if (!id_dbm) id_dbm = rb_intern("dbm");\
+ Make_Data_Struct(obj,id_dbm,DBM*,Qnil,free_dbm,_dbm);\
+ *_dbm=dp;\
+}
+
+static VALUE
+Sdbm_open(argc, argv, class)
+ int argc;
+ VALUE *argv;
+ VALUE class;
+{
+ VALUE file, vmode;
+ DBM *dbm, **dbm2;
+ int mode;
+ VALUE obj;
+
+ if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
+ mode = 0666; /* default value */
+ }
+ else if (NIL_P(vmode)) {
+ mode = -1; /* return nil if DB not exist */
+ }
+ else {
+ mode = NUM2INT(vmode);
+ }
+ Check_Type(file, T_STRING);
+
+ dbm = Qnil;
+ if (mode >= 0)
+ dbm = dbm_open(RSTRING(file)->ptr, O_RDWR|O_CREAT, mode);
+ if (!dbm)
+ dbm = dbm_open(RSTRING(file)->ptr, O_RDWR, mode);
+ if (!dbm)
+ dbm = dbm_open(RSTRING(file)->ptr, O_RDONLY, mode);
+
+ if (!dbm) {
+ if (mode == -1) return Qnil;
+ rb_sys_fail(RSTRING(file)->ptr);
+ }
+
+ obj = obj_alloc(class);
+ MakeDBM(obj, dbm);
+
+ return obj;
+}
+
+static VALUE
+Fdbm_close(obj)
+ VALUE obj;
+{
+ DBM **dbmp;
+
+ Get_Data_Struct(obj, id_dbm, DBM*, dbmp);
+ if (*dbmp == Qnil) Fail("already closed DBM file");
+ dbm_close(*dbmp);
+ *dbmp = Qnil;
+
+ return Qnil;
+}
+
+static VALUE
+Fdbm_fetch(obj, keystr)
+ VALUE obj, keystr;
+{
+ datum key, value;
+ DBM *dbm;
+
+ Check_Type(keystr, T_STRING);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbm);
+ value = dbm_fetch(dbm, key);
+ if (value.dptr == Qnil) {
+ return Qnil;
+ }
+ return str_new(value.dptr, value.dsize);
+}
+
+static VALUE
+Fdbm_indexes(obj, args)
+ VALUE obj;
+ struct RArray *args;
+{
+ VALUE *p, *pend;
+ struct RArray *new;
+ int i = 0;
+
+ if (!args || args->len == 1 && TYPE(args->ptr) != T_ARRAY) {
+ args = (struct RArray*)rb_to_a(args->ptr[0]);
+ }
+
+ new = (struct RArray*)ary_new2(args->len);
+
+ p = args->ptr; pend = p + args->len;
+ while (p < pend) {
+ new->ptr[i++] = Fdbm_fetch(obj, *p++);
+ new->len = i;
+ }
+ return (VALUE)new;
+}
+
+static VALUE
+Fdbm_delete(obj, keystr)
+ VALUE obj, keystr;
+{
+ datum key;
+ DBM *dbm;
+
+ Check_Type(keystr, T_STRING);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbm);
+ if (dbm_delete(dbm, key)) {
+ Fail("dbm_delete failed");
+ }
+ return obj;
+}
+
+static VALUE
+Fdbm_shift(obj)
+ VALUE obj;
+{
+ datum key, val;
+ DBM *dbm;
+ VALUE keystr, valstr;
+
+ GetDBM(obj, dbm);
+
+ key = dbm_firstkey(dbm);
+ if (!key.dptr) return Qnil;
+ val = dbm_fetch(dbm, key);
+ dbm_delete(dbm, key);
+
+ keystr = str_new(key.dptr, key.dsize);
+ valstr = str_new(val.dptr, val.dsize);
+ return assoc_new(keystr, valstr);
+}
+
+static VALUE
+Fdbm_delete_if(obj)
+ VALUE obj;
+{
+ datum key, val;
+ DBM *dbm;
+ VALUE keystr, valstr;
+
+ GetDBM(obj, dbm);
+ for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
+ val = dbm_fetch(dbm, key);
+ keystr = str_new(key.dptr, key.dsize);
+ valstr = str_new(val.dptr, val.dsize);
+ if (rb_yield(assoc_new(keystr, valstr))
+ && dbm_delete(dbm, key)) {
+ Fail("dbm_delete failed");
+ }
+ }
+ return obj;
+}
+
+static VALUE
+Fdbm_clear(obj)
+ VALUE obj;
+{
+ datum key;
+ DBM *dbm;
+
+ GetDBM(obj, dbm);
+ for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
+ if (dbm_delete(dbm, key)) {
+ Fail("dbm_delete failed");
+ }
+ }
+ return obj;
+}
+
+static VALUE
+Fdbm_store(obj, keystr, valstr)
+ VALUE obj, keystr, valstr;
+{
+ datum key, val;
+ DBM *dbm;
+
+ if (valstr == Qnil) {
+ Fdbm_delete(obj, keystr);
+ return Qnil;
+ }
+
+ Check_Type(keystr, T_STRING);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+ Check_Type(valstr, T_STRING);
+ val.dptr = RSTRING(valstr)->ptr;
+ val.dsize = RSTRING(valstr)->len;
+
+ GetDBM(obj, dbm);
+ if (dbm_store(dbm, key, val, DBM_REPLACE)) {
+ dbm_clearerr(dbm);
+ if (errno == EPERM) rb_sys_fail(Qnil);
+ Fail("dbm_store failed");
+ }
+ return valstr;
+}
+
+static VALUE
+Fdbm_length(obj)
+ VALUE obj;
+{
+ datum key;
+ DBM *dbm;
+ int i = 0;
+
+ GetDBM(obj, dbm);
+ for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
+ i++;
+ }
+ return INT2FIX(i);
+}
+
+static VALUE
+Fdbm_each_value(obj)
+ VALUE obj;
+{
+ datum key, val;
+ DBM *dbm;
+
+ GetDBM(obj, dbm);
+ for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
+ val = dbm_fetch(dbm, key);
+ rb_yield(str_new(val.dptr, val.dsize));
+ }
+ return obj;
+}
+
+static VALUE
+Fdbm_each_key(obj)
+ VALUE obj;
+{
+ datum key;
+ DBM *dbm;
+
+ GetDBM(obj, dbm);
+ for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
+ rb_yield(str_new(key.dptr, key.dsize));
+ }
+ return obj;
+}
+
+static VALUE
+Fdbm_each_pair(obj)
+ VALUE obj;
+{
+ datum key, val;
+ DBM *dbm;
+ VALUE keystr, valstr;
+
+ GetDBM(obj, dbm);
+
+ for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
+ val = dbm_fetch(dbm, key);
+ keystr = str_new(key.dptr, key.dsize);
+ valstr = str_new(val.dptr, val.dsize);
+ rb_yield(assoc_new(keystr, valstr));
+ }
+
+ return obj;
+}
+
+static VALUE
+Fdbm_keys(obj)
+ VALUE obj;
+{
+ datum key;
+ DBM *dbm;
+ VALUE ary;
+
+ ary = ary_new();
+ GetDBM(obj, dbm);
+ for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
+ ary_push(ary, str_new(key.dptr, key.dsize));
+ }
+
+ return ary;
+}
+
+static VALUE
+Fdbm_values(obj)
+ VALUE obj;
+{
+ datum key, val;
+ DBM *dbm;
+ VALUE ary;
+
+ ary = ary_new();
+ GetDBM(obj, dbm);
+ for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
+ val = dbm_fetch(dbm, key);
+ ary_push(ary, str_new(val.dptr, val.dsize));
+ }
+
+ return ary;
+}
+
+static VALUE
+Fdbm_has_key(obj, keystr)
+ VALUE obj, keystr;
+{
+ datum key, val;
+ DBM *dbm;
+
+ Check_Type(keystr, T_STRING);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbm);
+ val = dbm_fetch(dbm, key);
+ if (val.dptr) return TRUE;
+ return FALSE;
+}
+
+static VALUE
+Fdbm_has_value(obj, valstr)
+ VALUE obj, valstr;
+{
+ datum key, val;
+ DBM *dbm;
+
+ Check_Type(valstr, T_STRING);
+ val.dptr = RSTRING(valstr)->ptr;
+ val.dsize = RSTRING(valstr)->len;
+
+ GetDBM(obj, dbm);
+ for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
+ val = dbm_fetch(dbm, key);
+ if (val.dsize == RSTRING(valstr)->len &&
+ memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static VALUE
+Fdbm_to_a(obj)
+ VALUE obj;
+{
+ datum key, val;
+ DBM *dbm;
+ VALUE ary;
+
+ GetDBM(obj, dbm);
+
+ ary = ary_new();
+ for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
+ val = dbm_fetch(dbm, key);
+ ary_push(ary, assoc_new(str_new(key.dptr, key.dsize),
+ str_new(val.dptr, val.dsize)));
+ }
+
+ return ary;
+}
+
+Init_dbm()
+{
+#ifdef HAVE_LIBDBM
+ dln_load_lib("libdbm.a");
+#endif
+ C_DBM = rb_define_class("DBM", C_Object);
+ rb_include_module(C_DBM, M_Enumerable);
+
+ rb_define_single_method(C_DBM, "open", Sdbm_open, -1);
+ rb_define_method(C_DBM, "close", Fdbm_close, 0);
+ rb_define_method(C_DBM, "[]", Fdbm_fetch, 1);
+ rb_define_method(C_DBM, "[]=", Fdbm_store, 2);
+ rb_define_method(C_DBM, "indexes", Fdbm_indexes, -2);
+ rb_define_method(C_DBM, "length", Fdbm_length, 0);
+ rb_define_alias(C_DBM, "size", "length");
+ rb_define_method(C_DBM, "each", Fdbm_each_pair, 0);
+ rb_define_method(C_DBM, "each_value", Fdbm_each_value, 0);
+ rb_define_method(C_DBM, "each_key", Fdbm_each_key, 0);
+ rb_define_method(C_DBM, "each_pair", Fdbm_each_pair, 0);
+ rb_define_method(C_DBM, "keys", Fdbm_keys, 0);
+ rb_define_method(C_DBM, "values", Fdbm_values, 0);
+ rb_define_method(C_DBM, "shift", Fdbm_shift, 1);
+ rb_define_method(C_DBM, "delete", Fdbm_delete, 1);
+ rb_define_method(C_DBM, "delete_if", Fdbm_delete_if, 0);
+ rb_define_method(C_DBM, "clear", Fdbm_clear, 0);
+ rb_define_method(C_DBM, "includes", Fdbm_has_key, 1);
+ rb_define_method(C_DBM, "has_key", Fdbm_has_key, 1);
+ rb_define_method(C_DBM, "has_value", Fdbm_has_value, 1);
+
+ rb_define_method(C_DBM, "to_a", Fdbm_to_a, 0);
+}
+#endif /* USE_DBM */
diff --git a/ext/dbm.doc b/ext/dbm.doc
new file mode 100644
index 0000000..48c91a9
--- /dev/null
+++ b/ext/dbm.doc
@@ -0,0 +1,107 @@
+.\" dbm.doc - -*- Indented-Text -*- created at: Thu Mar 23 20:28:31 JST 1995
+
+** DBM(饹)
+
+NDBMե򥢥륯饹ǡȤʸǤʤФ
+ʤȤ¤ȡǡե¸ȤƤ
+Dict饹Ʊͤ˰ȤǤ롥NDBMƤʤƥǤ
+Υ饹ʤ
+
+SuperClass: Object
+
+Included Modules: Enumerable
+
+Methods:
+
+ self [key]
+
+ key򥭡Ȥ֤ͤ
+
+ self [key]= value
+
+ key򥭡ȤơvalueǼ롥valueȤnilꤹȡ
+ keyФܤκȤʤ롥
+
+ clear
+
+ DBMեȤˤ롥
+
+ close
+
+ DBMե򥯥롥ʸ㳰ȯ롥
+
+ delete(key)
+
+ key򥭡ȤȤ롥
+
+ delete_if
+
+ Ǥ륤ƥ졼key::valueȤڥͿơ֥
+ ɾͤλܤ롥
+
+ each
+ each_pair
+
+ key::valueʤڥͿ륤ƥ졼
+
+ each_key
+
+ ƤkeyФƷ֤ƥ졼
+
+ each_value
+
+ ƤvalueФƷ֤ƥ졼
+
+ has_key(key)
+ includes(key)
+
+ keyǡ١¸ߤ֤
+
+ has_value(value)
+
+ valueͤȤȤǡ١¸ߤ
+ ֤
+
+ indexes(ary)
+ indexes(key-1, ..., key-n)
+
+ 1ܤηǤʸȤƼơǤ򥭡
+ ȤǤޤ֤2ܤηǤϳưͤ򥭡
+ Ǥޤ֤.
+
+ keys
+
+ ǡ١¸ߤ륭Ƥޤ֤
+
+ length
+ size
+
+ ǡ١Ǥο֤(:ߤμ¸Ǥǿ
+ 뤿˥ǡ١Τǡ빽Ȥ⤤
+ ĤƻȤ.)
+
+ shift
+
+ ǡ١ǤļФ(ǡ١)
+ key::valueȤڥ֤
+
+ to_a
+
+ ǡ١key-valueڥǤȤ֤
+
+ values
+
+ ǡ١¸ߤƤޤ֤
+
+Single Methods:
+
+ open(dbname[, mode])
+
+ dbnameǻꤷǡ١⡼ɤmodeꤷƥץ
+ 롥modeξάͤ0666Ǥ롥modeȤnilꤹȥǡ
+ ١¸ߤʤˤϿ˥ץ󤻤nil֤
+
+-------------------------------------------------------
+Local variables:
+fill-column: 70
+end:
diff --git a/ext/socket.c b/ext/socket.c
new file mode 100644
index 0000000..ec99234
--- /dev/null
+++ b/ext/socket.c
@@ -0,0 +1,761 @@
+/************************************************
+
+ socket.c -
+
+ $Author: matz $
+ $Date: 1995/01/10 10:42:55 $
+ created at: Thu Mar 31 12:21:29 JST 1994
+
+************************************************/
+
+#include "ruby.h"
+#ifdef HAVE_SOCKET
+#include "io.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
+#include <sys/un.h>
+
+extern VALUE C_IO;
+VALUE C_BasicSocket;
+VALUE C_TCPsocket;
+VALUE C_TCPserver;
+VALUE C_UNIXsocket;
+VALUE C_UNIXserver;
+VALUE C_Socket;
+
+FILE *rb_fdopen();
+char *strdup();
+
+static VALUE
+sock_new(class, fd)
+ VALUE class;
+ int fd;
+{
+ VALUE sock = obj_alloc(class);
+ OpenFile *fp;
+
+ MakeOpenFile(sock, fp);
+ fp->f = rb_fdopen(fd, "r");
+ setbuf(fp->f, NULL);
+ fp->f2 = rb_fdopen(fd, "w");
+ fp->mode = FMODE_READWRITE|FMODE_SYNC;
+
+ return sock;
+}
+
+static VALUE
+Fbsock_shutdown(argc, argv, sock)
+ int argc;
+ VALUE *argv;
+ VALUE sock;
+{
+ VALUE howto;
+ int how;
+ OpenFile *fptr;
+
+ rb_scan_args(argc, argv, "01", &howto);
+ if (howto == Qnil)
+ how = 2;
+ else {
+ how = NUM2INT(howto);
+ if (how < 0 && how > 2) how = 2;
+ }
+ GetOpenFile(sock, fptr);
+ if (shutdown(fileno(fptr->f), how) == -1)
+ rb_sys_fail(Qnil);
+
+ return INT2FIX(0);
+}
+
+static VALUE
+Fbsock_setopt(sock, lev, optname, val)
+ VALUE sock, lev, optname;
+ struct RString *val;
+{
+ int level, option;
+ OpenFile *fptr;
+
+ level = NUM2INT(lev);
+ option = NUM2INT(optname);
+ Check_Type(val, T_STRING);
+
+ GetOpenFile(sock, fptr);
+ if (setsockopt(fileno(fptr->f), level, option, val->ptr, val->len) < 0)
+ rb_sys_fail(fptr->path);
+
+ return INT2FIX(0);
+}
+
+static VALUE
+Fbsock_getopt(sock, lev, optname)
+ VALUE sock, lev, optname;
+{
+ int level, option, len;
+ struct RString *val;
+ OpenFile *fptr;
+
+ level = NUM2INT(lev);
+ option = NUM2INT(optname);
+ len = 256;
+ val = (struct RString*)str_new(0, len);
+ Check_Type(val, T_STRING);
+
+ GetOpenFile(sock, fptr);
+ if (getsockopt(fileno(fptr->f), level, option, val->ptr, &len) < 0)
+ rb_sys_fail(fptr->path);
+ val->len = len;
+ return (VALUE)val;
+}
+
+static VALUE
+Fbsock_getsockname(sock)
+ VALUE sock;
+{
+ char buf[1024];
+ int len = sizeof buf;
+ OpenFile *fptr;
+
+ GetOpenFile(sock, fptr);
+ if (getsockname(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
+ rb_sys_fail("getsockname(2)");
+ return str_new(buf, len);
+}
+
+static VALUE
+Fbsock_getpeername(sock)
+ VALUE sock;
+{
+ char buf[1024];
+ int len = sizeof buf;
+ OpenFile *fptr;
+
+ GetOpenFile(sock, fptr);
+ if (getpeername(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
+ rb_sys_fail("getpeername(2)");
+ return str_new(buf, len);
+}
+
+static VALUE
+open_inet(class, h, serv, server)
+ VALUE class, h, serv;
+ int server;
+{
+ char *host;
+ struct hostent *hostent, _hostent;
+ struct servent *servent, _servent;
+ struct protoent *protoent;
+ struct sockaddr_in sockaddr;
+ int fd, status;
+ int hostaddr, hostaddrPtr[2];
+ int servport;
+ char *syscall;
+ VALUE sock;
+
+ if (h) {
+ Check_Type(h, T_STRING);
+ host = RSTRING(h)->ptr;
+ hostent = gethostbyname(host);
+ if (hostent == NULL) {
+ hostaddr = inet_addr(host);
+ if (hostaddr == -1) {
+ if (server && !strlen(host))
+ hostaddr = INADDR_ANY;
+ else
+ rb_sys_fail(host);
+ }
+ _hostent.h_addr_list = (char **)hostaddrPtr;
+ _hostent.h_addr_list[0] = (char *)&hostaddr;
+ _hostent.h_addr_list[1] = NULL;
+ _hostent.h_length = sizeof(hostaddr);
+ _hostent.h_addrtype = AF_INET;
+ hostent = &_hostent;
+ }
+ }
+ servent = NULL;
+ if (FIXNUM_P(serv)) {
+ servport = FIX2UINT(serv);
+ goto setup_servent;
+ }
+ Check_Type(serv, T_STRING);
+ servent = getservbyname(RSTRING(serv)->ptr, "tcp");
+ if (servent == NULL) {
+ servport = strtoul(RSTRING(serv)->ptr, Qnil, 0);
+ if (servport == -1) Fail("no such servce %s", RSTRING(serv)->ptr);
+ setup_servent:
+ _servent.s_port = servport;
+ _servent.s_proto = "tcp";
+ servent = &_servent;
+ }
+ protoent = getprotobyname(servent->s_proto);
+ if (protoent == NULL) Fail("no such proto %s", servent->s_proto);
+
+ fd = socket(PF_INET, SOCK_STREAM, protoent->p_proto);
+
+ sockaddr.sin_family = AF_INET;
+ if (h == Qnil) {
+ sockaddr.sin_addr.s_addr = INADDR_ANY;
+ }
+ else {
+ memcpy((char *)&(sockaddr.sin_addr.s_addr),
+ (char *) hostent->h_addr_list[0],
+ (size_t) hostent->h_length);
+ }
+ sockaddr.sin_port = servent->s_port;
+
+ if (server) {
+ status = bind(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
+ syscall = "bind(2)";
+ }
+ else {
+ status = connect(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
+ syscall = "connect(2)";
+ }
+
+ if (status < 0) {
+ close (fd);
+ rb_sys_fail(syscall);
+ }
+ if (server) listen(fd, 5);
+
+ /* create new instance */
+ sock = sock_new(class, fd);
+
+ return sock;
+}
+
+static VALUE
+Stcp_sock_open(class, host, serv)
+ VALUE class, host, serv;
+{
+ Check_Type(host, T_STRING);
+ return open_inet(class, host, serv, 0);
+}
+
+static VALUE
+Stcp_svr_open(argc, argv, class)
+ int argc;
+ VALUE *argv;
+ VALUE class;
+{
+ VALUE arg1, arg2;
+
+ if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2)
+ return open_inet(class, arg1, arg2, 1);
+ else
+ return open_inet(class, Qnil, arg1, 1);
+}
+
+static VALUE
+sock_accept(class, fd, sockaddr, len)
+ VALUE class;
+ int fd;
+ struct sockaddr *sockaddr;
+ int *len;
+{
+ int fd2;
+
+ retry:
+ fd2 = accept(fd, sockaddr, len);
+ if (fd2 < 0) {
+ if (errno == EINTR) goto retry;
+ rb_sys_fail(Qnil);
+ }
+ return sock_new(class, fd2);
+}
+
+static VALUE
+Ftcp_accept(sock)
+ VALUE sock;
+{
+ OpenFile *fptr;
+ struct sockaddr_in from;
+ int fromlen;
+
+ GetOpenFile(sock, fptr);
+ fromlen = sizeof(struct sockaddr_in);
+ return sock_accept(C_TCPsocket, fileno(fptr->f),
+ (struct sockaddr*)&from, &fromlen);
+}
+
+static VALUE
+open_unix(class, path, server)
+ VALUE class;
+ struct RString *path;
+ int server;
+{
+ struct sockaddr_un sockaddr;
+ int fd, status;
+ char *syscall;
+ VALUE sock;
+ OpenFile *fptr;
+
+ Check_Type(path, T_STRING);
+ fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) rb_sys_fail("socket(2)");
+
+ sockaddr.sun_family = AF_UNIX;
+ strncpy(sockaddr.sun_path, path->ptr, sizeof(sockaddr.sun_path)-1);
+ sockaddr.sun_path[sizeof(sockaddr.sun_path)-1] = '\0';
+
+ if (server) {
+ status = bind(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
+ syscall = "bind(2)";
+ }
+ else {
+ status = connect(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
+ syscall = "connect(2)";
+ }
+
+ if (status < 0) {
+ close (fd);
+ rb_sys_fail(syscall);
+ }
+
+ if (server) listen(fd, 5);
+
+ sock = sock_new(class, fd);
+ GetOpenFile(sock, fptr);
+ fptr->path = strdup(path->ptr);
+
+ return sock;
+}
+
+static VALUE
+tcp_addr(sockaddr)
+ struct sockaddr_in *sockaddr;
+{
+ VALUE family, port, addr;
+ VALUE ary;
+ struct hostent *hostent;
+
+ family = str_new2("AF_INET");
+ hostent = gethostbyaddr((char*)&sockaddr->sin_addr.s_addr,
+ sizeof(sockaddr->sin_addr),
+ AF_INET);
+ if (hostent) {
+ addr = str_new2(hostent->h_name);
+ }
+ else {
+ char buf[16];
+ char *a = (char*)&sockaddr->sin_addr;
+ sprintf(buf, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
+ addr = str_new2(buf);
+ }
+ port = INT2FIX(sockaddr->sin_port);
+ ary = ary_new3(3, family, port, addr);
+
+ return ary;
+}
+
+static VALUE
+Ftcp_addr(sock)
+ VALUE sock;
+{
+ OpenFile *fptr;
+ struct sockaddr_in addr;
+ int len = sizeof addr;
+
+ GetOpenFile(sock, fptr);
+
+ if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
+ rb_sys_fail("getsockname(2)");
+ return tcp_addr(&addr);
+}
+
+static VALUE
+Ftcp_peeraddr(sock)
+ VALUE sock;
+{
+ OpenFile *fptr;
+ struct sockaddr_in addr;
+ int len = sizeof addr;
+
+ GetOpenFile(sock, fptr);
+
+ if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
+ rb_sys_fail("getsockname(2)");
+ return tcp_addr(&addr);
+}
+
+static VALUE
+Sunix_sock_open(sock, path)
+ VALUE sock, path;
+{
+ return open_unix(sock, path, 0);
+}
+
+static VALUE
+Funix_path(sock)
+ VALUE sock;
+{
+ OpenFile *fptr;
+
+ GetOpenFile(sock, fptr);
+ if (fptr->path == Qnil) {
+ struct sockaddr_un addr;
+ int len = sizeof(addr);
+ if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
+ rb_sys_fail(Qnil);
+ fptr->path = strdup(addr.sun_path);
+ }
+ return str_new2(fptr->path);
+}
+
+static VALUE
+Sunix_svr_open(class, path)
+ VALUE class, path;
+{
+ return open_unix(class, path, 1);
+}
+
+static VALUE
+Funix_accept(sock)
+ VALUE sock;
+{
+ OpenFile *fptr;
+ struct sockaddr_un from;
+ int fromlen;
+
+ GetOpenFile(sock, fptr);
+ fromlen = sizeof(struct sockaddr_un);
+ return sock_accept(C_UNIXsocket, fileno(fptr->f),
+ (struct sockaddr*)&from, &fromlen);
+}
+
+static VALUE
+unix_addr(sockaddr)
+ struct sockaddr_un *sockaddr;
+{
+ return assoc_new(str_new2("AF_UNIX"),str_new2(sockaddr->sun_path));
+}
+
+static VALUE
+Funix_addr(sock)
+ VALUE sock;
+{
+ OpenFile *fptr;
+ struct sockaddr_un addr;
+ int len = sizeof addr;
+
+ GetOpenFile(sock, fptr);
+
+ if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
+ rb_sys_fail("getsockname(2)");
+ return unix_addr(&addr);
+}
+
+static VALUE
+Funix_peeraddr(sock)
+ VALUE sock;
+{
+ OpenFile *fptr;
+ struct sockaddr_un addr;
+ int len = sizeof addr;
+
+ GetOpenFile(sock, fptr);
+
+ if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
+ rb_sys_fail("getsockname(2)");
+ return unix_addr(&addr);
+}
+
+static void
+setup_domain_and_type(domain, dv, type, tv)
+ VALUE domain, type;
+ int *dv, *tv;
+{
+ char *ptr;
+
+ if (TYPE(domain) == T_STRING) {
+ ptr = RSTRING(domain)->ptr;
+ if (strcmp(ptr, "PF_UNIX") == 0)
+ *dv = PF_UNIX;
+ else if (strcmp(ptr, "PF_INET") == 0)
+ *dv = PF_INET;
+#ifdef PF_IMPLINK
+ else if (strcmp(ptr, "PF_IMPLINK") == 0)
+ *dv = PF_IMPLINK;
+#endif
+#ifdef PF_AX25
+ else if (strcmp(ptr, "PF_AX25") == 0)
+ *dv = PF_AX25;
+#endif
+#ifdef PF_IPX
+ else if (strcmp(ptr, "PF_IPX") == 0)
+ *dv = PF_IPX;
+#endif
+ else
+ Fail("Unknown socket domain %s", ptr);
+ }
+ else {
+ *dv = NUM2INT(domain);
+ }
+ if (TYPE(type) == T_STRING) {
+ ptr = RSTRING(type)->ptr;
+ if (strcmp(ptr, "SOCK_STREAM") == 0)
+ *tv = SOCK_STREAM;
+ else if (strcmp(ptr, "SOCK_DGRAM") == 0)
+ *tv = SOCK_DGRAM;
+#ifdef SOCK_RAW
+ else if (strcmp(ptr, "SOCK_RAW") == 0)
+ *tv = SOCK_RAW;
+#endif
+#ifdef SOCK_SEQPACKET
+ else if (strcmp(ptr, "SOCK_SEQPACKET") == 0)
+ *tv = SOCK_SEQPACKET;
+#endif
+#ifdef SOCK_RDM
+ else if (strcmp(ptr, "SOCK_RDM") == 0)
+ *tv = SOCK_RDM;
+#endif
+#ifdef SOCK_PACKET
+ else if (strcmp(ptr, "SOCK_PACKET") == 0)
+ *tv = SOCK_PACKET;
+#endif
+ else
+ Fail("Unknown socket type %s", ptr);
+ }
+ else {
+ *tv = NUM2INT(type);
+ }
+}
+
+static VALUE
+Ssock_open(class, domain, type, protocol)
+ VALUE class, domain, type, protocol;
+{
+ int fd;
+ int d, t;
+
+ setup_domain_and_type(domain, &d, type, &t);
+ fd = socket(d, t, NUM2INT(protocol));
+ if (fd < 0) rb_sys_fail("socke(2)");
+ return sock_new(class, fd);
+}
+
+static VALUE
+Ssock_for_fd(class, fd)
+ VALUE class, fd;
+{
+ return sock_new(class, NUM2INT(fd));
+}
+
+static VALUE
+Ssock_socketpair(class, domain, type, protocol)
+ VALUE class, domain, type, protocol;
+{
+ int fd;
+ 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]));
+}
+
+static VALUE
+Fsock_connect(sock, addr)
+ VALUE sock;
+ struct RString *addr;
+{
+ OpenFile *fptr;
+
+ Check_Type(addr, T_STRING);
+ str_modify(addr);
+
+ GetOpenFile(sock, fptr);
+ if (connect(fileno(fptr->f), (struct sockaddr*)addr->ptr, addr->len) < 0)
+ rb_sys_fail("connect(2)");
+
+ return INT2FIX(0);
+}
+
+static VALUE
+Fsock_bind(sock, addr)
+ VALUE sock;
+ struct RString *addr;
+{
+ OpenFile *fptr;
+
+ Check_Type(addr, T_STRING);
+ str_modify(addr);
+
+ GetOpenFile(sock, fptr);
+ if (bind(fileno(fptr->f), (struct sockaddr*)addr->ptr, addr->len) < 0)
+ rb_sys_fail("bind(2)");
+
+ return INT2FIX(0);
+}
+
+static VALUE
+Fsock_listen(sock, log)
+ VALUE sock, log;
+{
+ OpenFile *fptr;
+
+ GetOpenFile(sock, fptr);
+ if (listen(fileno(fptr->f), NUM2INT(log)) < 0)
+ rb_sys_fail("listen(2)");
+
+ return INT2FIX(0);
+}
+
+static VALUE
+Fsock_accept(sock)
+ VALUE sock;
+{
+ OpenFile *fptr;
+ VALUE addr, sock2;
+ char buf[1024];
+ int len = sizeof buf;
+
+ GetOpenFile(sock, fptr);
+ sock2 = sock_accept(C_Socket,fileno(fptr->f),(struct sockaddr*)buf,&len);
+
+ return assoc_new(sock2, str_new(buf, len));
+}
+
+static VALUE
+Fsock_send(argc, argv, sock)
+ int argc;
+ VALUE *argv;
+ VALUE sock;
+{
+ struct RString *msg, *to;
+ VALUE flags;
+ OpenFile *fptr;
+ FILE *f;
+ int fd, n;
+
+ rb_scan_args(argc, argv, "21", &msg, &flags, &to);
+
+ Check_Type(msg, T_STRING);
+
+ GetOpenFile(sock, fptr);
+ f = fptr->f2?fptr->f2:fptr->f;
+ fd = fileno(f);
+ if (to) {
+ Check_Type(to, T_STRING);
+ n = sendto(fd, msg->ptr, msg->len, NUM2INT(flags),
+ (struct sockaddr*)to->ptr, to->len);
+ }
+ else {
+ n = send(fd, msg->ptr, msg->len, NUM2INT(flags));
+ }
+ if (n < 0) {
+ rb_sys_fail("send(2)");
+ }
+ return INT2FIX(n);
+}
+
+static VALUE
+sock_recv(sock, argc, argv, from)
+ VALUE sock;
+ int argc;
+ VALUE *argv;
+ int from;
+{
+ OpenFile *fptr;
+ FILE f;
+ struct RString *str;
+ char buf[1024];
+ int fd, alen = sizeof buf;
+ VALUE len, flg;
+ int flags;
+
+ rb_scan_args(argc, argv, "11", &len, &flg);
+
+ if (flg == Qnil) flags = 0;
+ else flags = NUM2INT(flg);
+
+ str = (struct RString*)str_new(0, NUM2INT(len));
+
+ GetOpenFile(sock, fptr);
+ fd = fileno(fptr->f);
+ if ((str->len = recvfrom(fd, str->ptr, str->len, flags,
+ (struct sockaddr*)buf, &alen)) < 0) {
+ rb_sys_fail("recvfrom(2)");
+ }
+
+ if (from)
+ return assoc_new(str, str_new(buf, alen));
+ else
+ return (VALUE)str;
+}
+
+static VALUE
+Fsock_recv(argc, argv, sock)
+ int argc;
+ VALUE *argv;
+ VALUE sock;
+{
+ return sock_recv(sock, argc, argv, 0);
+}
+
+static VALUE
+Fsock_recvfrom(argc, argv, sock)
+ int argc;
+ VALUE *argv;
+ VALUE sock;
+{
+ return sock_recv(sock, argc, argv, 1);
+}
+
+Init_socket ()
+{
+#ifdef HAVE_LIBSOCKET
+ dln_load_lib("libsocket.a");
+#endif
+ C_BasicSocket = rb_define_class("BasicSocket", C_IO);
+ rb_undef_method(C_BasicSocket, "new");
+ rb_define_method(C_BasicSocket, "shutdown", Fbsock_shutdown, -1);
+ rb_define_method(C_BasicSocket, "setopt", Fbsock_setopt, 3);
+ rb_define_method(C_BasicSocket, "getopt", Fbsock_getopt, 2);
+ rb_define_method(C_BasicSocket, "getsockname", Fbsock_getsockname, 0);
+ rb_define_method(C_BasicSocket, "getpeername", Fbsock_getpeername, 0);
+
+ C_TCPsocket = rb_define_class("TCPsocket", C_BasicSocket);
+ rb_define_single_method(C_TCPsocket, "open", Stcp_sock_open, 2);
+ rb_define_single_method(C_TCPsocket, "new", Stcp_sock_open, 2);
+ rb_define_method(C_TCPsocket, "addr", Ftcp_addr, 0);
+ rb_define_method(C_TCPsocket, "peeraddr", Ftcp_peeraddr, 0);
+
+ C_TCPserver = rb_define_class("TCPserver", C_TCPsocket);
+ rb_define_single_method(C_TCPserver, "open", Stcp_svr_open, -1);
+ rb_define_single_method(C_TCPserver, "new", Stcp_svr_open, -1);
+ rb_define_method(C_TCPserver, "accept", Ftcp_accept, 0);
+
+ C_UNIXsocket = rb_define_class("UNIXsocket", C_BasicSocket);
+ rb_define_single_method(C_UNIXsocket, "open", Sunix_sock_open, 1);
+ rb_define_single_method(C_UNIXsocket, "new", Sunix_sock_open, 1);
+ rb_define_method(C_UNIXsocket, "path", Funix_path, 0);
+ rb_define_method(C_UNIXsocket, "addr", Funix_addr, 0);
+ rb_define_method(C_UNIXsocket, "peeraddr", Funix_peeraddr, 0);
+
+ C_UNIXserver = rb_define_class("UNIXserver", C_UNIXsocket);
+ rb_define_single_method(C_UNIXserver, "open", Sunix_svr_open, 1);
+ rb_define_single_method(C_UNIXserver, "new", Sunix_svr_open, 1);
+ rb_define_method(C_UNIXserver, "accept", Funix_accept, 0);
+
+ C_Socket = rb_define_class("Socket", C_BasicSocket);
+ rb_define_single_method(C_Socket, "open", Ssock_open, 3);
+ rb_define_single_method(C_Socket, "new", Ssock_open, 3);
+ rb_define_single_method(C_Socket, "for_fd", Ssock_for_fd, 1);
+
+ rb_define_method(C_Socket, "connect", Fsock_connect, 1);
+ rb_define_method(C_Socket, "bind", Fsock_bind, 1);
+ rb_define_method(C_Socket, "listen", Fsock_listen, 1);
+ rb_define_method(C_Socket, "accept", Fsock_accept, 0);
+
+ rb_define_method(C_Socket, "send", Fsock_send, -1);
+ rb_define_method(C_Socket, "recv", Fsock_recv, -1);
+ rb_define_method(C_Socket, "recvfrom", Fsock_recv, -1);
+
+ rb_define_single_method(C_Socket, "socketpair", Ssock_socketpair, 3);
+}
+#endif /* HAVE_SOCKET */
diff --git a/ext/socket.doc b/ext/socket.doc
new file mode 100644
index 0000000..aa5bfed
--- /dev/null
+++ b/ext/socket.doc
@@ -0,0 +1,227 @@
+.\" socket.doc - -*- Indented-Text -*- created at: Thu Mar 23 20:29:02 JST 1995
+
+** Socket(饹)
+
+SuperClass: BasicSocket
+
+åȤΤΤФ륷ƥॳ٥Υ󶡤륯饹
+PerlΥåȤФ륢Ʊ٥εǽ󶡤Ƥ롥Υ
+Ǥϥåȥɥ쥹pack줿ʸǡꤹ롥UDPåȤϤ
+Υ饹ȤäѤ롥
+
+Methods:
+
+ accept
+
+ ³դơ³Ф륽åȤȥɥ쥹
+ ڥ֤accept(2)򻲾ȡ
+
+ bind(addr)
+
+ bind(2)ƱƯ򤹤롥addrpack줿åȥɥ쥹¤
+ ΤǤ롥
+
+ connect(addr)
+
+ connect(2)ƱƯ򤹤롥addrpack줿åȥɥ쥹
+ ¤ΤǤ롥
+
+ listen(backlog)
+
+ listen(2)ƱƯ򤹤롥
+
+ recv(len[, flags])
+
+ åȤǡꡤʸȤ֤lenϼ
+ Ĺꤹ롥flagsˤĤƤrecv(2)򻲾ȡflagsΥ
+ եͤ0Ǥ롥
+
+ recvfrom(len[, flags])
+
+ recvƱͤ˥åȤǡ뤬ͤʸ
+ ꥽åȤΥɥ쥹ΥڥǤ롥ˤĤƤrecvƱ͡
+
+ send(mesg, flags[, to])
+
+ åȤ𤷤ƥǡ롥flags˴ؤƤsend(2)򻲾Ȥλ
+ connectƤʤåȤФƤǤtoꤹɬ
+ פ롥ºݤäǡĹ֤
+
+Single Methods:
+
+ open(domain, type, protocol)
+ new(domain, type, protocol)
+
+ åȤ롥domaintypeprotocolϥ󥯥롼
+ եƤͤǻꤹ롥domaintype˴ؤ
+ ϡʸǻǤ뤬٤Ƥ򥫥СƤݾڤϤʤ
+
+ socketpair(domain, type, protocol)
+
+ åȤΥڥ֤λ openƱǤ롥
+
+** BasicSocket(饹)
+
+åȤɽݥ饹Ūʥåϥ֥饹롥
+㤨Х󥿡ͥåȥɥᥤξTCPsocketѤ롥
+
+SuperClass: IO
+
+Methods:
+
+ getopt(level, optname)
+
+ åȤΥץ롥getsockopt(2)򻲾ȤΤȡ
+ ץƤޤʸ֤
+
+ getpeername
+
+ ³ΥåȤξ롥ѥå줿sockaddr¤
+ ٥˥פʸ֤롥getpeername(2)򻲾ȤΤȡ
+
+ getsockname
+
+ åȤξ롥ѥå줿sockaddr¤Τ٥˥
+ ʸ֤롥getsockname(2)򻲾ȤΤȡ
+
+ setopt(level, optname, optval)
+
+ åȤΥץꤹ롥setsockopt(2)򻲾ȤΤȡ
+
+ shutdown(how)
+
+ åȤΰʹߤ³λ롥how0Ǥʹߤμ
+ how1Ǥϡʹߤݤ롥how2λˤϡ
+ ʹߤȤ˵ݤ롥shutdown(2)򻲾ȡ
+
+** TCPserver(饹)
+
+TCP/IPȥ꡼෿³Υ¦ΥåȤΥ饹Υ饹ˤä
+ñ˥åȤѤФΥץߥ󥰤Ǥ롥㤨echo
+ФϰʲΤ褦ˤʤ롥
+
+ gs = TCPserver.open(4444)
+ socks = [gs]
+
+ while TRUE
+ nsock = select(socks);
+ if nsock == nil; continue end
+ for s in nsock[0]
+ if s == gs
+ socks.push(s.accept)
+ else
+ if s.eof
+ s.close
+ socks.delete(s)
+ else
+ str = s.gets
+ s.write(str)
+ end
+ end
+ end
+ end
+
+SuperClass: TCPsocket
+
+Methods:
+
+ accept
+
+ 饤Ȥ³׵դ³TCPsocketΥ
+ 󥹤֤
+
+Single Methods:
+
+ new([host, ]service)
+ open([host, ]service)
+
+ service/etc/services(ޤNIS)ϿƤ륵ӥ̾
+ ݡֹǻꤹ롥hostꤷϻꤷۥȤ
+ ³դ롥άƤΥۥȤ³׵
+ 롥
+
+** TCPsocket
+
+󥿡ͥåȥɥᥤΥȥ꡼෿åȤΥ饹̾IO饹
+֥饹ƱͤϤǤ롥Υ饹ˤäƥåȤѤ
+饤Ȥñ˵ҤǤ롥桼Ϥ򤽤ΤޤޥФž
+ϰʲΤ褦ˤʤ롥
+
+ s = TCPsocket("localhost", 4444)
+ while gets()
+ s.write($_)
+ print(s.read)
+ end
+
+SuperClass: BasicSocket
+
+Methods:
+
+ addr
+
+ åȤ³ɽ֤γǤ1
+ ʸ "AF_INET"2Ǥportֹ桤3ǤۥȤɽʸ
+ Ǥ롥
+
+ peeraddr
+
+ ³襽åȤξɽ֤γǤ
+ addr᥽åɤ֤ƱǤ롥
+
+Single Methods:
+
+ open(host, service)
+ new(host, service)
+
+ hostǻꤷۥȤserviceǻꤷݡȤ³
+ Ȥ֤hostϥۥ̾ޤϥ󥿡ͥåȥɥ쥹򼨤ʸ
+ service/etc/services(ޤNIS)ϿƤ륵
+ ̾ݡֹǤ롥
+
+** UNIXserver
+
+UNIXȥ꡼෿³Υ¦ΥåȤΥ饹
+
+SuperClass: UNIXsocket
+
+Methods:
+
+ accept
+
+ 饤Ȥ³׵դ³UNIXsocketΥ
+ 󥹤֤
+
+** UNIXsocket
+
+UNIXɥᥤΥȥ꡼෿åȤΥ饹̾IO饹Υ֥饹
+ƱͤϤǤ롥
+
+SuperClass: BasicSocket
+
+Methods:
+
+ addr
+
+ åȤ³ɽ֤γǤ1
+ ʸ "AF_UNIX"2ǤpathǤ롥
+
+ path
+
+ UNIXåȤΥѥ֤
+
+ peeraddr
+
+ ³襽åȤξɽ֤γǤ
+ addr᥽åɤ֤ƱǤ롥
+
+Single Methods:
+
+ open(path)
+ new(path)
+
+ pathǻꤷѥ̾Ѥ³åȤ֤
+
+-------------------------------------------------------
+Local variables:
+fill-column: 70
+end:
diff --git a/gc.c b/gc.c
index 2daf0d1..0c2219a 100644
--- a/gc.c
+++ b/gc.c
@@ -182,7 +182,7 @@ typedef struct RVALUE {
struct RStruct rstruct;
struct RBignum bignum;
struct RNode node;
- struct RCons cons;
+ struct RAssoc assoc;
struct SCOPE scope;
} as;
} RVALUE;
@@ -447,9 +447,9 @@ gc_mark(obj)
}
break;
- case T_CONS:
- gc_mark(obj->as.cons.car);
- obj = (RVALUE*)obj->as.cons.cdr;
+ case T_ASSOC:
+ gc_mark(obj->as.assoc.car);
+ obj = (RVALUE*)obj->as.assoc.cdr;
goto Top;
default:
@@ -537,7 +537,7 @@ obj_free(obj)
case T_ICLASS:
/* iClass shares table with the module */
case T_FLOAT:
- case T_CONS:
+ case T_ASSOC:
break;
case T_STRUCT:
free(obj->as.rstruct.name);
diff --git a/hash.c b/hash.c
index e2346f7..a261588 100644
--- a/hash.c
+++ b/hash.c
@@ -46,8 +46,8 @@ rb_hash(a, mod)
return rb_funcall(a, hash, 0) % mod;
}
-#define ASSOC_KEY(a) RCONS(a)->car
-#define ASSOC_VAL(a) RCONS(a)->cdr
+#define ASSOC_KEY(a) RASSOC(a)->car
+#define ASSOC_VAL(a) RASSOC(a)->cdr
static VALUE
Shash_new(class)
@@ -169,6 +169,37 @@ Fhash_delete(hash, key)
return Qnil;
}
+struct shift_var {
+ int stop;
+ VALUE key;
+ VALUE val;
+};
+
+static
+hash_shift(key, value, var)
+ VALUE key, value;
+ struct shift_var *var;
+{
+ if (var->stop) return ST_STOP;
+ var->stop = 1;
+ var->key = key;
+ var->val = value;
+ return ST_DELETE;
+}
+
+static VALUE
+Fhash_shift(hash)
+ struct RHash *hash;
+{
+ struct shift_var var;
+
+ var.stop = 0;
+ st_foreach(hash->tbl, hash_shift, &var);
+
+ if (var.stop == 0) return Qnil;
+ return assoc_new(var.key, var.val);
+}
+
static int
hash_delete_if(key, value)
VALUE key, value;
@@ -198,7 +229,7 @@ static VALUE
Fhash_clear(hash)
struct RHash *hash;
{
- st_foreach(hash->tbl, hash_clear, Qnil);
+ st_foreach(hash->tbl, hash_clear);
return (VALUE)hash;
}
@@ -616,6 +647,7 @@ Init_Hash()
rb_define_method(C_Hash,"keys", Fhash_keys, 0);
rb_define_method(C_Hash,"values", Fhash_values, 0);
+ rb_define_method(C_Hash,"shift", Fhash_shift, 0);
rb_define_method(C_Hash,"delete", Fhash_delete, 1);
rb_define_method(C_Hash,"delete_if", Fhash_delete_if, 0);
rb_define_method(C_Hash,"clear", Fhash_clear, 0);
diff --git a/inits.c b/inits.c
index e575e4b..e53c637 100644
--- a/inits.c
+++ b/inits.c
@@ -23,13 +23,13 @@ rb_call_inits()
Init_Enumerable();
Init_Numeric();
Init_Bignum();
+ Init_Assoc();
Init_Array();
Init_Hash();
Init_Struct();
Init_String();
Init_Regexp();
Init_pack();
- Init_Cons();
Init_Range();
Init_IO();
Init_Dir();
diff --git a/ruby.h b/ruby.h
index aed41ee..24ebc4c 100644
--- a/ruby.h
+++ b/ruby.h
@@ -100,7 +100,7 @@ extern VALUE C_Data;
#define T_HASH 0x0a
#define T_STRUCT 0x0b
#define T_BIGNUM 0x0c
-#define T_CONS 0x0f
+#define T_ASSOC 0x0f
#define T_DATA 0x10
#define T_SCOPE 0xfe
@@ -216,13 +216,13 @@ struct RBignum {
USHORT *digits;
};
-struct RCons {
+struct RAssoc {
struct RBasic basic;
VALUE car, cdr;
};
-#define CAR(c) (RCONS(c)->car)
-#define CDR(c) (RCONS(c)->cdr)
+#define CAR(c) (RASSOC(c)->car)
+#define CDR(c) (RASSOC(c)->cdr)
#define R_CAST(st) (struct st*)
#define RBASIC(obj) (R_CAST(RBasic)(obj))
@@ -236,7 +236,7 @@ struct RCons {
#define RDATA(obj) (R_CAST(RData)(obj))
#define RSTRUCT(obj) (R_CAST(RStruct)(obj))
#define RBIGNUM(obj) (R_CAST(RBignum)(obj))
-#define RCONS(obj) (R_CAST(RCons)(obj))
+#define RASSOC(obj) (R_CAST(RAssoc)(obj))
#define FL_SINGLE (1<<8)
#define FL_MARK (1<<9)
diff --git a/sample/from.rb b/sample/from.rb
index a8baf4f..df82d5a 100644..100755
--- a/sample/from.rb
+++ b/sample/from.rb
@@ -59,8 +59,11 @@ $ARGV[0] = '/usr/spool/mail/' + ENV['USER'] if $ARGV.length == 0
$outcount = 0;
def fromout(date, from, subj)
- y, m, d = parsedate(date)
- printf "%-2d/%02d/%02d [%.28s] %.40s\n", y, m, d, from, subj
+ y = m = d = 0
+ y, m, d = parsedate(date) if date
+ from = "sombody@somewhere" if ! from
+ subj = "(nil)" if ! subj
+ printf "%-2d/%02d/%02d [%-28.28s] %-40.40s\n", y, m, d, from, subj
$outcount += 1
end
@@ -83,7 +86,6 @@ while TRUE
fromout fields['Date'], fields['From'], fields['Subject']
while gets()
-# print $_
break if /^From /
end
diff --git a/spec b/spec
index eaec5a3..7414f37 100644
--- a/spec
+++ b/spec
@@ -287,7 +287,7 @@ Rubyѿϥ(ͭϰ)ȼ̿(ͭ)ˤä4ʬव졤
{1=>2, 2=>4, 3=>6}
ϢȤǤդΥ֥Ȥ򥭡(ź)ȤƻǤ롥Ruby
-ϢHash(ϥåɽ)饹Υ󥹥󥹤Ǥ롥ܺ٤ϥ饹
+ϢHash(Ϣ)饹Υ󥹥󥹤Ǥ롥ܺ٤ϥ饹
Hashι򻲾Ȥ줿ϢϢ󼰤ϰʲηǤ롥
`{' `=>' .. `}'
@@ -865,6 +865,13 @@ Rubyˤϸ̩ʰ̣ǤϴؿϤʤKernel饹δؿ᥽åɤ(Ƥ
ޥɥ饤󤫤ϤEOFãƤ硤֤
+ esub(pattern)
+
+ ƥѿ`$_'λؤʸФִԤʤƥ졼ʸ
+ pattern˥ޥåʬʸ˥֥åɾ
+ η̤֤롥String饹esub᥽åɤβ򻲾Ȥ
+ ȡesub᥽åɤ`$_'ͤ򹹿롥
+
eval(expr)
exprȤͿ줿ʸrubyץȤƲᡤ¹Ԥ롥
@@ -1255,8 +1262,8 @@ Methods:
assoc(key)
- Ϣۥꥹ(CONSڥǤȤ)򸡺1Ǥkey
- ("=="Ӥ)֤
+ Ϣۥꥹ(assocڥǤȤ)򸡺1Ǥkey
+ ("=="Ӥ)֤
clear
@@ -1376,6 +1383,31 @@ Single Methods:
ǤȤ롥
+** Assoc(饹)
+
+ǡ(ڥ)ɽ륯饹̾`::'黻ҤѤƹԤʤ
+롥
+
+SuperClass: Object
+
+Methods:
+
+ car
+
+ CONSڥΥǡCAR֤
+
+ car=(val)
+
+ CONSڥCARΥǡѹ롥
+
+ cdr
+
+ CONSڥΥǡCDR֤
+
+ cdr=(val)
+
+ CONSڥCDRΥǡѹ롥
+
** Bignum(饹)
̵¿ĹΥ饹黻η̤FixnumϰǤˤϼ
@@ -1495,63 +1527,6 @@ Methods:
selfminmaxϰˤ֤
-** Cons(饹)
-
-ǡ(ڥ)ɽ륯饹̾`::'黻ҤѤƹԤʤ
-롥LispCONSڥƱͤListѤ뤳Ȥ⤢롥
-Cons饹Υ᥽å`[]',`[]=',`each'CONSڥʤꥹȤФ
-ư褦߷פƤ롥
-
-:
- a=1::2::3
- a[0] # a[0] => 1
- a[2] = 5 # a => 1::5::3
- for i in a
- print i
- end # prints `153'
-
-SuperClass: Object
-
-Included Modules: Enumerable
-
-Methods:
-
- self [nth]
-
- CONSڥʤꥹȤnthܤǤ֤бǤ¸
- ߤʤnil֤
-
- self [nth]= val
-
- CONSڥʤꥹȤnthܤǤѹ롥ꥹȤĹ
- nthǻꤷĹûơбǤ¸ߤʤ
- 㳰ȯ롥nthꥹȤĹˤϥꥹȤ
- Ǥɲä롥
-
- car
-
- CONSڥΥǡCAR֤
-
- car=(val)
-
- CONSڥCARΥǡѹ롥
-
- cdr
-
- CONSڥΥǡCDR֤
-
- cdr=(val)
-
- CONSڥCDRΥǡѹ롥
-
- copy
-
- CONSڥʤꥹȤʣ֤(shallow copy)
-
- each
-
- CONSڥʤꥹȤγǤͿ륤ƥ졼
-
** Dir(饹)
ǥ쥯ȥǤ֤ǥ쥯ȥꥹȥ꡼ΤΥ饹
@@ -2235,11 +2210,11 @@ Methods:
has_key(key)
includes(key)
- key¸ߤ֤
+ keyϢ¸ߤ֤
has_value(value)
- valueͤȤȤ¸ߤ֤
+ valueͤȤȤϢ¸ߤ֤
indexes(ary)
indexes(key-1, ..., key-n)
@@ -2250,30 +2225,36 @@ Methods:
keys
- ¸ߤ륭Ƥޤ֤
+ Ϣ¸ߤ륭Ƥޤ֤
length
size
- Ǥο֤
+ ϢǤο֤
+
+ shift
+
+ ϢǤļФ()key::valueʤڥ
+ ֤
to_a
- key-valueڥǤȤ֤
+ Ϣkey-valueڥǤȤ֤
values
- ¸ߤƤޤ֤
+ Ϣ¸ߤƤޤ֤
Single Methods:
Hash[key, value..]
- ܤΰkeyܤΰvalueȤ뼭롥
+ ܤΰkeyܤΰvalueȤϢ
+ 롥
new
- ()񥪥֥Ȥ֤
+ ()Ϣ󥪥֥Ȥ֤
** Integer(饹)
@@ -2450,7 +2431,7 @@ Methods:
self :: other
- selfotherǤȤCONSڥ֤α黻ҤϱǤ
+ selfotherǤȤassocڥ֤α黻ҤϱǤ
Τǡa::b::c (a::(b::c)) Ȳᤵ롥
is_nil
@@ -2942,6 +2923,12 @@ Methods:
ʸΤ줾ΥХȤˤĤƷ֤ƥ졼
+ esub(pattern)
+
+ ʸpattern˥ޥåʬִ륤ƥ졼ޥå
+ ʬʸȤƥ֥åɾ̤ʸ֤
+ 롥sub/gsubΤ褦`&', `\1..\9'ִϹԤʤʤ
+
gsub(pattern, replace)
ʸpattern˥ޥåʬreplace֤롥
diff --git a/string.c b/string.c
index 73c1678..c733faf 100644
--- a/string.c
+++ b/string.c
@@ -674,15 +674,14 @@ str_sub(str, pat, val, once)
VALUE val;
int once;
{
- VALUE sub;
int beg, end, offset, n;
for (offset=0, n=0;
(beg=research(pat, str, offset)) >= 0;
offset=BEG(0)+STRLEN(val)) {
end = END(0)-1;
- sub = re_regsub(val);
- str_replace2(str, beg, end, sub);
+ val = re_regsub(val);
+ str_replace2(str, beg, END(0)-1, val);
n++;
if (once) break;
}
@@ -811,6 +810,37 @@ Fstr_gsub(str, pat, val)
return Fstr_sub_internal(str, pat, val, 0);
}
+static VALUE
+Fstr_esub(str, pat)
+ VALUE str, pat;
+{
+ VALUE val;
+ int beg, end, offset, n;
+
+ str_modify(str);
+ switch (TYPE(pat)) {
+ case T_REGEXP:
+ break;
+
+ case T_STRING:
+ pat = re_regcomp(pat);
+ break;
+
+ default:
+ /* type failed */
+ Check_Type(pat, T_REGEXP);
+ }
+
+ offset=0;
+ while ((beg=research(pat, str, offset)) >= 0) {
+ val = rb_yield(re_nth_match(0));
+ val = obj_as_string(val);
+ str_replace2(str, beg, END(0)-1, val);
+ offset=BEG(0)+STRLEN(val);
+ }
+ return (VALUE)str;
+}
+
extern VALUE rb_lastline;
static VALUE
@@ -830,6 +860,14 @@ Fgsub(obj, pat, val)
}
static VALUE
+Fesub(obj, pat)
+ VALUE obj, pat;
+{
+ Check_Type(rb_lastline, T_STRING);
+ return Fstr_esub(rb_lastline, pat);
+}
+
+static VALUE
Fstr_reverse(str)
struct RString *str;
{
@@ -1669,6 +1707,7 @@ Init_String()
rb_define_method(C_String, "sub", Fstr_sub, 2);
rb_define_method(C_String, "gsub", Fstr_gsub, 2);
+ rb_define_method(C_String, "esub", Fstr_esub, 1);
rb_define_method(C_String, "chop", Fstr_chop, 0);
rb_define_method(C_String, "strip", Fstr_strip, 0);
@@ -1684,6 +1723,7 @@ Init_String()
rb_define_private_method(C_Kernel, "sub", Fsub, 2);
rb_define_private_method(C_Kernel, "gsub", Fgsub, 2);
+ rb_define_private_method(C_Kernel, "esub", Fesub, 1);
pr_str = rb_intern("to_s");
}
diff --git a/struct.c b/struct.c
index 8ba8f43..c231191 100644
--- a/struct.c
+++ b/struct.c
@@ -97,8 +97,8 @@ struct_new(name, va_alist)
return st;
}
-#define ASSOC_KEY(a) RCONS(a)->car
-#define ASSOC_VAL(a) RCONS(a)->cdr
+#define ASSOC_KEY(a) RASSOC(a)->car
+#define ASSOC_VAL(a) RASSOC(a)->cdr
static VALUE
Sstruct_new(argc, argv, class)
@@ -117,7 +117,7 @@ Sstruct_new(argc, argv, class)
for (i=0, max=tbl->len; i<max; i++) {
VALUE assoc = tbl->ptr[i];
- Check_Type(assoc, T_CONS);
+ Check_Type(assoc, T_ASSOC);
Check_Type(ASSOC_KEY(assoc), T_STRING);
struct_add(st, RSTRING(ASSOC_KEY(assoc))->ptr, ASSOC_VAL(assoc));
}
diff --git a/version.h b/version.h
index 0602e0c..0884609 100644
--- a/version.h
+++ b/version.h
@@ -1,2 +1,2 @@
-#define RUBY_VERSION "0.72"
-#define VERSION_DATE "95/04/05"
+#define RUBY_VERSION "0.73"
+#define VERSION_DATE "95/04/13"