1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

thread bugs

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_3@482 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 1999-06-09 09:21:37 +00:00
parent 17ae11ca25
commit c1241cd2ed
42 changed files with 1371 additions and 8275 deletions

View file

@ -1,5 +1,80 @@
Wed Jun 9 13:26:38 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
* eval.c (rb_thread_loading): modified to avoid nested race
condition of require().
* ext/tcltklib/tcltklib.c (ip_invoke): queue invocation on non
main threads.
* ext/tcltklib/tcltklib.c (lib_mainloop): flush invoke queues.
* version.c (ruby_show_version): now print the message to stdout.
* version.c (ruby_show_copyright): ditto.
Tue Jun 8 00:00:34 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
* pack.c (pack_unpack): append sentinel (NUL) to the string.
* ext/md5/md5init.c (md5_hexdigest): new method to obtain
printable hash string.
* ext/md5/md5init.c (md5_update): should return self.
* pack.c (pack_pack): undocumented template 'U' for UTF8.
* pack.c (pack_unpack): ditto.
* marshal.c (r_byte): should replace getc() with rb_getc().
* io.c (rb_getc): getc() replacement uses READ_DATA_PENDING() and
rb_thread_wait_fd().
Mon Jun 7 23:23:38 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
* object.c (rb_mod_clone): should call CLOSESETUP().
* eval.c (bind_clone): should call CLONESETUP() for new clone.
Sat Jun 5 10:32:40 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
* string.c (rb_str_oct): binary (e.g. 0b10111) support.
* variable.c (rb_const_set): raise warning, not exception.
* parse.y (yycompile): initialize parser internal variables.
* parse.y (close_paren): set lex_state to EXPR_PAREN after closing
parenthesis.
* parse.y (yylex): returns kDO for `do' right after method_call.
Thu Jun 3 11:05:30 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
* regex.c (read_backslash): should decode \b within class.
Thu Jun 3 01:06:18 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
* dln.c (dln_load): AIX improvement (aix_findmain removed).
Wed Jun 2 00:41:31 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
* pack.c (pack_unpack): new undocumented template Z which strips
stuff after first null.
* pack.c (pack_pack): should preserve specified length of the
resulting string.
Tue Jun 1 15:29:33 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
* ext/socket/socket.c (ruby_socket): retry after GC, if socket(2)
failed on EMFILE or ENFILE.
* ext/socket/socket.c (sock_s_socketpair): ditto.
* eval.c (module_setup): need to add PUSH_VAR/POP_VAR to clear
dyna vars link list.
* version.h (RUBY_RELEASE_CODE): integer macro contant for source
version detection.

View file

@ -76,6 +76,7 @@ variable.c
version.c
version.h
beos/ruby.def.in
cygwin/GNUmakefile.in
ext/Setup
ext/Setup.dj
ext/Setup.emx
@ -85,6 +86,7 @@ ext/aix_mksym.rb
ext/cygwin32_ld.rb
ext/extmk.rb.in
ext/extmk.rb.nt
lib/CGI.rb
lib/English.rb
lib/Env.rb
lib/README
@ -171,6 +173,8 @@ sample/cbreak.rb
sample/clnt.rb
sample/dbmtest.rb
sample/dir.rb
sample/dualstack-fetch.rb
sample/dualstack-httpd.rb
sample/eval.rb
sample/export.rb
sample/exyacc.rb
@ -204,6 +208,7 @@ sample/rbc.rb
sample/rcs.awk
sample/rcs.dat
sample/rcs.rb
sample/rd2html.rb
sample/regx.rb
sample/sieve.rb
sample/svr.rb

6
README
View file

@ -98,9 +98,9 @@ You can redistribute it and/or modify it under either the terms of the GPL
4. You may modify and include the part of the software into any other
software (possibly commercial). But some files in the distribution
are not written by the author, so that they are not under this terms.
They are gc.c(partly), utils.c(partly), regex.[ch], glob.c, st.[ch]
and some files under the ./missing directory. See each file for the
copying condition.
They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
files under the ./missing directory. See each file for the copying
condition.
5. The scripts and library files supplied as input to or produced as
output from the software do not automatically fall under the

View file

@ -35,21 +35,21 @@ Ruby
* ホームページ
RubyのホームページのURLは
RubyのホームページのURLは
http://www.netlab.co.jp/ruby/jp/
です.
です.
* メーリングリスト
Rubyに関わる話題のためのメーリングリストを開設しました
ドレスは
Rubyに関わる話題のためのメーリングリストを開設しました
ドレスは
ruby-list@netlab.co.jp
です.このアドレスにメールを送れば,自動的に登録されます.
です.このアドレスにメールを送れば,自動的に登録されます.
* コンパイル・インストール
@ -150,9 +150,9 @@ Licence)
4. 他のプログラムへの引用はいかなる目的であれ自由です.た
だしRubyに含まれる他の作者によるコードはそれぞれの
作者の意向による制限が加えられます具体的にはgc.c(一部)
util.c(一部)st.[ch]regex.[ch], glob.c および.
/missingディレクトリ下のファイル群が該当します.それぞ
れの配布条件などに付いては各ファイルを参照してください.
util.c(一部)st.[ch]regex.[ch] および. /missingディ
レクトリ下のファイル群が該当します.それぞれの配布条件
などに付いては各ファイルを参照してください.
5. Rubyへの入力となるスクリプトおよびRubyからの出力の権
利はRubyの作者ではなくそれぞれの入出力を生成した人に

2
config.guess vendored
View file

@ -382,7 +382,7 @@ EOF
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
9000/6?? | 9000/7?? | 9000/80[24] | 9000/8?[13679] | 9000/892 )
9000/6?? | 9000/7?? | 9000/80[024] | 9000/8?[13679] | 9000/892 )
sed 's/^ //' << EOF >dummy.c
#include <stdlib.h>
#include <unistd.h>

373
configure vendored

File diff suppressed because it is too large Load diff

View file

@ -148,6 +148,7 @@ openstep*) ;;
rhapsody*) ;;
human*) ;;
beos*) ;;
cygwin*) ;;
*) LIBS="-lm $LIBS";;
esac
AC_CHECK_LIB(crypt, crypt)
@ -379,7 +380,13 @@ if test "$with_dln_a_out" != yes; then
openstep*) ;;
rhapsody*) ;;
human*) ;;
cygwin*) CCDLFLAGS=-DDLLIMPORT;;
bsdi3*) ;;
cygwin*) ;;
netbsd*) CCDLFLAGS=-fpic
case "$host_cpu" in
mips*) CCDLFLAGS=-fPIC ;;
*) ;;
esac ;;
*) CCDLFLAGS=-fPIC;;
esac
else
@ -426,17 +433,15 @@ if test "$with_dln_a_out" != yes; then
test "$GCC" = yes && `$CC --print-prog-name=ld` -v 2>&1 | grep "GNU ld" > /dev/null || LDSHARED="ld -Bshareable"
fi
rb_cv_dlopen=yes ;;
netbsd*) LDSHARED="ld -Bshareable"
case "$host_cpu" in
alpha|mips)
LDFLAGS="-export-dynamic" ;;
*)
;;
esac
netbsd*) LDSHARED="ld -shared"
rb_cv_dlopen=yes ;;
openbsd*) LDSHARED="ld -Bforcearchive -Bshareable"
rb_cv_dlopen=yes ;;
nextstep*) LDSHARED='cc -r'
bsdi3*) case "$CC" in
*shlicc*) LDSHARED="$CC -r"
rb_cv_dlopen=yes ;;
esac ;;
nextstep*) LDSHARED='cc -r -nostdlib'
LDFLAGS="-u libsys_s"
DLDFLAGS="$ARCH_FLAG"
rb_cv_dlopen=yes ;;
@ -470,7 +475,7 @@ if test "$with_dln_a_out" != yes; then
DLDFLAGS="ruby.def -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o"
esac
rb_cv_dlopen=yes ;;
cygwin*) LDSHARED='../../miniruby ../cygwin32_ld.rb'
cygwin*) LDSHARED='dllwrap --export-all -s'
rb_cv_dlopen=yes ;;
*) LDSHARED='ld' ;;
esac
@ -502,15 +507,15 @@ if test "$dln_a_out_works" = yes; then
else
STATIC=-Bstatic
fi
DLEXT=o
AC_DEFINE(DLEXT, ".o")
DLEXT=so
AC_DEFINE(DLEXT, ".so")
CCDLFLAGS=
else
case "$host_os" in
hpux*) DLEXT=sl
AC_DEFINE(DLEXT, ".sl");;
nextstep*) DLEXT=o
AC_DEFINE(DLEXT, ".o");;
nextstep*) DLEXT=bundle
AC_DEFINE(DLEXT, ".bundle");;
openstep*) DLEXT=bundle
AC_DEFINE(DLEXT, ".bundle");;
rhapsody*) DLEXT=bundle
@ -518,7 +523,7 @@ else
cygwin*) DLEXT=dll
AC_DEFINE(DLEXT, ".dll");;
os2_emx) DLEXT=o
AC_DEFINE(DLEXT, ".o");;
AC_DEFINE(DLEXT, ".so");;
*) DLEXT=so
AC_DEFINE(DLEXT, ".so");;
esac
@ -652,6 +657,7 @@ if test "$host_os" = "beos"; then
esac
fi
FIRSTMAKEFILE=""
LIBRUBY_LDSHARED=$LDSHARED
LIBRUBY_DLDFLAGS=$DLDFLAGS
LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR).$(TEENY)'
@ -674,6 +680,14 @@ if test "$enable_shared" = 'yes'; then
LIBRUBY_ALIASES=''
fi
;;
netbsd*)
LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR)'
case "$host_cpu" in
alpha|mipsel|mipseb|powerpc|sparc64) # ELF platforms
LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR) lib$(RUBY_INSTALL_NAME).so' ;;
*) LIBRUBY_ALIASES= ;; # a.out platforms
esac
;;
hpux*)
LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).sl.$(MAJOR).$(MINOR).$(TEENY)'
LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).sl.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).sl'
@ -689,6 +703,15 @@ if test "$enable_shared" = 'yes'; then
LIBRUBYARG='-L./ -Wl,lib$(RUBY_INSTALL_NAME).so'
SOLIBS='-lm -lc'
;;
cygwin*)
LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).a'
LIBRUBY_ALIASES=''
LIBRUBY_A='lib$(RUBY_INSTALL_NAME)s.a'
LIBRUBYARG='-L. -l$(RUBY_INSTALL_NAME)'
FIRSTMAKEFILE=GNUmakefile:cygwin/GNUmakefile.in
LIBOBJS="$LIBOBJS strftime.o"
CCDLFLAGS=-DUSEIMPORTLIB
;;
*)
;;
esac
@ -755,4 +778,4 @@ AC_DEFINE_UNQUOTED(RUBY_SITE_ARCHLIB, "${RUBY_SITE_LIB_PATH}/${arch}")
echo "creating config.h"
cat confdefs.h > config.h
AC_OUTPUT(Makefile ext/extmk.rb)
AC_OUTPUT($FIRSTMAKEFILE Makefile ext/extmk.rb)

59
dln.c
View file

@ -1158,35 +1158,6 @@ dln_strerror()
#if defined(_AIX)
static void *
aix_findmain()
{
struct ld_info *lp;
char *buf;
int size = 4 * 1024;
int rc;
void *ret;
if ((buf = xmalloc(size)) == NULL) {
return NULL;
}
while ((rc = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
free(buf);
size += 4 * 1024;
if ((buf = xmalloc(size)) == NULL) {
return NULL;
}
}
if (rc == -1) {
free(buf);
return NULL;
}
lp = (struct ld_info *)buf;
ret = lp->ldinfo_dataorg;
free(buf);
return ret;
}
static void
aix_loaderror(const char *pathname)
{
@ -1342,19 +1313,13 @@ dln_load(file)
#if defined(_AIX)
#define DLN_DEFINED
{
static void *main_module = NULL;
void (*init_fct)();
if (main_module == NULL) {
if ((main_module = aix_findmain()) == NULL) {
aix_loaderror(file);
}
}
init_fct = (void(*)())load((char*)file, 1, 0);
if (init_fct == NULL) {
aix_loaderror(file);
}
if (loadbind(0, main_module, (void*)init_fct) == -1) {
if (loadbind(0, (void*)dln_load, (void*)init_fct) == -1) {
aix_loaderror(file);
}
(*init_fct)();
@ -1372,7 +1337,7 @@ dln_load(file)
Mi hisho@tasihara.nest.or.jp,
and... Miss ARAI Akino(^^;)
----------------------------------------------------*/
#if defined(NeXT) && ( NS_TARGET_MAJOR < 4 )/* NeXTSTEP rld functions */
#if defined(NeXT) && (NS_TARGET_MAJOR < 4)/* NeXTSTEP rld functions */
{
unsigned long init_address;
@ -1409,7 +1374,7 @@ dln_load(file)
void (*init_fct)();
dyld_result = NSCreateObjectFileImageFromFile( file, &obj_file );
dyld_result = NSCreateObjectFileImageFromFile(file, &obj_file);
if (dyld_result != NSObjectFileImageSuccess) {
rb_loaderror("Failed to load %.200s", file);
@ -1419,12 +1384,12 @@ dln_load(file)
/* lookup the initial function */
/*NSIsSymbolNameDefined require function name without "_" */
if( NSIsSymbolNameDefined( buf + 1 ) ) {
if(NSIsSymbolNameDefined(buf + 1)) {
rb_loaderror("Failed to lookup Init function %.200s",file);
}
/* NSLookupAndBindSymbol require function name with "_" !! */
init_fct = NSAddressOfSymbol( NSLookupAndBindSymbol( buf ) );
init_fct = NSAddressOfSymbol(NSLookupAndBindSymbol(buf));
(*init_fct)();
return ;
@ -1499,8 +1464,8 @@ dln_load(file)
c2pstr(fullpath);
(void)FSMakeFSSpec(0, 0, fullpath, &libspec);
err = ResolveAliasFile(&libspec, 1, &isfolder, &didsomething);
if ( err ) {
rb_loaderror("Unresolved Alias - %s", file);
if (err) {
rb_loaderror("Unresolved Alias - %s", file);
}
/* Load the fragment (or return the connID if it is already loaded */
@ -1508,16 +1473,16 @@ dln_load(file)
err = GetDiskFragment(&libspec, 0, 0, fragname,
kLoadCFrag, &connID, &mainAddr,
errMessage);
if ( err ) {
p2cstr(errMessage);
rb_loaderror("%s - %s",errMessage , file);
if (err) {
p2cstr(errMessage);
rb_loaderror("%s - %s",errMessage , file);
}
/* Locate the address of the correct init function */
c2pstr(buf);
err = FindSymbol(connID, buf, &symAddr, &class);
if ( err ) {
rb_loaderror("Unresolved symbols - %s" , file);
if (err) {
rb_loaderror("Unresolved symbols - %s" , file);
}
init_fct = (void (*)())symAddr;

107
eval.c
View file

@ -648,23 +648,23 @@ static VALUE ruby_wrapper; /* security wrapper */
scope_vmode = SCOPE_PUBLIC;
#define SCOPE_DONT_RECYCLE FL_USER2
#define POP_SCOPE() \
#define POP_SCOPE() \
if (FL_TEST(ruby_scope, SCOPE_DONT_RECYCLE)) {\
FL_SET(_old, SCOPE_DONT_RECYCLE);\
}\
else {\
} \
else { \
if (ruby_scope->flag == SCOPE_ALLOCA) {\
ruby_scope->local_vars = 0;\
ruby_scope->local_tbl = 0;\
ruby_scope->local_vars = 0; \
ruby_scope->local_tbl = 0; \
if (ruby_scope != top_scope)\
rb_gc_force_recycle((VALUE)ruby_scope);\
}\
else {\
} \
else { \
ruby_scope->flag |= SCOPE_NOSTACK;\
}\
}\
ruby_scope = _old;\
scope_vmode = _vmode;\
} \
} \
ruby_scope = _old; \
scope_vmode = _vmode; \
}
static VALUE rb_eval _((VALUE,NODE*));
@ -2871,6 +2871,7 @@ module_setup(module, node)
PUSH_CLASS();
ruby_class = module;
PUSH_SCOPE();
PUSH_VARS();
if (node->nd_rval) ruby_frame->cbase = node->nd_rval;
if (node->nd_tbl) {
@ -2894,6 +2895,7 @@ module_setup(module, node)
result = rb_eval(ruby_class, node->nd_next);
}
POP_TAG();
POP_VARS();
POP_SCOPE();
POP_CLASS();
@ -4650,7 +4652,7 @@ rb_provided(feature)
}
static int rb_thread_loading _((const char*));
static void rb_thread_loading_done _((void));
static void rb_thread_loading_done _((const char*));
void
rb_provide(feature)
@ -4677,6 +4679,7 @@ rb_f_require(obj, fname)
{
char *ext, *file, *feature, *buf; /* OK */
volatile VALUE load;
int state;
rb_secure(4);
Check_SafeStr(fname);
@ -4729,34 +4732,32 @@ rb_f_require(obj, fname)
load_dyna:
if (rb_thread_loading(feature)) return Qfalse;
else {
int state;
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
load = rb_str_new2(file);
file = RSTRING(load)->ptr;
dln_load(file);
rb_provide(feature);
}
POP_TAG();
rb_thread_loading_done();
if (state) JUMP_TAG(state);
rb_provide(feature);
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
load = rb_str_new2(file);
file = RSTRING(load)->ptr;
dln_load(file);
}
POP_TAG();
rb_thread_loading_done(feature);
if (state) JUMP_TAG(state);
return Qtrue;
load_rb:
if (rb_thread_loading(feature)) return Qfalse;
else {
int state;
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
rb_load(fname, 0);
rb_provide(feature);
}
POP_TAG();
rb_thread_loading_done();
if (state) JUMP_TAG(state);
rb_provide(feature);
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
rb_load(fname, 0);
}
POP_TAG();
rb_thread_loading_done(feature);
if (state) JUMP_TAG(state);
return Qtrue;
}
@ -5306,7 +5307,8 @@ bind_clone(self)
VALUE bind;
Data_Get_Struct(self, struct BLOCK, orig);
bind = Data_Make_Struct(self,struct BLOCK,blk_mark,blk_free,data);
bind = Data_Make_Struct(rb_cBinding,struct BLOCK,blk_mark,blk_free,data);
CLONESETUP(bind,self);
MEMCPY(data, orig, struct BLOCK, 1);
data->frame.argv = ALLOC_N(VALUE, orig->frame.argc);
MEMCPY(data->frame.argv, orig->frame.argv, VALUE, orig->frame.argc);
@ -6616,7 +6618,7 @@ rb_thread_main()
return main_thread->thread;
}
static VALUE
VALUE
rb_thread_wakeup(thread)
VALUE thread;
{
@ -6629,7 +6631,7 @@ rb_thread_wakeup(thread)
return thread;
}
static VALUE
VALUE
rb_thread_run(thread)
VALUE thread;
{
@ -6675,7 +6677,7 @@ rb_thread_pass()
return Qnil;
}
static VALUE
VALUE
rb_thread_stop()
{
rb_thread_critical = 0;
@ -7125,32 +7127,29 @@ rb_thread_raise(argc, argv, thread)
return Qnil; /* not reached */
}
static thread_t loading_thread;
static int loading_nest;
static st_table *loading_tbl;
static int
rb_thread_loading(feature)
const char *feature;
{
if (curr_thread != curr_thread->next && loading_thread) {
while (loading_thread != curr_thread) {
rb_thread_schedule();
CHECK_INTS;
}
if (rb_provided(feature)) return Qtrue; /* no need to load */
if (!rb_provided(feature)) return Qfalse; /* need to load */
if (!loading_tbl) {
loading_tbl = st_init_strtable();
}
loading_thread = curr_thread;
loading_nest++;
return Qfalse;
while (st_lookup(loading_tbl, feature, 0)) {
CHECK_INTS;
rb_thread_schedule();
}
return Qtrue;
}
static void
rb_thread_loading_done()
rb_thread_loading_done(feature)
const char *feature;
{
if (--loading_nest == 0) {
loading_thread = 0;
if (loading_tbl) {
st_delete(loading_tbl, feature, 0);
}
}

View file

@ -324,6 +324,19 @@ def create_makefile(target)
$DLDFLAGS = $DLDFLAGS + " -L" + $topdir
end
defflag = ''
if PLATFORM =~ /cygwin/ and not $static
if File.exist? target + ".def"
defflag = "--def=" + target + ".def"
end
if $libs
$libs = $libs + " @LIBRUBYARG@"
else
$libs = "@LIBRUBYARG@"
end
$DLDFLAGS = $DLDFLAGS + " -L" + $topdir
end
$srcdir = $top_srcdir + "/ext/" + $mdir
mfile = open("Makefile", "w")
mfile.printf "\
@ -342,7 +355,7 @@ CC = @CC@
prefix = @prefix@
CFLAGS = %s -I#{$topdir} -I#{$top_srcdir} -I@includedir@ #{CFLAGS} #$CFLAGS %s
DLDFLAGS = #$DLDFLAGS #$LDFLAGS
LDSHARED = @LDSHARED@
LDSHARED = @LDSHARED@ #{defflag}
", if $static then "" else "@CCDLFLAGS@" end, $defs.join(" ")
mfile.printf "\
@ -367,7 +380,7 @@ archdir = $(pkglibdir)/@arch@
$objs = []
for f in Dir["#{$top_srcdir}/ext/#{$mdir}/*.{#{SRC_EXT.join(%q{,})}}"]
f = File.basename(f)
f.sub!(/\.(c|cc)$/, ".o")
f.sub!(/(#{SRC_EXT.join(%q{|})})$/, "o")
$objs.push f
end
end
@ -418,23 +431,21 @@ $(DLLIB): $(OBJS)
$(DLLIB): $(OBJS)
$(LDSHARED) $(DLDFLAGS) -o $(DLLIB) $(OBJS) $(LIBS) $(LOCAL_LIBS)
"
elsif not SRC_EXT.detect{|ext| File.exist?(target + ext)}
if PLATFORM == "m68k-human"
mfile.printf "\
elsif PLATFORM == "m68k-human"
mfile.printf "\
$(DLLIB): $(OBJS)
ar cru $(DLLIB) $(OBJS)
"
elsif PLATFORM =~ "-nextstep" || PLATFORM =~ "-openstep" || PLATFORM =~ "-rhapsody"
mfile.printf "\
elsif PLATFORM =~ "-nextstep" || PLATFORM =~ "-openstep" || PLATFORM =~ "-rhapsody"
mfile.printf "\
$(DLLIB): $(OBJS)
cc -r $(CFLAGS) -o $(DLLIB) $(OBJS)
"
else
mfile.printf "\
else
mfile.printf "\
$(DLLIB): $(OBJS)
ld $(DLDFLAGS) -r -o $(DLLIB) $(OBJS)
"
end
end
if File.exist?("depend")

View file

@ -29,8 +29,9 @@ md5_update(obj, str)
Data_Get_Struct(obj, MD5_CTX, md5);
MD5Update(md5, str->ptr, str->len);
return Qnil;
return obj;
}
static VALUE
md5_digest(obj)
VALUE obj;
@ -45,6 +46,26 @@ md5_digest(obj)
return rb_str_new(digest, 16);
}
static VALUE
md5_hexdigest(obj)
VALUE obj;
{
MD5_CTX *md5, ctx;
unsigned char digest[16];
char buf[35];
char *p = buf;
int i;
Data_Get_Struct(obj, MD5_CTX, md5);
ctx = *md5;
MD5Final(digest, &ctx);
for (i=0; i<16; i++) {
sprintf(buf+i*2, "%x", digest[i]);
}
return rb_str_new(buf, 32);
}
static VALUE
md5_clone(obj)
VALUE obj;
@ -90,5 +111,6 @@ Init_md5()
rb_define_method(cMD5, "update", md5_update, 1);
rb_define_method(cMD5, "digest", md5_digest, 0);
rb_define_method(cMD5, "hexdigest", md5_hexdigest, 0);
rb_define_method(cMD5, "clone", md5_clone, 0);
}

View file

@ -19,6 +19,10 @@
#include <sys/stropts.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#define DEVICELEN 16
#if !defined(HAVE_OPENPTY)

View file

@ -16,6 +16,7 @@ if readline_dir
$LDFLAGS = "-L#{readline_dir}"
end
have_library("user32", nil) if /cygwin/ === PLATFORM
have_library("termcap", "tgetnum")
have_library("curses", "tgetnum")
if have_header("readline/readline.h") and

View file

@ -27,6 +27,8 @@
* SUCH DAMAGE.
*/
#ifndef ADDR_INFO_H
#define ADDR_INFO_H
#ifndef HAVE_GETADDRINFO
/* special compatibility hack */
@ -167,3 +169,4 @@ Standard C system should have one. */
#endif
#endif
#endif

View file

@ -1,3 +1,3 @@
socket.o : socket.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h $(hdrdir)/rubyio.h $(hdrdir)/rubysig.h sockport.h
getaddrinfo.o: getaddrinfo.c addrinfo.h sockport.h
getnameinfo.o: getnameinfo.c addrinfo.h sockport.h
getnameinfo.o: getnameinfo.c $(hdrdir)/config.h addrinfo.h sockport.h
getaddrinfo.o: getaddrinfo.c $(hdrdir)/config.h addrinfo.h sockport.h

View file

@ -6,8 +6,11 @@ case PLATFORM
when /mswin32/
test_func = "WSACleanup"
have_library("wsock32", "WSACleanup")
when /cygwin32/
when /cygwin/
$LDFLAGS << " -L/usr/lib" if File.directory?("/usr/lib")
$CFLAGS << " -I/usr/include"
test_func = "socket"
have_library("bind", "gethostbyaddr")
when /beos/
test_func = "socket"
have_library("net", "socket")
@ -252,8 +255,8 @@ if have_getaddrinfo
$CFLAGS="-DHAVE_GETADDRINFO "+$CFLAGS
else
$CFLAGS="-I. "+$CFLAGS
$objs += "getaddrinfo.o"
$objs += "getnameinfo.o"
$objs += ["getaddrinfo.o"]
$objs += ["getnameinfo.o"]
have_func("inet_ntop") or have_func("inet_ntoa")
have_func("inet_pton") or have_func("inet_aton")
end

View file

@ -61,6 +61,12 @@
#define YES 1
#define NO 0
struct sockinet {
u_char si_len;
u_char si_family;
u_short si_port;
};
static struct afd {
int a_af;
int a_addrlen;
@ -68,18 +74,18 @@ static struct afd {
int a_off;
} afdl [] = {
#ifdef INET6
{PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
offsetof(struct sockaddr_in6, sin6_addr)},
#define N_INET6 0
{PF_INET6, sizeof(struct in6_addr),
sizeof(struct sockaddr_in6),
offsetof(struct sockaddr_in6, sin6_addr)},
#define N_INET 1
#else
#define N_INET 0
#endif
{PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
offsetof(struct sockaddr_in, sin_addr)},
{0, 0, 0},
};
struct sockinet {
u_char si_len;
u_char si_family;
u_short si_port;
{PF_INET, sizeof(struct in_addr),
sizeof(struct sockaddr_in),
offsetof(struct sockaddr_in, sin_addr)},
{0, 0, 0, 0},
};
#define ENI_NOSOCKET 0

View file

@ -582,6 +582,21 @@ thread_write_select(fd)
rb_thread_select(fd+1, 0, &fds, 0, 0);
}
static int
ruby_socket(domain, type, proto)
int domain, type, proto;
{
int fd;
fd = socket(domain, type, proto);
if (fd < 0) {
if (errno == EMFILE || errno == ENFILE) {
rb_gc();
fd = socket(domain, type, proto);
}
}
}
static int
ruby_connect(fd, sockaddr, len, socks)
int fd;
@ -683,11 +698,12 @@ open_inet(class, h, serv, type)
fd = -1;
for (res = res0; res; res = res->ai_next) {
status = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
status = ruby_socket(res->ai_family,res->ai_socktype,res->ai_protocol);
syscall = "socket(2)";
fd = status;
if (fd < 0)
if (fd < 0) {
continue;
}
if (type == INET_SERVER) {
status = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
@ -939,8 +955,10 @@ open_unix(class, path, server)
OpenFile *fptr;
Check_SafeStr(path);
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) rb_sys_fail("socket(2)");
fd = ruby_socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
rb_sys_fail("socket(2)");
}
MEMZERO(&sockaddr, struct sockaddr_un, 1);
sockaddr.sun_family = AF_UNIX;
@ -1017,11 +1035,17 @@ udp_s_open(argc, argv, class)
{
VALUE arg;
int socktype = AF_INET;
int fd;
if (rb_scan_args(argc, argv, "01", &arg) == 1) {
socktype = NUM2INT(arg);
}
return sock_new(class, socket(socktype, SOCK_DGRAM, 0));
fd = ruby_socket(socktype, SOCK_DGRAM, 0);
if (fd < 0) {
rb_sys_fail("socket(2) - udp");
}
return sock_new(class, fd);
}
static VALUE
@ -1312,7 +1336,7 @@ sock_s_open(class, domain, type, protocol)
int d, t;
setup_domain_and_type(domain, &d, type, &t);
fd = socket(d, t, NUM2INT(protocol));
fd = ruby_socket(d, t, NUM2INT(protocol));
if (fd < 0) rb_sys_fail("socket(2)");
return sock_new(class, fd);
@ -1333,8 +1357,14 @@ sock_s_socketpair(class, domain, type, protocol)
int d, t, sp[2];
setup_domain_and_type(domain, &d, type, &t);
if (socketpair(d, t, NUM2INT(protocol), sp) < 0)
again:
if (socketpair(d, t, NUM2INT(protocol), sp) < 0) {
if (errno == EMFILE || errno == ENFILE) {
rb_gc();
goto again;
}
rb_sys_fail("socketpair(2)");
}
return rb_assoc_new(sock_new(class, sp[0]), sock_new(class, sp[1]));
#else
@ -1920,6 +1950,8 @@ Init_socket()
#endif
#ifdef AF_INET6
sock_define_const("AF_INET6", AF_INET6);
#endif
#ifdef PF_INET6
sock_define_const("PF_INET6", PF_INET6);
#endif

View file

@ -1,6 +1,6 @@
/************************************************
sockcomm.h -
sockport.h -
$Author$
$Date$
@ -8,8 +8,8 @@
************************************************/
#ifndef SOCKCOMM_H
#define SOCKCOMM_H
#ifndef SOCKPORT_H
#define SOCKPORT_H
#ifndef SA_LEN
# ifdef HAVE_SA_LEN

View file

@ -30,6 +30,8 @@ fprintf(stderr, ARG1, ARG2); fprintf(stderr, "\n"); }
static VALUE eTkCallbackBreak;
static VALUE eTkCallbackContinue;
static VALUE ip_invoke_real _((int, VALUE*, VALUE));
/* from tkAppInit.c */
/*
@ -42,55 +44,47 @@ int *tclDummyMathPtr = (int *) matherr;
/*---- module TclTkLib ----*/
/* Tk_ThreadTimer */
typedef struct {
Tcl_TimerToken token;
int flag;
} Tk_TimerData;
static VALUE main_thread;
/* timer callback */
static void
_timer_for_tcl(clientData)
ClientData clientData;
{
Tk_TimerData *timer = (Tk_TimerData*)clientData;
struct invoke_queue {
int argc;
VALUE *argv;
VALUE obj;
int done;
VALUE result;
VALUE thread;
struct invoke_queue *next;
};
timer->flag = 0;
CHECK_INTS;
if (timer->flag) {
Tk_DeleteTimerHandler(timer->token);
}
timer->token = Tk_CreateTimerHandler(200, _timer_for_tcl,
(ClientData)timer);
timer->flag = 1;
}
static struct invoke_queue *iqueue;
/* execute Tk_MainLoop */
static VALUE
lib_mainloop(self)
VALUE self;
{
Tk_TimerData *timer;
timer = (Tk_TimerData *)ALLOC(Tk_TimerData);
timer->flag = 0;
timer->token = Tk_CreateTimerHandler(200, _timer_for_tcl,
(ClientData)timer);
timer->flag = 1;
struct invoke_queue *q, *tmp;
VALUE thread;
DUMP1("start Tk_Mainloop");
while (Tk_GetNumMainWindows() > 0) {
Tcl_DoOneEvent(0);
Tcl_DoOneEvent(TCL_DONT_WAIT);
CHECK_INTS;
q = iqueue;
while (q) {
tmp = q;
q = q->next;
if (!tmp->done) {
tmp->done = 1;
tmp->result = ip_invoke_real(tmp->argc, tmp->argv, tmp->obj);
thread = tmp->thread;
tmp = tmp->next;
rb_thread_run(thread);
}
}
}
DUMP1("stop Tk_Mainloop");
if (timer->flag) {
Tk_DeleteTimerHandler(timer->token);
}
free(timer);
return Qnil;
}
@ -206,11 +200,11 @@ ip_new(self)
/* from Tcl_AppInit() */
DUMP1("Tcl_Init");
if (Tcl_Init(ptr->ip) == TCL_ERROR) {
rb_raise(rb_eRuntimeError, "Tcl_Init");
rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
}
DUMP1("Tk_Init");
if (Tk_Init(ptr->ip) == TCL_ERROR) {
rb_raise(rb_eRuntimeError, "Tk_Init");
rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
}
DUMP1("Tcl_StaticPackage(\"Tk\")");
Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init,
@ -324,14 +318,13 @@ ip_fromUTF8(self, str, encodename)
static VALUE
ip_invoke(argc, argv, obj)
ip_invoke_real(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
{
struct tcltkip *ptr; /* tcltkip data struct */
int i;
int object = 0;
Tcl_CmdInfo info;
char *cmd;
char **av = (char **)NULL;
@ -350,13 +343,10 @@ ip_invoke(argc, argv, obj)
if (!Tcl_GetCommandInfo(ptr->ip, cmd, &info)) {
rb_raise(rb_eNameError, "invalid command name `%s'", cmd);
}
#if TCL_MAJOR_VERSION >= 8
object = info.isNativeObjectProc;
#endif
/* memory allocation for arguments of this command */
if (object) {
#if TCL_MAJOR_VERSION >= 8
if (info.isNativeObjectProc) {
/* object interface */
ov = (Tcl_Obj **)ALLOCA_N(Tcl_Obj *, argc+1);
for (i = 0; i < argc; ++i) {
@ -365,8 +355,10 @@ ip_invoke(argc, argv, obj)
Tcl_IncrRefCount(ov[i]);
}
ov[argc] = (Tcl_Obj *)NULL;
}
else
#endif
} else {
{
/* string interface */
av = (char **)ALLOCA_N(char *, argc+1);
for (i = 0; i < argc; ++i) {
@ -381,8 +373,8 @@ ip_invoke(argc, argv, obj)
Tcl_ResetResult(ptr->ip);
/* Invoke the C procedure */
if (object) {
#if TCL_MAJOR_VERSION >= 8
if (info.isNativeObjectProc) {
int dummy;
ptr->return_value = (*info.objProc)(info.objClientData,
ptr->ip, argc, ov);
@ -395,9 +387,10 @@ ip_invoke(argc, argv, obj)
for (i=0; i<argc; i++) {
Tcl_DecrRefCount(ov[i]);
}
#endif
}
else {
else
#endif
{
ptr->return_value = (*info.proc)(info.clientData,
ptr->ip, argc, av);
}
@ -410,6 +403,51 @@ ip_invoke(argc, argv, obj)
return rb_str_new2(ptr->ip->result);
}
static VALUE
ip_invoke(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
{
struct invoke_queue *tmp, *p;
VALUE result = rb_thread_current();
if (result == main_thread) {
return ip_invoke_real(argc, argv, obj);
}
tmp = ALLOC(struct invoke_queue);
tmp->obj = obj;
tmp->argc = argc;
tmp->argv = ALLOC_N(VALUE, argc);
MEMCPY(tmp->argv, argv, VALUE, argc);
tmp->thread = result;
tmp->done = 0;
tmp->next = iqueue;
iqueue = tmp;
rb_thread_stop();
result = tmp->result;
if (iqueue == tmp) {
iqueue = tmp->next;
free(tmp->argv);
free(tmp);
return result;
}
p = iqueue;
while (p->next) {
if (p->next == tmp) {
p->next = tmp->next;
free(tmp->argv);
free(tmp);
break;
}
p = p->next;
}
return result;
}
/* get return code from Tcl_Eval() */
static VALUE
ip_retval(self)
@ -454,6 +492,7 @@ Init_tcltklib()
rb_define_method(ip, "_return_value", ip_retval, 0);
rb_define_method(ip, "mainloop", lib_mainloop, 0);
main_thread = rb_thread_current();
#ifdef __MACOS__
_macinit();
#endif

View file

@ -285,8 +285,8 @@ class TkText<TkTextWin
end
else
if ( key == 'font' || key == 'kanjifont' \
|| key == 'latinfont' || key == 'asciifont' )
if key == 'font' || key == 'kanjifont' ||
key == 'latinfont' || key == 'asciifont'
tagfont_configure({key=>val})
else
tk_send 'tag', 'configure', tag, "-#{key}", val
@ -320,7 +320,7 @@ class TkText<TkTextWin
end
def tag_ranges(tag)
l = tk_split_list(tk_send('tag', 'ranges', tag))
l = tk_split_simplelist(tk_send('tag', 'ranges', tag))
r = []
while key=l.shift
r.push [key, l.shift]
@ -329,11 +329,11 @@ class TkText<TkTextWin
end
def tag_nextrange(tag, first, last=None)
tk_split_list(tk_send('tag', 'nextrange', tag, first, last))
tk_split_simplelist(tk_send('tag', 'nextrange', tag, first, last))
end
def tag_prevrange(tag, first, last=None)
tk_split_list(tk_send('tag', 'prevrange', tag, first, last))
tk_split_simplelist(tk_send('tag', 'prevrange', tag, first, last))
end
def search_with_length(pat,start,stop=None)
@ -437,9 +437,19 @@ class TkTextTag<TkObject
@path = @id = $tk_text_tag
$tk_text_tag = $tk_text_tag.succ
#tk_call @t.path, "tag", "configure", @id, *hash_kv(keys)
configure(keys) if keys
if args != [] then
keys = args.pop
if keys.kind_of? Hash then
add(*args) if args != []
configure(keys)
else
args.push keys
add(*args)
end
end
@t._addtag id, self
end
def id
return @id
end
@ -470,11 +480,11 @@ class TkTextTag<TkObject
end
def nextrange(first, last=None)
tk_split_list(tk_call(@t.path, 'tag', 'nextrange', @id, first, last))
tk_split_simplelist(tk_call(@t.path, 'tag', 'nextrange', @id, first, last))
end
def prevrange(first, last=None)
tk_split_list(tk_call(@t.path, 'tag', 'prevrange', @id, first, last))
tk_split_simplelist(tk_call(@t.path, 'tag', 'prevrange', @id, first, last))
end
def [](key)
@ -631,6 +641,18 @@ class TkTextMarkCurrent<TkTextMark
end
end
class TkTextMarkAnchor<TkTextMark
def initialize(parent,index=nil)
if not parent.kind_of?(TkText)
fail format("%s need to be TkText", parent.inspect)
end
@t = parent
@path = @id = 'anchor'
tk_call @t.path, 'mark', 'set', @id, index if index
@t._addtag id, self
end
end
class TkTextWindow<TkObject
def initialize(parent, index, keys)
if not parent.kind_of?(TkText)
@ -726,6 +748,133 @@ class TkTextWindow<TkObject
}
end
end
def _dump(type, *index)
str = tk_send('dump', type, *index)
result = []
sel = nil
i = 0
while i < str.size
# retrieve key
idx = str.index(/ /, i)
result.push str[i..(idx-1)]
i = idx + 1
# retrieve value
case result[-1]
when 'text'
if str[i] == ?{
# text formed as {...}
val, i = _retrieve_braced_text(str, i)
result.push val
else
# text which may contain backslahes
val, i = _retrieve_backslashed_text(str, i)
result.push val
end
else
idx = str.index(/ /, i)
val = str[i..(idx-1)]
case result[-1]
when 'mark'
case val
when 'insert'
result.push TkTextMarkInsert.new(self)
when 'current'
result.push TkTextMarkCurrent.new(self)
when 'anchor'
result.push TkTextMarkAnchor.new(self)
else
result.push tk_tcl2rb(val)
end
when 'tagon'
if val == 'sel'
if sel
result.push sel
else
result.push TkTextTagSel.new(self)
end
else
result.push tk_tcl2rb val
end
when 'tagoff'
result.push tk_tcl2rb sel
when 'window'
result.push tk_tcl2rb val
end
i = idx + 1
end
# retrieve index
idx = str.index(/ /, i)
if idx
result.push str[i..(idx-1)]
i = idx + 1
else
result.push str[i..-1]
break
end
end
kvis = []
until result.empty?
kvis.push [result.shift, result.shift, result.shift]
end
kvis # result is [[key1, value1, index1], [key2, value2, index2], ...]
end
private :_dump
def _retrieve_braced_text(str, i)
cnt = 0
idx = i
while idx < str.size
case str[idx]
when ?{
cnt += 1
when ?}
cnt -= 1
if cnt == 0
break
end
end
idx += 1
end
return str[i+1..idx-1], idx + 2
end
private :_retrieve_braced_text
def _retrieve_backslashed_text(str, i)
j = i
idx = nil
loop {
idx = str.index(/ /, j)
if str[idx-1] == ?\\
j += 1
else
break
end
}
val = str[i..(idx-1)]
val.gsub!(/\\( |\{|\})/, '\1')
return val, idx + 1
end
private :_retrieve_backslashed_text
def dump_all(*index)
_dump('-all', *index)
end
def dump_mark(*index)
_dump('-mark', *index)
end
def dump_tag(*index)
_dump('-tag', *index)
end
def dump_text(*index)
_dump('-text', *index)
end
def dump_window(*index)
_dump('-window', *index)
end
end
class TkTextImage<TkObject

7
hash.c
View file

@ -1048,6 +1048,13 @@ ruby_setenv(name, value)
SetEnvironmentVariable(name,value);
#endif
#elif defined __CYGWIN__
#undef setenv
#undef unsetenv
if (value)
setenv(name,value,1);
else
unsetenv(name);
#else /* WIN32 */
int i=envix(name); /* where does it go? */

View file

@ -132,6 +132,9 @@ void rb_thread_fd_close _((int));
int rb_thread_alone _((void));
void rb_thread_sleep _((int));
void rb_thread_sleep_forever _((void));
VALUE rb_thread_stop _((void));
VALUE rb_thread_wakeup _((VALUE));
VALUE rb_thread_run _((VALUE));
VALUE rb_thread_create _((VALUE (*)(), void*));
int rb_thread_scope_shared_p _((void));
void rb_thread_interrupt _((void));

21
io.c
View file

@ -306,10 +306,6 @@ rb_io_eof(io)
rb_io_check_readable(fptr);
if (READ_DATA_PENDING(fptr->f)) return Qfalse;
#if 0
if (feof(fptr->f)) return Qtrue;
return Qfalse;
#else
READ_CHECK(fptr->f);
TRAP_BEG;
ch = getc(fptr->f);
@ -320,7 +316,6 @@ rb_io_eof(io)
return Qfalse;
}
return Qtrue;
#endif
}
static VALUE
@ -811,6 +806,22 @@ rb_io_getc(io)
return INT2FIX(c & 0xff);
}
int
rb_getc(f)
FILE *f;
{
int c;
if (!READ_DATA_PENDING(f)) {
rb_thread_wait_fd(fileno(f));
}
TRAP_BEG;
c = getc(f);
TRAP_END;
return c;
}
static VALUE
rb_io_readchar(io)
VALUE io;

View file

@ -1,21 +1,23 @@
=begin
$Date: 1999/06/04 06:24:58 $
= simple telnet cliant library
== SIMPLE TELNET CLIANT LIBRARY
telnet.rb
Version 0.20
telnet.rb ver0.17 1999/04/30
Wakou Aoyama <wakou@fsinet.or.jp>
= methods
== new (make new Telnet object)
=== MAKE NEW TELNET OBJECT
host = Telnet.new({"Binmode" => FALSE, # default: FALSE
"Host" => "localhost", # default: "localhost"
"Output_log" => "output_log", # default: not output
"Dump_log" => "dump_log", # default: not output
"Port" => 23, # default: 23
"Prompt" => /[$%#>] \Z/, # default: /[$%#>] \Z/
"Prompt" => /[$%#>] \z/n, # default: /[$%#>] \z/n
"Telnetmode" => TRUE, # default: TRUE
"Timeout" => 10, # default: 10
"Waittime" => 0, # default: 0
@ -29,7 +31,7 @@ if set "Telnetmode" option FALSE. not TELNET command interpretation.
the same character as "Prompt" is included in the data, and, when
the network or the host is very heavy, the value is enlarged.
=== status output
=== STATUS OUTPUT
host = Telnet.new({"Hosh" => "localhost"){|c| print c }
@ -37,11 +39,11 @@ connection status output.
example
Trying localhost...
Connected to localhost.
Trying localhost...
Connected to localhost.
== waitfor (wait for match)
=== WAIT FOR MATCH
line = host.waitfor(/match/)
line = host.waitfor({"Match" => /match/,
@ -51,7 +53,7 @@ Connected to localhost.
if set "String" option. Match = Regexp.new(quote(string))
=== realtime output
==== REALTIME OUTPUT
host.waitfor(/match/){|c| print c }
host.waitfor({"Match" => /match/,
@ -61,138 +63,157 @@ if set "String" option. Match = Regexp.new(quote(string))
of cource, set sync=TRUE or flush is necessary.
== cmd (send string and wait prompt)
=== SEND STRING AND WAIT PROMPT
line = host.cmd("string")
line = host.cmd({"String" => "string",
"Prompt" => /[$%#>] \Z/,
"Prompt" => /[$%#>] \z/n,
"Timeout" => 10})
=== realtime output
==== REALTIME OUTPUT
host.cmd("string"){|c| print c }
host.cmd({"String" => "string",
"Prompt" => /[$%#>] \Z/,
"Prompt" => /[$%#>] \z/n,
"Timeout" => 10}){|c| print c }
of cource, set sync=TRUE or flush is necessary.
== print (send string)
=== SEND STRING
host.print("string")
== telnetmode (turn telnet command interpretation)
=== TURN TELNET COMMAND INTERPRETATION
host.telnetmode # turn on/off
host.telnetmode(TRUE) # on
host.telnetmode(FALSE) # off
== binmode (toggle newline translation)
=== TOGGLE NEWLINE TRANSLATION
host.binmode # turn TRUE/FALSE
host.binmode(TRUE) # no translate newline
host.binmode(FALSE) # translate newline
== login
=== LOGIN
host.login("username", "password")
host.login({"Name" => "username",
"Password" => "password",
"Prompt" => /[$%#>] \Z/,
"Prompt" => /[$%#>] \z/n,
"Timeout" => 10})
=== realtime output
==== REALTIME OUTPUT
host.login("username", "password"){|c| print c }
host.login({"Name" => "username",
"Password" => "password",
"Prompt" => /[$%#>] \Z/,
"Prompt" => /[$%#>] \z/n,
"Timeout" => 10}){|c| print c }
of cource, set sync=TRUE or flush is necessary.
= sample
== EXAMPLE
== login and send command
=== LOGIN AND SEND COMMAND
localhost = Telnet.new({"Host" => "localhost",
"Timeout" => 10,
"Prompt" => /[$%#>] \Z/})
"Prompt" => /[$%#>] \z/n})
localhost.login("username", "password"){|c| print c }
localhost.cmd("command"){|c| print c }
localhost.close
== checks a POP server to see if you have mail
=== CHECKS A POP SERVER TO SEE IF YOU HAVE MAIL
pop = Telnet.new({"Host" => "your_destination_host_here",
"Port" => 110,
"Telnetmode" => FALSE,
"Prompt" => /^\+OK/})
"Prompt" => /^\+OK/n})
pop.cmd("user " + "your_username_here"){|c| print c}
pop.cmd("pass " + "your_password_here"){|c| print c}
pop.cmd("list"){|c| print c}
= history
== HISTORY
ver0.17 1999/04/30
bug fix
$! + "\n" --> $!.to_s + "\n"
=== Version 0.20
waitfor: support for divided telnet command
ver0.163 1999/04/11
=== Version 0.181 1999/05/22
bug fix: print method
=== Version 0.18 1999/05/14
respond to "IAC WON'T SGA" with "IAC DON'T SGA"
DON'T SGA : end of line --> CR + LF
bug fix: preprocess method
=== Version 0.17 1999/04/30
bug fix: $! + "\n" --> $!.to_s + "\n"
=== Version 0.163 1999/04/11
STDOUT.write(message) --> yield(message) if iterator?
ver0.162 1999/03/17
=== Version 0.162 1999/03/17
add "Proxy" option
required timeout.rb
ver0.161 1999/02/03
=== Version 0.161 1999/02/03
select --> IO::select
ver0.16 1998/10/09
=== Version 0.16 1998/10/09
preprocess method change for the better
add binmode method.
change default Binmode
change default Binmode
TRUE --> FALSE
ver0.15 1998/10/04
=== Version 0.15 1998/10/04
add telnetmode method.
ver0.141 1998/09/22
=== Version 0.141 1998/09/22
change default prompt
/[$%#>] $/ --> /[$%#>] \Z/
/[$%#>] $/ --> /[$%#>] \Z/
ver0.14 1998/09/01
=== Version 0.14 1998/09/01
IAC WILL SGA send EOL --> CR+NULL
IAC WILL SGA IAC DO BIN send EOL --> CR
NONE send EOL --> LF
add Dump_log option.
ver0.13 1998/08/25
=== Version 0.13 1998/08/25
add print method.
ver0.122 1998/08/05
=== Version 0.122 1998/08/05
support for HP-UX 10.20 thanks to WATANABE Tetsuya <tetsu@jpn.hp.com>
socket.<< --> socket.write
ver0.121 1998/07/15
=== Version 0.121 1998/07/15
string.+= --> string.concat
ver0.12 1998/06/01
=== Version 0.12 1998/06/01
add timeout, waittime.
ver0.11 1998/04/21
=== Version 0.11 1998/04/21
add realtime output.
ver0.10 1998/04/13
=== Version 0.10 1998/04/13
first release.
=end
@ -205,84 +226,89 @@ TimeOut = TimeoutError
class Telnet < SimpleDelegator
IAC = 255.chr # interpret as command:
DONT = 254.chr # you are not to use option
DO = 253.chr # please, you use option
WONT = 252.chr # I won't use option
WILL = 251.chr # I will use option
SB = 250.chr # interpret as subnegotiation
GA = 249.chr # you may reverse the line
EL = 248.chr # erase the current line
EC = 247.chr # erase the current character
AYT = 246.chr # are you there
AO = 245.chr # abort output--but let prog finish
IP = 244.chr # interrupt process--permanently
BREAK = 243.chr # break
DM = 242.chr # data mark--for connect. cleaning
NOP = 241.chr # nop
SE = 240.chr # end sub negotiation
EOR = 239.chr # end of record (transparent mode)
ABORT = 238.chr # Abort process
SUSP = 237.chr # Suspend process
EOF = 236.chr # End of file
SYNCH = 242.chr # for telfunc calls
IAC = 255.chr # "\377" # interpret as command:
DONT = 254.chr # "\376" # you are not to use option
DO = 253.chr # "\375" # please, you use option
WONT = 252.chr # "\374" # I won't use option
WILL = 251.chr # "\373" # I will use option
SB = 250.chr # "\372" # interpret as subnegotiation
GA = 249.chr # "\371" # you may reverse the line
EL = 248.chr # "\370" # erase the current line
EC = 247.chr # "\367" # erase the current character
AYT = 246.chr # "\366" # are you there
AO = 245.chr # "\365" # abort output--but let prog finish
IP = 244.chr # "\364" # interrupt process--permanently
BREAK = 243.chr # "\363" # break
DM = 242.chr # "\362" # data mark--for connect. cleaning
NOP = 241.chr # "\361" # nop
SE = 240.chr # "\360" # end sub negotiation
EOR = 239.chr # "\357" # end of record (transparent mode)
ABORT = 238.chr # "\356" # Abort process
SUSP = 237.chr # "\355" # Suspend process
EOF = 236.chr # "\354" # End of file
SYNCH = 242.chr # "\362" # for telfunc calls
OPT_BINARY = 0.chr # Binary Transmission
OPT_ECHO = 1.chr # Echo
OPT_RCP = 2.chr # Reconnection
OPT_SGA = 3.chr # Suppress Go Ahead
OPT_NAMS = 4.chr # Approx Message Size Negotiation
OPT_STATUS = 5.chr # Status
OPT_TM = 6.chr # Timing Mark
OPT_RCTE = 7.chr # Remote Controlled Trans and Echo
OPT_NAOL = 8.chr # Output Line Width
OPT_NAOP = 9.chr # Output Page Size
OPT_NAOCRD = 10.chr # Output Carriage-Return Disposition
OPT_NAOHTS = 11.chr # Output Horizontal Tab Stops
OPT_NAOHTD = 12.chr # Output Horizontal Tab Disposition
OPT_NAOFFD = 13.chr # Output Formfeed Disposition
OPT_NAOVTS = 14.chr # Output Vertical Tabstops
OPT_NAOVTD = 15.chr # Output Vertical Tab Disposition
OPT_NAOLFD = 16.chr # Output Linefeed Disposition
OPT_XASCII = 17.chr # Extended ASCII
OPT_LOGOUT = 18.chr # Logout
OPT_BM = 19.chr # Byte Macro
OPT_DET = 20.chr # Data Entry Terminal
OPT_SUPDUP = 21.chr # SUPDUP
OPT_SUPDUPOUTPUT = 22.chr # SUPDUP Output
OPT_SNDLOC = 23.chr # Send Location
OPT_TTYPE = 24.chr # Terminal Type
OPT_EOR = 25.chr # End of Record
OPT_TUID = 26.chr # TACACS User Identification
OPT_OUTMRK = 27.chr # Output Marking
OPT_TTYLOC = 28.chr # Terminal Location Number
OPT_3270REGIME = 29.chr # Telnet 3270 Regime
OPT_X3PAD = 30.chr # X.3 PAD
OPT_NAWS = 31.chr # Negotiate About Window Size
OPT_TSPEED = 32.chr # Terminal Speed
OPT_LFLOW = 33.chr # Remote Flow Control
OPT_LINEMODE = 34.chr # Linemode
OPT_XDISPLOC = 35.chr # X Display Location
OPT_OLD_ENVIRON = 36.chr # Environment Option
OPT_AUTHENTICATION = 37.chr # Authentication Option
OPT_ENCRYPT = 38.chr # Encryption Option
OPT_NEW_ENVIRON = 39.chr # New Environment Option
OPT_EXOPL = 255.chr # Extended-Options-List
OPT_BINARY = 0.chr # "\000" # Binary Transmission
OPT_ECHO = 1.chr # "\001" # Echo
OPT_RCP = 2.chr # "\002" # Reconnection
OPT_SGA = 3.chr # "\003" # Suppress Go Ahead
OPT_NAMS = 4.chr # "\004" # Approx Message Size Negotiation
OPT_STATUS = 5.chr # "\005" # Status
OPT_TM = 6.chr # "\006" # Timing Mark
OPT_RCTE = 7.chr # "\a" # Remote Controlled Trans and Echo
OPT_NAOL = 8.chr # "\010" # Output Line Width
OPT_NAOP = 9.chr # "\t" # Output Page Size
OPT_NAOCRD = 10.chr # "\n" # Output Carriage-Return Disposition
OPT_NAOHTS = 11.chr # "\v" # Output Horizontal Tab Stops
OPT_NAOHTD = 12.chr # "\f" # Output Horizontal Tab Disposition
OPT_NAOFFD = 13.chr # "\r" # Output Formfeed Disposition
OPT_NAOVTS = 14.chr # "\016" # Output Vertical Tabstops
OPT_NAOVTD = 15.chr # "\017" # Output Vertical Tab Disposition
OPT_NAOLFD = 16.chr # "\020" # Output Linefeed Disposition
OPT_XASCII = 17.chr # "\021" # Extended ASCII
OPT_LOGOUT = 18.chr # "\022" # Logout
OPT_BM = 19.chr # "\023" # Byte Macro
OPT_DET = 20.chr # "\024" # Data Entry Terminal
OPT_SUPDUP = 21.chr # "\025" # SUPDUP
OPT_SUPDUPOUTPUT = 22.chr # "\026" # SUPDUP Output
OPT_SNDLOC = 23.chr # "\027" # Send Location
OPT_TTYPE = 24.chr # "\030" # Terminal Type
OPT_EOR = 25.chr # "\031" # End of Record
OPT_TUID = 26.chr # "\032" # TACACS User Identification
OPT_OUTMRK = 27.chr # "\e" # Output Marking
OPT_TTYLOC = 28.chr # "\034" # Terminal Location Number
OPT_3270REGIME = 29.chr # "\035" # Telnet 3270 Regime
OPT_X3PAD = 30.chr # "\036" # X.3 PAD
OPT_NAWS = 31.chr # "\037" # Negotiate About Window Size
OPT_TSPEED = 32.chr # " " # Terminal Speed
OPT_LFLOW = 33.chr # "!" # Remote Flow Control
OPT_LINEMODE = 34.chr # "\"" # Linemode
OPT_XDISPLOC = 35.chr # "#" # X Display Location
OPT_OLD_ENVIRON = 36.chr # "$" # Environment Option
OPT_AUTHENTICATION = 37.chr # "%" # Authentication Option
OPT_ENCRYPT = 38.chr # "&" # Encryption Option
OPT_NEW_ENVIRON = 39.chr # "'" # New Environment Option
OPT_EXOPL = 255.chr # "\377" # Extended-Options-List
NULL = "\000"
CR = "\015"
LF = "\012"
EOL = CR + LF
v = $-v
$-v = false
VERSION = "0.20"
RELEASE_DATE = "$Date: 1999/06/04 06:24:58 $"
$-v = v
def initialize(options)
@options = options
@options["Binmode"] = FALSE if not @options.include?("Binmode")
@options["Host"] = "localhost" if not @options.include?("Host")
@options["Port"] = 23 if not @options.include?("Port")
@options["Prompt"] = /[$%#>] \Z/ if not @options.include?("Prompt")
@options["Telnetmode"] = TRUE if not @options.include?("Telnetmode")
@options["Timeout"] = 10 if not @options.include?("Timeout")
@options["Waittime"] = 0 if not @options.include?("Waittime")
@options["Binmode"] = FALSE if not @options.include?("Binmode")
@options["Host"] = "localhost" if not @options.include?("Host")
@options["Port"] = 23 if not @options.include?("Port")
@options["Prompt"] = /[$%#>] \z/n if not @options.include?("Prompt")
@options["Telnetmode"] = TRUE if not @options.include?("Telnetmode")
@options["Timeout"] = 10 if not @options.include?("Timeout")
@options["Waittime"] = 0 if not @options.include?("Waittime")
@telnet_option = { "SGA" => FALSE, "BINARY" => FALSE }
@ -333,7 +359,7 @@ class Telnet < SimpleDelegator
end
super(@sock)
end
end # initialize
attr :sock
@ -353,50 +379,64 @@ class Telnet < SimpleDelegator
end
end
def preprocess(str)
def preprocess(string)
str = string.dup
if not @options["Binmode"]
str.gsub!(/#{CR}#{NULL}/no, CR) # combine CR+NULL into CR
str.gsub!(/#{EOL}/no, "\n") # combine EOL into "\n"
end
# combine CR+NULL into CR
str.gsub!(/#{CR}#{NULL}/no, CR) if @options["Telnetmode"]
# combine EOL into "\n"
str.gsub!(/#{EOL}/no, "\n") if not @options["Binmode"]
# respond to "IAC DO x"
str.gsub!(/(?:(?!#{IAC}))?#{IAC}#{DO}([#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}])/no){
if OPT_BINARY == $1
str.gsub!(/([^#{IAC}]?)#{IAC}#{DO}([#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}])/no){
if OPT_BINARY == $2
@telnet_option["BINARY"] = TRUE
@sock.write(IAC + WILL + OPT_BINARY)
else
@sock.write(IAC + WONT + $1)
@sock.write(IAC + WONT + $2)
end
''
$1
}
# respond to "IAC DON'T x" with "IAC WON'T x"
str.gsub!(/(?:(?!#{IAC}))?#{IAC}#{DONT}([#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}])/no){
@sock.write(IAC + WONT + $1)
''
str.gsub!(/([^#{IAC}]?)#{IAC}#{DONT}([#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}])/no){
@sock.write(IAC + WONT + $2)
$1
}
# respond to "IAC WILL x"
str.gsub!(/(?:(?!#{IAC}))?#{IAC}#{WILL}([#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}])/no){
if OPT_SGA == $1
str.gsub!(/([^#{IAC}]?)#{IAC}#{WILL}([#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}])/no){
if OPT_ECHO == $2
@sock.write(IAC + DO + OPT_ECHO)
elsif OPT_SGA == $2
@telnet_option["SGA"] = TRUE
@sock.write(IAC + DO + OPT_SGA)
end
''
$1
}
# ignore "IAC WON'T x"
str.gsub!(/(?:(?!#{IAC}))?#{IAC}#{WONT}[#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}]/no, '')
# respond to "IAC WON'T x"
str.gsub!(/([^#{IAC}]?)#{IAC}#{WONT}([#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}])/no){
if OPT_ECHO == $2
@sock.write(IAC + DONT + OPT_ECHO)
elsif OPT_SGA == $2
@telnet_option["SGA"] = FALSE
@sock.write(IAC + DONT + OPT_SGA)
end
$1
}
# respond to "IAC AYT" (are you there)
str.gsub!(/(?:(?!#{IAC}))?#{IAC}#{AYT}/no){
str.gsub!(/([^#{IAC}]?)#{IAC}#{AYT}/no){
@sock.write("nobody here but us pigeons" + EOL)
''
$1
}
str.gsub(/#{IAC}#{IAC}/no, IAC) # handle escaped IAC characters
end
str.gsub!(/#{IAC}#{IAC}/no, IAC) # handle escaped IAC characters
str
end # preprocess
def waitfor(options)
time_out = @options["Timeout"]
@ -417,41 +457,50 @@ class Telnet < SimpleDelegator
end
line = ''
buf = ''
until(not IO::select([@sock], nil, nil, waittime) and prompt === line)
raise TimeOut, "timed-out; wait for the next data" if
not IO::select([@sock], nil, nil, time_out)
buf = ''
begin
buf = @sock.sysread(1024 * 1024)
@dumplog.print(buf) if @options.include?("Dump_log")
buf = preprocess(buf) if @options["Telnetmode"]
rescue EOFError # End of file reached
break
ensure
c = @sock.sysread(1024 * 1024)
@dumplog.print(c) if @options.include?("Dump_log")
buf.concat c
if @options["Telnetmode"]
buf = preprocess(buf)
if /#{IAC}.?\z/no === buf
next
end
end
@log.print(buf) if @options.include?("Output_log")
yield buf if iterator?
line.concat(buf)
buf = ''
rescue EOFError # End of file reached
break
end
end
line
end
def print(string)
string.gsub!(/#{IAC}/no, IAC + IAC) if @options["Telnetmode"]
if @options["Binmode"]
@sock.write(string)
else
str = string.dup + "\n"
str.gsub!(/#{IAC}/no, IAC + IAC) if @options["Telnetmode"]
if not @options["Binmode"]
if @telnet_option["BINARY"] and @telnet_option["SGA"]
# IAC WILL SGA IAC DO BIN send EOL --> CR
@sock.write(string.gsub(/\n/, CR) + CR)
str.gsub!(/\n/n, CR)
elsif @telnet_option["SGA"]
# IAC WILL SGA send EOL --> CR+NULL
@sock.write(string.gsub(/\n/, CR + NULL) + CR + NULL)
str.gsub!(/\n/n, CR + NULL)
else
# NONE send EOL --> LF
@sock.write(string.gsub(/\n/, LF) + LF)
# NONE send EOL --> CR+LF
str.gsub!(/\n/n, EOL)
end
end
@sock.write(str)
end
def cmd(options)
@ -484,14 +533,14 @@ class Telnet < SimpleDelegator
end
if iterator?
line = waitfor(/login[: ]*\Z/){|c| yield c }
line = waitfor(/login[: ]*\z/n){|c| yield c }
line.concat( cmd({"String" => username,
"Match" => /Password[: ]*\Z/}){|c| yield c } )
"Match" => /Password[: ]*\z/n}){|c| yield c } )
line.concat( cmd(password){|c| yield c } )
else
line = waitfor(/login[: ]*\Z/)
line = waitfor(/login[: ]*\z/n)
line.concat( cmd({"String" => username,
"Match" => /Password[: ]*\Z/}) )
"Match" => /Password[: ]*\z/n}) )
line.concat( cmd(password) )
end
line

View file

@ -28,15 +28,13 @@ class Tempfile < SimpleDelegator
}
end
def initialize(basename, tmpdir = nil)
def initialize(basename, tmpdir=ENV['TMPDIR']||ENV['TMP']||ENV['TEMP']||'/tmp')
umask = File.umask(0177)
tmpname = lock = nil
begin
n = 0
while true
begin
tmpdir ||= ENV['TMPDIR'] || ENV['TMP'] || ENV['TEMP'] || '/tmp'
tmpname = sprintf('%s/%s.%d.%d', tmpdir, basename, $$, n)
tmpname = sprintf('%s/%s%d.%d', tmpdir, basename, $$, n)
lock = tmpname + '.lock'
unless File.exist?(tmpname) or File.exist?(lock)
Dir.mkdir(lock)

View file

@ -457,7 +457,7 @@ static int
r_byte(arg)
struct load_arg *arg;
{
if (arg->fp) return getc(arg->fp);
if (arg->fp) return rb_getc(arg->fp);
if (arg->ptr < arg->end) return *(unsigned char*)arg->ptr++;
return EOF;
}

View file

@ -152,6 +152,15 @@ The variable ruby-indent-level controls the amount of indentation.
(setq mode-name "Ruby")
(setq major-mode 'ruby-mode)
(ruby-mode-variables)
;; for font-lock
(make-local-variable 'font-lock-syntactic-keywords)
(setq font-lock-syntactic-keywords
'(("\\$\\([#\"'`$\\]\\)" 1 (1 . nil))
("\\(#\\)[{$@]" 1 (1 . nil))))
(make-local-variable 'font-lock-defaults)
(setq font-lock-defaults '((ruby-font-lock-keywords) nil nil))
(setq font-lock-keywords ruby-font-lock-keywords)
(run-hooks 'ruby-mode-hook))
(defun ruby-current-indentation ()
@ -627,8 +636,7 @@ An end of a defun is found by moving forward from the beginning of one."
("\\$\\(.\\|\\sw+\\)" nil type)
("[$@].[a-zA-Z_0-9]*" nil struct)
("^__END__" nil label))))
((featurep 'font-lock)
)
(or (boundp 'font-lock-variable-name-face)
(setq font-lock-variable-name-face font-lock-type-face))
(defvar ruby-font-lock-keywords
@ -687,15 +695,5 @@ An end of a defun is found by moving forward from the beginning of one."
'("^\\s *def\\s *\\<\\(\\(\\w\\|\\s_\\)+\\.\\)?\\(\\(\\w\\|\\s_\\)+\\)\\>"
3 font-lock-function-name-face t))
"*Additional expressions to highlight in ruby mode.")
(add-hook
'ruby-mode-hook
(lambda ()
(make-local-variable 'font-lock-syntactic-keywords)
(setq font-lock-syntactic-keywords
'(("\\$\\([#\"'`$\\]\\)" 1 (1 . nil))
("\\(#\\)[{$@]" 1 (1 . nil))))
(make-local-variable 'font-lock-defaults)
(setq font-lock-defaults '((ruby-font-lock-keywords) nil nil))
(setq font-lock-keywords ruby-font-lock-keywords)))))
(provide 'ruby-mode)

View file

@ -64,7 +64,7 @@ end
print v_fast, v_others
print <<EOS
CONFIG["compile_dir"] = "#{File.expand_path(File.dirname($0))}"
CONFIG["compile_dir"] = "#{Dir.pwd}"
CONFIG.each_value do |val|
val.gsub!(/\\$\\(([^()]+)\\)/) do |var|
key = $1

View file

@ -460,7 +460,7 @@ rb_mod_clone(module)
VALUE module;
{
NEWOBJ(clone, struct RClass);
OBJSETUP(clone, CLASS_OF(module), TYPE(module));
CLONESETUP(clone, module);
clone->super = RCLASS(module)->super;
clone->iv_tbl = 0;

377
pack.c
View file

@ -14,8 +14,17 @@
#include <sys/types.h>
#include <ctype.h>
#ifndef atof
double strtod();
#define SIZE16 2
#define SIZE32 4
#if SIZEOF_SHORT != 2 || SIZEOF_LONG != 4
# define NATINT_PACK
#endif
#ifdef NATINT_PACK
# define NATINT_LEN(type,len) (natint?sizeof(type):(len))
#else
# define NATINT_LEN(type,len) sizeof(type)
#endif
#define define_swapx(x, xtype) \
@ -280,6 +289,9 @@ static char *toofew = "too few arguments";
static void encodes _((VALUE,char*,int,int));
static void qpencode _((VALUE,VALUE,int));
static long uv_to_utf8 _((char*,long));
static long utf8_to_uv _((char*,int*));
static void
pack_add_ptr(str, add)
VALUE str, add;
@ -304,9 +316,11 @@ pack_pack(ary, fmt)
int items, len, idx;
char *ptr;
int plen;
#ifdef NATINT_PACK
int natint; /* native integer */
#endif
p = rb_str2cstr(fmt, &plen);
p = str2cstr(fmt, &plen);
pend = p + plen;
res = rb_str_new(0, 0);
@ -317,7 +331,24 @@ pack_pack(ary, fmt)
while (p < pend) {
type = *p++; /* get data type */
#ifdef NATINT_PACK
natint = 0;
#endif
if (ISSPACE(type)) continue;
if (*p == '_') {
char *natstr = "sSiIlL";
if (strchr(natstr, type)) {
#ifdef NATINT_PACK
natint = 1;
#endif
p++;
}
else {
rb_raise(rb_eArgError, "'_' allowed only after types %s", natstr);
}
}
if (*p == '*') { /* set data length */
len = strchr("@Xxu", type) ? 0 : items;
p++;
@ -339,9 +370,7 @@ pack_pack(ary, fmt)
plen = 0;
}
else {
from = rb_obj_as_string(from);
ptr = RSTRING(from)->ptr;
plen = RSTRING(from)->len;
ptr = str2cstr(from, &plen);
}
if (p[-1] == '*')
@ -350,6 +379,7 @@ pack_pack(ary, fmt)
switch (type) {
case 'a':
case 'A':
case 'Z':
if (plen >= len)
rb_str_cat(res, ptr, len);
else {
@ -366,8 +396,12 @@ pack_pack(ary, fmt)
case 'b':
{
int byte = 0;
int i;
int i, j;
if (len > plen) {
j = (len - plen + 1)/2;
len = plen;
}
for (i=0; i++ < len; ptr++) {
if (*ptr & 1)
byte |= 128;
@ -385,14 +419,21 @@ pack_pack(ary, fmt)
c = byte & 0xff;
rb_str_cat(res, &c, 1);
}
len = RSTRING(res)->len;
rb_str_resize(res, len+j);
MEMZERO(RSTRING(res)->ptr+len, char, j);
}
break;
case 'B':
{
int byte = 0;
int i;
int i, j;
if (len > plen) {
j = (len - plen + 1)/2;
len = plen;
}
for (i=0; i++ < len; ptr++) {
byte |= *ptr & 1;
if (i & 7)
@ -409,60 +450,73 @@ pack_pack(ary, fmt)
c = byte & 0xff;
rb_str_cat(res, &c, 1);
}
len = RSTRING(res)->len;
rb_str_resize(res, len+j);
MEMZERO(RSTRING(res)->ptr+len, char, j);
}
break;
case 'h':
{
int byte = 0;
int i;
int i, j;
if (len > plen) {
j = (len - plen + 1)/2;
len = plen;
}
for (i=0; i++ < len; ptr++) {
if (ISXDIGIT(*ptr)) {
if (ISALPHA(*ptr))
byte |= (((*ptr & 15) + 9) & 15) << 4;
else
byte |= (*ptr & 15) << 4;
if (i & 1)
byte >>= 4;
else {
char c = byte & 0xff;
rb_str_cat(res, &c, 1);
byte = 0;
}
if (ISALPHA(*ptr))
byte |= (((*ptr & 15) + 9) & 15) << 4;
else
byte |= (*ptr & 15) << 4;
if (i & 1)
byte >>= 4;
else {
char c = byte & 0xff;
rb_str_cat(res, &c, 1);
byte = 0;
}
}
if (len & 1) {
char c = byte & 0xff;
rb_str_cat(res, &c, 1);
}
len = RSTRING(res)->len;
rb_str_resize(res, len+j);
MEMZERO(RSTRING(res)->ptr+len, char, j);
}
break;
case 'H':
{
int byte = 0;
int i;
int i, j;
if (len > plen) {
j = (len - plen + 1)/2;
len = plen;
}
for (i=0; i++ < len; ptr++) {
if (ISXDIGIT(*ptr)) {
if (ISALPHA(*ptr))
byte |= ((*ptr & 15) + 9) & 15;
else
byte |= *ptr & 15;
if (i & 1)
byte <<= 4;
else {
char c = byte & 0xff;
rb_str_cat(res, &c, 1);
byte = 0;
}
if (ISALPHA(*ptr))
byte |= ((*ptr & 15) + 9) & 15;
else
byte |= *ptr & 15;
if (i & 1)
byte <<= 4;
else {
char c = byte & 0xff;
rb_str_cat(res, &c, 1);
byte = 0;
}
}
if (len & 1) {
char c = byte & 0xff;
rb_str_cat(res, &c, 1);
}
len = RSTRING(res)->len;
rb_str_resize(res, len+j);
MEMZERO(RSTRING(res)->ptr+len, char, j);
}
break;
}
@ -492,7 +546,7 @@ pack_pack(ary, fmt)
else {
s = NUM2INT(from);
}
rb_str_cat(res, (char*)&s, sizeof(short));
rb_str_cat(res, (char*)&s, NATINT_LEN(short,2));
}
break;
@ -520,7 +574,7 @@ pack_pack(ary, fmt)
else {
l = NUM2ULONG(from);
}
rb_str_cat(res, (char*)&l, sizeof(long));
rb_str_cat(res, (char*)&l, NATINT_LEN(long,4));
}
break;
@ -534,7 +588,7 @@ pack_pack(ary, fmt)
s = NUM2INT(from);
}
s = htons(s);
rb_str_cat(res, (char*)&s, sizeof(short));
rb_str_cat(res, (char*)&s, NATINT_LEN(short,2));
}
break;
@ -548,7 +602,7 @@ pack_pack(ary, fmt)
l = NUM2ULONG(from);
}
l = htonl(l);
rb_str_cat(res, (char*)&l, sizeof(long));
rb_str_cat(res, (char*)&l, NATINT_LEN(long,4));
}
break;
@ -562,7 +616,7 @@ pack_pack(ary, fmt)
s = NUM2INT(from);
}
s = htovs(s);
rb_str_cat(res, (char*)&s, sizeof(short));
rb_str_cat(res, (char*)&s, NATINT_LEN(short,2));
}
break;
@ -576,7 +630,7 @@ pack_pack(ary, fmt)
l = NUM2ULONG(from);
}
l = htovl(l);
rb_str_cat(res, (char*)&l, sizeof(long));
rb_str_cat(res, (char*)&l, NATINT_LEN(long,4));
}
break;
@ -732,11 +786,24 @@ pack_pack(ary, fmt)
rb_raise(rb_eArgError, "% may only be used in unpack");
break;
case 'U':
while (len-- > 0) {
unsigned long l;
char buf[8];
from = NEXTFROM;
if (NIL_P(from)) l = 0;
else {
l = NUM2ULONG(from);
}
l = uv_to_utf8(buf, l);
rb_str_cat(res, (char*)&buf, l);
}
break;
case 'u':
case 'm':
from = rb_obj_as_string(NEXTFROM);
ptr = RSTRING(from)->ptr;
plen = RSTRING(from)->len;
ptr = str2cstr(NEXTFROM, &plen);
if (len <= 1)
len = 45;
@ -914,7 +981,19 @@ hex2num(c)
}
}
#define PACK_LENGTH_ADJUST(type) do { \
#ifdef NATINT_PACK
#define PACK_LENGTH_ADJUST(type,sz) do { \
int t__len = NATINT_LEN((type),(sz)); \
tmp = 0; \
if (len > (send-s)/t__len) { \
if (!star) { \
tmp = len-(send-s)/t__len; \
} \
len = (send-s)/t__len; \
} \
} while (0)
#else
#define PACK_LENGTH_ADJUST(type,sz) do { \
tmp = 0; \
if (len > (send-s)/sizeof(type)) { \
if (!star) { \
@ -923,6 +1002,7 @@ hex2num(c)
len = (send-s)/sizeof(type); \
} \
} while (0)
#endif
#define PACK_ITEM_ADJUST() while (tmp--) rb_ary_push(ary, Qnil);
@ -936,17 +1016,35 @@ pack_unpack(str, fmt)
VALUE ary;
char type;
int len, tmp, star;
#ifdef NATINT_PACK
int natint; /* native integer */
#endif
s = rb_str2cstr(str, &len);
s = str2cstr(str, &len);
send = s + len;
p = rb_str2cstr(fmt, &len);
p = str2cstr(fmt, &len);
pend = p + len;
ary = rb_ary_new();
while (p < pend) {
star = 0;
type = *p++;
if (*p == '*') {
if (*p == '_') {
char *natstr = "sSiIlL";
if (strchr(natstr, type)) {
#ifdef NATINT_PACK
natint = 1;
#endif
p++;
}
else {
rb_raise(rb_eArgError, "'_' allowed only after types %s", natstr);
}
}
if (p >= pend)
len = 1;
else if (*p == '*') {
star = 1;
len = send - s;
p++;
@ -971,8 +1069,22 @@ pack_unpack(str, fmt)
while (t >= s) {
if (*t != ' ' && *t != '\0') break;
t--;
len--;
t--; len--;
}
rb_ary_push(ary, rb_str_new(s, len));
s += end;
}
break;
case 'Z':
if (len > send - s) len = send - s;
{
int end = len;
char *t = s + len - 1;
while (t >= s) {
if (*t) break;
t--; len--;
}
rb_ary_push(ary, rb_str_new(s, len));
s += end;
@ -985,6 +1097,7 @@ pack_unpack(str, fmt)
s += len;
break;
case 'b':
{
VALUE bitstr;
@ -1066,7 +1179,7 @@ pack_unpack(str, fmt)
break;
case 'c':
PACK_LENGTH_ADJUST(char);
PACK_LENGTH_ADJUST(char,sizeof(char));
while (len-- > 0) {
int c = *s++;
if (c > (char)127) c-=256;
@ -1076,7 +1189,7 @@ pack_unpack(str, fmt)
break;
case 'C':
PACK_LENGTH_ADJUST(char);
PACK_LENGTH_ADJUST(unsigned char,sizeof(unsigned char));
while (len-- > 0) {
unsigned char c = *s++;
rb_ary_push(ary, INT2FIX(c));
@ -1085,29 +1198,29 @@ pack_unpack(str, fmt)
break;
case 's':
PACK_LENGTH_ADJUST(short);
PACK_LENGTH_ADJUST(short,2);
while (len-- > 0) {
short tmp;
memcpy(&tmp, s, sizeof(short));
s += sizeof(short);
memcpy(&tmp, s, NATINT_LEN(short,2));
s += NATINT_LEN(short,2);
rb_ary_push(ary, INT2FIX(tmp));
}
PACK_ITEM_ADJUST();
break;
case 'S':
PACK_LENGTH_ADJUST(short);
PACK_LENGTH_ADJUST(unsigned short,2);
while (len-- > 0) {
unsigned short tmp;
memcpy(&tmp, s, sizeof(short));
s += sizeof(short);
memcpy(&tmp, s, NATINT_LEN(unsigned short,2));
s += NATINT_LEN(unsigned short,2);
rb_ary_push(ary, INT2FIX(tmp));
}
PACK_ITEM_ADJUST();
break;
case 'i':
PACK_LENGTH_ADJUST(int);
PACK_LENGTH_ADJUST(int,sizeof(int));
while (len-- > 0) {
int tmp;
memcpy(&tmp, s, sizeof(int));
@ -1118,44 +1231,44 @@ pack_unpack(str, fmt)
break;
case 'I':
PACK_LENGTH_ADJUST(int);
PACK_LENGTH_ADJUST(unsigned int,sizeof(unsigned int));
while (len-- > 0) {
unsigned int tmp;
memcpy(&tmp, s, sizeof(int));
s += sizeof(int);
memcpy(&tmp, s, sizeof(unsigned int));
s += sizeof(unsigned int);
rb_ary_push(ary, rb_uint2inum(tmp));
}
PACK_ITEM_ADJUST();
break;
case 'l':
PACK_LENGTH_ADJUST(long);
PACK_LENGTH_ADJUST(long,4);
while (len-- > 0) {
long tmp;
memcpy(&tmp, s, sizeof(long));
s += sizeof(long);
memcpy(&tmp, s, NATINT_LEN(long,4));
s += NATINT_LEN(long,4);
rb_ary_push(ary, rb_int2inum(tmp));
}
PACK_ITEM_ADJUST();
break;
case 'L':
PACK_LENGTH_ADJUST(long);
PACK_LENGTH_ADJUST(unsigned long,4);
while (len-- > 0) {
unsigned long tmp;
memcpy(&tmp, s, sizeof(long));
s += sizeof(long);
memcpy(&tmp, s, NATINT_LEN(unsigned long,4));
s += NATINT_LEN(unsigned long,4);
rb_ary_push(ary, rb_uint2inum(tmp));
}
PACK_ITEM_ADJUST();
break;
case 'n':
PACK_LENGTH_ADJUST(short);
PACK_LENGTH_ADJUST(unsigned short,2);
while (len-- > 0) {
unsigned short tmp;
memcpy(&tmp, s, sizeof(short));
s += sizeof(short);
memcpy(&tmp, s, NATINT_LEN(unsigned short,2));
s += NATINT_LEN(unsigned short,2);
tmp = ntohs(tmp);
rb_ary_push(ary, rb_uint2inum(tmp));
}
@ -1163,11 +1276,11 @@ pack_unpack(str, fmt)
break;
case 'N':
PACK_LENGTH_ADJUST(long);
PACK_LENGTH_ADJUST(unsigned long,4);
while (len-- > 0) {
unsigned long tmp;
memcpy(&tmp, s, sizeof(long));
s += sizeof(long);
memcpy(&tmp, s, NATINT_LEN(unsigned long,4));
s += NATINT_LEN(unsigned long,4);
tmp = ntohl(tmp);
rb_ary_push(ary, rb_uint2inum(tmp));
}
@ -1175,11 +1288,11 @@ pack_unpack(str, fmt)
break;
case 'v':
PACK_LENGTH_ADJUST(short);
PACK_LENGTH_ADJUST(unsigned short,2);
while (len-- > 0) {
unsigned short tmp;
memcpy(&tmp, s, sizeof(short));
s += sizeof(short);
memcpy(&tmp, s, NATINT_LEN(unsigned short,2));
s += NATINT_LEN(unsigned short,2);
tmp = vtohs(tmp);
rb_ary_push(ary, rb_uint2inum(tmp));
}
@ -1187,11 +1300,11 @@ pack_unpack(str, fmt)
break;
case 'V':
PACK_LENGTH_ADJUST(long);
PACK_LENGTH_ADJUST(unsigned long,4);
while (len-- > 0) {
unsigned long tmp;
memcpy(&tmp, s, sizeof(long));
s += sizeof(long);
memcpy(&tmp, s, NATINT_LEN(long,4));
s += NATINT_LEN(long,4);
tmp = vtohl(tmp);
rb_ary_push(ary, rb_uint2inum(tmp));
}
@ -1200,7 +1313,7 @@ pack_unpack(str, fmt)
case 'f':
case 'F':
PACK_LENGTH_ADJUST(float);
PACK_LENGTH_ADJUST(float,sizeof(float));
while (len-- > 0) {
float tmp;
memcpy(&tmp, s, sizeof(float));
@ -1211,7 +1324,7 @@ pack_unpack(str, fmt)
break;
case 'e':
PACK_LENGTH_ADJUST(float);
PACK_LENGTH_ADJUST(float,sizeof(float));
while (len-- > 0) {
float tmp;
FLOAT_CONVWITH(ftmp);
@ -1225,7 +1338,7 @@ pack_unpack(str, fmt)
break;
case 'E':
PACK_LENGTH_ADJUST(double);
PACK_LENGTH_ADJUST(double,sizeof(double));
while (len-- > 0) {
double tmp;
DOUBLE_CONVWITH(dtmp);
@ -1240,7 +1353,7 @@ pack_unpack(str, fmt)
case 'D':
case 'd':
PACK_LENGTH_ADJUST(double);
PACK_LENGTH_ADJUST(double,sizeof(double));
while (len-- > 0) {
double tmp;
memcpy(&tmp, s, sizeof(double));
@ -1251,7 +1364,7 @@ pack_unpack(str, fmt)
break;
case 'g':
PACK_LENGTH_ADJUST(float);
PACK_LENGTH_ADJUST(float,sizeof(float));
while (len-- > 0) {
float tmp;
FLOAT_CONVWITH(ftmp;)
@ -1265,7 +1378,7 @@ pack_unpack(str, fmt)
break;
case 'G':
PACK_LENGTH_ADJUST(double);
PACK_LENGTH_ADJUST(double,sizeof(double));
while (len-- > 0) {
double tmp;
DOUBLE_CONVWITH(dtmp);
@ -1278,6 +1391,18 @@ pack_unpack(str, fmt)
PACK_ITEM_ADJUST();
break;
case 'U':
if (len > send - s) len = send - s;
while (len-- > 0 && s < send) {
int alen;
unsigned long l;
l = utf8_to_uv(s, &alen);
s += alen;
rb_ary_push(ary, INT2NUM(l));
}
break;
case 'u':
{
VALUE str = rb_str_new(0, (send - s)*3/4);
@ -1327,6 +1452,8 @@ pack_unpack(str, fmt)
else if (s < send && (s+1 == send || s[1] == '\n'))
s += 2; /* possible checksum byte */
}
RSTRING(str)->ptr[total] = '\0';
RSTRING(str)->len = total;
rb_ary_push(ary, str);
}
@ -1369,6 +1496,7 @@ pack_unpack(str, fmt)
*ptr++ = a << 2 | b >> 4;
*ptr++ = b << 4 | c >> 2;
}
*ptr = '\0';
RSTRING(str)->len = ptr - RSTRING(str)->ptr;
rb_ary_push(ary, str);
}
@ -1395,6 +1523,7 @@ pack_unpack(str, fmt)
}
s++;
}
*ptr = '\0';
RSTRING(str)->len = ptr - RSTRING(str)->ptr;
rb_ary_push(ary, str);
}
@ -1454,6 +1583,82 @@ pack_unpack(str, fmt)
return ary;
}
#define BYTEWIDTH 8
static long
uv_to_utf8(buf, uv)
char *buf;
long uv;
{
if (uv < 0x80) {
buf[0] = (char)uv;
return 1;
}
if (uv < 0x7ff) {
buf[0] = ((uv>>6)&0xff)|0xc0;
buf[1] = uv&0x3f;
return 2;
}
if (uv < 0xffff) {
buf[0] = ((uv>>12)&0xff)|0xe0;
buf[1] = (uv>>6)&0x3f;
buf[2] = uv&0x3f;
return 3;
}
if (uv < 0x1fffff) {
buf[0] = ((uv>>18)&0xff)|0xf0;
buf[1] = (uv>>12)&0x3f;
buf[2] = (uv>>6)&0x3f;
buf[3] = uv&0x3f;
return 4;
}
if (uv < 0x3ffffff) {
buf[0] = ((uv>>24)&0xff)|0xf0;
buf[1] = (uv>>18)&0x3f;
buf[2] = (uv>>12)&0x3f;
buf[3] = (uv>>6)&0x3f;
buf[4] = uv&0x3f;
return 5;
}
if (uv < 0x7fffffff) {
buf[0] = ((uv>>30)&0xff)|0xfc;
buf[1] = (uv>>24)&0x3f;
buf[2] = (uv>>18)&0x3f;
buf[3] = (uv>>12)&0x3f;
buf[4] = (uv>>6)&0x3f;
buf[5] = uv&0x3f;
return 6;
}
buf[0] = uv>>BYTEWIDTH;
buf[1] = uv&0xff;
return 2;
}
static long
utf8_to_uv(p, lenp)
char *p;
int *lenp;
{
int c = (*p++)&0xff;
unsigned long uv;
int n = 1;
if (c < 0xc0) n = 1;
else if (c < 0xe0) n = 2;
else if (c < 0xf0) n = 3;
else if (c < 0xf8) n = 4;
else if (c < 0xfc) n = 5;
else if (c < 0xfe) n = 6;
*lenp = n--;
uv = c;
uv &= (1<<(BYTEWIDTH-2-n)) - 1;
while (n--) {
uv = uv << 6 | *p++ & ((1<<6)-1);
}
return uv;
}
void
Init_pack()
{

7571
parse.c

File diff suppressed because it is too large Load diff

46
parse.y
View file

@ -48,6 +48,7 @@ static enum lex_state {
EXPR_BEG, /* ignore newline, +/- is a sign. */
EXPR_MID, /* newline significant, +/- is a sign. */
EXPR_END, /* newline significant, +/- is a operator. */
EXPR_PAREN, /* almost like EXPR_END, `do' works as `{'. */
EXPR_ARG, /* newline significant, +/- is a operator. */
EXPR_FNAME, /* ignore newline, no reserved words. */
EXPR_DOT, /* right after `.' or `::', no reserved words. */
@ -139,6 +140,7 @@ static void top_local_setup();
kRETRY
kIN
kDO
kDO2
kRETURN
kYIELD
kSUPER
@ -1264,6 +1266,19 @@ brace_block : '{'
fixpos($$, $3?$3:$4);
dyna_pop($<vars>2);
}
| kDO2
{
$<vars>$ = dyna_push();
}
opt_block_var
compstmt
kEND
{
$$ = NEW_ITER($3, 0, $4);
fixpos($$, $3?$3:$4);
dyna_pop($<vars>2);
}
generic_call : tIDENTIFIER
{
@ -1290,12 +1305,12 @@ block_call : generic_call do_block
fixpos($$, $2);
}
method_call : operation '(' opt_call_args ')'
method_call : operation '(' opt_call_args close_paren
{
$$ = new_fcall($1, $3);
fixpos($$, $3);
}
| primary '.' operation2 '(' opt_call_args ')'
| primary '.' operation2 '(' opt_call_args close_paren
{
value_expr($1);
$$ = new_call($1, $3, $5);
@ -1307,7 +1322,7 @@ method_call : operation '(' opt_call_args ')'
$$ = new_call($1, $3, 0);
fixpos($$, $1);
}
| primary tCOLON2 operation2 '(' opt_call_args ')'
| primary tCOLON2 operation2 '(' opt_call_args close_paren
{
value_expr($1);
$$ = new_call($1, $3, $5);
@ -1318,7 +1333,7 @@ method_call : operation '(' opt_call_args ')'
value_expr($1);
$$ = new_call($1, $3, 0);
}
| kSUPER '(' opt_call_args ')'
| kSUPER '(' opt_call_args close_paren
{
if (!compile_for_eval && !cur_mid &&
!in_single && !in_defined)
@ -1333,6 +1348,10 @@ method_call : operation '(' opt_call_args ')'
$$ = NEW_ZSUPER();
}
close_paren : ')'
{
lex_state = EXPR_PAREN;
}
stmt_rhs : block_call
| command_call
@ -1701,6 +1720,9 @@ yycompile(f)
n = yyparse();
compile_for_eval = 0;
ruby_in_compile = 0;
class_nest = 0;
in_single = 0;
cur_mid = 0;
if (n == 0) return ruby_eval_tree;
return 0;
@ -1909,7 +1931,7 @@ read_escape()
return c;
case 'b': /* backspace */
return '\b';
return '\010';
case 's': /* space */
return ' ';
@ -2540,7 +2562,8 @@ yylex()
case '<':
c = nextc();
if (c == '<' &&
lex_state != EXPR_END && lex_state != EXPR_CLASS &&
lex_state != EXPR_END && lex_state != EXPR_PAREN &&
lex_state != EXPR_CLASS &&
(lex_state != EXPR_ARG || space_seen)) {
int c2 = nextc();
int indent = 0;
@ -2599,7 +2622,7 @@ yylex()
return parse_qstring(c,0);
case '?':
if (lex_state == EXPR_END) {
if (lex_state == EXPR_END || lex_state == EXPR_PAREN) {
lex_state = EXPR_BEG;
return '?';
}
@ -2891,7 +2914,7 @@ yylex()
return tCOLON2;
}
pushback(c);
if (lex_state == EXPR_END || ISSPACE(c)) {
if (lex_state == EXPR_END || lex_state == EXPR_PAREN || ISSPACE(c)) {
lex_state = EXPR_BEG;
return ':';
}
@ -2973,7 +2996,9 @@ yylex()
return c;
case '{':
if (lex_state != EXPR_END && lex_state != EXPR_ARG)
if (lex_state != EXPR_END &&
lex_state != EXPR_PAREN &&
lex_state != EXPR_ARG)
c = tLBRACE;
lex_state = EXPR_BEG;
return c;
@ -3186,6 +3211,9 @@ yylex()
if (state == EXPR_FNAME) {
yylval.id = rb_intern(kw->name);
}
if (state == EXPR_PAREN && kw->id[0] == kDO) {
return kDO2;
}
return kw->id[state != EXPR_BEG];
}
}

View file

@ -442,7 +442,6 @@ re_set_syntax(syntax)
do { \
if (current_mbctype == MBCTYPE_UTF8) { \
int n = mbclen(c) - 1; \
int c1; \
c &= (1<<(BYTEWIDTH-2-n)) - 1; \
while (n--) { \
c = c << 6 | *p++ & ((1<<6)-1); \
@ -1074,6 +1073,9 @@ read_backslash(c)
case 'a':
return '\007';
case 'b':
return '\010';
case 'e':
return '\033';
}
@ -3597,8 +3599,7 @@ re_match(bufp, string_arg, size, pos, regs)
not = is_in_list(c, p);
if (!not && cc != c) {
part = 1;
not = is_in_list(cc, p);
part = not = is_in_list(cc, p);
}
if (*(p - 1) == (unsigned char)charset_not) {
not = !not;

View file

@ -83,7 +83,6 @@ extern const unsigned char *re_mbctab;
#if defined(__STDC__)
void re_mbcinit (int);
#else
extern unsigned char *re_mbctab;
void re_mbcinit ();
#endif

14
ruby.h
View file

@ -19,12 +19,6 @@ extern "C" {
#include "config.h"
#include "defines.h"
#if 0
#ifndef RUBY_RENAME
#include "rename2.h"
#endif
#endif
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
@ -78,7 +72,7 @@ extern "C" {
#endif
#if defined(__CYGWIN32__)
#if defined(DLLIMPORT)
#if defined(USEIMPORTLIB)
#include "import.h"
#else
#if !defined(__CYGWIN__)
@ -181,7 +175,7 @@ void rb_secure _((int));
long rb_num2long _((VALUE));
unsigned long rb_num2ulong _((VALUE));
#define NUM2LONG(x) (FIXNUM_P(x)?FIX2INT(x):rb_num2long((VALUE)x))
#define NUM2LONG(x) (FIXNUM_P(x)?FIX2LONG(x):rb_num2long((VALUE)x))
#define NUM2ULONG(x) rb_num2ulong((VALUE)x)
#if SIZEOF_INT < SIZEOF_LONG
int rb_num2int _((VALUE));
@ -205,8 +199,8 @@ char *rb_str2cstr _((VALUE,int*));
#define STR2CSTR(x) rb_str2cstr((VALUE)(x),0)
#define NUM2CHR(x) (((TYPE(x) == T_STRING)&&(RSTRING(x)->len>=1))?\
RSTRING(x)->ptr[0]:(char)NUM2INT(x))
#define CHR2FIX(x) INT2FIX((int)x)
RSTRING(x)->ptr[0]:(char)(NUM2INT(x)&0xff))
#define CHR2FIX(x) INT2FIX((long)((x)&0xff))
VALUE rb_newobj _((void));
#define NEWOBJ(obj,type) type *obj = (type*)rb_newobj()

View file

@ -50,6 +50,7 @@ typedef struct OpenFile {
FILE *rb_fopen _((const char*, const char*));
FILE *rb_fdopen _((int, const char*));
int rb_getc _((FILE*));
int rb_io_mode_flags _((const char*));
void rb_io_check_writable _((OpenFile*));
void rb_io_check_readable _((OpenFile*));

View file

@ -5,6 +5,8 @@ cbreak.rb no echo done by ioctl
clnt.rb socket client
dbmtest.rb test for dbm
dir.rb directory access
dualstack-fetch.rb IPv6 demo
dualstack-httpd.rb IPv6 demo
dstore.rb object database on dbm
eval.rb simple evaluator
export.rb method access example
@ -40,6 +42,7 @@ rbc.rb interactive ruby, to be removed by irb
rcs.awk random character stereogram (AWK)
rcs.rb random character stereogram (Ruby)
rcs.dat data for random character stereogram
rd2html.rb rd (Ruby Document) to HTML translator
regx.rb regular expression tester
ruby-mode.el ruby mode for emacs
rubydb2x.el ruby debugger support for emacs 19.2x or before
@ -48,13 +51,6 @@ sieve.rb sieve of Eratosthenes
svr.rb socket server
test.rb test suite used by `make test'
time.rb /usr/bin/time clone
tkbiff.rb mail notifier using Tk
tkbrowse.rb directory browser using Tk
tkdialog.rb dialog example
tkfrom.rb scan mail spool using Tk
tkhello.rb simple Tk example
tkline.rb simple Tk example
tktimer.rb stopwatch
trojan.rb simple tool to find file that may be trojan horse.
tsvr.rb socket server using thread
uumerge.rb merge files and uudecode them

View file

@ -2439,9 +2439,17 @@ rb_str_oct(str)
{
int base = 8;
if (RSTRING(str)->len > 2 && RSTRING(str)->ptr[0] == '0' &&
(RSTRING(str)->ptr[1] == 'x' || RSTRING(str)->ptr[1] == 'X')) {
base = 16;
if (RSTRING(str)->len > 2 && RSTRING(str)->ptr[0] == '0') {
switch (RSTRING(str)->ptr[1]) {
case 'x':
case 'X':
base = 16;
break;
case 'b':
case 'B':
base = 2;
break;
}
}
return rb_str2inum(RSTRING(str)->ptr, base);
}

View file

@ -1179,11 +1179,10 @@ rb_const_set(klass, id, val)
RCLASS(klass)->iv_tbl = st_init_numtable();
}
else if (st_lookup(RCLASS(klass)->iv_tbl, id, 0)) {
rb_raise(rb_eNameError, "already initialized constant %s",
rb_id2name(id));
rb_warn("already initialized constant %s", rb_id2name(id));
}
st_add_direct(RCLASS(klass)->iv_tbl, id, val);
st_insert(RCLASS(klass)->iv_tbl, id, val);
}
void

View file

@ -18,20 +18,29 @@
void
Init_version()
{
rb_define_global_const("VERSION", rb_str_new2(RUBY_VERSION));
rb_define_global_const("RELEASE_DATE", rb_str_new2(RUBY_RELEASE_DATE));
rb_define_global_const("PLATFORM", rb_str_new2(RUBY_PLATFORM));
VALUE v = rb_str_new2(RUBY_VERSION);
VALUE d = rb_str_new2(RUBY_RELEASE_DATE);
VALUE p = rb_str_new2(RUBY_PLATFORM);
rb_define_global_const("RUBY_VERSION", v);
rb_define_global_const("RUBY_RELEASE_DATE", d);
rb_define_global_const("RUBY_PLATFORM", p);
/* obsolete constants */
rb_define_global_const("VERSION", v);
rb_define_global_const("RELEASE_DATE", d);
rb_define_global_const("PLATFORM", p);
}
void
ruby_show_version()
{
fprintf(stderr, "ruby %s (%s) [%s]\n", RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PLATFORM);
printf("ruby %s (%s) [%s]\n", RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PLATFORM);
}
void
ruby_show_copyright()
{
fprintf(stderr, "ruby - Copyright (C) 1993-1999 Yukihiro Matsumoto\n");
printf("ruby - Copyright (C) 1993-1999 Yukihiro Matsumoto\n");
exit(0);
}

View file

@ -1,3 +1,4 @@
#define RUBY_VERSION "1.3.4"
#define RUBY_RELEASE_DATE "1999-06-01"
#define RUBY_RELEASE_CODE 19990601
#define RUBY_RELEASE_DATE "1999-06-04"
#define RUBY_VERSION_CODE 134
#define RUBY_RELEASE_CODE 19990604