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> 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.h (RUBY_RELEASE_CODE): integer macro contant for source
version detection. version detection.

View file

@ -76,6 +76,7 @@ variable.c
version.c version.c
version.h version.h
beos/ruby.def.in beos/ruby.def.in
cygwin/GNUmakefile.in
ext/Setup ext/Setup
ext/Setup.dj ext/Setup.dj
ext/Setup.emx ext/Setup.emx
@ -85,6 +86,7 @@ ext/aix_mksym.rb
ext/cygwin32_ld.rb ext/cygwin32_ld.rb
ext/extmk.rb.in ext/extmk.rb.in
ext/extmk.rb.nt ext/extmk.rb.nt
lib/CGI.rb
lib/English.rb lib/English.rb
lib/Env.rb lib/Env.rb
lib/README lib/README
@ -171,6 +173,8 @@ sample/cbreak.rb
sample/clnt.rb sample/clnt.rb
sample/dbmtest.rb sample/dbmtest.rb
sample/dir.rb sample/dir.rb
sample/dualstack-fetch.rb
sample/dualstack-httpd.rb
sample/eval.rb sample/eval.rb
sample/export.rb sample/export.rb
sample/exyacc.rb sample/exyacc.rb
@ -204,6 +208,7 @@ sample/rbc.rb
sample/rcs.awk sample/rcs.awk
sample/rcs.dat sample/rcs.dat
sample/rcs.rb sample/rcs.rb
sample/rd2html.rb
sample/regx.rb sample/regx.rb
sample/sieve.rb sample/sieve.rb
sample/svr.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 4. You may modify and include the part of the software into any other
software (possibly commercial). But some files in the distribution software (possibly commercial). But some files in the distribution
are not written by the author, so that they are not under this terms. 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] They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
and some files under the ./missing directory. See each file for the files under the ./missing directory. See each file for the copying
copying condition. condition.
5. The scripts and library files supplied as input to or produced as 5. The scripts and library files supplied as input to or produced as
output from the software do not automatically fall under the 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/ http://www.netlab.co.jp/ruby/jp/
です. です.
* メーリングリスト * メーリングリスト
Rubyに関わる話題のためのメーリングリストを開設しました Rubyに関わる話題のためのメーリングリストを開設しました
ドレスは ドレスは
ruby-list@netlab.co.jp ruby-list@netlab.co.jp
です.このアドレスにメールを送れば,自動的に登録されます. です.このアドレスにメールを送れば,自動的に登録されます.
* コンパイル・インストール * コンパイル・インストール
@ -150,9 +150,9 @@ Licence)
4. 他のプログラムへの引用はいかなる目的であれ自由です.た 4. 他のプログラムへの引用はいかなる目的であれ自由です.た
だしRubyに含まれる他の作者によるコードはそれぞれの だしRubyに含まれる他の作者によるコードはそれぞれの
作者の意向による制限が加えられます具体的にはgc.c(一部) 作者の意向による制限が加えられます具体的にはgc.c(一部)
util.c(一部)st.[ch]regex.[ch], glob.c および. util.c(一部)st.[ch]regex.[ch] および. /missingディ
/missingディレクトリ下のファイル群が該当します.それぞ レクトリ下のファイル群が該当します.それぞれの配布条件
れの配布条件などに付いては各ファイルを参照してください. などに付いては各ファイルを参照してください.
5. Rubyへの入力となるスクリプトおよびRubyからの出力の権 5. Rubyへの入力となるスクリプトおよびRubyからの出力の権
利はRubyの作者ではなくそれぞれの入出力を生成した人に 利はRubyの作者ではなくそれぞれの入出力を生成した人に

2
config.guess vendored
View file

@ -382,7 +382,7 @@ EOF
case "${UNAME_MACHINE}" in case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;; 9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;; 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 sed 's/^ //' << EOF >dummy.c
#include <stdlib.h> #include <stdlib.h>
#include <unistd.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*) ;; rhapsody*) ;;
human*) ;; human*) ;;
beos*) ;; beos*) ;;
cygwin*) ;;
*) LIBS="-lm $LIBS";; *) LIBS="-lm $LIBS";;
esac esac
AC_CHECK_LIB(crypt, crypt) AC_CHECK_LIB(crypt, crypt)
@ -379,7 +380,13 @@ if test "$with_dln_a_out" != yes; then
openstep*) ;; openstep*) ;;
rhapsody*) ;; rhapsody*) ;;
human*) ;; human*) ;;
cygwin*) CCDLFLAGS=-DDLLIMPORT;; bsdi3*) ;;
cygwin*) ;;
netbsd*) CCDLFLAGS=-fpic
case "$host_cpu" in
mips*) CCDLFLAGS=-fPIC ;;
*) ;;
esac ;;
*) CCDLFLAGS=-fPIC;; *) CCDLFLAGS=-fPIC;;
esac esac
else 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" test "$GCC" = yes && `$CC --print-prog-name=ld` -v 2>&1 | grep "GNU ld" > /dev/null || LDSHARED="ld -Bshareable"
fi fi
rb_cv_dlopen=yes ;; rb_cv_dlopen=yes ;;
netbsd*) LDSHARED="ld -Bshareable" netbsd*) LDSHARED="ld -shared"
case "$host_cpu" in
alpha|mips)
LDFLAGS="-export-dynamic" ;;
*)
;;
esac
rb_cv_dlopen=yes ;; rb_cv_dlopen=yes ;;
openbsd*) LDSHARED="ld -Bforcearchive -Bshareable" openbsd*) LDSHARED="ld -Bforcearchive -Bshareable"
rb_cv_dlopen=yes ;; 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" LDFLAGS="-u libsys_s"
DLDFLAGS="$ARCH_FLAG" DLDFLAGS="$ARCH_FLAG"
rb_cv_dlopen=yes ;; 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" DLDFLAGS="ruby.def -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o"
esac esac
rb_cv_dlopen=yes ;; rb_cv_dlopen=yes ;;
cygwin*) LDSHARED='../../miniruby ../cygwin32_ld.rb' cygwin*) LDSHARED='dllwrap --export-all -s'
rb_cv_dlopen=yes ;; rb_cv_dlopen=yes ;;
*) LDSHARED='ld' ;; *) LDSHARED='ld' ;;
esac esac
@ -502,15 +507,15 @@ if test "$dln_a_out_works" = yes; then
else else
STATIC=-Bstatic STATIC=-Bstatic
fi fi
DLEXT=o DLEXT=so
AC_DEFINE(DLEXT, ".o") AC_DEFINE(DLEXT, ".so")
CCDLFLAGS= CCDLFLAGS=
else else
case "$host_os" in case "$host_os" in
hpux*) DLEXT=sl hpux*) DLEXT=sl
AC_DEFINE(DLEXT, ".sl");; AC_DEFINE(DLEXT, ".sl");;
nextstep*) DLEXT=o nextstep*) DLEXT=bundle
AC_DEFINE(DLEXT, ".o");; AC_DEFINE(DLEXT, ".bundle");;
openstep*) DLEXT=bundle openstep*) DLEXT=bundle
AC_DEFINE(DLEXT, ".bundle");; AC_DEFINE(DLEXT, ".bundle");;
rhapsody*) DLEXT=bundle rhapsody*) DLEXT=bundle
@ -518,7 +523,7 @@ else
cygwin*) DLEXT=dll cygwin*) DLEXT=dll
AC_DEFINE(DLEXT, ".dll");; AC_DEFINE(DLEXT, ".dll");;
os2_emx) DLEXT=o os2_emx) DLEXT=o
AC_DEFINE(DLEXT, ".o");; AC_DEFINE(DLEXT, ".so");;
*) DLEXT=so *) DLEXT=so
AC_DEFINE(DLEXT, ".so");; AC_DEFINE(DLEXT, ".so");;
esac esac
@ -652,6 +657,7 @@ if test "$host_os" = "beos"; then
esac esac
fi fi
FIRSTMAKEFILE=""
LIBRUBY_LDSHARED=$LDSHARED LIBRUBY_LDSHARED=$LDSHARED
LIBRUBY_DLDFLAGS=$DLDFLAGS LIBRUBY_DLDFLAGS=$DLDFLAGS
LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR).$(TEENY)' LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR).$(TEENY)'
@ -674,6 +680,14 @@ if test "$enable_shared" = 'yes'; then
LIBRUBY_ALIASES='' LIBRUBY_ALIASES=''
fi 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*) hpux*)
LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).sl.$(MAJOR).$(MINOR).$(TEENY)' LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).sl.$(MAJOR).$(MINOR).$(TEENY)'
LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).sl.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).sl' 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' LIBRUBYARG='-L./ -Wl,lib$(RUBY_INSTALL_NAME).so'
SOLIBS='-lm -lc' 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 esac
@ -755,4 +778,4 @@ AC_DEFINE_UNQUOTED(RUBY_SITE_ARCHLIB, "${RUBY_SITE_LIB_PATH}/${arch}")
echo "creating config.h" echo "creating config.h"
cat confdefs.h > 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) #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 static void
aix_loaderror(const char *pathname) aix_loaderror(const char *pathname)
{ {
@ -1342,19 +1313,13 @@ dln_load(file)
#if defined(_AIX) #if defined(_AIX)
#define DLN_DEFINED #define DLN_DEFINED
{ {
static void *main_module = NULL;
void (*init_fct)(); void (*init_fct)();
if (main_module == NULL) {
if ((main_module = aix_findmain()) == NULL) {
aix_loaderror(file);
}
}
init_fct = (void(*)())load((char*)file, 1, 0); init_fct = (void(*)())load((char*)file, 1, 0);
if (init_fct == NULL) { if (init_fct == NULL) {
aix_loaderror(file); 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); aix_loaderror(file);
} }
(*init_fct)(); (*init_fct)();
@ -1372,7 +1337,7 @@ dln_load(file)
Mi hisho@tasihara.nest.or.jp, Mi hisho@tasihara.nest.or.jp,
and... Miss ARAI Akino(^^;) 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; unsigned long init_address;
@ -1409,7 +1374,7 @@ dln_load(file)
void (*init_fct)(); void (*init_fct)();
dyld_result = NSCreateObjectFileImageFromFile( file, &obj_file ); dyld_result = NSCreateObjectFileImageFromFile(file, &obj_file);
if (dyld_result != NSObjectFileImageSuccess) { if (dyld_result != NSObjectFileImageSuccess) {
rb_loaderror("Failed to load %.200s", file); rb_loaderror("Failed to load %.200s", file);
@ -1419,12 +1384,12 @@ dln_load(file)
/* lookup the initial function */ /* lookup the initial function */
/*NSIsSymbolNameDefined require function name without "_" */ /*NSIsSymbolNameDefined require function name without "_" */
if( NSIsSymbolNameDefined( buf + 1 ) ) { if(NSIsSymbolNameDefined(buf + 1)) {
rb_loaderror("Failed to lookup Init function %.200s",file); rb_loaderror("Failed to lookup Init function %.200s",file);
} }
/* NSLookupAndBindSymbol require function name with "_" !! */ /* NSLookupAndBindSymbol require function name with "_" !! */
init_fct = NSAddressOfSymbol( NSLookupAndBindSymbol( buf ) ); init_fct = NSAddressOfSymbol(NSLookupAndBindSymbol(buf));
(*init_fct)(); (*init_fct)();
return ; return ;
@ -1499,8 +1464,8 @@ dln_load(file)
c2pstr(fullpath); c2pstr(fullpath);
(void)FSMakeFSSpec(0, 0, fullpath, &libspec); (void)FSMakeFSSpec(0, 0, fullpath, &libspec);
err = ResolveAliasFile(&libspec, 1, &isfolder, &didsomething); err = ResolveAliasFile(&libspec, 1, &isfolder, &didsomething);
if ( err ) { if (err) {
rb_loaderror("Unresolved Alias - %s", file); rb_loaderror("Unresolved Alias - %s", file);
} }
/* Load the fragment (or return the connID if it is already loaded */ /* 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, err = GetDiskFragment(&libspec, 0, 0, fragname,
kLoadCFrag, &connID, &mainAddr, kLoadCFrag, &connID, &mainAddr,
errMessage); errMessage);
if ( err ) { if (err) {
p2cstr(errMessage); p2cstr(errMessage);
rb_loaderror("%s - %s",errMessage , file); rb_loaderror("%s - %s",errMessage , file);
} }
/* Locate the address of the correct init function */ /* Locate the address of the correct init function */
c2pstr(buf); c2pstr(buf);
err = FindSymbol(connID, buf, &symAddr, &class); err = FindSymbol(connID, buf, &symAddr, &class);
if ( err ) { if (err) {
rb_loaderror("Unresolved symbols - %s" , file); rb_loaderror("Unresolved symbols - %s" , file);
} }
init_fct = (void (*)())symAddr; init_fct = (void (*)())symAddr;

107
eval.c
View file

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

View file

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

View file

@ -29,8 +29,9 @@ md5_update(obj, str)
Data_Get_Struct(obj, MD5_CTX, md5); Data_Get_Struct(obj, MD5_CTX, md5);
MD5Update(md5, str->ptr, str->len); MD5Update(md5, str->ptr, str->len);
return Qnil; return obj;
} }
static VALUE static VALUE
md5_digest(obj) md5_digest(obj)
VALUE obj; VALUE obj;
@ -45,6 +46,26 @@ md5_digest(obj)
return rb_str_new(digest, 16); 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 static VALUE
md5_clone(obj) md5_clone(obj)
VALUE obj; VALUE obj;
@ -90,5 +111,6 @@ Init_md5()
rb_define_method(cMD5, "update", md5_update, 1); rb_define_method(cMD5, "update", md5_update, 1);
rb_define_method(cMD5, "digest", md5_digest, 0); rb_define_method(cMD5, "digest", md5_digest, 0);
rb_define_method(cMD5, "hexdigest", md5_hexdigest, 0);
rb_define_method(cMD5, "clone", md5_clone, 0); rb_define_method(cMD5, "clone", md5_clone, 0);
} }

View file

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

View file

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

View file

@ -27,6 +27,8 @@
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#ifndef ADDR_INFO_H
#define ADDR_INFO_H
#ifndef HAVE_GETADDRINFO #ifndef HAVE_GETADDRINFO
/* special compatibility hack */ /* special compatibility hack */
@ -167,3 +169,4 @@ Standard C system should have one. */
#endif #endif
#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 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 $(hdrdir)/config.h addrinfo.h sockport.h
getnameinfo.o: getnameinfo.c 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/ when /mswin32/
test_func = "WSACleanup" test_func = "WSACleanup"
have_library("wsock32", "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" test_func = "socket"
have_library("bind", "gethostbyaddr")
when /beos/ when /beos/
test_func = "socket" test_func = "socket"
have_library("net", "socket") have_library("net", "socket")
@ -252,8 +255,8 @@ if have_getaddrinfo
$CFLAGS="-DHAVE_GETADDRINFO "+$CFLAGS $CFLAGS="-DHAVE_GETADDRINFO "+$CFLAGS
else else
$CFLAGS="-I. "+$CFLAGS $CFLAGS="-I. "+$CFLAGS
$objs += "getaddrinfo.o" $objs += ["getaddrinfo.o"]
$objs += "getnameinfo.o" $objs += ["getnameinfo.o"]
have_func("inet_ntop") or have_func("inet_ntoa") have_func("inet_ntop") or have_func("inet_ntoa")
have_func("inet_pton") or have_func("inet_aton") have_func("inet_pton") or have_func("inet_aton")
end end

View file

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

View file

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

View file

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

View file

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

View file

@ -285,8 +285,8 @@ class TkText<TkTextWin
end end
else else
if ( key == 'font' || key == 'kanjifont' \ if key == 'font' || key == 'kanjifont' ||
|| key == 'latinfont' || key == 'asciifont' ) key == 'latinfont' || key == 'asciifont'
tagfont_configure({key=>val}) tagfont_configure({key=>val})
else else
tk_send 'tag', 'configure', tag, "-#{key}", val tk_send 'tag', 'configure', tag, "-#{key}", val
@ -320,7 +320,7 @@ class TkText<TkTextWin
end end
def tag_ranges(tag) def tag_ranges(tag)
l = tk_split_list(tk_send('tag', 'ranges', tag)) l = tk_split_simplelist(tk_send('tag', 'ranges', tag))
r = [] r = []
while key=l.shift while key=l.shift
r.push [key, l.shift] r.push [key, l.shift]
@ -329,11 +329,11 @@ class TkText<TkTextWin
end end
def tag_nextrange(tag, first, last=None) 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 end
def tag_prevrange(tag, first, last=None) 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 end
def search_with_length(pat,start,stop=None) def search_with_length(pat,start,stop=None)
@ -437,9 +437,19 @@ class TkTextTag<TkObject
@path = @id = $tk_text_tag @path = @id = $tk_text_tag
$tk_text_tag = $tk_text_tag.succ $tk_text_tag = $tk_text_tag.succ
#tk_call @t.path, "tag", "configure", @id, *hash_kv(keys) #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 @t._addtag id, self
end end
def id def id
return @id return @id
end end
@ -470,11 +480,11 @@ class TkTextTag<TkObject
end end
def nextrange(first, last=None) 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 end
def prevrange(first, last=None) 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 end
def [](key) def [](key)
@ -631,6 +641,18 @@ class TkTextMarkCurrent<TkTextMark
end end
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 class TkTextWindow<TkObject
def initialize(parent, index, keys) def initialize(parent, index, keys)
if not parent.kind_of?(TkText) if not parent.kind_of?(TkText)
@ -726,6 +748,133 @@ class TkTextWindow<TkObject
} }
end end
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 end
class TkTextImage<TkObject class TkTextImage<TkObject

7
hash.c
View file

@ -1048,6 +1048,13 @@ ruby_setenv(name, value)
SetEnvironmentVariable(name,value); SetEnvironmentVariable(name,value);
#endif #endif
#elif defined __CYGWIN__
#undef setenv
#undef unsetenv
if (value)
setenv(name,value,1);
else
unsetenv(name);
#else /* WIN32 */ #else /* WIN32 */
int i=envix(name); /* where does it go? */ 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)); int rb_thread_alone _((void));
void rb_thread_sleep _((int)); void rb_thread_sleep _((int));
void rb_thread_sleep_forever _((void)); 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*)); VALUE rb_thread_create _((VALUE (*)(), void*));
int rb_thread_scope_shared_p _((void)); int rb_thread_scope_shared_p _((void));
void rb_thread_interrupt _((void)); void rb_thread_interrupt _((void));

21
io.c
View file

@ -306,10 +306,6 @@ rb_io_eof(io)
rb_io_check_readable(fptr); rb_io_check_readable(fptr);
if (READ_DATA_PENDING(fptr->f)) return Qfalse; if (READ_DATA_PENDING(fptr->f)) return Qfalse;
#if 0
if (feof(fptr->f)) return Qtrue;
return Qfalse;
#else
READ_CHECK(fptr->f); READ_CHECK(fptr->f);
TRAP_BEG; TRAP_BEG;
ch = getc(fptr->f); ch = getc(fptr->f);
@ -320,7 +316,6 @@ rb_io_eof(io)
return Qfalse; return Qfalse;
} }
return Qtrue; return Qtrue;
#endif
} }
static VALUE static VALUE
@ -811,6 +806,22 @@ rb_io_getc(io)
return INT2FIX(c & 0xff); 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 static VALUE
rb_io_readchar(io) rb_io_readchar(io)
VALUE io; VALUE io;

View file

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

View file

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

View file

@ -457,7 +457,7 @@ static int
r_byte(arg) r_byte(arg)
struct load_arg *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++; if (arg->ptr < arg->end) return *(unsigned char*)arg->ptr++;
return EOF; return EOF;
} }

View file

@ -152,6 +152,15 @@ The variable ruby-indent-level controls the amount of indentation.
(setq mode-name "Ruby") (setq mode-name "Ruby")
(setq major-mode 'ruby-mode) (setq major-mode 'ruby-mode)
(ruby-mode-variables) (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)) (run-hooks 'ruby-mode-hook))
(defun ruby-current-indentation () (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) ("\\$\\(.\\|\\sw+\\)" nil type)
("[$@].[a-zA-Z_0-9]*" nil struct) ("[$@].[a-zA-Z_0-9]*" nil struct)
("^__END__" nil label)))) ("^__END__" nil label))))
)
((featurep 'font-lock)
(or (boundp 'font-lock-variable-name-face) (or (boundp 'font-lock-variable-name-face)
(setq font-lock-variable-name-face font-lock-type-face)) (setq font-lock-variable-name-face font-lock-type-face))
(defvar ruby-font-lock-keywords (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_\\)+\\)\\>" '("^\\s *def\\s *\\<\\(\\(\\w\\|\\s_\\)+\\.\\)?\\(\\(\\w\\|\\s_\\)+\\)\\>"
3 font-lock-function-name-face t)) 3 font-lock-function-name-face t))
"*Additional expressions to highlight in ruby mode.") "*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) (provide 'ruby-mode)

View file

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

View file

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

377
pack.c
View file

@ -14,8 +14,17 @@
#include <sys/types.h> #include <sys/types.h>
#include <ctype.h> #include <ctype.h>
#ifndef atof #define SIZE16 2
double strtod(); #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 #endif
#define define_swapx(x, xtype) \ #define define_swapx(x, xtype) \
@ -280,6 +289,9 @@ static char *toofew = "too few arguments";
static void encodes _((VALUE,char*,int,int)); static void encodes _((VALUE,char*,int,int));
static void qpencode _((VALUE,VALUE,int)); static void qpencode _((VALUE,VALUE,int));
static long uv_to_utf8 _((char*,long));
static long utf8_to_uv _((char*,int*));
static void static void
pack_add_ptr(str, add) pack_add_ptr(str, add)
VALUE str, add; VALUE str, add;
@ -304,9 +316,11 @@ pack_pack(ary, fmt)
int items, len, idx; int items, len, idx;
char *ptr; char *ptr;
int plen; int plen;
#ifdef NATINT_PACK
int natint; /* native integer */
#endif
p = rb_str2cstr(fmt, &plen); p = str2cstr(fmt, &plen);
pend = p + plen; pend = p + plen;
res = rb_str_new(0, 0); res = rb_str_new(0, 0);
@ -317,7 +331,24 @@ pack_pack(ary, fmt)
while (p < pend) { while (p < pend) {
type = *p++; /* get data type */ 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 */ if (*p == '*') { /* set data length */
len = strchr("@Xxu", type) ? 0 : items; len = strchr("@Xxu", type) ? 0 : items;
p++; p++;
@ -339,9 +370,7 @@ pack_pack(ary, fmt)
plen = 0; plen = 0;
} }
else { else {
from = rb_obj_as_string(from); ptr = str2cstr(from, &plen);
ptr = RSTRING(from)->ptr;
plen = RSTRING(from)->len;
} }
if (p[-1] == '*') if (p[-1] == '*')
@ -350,6 +379,7 @@ pack_pack(ary, fmt)
switch (type) { switch (type) {
case 'a': case 'a':
case 'A': case 'A':
case 'Z':
if (plen >= len) if (plen >= len)
rb_str_cat(res, ptr, len); rb_str_cat(res, ptr, len);
else { else {
@ -366,8 +396,12 @@ pack_pack(ary, fmt)
case 'b': case 'b':
{ {
int byte = 0; int byte = 0;
int i; int i, j;
if (len > plen) {
j = (len - plen + 1)/2;
len = plen;
}
for (i=0; i++ < len; ptr++) { for (i=0; i++ < len; ptr++) {
if (*ptr & 1) if (*ptr & 1)
byte |= 128; byte |= 128;
@ -385,14 +419,21 @@ pack_pack(ary, fmt)
c = byte & 0xff; c = byte & 0xff;
rb_str_cat(res, &c, 1); rb_str_cat(res, &c, 1);
} }
len = RSTRING(res)->len;
rb_str_resize(res, len+j);
MEMZERO(RSTRING(res)->ptr+len, char, j);
} }
break; break;
case 'B': case 'B':
{ {
int byte = 0; int byte = 0;
int i; int i, j;
if (len > plen) {
j = (len - plen + 1)/2;
len = plen;
}
for (i=0; i++ < len; ptr++) { for (i=0; i++ < len; ptr++) {
byte |= *ptr & 1; byte |= *ptr & 1;
if (i & 7) if (i & 7)
@ -409,60 +450,73 @@ pack_pack(ary, fmt)
c = byte & 0xff; c = byte & 0xff;
rb_str_cat(res, &c, 1); rb_str_cat(res, &c, 1);
} }
len = RSTRING(res)->len;
rb_str_resize(res, len+j);
MEMZERO(RSTRING(res)->ptr+len, char, j);
} }
break; break;
case 'h': case 'h':
{ {
int byte = 0; int byte = 0;
int i; int i, j;
if (len > plen) {
j = (len - plen + 1)/2;
len = plen;
}
for (i=0; i++ < len; ptr++) { for (i=0; i++ < len; ptr++) {
if (ISXDIGIT(*ptr)) { if (ISALPHA(*ptr))
if (ISALPHA(*ptr)) byte |= (((*ptr & 15) + 9) & 15) << 4;
byte |= (((*ptr & 15) + 9) & 15) << 4; else
else byte |= (*ptr & 15) << 4;
byte |= (*ptr & 15) << 4; if (i & 1)
if (i & 1) byte >>= 4;
byte >>= 4; else {
else { char c = byte & 0xff;
char c = byte & 0xff; rb_str_cat(res, &c, 1);
rb_str_cat(res, &c, 1); byte = 0;
byte = 0;
}
} }
} }
if (len & 1) { if (len & 1) {
char c = byte & 0xff; char c = byte & 0xff;
rb_str_cat(res, &c, 1); rb_str_cat(res, &c, 1);
} }
len = RSTRING(res)->len;
rb_str_resize(res, len+j);
MEMZERO(RSTRING(res)->ptr+len, char, j);
} }
break; break;
case 'H': case 'H':
{ {
int byte = 0; int byte = 0;
int i; int i, j;
if (len > plen) {
j = (len - plen + 1)/2;
len = plen;
}
for (i=0; i++ < len; ptr++) { for (i=0; i++ < len; ptr++) {
if (ISXDIGIT(*ptr)) { if (ISALPHA(*ptr))
if (ISALPHA(*ptr)) byte |= ((*ptr & 15) + 9) & 15;
byte |= ((*ptr & 15) + 9) & 15; else
else byte |= *ptr & 15;
byte |= *ptr & 15; if (i & 1)
if (i & 1) byte <<= 4;
byte <<= 4; else {
else { char c = byte & 0xff;
char c = byte & 0xff; rb_str_cat(res, &c, 1);
rb_str_cat(res, &c, 1); byte = 0;
byte = 0;
}
} }
} }
if (len & 1) { if (len & 1) {
char c = byte & 0xff; char c = byte & 0xff;
rb_str_cat(res, &c, 1); rb_str_cat(res, &c, 1);
} }
len = RSTRING(res)->len;
rb_str_resize(res, len+j);
MEMZERO(RSTRING(res)->ptr+len, char, j);
} }
break; break;
} }
@ -492,7 +546,7 @@ pack_pack(ary, fmt)
else { else {
s = NUM2INT(from); s = NUM2INT(from);
} }
rb_str_cat(res, (char*)&s, sizeof(short)); rb_str_cat(res, (char*)&s, NATINT_LEN(short,2));
} }
break; break;
@ -520,7 +574,7 @@ pack_pack(ary, fmt)
else { else {
l = NUM2ULONG(from); l = NUM2ULONG(from);
} }
rb_str_cat(res, (char*)&l, sizeof(long)); rb_str_cat(res, (char*)&l, NATINT_LEN(long,4));
} }
break; break;
@ -534,7 +588,7 @@ pack_pack(ary, fmt)
s = NUM2INT(from); s = NUM2INT(from);
} }
s = htons(s); s = htons(s);
rb_str_cat(res, (char*)&s, sizeof(short)); rb_str_cat(res, (char*)&s, NATINT_LEN(short,2));
} }
break; break;
@ -548,7 +602,7 @@ pack_pack(ary, fmt)
l = NUM2ULONG(from); l = NUM2ULONG(from);
} }
l = htonl(l); l = htonl(l);
rb_str_cat(res, (char*)&l, sizeof(long)); rb_str_cat(res, (char*)&l, NATINT_LEN(long,4));
} }
break; break;
@ -562,7 +616,7 @@ pack_pack(ary, fmt)
s = NUM2INT(from); s = NUM2INT(from);
} }
s = htovs(s); s = htovs(s);
rb_str_cat(res, (char*)&s, sizeof(short)); rb_str_cat(res, (char*)&s, NATINT_LEN(short,2));
} }
break; break;
@ -576,7 +630,7 @@ pack_pack(ary, fmt)
l = NUM2ULONG(from); l = NUM2ULONG(from);
} }
l = htovl(l); l = htovl(l);
rb_str_cat(res, (char*)&l, sizeof(long)); rb_str_cat(res, (char*)&l, NATINT_LEN(long,4));
} }
break; break;
@ -732,11 +786,24 @@ pack_pack(ary, fmt)
rb_raise(rb_eArgError, "% may only be used in unpack"); rb_raise(rb_eArgError, "% may only be used in unpack");
break; 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 'u':
case 'm': case 'm':
from = rb_obj_as_string(NEXTFROM); ptr = str2cstr(NEXTFROM, &plen);
ptr = RSTRING(from)->ptr;
plen = RSTRING(from)->len;
if (len <= 1) if (len <= 1)
len = 45; 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; \ tmp = 0; \
if (len > (send-s)/sizeof(type)) { \ if (len > (send-s)/sizeof(type)) { \
if (!star) { \ if (!star) { \
@ -923,6 +1002,7 @@ hex2num(c)
len = (send-s)/sizeof(type); \ len = (send-s)/sizeof(type); \
} \ } \
} while (0) } while (0)
#endif
#define PACK_ITEM_ADJUST() while (tmp--) rb_ary_push(ary, Qnil); #define PACK_ITEM_ADJUST() while (tmp--) rb_ary_push(ary, Qnil);
@ -936,17 +1016,35 @@ pack_unpack(str, fmt)
VALUE ary; VALUE ary;
char type; char type;
int len, tmp, star; int len, tmp, star;
#ifdef NATINT_PACK
int natint; /* native integer */
#endif
s = rb_str2cstr(str, &len); s = str2cstr(str, &len);
send = s + len; send = s + len;
p = rb_str2cstr(fmt, &len); p = str2cstr(fmt, &len);
pend = p + len; pend = p + len;
ary = rb_ary_new(); ary = rb_ary_new();
while (p < pend) { while (p < pend) {
star = 0; star = 0;
type = *p++; 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; star = 1;
len = send - s; len = send - s;
p++; p++;
@ -971,8 +1069,22 @@ pack_unpack(str, fmt)
while (t >= s) { while (t >= s) {
if (*t != ' ' && *t != '\0') break; if (*t != ' ' && *t != '\0') break;
t--; t--; len--;
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)); rb_ary_push(ary, rb_str_new(s, len));
s += end; s += end;
@ -985,6 +1097,7 @@ pack_unpack(str, fmt)
s += len; s += len;
break; break;
case 'b': case 'b':
{ {
VALUE bitstr; VALUE bitstr;
@ -1066,7 +1179,7 @@ pack_unpack(str, fmt)
break; break;
case 'c': case 'c':
PACK_LENGTH_ADJUST(char); PACK_LENGTH_ADJUST(char,sizeof(char));
while (len-- > 0) { while (len-- > 0) {
int c = *s++; int c = *s++;
if (c > (char)127) c-=256; if (c > (char)127) c-=256;
@ -1076,7 +1189,7 @@ pack_unpack(str, fmt)
break; break;
case 'C': case 'C':
PACK_LENGTH_ADJUST(char); PACK_LENGTH_ADJUST(unsigned char,sizeof(unsigned char));
while (len-- > 0) { while (len-- > 0) {
unsigned char c = *s++; unsigned char c = *s++;
rb_ary_push(ary, INT2FIX(c)); rb_ary_push(ary, INT2FIX(c));
@ -1085,29 +1198,29 @@ pack_unpack(str, fmt)
break; break;
case 's': case 's':
PACK_LENGTH_ADJUST(short); PACK_LENGTH_ADJUST(short,2);
while (len-- > 0) { while (len-- > 0) {
short tmp; short tmp;
memcpy(&tmp, s, sizeof(short)); memcpy(&tmp, s, NATINT_LEN(short,2));
s += sizeof(short); s += NATINT_LEN(short,2);
rb_ary_push(ary, INT2FIX(tmp)); rb_ary_push(ary, INT2FIX(tmp));
} }
PACK_ITEM_ADJUST(); PACK_ITEM_ADJUST();
break; break;
case 'S': case 'S':
PACK_LENGTH_ADJUST(short); PACK_LENGTH_ADJUST(unsigned short,2);
while (len-- > 0) { while (len-- > 0) {
unsigned short tmp; unsigned short tmp;
memcpy(&tmp, s, sizeof(short)); memcpy(&tmp, s, NATINT_LEN(unsigned short,2));
s += sizeof(short); s += NATINT_LEN(unsigned short,2);
rb_ary_push(ary, INT2FIX(tmp)); rb_ary_push(ary, INT2FIX(tmp));
} }
PACK_ITEM_ADJUST(); PACK_ITEM_ADJUST();
break; break;
case 'i': case 'i':
PACK_LENGTH_ADJUST(int); PACK_LENGTH_ADJUST(int,sizeof(int));
while (len-- > 0) { while (len-- > 0) {
int tmp; int tmp;
memcpy(&tmp, s, sizeof(int)); memcpy(&tmp, s, sizeof(int));
@ -1118,44 +1231,44 @@ pack_unpack(str, fmt)
break; break;
case 'I': case 'I':
PACK_LENGTH_ADJUST(int); PACK_LENGTH_ADJUST(unsigned int,sizeof(unsigned int));
while (len-- > 0) { while (len-- > 0) {
unsigned int tmp; unsigned int tmp;
memcpy(&tmp, s, sizeof(int)); memcpy(&tmp, s, sizeof(unsigned int));
s += sizeof(int); s += sizeof(unsigned int);
rb_ary_push(ary, rb_uint2inum(tmp)); rb_ary_push(ary, rb_uint2inum(tmp));
} }
PACK_ITEM_ADJUST(); PACK_ITEM_ADJUST();
break; break;
case 'l': case 'l':
PACK_LENGTH_ADJUST(long); PACK_LENGTH_ADJUST(long,4);
while (len-- > 0) { while (len-- > 0) {
long tmp; long tmp;
memcpy(&tmp, s, sizeof(long)); memcpy(&tmp, s, NATINT_LEN(long,4));
s += sizeof(long); s += NATINT_LEN(long,4);
rb_ary_push(ary, rb_int2inum(tmp)); rb_ary_push(ary, rb_int2inum(tmp));
} }
PACK_ITEM_ADJUST(); PACK_ITEM_ADJUST();
break; break;
case 'L': case 'L':
PACK_LENGTH_ADJUST(long); PACK_LENGTH_ADJUST(unsigned long,4);
while (len-- > 0) { while (len-- > 0) {
unsigned long tmp; unsigned long tmp;
memcpy(&tmp, s, sizeof(long)); memcpy(&tmp, s, NATINT_LEN(unsigned long,4));
s += sizeof(long); s += NATINT_LEN(unsigned long,4);
rb_ary_push(ary, rb_uint2inum(tmp)); rb_ary_push(ary, rb_uint2inum(tmp));
} }
PACK_ITEM_ADJUST(); PACK_ITEM_ADJUST();
break; break;
case 'n': case 'n':
PACK_LENGTH_ADJUST(short); PACK_LENGTH_ADJUST(unsigned short,2);
while (len-- > 0) { while (len-- > 0) {
unsigned short tmp; unsigned short tmp;
memcpy(&tmp, s, sizeof(short)); memcpy(&tmp, s, NATINT_LEN(unsigned short,2));
s += sizeof(short); s += NATINT_LEN(unsigned short,2);
tmp = ntohs(tmp); tmp = ntohs(tmp);
rb_ary_push(ary, rb_uint2inum(tmp)); rb_ary_push(ary, rb_uint2inum(tmp));
} }
@ -1163,11 +1276,11 @@ pack_unpack(str, fmt)
break; break;
case 'N': case 'N':
PACK_LENGTH_ADJUST(long); PACK_LENGTH_ADJUST(unsigned long,4);
while (len-- > 0) { while (len-- > 0) {
unsigned long tmp; unsigned long tmp;
memcpy(&tmp, s, sizeof(long)); memcpy(&tmp, s, NATINT_LEN(unsigned long,4));
s += sizeof(long); s += NATINT_LEN(unsigned long,4);
tmp = ntohl(tmp); tmp = ntohl(tmp);
rb_ary_push(ary, rb_uint2inum(tmp)); rb_ary_push(ary, rb_uint2inum(tmp));
} }
@ -1175,11 +1288,11 @@ pack_unpack(str, fmt)
break; break;
case 'v': case 'v':
PACK_LENGTH_ADJUST(short); PACK_LENGTH_ADJUST(unsigned short,2);
while (len-- > 0) { while (len-- > 0) {
unsigned short tmp; unsigned short tmp;
memcpy(&tmp, s, sizeof(short)); memcpy(&tmp, s, NATINT_LEN(unsigned short,2));
s += sizeof(short); s += NATINT_LEN(unsigned short,2);
tmp = vtohs(tmp); tmp = vtohs(tmp);
rb_ary_push(ary, rb_uint2inum(tmp)); rb_ary_push(ary, rb_uint2inum(tmp));
} }
@ -1187,11 +1300,11 @@ pack_unpack(str, fmt)
break; break;
case 'V': case 'V':
PACK_LENGTH_ADJUST(long); PACK_LENGTH_ADJUST(unsigned long,4);
while (len-- > 0) { while (len-- > 0) {
unsigned long tmp; unsigned long tmp;
memcpy(&tmp, s, sizeof(long)); memcpy(&tmp, s, NATINT_LEN(long,4));
s += sizeof(long); s += NATINT_LEN(long,4);
tmp = vtohl(tmp); tmp = vtohl(tmp);
rb_ary_push(ary, rb_uint2inum(tmp)); rb_ary_push(ary, rb_uint2inum(tmp));
} }
@ -1200,7 +1313,7 @@ pack_unpack(str, fmt)
case 'f': case 'f':
case 'F': case 'F':
PACK_LENGTH_ADJUST(float); PACK_LENGTH_ADJUST(float,sizeof(float));
while (len-- > 0) { while (len-- > 0) {
float tmp; float tmp;
memcpy(&tmp, s, sizeof(float)); memcpy(&tmp, s, sizeof(float));
@ -1211,7 +1324,7 @@ pack_unpack(str, fmt)
break; break;
case 'e': case 'e':
PACK_LENGTH_ADJUST(float); PACK_LENGTH_ADJUST(float,sizeof(float));
while (len-- > 0) { while (len-- > 0) {
float tmp; float tmp;
FLOAT_CONVWITH(ftmp); FLOAT_CONVWITH(ftmp);
@ -1225,7 +1338,7 @@ pack_unpack(str, fmt)
break; break;
case 'E': case 'E':
PACK_LENGTH_ADJUST(double); PACK_LENGTH_ADJUST(double,sizeof(double));
while (len-- > 0) { while (len-- > 0) {
double tmp; double tmp;
DOUBLE_CONVWITH(dtmp); DOUBLE_CONVWITH(dtmp);
@ -1240,7 +1353,7 @@ pack_unpack(str, fmt)
case 'D': case 'D':
case 'd': case 'd':
PACK_LENGTH_ADJUST(double); PACK_LENGTH_ADJUST(double,sizeof(double));
while (len-- > 0) { while (len-- > 0) {
double tmp; double tmp;
memcpy(&tmp, s, sizeof(double)); memcpy(&tmp, s, sizeof(double));
@ -1251,7 +1364,7 @@ pack_unpack(str, fmt)
break; break;
case 'g': case 'g':
PACK_LENGTH_ADJUST(float); PACK_LENGTH_ADJUST(float,sizeof(float));
while (len-- > 0) { while (len-- > 0) {
float tmp; float tmp;
FLOAT_CONVWITH(ftmp;) FLOAT_CONVWITH(ftmp;)
@ -1265,7 +1378,7 @@ pack_unpack(str, fmt)
break; break;
case 'G': case 'G':
PACK_LENGTH_ADJUST(double); PACK_LENGTH_ADJUST(double,sizeof(double));
while (len-- > 0) { while (len-- > 0) {
double tmp; double tmp;
DOUBLE_CONVWITH(dtmp); DOUBLE_CONVWITH(dtmp);
@ -1278,6 +1391,18 @@ pack_unpack(str, fmt)
PACK_ITEM_ADJUST(); PACK_ITEM_ADJUST();
break; 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': case 'u':
{ {
VALUE str = rb_str_new(0, (send - s)*3/4); 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')) else if (s < send && (s+1 == send || s[1] == '\n'))
s += 2; /* possible checksum byte */ s += 2; /* possible checksum byte */
} }
RSTRING(str)->ptr[total] = '\0';
RSTRING(str)->len = total; RSTRING(str)->len = total;
rb_ary_push(ary, str); rb_ary_push(ary, str);
} }
@ -1369,6 +1496,7 @@ pack_unpack(str, fmt)
*ptr++ = a << 2 | b >> 4; *ptr++ = a << 2 | b >> 4;
*ptr++ = b << 4 | c >> 2; *ptr++ = b << 4 | c >> 2;
} }
*ptr = '\0';
RSTRING(str)->len = ptr - RSTRING(str)->ptr; RSTRING(str)->len = ptr - RSTRING(str)->ptr;
rb_ary_push(ary, str); rb_ary_push(ary, str);
} }
@ -1395,6 +1523,7 @@ pack_unpack(str, fmt)
} }
s++; s++;
} }
*ptr = '\0';
RSTRING(str)->len = ptr - RSTRING(str)->ptr; RSTRING(str)->len = ptr - RSTRING(str)->ptr;
rb_ary_push(ary, str); rb_ary_push(ary, str);
} }
@ -1454,6 +1583,82 @@ pack_unpack(str, fmt)
return ary; 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 void
Init_pack() 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_BEG, /* ignore newline, +/- is a sign. */
EXPR_MID, /* newline significant, +/- is a sign. */ EXPR_MID, /* newline significant, +/- is a sign. */
EXPR_END, /* newline significant, +/- is a operator. */ EXPR_END, /* newline significant, +/- is a operator. */
EXPR_PAREN, /* almost like EXPR_END, `do' works as `{'. */
EXPR_ARG, /* newline significant, +/- is a operator. */ EXPR_ARG, /* newline significant, +/- is a operator. */
EXPR_FNAME, /* ignore newline, no reserved words. */ EXPR_FNAME, /* ignore newline, no reserved words. */
EXPR_DOT, /* right after `.' or `::', no reserved words. */ EXPR_DOT, /* right after `.' or `::', no reserved words. */
@ -139,6 +140,7 @@ static void top_local_setup();
kRETRY kRETRY
kIN kIN
kDO kDO
kDO2
kRETURN kRETURN
kYIELD kYIELD
kSUPER kSUPER
@ -1264,6 +1266,19 @@ brace_block : '{'
fixpos($$, $3?$3:$4); fixpos($$, $3?$3:$4);
dyna_pop($<vars>2); 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 generic_call : tIDENTIFIER
{ {
@ -1290,12 +1305,12 @@ block_call : generic_call do_block
fixpos($$, $2); fixpos($$, $2);
} }
method_call : operation '(' opt_call_args ')' method_call : operation '(' opt_call_args close_paren
{ {
$$ = new_fcall($1, $3); $$ = new_fcall($1, $3);
fixpos($$, $3); fixpos($$, $3);
} }
| primary '.' operation2 '(' opt_call_args ')' | primary '.' operation2 '(' opt_call_args close_paren
{ {
value_expr($1); value_expr($1);
$$ = new_call($1, $3, $5); $$ = new_call($1, $3, $5);
@ -1307,7 +1322,7 @@ method_call : operation '(' opt_call_args ')'
$$ = new_call($1, $3, 0); $$ = new_call($1, $3, 0);
fixpos($$, $1); fixpos($$, $1);
} }
| primary tCOLON2 operation2 '(' opt_call_args ')' | primary tCOLON2 operation2 '(' opt_call_args close_paren
{ {
value_expr($1); value_expr($1);
$$ = new_call($1, $3, $5); $$ = new_call($1, $3, $5);
@ -1318,7 +1333,7 @@ method_call : operation '(' opt_call_args ')'
value_expr($1); value_expr($1);
$$ = new_call($1, $3, 0); $$ = new_call($1, $3, 0);
} }
| kSUPER '(' opt_call_args ')' | kSUPER '(' opt_call_args close_paren
{ {
if (!compile_for_eval && !cur_mid && if (!compile_for_eval && !cur_mid &&
!in_single && !in_defined) !in_single && !in_defined)
@ -1333,6 +1348,10 @@ method_call : operation '(' opt_call_args ')'
$$ = NEW_ZSUPER(); $$ = NEW_ZSUPER();
} }
close_paren : ')'
{
lex_state = EXPR_PAREN;
}
stmt_rhs : block_call stmt_rhs : block_call
| command_call | command_call
@ -1701,6 +1720,9 @@ yycompile(f)
n = yyparse(); n = yyparse();
compile_for_eval = 0; compile_for_eval = 0;
ruby_in_compile = 0; ruby_in_compile = 0;
class_nest = 0;
in_single = 0;
cur_mid = 0;
if (n == 0) return ruby_eval_tree; if (n == 0) return ruby_eval_tree;
return 0; return 0;
@ -1909,7 +1931,7 @@ read_escape()
return c; return c;
case 'b': /* backspace */ case 'b': /* backspace */
return '\b'; return '\010';
case 's': /* space */ case 's': /* space */
return ' '; return ' ';
@ -2540,7 +2562,8 @@ yylex()
case '<': case '<':
c = nextc(); c = nextc();
if (c == '<' && 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)) { (lex_state != EXPR_ARG || space_seen)) {
int c2 = nextc(); int c2 = nextc();
int indent = 0; int indent = 0;
@ -2599,7 +2622,7 @@ yylex()
return parse_qstring(c,0); return parse_qstring(c,0);
case '?': case '?':
if (lex_state == EXPR_END) { if (lex_state == EXPR_END || lex_state == EXPR_PAREN) {
lex_state = EXPR_BEG; lex_state = EXPR_BEG;
return '?'; return '?';
} }
@ -2891,7 +2914,7 @@ yylex()
return tCOLON2; return tCOLON2;
} }
pushback(c); pushback(c);
if (lex_state == EXPR_END || ISSPACE(c)) { if (lex_state == EXPR_END || lex_state == EXPR_PAREN || ISSPACE(c)) {
lex_state = EXPR_BEG; lex_state = EXPR_BEG;
return ':'; return ':';
} }
@ -2973,7 +2996,9 @@ yylex()
return c; return c;
case '{': 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; c = tLBRACE;
lex_state = EXPR_BEG; lex_state = EXPR_BEG;
return c; return c;
@ -3186,6 +3211,9 @@ yylex()
if (state == EXPR_FNAME) { if (state == EXPR_FNAME) {
yylval.id = rb_intern(kw->name); yylval.id = rb_intern(kw->name);
} }
if (state == EXPR_PAREN && kw->id[0] == kDO) {
return kDO2;
}
return kw->id[state != EXPR_BEG]; return kw->id[state != EXPR_BEG];
} }
} }

View file

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

View file

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

14
ruby.h
View file

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

View file

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

View file

@ -2439,9 +2439,17 @@ rb_str_oct(str)
{ {
int base = 8; int base = 8;
if (RSTRING(str)->len > 2 && RSTRING(str)->ptr[0] == '0' && if (RSTRING(str)->len > 2 && RSTRING(str)->ptr[0] == '0') {
(RSTRING(str)->ptr[1] == 'x' || RSTRING(str)->ptr[1] == 'X')) { switch (RSTRING(str)->ptr[1]) {
base = 16; case 'x':
case 'X':
base = 16;
break;
case 'b':
case 'B':
base = 2;
break;
}
} }
return rb_str2inum(RSTRING(str)->ptr, base); 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(); RCLASS(klass)->iv_tbl = st_init_numtable();
} }
else if (st_lookup(RCLASS(klass)->iv_tbl, id, 0)) { else if (st_lookup(RCLASS(klass)->iv_tbl, id, 0)) {
rb_raise(rb_eNameError, "already initialized constant %s", rb_warn("already initialized constant %s", rb_id2name(id));
rb_id2name(id));
} }
st_add_direct(RCLASS(klass)->iv_tbl, id, val); st_insert(RCLASS(klass)->iv_tbl, id, val);
} }
void void

View file

@ -18,20 +18,29 @@
void void
Init_version() Init_version()
{ {
rb_define_global_const("VERSION", rb_str_new2(RUBY_VERSION)); VALUE v = rb_str_new2(RUBY_VERSION);
rb_define_global_const("RELEASE_DATE", rb_str_new2(RUBY_RELEASE_DATE)); VALUE d = rb_str_new2(RUBY_RELEASE_DATE);
rb_define_global_const("PLATFORM", rb_str_new2(RUBY_PLATFORM)); 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 void
ruby_show_version() 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 void
ruby_show_copyright() ruby_show_copyright()
{ {
fprintf(stderr, "ruby - Copyright (C) 1993-1999 Yukihiro Matsumoto\n"); printf("ruby - Copyright (C) 1993-1999 Yukihiro Matsumoto\n");
exit(0); exit(0);
} }

View file

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