diff options
author | Yukihiro Matsumoto <[email protected]> | 1995-04-10 18:36:06 +0900 |
---|---|---|
committer | Takashi Kokubun <[email protected]> | 2019-08-17 22:09:32 +0900 |
commit | b2420d8ffa4d347a75efbbdc376f4ce65c0eb172 (patch) | |
tree | bd40c44d9155d9cb10232a0e962dc1cc221c2c8b | |
parent | 11e21a36bc935088f88a7cd1548f8c74c3bf6099 (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-- | ChangeLog | 11 | ||||
-rw-r--r-- | MANIFEST | 2 | ||||
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | array.c | 8 | ||||
-rw-r--r-- | assoc.c | 150 | ||||
-rw-r--r-- | bignum.c | 2 | ||||
-rw-r--r-- | configure.in | 5 | ||||
-rw-r--r-- | cons.c | 270 | ||||
-rw-r--r-- | error.c | 2 | ||||
-rw-r--r-- | ext/MANIFEST | 6 | ||||
-rw-r--r-- | ext/Makefile.in | 40 | ||||
-rw-r--r-- | ext/dbm.c | 441 | ||||
-rw-r--r-- | ext/dbm.doc | 107 | ||||
-rw-r--r-- | ext/socket.c | 761 | ||||
-rw-r--r-- | ext/socket.doc | 227 | ||||
-rw-r--r-- | gc.c | 10 | ||||
-rw-r--r-- | hash.c | 38 | ||||
-rw-r--r-- | inits.c | 2 | ||||
-rw-r--r-- | ruby.h | 10 | ||||
-rwxr-xr-x[-rw-r--r--] | sample/from.rb | 8 | ||||
-rw-r--r-- | spec | 125 | ||||
-rw-r--r-- | string.c | 46 | ||||
-rw-r--r-- | struct.c | 6 | ||||
-rw-r--r-- | version.h | 4 |
24 files changed, 1910 insertions, 373 deletions
@@ -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�Ȥ��Ƥε�ǽ������ + �Ĥ�����enumerable��include����Τ���� + + * string.c(esub): ʸ�����ִ����ƥ졼����perl��s///e���������롥 + Wed Apr 5 11:35:21 1995 Yukihiro Matsumoto (matz@ix-02) * version 0.72 @@ -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 35efe604f6..c992baea6d 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 \ @@ -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 0000000000..ef20c0216b --- /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); +} @@ -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 1dd44040f3..13468317ba 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 42df8cb4fa..0000000000 --- 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); -} @@ -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 0000000000..881a97c39e --- /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 0000000000..20d8c5c9c4 --- /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 0000000000..f3e8295d6a --- /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 0000000000..48c91a9157 --- /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 0000000000..ec992340a4 --- /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 0000000000..aa5bfedbff --- /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)��Ʊ��Ư���롥addr��pack���줿�����åȥ��ɥ쥹��¤ + �ΤǤ��롥 + + connect(addr) + + connect(2)��Ʊ��Ư���롥addr��pack���줿�����åȥ��ɥ쥹�� + ¤�ΤǤ��롥 + + 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) + + �����������åȤ��������롥domain��type��protocol�ϥ��롼�� + �ե�������������Ƥ�������ͤǻ��ꤹ�롥domain��type�˴ؤ��� + �ϡ�ʸ����ǻ���Ǥ��뤬�����٤ƤС����Ƥ����ݾڤϤʤ��� + + 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) + + �����åȤΰʹߤ���³��λ�����롥how��0�Ǥ�������ʹߤμ������� + how��1�Ǥ�����ϡ��ʹߤ����������ݤ���롥how��2�λ��ˤϡ����� + �ʹߤ������������Ȥ�˵��ݤ���롥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: @@ -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); @@ -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); @@ -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(); @@ -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 a8baf4f375..df82d5a745 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 @@ -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: self��min��max���ϰ���ˤ���������֤��� -** Cons(���饹) - -�ǡ�������(�ڥ�)��ɽ�����륯�饹���̾������`::'�黻�Ҥ��Ѥ��ƹԤʤ� -��롥Lisp��CONS�ڥ���Ʊ�ͤ�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 - self��other�����ǤȤ���CONS�ڥ����֤������α黻�Ҥϱ����Ǥ� + self��other�����ǤȤ���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���֤������롥 @@ -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"); } @@ -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)); } @@ -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" |