git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@520 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 1999-08-13 05:45:20 +00:00
parent fcd020c830
commit 65a5162550
156 changed files with 21888 additions and 18301 deletions

1844
ChangeLog

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,5 @@
COPYING COPYING
COPYING.LIB
ChangeLog ChangeLog
MANIFEST MANIFEST
Makefile.in Makefile.in
@ -28,10 +29,7 @@ env.h
error.c error.c
eval.c eval.c
file.c file.c
fnmatch.c
fnmatch.h
gc.c gc.c
glob.c
hash.c hash.c
inits.c inits.c
install-sh install-sh
@ -50,6 +48,7 @@ object.c
pack.c pack.c
parse.c parse.c
parse.y parse.y
prec.c
process.c process.c
random.c random.c
range.c range.c
@ -77,14 +76,16 @@ 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.nt ext/Setup.nt
ext/Setup.x68 ext/Setup.x68
ext/aix_ld.rb ext/aix_mksym.rb
ext/cygwin32_ld.rb ext/mswin32_extmk.rb
ext/extmk.rb.in ext/extmk.rb.in
ext/extmk.rb.nt lib/CGI.rb
lib/English.rb lib/English.rb
lib/Env.rb lib/Env.rb
lib/README lib/README
@ -142,16 +143,24 @@ missing/crypt.c
missing/dir.h missing/dir.h
missing/dup2.c missing/dup2.c
missing/file.h missing/file.h
missing/finite.c
missing/flock.c missing/flock.c
missing/fnmatch.c
missing/fnmatch.h
missing/isinf.c
missing/isnan.c
missing/memcmp.c missing/memcmp.c
missing/memmove.c missing/memmove.c
missing/mkdir.c missing/mkdir.c
missing/os2.c
missing/strcasecmp.c missing/strcasecmp.c
missing/strncasecmp.c
missing/strchr.c missing/strchr.c
missing/strdup.c missing/strdup.c
missing/strerror.c missing/strerror.c
missing/strftime.c missing/strftime.c
missing/strstr.c missing/strstr.c
missing/strtod.c
missing/strtol.c missing/strtol.c
missing/strtoul.c missing/strtoul.c
missing/vsnprintf.c missing/vsnprintf.c
@ -163,6 +172,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
@ -196,6 +207,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
@ -206,6 +218,7 @@ sample/tsvr.rb
sample/uumerge.rb sample/uumerge.rb
win32/Makefile win32/Makefile
win32/config.h win32/config.h
win32/config.status
win32/ntsetup.bat win32/ntsetup.bat
win32/ruby.def win32/ruby.def
win32/sdbm.c win32/sdbm.c

View file

@ -14,105 +14,115 @@ AUTOCONF = autoconf
prefix = @prefix@ prefix = @prefix@
CFLAGS = @CFLAGS@ -I. -I@srcdir@ -I@includedir@ CFLAGS = @CFLAGS@ -I. -I@srcdir@ -I@includedir@
LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@ LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@
XLDFLAGS = @XLDFLAGS@
EXTLIBS = EXTLIBS =
LIBS = @LIBS@ $(EXTLIBS) LIBS = @LIBS@ $(EXTLIBS)
MISSING = @LIBOBJS@ @ALLOCA@ MISSING = @LIBOBJS@ @ALLOCA@
LDSHARED = @LDSHARED@ LDSHARED = @LIBRUBY_LDSHARED@
DLDFLAGS = @DLDFLAGS@ DLDFLAGS = @LIBRUBY_DLDFLAGS@
SOLIBS = @SOLIBS@ SOLIBS = @SOLIBS@
binsuffix = @binsuffix@ RUBY_INSTALL_NAME=@RUBY_INSTALL_NAME@
EXEEXT = @EXEEXT@
PROGRAM=$(RUBY_INSTALL_NAME)$(EXEEXT)
#### End of system configuration section. #### #### End of system configuration section. ####
MAJOR= @MAJOR@
MINOR= @MINOR@
TEENY= @TEENY@
LIBRUBY_A = @LIBRUBY_A@
LIBRUBY_SO = @LIBRUBY_SO@
LIBRUBY_ALIASES= @LIBRUBY_ALIASES@
LIBRUBY = @LIBRUBY@ LIBRUBY = @LIBRUBY@
LIBRUBYARG = @LIBRUBYARG@ LIBRUBYARG = @LIBRUBYARG@
EXTOBJS = EXTOBJS =
MAINOBJ = main.o MAINOBJ = main.@OBJEXT@
OBJS = array.o \ OBJS = array.@OBJEXT@ \
bignum.o \ bignum.@OBJEXT@ \
class.o \ class.@OBJEXT@ \
compar.o \ compar.@OBJEXT@ \
dir.o \ dir.@OBJEXT@ \
dln.o \ dln.@OBJEXT@ \
enum.o \ enum.@OBJEXT@ \
error.o \ error.@OBJEXT@ \
eval.o \ eval.@OBJEXT@ \
file.o \ file.@OBJEXT@ \
fnmatch.o \ gc.@OBJEXT@ \
gc.o \ hash.@OBJEXT@ \
glob.o \ inits.@OBJEXT@ \
hash.o \ io.@OBJEXT@ \
inits.o \ marshal.@OBJEXT@ \
io.o \ math.@OBJEXT@ \
marshal.o \ numeric.@OBJEXT@ \
math.o \ object.@OBJEXT@ \
numeric.o \ pack.@OBJEXT@ \
object.o \ parse.@OBJEXT@ \
pack.o \ process.@OBJEXT@ \
parse.o \ prec.@OBJEXT@ \
process.o \ random.@OBJEXT@ \
random.o \ range.@OBJEXT@ \
range.o \ re.@OBJEXT@ \
re.o \ regex.@OBJEXT@ \
regex.o \ ruby.@OBJEXT@ \
ruby.o \ signal.@OBJEXT@ \
signal.o \ sprintf.@OBJEXT@ \
sprintf.o \ st.@OBJEXT@ \
st.o \ string.@OBJEXT@ \
string.o \ struct.@OBJEXT@ \
struct.o \ time.@OBJEXT@ \
time.o \ util.@OBJEXT@ \
util.o \ variable.@OBJEXT@ \
variable.o \ version.@OBJEXT@ \
version.o \
$(MISSING) $(MISSING)
all: miniruby$(binsuffix) rbconfig.rb all: miniruby$(EXEEXT) rbconfig.rb
@./miniruby$(binsuffix) -Xext extmk.rb @EXTSTATIC@ @./miniruby$(EXEEXT) -Xext extmk.rb @EXTSTATIC@
miniruby$(binsuffix): libruby.a $(MAINOBJ) dmyext.o miniruby$(EXEEXT): config.status $(LIBRUBY_A) $(MAINOBJ) dmyext.@OBJEXT@
@rm -f $@ @rm -f $@
$(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) dmyext.o libruby.a $(LIBS) -o $@ $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) dmyext.@OBJEXT@ $(LIBRUBY_A) $(LIBS) -o $@
ruby$(binsuffix): $(LIBRUBY) $(MAINOBJ) $(EXTOBJS) $(PROGRAM): $(LIBRUBY) $(MAINOBJ) $(EXTOBJS)
@rm -f $@ @rm -f $@
$(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) -o $@ $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) -o $@
libruby.a: $(OBJS) dmyext.o $(LIBRUBY_A): $(OBJS) dmyext.@OBJEXT@
@AR@ rcu $@ $(OBJS) dmyext.o @AR@ rcu $@ $(OBJS) dmyext.@OBJEXT@
@-@RANLIB@ $@ 2> /dev/null || true @-@RANLIB@ $@ 2> /dev/null || true
libruby.so: $(OBJS) dmyext.o $(LIBRUBY_SO): $(OBJS) dmyext.@OBJEXT@
$(LDSHARED) $(DLDFLAGS) $(SOLIBS) $(OBJS) dmyext.o -o $@ $(LDSHARED) $(DLDFLAGS) $(SOLIBS) $(OBJS) dmyext.@OBJEXT@ -o $@
@-./miniruby -e 'ARGV.each{|link| File.delete link if File.exist? link; \
File.symlink "$(LIBRUBY_SO)", link}' \
$(LIBRUBY_ALIASES) || true
install: rbconfig.rb install: rbconfig.rb
./miniruby$(binsuffix) $(srcdir)/instruby.rb $(DESTDIR) ./miniruby$(EXEEXT) $(srcdir)/instruby.rb $(DESTDIR)
clean:; @rm -f $(OBJS) $(LIBRUBY) $(MAINOBJ) rbconfig.rb clean:; @rm -f $(OBJS) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY_ALIASES) $(MAINOBJ) rbconfig.rb
@rm -f ext/extinit.c ext/extinit.o dmyext.o @rm -f ext/extinit.c ext/extinit.@OBJEXT@ dmyext.@OBJEXT@
@if test -f ./miniruby$(binsuffix); then \ @-./miniruby$(EXEEXT) -Xext extmk.rb clean 2> /dev/null || true
./miniruby$(binsuffix) -Xext extmk.rb clean; \ @rm -f $(PROGRAM) miniruby$(EXEEXT)
fi
distclean: clean distclean: clean
@rm -f Makefile ext/extmk.rb config.h @rm -f Makefile ext/extmk.rb config.h
@rm -f ext/config.cache config.cache config.log config.status @rm -f ext/config.cache config.cache config.log config.status
@rm -f parse.c *~ core *.core gmon.out y.tab.c y.output @rm -f *~ core *.core gmon.out y.tab.c y.output ruby.imp
@rm -f ruby$(binsuffix) miniruby$(binsuffix)
realclean: distclean realclean: distclean
@rm -f parse.c
@rm -f lex.c @rm -f lex.c
test: miniruby$(binsuffix) test: miniruby$(EXEEXT)
@./miniruby$(binsuffix) $(srcdir)/rubytest.rb @./miniruby$(EXEEXT) $(srcdir)/rubytest.rb
rbconfig.rb: config.status miniruby$(binsuffix) rbconfig.rb: miniruby$(EXEEXT)
@./miniruby$(binsuffix) $(srcdir)/mkconfig.rb rbconfig.rb @./miniruby$(EXEEXT) $(srcdir)/mkconfig.rb rbconfig.rb
config.status: $(srcdir)/configure config.status: $(srcdir)/configure
$(SHELL) ./config.status --recheck $(SHELL) ./config.status --recheck
@ -120,7 +130,7 @@ config.status: $(srcdir)/configure
$(srcdir)/configure: $(srcdir)/configure.in $(srcdir)/configure: $(srcdir)/configure.in
cd $(srcdir) && $(AUTOCONF) cd $(srcdir) && $(AUTOCONF)
.c.o: .c.@OBJEXT@:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
lex.c: keywords lex.c: keywords
@ -130,100 +140,123 @@ parse.c: parse.y
$(YACC) $< $(YACC) $<
mv -f y.tab.c parse.c mv -f y.tab.c parse.c
alloca.o: @srcdir@/missing/alloca.c alloca.@OBJEXT@: @srcdir@/missing/alloca.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/alloca.c $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/alloca.c
crypt.o: @srcdir@/missing/crypt.c crypt.@OBJEXT@: @srcdir@/missing/crypt.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/crypt.c $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/crypt.c
dup2.o: @srcdir@/missing/dup2.c dup2.@OBJEXT@: @srcdir@/missing/dup2.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/dup2.c $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/dup2.c
flock.o: @srcdir@/missing/flock.c finite.@OBJEXT@: @srcdir@/missing/finite.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/finite.c
flock.@OBJEXT@: @srcdir@/missing/flock.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/flock.c $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/flock.c
memcmp.o: @srcdir@/missing/memcmp.c isinf.@OBJEXT@: @srcdir@/missing/isinf.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/isinf.c
isnan.@OBJEXT@: @srcdir@/missing/isnan.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/isnan.c
fnmatch.@OBJEXT@: @srcdir@/missing/fnmatch.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/fnmatch.c
memcmp.@OBJEXT@: @srcdir@/missing/memcmp.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/memcmp.c $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/memcmp.c
memmove.o: @srcdir@/missing/memmove.c memmove.@OBJEXT@: @srcdir@/missing/memmove.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/memmove.c $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/memmove.c
mkdir.o: @srcdir@/missing/mkdir.c mkdir.@OBJEXT@: @srcdir@/missing/mkdir.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/mkdir.c $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/mkdir.c
vsnprintf.o: @srcdir@/missing/vsnprintf.c vsnprintf.@OBJEXT@: @srcdir@/missing/vsnprintf.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/vsnprintf.c $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/vsnprintf.c
strcasecmp.o: @srcdir@/missing/strcasecmp.c strcasecmp.@OBJEXT@: @srcdir@/missing/strcasecmp.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strcasecmp.c $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strcasecmp.c
strchr.o: @srcdir@/missing/strchr.c strncasecmp.@OBJEXT@: @srcdir@/missing/strncasecmp.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strncasecmp.c
strchr.@OBJEXT@: @srcdir@/missing/strchr.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strchr.c $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strchr.c
strdup.o: @srcdir@/missing/strdup.c strdup.@OBJEXT@: @srcdir@/missing/strdup.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strdup.c $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strdup.c
strerror.o: @srcdir@/missing/strerror.c strerror.@OBJEXT@: @srcdir@/missing/strerror.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strerror.c $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strerror.c
strftime.o: @srcdir@/missing/strftime.c strftime.@OBJEXT@: @srcdir@/missing/strftime.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strftime.c $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strftime.c
strstr.o: @srcdir@/missing/strstr.c strstr.@OBJEXT@: @srcdir@/missing/strstr.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strstr.c $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strstr.c
strtol.o: @srcdir@/missing/strtol.c strtod.@OBJEXT@: @srcdir@/missing/strtod.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strtod.c
strtol.@OBJEXT@: @srcdir@/missing/strtol.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strtol.c $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strtol.c
strtoul.o: @srcdir@/missing/strtoul.c strtoul.@OBJEXT@: @srcdir@/missing/strtoul.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strtoul.c $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strtoul.c
nt.o: @srcdir@/missing/nt.c nt.@OBJEXT@: @srcdir@/missing/nt.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/nt.c $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/nt.c
x68.o: @srcdir@/missing/x68.c x68.@OBJEXT@: @srcdir@/missing/x68.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/x68.c $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/x68.c
os2.@OBJEXT@: @srcdir@/missing/os2.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/os2.c
dl_os2.@OBJEXT@: @srcdir@/missing/dl_os2.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/dl_os2.c
# Prevent GNU make v3 from overflowing arg limit on SysV. # Prevent GNU make v3 from overflowing arg limit on SysV.
.NOEXPORT: .NOEXPORT:
### ###
parse.o: parse.y ruby.h config.h defines.h intern.h env.h node.h st.h regex.h util.h lex.c parse.@OBJEXT@: parse.y ruby.h config.h defines.h intern.h env.h node.h st.h regex.h util.h lex.c
### ###
array.o: array.c ruby.h config.h defines.h intern.h array.@OBJEXT@: array.c ruby.h config.h defines.h intern.h
bignum.o: bignum.c ruby.h config.h defines.h intern.h bignum.@OBJEXT@: bignum.c ruby.h config.h defines.h intern.h
class.o: class.c ruby.h config.h defines.h intern.h node.h st.h class.@OBJEXT@: class.c ruby.h config.h defines.h intern.h node.h st.h
compar.o: compar.c ruby.h config.h defines.h intern.h compar.@OBJEXT@: compar.c ruby.h config.h defines.h intern.h
dir.o: dir.c ruby.h config.h defines.h intern.h dir.@OBJEXT@: dir.c ruby.h config.h defines.h intern.h
dln.o: dln.c config.h defines.h dln.h dln.@OBJEXT@: dln.c config.h defines.h dln.h
dmyext.o: dmyext.c dmyext.@OBJEXT@: dmyext.c
enum.o: enum.c ruby.h config.h defines.h intern.h enum.@OBJEXT@: enum.c ruby.h config.h defines.h intern.h
error.o: error.c ruby.h config.h defines.h intern.h env.h error.@OBJEXT@: error.c ruby.h config.h defines.h intern.h env.h
eval.o: eval.c ruby.h config.h defines.h intern.h node.h env.h rubysig.h st.h dln.h eval.@OBJEXT@: eval.c ruby.h config.h defines.h intern.h node.h env.h rubysig.h st.h dln.h
file.o: file.c ruby.h config.h defines.h intern.h rubyio.h rubysig.h file.@OBJEXT@: file.c ruby.h config.h defines.h intern.h rubyio.h rubysig.h
fnmatch.o: fnmatch.c config.h fnmatch.h gc.@OBJEXT@: gc.c ruby.h config.h defines.h intern.h rubysig.h st.h node.h env.h re.h regex.h
gc.o: gc.c ruby.h config.h defines.h intern.h rubysig.h st.h node.h env.h re.h regex.h hash.@OBJEXT@: hash.c ruby.h config.h defines.h intern.h st.h rubysig.h util.h
glob.o: config.h glob.c fnmatch.h inits.@OBJEXT@: inits.c ruby.h config.h defines.h intern.h
hash.o: hash.c ruby.h config.h defines.h intern.h st.h rubysig.h io.@OBJEXT@: io.c ruby.h config.h defines.h intern.h rubyio.h rubysig.h env.h
inits.o: inits.c ruby.h config.h defines.h intern.h main.@OBJEXT@: main.c ruby.h config.h defines.h intern.h
io.o: io.c ruby.h config.h defines.h intern.h rubyio.h rubysig.h marshal.@OBJEXT@: marshal.c ruby.h config.h defines.h intern.h rubyio.h st.h
main.o: main.c ruby.h config.h defines.h intern.h prec.@OBJEXT@: prec.c ruby.h config.h defines.h intern.h
marshal.o: marshal.c ruby.h config.h defines.h intern.h rubyio.h st.h math.@OBJEXT@: math.c ruby.h config.h defines.h intern.h
math.o: math.c ruby.h config.h defines.h intern.h numeric.@OBJEXT@: numeric.c ruby.h config.h defines.h intern.h
numeric.o: numeric.c ruby.h config.h defines.h intern.h object.@OBJEXT@: object.c ruby.h config.h defines.h intern.h st.h
object.o: object.c ruby.h config.h defines.h intern.h st.h pack.@OBJEXT@: pack.c ruby.h config.h defines.h intern.h
pack.o: pack.c ruby.h config.h defines.h intern.h process.@OBJEXT@: process.c ruby.h config.h defines.h intern.h rubysig.h st.h
process.o: process.c ruby.h config.h defines.h intern.h rubysig.h st.h random.@OBJEXT@: random.c ruby.h config.h defines.h intern.h
random.o: random.c ruby.h config.h defines.h intern.h range.@OBJEXT@: range.c ruby.h config.h defines.h intern.h
range.o: range.c ruby.h config.h defines.h intern.h re.@OBJEXT@: re.c ruby.h config.h defines.h intern.h re.h regex.h
re.o: re.c ruby.h config.h defines.h intern.h re.h regex.h regex.@OBJEXT@: regex.c config.h regex.h util.h
regex.o: regex.c config.h regex.h util.h ruby.@OBJEXT@: ruby.c ruby.h config.h defines.h intern.h dln.h util.h
ruby.o: ruby.c ruby.h config.h defines.h intern.h dln.h util.h signal.@OBJEXT@: signal.c ruby.h config.h defines.h intern.h rubysig.h
signal.o: signal.c ruby.h config.h defines.h intern.h rubysig.h sprintf.@OBJEXT@: sprintf.c ruby.h config.h defines.h intern.h
sprintf.o: sprintf.c ruby.h config.h defines.h intern.h st.@OBJEXT@: st.c config.h st.h
st.o: st.c config.h st.h string.@OBJEXT@: string.c ruby.h config.h defines.h intern.h re.h regex.h
string.o: string.c ruby.h config.h defines.h intern.h re.h regex.h struct.@OBJEXT@: struct.c ruby.h config.h defines.h intern.h
struct.o: struct.c ruby.h config.h defines.h intern.h time.@OBJEXT@: time.c ruby.h config.h defines.h intern.h
time.o: time.c ruby.h config.h defines.h intern.h util.@OBJEXT@: util.c ruby.h config.h defines.h intern.h util.h
util.o: util.c ruby.h config.h defines.h intern.h util.h variable.@OBJEXT@: variable.c ruby.h config.h defines.h intern.h env.h node.h st.h
variable.o: variable.c ruby.h config.h defines.h intern.h env.h node.h st.h version.@OBJEXT@: version.c ruby.h config.h defines.h intern.h version.h
version.o: version.c ruby.h config.h defines.h intern.h version.h

26
README
View file

@ -20,10 +20,28 @@ Perl). It is simple, straight-forward, and extensible.
* How to get Ruby * How to get Ruby
The Ruby distribution can be found on The Ruby distribution can be found on:
ftp://ftp.netlab.co.jp/pub/lang/ruby/ ftp://ftp.netlab.co.jp/pub/lang/ruby/
You can get it by anonymous CVS. How to check out is:
$ cvs -d :pserver:anonymous@cvs.netlab.co.jp:/home/cvs login
(Logging in to anonymous@cvs.netlab.co.jp)
CVS password: guest
$ cvs -d :pserver:anonymous@cvs.netlab.co.jp:/home/cvs checkout ruby
* Mailing list
There is a mailing list to talk about Ruby.
To subscribe this list, please send the following phrase
subscribe Your-Last-Name Your-First-Name
e.g.
subscribe Joseph Smith
in the mail body (not subject) to the address <ruby-talk-ctl@netlab.co.jp>.
* How to compile and install * How to compile and install
This is what you need to do to compile and install Ruby: This is what you need to do to compile and install Ruby:
@ -98,9 +116,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], fnmatch.[ch], They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
glob.c, st.[ch] and some files under the ./missing directory. See files under the ./missing directory. See each file for the copying
each file for the 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

@ -1,8 +1,8 @@
.\" README.EXT - -*- Text -*- created at: Mon Aug 7 16:45:54 JST 1995 .\" README.EXT - -*- Text -*- created at: Mon Aug 7 16:45:54 JST 1995
This document explains how to make extention modules for Ruby. This document explains how to make extention libraries for Ruby.
1Basic knowledge 1. Basic knowledge
In C, variables have types and data do not have types. In contrast, In C, variables have types and data do not have types. In contrast,
Ruby variables do not have static type and data themselves have Ruby variables do not have static type and data themselves have
@ -109,35 +109,29 @@ bugs.
1.4 Convert C data into VALUE 1.4 Convert C data into VALUE
VALUEの実際の構造は To convert C data to the values of Ruby:
* FIXNUMの場合 * FIXNUM
1bit右シフトしてLSBを立てる left shift 1 bit, and turn on LSB.
* その他のポインタの場合 * Other pointer values
そのままVALUEにキャストする cast to VALUE.
となっていますよってLSBをチェックすればVALUEがFIXNUMかど You can determine whether VALUE is pointer or not, by checking LSB.
うかわかるわけです(ポインタのLSBが立っていないことを仮定して
いる)
ですからFIXNUM以外のRubyのオブジェクトの構造体は単にVALUE Notice Ruby does not allow arbitrary pointer value to be VALUE. They
にキャストするだけでVALUEに変換出来ますただし任意の構造 should be pointers to the structures which Ruby knows. The known
体がVALUEにキャスト出来るわけではありませんキャストするの structures are defined in <ruby.h>.
はRubyの知っている構造体(ruby.hで定義されているstruct RXxxx
のもの)だけにしておいてください.
FIXNUMに関しては変換マクロを経由する必要がありますCの整数 To convert C numbers to Ruby value, use these macros.
からVALUEに変換するマクロは以下のものがあります必要に応じ
て使い分けてください.
INT2FIX() もとの整数が31bit以内に収まる時 INT2FIX() for intergers within 31bits.
INT2NUM() 任意の整数からVALUEへ INT2NUM() for arbitrary sized integer.
INT2NUM()は整数がFIXNUMの範囲に収まらない場合Bignumに変換 INT2NUM() converts integers into Bignums, if it is out of FIXNUM
してくれます(が,少し遅い) range, but bit slower.
1.5 Manipulate Ruby data 1.5 Manipulate Ruby data
@ -190,23 +184,15 @@ interpreter. Useful functions are listed below (not all):
2. Extend Ruby with C 2. Extend Ruby with C
原理的にRubyで書けることはCでも書けますRubyそのものがCで記
述されているんですから,当然といえば当然なんですけど.ここで
はRubyの拡張に使うことが多いだろうと予測される機能を中心に紹
介します.
2.1 Add new features to Ruby 2.1 Add new features to Ruby
Rubyで提供されている関数を使えばRubyインタプリタに新しい機能 You can add new features (classes, methods, etc.) to the Ruby
を追加することができますRubyでは以下の機能を追加する関数が interpreter. Ruby provides the API to define things below:
提供されています.
* Classes, Modules * Classes, Modules
* Methods, Singleton Methods * Methods, Singleton Methods
* Constants * Constants
では順に紹介します.
2.1.1 Class/module definition 2.1.1 Class/module definition
To define class or module, use functions below: To define class or module, use functions below:
@ -327,9 +313,9 @@ by the symbol mid.
2.2.4 Accessing the variables and constants 2.2.4 Accessing the variables and constants
Cから関数を使って参照・更新できるのはクラス定数インスタ You can access class variables, and instance variables using access
ンス変数です大域変数は一部のものはCの大域変数としてアクセ functions. Also, global variables can be shared between both worlds.
スできます.ローカル変数を参照する方法は公開していません. There's no way to access Ruby's local variables.
The functions to access/modify instance variables are below: The functions to access/modify instance variables are below:
@ -346,9 +332,7 @@ See 2.1.3 for defining new constant.
3. Informatin sharing between Ruby and C 3. Informatin sharing between Ruby and C
C言語とRubyの間で情報を共有する方法について解説します 3.1 Ruby constant that C can be accessed from C
3.1 Ruby constant that Cから参照できるRubyの定数
Following Ruby constants can be referred from C. Following Ruby constants can be referred from C.
@ -363,43 +347,35 @@ Ruby nil in C scope.
3.2 Global variables shared between C and Ruby 3.2 Global variables shared between C and Ruby
CとRubyで大域変数を使って情報を共有できます共有できる大域 Information can be shared between two worlds, using shared global
変数にはいくつかの種類があります.そのなかでもっとも良く使わ variables. To define them, you can use functions listed below:
れると思われるのはrb_define_variable()です.
void rb_define_variable(char *name, VALUE *var) void rb_define_variable(char *name, VALUE *var)
この関数はRubyとCとで共有する大域変数を定義します変数名が This function defines the variable which is shared by the both world.
`$'で始まらない時には自動的に追加されます.この変数の値を変 The value of the global variable pointerd by `var', can be accessed
更すると自動的にRubyの対応する変数の値も変わります through Ruby's global variable named `name'.
またRuby側からは更新できない変数もありますこのread onlyの You can define read-only (from Ruby, of course) variable by the
変数は以下の関数で定義します. function below.
void rb_define_readonly_variable(char *name, VALUE *var) void rb_define_readonly_variable(char *name, VALUE *var)
これら変数の他にhookをつけた大域変数を定義できますhook付き You can defined hooked variables. The accessor functions (getter and
の大域変数は以下の関数を用いて定義しますhook付き大域変数の setter) are called on access to the hooked variables.
値の参照や設定はhookで行う必要があります
void rb_define_hooked_variable(char *name, VALUE *var, void rb_define_hooked_variable(char *name, VALUE *var,
VALUE (*getter)(), VALUE (*setter)()) VALUE (*getter)(), VALUE (*setter)())
この関数はCの関数によってhookのつけられた大域変数を定義しま If you need to supply either setter or getter, just supply 0 for the
変数が参照された時には関数getterが変数に値がセットされ hook you don't need. If both hooks are 0, rb_define_hooked_variable()
た時には関数setterが呼ばれるhookを指定しない場合はgetterや works just like rb_define_variable().
setterに0を指定します
# getterもsetterも0ならばrb_define_variable()と同じになる.
それからCの関数によって実現されるRubyの大域変数を定義する
関数があります.
void rb_define_virtual_variable(char *name, void rb_define_virtual_variable(char *name,
VALUE (*getter)(), VALUE (*setter)()) VALUE (*getter)(), VALUE (*setter)())
この関数によって定義されたRubyの大域変数が参照された時には This function defines the Ruby global variable without corresponding C
getterが変数に値がセットされた時にはsetterが呼ばれます variable. The value of the variable will be set/get only by hooks.
The prototypes of the getter and setter functions are as following: The prototypes of the getter and setter functions are as following:
@ -408,54 +384,44 @@ The prototypes of the getter and setter functions are as following:
3.3 Encapsulate C data into Ruby object 3.3 Encapsulate C data into Ruby object
Cの世界で定義されたデータ(構造体)をRubyのオブジェクトとして To wrapping and objectify the C pointer as Ruby object (so called
取り扱いたい場合がありえますこのような場合にはDataという DATA), use Data_Wrap_Struct().
RubyオブジェクトにCの構造体(へのポインタ)をくるむことでRuby
オブジェクトとして取り扱えるようになります.
Dataオブジェクトを生成して構造体をRubyオブジェクトにカプセル
化するためには,以下のマクロを使います.
Data_Wrap_Struct(class,mark,free,ptr) Data_Wrap_Struct(class,mark,free,ptr)
このマクロの戻り値は生成されたDataオブジェクトです Data_Wrap_Struct() returns a created DATA object. The class argument
is the class for the DATA object. The mark argument is the function
to mark Ruby objects pointed by this data. The free argument is the
function to free the pointer allocation. The functions, mark and
free, will be called from garbage collector.
classはこのDataオブジェクトのクラスですptrはカプセル化する You can allocate and wrap the structure in one step.
Cの構造体へのポインタですmarkはこの構造体がRubyのオブジェ
クトへの参照がある時に使う関数です.そのような参照を含まない
時には0を指定します
# そのような参照は勧められません.
freeはこの構造体がもう不要になった時に呼ばれる関数ですこの
関数がガーベージコレクタから呼ばれます.
Cの構造体の割当とDataオブジェクトの生成を同時に行うマクロと
して以下のものが提供されています.
Data_Make_Struct(class, type, mark, free, sval) Data_Make_Struct(class, type, mark, free, sval)
このマクロの戻り値は生成されたDataオブジェクトです This macro returns an allocated Data object, wrapping the pointer to
the structure, which is also allocated. This macro works like:
class, mark, freeはData_Wrap_Structと同じ働きをしますtype (sval = ALLOC(type), Data_Wrap_Struct(class, mark, free, sval))
は割り当てるC構造体の型です割り当てられた構造体は変数sval
に代入されます.この変数の型は (type*) である必要があります.
Dataオブジェクトからポインタを取り出すのは以下のマクロを用い Arguments, class, mark, free, works like thier counterpart of
ます. Data_Wrap_Struct(). The pointer to allocated structure will be
assigned to sval, which should be the pointer to the type specified.
To retrieve the C pointer from the Data object, use the macro
Data_Get_Struct().
Data_Get_Struct(obj, type, sval) Data_Get_Struct(obj, type, sval)
Cの構造体へのポインタは変数svalに代入されます The pointer to the structure will be assigned to the variable sval.
これらのDataの使い方はちょっと分かりにくいので後で説明する See example below for detail.
例題を参照してください.
4Example - Create dbm module 4. Example - Creating dbm extension
ここまでの説明でとりあえず拡張ライブラリは作れるはずです. OK, here's the example to make extension library. This is the
Rubyのextディレクトリにすでに含まれているdbmモジュールを例に extension to access dbm. The full source is included in ext/
して段階的に説明します. directory in the Ruby's source tree.
(1) make the directory (1) make the directory
@ -477,17 +443,17 @@ You need to design the library features, before making it.
(4) write C code. (4) write C code.
拡張ライブラリ本体となるC言語のソースを書きますC言語のソー You need to write C code for your extension library. If your library
スがひとつの時には「モジュール名.c」を選ぶと良いでしょうC has only one source file, choosing ``LIBRARY.c'' as a file name is
言語のソースが複数の場合には逆に「モジュール名.c」というファ preferred. On the other hand, in case your library has prural source
イル名は避ける必要があります.オブジェクトファイルとモジュー files, avoid chooing ``LIBRARY.c'' for a file name. It may conflict
ル生成時に中間的に生成される「モジュール名.o」というファイル with intermediate file ``LIBRARY.o'' on some platforms.
とが衝突するからです.
Rubyは拡張ライブラリをロードする時に「Init_モジュール名」と Ruby will execute the initializing function named ``Init_LIBRARY'' in
いう関数を自動的に実行しますdbmモジュールの場合「Init_dbm」 the library. For exapmle, ``Init_dbm()'' will be executed when loading
です.この関数の中でクラス,モジュール,メソッド,定数などの the library.
定義を行いますdbm.cから一部引用します
Here's the example of an initializing function.
-- --
Init_dbm() Init_dbm()
@ -509,11 +475,7 @@ Init_dbm()
} }
-- --
DBMモジュールはdbmのデータと対応するオブジェクトになるはずで The dbm extension wrap dbm struct in C world using Data_Make_Struct.
すからCの世界のdbmをRubyの世界に取り込む必要があります
dbm.cではData_Make_Structを以下のように使っています
-- --
struct dbmdata { struct dbmdata {
@ -525,12 +487,10 @@ struct dbmdata {
obj = Data_Make_Struct(class,struct dbmdata,0,free_dbm,dbmp); obj = Data_Make_Struct(class,struct dbmdata,0,free_dbm,dbmp);
-- --
ここではdbmstruct構造体へのポインタをDataにカプセル化してい This code wraps dbmdata structure into Ruby object. We avoid wrapping
ますDBM*を直接カプセル化しないのはclose()した時の処理を考 DBM* directly, because we want to cache size information.
えてのことです.
Dataオブジェクトからdbmstruct構造体のポインタを取り出すため To retrieve dbmdata structure from Ruby object, we define the macro below:
に以下のマクロを使っています.
-- --
#define GetDBM(obj, dbmp) {\ #define GetDBM(obj, dbmp) {\
@ -539,14 +499,11 @@ Data
} }
-- --
ちょっと複雑なマクロですが要するにdbmdata構造体のポインタ This sort of complicated macro do the retrieving and close check for
の取り出しとcloseされているかどうかのチェックをまとめてい the DBM.
るだけです.
DBMクラスにはたくさんメソッドがありますが分類すると3種類の There are three kind of way to receiving method arguments. First, the
引数の受け方があります.ひとつは引数の数が固定のもので,例と methods with fixed number of arguments receives arguments like this:
してはdeleteメソッドがありますdeleteメソッドを実装している
fdbm_delete()はこのようになっています.
-- --
static VALUE static VALUE
@ -557,13 +514,11 @@ fdbm_delete(obj, keystr)
} }
-- --
引数の数が固定のタイプは第1引数がself第2引数以降がメソッド The first argument of the C function is the self, the rest are the
の引数となります. arguments to the method.
引数の数が不定のものはCの配列で受けるものとRubyの配列で受け Second, the methods with arbtrary number of arguments receives
るものとがありますdbmモジュールの中でCの配列で受けるもの arguments like this:
はDBMのクラスメソッドであるopen()です.これを実装している関
数fdbm_s_open()はこうなっています.
-- --
static VALUE static VALUE
@ -580,36 +535,28 @@ fdbm_s_open(argc, argv, class)
} }
-- --
このタイプの関数は第1引数が与えられた引数の数第2引数が与え The first argument is the number of method arguments. the second
られた引数の入っている配列になりますselfは第3引数として与 argument is the C array of the method arguments. And the third
えられます. argument is the receiver of the method.
この配列で与えられた引数を解析するための関数がopen()でも使わ You can use the function rb_scan_args() to check and retrieve the
れているrb_scan_args()です第3引数に指定したフォーマットに arguments. For exapmle "11" means, the method requires at least one
従い第4変数以降に指定した変数に値を代入してくれますこの argument, and at most receives two arguments.
フォーマットは第1文字目が省略できない引数の数第2文字目が
省略できる引数の数第3文字目が対応する相手が無いあまりの引
数があるかどうかを示す"*"です2文字目と3文字目は省略できま
dbm.cの例ではフォーマットは"11"ですから引数は最低1つ
2つまで許されるという意味になります省略されている時の
変数の値はnil(C言語のレベルではQnil)になります.
Rubyの配列で引数を受け取るものはindexesがあります実装はこ The methods with arbtrary number of arguments can receives arguments
うです. by Ruby's array, like this:
-- --
static VALUE static VALUE
fdbm_indexes(obj, args) fdbm_indexes(obj, args)
VALUE obj; VALUE obj, args;
struct RArray *args;
{ {
: :
} }
-- --
第1引数はself第2引数はRubyの配列ですここではキャストを減 The first argument is the receiver, the second one is the Ruby array
らすため struct RArray* で受けていますがVALUEでも同じこと which contains the arguments to the method.
です.
** Notice ** Notice
@ -620,72 +567,82 @@ not exported to the Ruby world. You need to protect them by
(5) prepare extconf.rb (5) prepare extconf.rb
もしディレクトリに「extconf.rb」というファイルが存在すれば If there exists the file named extconf.rb, it will be executed to
make時に実行されますなければ適当にMakefileが生成されます generate Makefile. If not, compilation scheme try to generate
Makefile anyway.
extconf.rbはモジュールのコンパイルに必要な条件のチェックなど The extconf.rb is the file to check compilation condition etc. You
を行うことが目的ですextconf.rbの中では以下のRuby関数を使う need to put
ことが出来ます.
have_library(lib, func): ライブラリの存在チェック require 'mkmf'
have_func(func): 関数の存在チェック
have_header(header): ヘッダファイルの存在チェック
create_makefile(target): Makefileの生成
以下の変数を使うことができます. at the top of the file. You can use the funcitons below to check the
condition.
$CFLAGS: コンパイル時に追加的に指定するフラグ(-Iなど) have_library(lib, func): check whether library containing function exists.
$LDFLAGS: リンク時に追加的に指定するフラグ(-Lなど) have_func(func): check whether function exists
have_header(header): check whether header file exists
create_makefile(target): generate Makefile
モジュールをコンパイルする条件が揃わなず,そのモジュールはコ The value of variables below will affect Makefile.
ンパイルしない時にはcreate_makefileを呼ばなければMakefileは
生成されず,コンパイルも行われません. $CFLAGS: included in CFLAGS make variable (such as -I)
$LDFLAGS: included in LDFLAGS make variable (such as -L)
If compilation condition is not fulfilled, you do not call
``create_makefile''. Makefile will not generated, compilation will
not be done.
(6) prepare depend (optional) (6) prepare depend (optional)
もしディレクトリにdependというファイルが存在すれば If the file named depend exists, Makefile will include that file to
Makefileが依存関係をチェックしてくれます check dependency. You can make this file by invoking
% gcc -MM *.c > depend % gcc -MM *.c > depend
などで作ることが出来ます.あって損は無いでしょう. It's no harm. Prepare it.
(7) MANIFESTファイルにファイル名を入れる (7) put file names into MANIFEST (optional)
% ls > MANIFEST % find * -type f -print > MANIFEST
% vi MANIFEST % vi MANIFEST
*.o, *~など不必要なファイル以外はMANIFESTに追加しておきます Append file names into MANIFEST. The compilation scheme requires
make時にはMANIFESTの内容は参照しませんので空のままでも問題 MANIFEST only to be exist. But, you'd better take this step to
は起きませんが,パッケージングの時に参照することがあるのと, distinguish required files.
必要なファイルを区別できるので,用意しておいた方が良いでしょ
う.
(8) make (8) generate Makefile
Rubyのディレクトリでmakeを実行するとMakefileを生成からmake Try generate Makefile by:
必要によってはそのモジュールのRubyへのリンクまで自動的に実行
してくれますextconf.rbを書き換えるなどしてMakefileの再生成 ruby extconf.rb
が必要な時はまたRubyディレクトリでmakeしてください
You don't need this step, if you put extension library under ext
directory of the ruby source tree. In that case, compilation of the
interpreter will do this step for you.
(9) make
Type
make
to compile your extension. You don't need this step neither, if you
put extension library under ext directory of the ruby source tree.
(9) debug (9) debug
You may need to rb_debug the module. The modules can be linked You may need to rb_debug the extension. The extensions can be linked
statically by adding directory name in the ext/Setup file, statically by adding directory name in the ext/Setup file, so that you
so that you can inspect the module by the debugger. can inspect the extension with the debugger.
(10) done, now you have the extension library (10) done, now you have the extension library
後はこっそり使うなり,広く公開するなり,売るなり,ご自由にお You can do anything you want with your library. The author of Ruby
使いくださいRubyの作者は拡張ライブラリに関して一切の権利を will not claim any restriction about your code depending Ruby API.
主張しません. Feel free to use, modify, distribute or sell your program.
Appendix A. Rubyのソースコードの分類 Appendix A. Ruby source files overview
Rubyのソースはいくつかに分類することが出来ますこのうちクラ
スライブラリの部分は基本的に拡張ライブラリと同じ作り方になっ
ています.これらのソースは今までの説明でほとんど理解できると
思います.
ruby language core ruby language core
@ -737,18 +694,15 @@ class library
struct.c struct.c
time.c time.c
Appendix B. 拡張用関数リファレンス Appendix B. Ruby extension API reference
C言語からRubyの機能を利用するAPIは以下の通りである ** Types
** 型
VALUE VALUE
Rubyオブジェクトを表現する型必要に応じてキャストして用いる The type for Ruby object. Actual structures are defined in ruby.h,
組み込み型を表現するCの型はruby.hに記述してあるRで始まる構造 such as struct RString, etc. To refer the values in structures, use
体であるVALUE型をこれらにキャストするためにRで始まる構造体 casting macros like RSTRING(obj).
名を全て大文字にした名前のマクロが用意されている.
** Variables and constants ** Variables and constants
@ -758,58 +712,58 @@ const: nil object
Qtrue Qtrue
const: Qtrue object(default true value) const: true object(default true value)
Qfalse Qfalse
const: Qfalse object const: false object
** Cデータのカプセル化 ** C pointer wrapping
Data_Wrap_Struct(VALUE class, void (*mark)(), void (*free)(), void *sval) Data_Wrap_Struct(VALUE class, void (*mark)(), void (*free)(), void *sval)
Cの任意のポインタをカプセル化したRubyオブジェクトを返す Wrap C pointer into Ruby object. If object has references to other
のポインタがRubyからアクセスされなくなった時freeで指定した Ruby object, they should be marked by using mark function during GC
関数が呼ばれるまたこのポインタの指すデータが他のRubyオブ process. Otherwise, mark should be 0. When this object is no longer
ジェクトを指している場合markに指定する関数でマークする必要 referred by anywhere, the pointer will be discarded by free function.
がある.
Data_Make_Struct(class, type, mark, free, sval) Data_Make_Struct(class, type, mark, free, sval)
type型のメモリをmallocし変数svalに代入した後それをカプセ This macro allocates memory using malloc(), assigns it to the variable
ル化したデータを返すマクロ. sval, and returns the DATA encapsulating the pointer to memory region.
Data_Get_Struct(data, type, sval) Data_Get_Struct(data, type, sval)
dataからtype型のポインタを取り出し変数svalに代入するマクロ This macro retrieves the pointer value from DATA, and assigns it to
the variable sval.
** クラス/モジュール定義 ** defining class/module
VALUE rb_define_class(char *name, VALUE super) VALUE rb_define_class(char *name, VALUE super)
superのサブクラスとして新しいRubyクラスを定義する Defines new Ruby class as subclass of super.
VALUE rb_define_class_under(VALUE module, char *name, VALUE super) VALUE rb_define_class_under(VALUE module, char *name, VALUE super)
superのサブクラスとして新しいRubyクラスを定義しmoduleの定 Creates new Ruby class as subclass of super, under the module's
数として定義する. namespace.
VALUE rb_define_module(char *name) VALUE rb_define_module(char *name)
新しいRubyモジュールを定義する Defines new Ruby module.
VALUE rb_define_module_under(VALUE module, char *name, VALUE super) VALUE rb_define_module_under(VALUE module, char *name, VALUE super)
新しいRubyモジュールを定義しmoduleの定数として定義する Defines new Ruby module, under the modules's namespace.
void rb_include_module(VALUE class, VALUE module) void rb_include_module(VALUE class, VALUE module)
モジュールをインクルードするclassがすでにmoduleをインクルー Includes module into class. If class already includes it, just
ドしている時には何もしない(多重インクルードの禁止) ignore.
void rb_extend_object(VALUE object, VALUE module) void rb_extend_object(VALUE object, VALUE module)
オブジェクトをモジュール(で定義されているメソッド)で拡張する. Extend the object with module's attribute.
** Defining Global Variables ** Defining Global Variables
@ -871,115 +825,118 @@ Defines global contant. This is just work as
rb_define_method(VALUE class, char *name, VALUE (*func)(), int argc) rb_define_method(VALUE class, char *name, VALUE (*func)(), int argc)
メソッドを定義するargcはselfを除く引数の数argcが-1の時, Defines a method for the class. func is the function pointer. argc
関数には引数の数(selfを含まない)を第1引数, 引数の配列を第2引 is the number of arguments. if argc is -1, the function will receive
数とする形式で与えられる(第3引数はself)argcが-2の時, 第1引 3 arguments argc, argv, and self. if argc is -2, the function will
数がself, 第2引数がargs(argsは引数を含むRubyの配列)という形 receive 2 arguments, self and args, where args is the Ruby array of
式で与えられる. the method arguments.
rb_define_private_method(VALUE class, char *name, VALUE (*func)(), int argc) rb_define_private_method(VALUE class, char *name, VALUE (*func)(), int argc)
privateメソッドを定義する引数はrb_define_method()と同じ. Defines a private method for the class. Arguments are same as
rb_define_method().
rb_define_singleton_method(VALUE class, char *name, VALUE (*func)(), int argc) rb_define_singleton_method(VALUE class, char *name, VALUE (*func)(), int argc)
特異メソッドを定義する引数はrb_define_method()と同じ. Defines a singleton method. Arguments are same as rb_define_method().
rb_scan_args(int atgc, VALUE *argv, char *fmt, ...) rb_scan_args(int argc, VALUE *argv, char *fmt, ...)
argc,argv形式で与えられた引数を分解するfmtは必須引数の数, Retrieve argument from argc, argv. The fmt is the format string for
付加引数の数, 残りの引数があるかを指定する文字列で, "数字数 the arguments, such as "12" for 1 non-optinal argument, 2 optinal
字*"という形式である. 2 番目の数字と"*"はそれぞれ省略可能で aruguments. If `*' appears at the end of fmt, it means the rest of
ある必須引数が一つもない場合は0を指定する第3引数以降は変 the arguments are assigned to corresponding variable, packed in
数へのポインタで, 該当する要素がその変数に格納される.付加引 array.
数に対応する引数が与えられていない場合は変数にQnilが代入され
る.
** Rubyメソッド呼び出し ** Invoking Ruby method
VALUE rb_funcall(VALUE recv, ID mid, int narg, ...) VALUE rb_funcall(VALUE recv, ID mid, int narg, ...)
メソッド呼び出し文字列からmidを得るためにはrb_intern()を使う. Invokes the method. To retrieve mid from method name, use rb_intern().
VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv) VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv)
メソッド呼び出し引数をargc,argv形式で渡す Invokes method, passing arguments by array of values.
VALUE rb_eval_string(char *str) VALUE rb_eval_string(char *str)
文字列をRubyとスクリプトしてコンパイル・実行する Compiles and executes the string as Ruby program.
ID rb_intern(char *name) ID rb_intern(char *name)
文字列に対応するIDを返す Returns ID corresponding the name.
char *rb_id2name(ID id) char *rb_id2name(ID id)
IDに対応する文字列を返す(デバッグ用) Returns the name corresponding ID.
char *rb_class2name(VALUE class) char *rb_class2name(VALUE class)
classの名前を返す(デバッグ用)classが名前を持たない時には, Returns the name of the class.
祖先を遡って名前を持つクラスの名前を返す.
** インスタンス変数 ** Instance Variables
VALUE rb_iv_get(VALUE obj, char *name) VALUE rb_iv_get(VALUE obj, char *name)
objのインスタンス変数の値を得る`@'で始まらないインスタンス Retrieve the value of the instance variable. If the name is not
変数は Rubyプログラムからアクセスできない「隠れた」インスタ prefixed by `@', that variable shall be inaccessible from Ruby.
ンス変数になる.
VALUE rb_iv_set(VALUE obj, char *name, VALUE val) VALUE rb_iv_set(VALUE obj, char *name, VALUE val)
objのインスタンス変数をvalにセットする Sets the value of the instance variable.
** 制御構造 ** Control Structure
VALUE rb_iterate(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2) VALUE rb_iterate(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2)
func2をブロックとして設定し, func1をイテレータとして呼ぶ Calls the function func1, supplying func2 as the block. func1 will be
func1には arg1が引数として渡され, func2には第1引数にイテレー called with the argument arg1. func2 receives the value from yield as
タから与えられた値, 第2引数にarg2が渡される the first argument, arg2 as the second argument.
VALUE rb_yield(VALUE val) VALUE rb_yield(VALUE val)
valを値としてイテレータブロックを呼び出す Evaluates the block with value val.
VALUE rb_rescue(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2) VALUE rb_rescue(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2)
関数func1をarg1を引数に呼び出すfunc1の実行中に例外が発生し Calls the function func1, with arg1 as the argument. If exception
た時には func2をarg2を引数として呼ぶ戻り値は例外が発生しな occurs during func1, it calls func2 with arg2 as the argument. The
かった時はfunc1の戻り値, 例外が発生した時にはfunc2の戻り値で return value of rb_rescue() is the return value from func1 if no
ある. exception occurs, from func2 otherwise.
VALUE rb_ensure(VALUE (*func1)(), void *arg1, void (*func2)(), void *arg2) VALUE rb_ensure(VALUE (*func1)(), void *arg1, void (*func2)(), void *arg2)
関数func1をarg1を引数として実行し, 実行終了後(たとえ例外が発 Calls the function func1 with arg1 as the argument, then calls func2
生しても) func2をarg2を引数として実行する戻り値はfunc1の戻 with arg2, whenever execution terminated. The return value from
り値である(例外が発生した時は戻らない) rb_ensure() is that of func1.
** 例外・エラー ** Exceptions and Errors
void rb_warn(char *fmt, ...)
Prints warning message according to the printf-like format.
void rb_warning(char *fmt, ...) void rb_warning(char *fmt, ...)
rb_verbose時に標準エラー出力に警告情報を表示する引数はprintf()と同じ. Prints warning message according to the printf-like format, if
$VERBOSE is true.
void rb_raise(rb_eRuntimeError, char *fmt, ...) void rb_raise(VALUE exception, char *fmt, ...)
例外を発生させる引数はprintf()と同じ. Raises an exception of class exception. The fmt is the format string
just like printf().
void rb_fatal(char *fmt, ...) void rb_fatal(char *fmt, ...)
致命的例外を発生させる.通常の例外処理は行なわれず, インター Raises fatal error, terminates the interpreter. No exception handling
プリタが終了する(ただしensureで指定されたコードは終了前に実 will be done for fatal error, but ensure blocks will be executed.
行される)
void rb_bug(char *fmt, ...) void rb_bug(char *fmt, ...)
インタープリタなどプログラムのバグでしか発生するはずのない状 Termintates the interpreter immediately. This function should be
況の時呼ぶ.インタープリタはコアダンプし直ちに終了する.例外 called under the situation caused by the bug in the interpreter. No
処理は一切行なわれない. exception handling nor ensure execution will be done.
** Initialize and Starts the Interpreter ** Initialize and Starts the Interpreter
@ -999,8 +956,7 @@ Specifies the name of the script ($0).
Appendix B. Functions Available in extconf.rb Appendix B. Functions Available in extconf.rb
extconf.rbの中では利用可能なコンパイル条件チェックの関数は以 These functions are available in extconf.rb:
下の通りである.
have_library(lib, func) have_library(lib, func)
@ -1024,6 +980,6 @@ this method, the compilation will not be done.
/* /*
* Local variables: * Local variables:
* fill-column: 60 * fill-column: 70
* end: * end:
*/ */

1168
README.EXT.jp Normal file

File diff suppressed because it is too large Load diff

View file

@ -32,24 +32,45 @@ Ruby
ftp://ftp.netlab.co.jp/pub/lang/ruby/ ftp://ftp.netlab.co.jp/pub/lang/ruby/
** CVSで
$ cvs -d :pserver:anonymous@cvs.netlab.co.jp:/home/cvs login
(Logging in to anonymous@cvs.netlab.co.jp)
CVS password: guest
$ cvs -d :pserver:anonymous@cvs.netlab.co.jp:/home/cvs checkout 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-ctl@netlab.co.jp
です.このアドレスにメールを送れば,自動的に登録されます. まで本文に
subscribe YourFirstName YourFamilyName
と書いて送って下さい。
Ruby開発者向けメーリングリストもあります。こちらではrubyのバ
グ、将来の仕様拡張など実装上の問題について議論されています。
参加希望の方は
ruby-dev-ctl@netlab.co.jp
までruby-listと同様の方法でメールしてください。
Ruby拡張モジュールについて話し合うruby-extメーリングリストと
英語で話し合うruby-talkメーリングリストもあります。参加方法
はどれも同じです。
* コンパイル・インストール * コンパイル・インストール
@ -142,22 +163,21 @@ Licence)
(b) 機械可読なソースコードを添付する. (b) 機械可読なソースコードを添付する.
(c) 変更を行ったバイナリは名前を変更したうえ,ソースの (c) 変更を行ったバイナリは名前を変更したうえ,オリジナ
入手法を明示する. ルのソースコードの入手法を明示する.
(d) その他の配布条件を作者と合意する. (d) その他の配布条件を作者と合意する.
4. 他のプログラムへの引用はいかなる目的であれ自由です.た 4. 他のプログラムへの引用はいかなる目的であれ自由です.た
だしRubyに含まれる他の作者によるコードはそれぞれの だしRubyに含まれる他の作者によるコードはそれぞれの
作者の意向による制限が加えられます具体的にはgc.c(一部) 作者の意向による制限が加えられます具体的にはgc.c(一部)
util.c(一部)st.[ch]regex.[ch], fnmatch.[ch], glob.c util.c(一部)st.[ch]regex.[ch] および. /missingディ
および./missingディレクトリ下のファイル群が該当します レクトリ下のファイル群が該当します.それぞれの配布条件
それぞれの配布条件などに付いては各ファイルを参照してく などに付いては各ファイルを参照してください.
ださい.
5. Rubyへの入力となるスクリプトおよびRubyからの出力の権 5. Rubyへの入力となるスクリプトおよびRubyからの出力の権
利はRubyの作者ではなくそれぞれの入出力を生成した人に 利はRubyの作者ではなくそれぞれの入出力を生成した人に
属しますまたRubyに組み込むための拡張モジュールにつ 属しますまたRubyに組み込むための拡張ライブラリにつ
いても同様です. いても同様です.
6. Rubyは無保証です作者はRubyをサポートする意志はありま 6. Rubyは無保証です作者はRubyをサポートする意志はありま

33
ToDo
View file

@ -1,8 +1,17 @@
Language Spec. Language Spec.
* compile time string concatenation, "hello" "world" => "helloworld"
* ../... outside condition invokes operator method too.
* %w(a\ b\ c abc) => ["a b c", "abc"]
* package or access control for global variables * package or access control for global variables
* named arguments like foo(nation:="german"). * class variable (prefix?)
* multiple return values, yield values. maybe imcompatible * named arguments like foo(nation:="german") or foo(nation: "german").
* method to retrieve argument information (need new C API)
* multiple return values, yield values. maybe incompatible ???
* cascading method invocation ???
* def Class#method .. end ??
* class Foo::Bar<Baz .. end, module Boo::Bar .. end
* def Foo::Bar::baz() .. end ??
Hacking Interpreter Hacking Interpreter
@ -12,17 +21,28 @@ Hacking Interpreter
* remove rb_eval() recursions * remove rb_eval() recursions
* syntax tree -> bytecode ??? * syntax tree -> bytecode ???
* scrambled script, or script filter * scrambled script, or script filter
* regular expression bug /(?:\s+\d+){2}/ URGENT!! * setuid ruby
Standard Libraries
* Struct::new([name,]member,...) ??
* String#scanf(?)
* Object#fmt(?)
* Time::strptime
* Integer[num], Float[num]; Fixnum[num]?
* method to detect non-number trailer for to_i/to_f.
* Stream or Port, abstract superclass of IO ?
* String#{pred,prev}, String#downto
* optional stepsize argument for succ()
Extension Libraries Extension Libraries
* mod_ruby, FastCGI ruby * FastCGI ruby
* InterBase module
* ptk.rb pTk wrapper that is compatible to tk.rb * ptk.rb pTk wrapper that is compatible to tk.rb
Ruby Libraries Ruby Libraries
* CGI.rb * net/pop.rb net/smtp.rb
* httplib.rb, urllib.rb, nttplib.rb, etc. * httplib.rb, urllib.rb, nttplib.rb, etc.
* format like perl's * format like perl's
@ -33,5 +53,4 @@ Tools
Misc Misc
* translate README.EXT fully into English
* publish Ruby books * publish Ruby books

268
array.c
View file

@ -6,7 +6,7 @@
$Date$ $Date$
created at: Fri Aug 6 09:46:12 JST 1993 created at: Fri Aug 6 09:46:12 JST 1993
Copyright (C) 1993-1998 Yukihiro Matsumoto Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/ ************************************************/
@ -49,7 +49,7 @@ rb_ary_modify(ary)
rb_raise(rb_eTypeError, "can't modify frozen array"); rb_raise(rb_eTypeError, "can't modify frozen array");
if (FL_TEST(ary, ARY_TMPLOCK)) if (FL_TEST(ary, ARY_TMPLOCK))
rb_raise(rb_eTypeError, "can't modify array during sort"); rb_raise(rb_eTypeError, "can't modify array during sort");
if (rb_safe_level() >= 4 && !FL_TEST(ary, FL_TAINT)) if (!FL_TEST(ary, FL_TAINT) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify array"); rb_raise(rb_eSecurityError, "Insecure: can't modify array");
} }
@ -72,7 +72,7 @@ rb_ary_frozen_p(ary)
VALUE VALUE
rb_ary_new2(len) rb_ary_new2(len)
size_t len; long len;
{ {
NEWOBJ(ary, struct RArray); NEWOBJ(ary, struct RArray);
OBJSETUP(ary, rb_cArray, T_ARRAY); OBJSETUP(ary, rb_cArray, T_ARRAY);
@ -86,6 +86,7 @@ rb_ary_new2(len)
ary->len = 0; ary->len = 0;
ary->capa = len; ary->capa = len;
ary->ptr = 0; ary->ptr = 0;
if (len == 0) len++;
ary->ptr = ALLOC_N(VALUE, len); ary->ptr = ALLOC_N(VALUE, len);
return (VALUE)ary; return (VALUE)ary;
@ -107,16 +108,16 @@ rb_ary_new()
VALUE VALUE
#ifdef HAVE_STDARG_PROTOTYPES #ifdef HAVE_STDARG_PROTOTYPES
rb_ary_new3(size_t n, ...) rb_ary_new3(long n, ...)
#else #else
rb_ary_new3(n, va_alist) rb_ary_new3(n, va_alist)
size_t n; long n;
va_dcl va_dcl
#endif #endif
{ {
va_list ar; va_list ar;
VALUE ary; VALUE ary;
size_t i; long i;
if (n < 0) { if (n < 0) {
rb_raise(rb_eIndexError, "negative number of items(%d)", n); rb_raise(rb_eIndexError, "negative number of items(%d)", n);
@ -135,7 +136,7 @@ rb_ary_new3(n, va_alist)
VALUE VALUE
rb_ary_new4(n, elts) rb_ary_new4(n, elts)
size_t n; long n;
VALUE *elts; VALUE *elts;
{ {
VALUE ary; VALUE ary;
@ -169,7 +170,7 @@ rb_ary_s_new(argc, argv, klass)
VALUE *argv; VALUE *argv;
VALUE klass; VALUE klass;
{ {
size_t len = 0; long len = 0;
VALUE size, val; VALUE size, val;
NEWOBJ(ary, struct RArray); NEWOBJ(ary, struct RArray);
OBJSETUP(ary, klass, T_ARRAY); OBJSETUP(ary, klass, T_ARRAY);
@ -180,7 +181,7 @@ rb_ary_s_new(argc, argv, klass)
ary->capa = ARY_DEFAULT_SIZE; ary->capa = ARY_DEFAULT_SIZE;
} }
else { else {
size_t capa = NUM2UINT(size); long capa = NUM2LONG(size);
if (capa < 0) { if (capa < 0) {
rb_raise(rb_eArgError, "negative array size"); rb_raise(rb_eArgError, "negative array size");
@ -194,7 +195,6 @@ rb_ary_s_new(argc, argv, klass)
ary->ptr = ALLOC_N(VALUE, ary->capa); ary->ptr = ALLOC_N(VALUE, ary->capa);
memfill(ary->ptr, len, val); memfill(ary->ptr, len, val);
ary->len = len; ary->len = len;
rb_obj_call_init((VALUE)ary);
return (VALUE)ary; return (VALUE)ary;
} }
@ -208,8 +208,7 @@ rb_ary_s_create(argc, argv, klass)
NEWOBJ(ary, struct RArray); NEWOBJ(ary, struct RArray);
OBJSETUP(ary, klass, T_ARRAY); OBJSETUP(ary, klass, T_ARRAY);
ary->len = argc; ary->len = ary->capa = 0;
ary->capa = argc;
if (argc == 0) { if (argc == 0) {
ary->ptr = 0; ary->ptr = 0;
} }
@ -217,6 +216,7 @@ rb_ary_s_create(argc, argv, klass)
ary->ptr = ALLOC_N(VALUE, argc); ary->ptr = ALLOC_N(VALUE, argc);
MEMCPY(ary->ptr, argv, VALUE, argc); MEMCPY(ary->ptr, argv, VALUE, argc);
} }
ary->len = ary->capa = argc;
return (VALUE)ary; return (VALUE)ary;
} }
@ -224,19 +224,24 @@ rb_ary_s_create(argc, argv, klass)
void void
rb_ary_store(ary, idx, val) rb_ary_store(ary, idx, val)
VALUE ary; VALUE ary;
size_t idx; long idx;
VALUE val; VALUE val;
{ {
rb_ary_modify(ary); rb_ary_modify(ary);
if (idx < 0) { if (idx < 0) {
idx = RARRAY(ary)->len + idx; idx += RARRAY(ary)->len;
if (idx < 0) { if (idx < 0) {
rb_raise(rb_eIndexError, "negative index of array"); rb_raise(rb_eIndexError, "index %d out of array",
idx - RARRAY(ary)->len);
} }
} }
if (idx >= RARRAY(ary)->capa) { if (idx >= RARRAY(ary)->capa) {
RARRAY(ary)->capa = idx + ARY_DEFAULT_SIZE; long capa_inc = RARRAY(ary)->capa / 2;
if (capa_inc < ARY_DEFAULT_SIZE) {
capa_inc = ARY_DEFAULT_SIZE;
}
RARRAY(ary)->capa = idx + capa_inc;
REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa); REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
} }
if (idx > RARRAY(ary)->len) { if (idx > RARRAY(ary)->len) {
@ -310,7 +315,11 @@ rb_ary_unshift(ary, item)
{ {
rb_ary_modify(ary); rb_ary_modify(ary);
if (RARRAY(ary)->len >= RARRAY(ary)->capa) { if (RARRAY(ary)->len >= RARRAY(ary)->capa) {
RARRAY(ary)->capa+=ARY_DEFAULT_SIZE; long capa_inc = RARRAY(ary)->capa / 2;
if (capa_inc < ARY_DEFAULT_SIZE) {
capa_inc = ARY_DEFAULT_SIZE;
}
RARRAY(ary)->capa+=capa_inc;
REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa); REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
} }
@ -326,7 +335,7 @@ rb_ary_unshift(ary, item)
VALUE VALUE
rb_ary_entry(ary, offset) rb_ary_entry(ary, offset)
VALUE ary; VALUE ary;
size_t offset; long offset;
{ {
if (RARRAY(ary)->len == 0) return Qnil; if (RARRAY(ary)->len == 0) return Qnil;
@ -341,25 +350,25 @@ rb_ary_entry(ary, offset)
} }
static VALUE static VALUE
rb_ary_subseq(ary, beg, len) rb_ary_subary(ary, beg, len)
VALUE ary; VALUE ary;
size_t beg, len; long beg, len;
{ {
VALUE ary2; VALUE ary2;
if (len <= 0) { if (beg > RARRAY(ary)->len) return Qnil;
return rb_ary_new2(0);
}
if (beg < 0) { if (beg < 0) {
len += beg; len += beg;
beg = 0; beg = 0;
} }
if (len < 0) return Qnil;
if (beg + len > RARRAY(ary)->len) { if (beg + len > RARRAY(ary)->len) {
len = RARRAY(ary)->len - beg; len = RARRAY(ary)->len - beg;
} }
if (len < 0) { if (len < 0) {
len = 0; len = 0;
} }
if (len == 0) return rb_ary_new2(0);
ary2 = rb_ary_new2(len); ary2 = rb_ary_new2(len);
MEMCPY(RARRAY(ary2)->ptr, RARRAY(ary)->ptr+beg, VALUE, len); MEMCPY(RARRAY(ary2)->ptr, RARRAY(ary)->ptr+beg, VALUE, len);
@ -368,39 +377,6 @@ rb_ary_subseq(ary, beg, len)
return ary2; return ary2;
} }
static VALUE
beg_len(range, begp, lenp, len)
VALUE range;
size_t *begp, *lenp;
size_t len;
{
size_t beg, end;
size_t b, e;
if (!rb_range_beg_end(range, &beg, &end)) return Qfalse;
b = beg; e = end;
if (beg < 0) {
beg = len + beg;
}
if (end < 0) {
end = len + end;
}
if (beg > end) {
rb_raise(rb_eIndexError, "end smaller than beg [%d..%d]", b, e);
}
*begp = beg;
if (beg > len) {
*lenp = 0;
}
else {
len = end - beg +1;
*lenp = len;
}
return Qtrue;
}
VALUE VALUE
rb_ary_aref(argc, argv, ary) rb_ary_aref(argc, argv, ary)
int argc; int argc;
@ -408,29 +384,36 @@ rb_ary_aref(argc, argv, ary)
VALUE ary; VALUE ary;
{ {
VALUE arg1, arg2; VALUE arg1, arg2;
size_t beg, len; long beg, len;
if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) { if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
beg = NUM2UINT(arg1); beg = NUM2LONG(arg1);
len = NUM2UINT(arg2); len = NUM2LONG(arg2);
if (beg < 0) { if (beg < 0) {
beg = RARRAY(ary)->len + beg; beg = RARRAY(ary)->len + beg;
} }
return rb_ary_subseq(ary, beg, len); return rb_ary_subary(ary, beg, len);
} }
/* special case - speeding up */ /* special case - speeding up */
if (FIXNUM_P(arg1)) { if (FIXNUM_P(arg1)) {
return rb_ary_entry(ary, FIX2UINT(arg1)); return rb_ary_entry(ary, FIX2LONG(arg1));
} }
else if (TYPE(arg1) == T_BIGNUM) { else if (TYPE(arg1) == T_BIGNUM) {
rb_raise(rb_eIndexError, "index too big"); rb_raise(rb_eIndexError, "index too big");
} }
else if (beg_len(arg1, &beg, &len, RARRAY(ary)->len)) { else {
/* check if idx is Range */ /* check if idx is Range */
return rb_ary_subseq(ary, beg, len); switch (rb_range_beg_len(arg1, &beg, &len, RARRAY(ary)->len, 0)) {
case Qfalse:
break;
case Qnil:
return Qnil;
default:
return rb_ary_subary(ary, beg, len);
}
} }
return rb_ary_entry(ary, NUM2UINT(arg1)); return rb_ary_entry(ary, NUM2LONG(arg1));
} }
static VALUE static VALUE
@ -438,11 +421,11 @@ rb_ary_index(ary, val)
VALUE ary; VALUE ary;
VALUE val; VALUE val;
{ {
size_t i; long i;
for (i=0; i<RARRAY(ary)->len; i++) { for (i=0; i<RARRAY(ary)->len; i++) {
if (rb_equal(RARRAY(ary)->ptr[i], val)) if (rb_equal(RARRAY(ary)->ptr[i], val))
return INT2FIX(i); return INT2NUM(i);
} }
return Qnil; return Qnil;
} }
@ -452,11 +435,11 @@ rb_ary_rindex(ary, val)
VALUE ary; VALUE ary;
VALUE val; VALUE val;
{ {
size_t i = RARRAY(ary)->len; long i = RARRAY(ary)->len;
while (i--) { while (i--) {
if (rb_equal(RARRAY(ary)->ptr[i], val)) if (rb_equal(RARRAY(ary)->ptr[i], val))
return INT2FIX(i); return INT2NUM(i);
} }
return Qnil; return Qnil;
} }
@ -468,11 +451,11 @@ rb_ary_indexes(argc, argv, ary)
VALUE ary; VALUE ary;
{ {
VALUE new_ary; VALUE new_ary;
size_t i; long i;
new_ary = rb_ary_new2(argc); new_ary = rb_ary_new2(argc);
for (i=0; i<argc; i++) { for (i=0; i<argc; i++) {
rb_ary_store(new_ary, i, rb_ary_entry(ary, NUM2UINT(argv[i]))); rb_ary_push(new_ary, rb_ary_aref(1, argv+i, ary));
} }
return new_ary; return new_ary;
@ -481,24 +464,24 @@ rb_ary_indexes(argc, argv, ary)
static void static void
rb_ary_replace(ary, beg, len, rpl) rb_ary_replace(ary, beg, len, rpl)
VALUE ary, rpl; VALUE ary, rpl;
size_t beg, len; long beg, len;
{ {
if (len < 0) { if (len < 0) rb_raise(rb_eIndexError, "negative length %d", len);
rb_raise(rb_eIndexError, "negative length %d", len); if (beg < 0) {
beg += RARRAY(ary)->len;
}
if (beg < 0) {
beg -= RARRAY(ary)->len;
rb_raise(rb_eIndexError, "index %d out of array", beg);
}
if (beg + len > RARRAY(ary)->len) {
len = RARRAY(ary)->len - beg;
} }
if (TYPE(rpl) != T_ARRAY) { if (TYPE(rpl) != T_ARRAY) {
rpl = rb_Array(rpl); rpl = rb_Array(rpl);
} }
if (beg + len < 0 || (beg < 0 && beg <= -len)) {
rb_raise(rb_eIndexError, "index %d out of range", beg);
}
if (beg < 0) {
len += beg;
beg = 0;
}
rb_ary_modify(ary); rb_ary_modify(ary);
if (beg >= RARRAY(ary)->len) { if (beg >= RARRAY(ary)->len) {
len = beg + RARRAY(rpl)->len; len = beg + RARRAY(rpl)->len;
@ -511,7 +494,7 @@ rb_ary_replace(ary, beg, len, rpl)
RARRAY(ary)->len = len; RARRAY(ary)->len = len;
} }
else { else {
size_t alen; long alen;
if (beg + len > RARRAY(ary)->len) { if (beg + len > RARRAY(ary)->len) {
len = RARRAY(ary)->len - beg; len = RARRAY(ary)->len - beg;
@ -539,24 +522,17 @@ rb_ary_aset(argc, argv, ary)
VALUE ary; VALUE ary;
{ {
VALUE arg1, arg2, arg3; VALUE arg1, arg2, arg3;
size_t offset; long offset, beg, len;
size_t beg, len;
if (rb_scan_args(argc, argv, "21", &arg1, &arg2, &arg3) == 3) { if (rb_scan_args(argc, argv, "21", &arg1, &arg2, &arg3) == 3) {
beg = NUM2UINT(arg1); rb_ary_replace(ary, NUM2LONG(arg1), NUM2LONG(arg2), arg3);
len = NUM2UINT(arg2);
if (beg < 0) {
beg = RARRAY(ary)->len + beg;
}
rb_ary_replace(ary, beg, len, arg3);
return arg3; return arg3;
} }
else if (FIXNUM_P(arg1)) { else if (FIXNUM_P(arg1)) {
offset = FIX2UINT(arg1); offset = FIX2LONG(arg1);
goto fixnum; goto fixnum;
} }
else if (beg_len(arg1, &beg, &len, RARRAY(ary)->len)) { else if (rb_range_beg_len(arg1, &beg, &len, RARRAY(ary)->len, 1)) {
/* check if idx is Range */ /* check if idx is Range */
rb_ary_replace(ary, beg, len, arg2); rb_ary_replace(ary, beg, len, arg2);
return arg2; return arg2;
@ -565,7 +541,7 @@ rb_ary_aset(argc, argv, ary)
rb_raise(rb_eIndexError, "index too big"); rb_raise(rb_eIndexError, "index too big");
} }
offset = NUM2UINT(arg1); offset = NUM2LONG(arg1);
fixnum: fixnum:
rb_ary_store(ary, offset, arg2); rb_ary_store(ary, offset, arg2);
return arg2; return arg2;
@ -575,43 +551,43 @@ VALUE
rb_ary_each(ary) rb_ary_each(ary)
VALUE ary; VALUE ary;
{ {
size_t i; long i;
for (i=0; i<RARRAY(ary)->len; i++) { for (i=0; i<RARRAY(ary)->len; i++) {
rb_yield(RARRAY(ary)->ptr[i]); rb_yield(RARRAY(ary)->ptr[i]);
} }
return Qnil; return ary;
} }
static VALUE static VALUE
rb_ary_each_index(ary) rb_ary_each_index(ary)
VALUE ary; VALUE ary;
{ {
size_t i; long i;
for (i=0; i<RARRAY(ary)->len; i++) { for (i=0; i<RARRAY(ary)->len; i++) {
rb_yield(INT2FIX(i)); rb_yield(INT2NUM(i));
} }
return Qnil; return ary;
} }
static VALUE static VALUE
rb_ary_reverse_each(ary) rb_ary_reverse_each(ary)
VALUE ary; VALUE ary;
{ {
size_t len = RARRAY(ary)->len; long len = RARRAY(ary)->len;
while (len--) { while (len--) {
rb_yield(RARRAY(ary)->ptr[len]); rb_yield(RARRAY(ary)->ptr[len]);
} }
return Qnil; return ary;
} }
static VALUE static VALUE
rb_ary_length(ary) rb_ary_length(ary)
VALUE ary; VALUE ary;
{ {
return INT2FIX(RARRAY(ary)->len); return INT2NUM(RARRAY(ary)->len);
} }
static VALUE static VALUE
@ -639,7 +615,7 @@ static VALUE
rb_ary_dup(ary) rb_ary_dup(ary)
VALUE ary; VALUE ary;
{ {
return rb_ary_new4(RARRAY(ary)->len, RARRAY(ary)->ptr); return rb_ary_s_create(RARRAY(ary)->len, RARRAY(ary)->ptr, CLASS_OF(ary));
} }
static VALUE static VALUE
@ -663,7 +639,7 @@ VALUE
rb_ary_join(ary, sep) rb_ary_join(ary, sep)
VALUE ary, sep; VALUE ary, sep;
{ {
size_t i; long i;
VALUE result, tmp; VALUE result, tmp;
if (RARRAY(ary)->len == 0) return rb_str_new(0, 0); if (RARRAY(ary)->len == 0) return rb_str_new(0, 0);
@ -742,11 +718,7 @@ rb_ary_to_s(ary)
return str; return str;
} }
#ifdef USE_THREAD
static ID inspect_key; static ID inspect_key;
#else
static VALUE inspect_tbl;
#endif
struct inspect_arg { struct inspect_arg {
VALUE (*func)(); VALUE (*func)();
@ -764,11 +736,9 @@ static VALUE
inspect_ensure(obj) inspect_ensure(obj)
VALUE obj; VALUE obj;
{ {
#ifdef USE_THREAD
VALUE inspect_tbl; VALUE inspect_tbl;
inspect_tbl = rb_thread_local_aref(rb_thread_current(), inspect_key); inspect_tbl = rb_thread_local_aref(rb_thread_current(), inspect_key);
#endif
rb_ary_pop(inspect_tbl); rb_ary_pop(inspect_tbl);
return 0; return 0;
} }
@ -780,7 +750,6 @@ rb_protect_inspect(func, obj, arg)
{ {
struct inspect_arg iarg; struct inspect_arg iarg;
#ifdef USE_THREAD
VALUE inspect_tbl; VALUE inspect_tbl;
if (!inspect_key) { if (!inspect_key) {
@ -791,12 +760,6 @@ rb_protect_inspect(func, obj, arg)
inspect_tbl = rb_ary_new(); inspect_tbl = rb_ary_new();
rb_thread_local_aset(rb_thread_current(), inspect_key, inspect_tbl); rb_thread_local_aset(rb_thread_current(), inspect_key, inspect_tbl);
} }
#else
if (!inspect_tbl) {
inspect_tbl = rb_ary_new();
rb_global_variable(&inspect_tbl);
}
#endif
rb_ary_push(inspect_tbl, obj); rb_ary_push(inspect_tbl, obj);
iarg.func = func; iarg.func = func;
iarg.arg1 = obj; iarg.arg1 = obj;
@ -808,15 +771,11 @@ VALUE
rb_inspecting_p(obj) rb_inspecting_p(obj)
VALUE obj; VALUE obj;
{ {
#ifdef USE_THREAD
VALUE inspect_tbl; VALUE inspect_tbl;
if (!inspect_key) return Qfalse; if (!inspect_key) return Qfalse;
inspect_tbl = rb_thread_local_aref(rb_thread_current(), inspect_key); inspect_tbl = rb_thread_local_aref(rb_thread_current(), inspect_key);
if (NIL_P(inspect_tbl)) return Qfalse; if (NIL_P(inspect_tbl)) return Qfalse;
#else
if (!inspect_tbl) return Qnil;
#endif
return rb_ary_includes(inspect_tbl, obj); return rb_ary_includes(inspect_tbl, obj);
} }
@ -824,7 +783,7 @@ static VALUE
inspect_ary(ary) inspect_ary(ary)
VALUE ary; VALUE ary;
{ {
size_t i = 0; long i = 0;
VALUE s, str; VALUE s, str;
str = rb_str_new2("["); str = rb_str_new2("[");
@ -953,7 +912,7 @@ rb_ary_delete(ary, item)
VALUE ary; VALUE ary;
VALUE item; VALUE item;
{ {
size_t i1, i2; long i1, i2;
rb_ary_modify(ary); rb_ary_modify(ary);
for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) { for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
@ -981,11 +940,11 @@ rb_ary_delete_at(ary, at)
VALUE ary; VALUE ary;
VALUE at; VALUE at;
{ {
size_t i1, i2, pos; long i1, i2, pos;
VALUE del = Qnil; VALUE del = Qnil;
rb_ary_modify(ary); rb_ary_modify(ary);
pos = NUM2UINT(at); pos = NUM2LONG(at);
for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) { for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
if (i1 == pos) { if (i1 == pos) {
del = RARRAY(ary)->ptr[i1]; del = RARRAY(ary)->ptr[i1];
@ -1005,11 +964,11 @@ static VALUE
rb_ary_delete_if(ary) rb_ary_delete_if(ary)
VALUE ary; VALUE ary;
{ {
size_t i1, i2; long i1, i2;
rb_ary_modify(ary); rb_ary_modify(ary);
for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) { for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
if (rb_yield(RARRAY(ary)->ptr[i1])) continue; if (RTEST(rb_yield(RARRAY(ary)->ptr[i1]))) continue;
if (i1 != i2) { if (i1 != i2) {
RARRAY(ary)->ptr[i2] = RARRAY(ary)->ptr[i1]; RARRAY(ary)->ptr[i2] = RARRAY(ary)->ptr[i1];
} }
@ -1024,7 +983,7 @@ static VALUE
rb_ary_filter(ary) rb_ary_filter(ary)
VALUE ary; VALUE ary;
{ {
size_t i; long i;
rb_ary_modify(ary); rb_ary_modify(ary);
for (i = 0; i < RARRAY(ary)->len; i++) { for (i = 0; i < RARRAY(ary)->len; i++) {
@ -1038,7 +997,7 @@ rb_ary_replace_method(ary, ary2)
VALUE ary, ary2; VALUE ary, ary2;
{ {
ary2 = to_ary(ary2); ary2 = to_ary(ary2);
rb_ary_replace(ary, 0, RARRAY(ary2)->len, ary2); rb_ary_replace(ary, 0, RARRAY(ary)->len, ary2);
return ary; return ary;
} }
@ -1061,20 +1020,28 @@ rb_ary_fill(argc, argv, ary)
VALUE ary; VALUE ary;
{ {
VALUE item, arg1, arg2; VALUE item, arg1, arg2;
size_t beg, len, end; long beg, end, len;
VALUE *p, *pend; VALUE *p, *pend;
if (rb_scan_args(argc, argv, "12", &item, &arg1, &arg2) == 2 && rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
beg_len(arg1, &beg, &len, RARRAY(ary)->len)) { switch (argc) {
/* beg and len set already */ case 1:
} beg = 0;
else { len = RARRAY(ary)->len - beg;
beg = NIL_P(arg1)?0:NUM2UINT(arg1); break;
case 2:
if (rb_range_beg_len(arg1, &beg, &len, RARRAY(ary)->len, 1)) {
break;
}
/* fall through */
case 3:
beg = NIL_P(arg1)?0:NUM2LONG(arg1);
if (beg < 0) { if (beg < 0) {
beg = RARRAY(ary)->len + beg; beg = RARRAY(ary)->len + beg;
if (beg < 0) beg = 0; if (beg < 0) beg = 0;
} }
len = NIL_P(arg2)?RARRAY(ary)->len - beg:NUM2UINT(arg2); len = NIL_P(arg2)?RARRAY(ary)->len - beg:NUM2LONG(arg2);
break;
} }
rb_ary_modify(ary); rb_ary_modify(ary);
end = beg + len; end = beg + len;
@ -1138,13 +1105,13 @@ rb_ary_times(ary, times)
VALUE times; VALUE times;
{ {
VALUE ary2; VALUE ary2;
size_t i, len; long i, len;
if (TYPE(times) == T_STRING) { if (TYPE(times) == T_STRING) {
return rb_ary_join(ary, times); return rb_ary_join(ary, times);
} }
len = NUM2UINT(times); len = NUM2LONG(times);
if (len < 0) { if (len < 0) {
rb_raise(rb_eArgError, "negative argument"); rb_raise(rb_eArgError, "negative argument");
} }
@ -1200,7 +1167,7 @@ static VALUE
rb_ary_equal(ary1, ary2) rb_ary_equal(ary1, ary2)
VALUE ary1, ary2; VALUE ary1, ary2;
{ {
size_t i; long i;
if (TYPE(ary2) != T_ARRAY) return Qfalse; if (TYPE(ary2) != T_ARRAY) return Qfalse;
if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse; if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
@ -1215,7 +1182,7 @@ static VALUE
rb_ary_eql(ary1, ary2) rb_ary_eql(ary1, ary2)
VALUE ary1, ary2; VALUE ary1, ary2;
{ {
size_t i; long i;
if (TYPE(ary2) != T_ARRAY) return Qfalse; if (TYPE(ary2) != T_ARRAY) return Qfalse;
if (RARRAY(ary1)->len != RARRAY(ary2)->len) if (RARRAY(ary1)->len != RARRAY(ary2)->len)
@ -1231,7 +1198,7 @@ static VALUE
rb_ary_hash(ary) rb_ary_hash(ary)
VALUE ary; VALUE ary;
{ {
size_t i; long i;
int h; int h;
h = RARRAY(ary)->len; h = RARRAY(ary)->len;
@ -1247,7 +1214,7 @@ rb_ary_includes(ary, item)
VALUE ary; VALUE ary;
VALUE item; VALUE item;
{ {
size_t i; long i;
for (i=0; i<RARRAY(ary)->len; i++) { for (i=0; i<RARRAY(ary)->len; i++) {
if (rb_equal(RARRAY(ary)->ptr[i], item)) { if (rb_equal(RARRAY(ary)->ptr[i], item)) {
return Qtrue; return Qtrue;
@ -1261,7 +1228,7 @@ rb_ary_cmp(ary, ary2)
VALUE ary; VALUE ary;
VALUE ary2; VALUE ary2;
{ {
size_t i, len; long i, len;
ary2 = to_ary(ary2); ary2 = to_ary(ary2);
len = RARRAY(ary)->len; len = RARRAY(ary)->len;
@ -1285,7 +1252,7 @@ rb_ary_diff(ary1, ary2)
VALUE ary1, ary2; VALUE ary1, ary2;
{ {
VALUE ary3; VALUE ary3;
size_t i; long i;
ary2 = to_ary(ary2); ary2 = to_ary(ary2);
ary3 = rb_ary_new(); ary3 = rb_ary_new();
@ -1302,7 +1269,7 @@ rb_ary_and(ary1, ary2)
VALUE ary1, ary2; VALUE ary1, ary2;
{ {
VALUE ary3; VALUE ary3;
size_t i; long i;
ary2 = to_ary(ary2); ary2 = to_ary(ary2);
ary3 = rb_ary_new(); ary3 = rb_ary_new();
@ -1320,7 +1287,7 @@ rb_ary_or(ary1, ary2)
VALUE ary1, ary2; VALUE ary1, ary2;
{ {
VALUE ary3; VALUE ary3;
size_t i; long i;
if (TYPE(ary2) != T_ARRAY) { if (TYPE(ary2) != T_ARRAY) {
if (rb_ary_includes(ary1, ary2)) return ary1; if (rb_ary_includes(ary1, ary2)) return ary1;
@ -1414,7 +1381,7 @@ static VALUE
rb_ary_nitems(ary) rb_ary_nitems(ary)
VALUE ary; VALUE ary;
{ {
size_t n = 0; long n = 0;
VALUE *p, *pend; VALUE *p, *pend;
p = RARRAY(ary)->ptr; p = RARRAY(ary)->ptr;
@ -1423,14 +1390,14 @@ rb_ary_nitems(ary)
if (!NIL_P(*p)) n++; if (!NIL_P(*p)) n++;
p++; p++;
} }
return INT2FIX(n); return INT2NUM(n);
} }
static VALUE static VALUE
rb_ary_flatten_bang(ary) rb_ary_flatten_bang(ary)
VALUE ary; VALUE ary;
{ {
size_t i; long i;
int mod = 0; int mod = 0;
rb_ary_modify(ary); rb_ary_modify(ary);
@ -1504,6 +1471,7 @@ Init_Array()
rb_define_method(rb_cArray, "delete", rb_ary_delete, 1); rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at, 1); rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at, 1);
rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0); rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
rb_define_method(rb_cArray, "reject!", rb_ary_delete_if, 0);
rb_define_method(rb_cArray, "filter", rb_ary_filter, 0); rb_define_method(rb_cArray, "filter", rb_ary_filter, 0);
rb_define_method(rb_cArray, "replace", rb_ary_replace_method, 1); rb_define_method(rb_cArray, "replace", rb_ary_replace_method, 1);
rb_define_method(rb_cArray, "clear", rb_ary_clear, 0); rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);

190
bignum.c
View file

@ -26,7 +26,7 @@ typedef unsigned short USHORT;
static VALUE static VALUE
bignew_1(klass, len, sign) bignew_1(klass, len, sign)
VALUE klass; VALUE klass;
size_t len; long len;
char sign; char sign;
{ {
NEWOBJ(big, struct RBignum); NEWOBJ(big, struct RBignum);
@ -54,7 +54,7 @@ void
rb_big_2comp(x) /* get 2's complement */ rb_big_2comp(x) /* get 2's complement */
VALUE x; VALUE x;
{ {
int i = RBIGNUM(x)->len; long i = RBIGNUM(x)->len;
USHORT *ds = BDIGITS(x); USHORT *ds = BDIGITS(x);
long num; long num;
@ -79,7 +79,7 @@ static VALUE
bignorm(x) bignorm(x)
VALUE x; VALUE x;
{ {
size_t len = RBIGNUM(x)->len; long len = RBIGNUM(x)->len;
USHORT *ds = BDIGITS(x); USHORT *ds = BDIGITS(x);
while (len-- && !ds[len]) ; while (len-- && !ds[len]) ;
@ -165,13 +165,13 @@ rb_int2inum(n)
VALUE VALUE
rb_str2inum(str, base) rb_str2inum(str, base)
char *str; const char *str;
int base; int base;
{ {
char sign = 1, c; char sign = 1, c;
unsigned long num; unsigned long num;
size_t len, blen = 1; long len, blen = 1;
int i; long i;
VALUE z; VALUE z;
USHORT *zds; USHORT *zds;
@ -191,6 +191,10 @@ rb_str2inum(str, base)
str++; str++;
base = 16; base = 16;
} }
else if (*str == 'b' || *str == 'B') {
str++;
base = 2;
}
else { else {
base = 8; base = 8;
} }
@ -204,16 +208,19 @@ rb_str2inum(str, base)
while (str[0] == '0') str++; while (str[0] == '0') str++;
len = 3*strlen(str)*sizeof(char); len = 3*strlen(str)*sizeof(char);
} }
else { /* base == 10 or 16 */ else { /* base == 10, 2 or 16 */
if (base == 16 && str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) { if (base == 16 && str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
str += 2; str += 2;
} }
if (base == 2 && str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
str += 2;
}
while (str[0] == '0') str++; while (str[0] == '0') str++;
len = 4*strlen(str)*sizeof(char); len = 4*strlen(str)*sizeof(char);
} }
if (len <= (sizeof(VALUE)*CHAR_BIT)) { if (len <= (sizeof(VALUE)*CHAR_BIT)) {
unsigned int val = strtoul((char*)str, 0, base); unsigned long val = strtoul((char*)str, 0, base);
if (POSFIXABLE(val)) { if (POSFIXABLE(val)) {
if (sign) return INT2FIX(val); if (sign) return INT2FIX(val);
@ -278,7 +285,7 @@ rb_big2str(x, base)
{ {
VALUE t; VALUE t;
USHORT *ds; USHORT *ds;
unsigned int i, j, hbase; unsigned long i, j, hbase;
VALUE ss; VALUE ss;
char *s, c; char *s, c;
@ -316,7 +323,7 @@ rb_big2str(x, base)
s[0] = RBIGNUM(x)->sign ? '+' : '-'; s[0] = RBIGNUM(x)->sign ? '+' : '-';
while (i && j) { while (i && j) {
int k = i; long k = i;
unsigned long num = 0; unsigned long num = 0;
while (k--) { while (k--) {
num = BIGUP(num) + ds[k]; num = BIGUP(num) + ds[k];
@ -352,7 +359,7 @@ rb_big2ulong(x)
VALUE x; VALUE x;
{ {
unsigned long num; unsigned long num;
size_t len = RBIGNUM(x)->len; long len = RBIGNUM(x)->len;
USHORT *ds; USHORT *ds;
if (len > sizeof(long)/sizeof(USHORT)) if (len > sizeof(long)/sizeof(USHORT))
@ -390,13 +397,20 @@ VALUE
rb_dbl2big(d) rb_dbl2big(d)
double d; double d;
{ {
unsigned int i = 0; unsigned long i = 0;
long c; long c;
USHORT *digits; USHORT *digits;
VALUE z; VALUE z;
double u = (d < 0)?-d:d; double u = (d < 0)?-d:d;
while (0 != (long)u) { if (isinf(d)) {
rb_raise(rb_eFloatDomainError, d < 0 ? "-Infinity" : "Infinity");
}
if (isnan(d)) {
rb_raise(rb_eFloatDomainError, "NaN");
}
while (!POSFIXABLE(u) || 0 != (long)u) {
u /= (double)(BIGRAD); u /= (double)(BIGRAD);
i++; i++;
} }
@ -417,7 +431,7 @@ rb_big2dbl(x)
VALUE x; VALUE x;
{ {
double d = 0.0; double d = 0.0;
size_t i = RBIGNUM(x)->len; long i = RBIGNUM(x)->len;
USHORT *ds = BDIGITS(x); USHORT *ds = BDIGITS(x);
while (i--) { while (i--) {
@ -438,7 +452,7 @@ static VALUE
rb_big_cmp(x, y) rb_big_cmp(x, y)
VALUE x, y; VALUE x, y;
{ {
size_t xlen = RBIGNUM(x)->len; long xlen = RBIGNUM(x)->len;
switch (TYPE(y)) { switch (TYPE(y)) {
case T_FIXNUM: case T_FIXNUM:
@ -490,7 +504,7 @@ rb_big_neg(x)
VALUE x; VALUE x;
{ {
VALUE z = rb_big_clone(x); VALUE z = rb_big_clone(x);
size_t i = RBIGNUM(x)->len; long i = RBIGNUM(x)->len;
USHORT *ds = BDIGITS(z); USHORT *ds = BDIGITS(z);
if (!RBIGNUM(x)->sign) rb_big_2comp(z); if (!RBIGNUM(x)->sign) rb_big_2comp(z);
@ -508,7 +522,7 @@ bigsub(x, y)
VALUE z = 0; VALUE z = 0;
USHORT *zds; USHORT *zds;
long num; long num;
size_t i; long i;
i = RBIGNUM(x)->len; i = RBIGNUM(x)->len;
/* if x is larger than y, swap */ /* if x is larger than y, swap */
@ -556,7 +570,7 @@ bigadd(x, y, sign)
{ {
VALUE z; VALUE z;
long num; long num;
size_t i, len; long i, len;
sign = (sign == RBIGNUM(y)->sign); sign = (sign == RBIGNUM(y)->sign);
if (RBIGNUM(x)->sign != sign) { if (RBIGNUM(x)->sign != sign) {
@ -636,7 +650,7 @@ VALUE
rb_big_mul(x, y) rb_big_mul(x, y)
VALUE x, y; VALUE x, y;
{ {
size_t i, j; long i, j;
unsigned long n = 0; unsigned long n = 0;
VALUE z; VALUE z;
USHORT *zds; USHORT *zds;
@ -685,11 +699,11 @@ bigdivmod(x, y, div, mod, modulo)
VALUE *div, *mod; VALUE *div, *mod;
int modulo; int modulo;
{ {
size_t nx = RBIGNUM(x)->len, ny = RBIGNUM(y)->len; long nx = RBIGNUM(x)->len, ny = RBIGNUM(y)->len;
int i, j; long i, j;
VALUE yy, z; VALUE yy, z;
USHORT *xds, *yds, *zds, *tds; USHORT *xds, *yds, *zds, *tds;
size_t t2; unsigned long t2;
long num; long num;
USHORT dd, q; USHORT dd, q;
@ -711,10 +725,11 @@ bigdivmod(x, y, div, mod, modulo)
zds[i] = (USHORT)(t2 / dd); zds[i] = (USHORT)(t2 / dd);
t2 %= dd; t2 %= dd;
} }
RBIGNUM(z)->sign = RBIGNUM(x)->sign==RBIGNUM(y)->sign;
if (div) *div = bignorm(z); if (div) *div = bignorm(z);
if (mod) { if (mod) {
if (!RBIGNUM(y)->sign) t2 = -(long)t2; if (!RBIGNUM(y)->sign) t2 = -(long)t2;
*mod = INT2FIX(t2); *mod = INT2NUM(t2);
} }
return; return;
} }
@ -798,7 +813,7 @@ bigdivmod(x, y, div, mod, modulo)
RBIGNUM(*mod)->len = ny; RBIGNUM(*mod)->len = ny;
RBIGNUM(*mod)->sign = RBIGNUM(x)->sign; RBIGNUM(*mod)->sign = RBIGNUM(x)->sign;
if (modulo && RBIGNUM(x)->sign != RBIGNUM(y)->sign) { if (modulo && RBIGNUM(x)->sign != RBIGNUM(y)->sign) {
size_t len = ny; long len = ny;
zds = BDIGITS(*mod); zds = BDIGITS(*mod);
while (len-- && !zds[len]); while (len-- && !zds[len]);
if (len > 0) { if (len > 0) {
@ -936,6 +951,7 @@ rb_big_pow(x, y)
} }
z = rb_big_mul(z, x); z = rb_big_mul(z, x);
} }
if (!FIXNUM_P(z)) z = bignorm(z);
return z; return z;
} }
d = (double)yy; d = (double)yy;
@ -953,58 +969,7 @@ rb_big_and(x, y)
{ {
VALUE z; VALUE z;
USHORT *ds1, *ds2, *zds; USHORT *ds1, *ds2, *zds;
size_t i, l1, l2; long i, l1, l2;
char sign;
if (FIXNUM_P(y)) {
y = rb_int2big(FIX2LONG(y));
}
else {
Check_Type(y, T_BIGNUM);
}
if (!RBIGNUM(y)->sign) {
y = rb_big_clone(y);
rb_big_2comp(y);
}
if (!RBIGNUM(x)->sign) {
x = rb_big_clone(x);
rb_big_2comp(x);
}
if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
l1 = RBIGNUM(y)->len;
l2 = RBIGNUM(x)->len;
ds1 = BDIGITS(y);
ds2 = BDIGITS(x);
sign = RBIGNUM(y)->sign;
}
else {
l1 = RBIGNUM(x)->len;
l2 = RBIGNUM(y)->len;
ds1 = BDIGITS(x);
ds2 = BDIGITS(y);
sign = RBIGNUM(x)->sign;
}
z = bignew(l2, RBIGNUM(x)->sign && RBIGNUM(y)->sign);
zds = BDIGITS(z);
for (i=0; i<l1; i++) {
zds[i] = ds1[i] & ds2[i];
}
for (; i<l2; i++) {
zds[i] = sign?0:ds2[i];
}
if (!RBIGNUM(z)->sign) rb_big_2comp(z);
return bignorm(z);
}
VALUE
rb_big_or(x, y)
VALUE x, y;
{
VALUE z;
USHORT *ds1, *ds2, *zds;
unsigned int i, l1, l2;
char sign; char sign;
if (FIXNUM_P(y)) { if (FIXNUM_P(y)) {
@ -1039,6 +1004,57 @@ rb_big_or(x, y)
z = bignew(l2, RBIGNUM(x)->sign || RBIGNUM(y)->sign); z = bignew(l2, RBIGNUM(x)->sign || RBIGNUM(y)->sign);
zds = BDIGITS(z); zds = BDIGITS(z);
for (i=0; i<l1; i++) {
zds[i] = ds1[i] & ds2[i];
}
for (; i<l2; i++) {
zds[i] = sign?0:ds2[i];
}
if (!RBIGNUM(z)->sign) rb_big_2comp(z);
return bignorm(z);
}
VALUE
rb_big_or(x, y)
VALUE x, y;
{
VALUE z;
USHORT *ds1, *ds2, *zds;
unsigned long i, l1, l2;
char sign;
if (FIXNUM_P(y)) {
y = rb_int2big(FIX2LONG(y));
}
else {
Check_Type(y, T_BIGNUM);
}
if (!RBIGNUM(y)->sign) {
y = rb_big_clone(y);
rb_big_2comp(y);
}
if (!RBIGNUM(x)->sign) {
x = rb_big_clone(x);
rb_big_2comp(x);
}
if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
l1 = RBIGNUM(y)->len;
l2 = RBIGNUM(x)->len;
ds1 = BDIGITS(y);
ds2 = BDIGITS(x);
sign = RBIGNUM(y)->sign;
}
else {
l1 = RBIGNUM(x)->len;
l2 = RBIGNUM(y)->len;
ds1 = BDIGITS(x);
ds2 = BDIGITS(y);
sign = RBIGNUM(x)->sign;
}
z = bignew(l2, RBIGNUM(x)->sign && RBIGNUM(y)->sign);
zds = BDIGITS(z);
for (i=0; i<l1; i++) { for (i=0; i<l1; i++) {
zds[i] = ds1[i] | ds2[i]; zds[i] = ds1[i] | ds2[i];
} }
@ -1112,11 +1128,11 @@ rb_big_lshift(x, y)
{ {
USHORT *xds, *zds; USHORT *xds, *zds;
int shift = NUM2INT(y); int shift = NUM2INT(y);
size_t s1 = shift/BITSPERDIG; int s1 = shift/BITSPERDIG;
size_t s2 = shift%BITSPERDIG; int s2 = shift%BITSPERDIG;
VALUE z; VALUE z;
unsigned long num = 0; unsigned long num = 0;
size_t len, i; long len, i;
if (shift < 0) return rb_big_rshift(x, INT2FIX(-shift)); if (shift < 0) return rb_big_rshift(x, INT2FIX(-shift));
xds = BDIGITS(x); xds = BDIGITS(x);
@ -1141,12 +1157,12 @@ rb_big_rshift(x, y)
{ {
USHORT *xds, *zds; USHORT *xds, *zds;
int shift = NUM2INT(y); int shift = NUM2INT(y);
size_t s1 = shift/BITSPERDIG; int s1 = shift/BITSPERDIG;
size_t s2 = shift%BITSPERDIG; int s2 = shift%BITSPERDIG;
VALUE z; VALUE z;
unsigned long num = 0; unsigned long num = 0;
size_t i = RBIGNUM(x)->len; long i = RBIGNUM(x)->len;
size_t j; long j;
if (shift < 0) return rb_big_lshift(x, INT2FIX(-shift)); if (shift < 0) return rb_big_lshift(x, INT2FIX(-shift));
if (s1 > RBIGNUM(x)->len) { if (s1 > RBIGNUM(x)->len) {
@ -1173,7 +1189,7 @@ rb_big_aref(x, y)
{ {
USHORT *xds; USHORT *xds;
int shift = NUM2INT(y); int shift = NUM2INT(y);
size_t s1, s2; int s1, s2;
if (shift < 0) return INT2FIX(0); if (shift < 0) return INT2FIX(0);
s1 = shift/BITSPERDIG; s1 = shift/BITSPERDIG;
@ -1197,7 +1213,7 @@ static VALUE
rb_big_hash(x) rb_big_hash(x)
VALUE x; VALUE x;
{ {
size_t i, len; long i, len;
int key; int key;
USHORT *digits; USHORT *digits;
@ -1216,7 +1232,7 @@ rb_big_coerce(x, y)
return rb_assoc_new(rb_int2big(FIX2LONG(y)), x); return rb_assoc_new(rb_int2big(FIX2LONG(y)), x);
} }
else { else {
rb_raise(rb_eTypeError, "can't coerce %s to Bignum", rb_raise(rb_eTypeError, "Can't coerce %s to Bignum",
rb_class2name(CLASS_OF(y))); rb_class2name(CLASS_OF(y)));
} }
/* not reached */ /* not reached */
@ -1243,7 +1259,7 @@ rb_big_rand(max)
VALUE max; VALUE max;
{ {
struct RBignum *v; struct RBignum *v;
size_t len; long len;
len = RBIGNUM(max)->len; len = RBIGNUM(max)->len;
v = RBIGNUM(bignew(len,1)); v = RBIGNUM(bignew(len,1));

59
class.c
View file

@ -6,7 +6,7 @@
$Date$ $Date$
created at: Tue Aug 10 15:05:44 JST 1993 created at: Tue Aug 10 15:05:44 JST 1993
Copyright (C) 1993-1998 Yukihiro Matsumoto Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/ ************************************************/
@ -105,7 +105,7 @@ rb_define_class_id(id, super)
VALUE VALUE
rb_define_class(name, super) rb_define_class(name, super)
char *name; const char *name;
VALUE super; VALUE super;
{ {
VALUE klass; VALUE klass;
@ -122,7 +122,7 @@ rb_define_class(name, super)
VALUE VALUE
rb_define_class_under(outer, name, super) rb_define_class_under(outer, name, super)
VALUE outer; VALUE outer;
char *name; const char *name;
VALUE super; VALUE super;
{ {
VALUE klass; VALUE klass;
@ -164,7 +164,7 @@ rb_define_module_id(id)
VALUE VALUE
rb_define_module(name) rb_define_module(name)
char *name; const char *name;
{ {
VALUE module; VALUE module;
ID id; ID id;
@ -179,7 +179,7 @@ rb_define_module(name)
VALUE VALUE
rb_define_module_under(outer, name) rb_define_module_under(outer, name)
VALUE outer; VALUE outer;
char *name; const char *name;
{ {
VALUE module; VALUE module;
ID id; ID id;
@ -199,8 +199,11 @@ include_class_new(module, super)
NEWOBJ(klass, struct RClass); NEWOBJ(klass, struct RClass);
OBJSETUP(klass, rb_cClass, T_ICLASS); OBJSETUP(klass, rb_cClass, T_ICLASS);
klass->m_tbl = RCLASS(module)->m_tbl; if (!RCLASS(module)->iv_tbl) {
RCLASS(module)->iv_tbl = st_init_numtable();
}
klass->iv_tbl = RCLASS(module)->iv_tbl; klass->iv_tbl = RCLASS(module)->iv_tbl;
klass->m_tbl = RCLASS(module)->m_tbl;
klass->super = super; klass->super = super;
if (TYPE(module) == T_ICLASS) { if (TYPE(module) == T_ICLASS) {
RBASIC(klass)->klass = RBASIC(module)->klass; RBASIC(klass)->klass = RBASIC(module)->klass;
@ -365,6 +368,8 @@ method_list(mod, option, func)
VALUE klass; VALUE klass;
VALUE *p, *q, *pend; VALUE *p, *q, *pend;
if (!FL_TEST(mod, FL_TAINT) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't get metainfo");
ary = rb_ary_new(); ary = rb_ary_new();
for (klass = mod; klass; klass = RCLASS(klass)->super) { for (klass = mod; klass; klass = RCLASS(klass)->super) {
st_foreach(RCLASS(klass)->m_tbl, func, ary); st_foreach(RCLASS(klass)->m_tbl, func, ary);
@ -426,6 +431,8 @@ rb_obj_singleton_methods(obj)
VALUE klass; VALUE klass;
VALUE *p, *q, *pend; VALUE *p, *q, *pend;
if (rb_safe_level() >= 4 && !FL_TEST(obj, FL_TAINT))
rb_raise(rb_eSecurityError, "Insecure: can't get metainfo");
ary = rb_ary_new(); ary = rb_ary_new();
klass = CLASS_OF(obj); klass = CLASS_OF(obj);
while (klass && FL_TEST(klass, FL_SINGLETON)) { while (klass && FL_TEST(klass, FL_SINGLETON)) {
@ -458,7 +465,7 @@ rb_define_method_id(klass, name, func, argc)
void void
rb_define_method(klass, name, func, argc) rb_define_method(klass, name, func, argc)
VALUE klass; VALUE klass;
char *name; const char *name;
VALUE (*func)(); VALUE (*func)();
int argc; int argc;
{ {
@ -472,7 +479,7 @@ rb_define_method(klass, name, func, argc)
void void
rb_define_protected_method(klass, name, func, argc) rb_define_protected_method(klass, name, func, argc)
VALUE klass; VALUE klass;
char *name; const char *name;
VALUE (*func)(); VALUE (*func)();
int argc; int argc;
{ {
@ -483,7 +490,7 @@ rb_define_protected_method(klass, name, func, argc)
void void
rb_define_private_method(klass, name, func, argc) rb_define_private_method(klass, name, func, argc)
VALUE klass; VALUE klass;
char *name; const char *name;
VALUE (*func)(); VALUE (*func)();
int argc; int argc;
{ {
@ -494,7 +501,7 @@ rb_define_private_method(klass, name, func, argc)
void void
rb_undef_method(klass, name) rb_undef_method(klass, name)
VALUE klass; VALUE klass;
char *name; const char *name;
{ {
rb_add_method(klass, rb_intern(name), 0, NOEX_UNDEF); rb_add_method(klass, rb_intern(name), 0, NOEX_UNDEF);
} }
@ -504,7 +511,7 @@ rb_singleton_class(obj)
VALUE obj; VALUE obj;
{ {
if (rb_special_const_p(obj)) { if (rb_special_const_p(obj)) {
rb_raise(rb_eTypeError, "cannot define singleton"); rb_raise(rb_eTypeError, "can't define singleton");
} }
if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON)) { if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON)) {
return RBASIC(obj)->klass; return RBASIC(obj)->klass;
@ -517,7 +524,7 @@ rb_singleton_class(obj)
void void
rb_define_singleton_method(obj, name, func, argc) rb_define_singleton_method(obj, name, func, argc)
VALUE obj; VALUE obj;
char *name; const char *name;
VALUE (*func)(); VALUE (*func)();
int argc; int argc;
{ {
@ -527,7 +534,7 @@ rb_define_singleton_method(obj, name, func, argc)
void void
rb_define_module_function(module, name, func, argc) rb_define_module_function(module, name, func, argc)
VALUE module; VALUE module;
char *name; const char *name;
VALUE (*func)(); VALUE (*func)();
int argc; int argc;
{ {
@ -537,7 +544,7 @@ rb_define_module_function(module, name, func, argc)
void void
rb_define_global_function(name, func, argc) rb_define_global_function(name, func, argc)
char *name; const char *name;
VALUE (*func)(); VALUE (*func)();
int argc; int argc;
{ {
@ -547,7 +554,7 @@ rb_define_global_function(name, func, argc)
void void
rb_define_alias(klass, name1, name2) rb_define_alias(klass, name1, name2)
VALUE klass; VALUE klass;
char *name1, *name2; const char *name1, *name2;
{ {
rb_alias(klass, rb_intern(name1), rb_intern(name2)); rb_alias(klass, rb_intern(name1), rb_intern(name2));
} }
@ -555,7 +562,7 @@ rb_define_alias(klass, name1, name2)
void void
rb_define_attr(klass, name, read, write) rb_define_attr(klass, name, read, write)
VALUE klass; VALUE klass;
char *name; const char *name;
int read, write; int read, write;
{ {
rb_attr(klass, rb_intern(name), read, write, Qfalse); rb_attr(klass, rb_intern(name), read, write, Qfalse);
@ -571,17 +578,17 @@ rb_define_attr(klass, name, read, write)
int int
#ifdef HAVE_STDARG_PROTOTYPES #ifdef HAVE_STDARG_PROTOTYPES
rb_scan_args(int argc, VALUE *argv, char *fmt, ...) rb_scan_args(int argc, VALUE *argv, const char *fmt, ...)
#else #else
rb_scan_args(argc, argv, fmt, va_alist) rb_scan_args(argc, argv, fmt, va_alist)
int argc; int argc;
VALUE *argv; VALUE *argv;
char *fmt; const char *fmt;
va_dcl va_dcl
#endif #endif
{ {
int n, i; int n, i;
char *p = fmt; const char *p = fmt;
VALUE *var; VALUE *var;
va_list vargs; va_list vargs;
@ -596,10 +603,10 @@ rb_scan_args(argc, argv, fmt, va_alist)
if (ISDIGIT(*p)) { if (ISDIGIT(*p)) {
n = *p - '0'; n = *p - '0';
if (n > argc) if (n > argc)
rb_raise(rb_eArgError, "Wrong # of arguments (%d for %d)", argc, n); rb_raise(rb_eArgError, "wrong # of arguments (%d for %d)", argc, n);
for (i=0; i<n; i++) { for (i=0; i<n; i++) {
var = va_arg(vargs, VALUE*); var = va_arg(vargs, VALUE*);
*var = argv[i]; if (var) *var = argv[i];
} }
p++; p++;
} }
@ -612,10 +619,10 @@ rb_scan_args(argc, argv, fmt, va_alist)
for (; i<n; i++) { for (; i<n; i++) {
var = va_arg(vargs, VALUE*); var = va_arg(vargs, VALUE*);
if (argc > i) { if (argc > i) {
*var = argv[i]; if (var) *var = argv[i];
} }
else { else {
*var = Qnil; if (var) *var = Qnil;
} }
} }
p++; p++;
@ -624,15 +631,15 @@ rb_scan_args(argc, argv, fmt, va_alist)
if(*p == '*') { if(*p == '*') {
var = va_arg(vargs, VALUE*); var = va_arg(vargs, VALUE*);
if (argc > i) { if (argc > i) {
*var = rb_ary_new4(argc-i, argv+i); if (var) *var = rb_ary_new4(argc-i, argv+i);
} }
else { else {
*var = rb_ary_new(); if (var) *var = rb_ary_new();
} }
} }
else if (*p == '\0') { else if (*p == '\0') {
if (argc > i) { if (argc > i) {
rb_raise(rb_eArgError, "Wrong # of arguments(%d for %d)", argc, i); rb_raise(rb_eArgError, "wrong # of arguments(%d for %d)", argc, i);
} }
} }
else { else {

View file

@ -6,7 +6,7 @@
$Date$ $Date$
created at: Thu Aug 26 14:39:48 JST 1993 created at: Thu Aug 26 14:39:48 JST 1993
Copyright (C) 1993-1998 Yukihiro Matsumoto Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/ ************************************************/

9
config.guess vendored
View file

@ -62,6 +62,9 @@ trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
# Note: order is significant - the case branches are not exclusive. # Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:OS/2:*:*)
echo "i386-pc-os2_emx"
exit 0;;
alpha:OSF1:*:*) alpha:OSF1:*:*)
if test $UNAME_RELEASE = "V4.0"; then if test $UNAME_RELEASE = "V4.0"; then
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
@ -379,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/[678]?? )
sed 's/^ //' << EOF >dummy.c sed 's/^ //' << EOF >dummy.c
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
@ -621,11 +624,11 @@ EOF
objdump --private-headers dummy | \ objdump --private-headers dummy | \
grep ld.so.1 > /dev/null grep ld.so.1 > /dev/null
if test "$?" = 0 ; then if test "$?" = 0 ; then
LIBC="libc1" LIBC="-libc1"
fi fi
fi fi
rm -f dummy.s dummy rm -f dummy.s dummy
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0 echo ${UNAME_MACHINE}-unknown-linux${LIBC} ; exit 0
elif test "${UNAME_MACHINE}" = "mips" ; then elif test "${UNAME_MACHINE}" = "mips" ; then
cat >dummy.c <<EOF cat >dummy.c <<EOF
main(argc, argv) main(argc, argv)

8
config.sub vendored
View file

@ -151,7 +151,7 @@ case $basic_machine in
# Some are omitted here because they have special meanings below. # Some are omitted here because they have special meanings below.
tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
| arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \ | arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \
| 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 | hppa2.0 \ | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w \
| alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \ | alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \
| i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \ | i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \
| mips64 | mipsel | mips64el | mips64orion | mips64orionel \ | mips64 | mipsel | mips64el | mips64orion | mips64orionel \
@ -178,7 +178,7 @@ case $basic_machine in
| m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \ | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
| mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
| power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \ | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \
| xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* \ | xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \
| alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \ | alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \
| ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \ | ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \
| sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
@ -705,6 +705,8 @@ case $os in
-gnu/linux*) -gnu/linux*)
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
;; ;;
-os2_emx)
;;
# First accept the basic system types. # First accept the basic system types.
# The portable systems comes first. # The portable systems comes first.
# Each alternative MUST END IN A *, to match a version number. # Each alternative MUST END IN A *, to match a version number.
@ -721,7 +723,7 @@ case $os in
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux* | -uxpv* | -beos*) | -mingw32* | -linux* | -uxpv* | -beos* | -rhapsody* )
# Remember, each alternative MUST END IN *, to match a version number. # Remember, each alternative MUST END IN *, to match a version number.
;; ;;
-sunos5*) -sunos5*)

71
config_h.dj Normal file
View file

@ -0,0 +1,71 @@
#define USE_THREAD 1
#define SIZEOF_INT 4
#define SIZEOF_SHORT 2
#define SIZEOF_LONG 4
#define SIZEOF_VOIDP 4
#define SIZEOF_FLOAT 4
#define SIZEOF_DOUBLE 8
#define HAVE_PROTOTYPES 1
#define TOKEN_PASTE(x,y) x##y
#define HAVE_STDARG_PROTOTYPES 1
#define HAVE_ATTR_NORETURN 1
#define HAVE_DIRENT_H 1
#define STDC_HEADERS 1
#define HAVE_STDLIB_H 1
#define HAVE_UNISTD_H 1
#define HAVE_LIMITS_H 1
#define HAVE_SYS_FILE_H 1
#define HAVE_SYS_IOCTL_H 1
#define HAVE_PWD_H 1
#define HAVE_SYS_TIME_H 1
#define HAVE_SYS_TIMES_H 1
#define HAVE_SYS_PARAM_H 1
#define HAVE_SYS_WAIT_H 1
#define HAVE_STRING_H 1
#define HAVE_UTIME_H 1
#define HAVE_MEMORY_H 1
#define HAVE_DIRECT_H 1
#define HAVE_ST_BLKSIZE 1
#define HAVE_ST_RDEV 1
#define GETGROUPS_T gid_t
#define RETSIGTYPE void
#define HAVE_ALLOCA 1
#define vfork fork
#define HAVE_DUP2 1
#define HAVE_SETENV 1
#define HAVE_MEMMOVE 1
#define HAVE_MKDIR 1
#define HAVE_STRCASECMP 1
#define HAVE_STRERROR 1
#define HAVE_STRFTIME 1
#define HAVE_STRCHR 1
#define HAVE_STRSTR 1
#define HAVE_STRTOUL 1
#define HAVE_STRDUP 1
#define HAVE_ISINF 1
#define HAVE_ISNAN 1
#define HAVE_FINITE 1
#define HAVE_FMOD 1
#define HAVE_RANDOM 1
#define HAVE_WAITPID 1
#define HAVE_GETCWD 1
#define HAVE_TRUNCATE 1
#define HAVE_CHSIZE 1
#define HAVE_TIMES 1
#define HAVE_UTIMES 1
#define HAVE_FCNTL_H 1
/*#define HAVE_SETITIMER 1*/
#define HAVE_GETGROUPS 1
#define HAVE_SIGPROCMASK 1
#define HAVE_SIGACTION 1
#define HAVE_SETSID 1
#define POSIX_SIGNAL 1
#define BSD_SETPGRP setpgrp
#define RSHIFT(x,y) ((x)>>y)
#define FILE_COUNT _cnt
#define DLEXT ".o"
#define RUBY_LIB "/usr/local/lib/ruby/1.4"
#define RUBY_SITE_LIB "/usr/local/lib/ruby/1.4/site_ruby"
#define RUBY_PLATFORM "i386-djgpp"
#define RUBY_ARCHLIB "/usr/local/lib/ruby/1.4/i386-djgpp"
#define RUBY_SITE_ARCHLIB "/usr/local/lib/ruby/1.4/site_ruby/i386-djgpp"

56
config_s.dj Normal file
View file

@ -0,0 +1,56 @@
s%@CFLAGS@%-O2%g
s%@CPPFLAGS@%%g
s%@CXXFLAGS@%%g
s%@DEFS@% -DUSE_THREAD=1 -DSIZEOF_INT=4 -DSIZEOF_LONG=4 -DSIZEOF_VOIDP=4 -DHAVE_PROTOTYPES=1 -DHAVE_STDARG_PROTOTYPES=1 -DHAVE_ATTR_NORETURN=1 -DHAVE_DIRENT_H=1 -DSTDC_HEADERS=1 -DHAVE_STDLIB_H=1 -DHAVE_UNISTD_H=1 -DHAVE_LIMITS_H=1 -DHAVE_SYS_FILE_H=1 -DHAVE_SYS_IOCTL_H=1 -DHAVE_PWD_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_TIMES_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_WAIT_H=1 -DHAVE_STRING_H=1 -DHAVE_UTIME_H=1 -DHAVE_MEMORY_H=1 -DHAVE_DIRECT_H=1 -DHAVE_ST_BLKSIZE=1 -DHAVE_ST_RDEV=1 -DGETGROUPS_T=gid_t -DRETSIGTYPE=void -DHAVE_ALLOCA=1 -Dvfork=fork -DHAVE_DUP2=1 -DHAVE_SETENV=1 -DHAVE_MEMMOVE=1 -DHAVE_MKDIR=1 -DHAVE_STRCASECMP=1 -DHAVE_STRERROR=1 -DHAVE_STRFTIME=1 -DHAVE_STRCHR=1 -DHAVE_STRSTR=1 -DHAVE_STRTOUL=1 -DHAVE_STRDUP=1 -DHAVE_FMOD=1 -DHAVE_RANDOM=1 -DHAVE_WAITPID=1 -DHAVE_GETCWD=1 -DHAVE_TRUNCATE=1 -DHAVE_CHSIZE=1 -DHAVE_TIMES=1 -DHAVE_UTIMES=1 -DHAVE_FCNTL=1 -DHAVE_SETITIMER=1 -DHAVE_GETGROUPS=1 -DHAVE_SIGPROCMASK=1 -DHAVE_SIGACTION=1 -DHAVE_SETSID=1 -DPOSIX_SIGNAL=1 -DBSD_SETPGRP=setpgrp -DRSHIFT=\(x,y\)\ \(\(x\)\>\>y\) -DFILE_COUNT=_cnt -DDLEXT=\".so\" -DRUBY_LIB=\"/usr/local/lib/ruby\" -DRUBY_SITE_LIB=\"/usr/local/lib/ruby/site_ruby\" -DRUBY_ARCHLIB=\"/usr/local/lib/ruby/i386-djgpp\" -DRUBY_SITE_ARCHLIB=\"/usr/local/lib/ruby/site_ruby/i386-djgpp\" -DRUBY_PLATFORM=\"i386-djgpp\" %g
s%@LDFLAGS@%%g
s%@LIBS@%-lm %g
s%@exec_prefix@%${prefix}%g
s%@prefix@%/usr/local%g
s%@program_transform_name@%s,x,x,%g
s%@bindir@%${exec_prefix}/bin%g
s%@sbindir@%${exec_prefix}/sbin%g
s%@libexecdir@%${exec_prefix}/libexec%g
s%@datadir@%${prefix}/share%g
s%@sysconfdir@%${prefix}/etc%g
s%@sharedstatedir@%${prefix}/com%g
s%@localstatedir@%${prefix}/var%g
s%@libdir@%${exec_prefix}/lib%g
s%@includedir@%${prefix}/include%g
s%@oldincludedir@%/usr/include%g
s%@infodir@%${prefix}/info%g
s%@mandir@%${prefix}/man%g
s%@host@%i386-pc-djgpp%g
s%@host_alias@%i386-djgpp%g
s%@host_cpu@%i386%g
s%@host_vendor@%pc%g
s%@host_os@%djgpp%g
s%@CC@%gcc%g
s%@CPP@%gcc -E%g
s%@YACC@%bison -y%g
s%@RANLIB@%ranlib%g
s%@AR@%ar%g
s%@INSTALL_PROGRAM@%${INSTALL}%g
s%@INSTALL_DATA@%${INSTALL} -m 644%g
s%@SET_MAKE@%%g
s%@LIBOBJS@% crypt.o flock.o fnmatch.o snprintf.o%g
s%@ALLOCA@%%g
s%@DEFAULT_KCODE@%%g
s%@EXEEXT@%.exe%g
s%@OBJEXT@%o%g
s%@DLDFLAGS@%%g
s%@STATIC@%%g
s%@CCDLFLAGS@%%g
s%@LDSHARED@%ld%g
s%@DLEXT@%o%g
s%@STRIP@%strip%g
s%@EXTSTATIC@%%g
s%@binsuffix@%.exe%g
s%@setup@%Setup%g
s%@LIBRUBY@%libruby.a%g
s%@LIBRUBY_A@%libruby.a%g
s%@LIBRUBYARG@%libruby.a%g
s%@LIBRUBY_SO@%%g
s%@SOLIBS@%%g
s%@srcdir%.%g
s%@arch@%i386-djgpp%g
ac_given_srcdir=.

1490
configure vendored

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,24 @@
@echo off @echo off
sed -f top.sed Makefile.in >Makefile grep -qs MAJOR top.sed
sed -f top.sed ext/extmk.rb.in > ext\extmk.rb if errorlevel 1 goto seen
copy ext\Setup.dj ext\Setup if errorlevel 0 goto not_seen
:seen
sed -n "/VERSION /s/[^0-9.]//gp" < version.h > version.out
cut -d. -f1 version.out > major.out
cut -d. -f2 version.out > minor.out
cut -d. -f3 version.out > teeny.out
sed "s/^/s,@MAJOR@,/;s/$/,/g" major.out >> top.sed
sed "s/^/s,@MINOR@,/;s/$/,/g" minor.out >> top.sed
sed "s/^/s,@TEENY@,/;s/$/,/g" teeny.out >> top.sed
rm version.out major.out minor.out teeny.out
:not_seen
sed -f top.sed < Makefile.in > Makefile
sed -f top.sed < ext\extmk.rb.in > ext\extmk.rb
copy config_h.dj config.h copy config_h.dj config.h
copy config_s.dj config.status if not (%OS%) == (Windows_NT) goto LFN
copy missing\vsnprintf.c missing\vsnprint.c
copy config_s.dj config.sta
goto end
:LFN
copy config_s.dj config.status
:end

View file

@ -1,6 +1,13 @@
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
AC_INIT(ruby.h) AC_INIT(ruby.h)
rb_version=`grep RUBY_VERSION $srcdir/version.h`
MAJOR=`expr "$rb_version" : '#define RUBY_VERSION "\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*"'`
MINOR=`expr "$rb_version" : '#define RUBY_VERSION "[0-9][0-9]*\.\([0-9][0-9]*\)\.[0-9][0-9]*"'`
TEENY=`expr "$rb_version" : '#define RUBY_VERSION "[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\)"'`
AC_SUBST(MAJOR)
AC_SUBST(MINOR)
AC_SUBST(TEENY)
dnl checks for alternative programs dnl checks for alternative programs
AC_ARG_WITH(gcc, [--without-gcc never use gcc], [ AC_ARG_WITH(gcc, [--without-gcc never use gcc], [
case $withval in case $withval in
@ -18,42 +25,25 @@ then
(it is also a good idea to do 'make clean' before compiling)) (it is also a good idea to do 'make clean' before compiling))
fi fi
dnl checks for thread
rb_thread=yes
AC_ARG_ENABLE(thread, [--disable-thread never use user-level thread], [
rb_thread=$enableval
])
if test $rb_thread = yes; then
AC_DEFINE(USE_THREAD)
fi
AC_CANONICAL_HOST AC_CANONICAL_HOST
dnl checks for fat-binary dnl checks for fat-binary
fat_binary=no fat_binary=no
AC_ARG_ENABLE( fat-binary, AC_ARG_ENABLE(fat-binary,
[--enable-fat-binary build a NeXT/Apple Multi Architecture Binary. ], [--enable-fat-binary build a NeXT/Apple Multi Architecture Binary. ],
[ fat_binary=$enableval ] ) [fat_binary=$enableval])
if test "$fat_binary" = yes ; then if test "$fat_binary" = yes ; then
AC_MSG_CHECKING( target architecture ) AC_MSG_CHECKING(target architecture)
case "$host_os" in case "$host_os" in
rhapsody*) rhapsody*)
echo -n "MacOS X Server: " echo -n "MacOS X Server: "
if test "$TARGET_ARCHS" = "" ; then if test "$TARGET_ARCHS" = "" ; then
TARGET_ARCHS="ppc i386" TARGET_ARCHS="ppc i386"
fi fi
;; ;;
nextstep*|openstep*) nextstep*|openstep*)
echo -n "NeXTSTEP/OPENSTEP: "
if test "$host_os" = "rhapsody" ; then
echo -n "Rhapsody: "
if test "$TARGET_ARCHS" = "" ; then
TARGET_ARCHS="ppc i486"
fi
else
echo -n "NeXTSTEP/OPENSTEP: " echo -n "NeXTSTEP/OPENSTEP: "
if test "$TARGET_ARCHS" = "" ; then if test "$TARGET_ARCHS" = "" ; then
if test `/usr/bin/arch` = "m68k" ; then if test `/usr/bin/arch` = "m68k" ; then
@ -62,7 +52,6 @@ AC_ARG_ENABLE( fat-binary,
TARGET_ARCHS="m68k `/usr/bin/arch`" TARGET_ARCHS="m68k `/usr/bin/arch`"
fi fi
fi fi
fi
;; ;;
esac esac
# /usr/lib/arch_tool -archify_list $TARGET_ARCHS # /usr/lib/arch_tool -archify_list $TARGET_ARCHS
@ -71,7 +60,7 @@ AC_ARG_ENABLE( fat-binary,
ARCH_FLAG="$ARCH_FLAG -arch $archs " ARCH_FLAG="$ARCH_FLAG -arch $archs "
echo -n " $archs" echo -n " $archs"
done done
AC_DEFINE( NEXT_FAT_BINARY ) AC_DEFINE(NEXT_FAT_BINARY)
echo "." echo "."
fi fi
@ -84,28 +73,43 @@ AC_PROG_YACC
AC_PROG_RANLIB AC_PROG_RANLIB
AC_SUBST(AR) AC_SUBST(AR)
AC_CHECK_PROGS(AR, ar aal, ar) AC_CHECK_PROGS(AR, ar aal, ar)
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET AC_PROG_MAKE_SET
AC_EXEEXT
AC_OBJEXT
# checks for UNIX variants that set C preprocessor variables # checks for UNIX variants that set C preprocessor variables
AC_MINIX AC_MINIX
AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(short)
AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(long)
AC_CHECK_SIZEOF(void*) AC_CHECK_SIZEOF(void*)
AC_CHECK_SIZEOF(float)
AC_CHECK_SIZEOF(double)
AC_MSG_CHECKING(for prototypes) AC_CACHE_CHECK(for prototypes, rb_cv_have_prototypes,
AC_CACHE_VAL(rb_cv_have_prototypes,
[AC_TRY_COMPILE([int foo(int x) { return 0; }], [return foo(10);], [AC_TRY_COMPILE([int foo(int x) { return 0; }], [return foo(10);],
rb_cv_have_prototypes=yes, rb_cv_have_prototypes=yes,
rb_cv_have_prototypes=no)]) rb_cv_have_prototypes=no)])
AC_MSG_RESULT($rb_cv_have_prototypes)
if test "$rb_cv_have_prototypes" = yes; then if test "$rb_cv_have_prototypes" = yes; then
AC_DEFINE(HAVE_PROTOTYPES) AC_DEFINE(HAVE_PROTOTYPES)
fi fi
AC_MSG_CHECKING(for variable length prototypes and stdarg.h) AC_CACHE_CHECK(token paste string, rb_cv_tokenpaste,
AC_CACHE_VAL(rb_cv_stdarg, [AC_TRY_COMPILE([#define paste(a,b) a##b],
[int xy = 1; return paste(x,y);],
rb_cv_tokenpaste=ansi,
rb_cv_tokenpaste=knr)])
if test "$rb_cv_tokenpaste" = ansi; then
AC_DEFINE(TOKEN_PASTE(x,y),[x##y])
else
AC_DEFINE(TOKEN_PASTE(x,y),[x/**/y])
fi
AC_CACHE_CHECK(for variable length prototypes and stdarg.h, rb_cv_stdarg,
[AC_TRY_COMPILE([ [AC_TRY_COMPILE([
#include <stdarg.h> #include <stdarg.h>
int foo(int x, ...) { int foo(int x, ...) {
@ -119,17 +123,14 @@ int foo(int x, ...) {
], [return foo(10, "", 3.14);], ], [return foo(10, "", 3.14);],
rb_cv_stdarg=yes, rb_cv_stdarg=yes,
rb_cv_stdarg=no)]) rb_cv_stdarg=no)])
AC_MSG_RESULT($rb_cv_stdarg)
if test "$rb_cv_stdarg" = yes; then if test "$rb_cv_stdarg" = yes; then
AC_DEFINE(HAVE_STDARG_PROTOTYPES) AC_DEFINE(HAVE_STDARG_PROTOTYPES)
fi fi
AC_MSG_CHECKING(for gcc attribute noreturn) AC_CACHE_CHECK(for gcc attribute noreturn, rb_cv_have_attr_noreturn,
AC_CACHE_VAL(rb_cv_have_attr_noreturn,
[AC_TRY_COMPILE([void exit(int x) __attribute__ ((noreturn));], [], [AC_TRY_COMPILE([void exit(int x) __attribute__ ((noreturn));], [],
rb_cv_have_attr_noreturn=yes, rb_cv_have_attr_noreturn=yes,
rb_cv_have_attr_noreturn=no)]) rb_cv_have_attr_noreturn=no)])
AC_MSG_RESULT($rb_cv_have_attr_noreturn)
if test "$rb_cv_have_attr_noreturn" = yes; then if test "$rb_cv_have_attr_noreturn" = yes; then
AC_DEFINE(HAVE_ATTR_NORETURN) AC_DEFINE(HAVE_ATTR_NORETURN)
fi fi
@ -141,6 +142,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)
@ -151,9 +153,10 @@ AC_CHECK_LIB(xpg4, setlocale) # FreeBSD needs this
dnl Checks for header files. dnl Checks for header files.
AC_HEADER_DIRENT AC_HEADER_DIRENT
AC_HEADER_STDC AC_HEADER_STDC
AC_CHECK_HEADERS(stdlib.h unistd.h limits.h sys/file.h sys/ioctl.h pwd.h \ AC_HEADER_SYS_WAIT
sys/select.h sys/time.h sys/times.h sys/param.h sys/wait.h\ AC_CHECK_HEADERS(stdlib.h string.h unistd.h limits.h sys/file.h sys/ioctl.h\
syscall.h a.out.h string.h utime.h memory.h direct.h) fcntl.h sys/fcntl.h sys/select.h sys/time.h sys/times.h sys/param.h\
syscall.h pwd.h a.out.h utime.h memory.h direct.h fnmatch.h)
dnl Checks for typedefs, structures, and compiler characteristics. dnl Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_UID_T AC_TYPE_UID_T
@ -170,15 +173,16 @@ AC_TYPE_SIGNAL
AC_FUNC_ALLOCA AC_FUNC_ALLOCA
AC_FUNC_VFORK AC_FUNC_VFORK
AC_FUNC_MEMCMP AC_FUNC_MEMCMP
AC_REPLACE_FUNCS(dup2 memmove mkdir strcasecmp strerror strftime\ AC_REPLACE_FUNCS(dup2 memmove mkdir strcasecmp strncasecmp strerror strftime\
strchr strstr strtoul strdup crypt flock vsnprintf) strchr strstr strtoul strdup crypt flock vsnprintf\
fnmatch isinf isnan finite)
AC_CHECK_FUNCS(fmod killpg drand48 random wait4 waitpid syscall getcwd\ AC_CHECK_FUNCS(fmod killpg drand48 random wait4 waitpid syscall getcwd\
truncate chsize times utimes fcntl lockf setitimer\ truncate chsize times utimes fcntl lockf setitimer\
setruid seteuid setreuid setrgid setegid setregid\ setruid seteuid setreuid setrgid setegid setregid\
setpgrp2 getpgid setpgid getgroups getpriority\ getpgrp setpgrp getpgid setpgid getgroups getpriority\
dlopen sigprocmask sigaction _setjmp setpgrp setsid) dlopen sigprocmask sigaction _setjmp setsid)
AC_STRUCT_TIMEZONE
if test "$ac_cv_func_strftime" = no; then if test "$ac_cv_func_strftime" = no; then
AC_STRUCT_TIMEZONE
AC_TRY_LINK([], AC_TRY_LINK([],
[extern int daylight; int i = daylight;], AC_DEFINE(HAVE_DAYLIGHT)) [extern int daylight; int i = daylight;], AC_DEFINE(HAVE_DAYLIGHT))
fi fi
@ -186,8 +190,7 @@ fi
if test "$ac_cv_func_sigprocmask" = yes && test "$ac_cv_func_sigaction" = yes; then if test "$ac_cv_func_sigprocmask" = yes && test "$ac_cv_func_sigaction" = yes; then
AC_DEFINE(POSIX_SIGNAL) AC_DEFINE(POSIX_SIGNAL)
else else
AC_MSG_CHECKING(for BSD signal semantics) AC_CACHE_CHECK(for BSD signal semantics, rb_cv_bsd_signal,
AC_CACHE_VAL(rb_cv_bsd_signal,
[AC_TRY_RUN([ [AC_TRY_RUN([
#include <stdio.h> #include <stdio.h>
#include <signal.h> #include <signal.h>
@ -208,43 +211,51 @@ main()
} }
], ],
rb_cv_bsd_signal=yes, rb_cv_bsd_signal=yes,
rb_cv_bsd_signal=no,
rb_cv_bsd_signal=no)]) rb_cv_bsd_signal=no)])
AC_MSG_RESULT($rb_cv_bsd_signal)
if test "$rb_cv_bsd_signal" = yes; then if test "$rb_cv_bsd_signal" = yes; then
AC_DEFINE(BSD_SIGNAL) AC_DEFINE(BSD_SIGNAL)
fi fi
fi fi
if test "$ac_cv_func_setpgrp2" = yes; then AC_FUNC_GETPGRP
AC_DEFINE(BSD_GETPGRP, getpgrp2) AC_FUNC_SETPGRP
AC_DEFINE(BSD_SETPGRP, setpgrp2)
else
AC_MSG_CHECKING(whether getpgrp() has arg)
AC_CACHE_VAL(rb_cv_bsdgetpgrp,
[AC_TRY_COMPILE([#include <unistd.h>], [getpgrp(0);],
rb_cv_bsdgetpgrp=yes,
rb_cv_bsdgetpgrp=no)])
AC_MSG_RESULT($rb_cv_bsdgetpgrp)
if test "$rb_cv_bsdgetpgrp" = yes; then
AC_DEFINE(BSD_GETPGRP, getpgrp)
fi
AC_MSG_CHECKING(whether setpgrp() has args) AC_CACHE_CHECK(for working strtod, rb_cv_func_strtod,
AC_CACHE_VAL(rb_cv_bsdsetpgrp, [AC_TRY_RUN([
[AC_TRY_COMPILE([#include <unistd.h>], [setpgrp(1, 1);], double strtod ();
rb_cv_bsdsetpgrp=yes, int
rb_cv_bsdsetpgrp=no)]) main()
AC_MSG_RESULT($rb_cv_bsdsetpgrp) {
if test "$rb_cv_bsdsetpgrp" = yes; then {
AC_DEFINE(BSD_SETPGRP, setpgrp) /* Some versions of Linux strtod mis-parse strings with leading '+'. */
fi char *string = " +69";
fi char *term;
double value;
value = strtod(string, &term);
if (value != 69 || term != (string + 4))
exit(1);
}
{
/* Under Solaris 2.4, strtod returns the wrong value for the
terminating character under some conditions. */
char *string = "NaN";
char *term;
strtod(string, &term);
if (term != string && *(term - 1) == 0)
exit(1);
}
exit(0);
}
], rb_cv_func_strtod=yes, rb_cv_func_strtod=no, rb_cv_func_strtod=no)])
test $rb_cv_func_strtod = no && LIBOBJS="$LIBOBJS strtod.o"
AC_C_BIGENDIAN AC_C_BIGENDIAN
AC_C_CONST
AC_CHAR_UNSIGNED AC_CHAR_UNSIGNED
AC_MSG_CHECKING(whether right shift preserve sign bit) AC_CACHE_CHECK(whether right shift preserve sign bit, rb_cv_rshift_sign,
AC_CACHE_VAL(rb_cv_rshift_sign,
[AC_TRY_RUN([ [AC_TRY_RUN([
int int
main() main()
@ -255,15 +266,15 @@ main()
} }
], ],
rb_cv_rshift_sign=yes, rb_cv_rshift_sign=yes,
rb_cv_rshift_sign=no)]) rb_cv_rshift_sign=no,
AC_MSG_RESULT($rb_cv_rshift_sign) rb_cv_rshift_sign=yes)])
if test "$rb_cv_rshift_sign" = yes; then if test "$rb_cv_rshift_sign" = yes; then
AC_DEFINE(RSHIFT(x,y), ((x)>>y)) AC_DEFINE(RSHIFT(x,y), ((x)>>y))
else else
AC_DEFINE(RSHIFT(x,y), (((x)<0) ? ~((~(x))>>y) : (x)>>y)) AC_DEFINE(RSHIFT(x,y), (((x)<0) ? ~((~(x))>>y) : (x)>>y))
fi fi
AC_MSG_CHECKING([count field in FILE structures]) AC_MSG_CHECKING(count field in FILE structures)
AC_CACHE_VAL(rb_cv_fcnt, AC_CACHE_VAL(rb_cv_fcnt,
[AC_TRY_COMPILE([#include <stdio.h>], [AC_TRY_COMPILE([#include <stdio.h>],
[FILE *f = stdin; f->_cnt = 0;], rb_cv_fcnt="_cnt", ) [FILE *f = stdin; f->_cnt = 0;], rb_cv_fcnt="_cnt", )
@ -278,7 +289,13 @@ fi
if test "$rb_cv_fcnt" = ""; then if test "$rb_cv_fcnt" = ""; then
AC_TRY_COMPILE([#include <stdio.h>], AC_TRY_COMPILE([#include <stdio.h>],
[FILE *f = stdin; f->readCount = 0;], [FILE *f = stdin; f->readCount = 0;],
rb_cv_fcnt="readCount", rb_cv_fcnt="not found") rb_cv_fcnt="readCount", )
fi
dnl for emx0.9c
if test "$rb_cv_fcnt" = ""; then
AC_TRY_COMPILE([#include <stdio.h>],
[FILE *f = stdin; f->_rcount = 0;],
rb_cv_fcnt="_rcount", rb_cv_fcnt="not found")
fi]) fi])
if test "$rb_cv_fcnt" = "not found"; then if test "$rb_cv_fcnt" = "not found"; then
AC_MSG_RESULT([not found(OK if using GNU libc)]) AC_MSG_RESULT([not found(OK if using GNU libc)])
@ -287,17 +304,31 @@ else
AC_DEFINE_UNQUOTED(FILE_COUNT, $rb_cv_fcnt) AC_DEFINE_UNQUOTED(FILE_COUNT, $rb_cv_fcnt)
fi fi
dnl default value for $KANJI
AC_SUBST(DEFAULT_KCODE)
AC_ARG_WITH(default-kcode,
[--with-default-kcode=CODE specify default value for \$KCODE (utf8|euc|sjis|none)],
[case $withval in
utf8) AC_DEFINE(DEFAULT_KCODE, KCODE_UTF8);;
euc) AC_DEFINE(DEFAULT_KCODE, KCODE_EUC);;
sjis) AC_DEFINE(DEFAULT_KCODE, KCODE_SJIS);;
none) AC_DEFINE(DEFAULT_KCODE, KCODE_NONE);;
*) AC_MSG_WARN($withval is not valid kcode; ignored);;
esac])
dnl wheather use dln_a_out ot not dnl wheather use dln_a_out ot not
AC_ARG_WITH(dln-a-out, [--with-dln-a-out use dln_a_out if possible], [ AC_ARG_WITH(dln-a-out,
[--with-dln-a-out use dln_a_out if possible], [
case $withval in case $withval in
yes) with_dln_a_out=yes;; yes) with_dln_a_out=yes;;
*) with_dln_a_out=no;; *) with_dln_a_out=no;;
esac], [with_dln_a_out=no]) esac], [with_dln_a_out=no])
AC_SUBST(XLDFLAGS)dnl
case "$host_os" in case "$host_os" in
linux*) linux*)
AC_MSG_CHECKING(whether ELF binaries are produced) AC_CACHE_CHECK(whether ELF binaries are produced, rb_cv_binary_elf,
AC_CACHE_VAL(rb_cv_linux_elf,
[AC_TRY_RUN([ [AC_TRY_RUN([
/* Test for whether ELF binaries are produced */ /* Test for whether ELF binaries are produced */
#include <fcntl.h> #include <fcntl.h>
@ -315,13 +346,12 @@ main() {
exit(0); /* succeed (yes, it's ELF) */ exit(0); /* succeed (yes, it's ELF) */
} }
], ],
rb_cv_linux_elf=yes, rb_cv_binary_elf=yes,
rb_cv_linux_elf=no, rb_cv_binary_elf=no,
[:])]) rb_cv_binary_elf=yes)])
AC_MSG_RESULT($rb_cv_linux_elf) if test "$rb_cv_binary_elf" = no; then
if test "$rb_cv_linux_elf" = no; then
with_dln_a_out=yes with_dln_a_out=yes
host_os=linux-a.out host_os=${host_os}-a_out
else else
LDFLAGS="-rdynamic" LDFLAGS="-rdynamic"
fi;; fi;;
@ -345,15 +375,21 @@ if test "$with_dln_a_out" != yes; then
openstep*) ;; openstep*) ;;
rhapsody*) ;; rhapsody*) ;;
human*) ;; human*) ;;
cygwin*) CCDLFLAGS=-DDLLIMPORT;; bsdi3*) ;;
*) CCDLFLAGS=-fpic;; cygwin*) ;;
netbsd*) CCDLFLAGS=-fpic
case "$host_cpu" in
mips*) CCDLFLAGS=-fPIC ;;
*) ;;
esac ;;
*) CCDLFLAGS=-fPIC;;
esac esac
else else
case "$host_os" in case "$host_os" in
hpux*) CCDLFLAGS='+z';; hpux*) CCDLFLAGS='+z';;
solaris*|irix*) CCDLFLAGS='-K pic' ;; solaris*|irix*) CCDLFLAGS='-K PIC' ;;
sunos*) CCDLFLAGS='-pic' ;; sunos*) CCDLFLAGS='-PIC' ;;
esix*|uxpds*) CCDLFLAGS='-Kpic' ;; esix*|uxpds*) CCDLFLAGS='-KPIC' ;;
*) CCDLFLAGS='' ;; *) CCDLFLAGS='' ;;
esac esac
fi fi
@ -363,7 +399,12 @@ if test "$with_dln_a_out" != yes; then
LDSHARED='ld -b' LDSHARED='ld -b'
LDFLAGS="-Wl,-E" LDFLAGS="-Wl,-E"
rb_cv_dlopen=yes;; rb_cv_dlopen=yes;;
solaris*) LDSHARED='ld -G' solaris*) if test "$GCC" = yes; then
LDSHARED='$(CC) -Wl,-G'
`$CC --print-prog-name=ld` -v 2>&1 | grep "GNU ld" > /dev/null && LDFLAGS="-Wl,-E"
else
LDSHARED='ld -G'
fi
rb_cv_dlopen=yes;; rb_cv_dlopen=yes;;
sunos*) LDSHARED='ld -assert nodefinitions' sunos*) LDSHARED='ld -assert nodefinitions'
rb_cv_dlopen=yes;; rb_cv_dlopen=yes;;
@ -373,19 +414,29 @@ if test "$with_dln_a_out" != yes; then
rb_cv_dlopen=yes;; rb_cv_dlopen=yes;;
esix*|uxpds*) LDSHARED="ld -G" esix*|uxpds*) LDSHARED="ld -G"
rb_cv_dlopen=yes ;; rb_cv_dlopen=yes ;;
linux*) LDSHARED="gcc -shared" osf*) LDSHARED="$CC -shared"
rb_cv_dlopen=yes ;; rb_cv_dlopen=yes ;;
freebsd3*) LDSHARED="ld -Bshareable" linux*) LDSHARED="$CC -shared"
LDFLAGS="-rdynamic"
rb_cv_dlopen=yes ;; rb_cv_dlopen=yes ;;
freebsd*) LDSHARED="ld -Bshareable" freebsd*) LDSHARED="$CC -shared"
if test -x /usr/bin/objformat && \
test `/usr/bin/objformat` = "elf" ; then
LDFLAGS="-rdynamic"
DLDFLAGS='-Wl,-soname,$(.TARGET)'
rb_cv_freebsd_elf=yes
else
test "$GCC" = yes && `$CC --print-prog-name=ld` -v 2>&1 | grep "GNU ld" > /dev/null || LDSHARED="ld -Bshareable"
fi
rb_cv_dlopen=yes ;; rb_cv_dlopen=yes ;;
netbsd*) LDSHARED="ld -Bshareable" netbsd*) LDSHARED="ld -shared"
rb_cv_dlopen=yes ;; rb_cv_dlopen=yes ;;
openbsd*) LDSHARED="ld -Bforcearchive -Bshareable" openbsd*) LDSHARED="ld -Bforcearchive -Bshareable"
CCDLFLAGS=-fPIC
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 ;;
@ -397,22 +448,30 @@ if test "$with_dln_a_out" != yes; then
LDFLAGS="" LDFLAGS=""
DLDFLAGS="$ARCH_FLAG" DLDFLAGS="$ARCH_FLAG"
rb_cv_dlopen=yes ;; rb_cv_dlopen=yes ;;
aix*) LDSHARED='../../miniruby ../aix_ld.rb $(TARGET)' aix*) LDSHARED='/usr/ccs/bin/ld'
XLDFLAGS='-Wl,-bE:ruby.imp'
DLDFLAGS='-eInit_$(TARGET) -bI:$(topdir)/ruby.imp -bM:SRE -T512 -H512 -lc'
rb_cv_dlopen=yes ;; rb_cv_dlopen=yes ;;
human*) DLDFLAGS='' human*) DLDFLAGS=''
LDSHARED='' LDSHARED=''
LDFLAGS='' ;; LDFLAGS=''
beos*) LDSHARED="ld -xms" rb_cv_dlopen=yes ;;
case "$host_cpu" in beos*) case "$host_cpu" in
powerpc*) powerpc*)
LDSHARED="ld -xms"
DLDFLAGS="-f ruby.exp -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o" DLDFLAGS="-f ruby.exp -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o"
;; ;;
i586*)
LDSHARED="ld -shared"
DLDFLAGS="-L/boot/develop/lib/x86 -lbe -lroot"
;;
*) *)
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 ;;
*) LDSHARED='ld' ;; *) LDSHARED='ld' ;;
esac esac
AC_MSG_RESULT($rb_cv_dlopen) AC_MSG_RESULT($rb_cv_dlopen)
@ -421,9 +480,8 @@ fi
dln_a_out_works=no dln_a_out_works=no
if test "$ac_cv_header_a_out_h" = yes; then if test "$ac_cv_header_a_out_h" = yes; then
if test "$with_dln_a_out" = yes || test "$rb_cv_dlopen" = unknown; then if test "$with_dln_a_out" = yes || test "$rb_cv_dlopen" = unknown; then
AC_MSG_CHECKING(whether matz's dln works)
cat confdefs.h > config.h cat confdefs.h > config.h
AC_CACHE_VAL(rb_cv_dln_a_out, AC_CACHE_CHECK(whether matz's dln works, rb_cv_dln_a_out,
[AC_TRY_COMPILE([ [AC_TRY_COMPILE([
#define USE_DLN_A_OUT #define USE_DLN_A_OUT
#include "dln.c" #include "dln.c"
@ -431,7 +489,6 @@ if test "$ac_cv_header_a_out_h" = yes; then
[], [],
rb_cv_dln_a_out=yes, rb_cv_dln_a_out=yes,
rb_cv_dln_a_out=no)]) rb_cv_dln_a_out=no)])
AC_MSG_RESULT($rb_cv_dln_a_out)
if test "$rb_cv_dln_a_out" = yes; then if test "$rb_cv_dln_a_out" = yes; then
dln_a_out_works=yes dln_a_out_works=yes
AC_DEFINE(USE_DLN_A_OUT) AC_DEFINE(USE_DLN_A_OUT)
@ -445,21 +502,23 @@ 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
AC_DEFINE(DLEXT, ".bundle");; AC_DEFINE(DLEXT, ".bundle");;
cygwin*) DLEXT=dll cygwin*) DLEXT=dll
AC_DEFINE(DLEXT, ".dll");; AC_DEFINE(DLEXT, ".dll");;
os2_emx) DLEXT=o
AC_DEFINE(DLEXT, ".so");;
*) DLEXT=so *) DLEXT=so
AC_DEFINE(DLEXT, ".so");; AC_DEFINE(DLEXT, ".so");;
esac esac
@ -498,8 +557,8 @@ case "$host_os" in
AC_CHECK_LIB(signal, _harderr) AC_CHECK_LIB(signal, _harderr)
AC_CHECK_LIB(hmem, hmemset) AC_CHECK_LIB(hmem, hmemset)
AC_CHECK_FUNCS(select) AC_CHECK_FUNCS(select)
AC_MSG_CHECKING(whether PD libc _dtos18 fail to convert big number) AC_CACHE_CHECK(whether PD libc _dtos18 fail to convert big number,
AC_CACHE_VAL(rb_cv_missing__dtos18, rb_cv_missing__dtos18,
[AC_TRY_RUN( [AC_TRY_RUN(
changequote(<<, >>)dnl changequote(<<, >>)dnl
<< <<
@ -512,13 +571,12 @@ main ()
} }
>>, >>,
changequote([, ])dnl changequote([, ])dnl
rb_cv_missing__dtos18=yes, rb_cv_missing__dtos18=no)]) rb_cv_missing__dtos18=yes, rb_cv_missing__dtos18=no, rb_cv_missing__dtos18=no)])
AC_MSG_RESULT($rb_cv_missing__dtos18)
if test "$rb_cv_missing__dtos18" = yes; then if test "$rb_cv_missing__dtos18" = yes; then
AC_DEFINE(MISSING__DTOS18) AC_DEFINE(MISSING__DTOS18)
fi fi
AC_MSG_CHECKING(whether PD libc fconvert fail to round) AC_CACHE_CHECK(whether PD libc fconvert fail to round,
AC_CACHE_VAL(rb_cv_missing_fconvert, rb_cv_missing_fconvert,
[AC_TRY_RUN( [AC_TRY_RUN(
changequote(<<, >>)dnl changequote(<<, >>)dnl
<< <<
@ -532,29 +590,29 @@ main ()
} }
>>, >>,
changequote([, ])dnl changequote([, ])dnl
rb_cv_missing_fconvert=yes, rb_cv_missing_fconvert=no)]) rb_cv_missing_fconvert=yes, rb_cv_missing_fconvert=no, rb_cv_missing_fconvert=no)])
AC_MSG_RESULT($rb_cv_missing_fconvert)
if test "$rb_cv_missing_fconvert" = yes; then if test "$rb_cv_missing_fconvert" = yes; then
AC_DEFINE(MISSING_FCONVERT) AC_DEFINE(MISSING_FCONVERT)
fi fi
LIBOBJS="$LIBOBJS x68.o" LIBOBJS="$LIBOBJS x68.o"
CFLAGS="$CFLAGS -fansi-only -cc1-stack=196608 -cpp-stack=2694144" CFLAGS="$CFLAGS -fansi-only -cc1-stack=196608 -cpp-stack=2694144"
binsuffix=.x EXEEXT=.x
OBJEXT=o
setup=Setup.x68 setup=Setup.x68
;; ;;
dnl OS/2 environment w/ Autoconf 2.1x for EMX
os2_emx)
LIBOBJS="$LIBOBJS os2.o"
setup=Setup.emx
;;
cygwin*) cygwin*)
binsuffix=.exe
setup=Setup setup=Setup
;; ;;
*) *)
binsuffix=
setup=Setup setup=Setup
;; ;;
esac esac
AC_SUBST(binsuffix)
AC_SUBST(setup) AC_SUBST(setup)
if test "$prefix" = NONE; then if test "$prefix" = NONE; then
@ -565,18 +623,22 @@ if test "$fat_binary" = yes ; then
CFLAGS="$CFLAGS $ARCH_FLAG" CFLAGS="$CFLAGS $ARCH_FLAG"
fi fi
LIBRUBY='libruby.a' LIBRUBY_A='lib$(RUBY_INSTALL_NAME).a'
LIBRUBYARG='libruby.a' LIBRUBY='$(LIBRUBY_A)'
LIBRUBYARG='$(LIBRUBY_A)'
SOLIBS= SOLIBS=
if test "$host_os" = "beos"; then if test "$host_os" = "beos"; then
CFLAGS="$CFLAGS -relax_pointers" LIBRUBY='$(LIBRUBY_SO)'
LIBRUBY='libruby.so' LIBRUBYARG='-l$(RUBY_INSTALL_NAME)'
LIBRUBYARG='-lruby'
SOLIBS='-lnet' SOLIBS='-lnet'
echo creating ruby.def echo creating ruby.def
case "$host_cpu" in case "$host_cpu" in
powerpc*) powerpc*)
cp beos/ruby.def.in ruby.exp cp beos/ruby.def.in ruby.exp
CFLAGS="$CFLAGS -relax_pointers"
;;
i586*)
LDFLAGS="$LDFLAGS -L."
;; ;;
*) *)
echo EXPORTS > ruby.def echo EXPORTS > ruby.def
@ -585,9 +647,72 @@ if test "$host_os" = "beos"; then
esac esac
fi fi
FIRSTMAKEFILE=""
LIBRUBY_LDSHARED=$LDSHARED
LIBRUBY_DLDFLAGS=$DLDFLAGS
LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR).$(TEENY)'
LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so'
AC_ARG_ENABLE(enable-shared,
[--enable-shared build a shared library for Ruby. ],
[enable_shared=$enableval])
if test "$enable_shared" = 'yes'; then if test "$enable_shared" = 'yes'; then
LIBRUBY='libruby.so' LIBRUBY='$(LIBRUBY_SO)'
LIBRUBYARG='-L./ -lruby' LIBRUBYARG='-L. -l$(RUBY_INSTALL_NAME)'
CFLAGS="$CFLAGS $CCDLFLAGS"
case "$host_os" in
sunos4*)
LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).so'
;;
linux*)
XLDFLAGS='-Wl,-rpath,${prefix}/lib':/usr/lib:/lib
LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).so'
;;
freebsd*)
LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR)$(MINOR)'
if test "$rb_cv_freebsd_elf" != "yes" ; then
LIBRUBY_SO="$LIBRUBY_SO.\$(TEENY)"
LIBRUBY_ALIASES=''
fi
;;
netbsd*)
LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR)'
case "$host_cpu" in
alpha|mipsel|mipseb|powerpc|sparc64) # ELF platforms
LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR) lib$(RUBY_INSTALL_NAME).so' ;;
*) LIBRUBY_ALIASES= ;; # a.out platforms
esac
;;
solaris*)
XLDFLAGS='-R${prefix}/lib'
;;
hpux*)
XLDFLAGS='-Wl,+s,+b,$(prefix)/lib'
LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).sl.$(MAJOR).$(MINOR).$(TEENY)'
LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).sl.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).sl'
;;
aix*)
if test "$GCC" = yes; then
LIBRUBY_LDSHARED='$(CC) -shared'
LIBRUBY_DLDFLAGS='-Wl,-bE:ruby.imp'
else
LIBRUBY_LDSHARED='/usr/ccs/bin/ld'
LIBRUBY_DLDFLAGS='-bE:ruby.imp -bM:SRE -bnoentry'
fi
LIBRUBYARG='-L${prefix}/lib -Wl,lib$(RUBY_INSTALL_NAME).so'
SOLIBS='-lm -lc'
;;
cygwin*)
LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).a'
LIBRUBY_ALIASES=''
LIBRUBY_A='lib$(RUBY_INSTALL_NAME)s.a'
LIBRUBYARG='-L. -l$(RUBY_INSTALL_NAME)'
FIRSTMAKEFILE=GNUmakefile:cygwin/GNUmakefile.in
LIBOBJS="$LIBOBJS strftime.o"
CCDLFLAGS=-DUSEIMPORTLIB
;;
*)
;;
esac
fi fi
case "$host_os" in case "$host_os" in
@ -604,7 +729,12 @@ case "$host_os" in
;; ;;
esac esac
AC_SUBST(LIBRUBY_LDSHARED)
AC_SUBST(LIBRUBY_DLDFLAGS)
AC_SUBST(RUBY_INSTALL_NAME)
AC_SUBST(LIBRUBY_A)
AC_SUBST(LIBRUBY_SO)
AC_SUBST(LIBRUBY_ALIASES)
AC_SUBST(LIBRUBY) AC_SUBST(LIBRUBY)
AC_SUBST(LIBRUBYARG) AC_SUBST(LIBRUBYARG)
AC_SUBST(SOLIBS) AC_SUBST(SOLIBS)
@ -618,30 +748,39 @@ test "$program_suffix" != NONE &&
ri_suffix=$program_suffix ri_suffix=$program_suffix
RUBY_INSTALL_NAME="${ri_prefix}ruby${ri_suffix}" RUBY_INSTALL_NAME="${ri_prefix}ruby${ri_suffix}"
AC_DEFINE_UNQUOTED(RUBY_LIB, "${prefix}/lib/${RUBY_INSTALL_NAME}") RUBY_LIB_PATH="${prefix}/lib/ruby/${MAJOR}.${MINOR}"
AC_DEFINE_UNQUOTED(RUBY_SITE_LIB, "${prefix}/lib/${RUBY_INSTALL_NAME}/site_ruby") AC_DEFINE_UNQUOTED(RUBY_LIB, "${RUBY_LIB_PATH}")
RUBY_SITE_LIB_PATH="${RUBY_LIB_PATH}/site_ruby"
AC_DEFINE_UNQUOTED(RUBY_SITE_LIB, "${RUBY_SITE_LIB_PATH}")
AC_SUBST(arch)dnl AC_SUBST(arch)dnl
configure_args=$ac_configure_args
AC_SUBST(configure_args)dnl
if test "$fat_binary" = yes ; then if test "$fat_binary" = yes ; then
arch="fat-${host_os}" arch="fat-${host_os}"
AC_DEFINE_UNQUOTED(RUBY_THIN_ARCHLIB, AC_DEFINE_UNQUOTED(RUBY_THIN_ARCHLIB,
"${prefix}/lib/${RUBY_INSTALL_NAME}/" __ARCHITECTURE__ "-${host_os}" ) "${RUBY_LIB_PATH}/" __ARCHITECTURE__ "-${host_os}")
AC_DEFINE_UNQUOTED(RUBY_SITE_THIN_ARCHLIB, AC_DEFINE_UNQUOTED(RUBY_SITE_THIN_ARCHLIB,
"${prefix}/lib/${RUBY_INSTALL_NAME}/" __ARCHITECTURE__ "-${host_os}" ) "${RUBY_SITE_LIB_PATH}/" __ARCHITECTURE__ "-${host_os}")
AC_DEFINE_UNQUOTED(RUBY_PLATFORM, __ARCHITECTURE__ "-${host_os}")
AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "${prefix}/lib/${RUBY_INSTALL_NAME}/${arch}")
AC_DEFINE_UNQUOTED(RUBY_SITE_ARCHLIB, "${prefix}/lib/${RUBY_INSTALL_NAME}/site_ruby/${arch}")
AC_DEFINE_UNQUOTED(RUBY_PLATFORM, __ARCHITECTURE__ "-${host_os}" )
else else
arch="${host_cpu}-${host_os}" arch="${host_cpu}-${host_os}"
AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "${prefix}/lib/${RUBY_INSTALL_NAME}/${arch}")
AC_DEFINE_UNQUOTED(RUBY_SITE_ARCHLIB, "${prefix}/lib/${RUBY_INSTALL_NAME}/site_ruby/${arch}")
AC_DEFINE_UNQUOTED(RUBY_PLATFORM, "${arch}") AC_DEFINE_UNQUOTED(RUBY_PLATFORM, "${arch}")
fi fi
AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "${RUBY_LIB_PATH}/${arch}")
AC_DEFINE_UNQUOTED(RUBY_SITE_ARCHLIB, "${RUBY_SITE_LIB_PATH}/${arch}")
AC_ARG_WITH(search-path,
[--with-search-path specify the additional search path],
[search_path=$withval])
if test "$search_path" != ""; then
AC_DEFINE_UNQUOTED(RUBY_SEARCH_PATH,"$search_path")
fi
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)

9
cygwin/GNUmakefile.in Normal file
View file

@ -0,0 +1,9 @@
include Makefile
RUBYCWDLL=rubycw.dll
miniruby$(EXEEXT): $(RUBYCWDLL)
$(RUBYCWDLL): $(OBJS) dmyext.o
dllwrap -o $(RUBYCWDLL) --export-all --output-lib=$(LIBRUBY_SO) --dllname=$(RUBYCWDLL) -Wl,-e,__cygwin_noncygwin_dll_entry@12 --add-stdcall-alias -s $(OBJS) dmyext.o
nm --extern-only $(OBJS) dmyext.o | sed -n '/^........ [CD] _\(.*\)$$/s//#define \1 (*__imp_\1)/p' >import.h

View file

@ -13,12 +13,12 @@
#define RUBY #define RUBY
/* define RUBY_USE_EUC/SJIS for default kanji-code */ /* define RUBY_USE_EUC/SJIS for default kanji-code */
#if defined(MSDOS) || defined(__CYGWIN32__) || defined(__human68k__) || defined(__MACOS__) #ifndef DEFAULT_KCODE
#undef RUBY_USE_EUC #if defined(MSDOS) || defined(__CYGWIN32__) || defined(__human68k__) || defined(__MACOS__) || defined(__EMX__) || defined(OS2)
#define RUBY_USE_SJIS #define DEFAULT_KCODE KCODE_SJIS
#else #else
#define RUBY_USE_EUC #define DEFAULT_KCODE KCODE_EUC
#undef RUBY_USE_SJIS #endif
#endif #endif
#ifdef NeXT #ifdef NeXT
@ -31,7 +31,7 @@
#endif /* NeXT */ #endif /* NeXT */
#ifdef NT #ifdef NT
#include "missing/nt.h" #include "win32/win32.h"
#endif #endif
#ifndef EXTERN #ifndef EXTERN
@ -44,12 +44,17 @@
#define FLUSH_REGISTER_WINDOWS /* empty */ #define FLUSH_REGISTER_WINDOWS /* empty */
#endif #endif
#if defined(MSDOS) || defined(NT) || defined(__human68k__) || defined(__MACOS__) #if defined(MSDOS) || defined(_WIN32) || defined(__human68k__) || defined(__EMX__)
#define RUBY_PATH_SEP ";" #define DOSISH 1
#else
#define RUBY_PATH_SEP ":"
#endif #endif
#if defined(MSDOS) || defined(NT) || defined(__human68k__)
#define PATH_SEP ";"
#else
#define PATH_SEP ":"
#endif
#define PATH_SEP_CHAR PATH_SEP[0]
#if defined(__human68k__) || defined(__CYGWIN32__) #if defined(__human68k__) || defined(__CYGWIN32__)
#undef HAVE_RANDOM #undef HAVE_RANDOM
#undef HAVE_SETITIMER #undef HAVE_SETITIMER

234
dir.c
View file

@ -6,7 +6,7 @@
$Date$ $Date$
created at: Wed Jan 5 09:51:01 JST 1994 created at: Wed Jan 5 09:51:01 JST 1994
Copyright (C) 1993-1998 Yukihiro Matsumoto Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/ ************************************************/
@ -47,14 +47,23 @@
# endif # endif
#endif #endif
#include <errno.h> #ifdef HAVE_FNMATCH_H
#include <fnmatch.h>
#else
#include "missing/fnmatch.h"
#endif
#ifndef NT #include <errno.h>
#ifdef USE_CWGUSI
# include <sys/errno.h>
#endif
#ifndef HAVE_STDLIB_H
char *getenv(); char *getenv();
#endif #endif
#ifdef USE_CWGUSI #ifndef HAVE_STRING_H
# include <sys/errno.h> char *strchr _((char*,char));
#endif #endif
VALUE rb_cDir; VALUE rb_cDir;
@ -149,10 +158,10 @@ static VALUE
dir_tell(dir) dir_tell(dir)
VALUE dir; VALUE dir;
{ {
DIR *dirp;
int pos;
#if !defined(__CYGWIN32__) && !defined(__BEOS__) #if !defined(__CYGWIN32__) && !defined(__BEOS__)
DIR *dirp;
long pos;
GetDIR(dir, dirp); GetDIR(dir, dirp);
pos = telldir(dirp); pos = telldir(dirp);
return rb_int2inum(pos); return rb_int2inum(pos);
@ -248,7 +257,7 @@ static VALUE
dir_s_chroot(dir, path) dir_s_chroot(dir, path)
VALUE dir, path; VALUE dir, path;
{ {
#if !defined(DJGPP) && !defined(NT) && !defined(__human68k__) && !defined(USE_CWGUSI) && !defined(__BEOS__) #if !defined(DJGPP) && !defined(NT) && !defined(__human68k__) && !defined(USE_CWGUSI) && !defined(__BEOS__) && !defined(__EMX__)
rb_secure(2); rb_secure(2);
Check_SafeStr(path); Check_SafeStr(path);
@ -303,29 +312,169 @@ dir_s_rmdir(obj, dir)
return Qtrue; return Qtrue;
} }
#define isdelim(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\0') /* Return nonzero if S has any special globbing chars in it. */
static int
has_magic(s, send)
char *s, *send;
{
register char *p = s;
register char c;
int open = 0;
char **glob_filename(); while ((c = *p++) != '\0') {
extern char *glob_error_return; switch (c) {
case '?':
case '*':
return Qtrue;
case '[': /* Only accept an open brace if there is a close */
open++; /* brace to match it. Bracket expressions must be */
continue; /* complete, according to Posix.2 */
case ']':
if (open)
return Qtrue;
continue;
case '\\':
if (*p++ == '\0')
return Qfalse;
}
if (send && p >= send) break;
}
return Qfalse;
}
static char*
extract_path(p, pend)
char *p, *pend;
{
char *alloc;
int len;
len = pend - p;
alloc = ALLOC_N(char, len+1);
memcpy(alloc, p, len);
if (len > 0 && pend[-1] == '/') {
alloc[len-1] = 0;
}
else {
alloc[len] = 0;
}
return alloc;
}
static char*
extract_elem(path)
char *path;
{
char *pend;
pend = strchr(path, '/');
if (!pend) pend = path + strlen(path);
return extract_path(path, pend);
}
#ifndef S_ISDIR
# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
#endif
static void
glob(path, func, arg)
char *path;
void (*func)();
VALUE arg;
{
struct stat st;
char *p, *m;
if (!has_magic(path, 0)) {
if (stat(path, &st) == 0) {
(*func)(path, arg);
}
return;
}
p = path;
while (p) {
if (*p == '/') p++;
m = strchr(p, '/');
if (has_magic(p, m)) {
char *dir, *base, *magic;
DIR *dirp;
struct dirent *dp;
struct d_link {
char *path;
struct d_link *next;
} *tmp, *link = 0;
base = extract_path(path, p);
if (path == p) dir = ".";
else dir = base;
dirp = opendir(dir);
if (dirp == NULL) {
free(base);
break;
}
magic = extract_elem(p);
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
if (fnmatch(magic, dp->d_name, FNM_PERIOD|FNM_PATHNAME) == 0) {
char *fix = ALLOC_N(char, strlen(base)+NAMLEN(dp)+2);
sprintf(fix, "%s%s%s", base, (*base)?"/":"", dp->d_name);
if (!m) {
(*func)(fix, arg);
free(fix);
continue;
}
tmp = ALLOC(struct d_link);
tmp->path = fix;
tmp->next = link;
link = tmp;
}
}
closedir(dirp);
free(base);
free(magic);
while (link) {
stat(link->path, &st); /* should success */
if (S_ISDIR(st.st_mode)) {
int len = strlen(link->path);
int mlen = strlen(m);
char *t = ALLOC_N(char, len+mlen+1);
sprintf(t, "%s%s", link->path, m);
glob(t, func, arg);
free(t);
}
tmp = link;
link = link->next;
free(tmp->path);
free(tmp);
}
}
p = m;
}
}
static void
push_pattern(path, ary)
char *path;
VALUE ary;
{
rb_ary_push(ary, rb_tainted_str_new2(path));
}
static void static void
push_globs(ary, s) push_globs(ary, s)
VALUE ary; VALUE ary;
char *s; char *s;
{ {
char **fnames, **ff; glob(s, push_pattern, ary);
fnames = glob_filename(s);
if (fnames == (char**)-1) rb_sys_fail(s);
ff = fnames;
while (*ff) {
rb_ary_push(ary, rb_tainted_str_new2(*ff));
free(*ff);
ff++;
}
if (fnames != &glob_error_return) {
free(fnames);
}
} }
static void static void
@ -333,9 +482,10 @@ push_braces(ary, s)
VALUE ary; VALUE ary;
char *s; char *s;
{ {
char buf[MAXPATHLEN]; char buffer[MAXPATHLEN], *buf = buffer;
char *p, *t, *b; char *p, *t, *b;
char *lbrace, *rbrace; char *lbrace, *rbrace;
int nest = 0;
p = s; p = s;
lbrace = rbrace = 0; lbrace = rbrace = 0;
@ -347,7 +497,8 @@ push_braces(ary, s)
p++; p++;
} }
while (*p) { while (*p) {
if (*p == '}' && lbrace) { if (*p == '{') nest++;
if (*p == '}' && --nest == 0) {
rbrace = p; rbrace = p;
break; break;
} }
@ -355,6 +506,9 @@ push_braces(ary, s)
} }
if (lbrace) { if (lbrace) {
int len = strlen(s);
if (len >= MAXPATHLEN)
buf = xmalloc(len + 1);
memcpy(buf, s, lbrace-s); memcpy(buf, s, lbrace-s);
b = buf + (lbrace-s); b = buf + (lbrace-s);
p = lbrace; p = lbrace;
@ -368,46 +522,44 @@ push_braces(ary, s)
strcpy(b+(p-t), rbrace+1); strcpy(b+(p-t), rbrace+1);
push_braces(ary, buf); push_braces(ary, buf);
} }
if (buf != buffer)
free(buf);
} }
else { else {
push_globs(ary, s); push_globs(ary, s);
} }
} }
#define isdelim(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\0')
static VALUE static VALUE
dir_s_glob(dir, str) dir_s_glob(dir, str)
VALUE dir, str; VALUE dir, str;
{ {
char *p, *pend; char *p, *pend;
char buf[MAXPATHLEN]; char buffer[MAXPATHLEN], *buf = buffer;
char *t, *t0; char *t;
int nest; int nest;
VALUE ary; VALUE ary;
Check_SafeStr(str); Check_SafeStr(str);
if (RSTRING(str)->len > MAXPATHLEN) {
rb_raise(rb_eArgError, "pathname too long (%d bytes)",
RSTRING(str)->len);
}
ary = rb_ary_new(); ary = rb_ary_new();
if (RSTRING(str)->len >= MAXPATHLEN)
buf = xmalloc(RSTRING(str)->len + 1);
p = RSTRING(str)->ptr; p = RSTRING(str)->ptr;
pend = p + RSTRING(str)->len; pend = p + RSTRING(str)->len;
while (p < pend) { while (p < pend) {
t = buf; t = buf;
nest = 0;
while (p < pend && isdelim(*p)) p++; while (p < pend && isdelim(*p)) p++;
while (p < pend && !isdelim(*p)) { while (p < pend && !isdelim(*p)) {
if (*p == '{') nest+=2;
if (*p == '}') nest+=3;
*t++ = *p++; *t++ = *p++;
} }
*t = '\0'; *t = '\0';
t0 = buf;
nest = 0;
while (t0 < t) {
if (*t0 == '{') nest+=2;
if (*t0 == '}') nest+=3;
t0++;
}
if (nest == 0) { if (nest == 0) {
push_globs(ary, buf); push_globs(ary, buf);
} }
@ -416,6 +568,8 @@ dir_s_glob(dir, str)
} }
/* else unmatched braces */ /* else unmatched braces */
} }
if (buf != buffer)
free(buf);
return ary; return ary;
} }

162
dln.c
View file

@ -6,7 +6,7 @@
$Date$ $Date$
created at: Tue Jan 18 17:05:06 JST 1994 created at: Tue Jan 18 17:05:06 JST 1994
Copyright (C) 1993-1998 Yukihiro Matsumoto Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/ ************************************************/
@ -30,9 +30,11 @@ char *dln_argv0;
# include <strings.h> # include <strings.h>
#endif #endif
#ifndef xmalloc
void *xmalloc(); void *xmalloc();
void *xcalloc(); void *xcalloc();
void *xrealloc(); void *xrealloc();
#endif
#include <stdio.h> #include <stdio.h>
#ifndef NT #ifndef NT
@ -56,7 +58,6 @@ void *xrealloc();
#endif #endif
#ifndef NT #ifndef NT
char *strdup();
char *getenv(); char *getenv();
#endif #endif
@ -64,6 +65,7 @@ char *getenv();
# include <TextUtils.h> # include <TextUtils.h>
# include <CodeFragments.h> # include <CodeFragments.h>
# include <Aliases.h> # include <Aliases.h>
# include "macruby_private.h"
#endif #endif
#ifdef __BEOS__ #ifdef __BEOS__
@ -78,7 +80,7 @@ int eaccess();
#endif #endif
#ifndef FUNCNAME_PATTERN #ifndef FUNCNAME_PATTERN
# if defined(__hp9000s300) || defined(__NetBSD__) || defined(__BORLANDC__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) || defined(NeXT) || defined(__WATCOMC__) # if defined(__hp9000s300) || (defined(__NetBSD__) && (!defined(__alpha__) && !defined(__mips__))) || defined(__BORLANDC__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) || defined(NeXT) || defined(__WATCOMC__) || defined(__APPLE__)
# define FUNCNAME_PATTERN "_Init_%.200s" # define FUNCNAME_PATTERN "_Init_%.200s"
# else # else
# define FUNCNAME_PATTERN "Init_%.200s" # define FUNCNAME_PATTERN "Init_%.200s"
@ -87,7 +89,8 @@ int eaccess();
static void static void
init_funcname(buf, file) init_funcname(buf, file)
char *buf, *file; char *buf;
char *file;
{ {
char *p, *slash; char *p, *slash;
@ -100,7 +103,7 @@ init_funcname(buf, file)
#endif #endif
sprintf(buf, FUNCNAME_PATTERN, slash + 1); sprintf(buf, FUNCNAME_PATTERN, slash + 1);
for (p = buf; *p; p++) { /* Delete suffix it it exists */ for (p = buf; *p; p++) { /* Delete suffix if it exists */
if (*p == '.') { if (*p == '.') {
*p = '\0'; break; *p = '\0'; break;
} }
@ -315,7 +318,7 @@ sym_hash(hdrp, syms)
static int static int
dln_init(prog) dln_init(prog)
char *prog; const char *prog;
{ {
char *file; char *file;
int fd; int fd;
@ -423,7 +426,7 @@ load_text_data(fd, hdrp, bss, disp)
} }
static int static int
underb_f_print(key, value) undef_print(key, value)
char *key, *value; char *key, *value;
{ {
fprintf(stderr, " %s\n", key); fprintf(stderr, " %s\n", key);
@ -434,7 +437,7 @@ static void
dln_print_undef() dln_print_undef()
{ {
fprintf(stderr, " Undefined symbols:\n"); fprintf(stderr, " Undefined symbols:\n");
st_foreach(undef_tbl, underb_f_print, NULL); st_foreach(undef_tbl, undef_print, NULL);
} }
static void static void
@ -462,7 +465,7 @@ struct undef {
static st_table *reloc_tbl = NULL; static st_table *reloc_tbl = NULL;
static void static void
link_undef(name, base, reloc) link_undef(name, base, reloc)
char *name; const char *name;
long base; long base;
struct relocation_info *reloc; struct relocation_info *reloc;
{ {
@ -492,7 +495,7 @@ link_undef(name, base, reloc)
} }
struct reloc_arg { struct reloc_arg {
char *name; const char *name;
long value; long value;
}; };
@ -562,7 +565,7 @@ reloc_undef(no, undef, arg)
static void static void
unlink_undef(name, value) unlink_undef(name, value)
char *name; const char *name;
long value; long value;
{ {
struct reloc_arg arg; struct reloc_arg arg;
@ -595,7 +598,7 @@ static int
load_1(fd, disp, need_init) load_1(fd, disp, need_init)
int fd; int fd;
long disp; long disp;
char *need_init; const char *need_init;
{ {
static char *libc = LIBC_NAME; static char *libc = LIBC_NAME;
struct exec hdr; struct exec hdr;
@ -873,7 +876,7 @@ load_1(fd, disp, need_init)
static int target_offset; static int target_offset;
static int static int
search_undef(key, value, lib_tbl) search_undef(key, value, lib_tbl)
char *key; const char *key;
int value; int value;
st_table *lib_tbl; st_table *lib_tbl;
{ {
@ -893,7 +896,7 @@ char *dln_librrb_ary_path = DLN_DEFAULT_LIB_PATH;
static int static int
load_lib(lib) load_lib(lib)
char *lib; const char *lib;
{ {
char *path, *file; char *path, *file;
char armagic[SARMAG]; char armagic[SARMAG];
@ -1030,7 +1033,7 @@ load_lib(lib)
static int static int
load(file) load(file)
char *file; const char *file;
{ {
int fd; int fd;
int result; int result;
@ -1056,7 +1059,7 @@ load(file)
void* void*
dln_sym(name) dln_sym(name)
char *name; const char *name;
{ {
struct nlist *sym; struct nlist *sym;
@ -1076,7 +1079,7 @@ dln_sym(name)
# endif # endif
#endif #endif
#ifdef hpux #ifdef __hpux
#include <errno.h> #include <errno.h>
#include "dl.h" #include "dl.h"
#endif #endif
@ -1094,12 +1097,16 @@ dln_sym(name)
#include <mach-o/dyld.h> #include <mach-o/dyld.h>
#endif #endif
#endif #endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
#endif #endif
static char * static const char *
dln_strerror() dln_strerror()
{ {
#ifdef USE_DLN_A_OUT #ifdef USE_DLN_A_OUT
@ -1152,7 +1159,7 @@ dln_strerror()
#if defined(_AIX) #if defined(_AIX)
static void static void
aix_loaderror(char *pathname) aix_loaderror(const char *pathname)
{ {
char *message[8], errbuf[1024]; char *message[8], errbuf[1024];
int i,j; int i,j;
@ -1184,11 +1191,11 @@ aix_loaderror(char *pathname)
ERRBUF_APPEND(strerror(errno)); ERRBUF_APPEND(strerror(errno));
for(i = 0; message[i] && *message[i]; i++) { for(i = 0; message[i] && *message[i]; i++) {
int nerr = atoi(message[i]); int nerr = atoi(message[i]);
for (j=0; j<LOAD_ERRTAB_LEN ; j++) { for (j=0; j<LOAD_ERRTAB_LEN; j++) {
if (nerr == load_errtab[i].errno && load_errtab[i].errstr) if (nerr == load_errtab[i].errno && load_errtab[i].errstr)
ERRBUF_APPEND(load_errtab[i].errstr); ERRBUF_APPEND(load_errtab[i].errstr);
} }
while (isdigit(*message[i])) message[i]++ ; while (isdigit(*message[i])) message[i]++;
ERRBUF_APPEND(message[i]); ERRBUF_APPEND(message[i]);
ERRBUF_APPEND("\n"); ERRBUF_APPEND("\n");
} }
@ -1200,7 +1207,7 @@ aix_loaderror(char *pathname)
void void
dln_load(file) dln_load(file)
char *file; const char *file;
{ {
#ifdef _WIN32 #ifdef _WIN32
HINSTANCE handle; HINSTANCE handle;
@ -1277,7 +1284,7 @@ dln_load(file)
} }
#endif /* USE_DLN_DLOPEN */ #endif /* USE_DLN_DLOPEN */
#ifdef hpux #ifdef __hpux
#define DLN_DEFINED #define DLN_DEFINED
{ {
shl_t lib = NULL; shl_t lib = NULL;
@ -1308,16 +1315,19 @@ dln_load(file)
{ {
void (*init_fct)(); void (*init_fct)();
init_fct = (void(*)())load(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, (void*)dln_load, (void*)init_fct) == -1) {
aix_loaderror(file);
}
(*init_fct)(); (*init_fct)();
return; return;
} }
#endif /* _AIX */ #endif /* _AIX */
#ifdef NeXT #if defined(NeXT) || defined(__APPLE__)
#define DLN_DEFINED #define DLN_DEFINED
/*---------------------------------------------------- /*----------------------------------------------------
By SHIROYAMA Takayuki Psi@fortune.nest.or.jp By SHIROYAMA Takayuki Psi@fortune.nest.or.jp
@ -1327,7 +1337,8 @@ dln_load(file)
Mi hisho@tasihara.nest.or.jp, Mi hisho@tasihara.nest.or.jp,
and... Miss ARAI Akino(^^;) and... Miss ARAI Akino(^^;)
----------------------------------------------------*/ ----------------------------------------------------*/
#if 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;
char *object_files[2] = {NULL, NULL}; char *object_files[2] = {NULL, NULL};
@ -1351,19 +1362,19 @@ dln_load(file)
init_fct = (void(*)())init_address; init_fct = (void(*)())init_address;
(*init_fct)(); (*init_fct)();
return ; return;
} }
#else/* OPENSTEP dyld functions */ #else/* OPENSTEP dyld functions */
{ {
int dyld_result ; int dyld_result;
NSObjectFileImage obj_file ; /* handle, but not use it */ NSObjectFileImage obj_file; /* handle, but not use it */
/* "file" is module file name . /* "file" is module file name .
"buf" is initial function name with "_" . */ "buf" is initial function name with "_" . */
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);
@ -1373,15 +1384,15 @@ 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;
} }
#endif /* rld or dyld */ #endif /* rld or dyld */
#endif #endif
@ -1406,14 +1417,14 @@ dln_load(file)
/* strcat(init_fct_symname, "__Fv"); */ /* parameter nothing. */ /* strcat(init_fct_symname, "__Fv"); */ /* parameter nothing. */
/* "__Fv" dont need! The Be Book Bug ? */ /* "__Fv" dont need! The Be Book Bug ? */
err_stat = get_image_symbol(img_id, buf, err_stat = get_image_symbol(img_id, buf,
B_SYMBOL_TYPE_TEXT, &init_fct); B_SYMBOL_TYPE_TEXT, (void **)&init_fct);
if (err_stat != B_NO_ERROR) { if (err_stat != B_NO_ERROR) {
char real_name[1024]; char real_name[1024];
strcpy(real_name, buf); strcpy(real_name, buf);
strcat(real_name, "__Fv"); strcat(real_name, "__Fv");
err_stat = get_image_symbol(img_id, real_name, err_stat = get_image_symbol(img_id, real_name,
B_SYMBOL_TYPE_TEXT, &init_fct); B_SYMBOL_TYPE_TEXT, (void **)&init_fct);
} }
if ((B_BAD_IMAGE_ID == err_stat) || (B_BAD_INDEX == err_stat)) { if ((B_BAD_IMAGE_ID == err_stat) || (B_BAD_INDEX == err_stat)) {
@ -1453,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 */
@ -1462,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;
@ -1496,8 +1507,8 @@ static char *dln_find_1();
char * char *
dln_find_exe(fname, path) dln_find_exe(fname, path)
char *fname; const char *fname;
char *path; const char *path;
{ {
if (!path) { if (!path) {
#if defined(__human68k__) #if defined(__human68k__)
@ -1519,18 +1530,24 @@ dln_find_exe(fname, path)
char * char *
dln_find_file(fname, path) dln_find_file(fname, path)
char *fname; const char *fname;
char *path; const char *path;
{ {
#ifndef __MACOS__
if (!path) path = "."; if (!path) path = ".";
return dln_find_1(fname, path, 0); return dln_find_1(fname, path, 0);
#else
if (!path) path = ".";
return _macruby_path_conv_posix_to_macos(dln_find_1(fname, path, 0));
#endif
} }
#if defined(__CYGWIN32__) #if defined(__CYGWIN32__)
char * const char *
conv_to_posix_path(win32, posix) conv_to_posix_path(win32, posix, len)
char *win32; char *win32;
char *posix; char *posix;
int len;
{ {
char *first = win32; char *first = win32;
char *p = win32; char *p = win32;
@ -1545,7 +1562,10 @@ conv_to_posix_path(win32, posix)
first = p + 1; first = p + 1;
*p = ';'; *p = ';';
} }
cygwin32_conv_to_posix_path(first, posix); if (len < strlen(first))
fprintf(stderr, "PATH length too long: %s\n", first);
else
cygwin32_conv_to_posix_path(first, posix);
return dst; return dst;
} }
#endif #endif
@ -1561,26 +1581,23 @@ dln_find_1(fname, path, exe_flag)
register char *dp; register char *dp;
register char *ep; register char *ep;
register char *bp; register char *bp;
struct stat st;
#if defined(__CYGWIN32__)
char rubypath[MAXPATHLEN];
conv_to_posix_path(path, rubypath);
path = rubypath;
#endif
#ifndef __MACOS__ #ifndef __MACOS__
struct stat st;
#else
const char* mac_fullpath;
#endif
if (fname[0] == '/') return fname; if (fname[0] == '/') return fname;
if (strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0) if (strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0)
return fname; return fname;
if (exe_flag && strchr(fname, '/')) return fname; if (exe_flag && strchr(fname, '/')) return fname;
#if defined(MSDOS) || defined(NT) || defined(__human68k__) #if defined(MSDOS) || defined(NT) || defined(__human68k__) || defined(__EMX__)
if (fname[0] == '\\') return fname; if (fname[0] == '\\') return fname;
if (strlen(fname) > 2 && fname[1] == ':') return fname; if (strlen(fname) > 2 && fname[1] == ':') return fname;
if (strncmp(".\\", fname, 2) == 0 || strncmp("..\\", fname, 3) == 0) if (strncmp(".\\", fname, 2) == 0 || strncmp("..\\", fname, 3) == 0)
return fname; return fname;
if (exe_flag && strchr(fname, '\\')) return fname; if (exe_flag && strchr(fname, '\\')) return fname;
#endif #endif
#endif /* __MACOS__ */
for (dp = path;; dp = ++ep) { for (dp = path;; dp = ++ep) {
register int l; register int l;
@ -1588,7 +1605,7 @@ dln_find_1(fname, path, exe_flag)
int fspace; int fspace;
/* extract a component */ /* extract a component */
ep = strchr(dp, RUBY_PATH_SEP[0]); ep = strchr(dp, PATH_SEP[0]);
if (ep == NULL) if (ep == NULL)
ep = dp+strlen(dp); ep = dp+strlen(dp);
@ -1606,7 +1623,7 @@ dln_find_1(fname, path, exe_flag)
*/ */
if (*dp == '~' && (l == 1 || if (*dp == '~' && (l == 1 ||
#if defined(MSDOS) || defined(NT) || defined(__human68k__) #if defined(MSDOS) || defined(NT) || defined(__human68k__) || defined(__EMX__)
dp[1] == '\\' || dp[1] == '\\' ||
#endif #endif
dp[1] == '/')) { dp[1] == '/')) {
@ -1632,11 +1649,7 @@ dln_find_1(fname, path, exe_flag)
/* add a "/" between directory and filename */ /* add a "/" between directory and filename */
if (ep[-1] != '/') if (ep[-1] != '/')
#ifdef __MACOS__
*bp++ = ':';
#else
*bp++ = '/'; *bp++ = '/';
#endif
} }
/* now append the file name */ /* now append the file name */
@ -1651,12 +1664,20 @@ dln_find_1(fname, path, exe_flag)
} }
memcpy(bp, fname, i + 1); memcpy(bp, fname, i + 1);
#ifndef __MACOS__
if (stat(fbuf, &st) == 0) { if (stat(fbuf, &st) == 0) {
if (exe_flag == 0) return fbuf; if (exe_flag == 0) return fbuf;
/* looking for executable */ /* looking for executable */
if (eaccess(fbuf, X_OK) == 0) return fbuf; if (eaccess(fbuf, X_OK) == 0) return fbuf;
} }
#if defined(MSDOS) || defined(NT) || defined(__human68k__) #else
if (mac_fullpath = _macruby_exist_file_in_libdir_as_posix_name(fbuf)) {
if (exe_flag == 0) return mac_fullpath;
/* looking for executable */
if (eaccess(mac_fullpath, X_OK) == 0) return mac_fullpath;
}
#endif
#if defined(MSDOS) || defined(NT) || defined(__human68k__) || defined(__EMX__)
if (exe_flag) { if (exe_flag) {
static const char *extension[] = { static const char *extension[] = {
#if defined(MSDOS) #if defined(MSDOS)
@ -1664,8 +1685,12 @@ dln_find_1(fname, path, exe_flag)
#if defined(DJGPP) #if defined(DJGPP)
".btm", ".sh", ".ksh", ".pl", ".sed", ".btm", ".sh", ".ksh", ".pl", ".sed",
#endif #endif
#elif defined(__EMX__) || defined(NT)
".exe", ".com", ".cmd", ".bat",
/* end of __EMX__ or NT*/
#else #else
".r", ".R", ".x", ".X", ".bat", ".BAT", ".r", ".R", ".x", ".X", ".bat", ".BAT",
/* __human68k__ */
#endif #endif
(char *) NULL (char *) NULL
}; };
@ -1679,11 +1704,16 @@ dln_find_1(fname, path, exe_flag)
continue; continue;
} }
strcpy(bp + i, extension[j]); strcpy(bp + i, extension[j]);
#ifndef __MACOS__
if (stat(fbuf, &st) == 0) if (stat(fbuf, &st) == 0)
return fbuf; return fbuf;
#else
if (mac_fullpath = _macruby_exist_file_in_libdir_as_posix_name(fbuf))
return mac_fullpath;
#endif
} }
} }
#endif /* MSDOS or NT or __human68k__ */ #endif /* MSDOS or NT or __human68k__ or __EMX__ */
/* if not, and no other alternatives, life is bleak */ /* if not, and no other alternatives, life is bleak */
if (*ep == '\0') { if (*ep == '\0') {
return NULL; return NULL;

8
dln.h
View file

@ -3,7 +3,6 @@
dln.h - dln.h -
$Author$ $Author$
$Revision$
$Date$ $Date$
created at: Wed Jan 19 16:53:09 JST 1994 created at: Wed Jan 19 16:53:09 JST 1994
@ -14,17 +13,18 @@
#ifndef _ #ifndef _
#ifndef __STDC__ #ifndef __STDC__
# define _(args) () # define _(args) ()
# define const
#else #else
# define _(args) args # define _(args) args
#endif #endif
#endif #endif
char *dln_find_exe _((char*,char*)); char *dln_find_exe _((const char*,const char*));
char *dln_find_file _((char*,char*)); char *dln_find_file _((const char*,const char*));
#ifdef USE_DLN_A_OUT #ifdef USE_DLN_A_OUT
extern char *dln_argv0; extern char *dln_argv0;
#endif #endif
void dln_load _((char*)); void dln_load _((const char*));
#endif #endif

28
enum.c
View file

@ -6,7 +6,7 @@
$Date$ $Date$
created at: Fri Oct 1 15:15:19 JST 1993 created at: Fri Oct 1 15:15:19 JST 1993
Copyright (C) 1993-1998 Yukihiro Matsumoto Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/ ************************************************/
@ -56,6 +56,7 @@ enum_grep(obj, pat)
arg[0] = pat; arg[1] = tmp = rb_ary_new(); arg[0] = pat; arg[1] = tmp = rb_ary_new();
rb_iterate(rb_each, obj, grep_i, (VALUE)arg); rb_iterate(rb_each, obj, grep_i, (VALUE)arg);
if (RARRAY(tmp)->len == 0) return Qnil;
return tmp; return tmp;
} }
} }
@ -121,6 +122,28 @@ enum_find_all(obj)
return tmp; return tmp;
} }
static VALUE
reject_i(i, tmp)
VALUE i, tmp;
{
if (!RTEST(rb_yield(i))) {
rb_ary_push(tmp, i);
}
return Qnil;
}
static VALUE
enum_reject(obj)
VALUE obj;
{
VALUE tmp;
tmp = rb_ary_new();
rb_iterate(rb_each, obj, reject_i, tmp);
return tmp;
}
static VALUE static VALUE
collect_i(i, tmp) collect_i(i, tmp)
VALUE i, tmp; VALUE i, tmp;
@ -373,7 +396,10 @@ Init_Enumerable()
rb_define_method(rb_mEnumerable,"sort", enum_sort, 0); rb_define_method(rb_mEnumerable,"sort", enum_sort, 0);
rb_define_method(rb_mEnumerable,"grep", enum_grep, 1); rb_define_method(rb_mEnumerable,"grep", enum_grep, 1);
rb_define_method(rb_mEnumerable,"find", enum_find, -1); rb_define_method(rb_mEnumerable,"find", enum_find, -1);
rb_define_method(rb_mEnumerable,"detect", enum_find, -1);
rb_define_method(rb_mEnumerable,"find_all", enum_find_all, 0); rb_define_method(rb_mEnumerable,"find_all", enum_find_all, 0);
rb_define_method(rb_mEnumerable,"select", enum_find_all, 0);
rb_define_method(rb_mEnumerable,"reject", enum_reject, 0);
rb_define_method(rb_mEnumerable,"collect", enum_collect, 0); rb_define_method(rb_mEnumerable,"collect", enum_collect, 0);
rb_define_method(rb_mEnumerable,"min", enum_min, 0); rb_define_method(rb_mEnumerable,"min", enum_min, 0);
rb_define_method(rb_mEnumerable,"max", enum_max, 0); rb_define_method(rb_mEnumerable,"max", enum_max, 0);

4
env.h
View file

@ -3,7 +3,6 @@
env.h - env.h -
$Author$ $Author$
$Revision$
$Date$ $Date$
created at: Mon Jul 11 11:53:03 JST 1994 created at: Mon Jul 11 11:53:03 JST 1994
@ -19,6 +18,7 @@ extern struct FRAME {
VALUE last_class; VALUE last_class;
VALUE cbase; VALUE cbase;
struct FRAME *prev; struct FRAME *prev;
struct FRAME *tmp;
char *file; char *file;
int line; int line;
int iter; int iter;
@ -37,7 +37,7 @@ extern struct SCOPE {
#define SCOPE_MALLOC 1 #define SCOPE_MALLOC 1
#define SCOPE_NOSTACK 2 #define SCOPE_NOSTACK 2
extern int rb_in_eval; extern int ruby_in_eval;
extern VALUE ruby_class; extern VALUE ruby_class;

136
error.c
View file

@ -6,7 +6,7 @@
$Date$ $Date$
created at: Mon Aug 9 16:11:34 JST 1993 created at: Mon Aug 9 16:11:34 JST 1993
Copyright (C) 1993-1998 Yukihiro Matsumoto Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/ ************************************************/
@ -45,10 +45,10 @@ err_snprintf(buf, len, fmt, args)
} }
} }
static void err_append _((char*)); static void err_append _((const char*));
static void static void
err_print(fmt, args) err_print(fmt, args)
char *fmt; const char *fmt;
va_list args; va_list args;
{ {
char buf[BUFSIZ]; char buf[BUFSIZ];
@ -59,10 +59,10 @@ err_print(fmt, args)
void void
#ifdef HAVE_STDARG_PROTOTYPES #ifdef HAVE_STDARG_PROTOTYPES
rb_compile_error(char *fmt, ...) rb_compile_error(const char *fmt, ...)
#else #else
rb_compile_error(fmt, va_alist) rb_compile_error(fmt, va_alist)
char *fmt; const char *fmt;
va_dcl va_dcl
#endif #endif
{ {
@ -76,10 +76,10 @@ rb_compile_error(fmt, va_alist)
void void
#ifdef HAVE_STDARG_PROTOTYPES #ifdef HAVE_STDARG_PROTOTYPES
rb_compile_error_append(char *fmt, ...) rb_compile_error_append(const char *fmt, ...)
#else #else
rb_compile_error_append(fmt, va_alist) rb_compile_error_append(fmt, va_alist)
char *fmt; const char *fmt;
va_dcl va_dcl
#endif #endif
{ {
@ -94,10 +94,10 @@ rb_compile_error_append(fmt, va_alist)
void void
#ifdef HAVE_STDARG_PROTOTYPES #ifdef HAVE_STDARG_PROTOTYPES
rb_warn(char *fmt, ...) rb_warn(const char *fmt, ...)
#else #else
rb_warn(fmt, va_alist) rb_warn(fmt, va_alist)
char *fmt; const char *fmt;
va_dcl va_dcl
#endif #endif
{ {
@ -114,17 +114,17 @@ rb_warn(fmt, va_alist)
/* rb_warning() reports only in verbose mode */ /* rb_warning() reports only in verbose mode */
void void
#ifdef HAVE_STDARG_PROTOTYPES #ifdef HAVE_STDARG_PROTOTYPES
rb_warning(char *fmt, ...) rb_warning(const char *fmt, ...)
#else #else
rb_warning(fmt, va_alist) rb_warning(fmt, va_alist)
char *fmt; const char *fmt;
va_dcl va_dcl
#endif #endif
{ {
char buf[BUFSIZ]; char buf[BUFSIZ];
va_list args; va_list args;
if (!RTEST(rb_verbose)) return; if (!RTEST(ruby_verbose)) return;
snprintf(buf, BUFSIZ, "warning: %s", fmt); snprintf(buf, BUFSIZ, "warning: %s", fmt);
@ -135,10 +135,10 @@ rb_warning(fmt, va_alist)
void void
#ifdef HAVE_STDARG_PROTOTYPES #ifdef HAVE_STDARG_PROTOTYPES
rb_bug(char *fmt, ...) rb_bug(const char *fmt, ...)
#else #else
rb_bug(fmt, va_alist) rb_bug(fmt, va_alist)
char *fmt; const char *fmt;
va_dcl va_dcl
#endif #endif
{ {
@ -146,7 +146,7 @@ rb_bug(fmt, va_alist)
va_list args; va_list args;
snprintf(buf, BUFSIZ, "[BUG] %s", fmt); snprintf(buf, BUFSIZ, "[BUG] %s", fmt);
rb_in_eval = 0; ruby_in_eval = 0;
va_init_list(args, fmt); va_init_list(args, fmt);
err_print(buf, args); err_print(buf, args);
@ -156,7 +156,7 @@ rb_bug(fmt, va_alist)
static struct types { static struct types {
int type; int type;
char *name; const char *name;
} builtin_types[] = { } builtin_types[] = {
T_NIL, "nil", T_NIL, "nil",
T_OBJECT, "Object", T_OBJECT, "Object",
@ -220,7 +220,10 @@ rb_check_type(x, t)
#include <errno.h> #include <errno.h>
VALUE rb_eException; VALUE rb_eException;
VALUE rb_eSystemExit, rb_eInterrupt, rb_eFatal; VALUE rb_eSystemExit;
VALUE rb_eInterrupt;
VALUE rb_eSignal;
VALUE rb_eFatal;
VALUE rb_eStandardError; VALUE rb_eStandardError;
VALUE rb_eRuntimeError; VALUE rb_eRuntimeError;
VALUE rb_eSyntaxError; VALUE rb_eSyntaxError;
@ -238,8 +241,8 @@ VALUE rb_mErrno;
VALUE VALUE
rb_exc_new(etype, ptr, len) rb_exc_new(etype, ptr, len)
VALUE etype; VALUE etype;
char *ptr; const char *ptr;
int len; long len;
{ {
VALUE exc = rb_obj_alloc(etype); VALUE exc = rb_obj_alloc(etype);
@ -250,7 +253,7 @@ rb_exc_new(etype, ptr, len)
VALUE VALUE
rb_exc_new2(etype, s) rb_exc_new2(etype, s)
VALUE etype; VALUE etype;
char *s; const char *s;
{ {
return rb_exc_new(etype, s, strlen(s)); return rb_exc_new(etype, s, strlen(s));
} }
@ -283,20 +286,21 @@ exc_initialize(argc, argv, exc)
} }
static VALUE static VALUE
exc_new(argc, argv, self) exc_exception(argc, argv, self)
int argc; int argc;
VALUE *argv; VALUE *argv;
VALUE self; VALUE self;
{ {
VALUE etype, exc; VALUE etype, exc;
if (argc == 0) return self;
if (argc == 1 && self == argv[0]) return self; if (argc == 1 && self == argv[0]) return self;
etype = CLASS_OF(self); etype = CLASS_OF(self);
while (FL_TEST(etype, FL_SINGLETON)) { while (FL_TEST(etype, FL_SINGLETON)) {
etype = RCLASS(etype)->super; etype = RCLASS(etype)->super;
} }
exc = rb_obj_alloc(etype); exc = rb_obj_alloc(etype);
rb_obj_call_init(exc); rb_obj_call_init(exc, argc, argv);
return exc; return exc;
} }
@ -337,7 +341,10 @@ static VALUE
exc_backtrace(exc) exc_backtrace(exc)
VALUE exc; VALUE exc;
{ {
return rb_iv_get(exc, "bt"); ID bt = rb_intern("bt");
if (!rb_ivar_defined(exc, bt)) return Qnil;
return rb_ivar_get(exc, bt);
} }
static VALUE static VALUE
@ -370,54 +377,15 @@ exc_set_backtrace(exc, bt)
return rb_iv_set(exc, "bt", check_backtrace(bt)); return rb_iv_set(exc, "bt", check_backtrace(bt));
} }
static VALUE
exception(argc, argv)
int argc;
VALUE *argv;
{
VALUE v = Qnil;
VALUE etype = rb_eStandardError;
int i;
ID id;
if (argc == 0) {
rb_raise(rb_eArgError, "wrong # of arguments");
}
rb_warn("Exception() is now obsolete");
if (TYPE(argv[argc-1]) == T_CLASS) {
etype = argv[argc-1];
argc--;
if (!rb_funcall(etype, '<', 1, rb_eException)) {
rb_raise(rb_eTypeError, "exception should be subclass of Exception");
}
}
for (i=0; i<argc; i++) { /* argument check */
id = rb_to_id(argv[i]);
if (!rb_id2name(id)) {
rb_raise(rb_eArgError, "argument needs to be symbol or string");
}
if (!rb_is_const_id(id)) {
rb_raise(rb_eArgError, "identifier `%s' needs to be constant",
rb_id2name(id));
}
}
for (i=0; i<argc; i++) {
v = rb_define_class_under(ruby_class,
rb_id2name(rb_to_id(argv[i])),
rb_eStandardError);
}
return v;
}
#ifdef __BEOS__ #ifdef __BEOS__
typedef struct { typedef struct {
VALUE *list; VALUE *list;
size_t n; int n;
} syserr_list_entry; } syserr_list_entry;
typedef struct { typedef struct {
int ix; int ix;
size_t n; int n;
} syserr_index_entry; } syserr_index_entry;
static VALUE syserr_list_b_general[16+1]; static VALUE syserr_list_b_general[16+1];
@ -471,7 +439,7 @@ extern int sys_nerr;
static VALUE static VALUE
set_syserr(i, name) set_syserr(i, name)
int i; int i;
char *name; const char *name;
{ {
#ifdef __BEOS__ #ifdef __BEOS__
VALUE *list; VALUE *list;
@ -533,7 +501,8 @@ void
Init_Exception() Init_Exception()
{ {
rb_eException = rb_define_class("Exception", rb_cObject); rb_eException = rb_define_class("Exception", rb_cObject);
rb_define_method(rb_eException, "new", exc_new, -1); rb_define_singleton_method(rb_eException, "exception", rb_class_new_instance, -1);
rb_define_method(rb_eException, "exception", exc_exception, -1);
rb_define_method(rb_eException, "initialize", exc_initialize, -1); rb_define_method(rb_eException, "initialize", exc_initialize, -1);
rb_define_method(rb_eException, "to_s", exc_to_s, 0); rb_define_method(rb_eException, "to_s", exc_to_s, 0);
rb_define_method(rb_eException, "to_str", exc_to_s, 0); rb_define_method(rb_eException, "to_str", exc_to_s, 0);
@ -543,8 +512,9 @@ Init_Exception()
rb_define_method(rb_eException, "set_backtrace", exc_set_backtrace, 1); rb_define_method(rb_eException, "set_backtrace", exc_set_backtrace, 1);
rb_eSystemExit = rb_define_class("SystemExit", rb_eException); rb_eSystemExit = rb_define_class("SystemExit", rb_eException);
rb_eFatal = rb_define_class("fatal", rb_eException); rb_eFatal = rb_define_class("fatal", rb_eException);
rb_eInterrupt = rb_define_class("Interrupt", rb_eException); rb_eInterrupt = rb_define_class("Interrupt", rb_eException);
rb_eSignal = rb_define_class("SignalException", rb_eException);
rb_eStandardError = rb_define_class("StandardError", rb_eException); rb_eStandardError = rb_define_class("StandardError", rb_eException);
rb_eSyntaxError = rb_define_class("SyntaxError", rb_eStandardError); rb_eSyntaxError = rb_define_class("SyntaxError", rb_eStandardError);
@ -559,17 +529,15 @@ Init_Exception()
rb_eNotImpError = rb_define_class("NotImplementError", rb_eException); rb_eNotImpError = rb_define_class("NotImplementError", rb_eException);
init_syserr(); init_syserr();
rb_define_global_function("Exception", exception, -1);
} }
void void
#ifdef HAVE_STDARG_PROTOTYPES #ifdef HAVE_STDARG_PROTOTYPES
rb_raise(VALUE exc, char *fmt, ...) rb_raise(VALUE exc, const char *fmt, ...)
#else #else
rb_raise(exc, fmt, va_alist) rb_raise(exc, fmt, va_alist)
VALUE exc; VALUE exc;
char *fmt; const char *fmt;
va_dcl va_dcl
#endif #endif
{ {
@ -584,10 +552,10 @@ rb_raise(exc, fmt, va_alist)
void void
#ifdef HAVE_STDARG_PROTOTYPES #ifdef HAVE_STDARG_PROTOTYPES
rb_loaderror(char *fmt, ...) rb_loaderror(const char *fmt, ...)
#else #else
rb_loaderror(fmt, va_alist) rb_loaderror(fmt, va_alist)
char *fmt; const char *fmt;
va_dcl va_dcl
#endif #endif
{ {
@ -610,10 +578,10 @@ rb_notimplement()
void void
#ifdef HAVE_STDARG_PROTOTYPES #ifdef HAVE_STDARG_PROTOTYPES
rb_fatal(char *fmt, ...) rb_fatal(const char *fmt, ...)
#else #else
rb_fatal(fmt, va_alist) rb_fatal(fmt, va_alist)
char *fmt; const char *fmt;
va_dcl va_dcl
#endif #endif
{ {
@ -624,13 +592,13 @@ rb_fatal(fmt, va_alist)
vsnprintf(buf, BUFSIZ, fmt, args); vsnprintf(buf, BUFSIZ, fmt, args);
va_end(args); va_end(args);
rb_in_eval = 0; ruby_in_eval = 0;
rb_exc_fatal(rb_exc_new2(rb_eFatal, buf)); rb_exc_fatal(rb_exc_new2(rb_eFatal, buf));
} }
void void
rb_sys_fail(mesg) rb_sys_fail(mesg)
char *mesg; const char *mesg;
{ {
#ifndef NT #ifndef NT
char *strerror(); char *strerror();
@ -1079,20 +1047,20 @@ init_syserr()
static void static void
err_append(s) err_append(s)
char *s; const char *s;
{ {
extern VALUE rb_errinfo; extern VALUE ruby_errinfo;
if (rb_in_eval) { if (ruby_in_eval) {
if (NIL_P(rb_errinfo)) { if (NIL_P(ruby_errinfo)) {
rb_errinfo = rb_exc_new2(rb_eSyntaxError, s); ruby_errinfo = rb_exc_new2(rb_eSyntaxError, s);
} }
else { else {
VALUE str = rb_str_to_str(rb_errinfo); VALUE str = rb_str_to_str(ruby_errinfo);
rb_str_cat(str, "\n", 1); rb_str_cat(str, "\n", 1);
rb_str_cat(str, s, strlen(s)); rb_str_cat(str, s, strlen(s));
rb_errinfo = rb_exc_new3(rb_eSyntaxError, str); ruby_errinfo = rb_exc_new3(rb_eSyntaxError, str);
} }
} }
else { else {

1599
eval.c

File diff suppressed because it is too large Load diff

233
file.c
View file

@ -6,7 +6,7 @@
$Date$ $Date$
created at: Mon Nov 15 12:24:34 JST 1993 created at: Mon Nov 15 12:24:34 JST 1993
Copyright (C) 1993-1998 Yukihiro Matsumoto Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/ ************************************************/
@ -28,6 +28,7 @@
# define MAXPATHLEN 1024 # define MAXPATHLEN 1024
#endif #endif
#include <time.h>
#ifdef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIME_H
# include <sys/time.h> # include <sys/time.h>
#else #else
@ -39,6 +40,8 @@ struct timeval {
#endif /* NT */ #endif /* NT */
#endif #endif
VALUE rb_time_new _((time_t, time_t));
#ifdef HAVE_UTIME_H #ifdef HAVE_UTIME_H
#include <utime.h> #include <utime.h>
#endif #endif
@ -48,7 +51,7 @@ struct timeval {
#endif #endif
#ifndef HAVE_STRING_H #ifndef HAVE_STRING_H
char *strrchr _((char*,char)); char *strrchr _((const char*,const char));
#endif #endif
#include <sys/types.h> #include <sys/types.h>
@ -58,107 +61,17 @@ char *strrchr _((char*,char));
#include "macruby_missing.h" #include "macruby_missing.h"
extern int fileno(FILE *stream); extern int fileno(FILE *stream);
extern int utimes(); extern int utimes();
char* strdup(char*);
#endif #endif
#ifdef __EMX__
#define lstat stat
#endif
VALUE rb_cFile; VALUE rb_cFile;
VALUE rb_mFileTest; VALUE rb_mFileTest;
static VALUE sStat; static VALUE sStat;
VALUE
rb_file_open(fname, mode)
char *fname, *mode;
{
OpenFile *fptr;
NEWOBJ(port, struct RFile);
OBJSETUP(port, rb_cFile, T_FILE);
MakeOpenFile(port, fptr);
fptr->mode = rb_io_mode_flags(mode);
fptr->f = rb_fopen(fname, mode);
fptr->path = strdup(fname);
rb_obj_call_init((VALUE)port);
return (VALUE)port;
}
static VALUE
rb_file_s_open(argc, argv, klass)
int argc;
VALUE *argv;
VALUE klass;
{
VALUE fname, vmode, file;
char *mode;
rb_scan_args(argc, argv, "11", &fname, &vmode);
Check_SafeStr(fname);
if (!NIL_P(vmode)) {
mode = STR2CSTR(vmode);
}
else {
mode = "r";
}
file = rb_file_open(RSTRING(fname)->ptr, mode);
RBASIC(file)->klass = klass;
rb_obj_call_init(file);
if (rb_iterator_p()) {
return rb_ensure(rb_yield, file, rb_io_close, file);
}
return file;
}
static VALUE
rb_file_reopen(argc, argv, file)
int argc;
VALUE *argv;
VALUE file;
{
VALUE fname, nmode;
char *mode;
OpenFile *fptr;
rb_secure(4);
if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 1) {
if (TYPE(fname) == T_FILE) { /* fname must be IO */
return rb_io_reopen(file, fname);
}
}
Check_SafeStr(fname);
if (!NIL_P(nmode)) {
mode = STR2CSTR(nmode);
}
else {
mode = "r";
}
GetOpenFile(file, fptr);
if (fptr->path) free(fptr->path);
fptr->path = strdup(RSTRING(fname)->ptr);
fptr->mode = rb_io_mode_flags(mode);
if (!fptr->f) {
fptr->f = rb_fopen(RSTRING(fname)->ptr, mode);
if (fptr->f2) {
fclose(fptr->f2);
fptr->f2 = NULL;
}
return file;
}
if (freopen(RSTRING(fname)->ptr, mode, fptr->f) == NULL) {
rb_sys_fail(fptr->path);
}
if (fptr->f2) {
if (freopen(RSTRING(fname)->ptr, "w", fptr->f2) == NULL) {
rb_sys_fail(fptr->path);
}
}
return file;
}
static int static int
apply2files(func, vargs, arg) apply2files(func, vargs, arg)
int (*func)(); int (*func)();
@ -247,6 +160,9 @@ rb_stat(file, st)
return fstat(fileno(fptr->f), st); return fstat(fileno(fptr->f), st);
} }
Check_SafeStr(file); Check_SafeStr(file);
#if defined DJGPP
if (RSTRING(file)->len == 0) return -1;
#endif
return stat(RSTRING(file)->ptr, st); return stat(RSTRING(file)->ptr, st);
} }
@ -281,7 +197,7 @@ static VALUE
rb_file_s_lstat(obj, fname) rb_file_s_lstat(obj, fname)
VALUE obj, fname; VALUE obj, fname;
{ {
#if !defined(MSDOS) && !defined(NT) #if !defined(MSDOS) && !defined(NT) && !defined(__EMX__)
struct stat st; struct stat st;
Check_SafeStr(fname); Check_SafeStr(fname);
@ -299,7 +215,7 @@ static VALUE
rb_file_lstat(obj) rb_file_lstat(obj)
VALUE obj; VALUE obj;
{ {
#if !defined(MSDOS) && !defined(NT) #if !defined(MSDOS) && !defined(NT)
OpenFile *fptr; OpenFile *fptr;
struct stat st; struct stat st;
@ -347,7 +263,7 @@ group_member(gid)
int int
eaccess(path, mode) eaccess(path, mode)
char *path; const char *path;
int mode; int mode;
{ {
#ifndef NT #ifndef NT
@ -608,8 +524,8 @@ test_s(obj, fname)
{ {
struct stat st; struct stat st;
if (rb_stat(fname, &st) < 0) return Qfalse; if (rb_stat(fname, &st) < 0) return Qnil;
if (st.st_size == 0) return Qfalse; if (st.st_size == 0) return Qnil;
return rb_int2inum(st.st_size); return rb_int2inum(st.st_size);
} }
@ -651,7 +567,7 @@ test_grpowned(obj, fname)
#if defined(S_ISUID) || defined(S_ISGID) || defined(S_ISVTX) #if defined(S_ISUID) || defined(S_ISGID) || defined(S_ISVTX)
static VALUE static VALUE
check3rdbyte(file, mode) check3rdbyte(file, mode)
char *file; const char *file;
int mode; int mode;
{ {
struct stat st; struct stat st;
@ -693,7 +609,7 @@ test_sticky(obj, fname)
#ifdef S_ISVTX #ifdef S_ISVTX
return check3rdbyte(STR2CSTR(fname), S_ISVTX); return check3rdbyte(STR2CSTR(fname), S_ISVTX);
#else #else
return Qfalse; return Qnil;
#endif #endif
} }
@ -836,7 +752,7 @@ rb_file_ctime(obj)
static void static void
chmod_internal(path, mode) chmod_internal(path, mode)
char *path; const char *path;
int mode; int mode;
{ {
if (chmod(path, mode) == -1) if (chmod(path, mode) == -1)
@ -870,7 +786,7 @@ rb_file_chmod(obj, vmode)
mode = NUM2INT(vmode); mode = NUM2INT(vmode);
GetOpenFile(obj, fptr); GetOpenFile(obj, fptr);
#if defined(DJGPP) || defined(NT) || defined(USE_CWGUSI) || defined(__BEOS__) #if defined(DJGPP) || defined(NT) || defined(USE_CWGUSI) || defined(__BEOS__) || defined(__EMX__)
if (chmod(fptr->path, mode) == -1) if (chmod(fptr->path, mode) == -1)
rb_sys_fail(fptr->path); rb_sys_fail(fptr->path);
#else #else
@ -887,7 +803,7 @@ struct chown_args {
static void static void
chown_internal(path, args) chown_internal(path, args)
char *path; const char *path;
struct chown_args *args; struct chown_args *args;
{ {
if (chown(path, args->owner, args->group) < 0) if (chown(path, args->owner, args->group) < 0)
@ -929,7 +845,7 @@ rb_file_chown(obj, owner, group)
rb_secure(4); rb_secure(4);
GetOpenFile(obj, fptr); GetOpenFile(obj, fptr);
#if defined(DJGPP) || defined(__CYGWIN32__) || defined(NT) || defined(USE_CWGUSI) #if defined(DJGPP) || defined(__CYGWIN32__) || defined(NT) || defined(USE_CWGUSI) || defined(__EMX__)
if (chown(fptr->path, NUM2INT(owner), NUM2INT(group)) == -1) if (chown(fptr->path, NUM2INT(owner), NUM2INT(group)) == -1)
rb_sys_fail(fptr->path); rb_sys_fail(fptr->path);
#else #else
@ -993,7 +909,7 @@ struct utimbuf {
static void static void
utime_internal(path, utp) utime_internal(path, utp)
char *path; const char *path;
struct utimbuf *utp; struct utimbuf *utp;
{ {
if (utime(path, utp) < 0) if (utime(path, utp) < 0)
@ -1043,7 +959,7 @@ static VALUE
rb_file_s_symlink(obj, from, to) rb_file_s_symlink(obj, from, to)
VALUE obj, from, to; VALUE obj, from, to;
{ {
#if !defined(MSDOS) && !defined(NT) #if !defined(MSDOS) && !defined(NT) && !defined(__EMX__)
Check_SafeStr(from); Check_SafeStr(from);
Check_SafeStr(to); Check_SafeStr(to);
@ -1060,7 +976,7 @@ static VALUE
rb_file_s_readlink(obj, path) rb_file_s_readlink(obj, path)
VALUE obj, path; VALUE obj, path;
{ {
#if !defined(MSDOS) && !defined(NT) #if !defined(MSDOS) && !defined(NT) && !defined(__EMX__)
char buf[MAXPATHLEN]; char buf[MAXPATHLEN];
int cc; int cc;
@ -1078,7 +994,7 @@ rb_file_s_readlink(obj, path)
static void static void
unlink_internal(path) unlink_internal(path)
char *path; const char *path;
{ {
if (unlink(path) < 0) if (unlink(path) < 0)
rb_sys_fail(path); rb_sys_fail(path);
@ -1132,6 +1048,12 @@ rb_file_s_umask(argc, argv)
#endif /* USE_CWGUSI */ #endif /* USE_CWGUSI */
} }
#if defined DOSISH
#define isdirsep(x) ((x) == '/' || (x) == '\\')
#else
#define isdirsep(x) ((x) == '/')
#endif
VALUE VALUE
rb_file_s_expand_path(argc, argv) rb_file_s_expand_path(argc, argv)
int argc; int argc;
@ -1146,11 +1068,7 @@ rb_file_s_expand_path(argc, argv)
s = STR2CSTR(fname); s = STR2CSTR(fname);
p = buf; p = buf;
if (s[0] == '~') { if (s[0] == '~') {
if (s[1] == '/' || if (isdirsep(s[1]) || s[1] == '\0') {
#if defined(MSDOS) || defined(NT) || defined(__human68k__)
s[1] == '\\' ||
#endif
s[1] == '\0') {
char *dir = getenv("HOME"); char *dir = getenv("HOME");
if (!dir) { if (!dir) {
@ -1165,7 +1083,7 @@ rb_file_s_expand_path(argc, argv)
struct passwd *pwPtr; struct passwd *pwPtr;
s++; s++;
#endif #endif
while (*s && *s != '/') { while (*s && !isdirsep(*s)) {
*p++ = *s++; *p++ = *s++;
} }
*p = '\0'; *p = '\0';
@ -1181,6 +1099,14 @@ rb_file_s_expand_path(argc, argv)
#endif #endif
} }
} }
#if defined DOSISH
/* skip drive letter */
else if (isalpha(s[0]) && s[1] == ':' && isdirsep(s[2])) {
while (*s && !isdirsep(*s)) {
*p++ = *s++;
}
}
#endif
else if (s[0] != '/') { else if (s[0] != '/') {
if (argc == 2) { if (argc == 2) {
dname = rb_file_s_expand_path(1, &dname); dname = rb_file_s_expand_path(1, &dname);
@ -1204,10 +1130,10 @@ rb_file_s_expand_path(argc, argv)
if (*(s+1)) { if (*(s+1)) {
switch (*++s) { switch (*++s) {
case '.': case '.':
if (*(s+1) == '\0' || *(s+1) == '/') { if (*(s+1) == '\0' || isdirsep(*(s+1))) {
/* We must go back to the parent */ /* We must go back to the parent */
if (*p == '/' && p > buf) p--; if (isdirsep(*p) && p > buf) p--;
while (p > buf && *p != '/') p--; while (p > buf && !isdirsep(*p)) p--;
} }
else { else {
*++p = '.'; *++p = '.';
@ -1215,7 +1141,10 @@ rb_file_s_expand_path(argc, argv)
} }
break; break;
case '/': case '/':
if (*p != '/') *++p = '/'; #if defined DOSISH
case '\\':
#endif
if (!isdirsep(*p)) *++p = '/';
break; break;
default: default:
*++p = '.'; *++p = *s; break; *++p = '.'; *++p = *s; break;
@ -1223,14 +1152,17 @@ rb_file_s_expand_path(argc, argv)
} }
break; break;
case '/': case '/':
if (*p != '/') *++p = '/'; break; #if defined DOSISH
case '\\':
#endif
if (!isdirsep(*p)) *++p = '/'; break;
default: default:
*++p = *s; *++p = *s;
} }
} }
/* Place a \0 at end. If path ends with a "/", delete it */ /* Place a \0 at end. If path ends with a "/", delete it */
if (p == buf || *p != '/') p++; if (p == buf || !isdirsep(*p)) p++;
*p = '\0'; *p = '\0';
return rb_tainted_str_new2(buf); return rb_tainted_str_new2(buf);
@ -1238,7 +1170,7 @@ rb_file_s_expand_path(argc, argv)
static int static int
rmext(p, e) rmext(p, e)
char *p, *e; const char *p, *e;
{ {
int l1, l2; int l1, l2;
@ -1394,10 +1326,11 @@ rb_file_truncate(obj, len)
# define LOCK_UN 8 # define LOCK_UN 8
# endif # endif
#if defined(USE_THREAD) && defined(EWOULDBLOCK) #if defined(EWOULDBLOCK)
static int static int
rb_thread_flock(fd, op) rb_thread_flock(fd, op, fptr)
int fd, op; int fd, op;
OpenFile *fptr;
{ {
if (rb_thread_alone() || (op & LOCK_NB)) { if (rb_thread_alone() || (op & LOCK_NB)) {
return flock(fd, op); return flock(fd, op);
@ -1408,6 +1341,7 @@ rb_thread_flock(fd, op)
case EINTR: /* can be happen? */ case EINTR: /* can be happen? */
case EWOULDBLOCK: case EWOULDBLOCK:
rb_thread_schedule(); /* busy wait */ rb_thread_schedule(); /* busy wait */
rb_io_check_closed(fptr);
break; break;
default: default:
return -1; return -1;
@ -1415,7 +1349,7 @@ rb_thread_flock(fd, op)
} }
return 0; return 0;
} }
#define flock rb_thread_flock #define flock(fd, op) rb_thread_flock(fd, op, fptr)
#endif #endif
static VALUE static VALUE
@ -1452,7 +1386,7 @@ test_check(n, argc, argv)
int i; int i;
n+=1; n+=1;
if (n < argc) rb_raise(rb_eArgError, "Wrong # of arguments(%d for %d)", argc, n); if (n < argc) rb_raise(rb_eArgError, "wrong # of arguments(%d for %d)", argc, n);
for (i=1; i<n; i++) { for (i=1; i<n; i++) {
switch (TYPE(argv[i])) { switch (TYPE(argv[i])) {
case T_STRING: case T_STRING:
@ -1476,7 +1410,7 @@ rb_f_test(argc, argv)
{ {
int cmd; int cmd;
if (argc == 0) rb_raise(rb_eArgError, "Wrong # of arguments"); if (argc == 0) rb_raise(rb_eArgError, "wrong # of arguments");
cmd = NUM2CHR(argv[0]); cmd = NUM2CHR(argv[0]);
if (cmd == 0) return Qfalse; if (cmd == 0) return Qfalse;
if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) { if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) {
@ -1596,15 +1530,24 @@ rb_f_test(argc, argv)
} }
} }
/* unknown command */ /* unknown command */
rb_raise(rb_eArgError, "unknow command ?%c", cmd); rb_raise(rb_eArgError, "unknown command ?%c", cmd);
return Qnil; /* not reached */ return Qnil; /* not reached */
} }
static VALUE rb_mConst;
void
rb_file_const(name, value)
const char *name;
VALUE value;
{
rb_define_const(rb_cFile, name, value);
rb_define_const(rb_mConst, name, value);
}
void void
Init_File() Init_File()
{ {
VALUE rb_mConst;
rb_mFileTest = rb_define_module("FileTest"); rb_mFileTest = rb_define_module("FileTest");
rb_define_module_function(rb_mFileTest, "directory?", test_d, 1); rb_define_module_function(rb_mFileTest, "directory?", test_d, 1);
@ -1637,9 +1580,6 @@ Init_File()
rb_cFile = rb_define_class("File", rb_cIO); rb_cFile = rb_define_class("File", rb_cIO);
rb_extend_object(rb_cFile, CLASS_OF(rb_mFileTest)); rb_extend_object(rb_cFile, CLASS_OF(rb_mFileTest));
rb_define_singleton_method(rb_cFile, "new", rb_file_s_open, -1);
rb_define_singleton_method(rb_cFile, "open", rb_file_s_open, -1);
rb_define_singleton_method(rb_cFile, "stat", rb_file_s_stat, 1); rb_define_singleton_method(rb_cFile, "stat", rb_file_s_stat, 1);
rb_define_singleton_method(rb_cFile, "lstat", rb_file_s_lstat, 1); rb_define_singleton_method(rb_cFile, "lstat", rb_file_s_lstat, 1);
rb_define_singleton_method(rb_cFile, "ftype", rb_file_s_ftype, 1); rb_define_singleton_method(rb_cFile, "ftype", rb_file_s_ftype, 1);
@ -1668,10 +1608,16 @@ Init_File()
separator = rb_str_new2("/"); separator = rb_str_new2("/");
rb_define_const(rb_cFile, "Separator", separator); rb_define_const(rb_cFile, "Separator", separator);
rb_define_const(rb_cFile, "SEPARATOR", separator);
rb_define_singleton_method(rb_cFile, "split", rb_file_s_split, 1); rb_define_singleton_method(rb_cFile, "split", rb_file_s_split, 1);
rb_define_singleton_method(rb_cFile, "join", rb_file_s_join, -2); rb_define_singleton_method(rb_cFile, "join", rb_file_s_join, -2);
rb_define_method(rb_cFile, "reopen", rb_file_reopen, -1); #ifdef DOSISH
rb_define_const(rb_cFile, "ALT_SEPARATOR", rb_str_new2("\\"));
#else
rb_define_const(rb_cFile, "ALT_SEPARATOR", Qnil);
#endif
rb_define_const(rb_cFile, "PATH_SEPARATOR", rb_str_new2(PATH_SEP));
rb_define_method(rb_cIO, "stat", rb_io_stat, 0); /* this is IO's method */ rb_define_method(rb_cIO, "stat", rb_io_stat, 0); /* this is IO's method */
rb_define_method(rb_cFile, "lstat", rb_file_lstat, 0); rb_define_method(rb_cFile, "lstat", rb_file_lstat, 0);
@ -1687,15 +1633,10 @@ Init_File()
rb_define_method(rb_cFile, "flock", rb_file_flock, 1); rb_define_method(rb_cFile, "flock", rb_file_flock, 1);
rb_mConst = rb_define_module_under(rb_cFile, "Constants"); rb_mConst = rb_define_module_under(rb_cFile, "Constants");
rb_define_const(rb_cFile, "LOCK_SH", INT2FIX(LOCK_SH)); rb_file_const("LOCK_SH", INT2FIX(LOCK_SH));
rb_define_const(rb_cFile, "LOCK_EX", INT2FIX(LOCK_EX)); rb_file_const("LOCK_EX", INT2FIX(LOCK_EX));
rb_define_const(rb_cFile, "LOCK_UN", INT2FIX(LOCK_UN)); rb_file_const("LOCK_UN", INT2FIX(LOCK_UN));
rb_define_const(rb_cFile, "LOCK_NB", INT2FIX(LOCK_NB)); rb_file_const("LOCK_NB", INT2FIX(LOCK_NB));
rb_define_const(rb_mConst, "LOCK_SH", INT2FIX(LOCK_SH));
rb_define_const(rb_mConst, "LOCK_EX", INT2FIX(LOCK_EX));
rb_define_const(rb_mConst, "LOCK_UN", INT2FIX(LOCK_UN));
rb_define_const(rb_mConst, "LOCK_NB", INT2FIX(LOCK_NB));
rb_define_method(rb_cFile, "path", rb_file_path, 0); rb_define_method(rb_cFile, "path", rb_file_path, 0);

243
fnmatch.c
View file

@ -1,243 +0,0 @@
/* Copyright (C) 1991 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include "config.h"
#include <errno.h>
#include "fnmatch.h"
#ifdef USE_CWGUSI
#include <sys/errno.h>
#endif
#if !defined (__GNU_LIBRARY__) && !defined (STDC_HEADERS)
# if !defined (errno)
extern int errno;
# endif /* !errno */
#endif
/* Match STRING against the filename pattern PATTERN, returning zero if
it matches, FNM_NOMATCH if not. */
int
fnmatch (pattern, string, flags)
char *pattern;
char *string;
int flags;
{
register char *p = pattern, *n = string;
register char c;
if ((flags & ~__FNM_FLAGS) != 0)
{
errno = EINVAL;
return (-1);
}
while ((c = *p++) != '\0')
{
switch (c)
{
case '?':
if (*n == '\0')
return (FNM_NOMATCH);
else if ((flags & FNM_PATHNAME) && *n == '/')
/* If we are matching a pathname, `?' can never match a `/'. */
return (FNM_NOMATCH);
else if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
/* `?' cannot match a `.' if it is the first character of the
string or if it is the first character following a slash and
we are matching a pathname. */
return (FNM_NOMATCH);
break;
case '\\':
if (!(flags & FNM_NOESCAPE))
{
c = *p++;
if (c == '\0')
return (FNM_NOMATCH);
}
if (*n != c)
return (FNM_NOMATCH);
break;
case '*':
if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
/* `*' cannot match a `.' if it is the first character of the
string or if it is the first character following a slash and
we are matching a pathname. */
return (FNM_NOMATCH);
/* Collapse multiple consecutive, `*' and `?', but make sure that
one character of the string is consumed for each `?'. */
for (c = *p++; c == '?' || c == '*'; c = *p++)
{
if ((flags & FNM_PATHNAME) && *n == '/')
/* A slash does not match a wildcard under FNM_PATHNAME. */
return (FNM_NOMATCH);
else if (c == '?')
{
if (*n == '\0')
return (FNM_NOMATCH);
/* One character of the string is consumed in matching
this ? wildcard, so *??? won't match if there are
fewer than three characters. */
n++;
}
}
if (c == '\0')
return (0);
/* General case, use recursion. */
{
char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
for (--p; *n != '\0'; ++n)
/* Only call fnmatch if the first character indicates a
possible match. */
if ((c == '[' || *n == c1) &&
fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
return (0);
return (FNM_NOMATCH);
}
case '[':
{
/* Nonzero if the sense of the character class is inverted. */
register int not;
if (*n == '\0')
return (FNM_NOMATCH);
/* A character class cannot match a `.' if it is the first
character of the string or if it is the first character
following a slash and we are matching a pathname. */
if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
return (FNM_NOMATCH);
/* POSIX.2 2.8.3.1.2 says: `An expression containing a `[' that
is not preceded by a backslash and is not part of a bracket
expression produces undefined results.' This implementation
treats the `[' as just a character to be matched if there is
not a closing `]'. This code will have to be changed when
POSIX.2 character classes are implemented. */
{
register char *np;
for (np = p; np && *np && *np != ']'; np++)
;
if (np && !*np)
{
if (*n != '[')
return (FNM_NOMATCH);
break;
}
}
not = (*p == '!' || *p == '^');
if (not)
++p;
c = *p++;
for (;;)
{
register char cstart, cend;
/* Initialize cstart and cend in case `-' is the last
character of the pattern. */
cstart = cend = c;
if (!(flags & FNM_NOESCAPE) && c == '\\')
{
if (*p == '\0')
return FNM_NOMATCH;
cstart = cend = *p++;
}
if (c == '\0')
/* [ (unterminated) loses. */
return (FNM_NOMATCH);
c = *p++;
if ((flags & FNM_PATHNAME) && c == '/')
/* [/] can never match. */
return (FNM_NOMATCH);
/* This introduces a range, unless the `-' is the last
character of the class. Find the end of the range
and move past it. */
if (c == '-' && *p != ']')
{
cend = *p++;
if (!(flags & FNM_NOESCAPE) && cend == '\\')
cend = *p++;
if (cend == '\0')
return (FNM_NOMATCH);
c = *p++;
}
if (*n >= cstart && *n <= cend)
goto matched;
if (c == ']')
break;
}
if (!not)
return (FNM_NOMATCH);
break;
matched:
/* Skip the rest of the [...] that already matched. */
while (c != ']')
{
if (c == '\0')
/* [... (unterminated) loses. */
return (FNM_NOMATCH);
c = *p++;
if (!(flags & FNM_NOESCAPE) && c == '\\')
{
if (*p == '\0')
return FNM_NOMATCH;
/* XXX 1003.2d11 is unclear if this is right. */
++p;
}
}
if (not)
return (FNM_NOMATCH);
}
break;
default:
if (c != *n)
return (FNM_NOMATCH);
}
++n;
}
if (*n == '\0')
return (0);
return (FNM_NOMATCH);
}

View file

@ -1,36 +0,0 @@
/* Copyright (C) 1991 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#ifndef _FNMATCH_H
#define _FNMATCH_H 1
/* Bits set in the FLAGS argument to `fnmatch'. */
#define FNM_PATHNAME (1 << 0)/* No wildcard can ever match `/'. */
#define FNM_NOESCAPE (1 << 1)/* Backslashes don't quote special chars. */
#define FNM_PERIOD (1 << 2)/* Leading `.' is matched only explicitly. */
#define __FNM_FLAGS (FNM_PATHNAME|FNM_NOESCAPE|FNM_PERIOD)
/* Value returned by `fnmatch' if STRING does not match PATTERN. */
#define FNM_NOMATCH 1
/* Match STRING against the filename pattern PATTERN,
returning zero if it matches, FNM_NOMATCH if not. */
extern int fnmatch();
#endif /* fnmatch.h */

92
gc.c
View file

@ -6,7 +6,7 @@
$Date$ $Date$
created at: Tue Oct 5 09:44:46 JST 1993 created at: Tue Oct 5 09:44:46 JST 1993
Copyright (C) 1993-1998 Yukihiro Matsumoto Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/ ************************************************/
@ -42,14 +42,18 @@ static void run_final();
#if defined(MSDOS) || defined(__human68k__) #if defined(MSDOS) || defined(__human68k__)
#define GC_MALLOC_LIMIT 100000 #define GC_MALLOC_LIMIT 100000
#else #else
#define GC_MALLOC_LIMIT 200000 #define GC_MALLOC_LIMIT 400000
#endif #endif
#endif #endif
#define GC_NEWOBJ_LIMIT 1000 #define GC_NEWOBJ_LIMIT 10000
static unsigned long malloc_memories = 0; static unsigned long malloc_memories = 0;
static unsigned long alloc_objects = 0; static unsigned long alloc_objects = 0;
static int malloc_called = 0;
static int free_called = 0;
#ifndef xmalloc
void * void *
xmalloc(size) xmalloc(size)
size_t size; size_t size;
@ -64,6 +68,7 @@ xmalloc(size)
if (malloc_memories > GC_MALLOC_LIMIT && alloc_objects > GC_NEWOBJ_LIMIT) { if (malloc_memories > GC_MALLOC_LIMIT && alloc_objects > GC_NEWOBJ_LIMIT) {
rb_gc(); rb_gc();
} }
malloc_called++;
mem = malloc(size); mem = malloc(size);
if (!mem) { if (!mem) {
rb_gc(); rb_gc();
@ -111,6 +116,15 @@ xrealloc(ptr, size)
return mem; return mem;
} }
static void
xfree(x)
void *x;
{
free_called++;
free(x);
}
#endif
/* The way of garbage collecting which allows use of the cstack is due to */ /* The way of garbage collecting which allows use of the cstack is due to */
/* Scheme In One Defun, but in C this time. /* Scheme In One Defun, but in C this time.
@ -284,7 +298,7 @@ rb_data_object_alloc(klass, datap, dmark, dfree)
} }
extern st_table *rb_class_tbl; extern st_table *rb_class_tbl;
VALUE *rb_gc_stack_start; VALUE *rb_gc_stack_start = 0;
#if defined(__GNUC__) && __GNUC__ >= 2 #if defined(__GNUC__) && __GNUC__ >= 2
__inline__ __inline__
@ -334,7 +348,7 @@ rb_gc_mark_locations(start, end)
start = end; start = end;
end = tmp; end = tmp;
} }
n = end - start; n = end - start + 1;
mark_locations_array(start,n); mark_locations_array(start,n);
} }
@ -389,10 +403,10 @@ rb_gc_mark(ptr)
register RVALUE *obj = RANY(ptr); register RVALUE *obj = RANY(ptr);
Top: Top:
if (FIXNUM_P(obj)) return; /* fixnum not marked */ if (FIXNUM_P(obj)) return; /* fixnum not marked */
if (rb_special_const_p((VALUE)obj)) return; /* special const not marked */ if (rb_special_const_p((VALUE)obj)) return; /* special const not marked */
if (obj->as.basic.flags == 0) return; /* free cell */ if (obj->as.basic.flags == 0) return; /* free cell */
if (obj->as.basic.flags & FL_MARK) return; /* already marked */ if (obj->as.basic.flags & FL_MARK) return; /* already marked */
obj->as.basic.flags |= FL_MARK; obj->as.basic.flags |= FL_MARK;
@ -445,7 +459,6 @@ rb_gc_mark(ptr)
case NODE_OR: case NODE_OR:
case NODE_CASE: case NODE_CASE:
case NODE_SCLASS: case NODE_SCLASS:
case NODE_ARGS:
case NODE_DOT2: case NODE_DOT2:
case NODE_DOT3: case NODE_DOT3:
case NODE_FLIP2: case NODE_FLIP2:
@ -479,6 +492,7 @@ rb_gc_mark(ptr)
case NODE_RETURN: case NODE_RETURN:
case NODE_YIELD: case NODE_YIELD:
case NODE_COLON2: case NODE_COLON2:
case NODE_ARGS:
obj = RANY(obj->as.node.u1.node); obj = RANY(obj->as.node.u1.node);
goto Top; goto Top;
@ -598,7 +612,8 @@ rb_gc_mark(ptr)
break; break;
case T_SCOPE: case T_SCOPE:
if (obj->as.scope.local_vars) { if (obj->as.scope.local_vars &&
obj->as.scope.flag != SCOPE_ALLOCA) {
int n = obj->as.scope.local_tbl[0]+1; int n = obj->as.scope.local_tbl[0]+1;
VALUE *vars = &obj->as.scope.local_vars[-1]; VALUE *vars = &obj->as.scope.local_vars[-1];
@ -660,7 +675,7 @@ gc_sweep()
if (p->as.basic.flags) { if (p->as.basic.flags) {
obj_free((VALUE)p); obj_free((VALUE)p);
} }
if (need_call_final && FL_TEST(p, FL_FINALIZE)) { if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
p->as.free.flag = FL_MARK; /* remain marked */ p->as.free.flag = FL_MARK; /* remain marked */
p->as.free.next = final_list; p->as.free.next = final_list;
final_list = p; final_list = p;
@ -769,10 +784,10 @@ obj_free(obj)
} }
break; break;
case T_MATCH: case T_MATCH:
if (RANY(obj)->as.match.regs) if (RANY(obj)->as.match.regs) {
re_free_registers(RANY(obj)->as.match.regs); re_free_registers(RANY(obj)->as.match.regs);
if (RANY(obj)->as.match.regs)
free(RANY(obj)->as.match.regs); free(RANY(obj)->as.match.regs);
}
break; break;
case T_FILE: case T_FILE:
if (RANY(obj)->as.file.fptr) { if (RANY(obj)->as.file.fptr) {
@ -807,7 +822,8 @@ obj_free(obj)
return; /* no need to free iv_tbl */ return; /* no need to free iv_tbl */
case T_SCOPE: case T_SCOPE:
if (RANY(obj)->as.scope.local_vars) { if (RANY(obj)->as.scope.local_vars &&
RANY(obj)->as.scope.flag != SCOPE_ALLOCA) {
VALUE *vars = RANY(obj)->as.scope.local_vars-1; VALUE *vars = RANY(obj)->as.scope.local_vars-1;
if (vars[0] == 0) if (vars[0] == 0)
free(RANY(obj)->as.scope.local_tbl); free(RANY(obj)->as.scope.local_tbl);
@ -890,7 +906,16 @@ rb_gc()
/* mark frame stack */ /* mark frame stack */
for (frame = ruby_frame; frame; frame = frame->prev) { for (frame = ruby_frame; frame; frame = frame->prev) {
rb_gc_mark_frame(frame); rb_gc_mark_frame(frame);
}
for (frame = ruby_frame; frame; frame = frame->prev) {
if (frame->tmp) {
struct FRAME *tmp = frame->tmp;
while (tmp) {
rb_gc_mark_frame(tmp);
tmp = tmp->prev;
}
}
} }
rb_gc_mark(ruby_class); rb_gc_mark(ruby_class);
rb_gc_mark(ruby_scope); rb_gc_mark(ruby_scope);
@ -909,10 +934,7 @@ rb_gc()
rb_gc_mark_locations((VALUE*)((char*)rb_gc_stack_start + 2), rb_gc_mark_locations((VALUE*)((char*)rb_gc_stack_start + 2),
(VALUE*)((char*)&stack_end + 2)); (VALUE*)((char*)&stack_end + 2));
#endif #endif
#ifdef USE_THREAD
rb_gc_mark_threads(); rb_gc_mark_threads();
#endif
/* mark protected global variables */ /* mark protected global variables */
for (list = Global_List; list; list = list->next) { for (list = Global_List; list; list = list->next) {
@ -937,22 +959,26 @@ gc_start()
} }
void void
Init_stack() Init_stack(addr)
VALUE *addr;
{ {
#ifdef __human68k__ #ifdef __human68k__
extern void *_SEND; extern void *_SEND;
gc_stack_start = _SEND; rb_gc_stack_start = _SEND;
#else #else
VALUE start; VALUE start;
rb_gc_stack_start = &start; if (!addr) addr = &start;
rb_gc_stack_start = addr;
#endif #endif
} }
void void
Init_heap() Init_heap()
{ {
Init_stack(); if (!rb_gc_stack_start) {
Init_stack(0);
}
add_heap(); add_heap();
} }
@ -1073,15 +1099,26 @@ call_final(os, obj)
return obj; return obj;
} }
static VALUE
run_single_final(args)
VALUE *args;
{
rb_eval_cmd(args[0], args[1]);
return Qnil;
}
static void static void
run_final(obj) run_final(obj)
VALUE obj; VALUE obj;
{ {
int i; int i, status;
VALUE args[2];
obj = rb_obj_id(obj); /* make obj into id */ obj = rb_obj_id(obj); /* make obj into id */
args[1] = rb_ary_new3(1, obj);
for (i=0; i<RARRAY(finalizers)->len; i++) { for (i=0; i<RARRAY(finalizers)->len; i++) {
rb_eval_cmd(RARRAY(finalizers)->ptr[i], rb_ary_new3(1, obj)); args[0] = RARRAY(finalizers)->ptr[i];
rb_protect(run_single_final, (VALUE)args, &status);
} }
} }
@ -1105,9 +1142,12 @@ rb_gc_call_finalizer_at_exit()
p = heaps[i]; pend = p + HEAP_SLOTS; p = heaps[i]; pend = p + HEAP_SLOTS;
while (p < pend) { while (p < pend) {
if (BUILTIN_TYPE(p) == T_DATA && if (BUILTIN_TYPE(p) == T_DATA &&
DATA_PTR(p) && DATA_PTR(p) && RANY(p)->as.data.dfree) {
RANY(p)->as.data.dfree)
(*RANY(p)->as.data.dfree)(DATA_PTR(p)); (*RANY(p)->as.data.dfree)(DATA_PTR(p));
}
else if (BUILTIN_TYPE(p) == T_FILE) {
rb_io_fptr_finalize(RANY(p)->as.file.fptr);
}
p++; p++;
} }
} }

591
glob.c
View file

@ -1,591 +0,0 @@
/* File-name wildcard pattern matching for GNU.
Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* To whomever it may concern: I have never seen the code which most
Unix programs use to perform this function. I wrote this from scratch
based on specifications for the pattern matching. --RMS. */
#include "config.h"
#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
#pragma alloca
#endif /* _AIX && RISC6000 && !__GNUC__ */
#if defined (HAVE_ALLOCA_H)
# include <alloca.h>
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined (HAVE_STDLIB_H)
# include <stdlib.h>
#else
# if defined (SHELL)
# include "ansi_stdlib.h"
# endif /* SHELL */
#endif
#include <sys/types.h>
#if defined (HAVE_DIRENT_H)
# include <dirent.h>
# define D_NAMLEN(d) strlen ((d)->d_name)
#elif HAVE_DIRECT_H
# include <direct.h>
# define D_NAMLEN(d) strlen ((d)->d_name)
#else /* !HAVE_DIRENT_H */
# define D_NAMLEN(d) ((d)->d_namlen)
# if defined (HAVE_SYS_NDIR_H)
# include <sys/ndir.h>
# endif
# if defined (HAVE_SYS_DIR_H)
# include <sys/dir.h>
# endif /* HAVE_SYS_DIR_H */
# if defined (HAVE_NDIR_H)
# include <ndir.h>
# endif
# if !defined (dirent)
# define dirent direct
# endif
#endif /* !HAVE_DIRENT_H */
#if defined (_POSIX_SOURCE) || defined(DJGPP) || defined(USE_CWGUSI)
/* Posix does not require that the d_ino field be present, and some
systems do not provide it. */
# define REAL_DIR_ENTRY(dp) 1
#elif defined (__BORLANDC__)
# define REAL_DIR_ENTRY(dp) 1
#else
# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
#endif /* _POSIX_SOURCE */
#if defined (HAVE_STRING_H)
# include <string.h>
#else /* !HAVE_STRING_H */
# include <strings.h>
#endif /* !HAVE_STRING_H */
#if !defined (HAVE_BCOPY) && !defined (bcopy)
# define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
#endif /* !HAVE_BCOPY */
/* If the opendir () on your system lets you open non-directory files,
then we consider that not robust. */
#if defined (OPENDIR_NOT_ROBUST)
# if defined (SHELL)
# include "posixstat.h"
# else /* !SHELL */
# include <sys/stat.h>
# endif /* !SHELL */
#endif /* OPENDIR_NOT_ROBUST */
#include "fnmatch.h"
extern void *xmalloc (), *xrealloc ();
#if !defined (HAVE_STDLIB_H)
extern void free ();
#endif /* !HAVE_STDLIB_H */
#if !defined (NULL)
# if defined (__STDC__)
# define NULL ((void *) 0)
# else
# define NULL 0x0
# endif /* __STDC__ */
#endif /* !NULL */
#if defined (SHELL)
extern void throw_to_top_level ();
extern int interrupt_state;
#endif /* SHELL */
#if defined(NT) && defined(_MSC_VER)
#include "missing/dir.h"
#endif
/* Global variable which controls whether or not * matches .*.
Non-zero means don't match .*. */
int noglob_dot_filenames = 1;
/* Global variable to return to signify an error in globbing. */
char *glob_error_return;
/* Return nonzero if PATTERN has any special globbing chars in it. */
int
glob_pattern_p (pattern)
char *pattern;
{
register char *p = pattern;
register char c;
int open = 0;
while ((c = *p++) != '\0')
switch (c)
{
case '?':
case '*':
return (1);
case '[': /* Only accept an open brace if there is a close */
open++; /* brace to match it. Bracket expressions must be */
continue; /* complete, according to Posix.2 */
case ']':
if (open)
return (1);
continue;
case '\\':
if (*p++ == '\0')
return (0);
}
return (0);
}
/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
static void
dequote_pathname (pathname)
char *pathname;
{
register int i, j;
for (i = j = 0; pathname && pathname[i]; )
{
if (pathname[i] == '\\')
i++;
pathname[j++] = pathname[i++];
if (!pathname[i - 1])
break;
}
pathname[j] = '\0';
}
/* Return a vector of names of files in directory DIR
whose names match glob pattern PAT.
The names are not in any particular order.
Wildcards at the beginning of PAT do not match an initial period.
The vector is terminated by an element that is a null pointer.
To free the space allocated, first free the vector's elements,
then free the vector.
Return 0 if cannot get enough memory to hold the pointer
and the names.
Return -1 if cannot access directory DIR.
Look in errno for more information. */
char **
glob_vector (pat, dir)
char *pat;
char *dir;
{
struct globval
{
struct globval *next;
char *name;
};
DIR *d;
register struct dirent *dp;
struct globval *lastlink;
register struct globval *nextlink;
register char *nextname;
unsigned int count;
int lose, skip;
register char **name_vector;
register unsigned int i;
#if defined (OPENDIR_NOT_ROBUST)
struct stat finfo;
if (stat (dir, &finfo) < 0)
return ((char **) &glob_error_return);
if (!S_ISDIR (finfo.st_mode))
return ((char **) &glob_error_return);
#endif /* OPENDIR_NOT_ROBUST */
d = opendir (dir);
if (d == NULL)
return ((char **) &glob_error_return);
lastlink = 0;
count = 0;
lose = 0;
skip = 0;
/* If PAT is empty, skip the loop, but return one (empty) filename. */
if (!pat || !*pat)
{
nextlink = (struct globval *)alloca (sizeof (struct globval));
nextlink->next = lastlink;
nextname = (char *) xmalloc (1);
if (!nextname)
lose = 1;
else
{
lastlink = nextlink;
nextlink->name = nextname;
nextname[0] = '\0';
count++;
}
skip = 1;
}
/* Scan the directory, finding all names that match.
For each name that matches, allocate a struct globval
on the stack and store the name in it.
Chain those structs together; lastlink is the front of the chain. */
while (!skip)
{
int flags; /* Flags passed to fnmatch (). */
#if defined (SHELL)
/* Make globbing interruptible in the bash shell. */
if (interrupt_state)
{
closedir (d);
lose = 1;
goto lost;
}
#endif /* SHELL */
dp = readdir (d);
if (dp == NULL)
break;
/* If this directory entry is not to be used, try again. */
if (!REAL_DIR_ENTRY (dp))
continue;
/* If a dot must be explicity matched, check to see if they do. */
if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.' &&
(pat[0] != '\\' || pat[1] != '.'))
continue;
flags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
if (fnmatch (pat, dp->d_name, flags) != FNM_NOMATCH)
{
nextlink = (struct globval *) alloca (sizeof (struct globval));
nextlink->next = lastlink;
nextname = (char *) xmalloc (D_NAMLEN (dp) + 1);
if (nextname == NULL)
{
lose = 1;
break;
}
lastlink = nextlink;
nextlink->name = nextname;
bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1);
++count;
}
}
(void) closedir (d);
if (!lose)
{
name_vector = (char **) xmalloc ((count + 1) * sizeof (char *));
lose |= name_vector == NULL;
}
/* Have we run out of memory? */
#if defined (SHELL)
lost:
#endif
if (lose)
{
/* Here free the strings we have got. */
while (lastlink)
{
free (lastlink->name);
lastlink = lastlink->next;
}
#if defined (SHELL)
if (interrupt_state)
throw_to_top_level ();
#endif /* SHELL */
return (NULL);
}
/* Copy the name pointers from the linked list into the vector. */
for (i = 0; i < count; ++i)
{
name_vector[i] = lastlink->name;
lastlink = lastlink->next;
}
name_vector[count] = NULL;
return (name_vector);
}
/* Return a new array which is the concatenation of each string in ARRAY
to DIR. This function expects you to pass in an allocated ARRAY, and
it takes care of free()ing that array. Thus, you might think of this
function as side-effecting ARRAY. */
static char **
glob_dir_to_array (dir, array)
char *dir, **array;
{
register unsigned int i, l;
int add_slash;
char **result;
l = strlen (dir);
if (l == 0)
return (array);
add_slash = dir[l - 1] != '/';
i = 0;
while (array[i] != NULL)
++i;
result = (char **) xmalloc ((i + 1) * sizeof (char *));
if (result == NULL)
return (NULL);
for (i = 0; array[i] != NULL; i++)
{
result[i] = (char *) xmalloc (l + (add_slash ? 1 : 0)
+ strlen (array[i]) + 1);
if (result[i] == NULL)
return (NULL);
#if 1
strcpy (result[i], dir);
if (add_slash)
result[i][l] = '/';
strcpy (result[i] + l + add_slash, array[i]);
#else
(void)sprintf (result[i], "%s%s%s", dir, add_slash ? "/" : "", array[i]);
#endif
}
result[i] = NULL;
/* Free the input array. */
for (i = 0; array[i] != NULL; i++)
free (array[i]);
free ((char *) array);
return (result);
}
/* Do globbing on PATHNAME. Return an array of pathnames that match,
marking the end of the array with a null-pointer as an element.
If no pathnames match, then the array is empty (first element is null).
If there isn't enough memory, then return NULL.
If a file system error occurs, return -1; `errno' has the error code. */
char **
glob_filename (pathname)
char *pathname;
{
#ifndef strrchr
char *strrchr();
#endif
char **result;
unsigned int result_size;
char *directory_name, *filename;
unsigned int directory_len;
result = (char **) xmalloc (sizeof (char *));
result_size = 1;
if (result == NULL)
return (NULL);
result[0] = NULL;
/* Find the filename. */
filename = strrchr (pathname, '/');
if (filename == NULL)
{
filename = pathname;
directory_name = "";
directory_len = 0;
}
else
{
directory_len = (filename - pathname) + 1;
directory_name = (char *) alloca (directory_len + 1);
bcopy (pathname, directory_name, directory_len);
directory_name[directory_len] = '\0';
++filename;
}
/* If directory_name contains globbing characters, then we
have to expand the previous levels. Just recurse. */
if (glob_pattern_p (directory_name))
{
char **directories;
register unsigned int i;
if (directory_name[directory_len - 1] == '/')
directory_name[directory_len - 1] = '\0';
directories = glob_filename (directory_name);
if (directories == NULL)
goto memory_error;
else if (directories == (char **)&glob_error_return)
{
free ((char *) result);
return ((char **) &glob_error_return);
}
else if (*directories == NULL)
{
free ((char *) directories);
free ((char *) result);
return ((char **) &glob_error_return);
}
/* We have successfully globbed the preceding directory name.
For each name in DIRECTORIES, call glob_vector on it and
FILENAME. Concatenate the results together. */
for (i = 0; directories[i] != NULL; ++i)
{
char **temp_results;
/* Scan directory even on a NULL pathname. That way, `*h/'
returns only directories ending in `h', instead of all
files ending in `h' with a `/' appended. */
temp_results = glob_vector (filename, directories[i]);
/* Handle error cases. */
if (temp_results == NULL)
goto memory_error;
else if (temp_results == (char **)&glob_error_return)
/* This filename is probably not a directory. Ignore it. */
;
else
{
char **array;
register unsigned int l;
array = glob_dir_to_array (directories[i], temp_results);
l = 0;
while (array[l] != NULL)
++l;
result =
(char **)xrealloc(result, (result_size + l) * sizeof (char *));
if (result == NULL)
goto memory_error;
for (l = 0; array[l] != NULL; ++l)
result[result_size++ - 1] = array[l];
result[result_size - 1] = NULL;
/* Note that the elements of ARRAY are not freed. */
free ((char *) array);
}
}
/* Free the directories. */
for (i = 0; directories[i]; i++)
free (directories[i]);
free ((char *) directories);
return (result);
}
/* If there is only a directory name, return it. */
if (*filename == '\0')
{
result = (char **) xrealloc ((char *) result, 2 * sizeof (char *));
if (result == NULL)
return (NULL);
result[0] = (char *) xmalloc (directory_len + 1);
if (result[0] == NULL)
goto memory_error;
bcopy (directory_name, result[0], directory_len + 1);
result[1] = NULL;
return (result);
}
else
{
char **temp_results;
/* There are no unquoted globbing characters in DIRECTORY_NAME.
Dequote it before we try to open the directory since there may
be quoted globbing characters which should be treated verbatim. */
if (directory_len > 0)
dequote_pathname (directory_name);
/* We allocated a small array called RESULT, which we won't be using.
Free that memory now. */
free (result);
/* Just return what glob_vector () returns appended to the
directory name. */
temp_results =
glob_vector (filename, (directory_len == 0 ? "." : directory_name));
if (temp_results == NULL || temp_results == (char **)&glob_error_return)
return (temp_results);
return (glob_dir_to_array (directory_name, temp_results));
}
/* We get to memory_error if the program has run out of memory, or
if this is the shell, and we have been interrupted. */
memory_error:
if (result != NULL)
{
register unsigned int i;
for (i = 0; result[i] != NULL; ++i)
free (result[i]);
free ((char *) result);
}
#if defined (SHELL)
if (interrupt_state)
throw_to_top_level ();
#endif /* SHELL */
return (NULL);
}
#if defined (TEST)
main (argc, argv)
int argc;
char **argv;
{
unsigned int i;
for (i = 1; i < argc; ++i)
{
char **value = glob_filename (argv[i]);
if (value == NULL)
puts ("Out of memory.");
else if (value == &glob_error_return)
perror (argv[i]);
else
for (i = 0; value[i] != NULL; i++)
puts (value[i]);
}
exit (0);
}
#endif /* TEST. */

220
hash.c
View file

@ -6,12 +6,13 @@
$Date$ $Date$
created at: Mon Nov 22 18:51:18 JST 1993 created at: Mon Nov 22 18:51:18 JST 1993
Copyright (C) 1993-1998 Yukihiro Matsumoto Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/ ************************************************/
#include "ruby.h" #include "ruby.h"
#include "st.h" #include "st.h"
#include "util.h"
#include "rubysig.h" #include "rubysig.h"
#include <sys/types.h> #include <sys/types.h>
@ -21,6 +22,10 @@
char *strchr _((char*,char)); char *strchr _((char*,char));
#endif #endif
#ifdef USE_CWGUSI
char* strdup(const char*);
#endif
#define HASH_FREEZE FL_USER1 #define HASH_FREEZE FL_USER1
#define HASH_DELETED FL_USER2 #define HASH_DELETED FL_USER2
@ -30,7 +35,7 @@ rb_hash_modify(hash)
{ {
if (FL_TEST(hash, HASH_FREEZE)) if (FL_TEST(hash, HASH_FREEZE))
rb_raise(rb_eTypeError, "can't modify frozen hash"); rb_raise(rb_eTypeError, "can't modify frozen hash");
if (rb_safe_level() >= 4 && !FL_TEST(hash, FL_TAINT)) if (!FL_TEST(hash, FL_TAINT) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify hash"); rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
} }
@ -63,6 +68,13 @@ rb_hash(obj)
return rb_funcall(obj, hash, 0); return rb_funcall(obj, hash, 0);
} }
static VALUE
eql(args)
VALUE *args;
{
return (VALUE)rb_eql(args[0], args[1]);
}
static int static int
rb_any_cmp(a, b) rb_any_cmp(a, b)
VALUE a, b; VALUE a, b;
@ -73,11 +85,13 @@ rb_any_cmp(a, b)
else if (TYPE(a) == T_STRING) { else if (TYPE(a) == T_STRING) {
if (TYPE(b) == T_STRING) return rb_str_cmp(a, b); if (TYPE(b) == T_STRING) return rb_str_cmp(a, b);
} }
else {
VALUE args[2];
DEFER_INTS; args[0] = a;
a = !rb_eql(a, b); args[1] = b;
ENABLE_INTS; return !rb_with_disable_interrupt(eql, (VALUE)args);
return a; }
} }
static int static int
@ -127,7 +141,7 @@ rb_hash_foreach_iter(key, value, arg)
st_table *tbl = RHASH(arg->hash)->tbl; st_table *tbl = RHASH(arg->hash)->tbl;
struct st_table_entry **bins = tbl->bins; struct st_table_entry **bins = tbl->bins;
if (key == Qnil) return ST_CONTINUE; if (value == Qnil) return ST_CONTINUE;
status = (*arg->func)(key, value, arg->arg); status = (*arg->func)(key, value, arg->arg);
if (RHASH(arg->hash)->tbl != tbl || RHASH(arg->hash)->tbl->bins != bins){ if (RHASH(arg->hash)->tbl != tbl || RHASH(arg->hash)->tbl->bins != bins){
rb_raise(rb_eIndexError, "rehash occurred during iteration"); rb_raise(rb_eIndexError, "rehash occurred during iteration");
@ -143,14 +157,6 @@ rb_hash_foreach_call(arg)
return Qnil; return Qnil;
} }
static int
rb_hash_delete_nil(key, value)
VALUE key, value;
{
if (value == Qnil) return ST_DELETE;
return ST_CONTINUE;
}
static VALUE static VALUE
rb_hash_foreach_ensure(hash) rb_hash_foreach_ensure(hash)
VALUE hash; VALUE hash;
@ -159,7 +165,7 @@ rb_hash_foreach_ensure(hash)
if (RHASH(hash)->iter_lev == 0) { if (RHASH(hash)->iter_lev == 0) {
if (FL_TEST(hash, HASH_DELETED)) { if (FL_TEST(hash, HASH_DELETED)) {
st_foreach(RHASH(hash)->tbl, rb_hash_delete_nil, 0); st_cleanup_safe(RHASH(hash)->tbl, Qnil);
FL_UNSET(hash, HASH_DELETED); FL_UNSET(hash, HASH_DELETED);
} }
} }
@ -187,8 +193,7 @@ rb_hash_s_new(argc, argv, klass)
VALUE *argv; VALUE *argv;
VALUE klass; VALUE klass;
{ {
VALUE sz, ifnone; VALUE ifnone;
int size;
NEWOBJ(hash, struct RHash); NEWOBJ(hash, struct RHash);
OBJSETUP(hash, klass, T_HASH); OBJSETUP(hash, klass, T_HASH);
@ -197,15 +202,10 @@ rb_hash_s_new(argc, argv, klass)
hash->ifnone = Qnil; hash->ifnone = Qnil;
hash->tbl = 0; /* avoid GC crashing */ hash->tbl = 0; /* avoid GC crashing */
rb_scan_args(argc, argv, "02", &ifnone, &sz); rb_scan_args(argc, argv, "01", &ifnone);
if (NIL_P(sz)) {
size = 0;
}
else size = NUM2INT(sz);
hash->ifnone = ifnone; hash->ifnone = ifnone;
hash->tbl = st_init_table_with_size(&objhash, size); hash->tbl = st_init_table(&objhash);
rb_obj_call_init((VALUE)hash);
return (VALUE)hash; return (VALUE)hash;
} }
@ -240,19 +240,22 @@ rb_hash_s_create(argc, argv, klass)
VALUE hash; VALUE hash;
int i; int i;
if (argc == 1 && TYPE(argv[0]) == T_HASH) { if (argc == 1) {
if (klass == CLASS_OF(argv[0])) return argv[0]; if (TYPE(argv[0]) == T_HASH) {
else {
NEWOBJ(hash, struct RHash); NEWOBJ(hash, struct RHash);
OBJSETUP(hash, klass, T_HASH); OBJSETUP(hash, klass, T_HASH);
hash->iter_lev = 0; hash->iter_lev = 0;
hash->ifnone = Qnil; hash->ifnone = Qnil;
hash->tbl = 0; /* avoid GC crashing */ hash->tbl = 0; /* avoid GC crashing */
hash->tbl = (st_table*)st_copy(RHASH(argv[0])->tbl); hash->tbl = st_copy(RHASH(argv[0])->tbl);
rb_obj_call_init((VALUE)hash);
return (VALUE)hash; return (VALUE)hash;
} }
else {
VALUE a = rb_Array(argv[0]);
return rb_hash_s_create(RARRAY(a)->len, RARRAY(a)->ptr, klass);
}
} }
if (argc % 2 != 0) { if (argc % 2 != 0) {
@ -263,7 +266,6 @@ rb_hash_s_create(argc, argv, klass)
for (i=0; i<argc; i+=2) { for (i=0; i<argc; i+=2) {
st_insert(RHASH(hash)->tbl, argv[i], argv[i+1]); st_insert(RHASH(hash)->tbl, argv[i], argv[i+1]);
} }
rb_obj_call_init(hash);
return hash; return hash;
} }
@ -380,6 +382,32 @@ rb_hash_set_default(hash, ifnone)
return hash; return hash;
} }
static int
index_i(key, value, args)
VALUE key, value;
VALUE *args;
{
if (rb_equal(value, args[0])) {
args[1] = key;
return ST_STOP;
}
return ST_CONTINUE;
}
static VALUE
rb_hash_index(hash, value)
VALUE hash, value;
{
VALUE args[2];
args[0] = value;
args[1] = Qnil;
st_foreach(RHASH(hash)->tbl, index_i, args);
return args[1];
}
static VALUE static VALUE
rb_hash_indexes(argc, argv, hash) rb_hash_indexes(argc, argv, hash)
int argc; int argc;
@ -428,7 +456,7 @@ shift_i(key, value, var)
VALUE key, value; VALUE key, value;
struct shift_var *var; struct shift_var *var;
{ {
if (key == Qnil) return ST_CONTINUE; if (value == Qnil) return ST_CONTINUE;
if (var->stop) return ST_STOP; if (var->stop) return ST_STOP;
var->stop = 1; var->stop = 1;
var->key = key; var->key = key;
@ -454,8 +482,8 @@ static int
delete_if_i(key, value) delete_if_i(key, value)
VALUE key, value; VALUE key, value;
{ {
if (key == Qnil) return ST_CONTINUE; if (value == Qnil) return ST_CONTINUE;
if (rb_yield(rb_assoc_new(key, value))) if (RTEST(rb_yield(rb_assoc_new(key, value))))
return ST_DELETE; return ST_DELETE;
return ST_CONTINUE; return ST_CONTINUE;
} }
@ -471,8 +499,8 @@ rb_hash_delete_if(hash)
} }
static int static int
clear_i(key, value) clear_i(key, value, dummy)
VALUE key, value; VALUE key, value, dummy;
{ {
return ST_DELETE; return ST_DELETE;
} }
@ -482,7 +510,7 @@ rb_hash_clear(hash)
VALUE hash; VALUE hash;
{ {
rb_hash_modify(hash); rb_hash_modify(hash);
st_foreach(RHASH(hash)->tbl, clear_i); st_foreach(RHASH(hash)->tbl, clear_i, 0);
return hash; return hash;
} }
@ -500,7 +528,7 @@ rb_hash_aset(hash, key, val)
st_insert(RHASH(hash)->tbl, key, val); st_insert(RHASH(hash)->tbl, key, val);
} }
else { else {
st_add_direct(RHASH(hash)->tbl, rb_str_dup_frozen(key), val); st_add_direct(RHASH(hash)->tbl, rb_str_new4(key), val);
} }
return val; return val;
} }
@ -544,7 +572,7 @@ static int
each_value_i(key, value) each_value_i(key, value)
VALUE key, value; VALUE key, value;
{ {
if (key == Qnil) return ST_CONTINUE; if (value == Qnil) return ST_CONTINUE;
rb_yield(value); rb_yield(value);
return ST_CONTINUE; return ST_CONTINUE;
} }
@ -561,7 +589,7 @@ static int
each_key_i(key, value) each_key_i(key, value)
VALUE key, value; VALUE key, value;
{ {
if (key == Qnil) return ST_CONTINUE; if (value == Qnil) return ST_CONTINUE;
rb_yield(key); rb_yield(key);
return ST_CONTINUE; return ST_CONTINUE;
} }
@ -578,7 +606,7 @@ static int
each_pair_i(key, value) each_pair_i(key, value)
VALUE key, value; VALUE key, value;
{ {
if (key == Qnil) return ST_CONTINUE; if (value == Qnil) return ST_CONTINUE;
rb_yield(rb_assoc_new(key, value)); rb_yield(rb_assoc_new(key, value));
return ST_CONTINUE; return ST_CONTINUE;
} }
@ -595,7 +623,7 @@ static int
to_a_i(key, value, ary) to_a_i(key, value, ary)
VALUE key, value, ary; VALUE key, value, ary;
{ {
if (key == Qnil) return ST_CONTINUE; if (value == Qnil) return ST_CONTINUE;
rb_ary_push(ary, rb_assoc_new(key, value)); rb_ary_push(ary, rb_assoc_new(key, value));
return ST_CONTINUE; return ST_CONTINUE;
} }
@ -625,7 +653,7 @@ inspect_i(key, value, str)
{ {
VALUE str2; VALUE str2;
if (key == Qnil) return ST_CONTINUE; if (value == Qnil) return ST_CONTINUE;
if (RSTRING(str)->len > 1) { if (RSTRING(str)->len > 1) {
rb_str_cat(str, ", ", 2); rb_str_cat(str, ", ", 2);
} }
@ -687,7 +715,7 @@ static int
keys_i(key, value, ary) keys_i(key, value, ary)
VALUE key, value, ary; VALUE key, value, ary;
{ {
if (key == Qnil) return ST_CONTINUE; if (value == Qnil) return ST_CONTINUE;
rb_ary_push(ary, key); rb_ary_push(ary, key);
return ST_CONTINUE; return ST_CONTINUE;
} }
@ -708,7 +736,7 @@ static int
values_i(key, value, ary) values_i(key, value, ary)
VALUE key, value, ary; VALUE key, value, ary;
{ {
if (key == Qnil) return ST_CONTINUE; if (value == Qnil) return ST_CONTINUE;
rb_ary_push(ary, value); rb_ary_push(ary, value);
return ST_CONTINUE; return ST_CONTINUE;
} }
@ -740,7 +768,7 @@ static int
rb_hash_search_value(key, value, data) rb_hash_search_value(key, value, data)
VALUE key, value, *data; VALUE key, value, *data;
{ {
if (key == Qnil) return ST_CONTINUE; if (value == Qnil) return ST_CONTINUE;
if (rb_equal(value, data[1])) { if (rb_equal(value, data[1])) {
data[0] = Qtrue; data[0] = Qtrue;
return ST_STOP; return ST_STOP;
@ -773,7 +801,7 @@ equal_i(key, val1, data)
{ {
VALUE val2; VALUE val2;
if (key == Qnil) return ST_CONTINUE; if (val1 == Qnil) return ST_CONTINUE;
if (!st_lookup(data->tbl, key, &val2)) { if (!st_lookup(data->tbl, key, &val2)) {
data->result = Qfalse; data->result = Qfalse;
return ST_STOP; return ST_STOP;
@ -807,7 +835,7 @@ rb_hash_invert_i(key, value, hash)
VALUE key, value; VALUE key, value;
VALUE hash; VALUE hash;
{ {
if (key == Qnil) return ST_CONTINUE; if (value == Qnil) return ST_CONTINUE;
rb_hash_aset(hash, value, key); rb_hash_aset(hash, value, key);
return ST_CONTINUE; return ST_CONTINUE;
} }
@ -827,7 +855,7 @@ rb_hash_update_i(key, value, hash)
VALUE key, value; VALUE key, value;
VALUE hash; VALUE hash;
{ {
if (key == Qnil) return ST_CONTINUE; if (value == Qnil) return ST_CONTINUE;
rb_hash_aset(hash, key, value); rb_hash_aset(hash, key, value);
return ST_CONTINUE; return ST_CONTINUE;
} }
@ -841,7 +869,6 @@ rb_hash_update(hash1, hash2)
return hash1; return hash1;
} }
#ifndef __MACOS__ /* no environment variables on MacOS. */
static int path_tainted = -1; static int path_tainted = -1;
#ifndef NT #ifndef NT
@ -853,24 +880,20 @@ static VALUE
env_delete(obj, name) env_delete(obj, name)
VALUE obj, name; VALUE obj, name;
{ {
int i, len; int len;
char *nam, *val = 0; char *nam, *val;
rb_secure(4); rb_secure(4);
nam = STR2CSTR(name); nam = str2cstr(name, &len);
if (strcmp(nam, "PATH") == 0) path_tainted = 0; if (strlen(nam) != len) {
len = strlen(nam); rb_raise(rb_eArgError, "bad environment variable name");
for(i=0; environ[i]; i++) {
if (strncmp(environ[i], nam, len) == 0 && environ[i][len] == '=') {
val = environ[i]+len+1;
break;
}
}
while (environ[i]) {
environ[i] = environ[i+1];
i++;
} }
val = getenv(nam);
if (val) { if (val) {
ruby_setenv(nam, 0);
if (strcmp(nam, "PATH") == 0 && !OBJ_TAINTED(name)) {
path_tainted = 0;
}
return rb_str_new2(val); return rb_str_new2(val);
} }
return Qnil; return Qnil;
@ -894,7 +917,7 @@ rb_f_getenv(obj, name)
nam = str2cstr(name, &len); nam = str2cstr(name, &len);
if (strlen(nam) != len) { if (strlen(nam) != len) {
rb_raise(rb_eArgError, "Bad environment variable name"); rb_raise(rb_eArgError, "bad environment variable name");
} }
env = getenv(nam); env = getenv(nam);
if (env) { if (env) {
@ -930,7 +953,7 @@ rb_path_check(path)
char *path; char *path;
{ {
char *p, *pend; char *p, *pend;
const char sep = RUBY_PATH_SEP[0]; const char sep = PATH_SEP_CHAR;
if (!path) return 1; if (!path) return 1;
@ -988,12 +1011,12 @@ char *nam;
return i; return i;
} }
static void void
my_setenv(name, value) ruby_setenv(name, value)
char *name; const char *name;
char *value; const char *value;
{ {
#ifdef WIN32 #if defined(WIN32) && !defined(__CYGWIN32__)
#ifdef USE_WIN32_RTL_ENV #ifdef USE_WIN32_RTL_ENV
register char *envstr; register char *envstr;
STRLEN namlen = strlen(name); STRLEN namlen = strlen(name);
@ -1049,9 +1072,16 @@ my_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 */
register int i=envix(name); /* where does it go? */ int i=envix(name); /* where does it go? */
if (environ == origenviron) { /* need we copy environment? */ if (environ == origenviron) { /* need we copy environment? */
int j; int j;
@ -1066,6 +1096,7 @@ my_setenv(name, value)
environ = tmpenv; /* tell exec where it is now */ environ = tmpenv; /* tell exec where it is now */
} }
if (!value) { if (!value) {
free(environ[i]);
while (environ[i]) { while (environ[i]) {
environ[i] = environ[i+1]; environ[i] = environ[i+1];
i++; i++;
@ -1095,6 +1126,13 @@ my_setenv(name, value)
#endif /* WIN32 */ #endif /* WIN32 */
} }
void
ruby_unsetenv(name)
const char *name;
{
ruby_setenv(name, 0);
}
static VALUE static VALUE
rb_f_setenv(obj, nm, val) rb_f_setenv(obj, nm, val)
VALUE obj, nm, val; VALUE obj, nm, val;
@ -1112,13 +1150,13 @@ rb_f_setenv(obj, nm, val)
} }
name = str2cstr(nm, &nlen); name = str2cstr(nm, &nlen);
value = STR2CSTR(val &vlen); value = str2cstr(val, &vlen);
if (strlen(name) != nlen) if (strlen(name) != nlen)
rb_raise(rb_eArgError, "Bad environment name"); rb_raise(rb_eArgError, "bad environment variable name");
if (strlen(value) != vlen) if (strlen(value) != vlen)
rb_raise(rb_eArgError, "Bad environment value"); rb_raise(rb_eArgError, "bad environment variable value");
my_setenv(name, value); ruby_setenv(name, value);
if (strcmp(name, "PATH") == 0) { if (strcmp(name, "PATH") == 0) {
if (OBJ_TAINTED(val)) { if (OBJ_TAINTED(val)) {
/* already tainted, no check */ /* already tainted, no check */
@ -1303,10 +1341,8 @@ env_has_value(dmy, value)
VALUE dmy, value; VALUE dmy, value;
{ {
char **env; char **env;
volatile VALUE ary;
if (TYPE(value) != T_STRING) return Qfalse; if (TYPE(value) != T_STRING) return Qfalse;
ary = rb_ary_new();
env = environ; env = environ;
while (*env) { while (*env) {
char *s = strchr(*env, '=')+1; char *s = strchr(*env, '=')+1;
@ -1319,6 +1355,26 @@ env_has_value(dmy, value)
return Qfalse; return Qfalse;
} }
static VALUE
env_index(dmy, value)
VALUE dmy, value;
{
char **env;
if (TYPE(value) != T_STRING) return Qnil;
env = environ;
while (*env) {
char *s = strchr(*env, '=')+1;
if (s) {
if (strncmp(s, RSTRING(value)->ptr, strlen(s)) == 0) {
return rb_tainted_str_new(*env, s-*env);
}
}
env++;
}
return Qnil;
}
static VALUE static VALUE
env_indexes(argc, argv) env_indexes(argc, argv)
int argc; int argc;
@ -1363,8 +1419,6 @@ env_to_hash(obj)
return hash; return hash;
} }
#endif /* ifndef __MACOS__ no environment variables on MacOS. */
void void
Init_Hash() Init_Hash()
{ {
@ -1396,6 +1450,7 @@ Init_Hash()
rb_define_method(rb_cHash,"store", rb_hash_aset, 2); rb_define_method(rb_cHash,"store", rb_hash_aset, 2);
rb_define_method(rb_cHash,"default", rb_hash_default, 0); rb_define_method(rb_cHash,"default", rb_hash_default, 0);
rb_define_method(rb_cHash,"default=", rb_hash_set_default, 1); rb_define_method(rb_cHash,"default=", rb_hash_set_default, 1);
rb_define_method(rb_cHash,"index", rb_hash_index, 1);
rb_define_method(rb_cHash,"indexes", rb_hash_indexes, -1); rb_define_method(rb_cHash,"indexes", rb_hash_indexes, -1);
rb_define_method(rb_cHash,"indices", rb_hash_indexes, -1); rb_define_method(rb_cHash,"indices", rb_hash_indexes, -1);
rb_define_method(rb_cHash,"length", rb_hash_length, 0); rb_define_method(rb_cHash,"length", rb_hash_length, 0);
@ -1414,12 +1469,14 @@ Init_Hash()
rb_define_method(rb_cHash,"shift", rb_hash_shift, 0); rb_define_method(rb_cHash,"shift", rb_hash_shift, 0);
rb_define_method(rb_cHash,"delete", rb_hash_delete, 1); rb_define_method(rb_cHash,"delete", rb_hash_delete, 1);
rb_define_method(rb_cHash,"delete_if", rb_hash_delete_if, 0); rb_define_method(rb_cHash,"delete_if", rb_hash_delete_if, 0);
rb_define_method(rb_cHash,"reject!", rb_hash_delete_if, 0);
rb_define_method(rb_cHash,"clear", rb_hash_clear, 0); rb_define_method(rb_cHash,"clear", rb_hash_clear, 0);
rb_define_method(rb_cHash,"invert", rb_hash_invert, 0); rb_define_method(rb_cHash,"invert", rb_hash_invert, 0);
rb_define_method(rb_cHash,"update", rb_hash_update, 1); rb_define_method(rb_cHash,"update", rb_hash_update, 1);
rb_define_method(rb_cHash,"replace", rb_hash_replace, 1); rb_define_method(rb_cHash,"replace", rb_hash_replace, 1);
rb_define_method(rb_cHash,"include?", rb_hash_has_key, 1); rb_define_method(rb_cHash,"include?", rb_hash_has_key, 1);
rb_define_method(rb_cHash,"member?", rb_hash_has_key, 1);
rb_define_method(rb_cHash,"has_key?", rb_hash_has_key, 1); rb_define_method(rb_cHash,"has_key?", rb_hash_has_key, 1);
rb_define_method(rb_cHash,"has_value?", rb_hash_has_value, 1); rb_define_method(rb_cHash,"has_value?", rb_hash_has_value, 1);
rb_define_method(rb_cHash,"key?", rb_hash_has_key, 1); rb_define_method(rb_cHash,"key?", rb_hash_has_key, 1);
@ -1438,9 +1495,11 @@ Init_Hash()
rb_define_singleton_method(envtbl,"each_value", env_each_value, 0); rb_define_singleton_method(envtbl,"each_value", env_each_value, 0);
rb_define_singleton_method(envtbl,"delete", env_delete_method, 1); rb_define_singleton_method(envtbl,"delete", env_delete_method, 1);
rb_define_singleton_method(envtbl,"delete_if", env_delete_if, 0); rb_define_singleton_method(envtbl,"delete_if", env_delete_if, 0);
rb_define_singleton_method(envtbl,"reject!", env_delete_if, 0);
rb_define_singleton_method(envtbl,"to_s", env_to_s, 0); rb_define_singleton_method(envtbl,"to_s", env_to_s, 0);
rb_define_singleton_method(envtbl,"rehash", env_none, 0); rb_define_singleton_method(envtbl,"rehash", env_none, 0);
rb_define_singleton_method(envtbl,"to_a", env_to_a, 0); rb_define_singleton_method(envtbl,"to_a", env_to_a, 0);
rb_define_singleton_method(envtbl,"index", env_index, 1);
rb_define_singleton_method(envtbl,"indexes", env_indexes, -1); rb_define_singleton_method(envtbl,"indexes", env_indexes, -1);
rb_define_singleton_method(envtbl,"indices", env_indexes, -1); rb_define_singleton_method(envtbl,"indices", env_indexes, -1);
rb_define_singleton_method(envtbl,"length", env_size, 0); rb_define_singleton_method(envtbl,"length", env_size, 0);
@ -1448,6 +1507,7 @@ Init_Hash()
rb_define_singleton_method(envtbl,"keys", env_keys, 0); rb_define_singleton_method(envtbl,"keys", env_keys, 0);
rb_define_singleton_method(envtbl,"values", env_values, 0); rb_define_singleton_method(envtbl,"values", env_values, 0);
rb_define_singleton_method(envtbl,"include?", env_has_key, 1); rb_define_singleton_method(envtbl,"include?", env_has_key, 1);
rb_define_singleton_method(envtbl,"member?", env_has_key, 1);
rb_define_singleton_method(envtbl,"has_key?", env_has_key, 1); rb_define_singleton_method(envtbl,"has_key?", env_has_key, 1);
rb_define_singleton_method(envtbl,"has_value?", env_has_value, 1); rb_define_singleton_method(envtbl,"has_value?", env_has_value, 1);
rb_define_singleton_method(envtbl,"key?", env_has_key, 1); rb_define_singleton_method(envtbl,"key?", env_has_key, 1);

View file

@ -6,7 +6,7 @@
$Date$ $Date$
created at: Tue Dec 28 16:01:58 JST 1993 created at: Tue Dec 28 16:01:58 JST 1993
Copyright (C) 1993-1998 Yukihiro Matsumoto Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/ ************************************************/
@ -31,6 +31,7 @@ void Init_marshal _((void));
void Init_Numeric _((void)); void Init_Numeric _((void));
void Init_Object _((void)); void Init_Object _((void));
void Init_pack _((void)); void Init_pack _((void));
void Init_Precision _((void));
void Init_sym _((void)); void Init_sym _((void));
void Init_process _((void)); void Init_process _((void));
void Init_Random _((void)); void Init_Random _((void));
@ -51,12 +52,11 @@ rb_call_inits()
Init_Object(); Init_Object();
Init_Comparable(); Init_Comparable();
Init_Enumerable(); Init_Enumerable();
Init_Precision();
Init_eval(); Init_eval();
Init_String(); Init_String();
Init_Exception(); Init_Exception();
#ifdef USE_THREAD
Init_Thread(); Init_Thread();
#endif
Init_Numeric(); Init_Numeric();
Init_Bignum(); Init_Bignum();
Init_Array(); Init_Array();

View file

@ -1,238 +0,0 @@
#! /bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
#
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
tranformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

View file

@ -7,51 +7,85 @@ destdir = ARGV[0] || ''
$:.unshift CONFIG["srcdir"]+"/lib" $:.unshift CONFIG["srcdir"]+"/lib"
require "ftools" require "ftools"
require "find"
binsuffix = CONFIG["binsuffix"] exeext = CONFIG["EXEEXT"]
if ENV["prefix"] if ENV["prefix"]
prefix = ENV["prefix"] prefix = ENV["prefix"]
else else
prefix = CONFIG["prefix"] prefix = CONFIG["prefix"]
end end
ruby_install_name = CONFIG["ruby_install_name"] ruby_install_name = CONFIG["ruby_install_name"]
bindir = CONFIG["bindir"] bindir = destdir+CONFIG["bindir"]
libdir = CONFIG["libdir"] libdir = destdir+CONFIG["libdir"]
pkglibdir = libdir + "/" + ruby_install_name #pkglibdir = libdir + "/" + ruby_install_name+"/"+CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
pkglibdir = libdir + "/ruby/"+CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
archdir = pkglibdir + "/" + CONFIG["arch"] archdir = pkglibdir + "/" + CONFIG["arch"]
mandir = CONFIG["mandir"] + "/man1" mandir = destdir+CONFIG["mandir"] + "/man1"
wdir = Dir.getwd wdir = Dir.getwd
File.makedirs "#{destdir}#{bindir}", true File.makedirs bindir, true
File.install "ruby#{binsuffix}", File.install ruby_install_name+exeext,
"#{destdir}#{bindir}/#{ruby_install_name}#{binsuffix}", 0755, true "#{bindir}/#{ruby_install_name}#{exeext}", 0755, true
for dll in Dir['*.dll'] for dll in Dir['*.dll']
File.install dll, "#{destdir}#{bindir}/#{dll}", 0755, true File.install dll, "#{bindir}/#{dll}", 0755, true
end end
File.makedirs "#{destdir}#{libdir}", true File.makedirs libdir, true
for lib in ["libruby.so", "libruby.so.LIB"] for lib in ["libruby.so.LIB", CONFIG["LIBRUBY_SO"]]
if File.exist? lib if File.exist? lib
File.install lib, "#{destdir}#{libdir}", 0644, true File.install lib, libdir, 0555, true
end end
end end
File.makedirs "#{destdir}#{pkglibdir}", true Dir.chdir libdir
File.makedirs "#{destdir}#{archdir}", true if File.exist? CONFIG["LIBRUBY_SO"]
Dir.chdir "ext" for link in CONFIG["LIBRUBY_ALIASES"].split
system "../miniruby#{binsuffix} extmk.rb install #{destdir}" if File.exist? link
Dir.chdir CONFIG["srcdir"] File.delete link
for f in Dir["lib/*.rb"] end
File.install f, "#{destdir}#{pkglibdir}", 0644, true File.symlink CONFIG["LIBRUBY_SO"], link
print "link #{CONFIG['LIBRUBY_SO']} -> #{link}\n"
end
end end
File.makedirs(archdir,true)
for f in Dir["*.h"]
File.install f, "#{destdir}#{archdir}", 0644, true
end
File.install "libruby.a", "#{destdir}#{archdir}", 0644, true
File.makedirs "#{destdir}#{mandir}", true
File.install "ruby.1", "#{destdir}#{mandir}", 0644, true
Dir.chdir wdir Dir.chdir wdir
File.install "config.h", "#{destdir}#{archdir}", 0644, true File.makedirs pkglibdir, true
File.install "rbconfig.rb", "#{destdir}#{archdir}", 0644, true File.makedirs archdir, true
File.makedirs pkglibdir+"/site_ruby", true
File.makedirs pkglibdir+"/site_ruby/"+CONFIG["arch"], true
if RUBY_PLATFORM =~ /cygwin/ and File.exist? "import.h"
File.install "import.h", archdir, 0644, true
end
if RUBY_PLATFORM =~ /-aix/
File.install "ruby.imp", archdir, 0644, true
end
Dir.chdir "ext"
system "../miniruby#{exeext} extmk.rb install #{destdir}"
Dir.chdir CONFIG["srcdir"]
Find.find("lib") do |f|
next unless /\.rb$/ =~ f
dir = pkglibdir+"/"+File.dirname(f[4..-1])
File.makedirs dir, true unless File.directory? dir
File.install f, dir, 0644, true
end
for f in Dir["*.h"]
File.install f, archdir, 0644, true
end
if RUBY_PLATFORM =~ /mswin32/
File.makedirs archdir + "/win32", true
File.install "win32/win32.h", archdir + "/win32", 0644, true
if File.exist? wdir+'/rubymw.lib'
File.install wdir+'/rubymw.lib', archdir, 0644, true
end
end
File.install wdir+'/'+CONFIG['LIBRUBY_A'], archdir, 0644, true
File.makedirs mandir, true
File.install "ruby.1", mandir, 0644, true
Dir.chdir wdir
File.install "config.h", archdir, 0644, true
File.install "rbconfig.rb", archdir, 0644, true
# vi:set sw=2: # vi:set sw=2:

110
intern.h
View file

@ -6,18 +6,18 @@
void rb_mem_clear _((register VALUE*, register size_t)); void rb_mem_clear _((register VALUE*, register size_t));
VALUE rb_assoc_new _((VALUE, VALUE)); VALUE rb_assoc_new _((VALUE, VALUE));
VALUE rb_ary_new _((void)); VALUE rb_ary_new _((void));
VALUE rb_ary_new2 _((size_t)); VALUE rb_ary_new2 _((long));
VALUE rb_ary_new3 __((size_t,...)); VALUE rb_ary_new3 __((long,...));
VALUE rb_ary_new4 _((size_t, VALUE *)); VALUE rb_ary_new4 _((long, VALUE *));
VALUE rb_ary_freeze _((VALUE)); VALUE rb_ary_freeze _((VALUE));
VALUE rb_ary_aref _((int, VALUE*, VALUE)); VALUE rb_ary_aref _((int, VALUE*, VALUE));
void rb_ary_store _((VALUE, size_t, VALUE)); void rb_ary_store _((VALUE, long, VALUE));
VALUE rb_ary_to_s _((VALUE)); VALUE rb_ary_to_s _((VALUE));
VALUE rb_ary_push _((VALUE, VALUE)); VALUE rb_ary_push _((VALUE, VALUE));
VALUE rb_ary_pop _((VALUE)); VALUE rb_ary_pop _((VALUE));
VALUE rb_ary_shift _((VALUE)); VALUE rb_ary_shift _((VALUE));
VALUE rb_ary_unshift _((VALUE, VALUE)); VALUE rb_ary_unshift _((VALUE, VALUE));
VALUE rb_ary_entry _((VALUE, size_t)); VALUE rb_ary_entry _((VALUE, long));
VALUE rb_ary_each _((VALUE)); VALUE rb_ary_each _((VALUE));
VALUE rb_ary_join _((VALUE, VALUE)); VALUE rb_ary_join _((VALUE, VALUE));
VALUE rb_ary_print_on _((VALUE, VALUE)); VALUE rb_ary_print_on _((VALUE, VALUE));
@ -41,7 +41,7 @@ VALUE rb_uint2big _((unsigned long));
VALUE rb_int2big _((long)); VALUE rb_int2big _((long));
VALUE rb_uint2inum _((unsigned long)); VALUE rb_uint2inum _((unsigned long));
VALUE rb_int2inum _((long)); VALUE rb_int2inum _((long));
VALUE rb_str2inum _((char*, int)); VALUE rb_str2inum _((const char*, int));
VALUE rb_big2str _((VALUE, int)); VALUE rb_big2str _((VALUE, int));
long rb_big2long _((VALUE)); long rb_big2long _((VALUE));
#define rb_big2int(x) rb_big2long(x) #define rb_big2int(x) rb_big2long(x)
@ -73,28 +73,28 @@ VALUE rb_class_protected_instance_methods _((int, VALUE*, VALUE));
VALUE rb_class_private_instance_methods _((int, VALUE*, VALUE)); VALUE rb_class_private_instance_methods _((int, VALUE*, VALUE));
VALUE rb_obj_singleton_methods _((VALUE)); VALUE rb_obj_singleton_methods _((VALUE));
void rb_define_method_id _((VALUE, ID, VALUE (*)(), int)); void rb_define_method_id _((VALUE, ID, VALUE (*)(), int));
void rb_undef_method _((VALUE, char*)); void rb_undef_method _((VALUE, const char*));
void rb_define_protected_method _((VALUE, char*, VALUE (*)(), int)); void rb_define_protected_method _((VALUE, const char*, VALUE (*)(), int));
void rb_define_private_method _((VALUE, char*, VALUE (*)(), int)); void rb_define_private_method _((VALUE, const char*, VALUE (*)(), int));
void rb_define_singleton_method _((VALUE,char*,VALUE(*)(),int)); void rb_define_singleton_method _((VALUE,const char*,VALUE(*)(),int));
void rb_define_private_method _((VALUE,char*,VALUE(*)(),int)); void rb_define_private_method _((VALUE,const char*,VALUE(*)(),int));
VALUE rb_singleton_class _((VALUE)); VALUE rb_singleton_class _((VALUE));
/* enum.c */ /* enum.c */
VALUE rb_enum_length _((VALUE)); VALUE rb_enum_length _((VALUE));
/* error.c */ /* error.c */
extern int ruby_nerrs; extern int ruby_nerrs;
VALUE rb_exc_new _((VALUE, char*, int)); VALUE rb_exc_new _((VALUE, const char*, long));
VALUE rb_exc_new2 _((VALUE, char*)); VALUE rb_exc_new2 _((VALUE, const char*));
VALUE rb_exc_new3 _((VALUE, VALUE)); VALUE rb_exc_new3 _((VALUE, VALUE));
void rb_loaderror __((char*, ...)) NORETURN; void rb_loaderror __((const char*, ...)) NORETURN;
void rb_compile_error __((char*, ...)); void rb_compile_error __((const char*, ...));
void rb_compile_error_append __((char*, ...)); void rb_compile_error_append __((const char*, ...));
/* eval.c */ /* eval.c */
void rb_exc_raise _((VALUE)) NORETURN; void rb_exc_raise _((VALUE)) NORETURN;
void rb_exc_fatal _((VALUE)) NORETURN; void rb_exc_fatal _((VALUE)) NORETURN;
void rb_remove_method _((VALUE, char*)); void rb_remove_method _((VALUE, const char*));
void rb_disable_super _((VALUE, char*)); void rb_disable_super _((VALUE, const char*));
void rb_enable_super _((VALUE, char*)); void rb_enable_super _((VALUE, const char*));
void rb_clear_cache _((void)); void rb_clear_cache _((void));
void rb_alias _((VALUE, ID, ID)); void rb_alias _((VALUE, ID, ID));
void rb_attr _((VALUE,ID,int,int,int)); void rb_attr _((VALUE,ID,int,int,int));
@ -104,37 +104,41 @@ VALUE rb_dvar_ref _((ID));
void rb_dvar_asgn _((ID, VALUE)); void rb_dvar_asgn _((ID, VALUE));
void rb_dvar_push _((ID, VALUE)); void rb_dvar_push _((ID, VALUE));
VALUE rb_eval_cmd _((VALUE, VALUE)); VALUE rb_eval_cmd _((VALUE, VALUE));
VALUE rb_trap_eval _((VALUE, int));
int rb_respond_to _((VALUE, ID)); int rb_respond_to _((VALUE, ID));
void rb_interrupt _((void)); void rb_interrupt _((void));
VALUE rb_apply _((VALUE, ID, VALUE)); VALUE rb_apply _((VALUE, ID, VALUE));
VALUE rb_funcall2 _((VALUE, ID, int, VALUE*));
void rb_backtrace _((void)); void rb_backtrace _((void));
ID rb_frame_last_func _((void)); ID rb_frame_last_func _((void));
VALUE rb_obj_instance_eval _((int, VALUE*, VALUE)); VALUE rb_obj_instance_eval _((int, VALUE*, VALUE));
void rb_load _((VALUE, int)); void rb_load _((VALUE, int));
void rb_load_protect _((VALUE, int, int*)); void rb_load_protect _((VALUE, int, int*));
void rb_jump_tag _((int)) NORETURN; void rb_jump_tag _((int)) NORETURN;
void rb_provide _((char*)); void rb_provide _((const char*));
VALUE rb_f_require _((VALUE, VALUE)); VALUE rb_f_require _((VALUE, VALUE));
void rb_obj_call_init _((VALUE)); void rb_obj_call_init _((VALUE, int, VALUE*));
VALUE rb_class_new_instance _((int, VALUE*, VALUE)); VALUE rb_class_new_instance _((int, VALUE*, VALUE));
VALUE rb_f_lambda _((void)); VALUE rb_f_lambda _((void));
VALUE rb_protect _((VALUE (*)(), VALUE, int*)); VALUE rb_protect _((VALUE (*)(), VALUE, int*));
void rb_set_end_proc _((void (*)(), VALUE)); void rb_set_end_proc _((void (*)(), VALUE));
void rb_exec_end_proc _((void));
void rb_gc_mark_threads _((void)); void rb_gc_mark_threads _((void));
void rb_thread_start_timer _((void)); void rb_thread_start_timer _((void));
void rb_thread_stop_timer _((void)); void rb_thread_stop_timer _((void));
void rb_thread_schedule _((void)); void rb_thread_schedule _((void));
void rb_thread_wait_fd _((int)); void rb_thread_wait_fd _((int));
void rb_thread_fd_writable _((int)); int rb_thread_fd_writable _((int));
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));
void rb_thread_trap_eval _((VALUE, int)); void rb_thread_trap_eval _((VALUE, int));
void rb_thread_signal_raise _((char*));
int rb_thread_select(); int rb_thread_select();
void rb_thread_wait_for(); void rb_thread_wait_for();
VALUE rb_thread_current _((void)); VALUE rb_thread_current _((void));
@ -142,9 +146,9 @@ VALUE rb_thread_main _((void));
VALUE rb_thread_local_aref _((VALUE, ID)); VALUE rb_thread_local_aref _((VALUE, ID));
VALUE rb_thread_local_aset _((VALUE, ID, VALUE)); VALUE rb_thread_local_aset _((VALUE, ID, VALUE));
/* file.c */ /* file.c */
VALUE rb_file_open _((char*, char*)); int eaccess _((const char*, int));
int eaccess _((char*, int));
VALUE rb_file_s_expand_path _((int, VALUE *)); VALUE rb_file_s_expand_path _((int, VALUE *));
void rb_file_const _((const char*, VALUE));
/* gc.c */ /* gc.c */
void rb_global_variable _((VALUE*)); void rb_global_variable _((VALUE*));
void rb_gc_mark_locations _((VALUE*, VALUE*)); void rb_gc_mark_locations _((VALUE*, VALUE*));
@ -176,8 +180,7 @@ VALUE rb_io_ungetc _((VALUE, VALUE));
VALUE rb_io_close _((VALUE)); VALUE rb_io_close _((VALUE));
VALUE rb_io_eof _((VALUE)); VALUE rb_io_eof _((VALUE));
VALUE rb_io_binmode _((VALUE)); VALUE rb_io_binmode _((VALUE));
int rb_io_mode_flags _((char*)); VALUE rb_file_open _((const char*, const char*));
VALUE rb_io_reopen _((VALUE, VALUE));
VALUE rb_gets _((void)); VALUE rb_gets _((void));
void rb_str_setter _((VALUE, ID, VALUE*)); void rb_str_setter _((VALUE, ID, VALUE*));
/* numeric.c */ /* numeric.c */
@ -199,7 +202,7 @@ VALUE rb_obj_taint _((VALUE));
VALUE rb_obj_tainted _((VALUE)); VALUE rb_obj_tainted _((VALUE));
VALUE rb_obj_untaint _((VALUE)); VALUE rb_obj_untaint _((VALUE));
VALUE rb_obj_id _((VALUE)); VALUE rb_obj_id _((VALUE));
VALUE rb_convert_type _((VALUE,int,char*,char*)); VALUE rb_convert_type _((VALUE,int,const char*,const char*));
VALUE rb_Integer _((VALUE)); VALUE rb_Integer _((VALUE));
VALUE rb_Float _((VALUE)); VALUE rb_Float _((VALUE));
VALUE rb_String _((VALUE)); VALUE rb_String _((VALUE));
@ -218,11 +221,11 @@ void rb_backref_set _((VALUE));
VALUE rb_lastline_get _((void)); VALUE rb_lastline_get _((void));
void rb_lastline_set _((VALUE)); void rb_lastline_set _((VALUE));
/* process.c */ /* process.c */
int rb_proc_exec _((char*)); int rb_proc_exec _((const char*));
void rb_syswait _((int)); void rb_syswait _((int));
/* range.c */ /* range.c */
VALUE rb_range_new _((VALUE, VALUE)); VALUE rb_range_new _((VALUE, VALUE, int));
VALUE rb_range_beg_end _((VALUE, int*, int*)); VALUE rb_range_beg_len _((VALUE, long*, long*, long, int));
/* re.c */ /* re.c */
VALUE rb_reg_nth_defined _((int, VALUE)); VALUE rb_reg_nth_defined _((int, VALUE));
VALUE rb_reg_nth_match _((int, VALUE)); VALUE rb_reg_nth_match _((int, VALUE));
@ -230,20 +233,23 @@ VALUE rb_reg_last_match _((VALUE));
VALUE rb_reg_match_pre _((VALUE)); VALUE rb_reg_match_pre _((VALUE));
VALUE rb_reg_match_post _((VALUE)); VALUE rb_reg_match_post _((VALUE));
VALUE rb_reg_match_last _((VALUE)); VALUE rb_reg_match_last _((VALUE));
VALUE rb_reg_new _((char*, size_t, int)); VALUE rb_reg_new _((const char*, long, int));
VALUE rb_reg_match _((VALUE, VALUE)); VALUE rb_reg_match _((VALUE, VALUE));
VALUE rb_reg_match2 _((VALUE)); VALUE rb_reg_match2 _((VALUE));
int rb_reg_options _((VALUE)); int rb_reg_options _((VALUE));
char*rb_get_kcode _((void)); const char* rb_get_kcode _((void));
void rb_set_kcode _((char*)); void rb_set_kcode _((const char*));
int rb_ignorecase_p _((void)); int rb_ignorecase_p _((void));
void rb_match_busy _((VALUE, int));
/* ruby.c */ /* ruby.c */
EXTERN VALUE rb_argv;
EXTERN VALUE rb_argv0;
void rb_load_file _((char*)); void rb_load_file _((char*));
void ruby_script _((char*)); void ruby_script _((char*));
void ruby_prog_init _((void)); void ruby_prog_init _((void));
void ruby_set_argv _((int, char**)); void ruby_set_argv _((int, char**));
void ruby_process_options _((int, char**)); void ruby_process_options _((int, char**));
void ruby_require_modules _((void)); void ruby_require_libraries _((void));
void ruby_load_script _((void)); void ruby_load_script _((void));
/* signal.c */ /* signal.c */
VALUE rb_f_kill _((int, VALUE*)); VALUE rb_f_kill _((int, VALUE*));
@ -257,52 +263,52 @@ void rb_trap_exec _((void));
/* sprintf.c */ /* sprintf.c */
VALUE rb_f_sprintf _((int, VALUE*)); VALUE rb_f_sprintf _((int, VALUE*));
/* string.c */ /* string.c */
VALUE rb_str_new _((char*, size_t)); VALUE rb_str_new _((const char*, long));
VALUE rb_str_new2 _((char*)); VALUE rb_str_new2 _((const char*));
VALUE rb_str_new3 _((VALUE)); VALUE rb_str_new3 _((VALUE));
VALUE rb_str_new4 _((VALUE)); VALUE rb_str_new4 _((VALUE));
VALUE rb_tainted_str_new _((char*, size_t)); VALUE rb_tainted_str_new _((const char*, long));
VALUE rb_tainted_str_new2 _((char*)); VALUE rb_tainted_str_new2 _((const char*));
VALUE rb_obj_as_string _((VALUE)); VALUE rb_obj_as_string _((VALUE));
VALUE rb_str_to_str _((VALUE)); VALUE rb_str_to_str _((VALUE));
VALUE rb_str_dup _((VALUE)); VALUE rb_str_dup _((VALUE));
VALUE rb_str_plus _((VALUE, VALUE)); VALUE rb_str_plus _((VALUE, VALUE));
VALUE rb_str_times _((VALUE, VALUE)); VALUE rb_str_times _((VALUE, VALUE));
VALUE rb_str_substr _((VALUE, size_t, size_t)); VALUE rb_str_substr _((VALUE, long, long));
void rb_str_modify _((VALUE)); void rb_str_modify _((VALUE));
VALUE rb_str_freeze _((VALUE)); VALUE rb_str_freeze _((VALUE));
VALUE rb_str_dup_frozen _((VALUE)); VALUE rb_str_resize _((VALUE, long));
VALUE rb_str_resize _((VALUE, size_t)); VALUE rb_str_cat _((VALUE, const char*, long));
VALUE rb_str_cat _((VALUE, char*, size_t));
VALUE rb_str_concat _((VALUE, VALUE)); VALUE rb_str_concat _((VALUE, VALUE));
int rb_str_hash _((VALUE)); int rb_str_hash _((VALUE));
int rb_str_cmp _((VALUE, VALUE)); int rb_str_cmp _((VALUE, VALUE));
VALUE rb_str_upto _((VALUE, VALUE)); VALUE rb_str_upto _((VALUE, VALUE, int));
VALUE rb_str_inspect _((VALUE)); VALUE rb_str_inspect _((VALUE));
VALUE rb_str_split _((VALUE, char*)); VALUE rb_str_split _((VALUE, const char*));
/* struct.c */ /* struct.c */
VALUE rb_struct_new __((VALUE, ...)); VALUE rb_struct_new __((VALUE, ...));
VALUE rb_struct_define __((char*, ...)); VALUE rb_struct_define __((const char*, ...));
VALUE rb_struct_alloc _((VALUE, VALUE)); VALUE rb_struct_alloc _((VALUE, VALUE));
VALUE rb_struct_aref _((VALUE, VALUE)); VALUE rb_struct_aref _((VALUE, VALUE));
VALUE rb_struct_aset _((VALUE, VALUE, VALUE)); VALUE rb_struct_aset _((VALUE, VALUE, VALUE));
VALUE rb_struct_getmember _((VALUE, ID)); VALUE rb_struct_getmember _((VALUE, ID));
/* time.c */ /* time.c */
VALUE rb_time_new _((int, int)); VALUE rb_time_new();
/* variable.c */ /* variable.c */
VALUE rb_mod_name _((VALUE)); VALUE rb_mod_name _((VALUE));
VALUE rb_class_path _((VALUE)); VALUE rb_class_path _((VALUE));
void rb_set_class_path _((VALUE, VALUE, char*)); void rb_set_class_path _((VALUE, VALUE, const char*));
VALUE rb_path2class _((char*)); VALUE rb_path2class _((const char*));
void rb_name_class _((VALUE, ID)); void rb_name_class _((VALUE, ID));
void rb_autoload _((char*, char*)); void rb_autoload _((const char*, const char*));
VALUE rb_f_autoload _((VALUE, VALUE, VALUE)); VALUE rb_f_autoload _((VALUE, VALUE, VALUE));
void rb_gc_mark_global_tbl _((void)); void rb_gc_mark_global_tbl _((void));
VALUE rb_f_trace_var _((int, VALUE*)); VALUE rb_f_trace_var _((int, VALUE*));
VALUE rb_f_untrace_var _((int, VALUE*)); VALUE rb_f_untrace_var _((int, VALUE*));
VALUE rb_gvar_set2 _((char*, VALUE)); VALUE rb_gvar_set2 _((const char*, VALUE));
VALUE rb_f_global_variables _((void)); VALUE rb_f_global_variables _((void));
void rb_alias_variable _((ID, ID)); void rb_alias_variable _((ID, ID));
void rb_clone_generic_ivar _((VALUE,VALUE));
void rb_mark_generic_ivar _((VALUE)); void rb_mark_generic_ivar _((VALUE));
void rb_mark_generic_ivar_tbl _((void)); void rb_mark_generic_ivar_tbl _((void));
void rb_free_generic_ivar _((VALUE)); void rb_free_generic_ivar _((VALUE));

1087
io.c

File diff suppressed because it is too large Load diff

149
lex.c
View file

@ -1,5 +1,5 @@
/* C code produced by gperf version 2.5 (GNU C++ version) */ /* C code produced by gperf version 2.7.1 (19981006 egcs) */
/* Command-line: gperf -p -j1 -i 1 -g -o -t -N rb_reserved_word -k1,3,$ keywords */ /* Command-line: gperf -p -j1 -i 1 -g -o -t -N rb_reserved_word -k1,3,$ ./keywords */
struct kwtable {char *name; int id[2]; enum lex_state state;}; struct kwtable {char *name; int id[2]; enum lex_state state;};
#define TOTAL_KEYWORDS 40 #define TOTAL_KEYWORDS 40
@ -10,28 +10,41 @@ struct kwtable {char *name; int id[2]; enum lex_state state;};
/* maximum key range = 50, duplicates = 0 */ /* maximum key range = 50, duplicates = 0 */
#ifdef __GNUC__ #ifdef __GNUC__
inline __inline
#endif #endif
static unsigned int static unsigned int
hash (str, len) hash (str, len)
register char *str; register const char *str;
register int unsigned len; register unsigned int len;
{ {
static unsigned char asso_values[] = static unsigned char asso_values[] =
{ {
56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 11, 56, 56, 36, 56, 1, 37, 56, 56, 56, 11, 56, 56, 36, 56, 1, 37,
31, 1, 56, 56, 56, 56, 29, 56, 1, 56, 31, 1, 56, 56, 56, 56, 29, 56, 1, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 1, 56, 32, 1, 2, 56, 56, 56, 56, 56, 1, 56, 32, 1, 2,
1, 1, 4, 23, 56, 17, 56, 20, 9, 2, 1, 1, 4, 23, 56, 17, 56, 20, 9, 2,
9, 26, 14, 56, 5, 1, 1, 16, 56, 21, 9, 26, 14, 56, 5, 1, 1, 16, 56, 21,
20, 9, 56, 56, 56, 56, 56, 56, 20, 9, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
56, 56, 56, 56, 56, 56
}; };
register int hval = len; register int hval = len;
@ -39,68 +52,68 @@ hash (str, len)
{ {
default: default:
case 3: case 3:
hval += asso_values[str[2]]; hval += asso_values[(unsigned char)str[2]];
case 2: case 2:
case 1: case 1:
hval += asso_values[str[0]]; hval += asso_values[(unsigned char)str[0]];
break; break;
} }
return hval + asso_values[str[len - 1]]; return hval + asso_values[(unsigned char)str[len - 1]];
} }
#ifdef __GNUC__ #ifdef __GNUC__
inline __inline
#endif #endif
struct kwtable * struct kwtable *
rb_reserved_word (str, len) rb_reserved_word (str, len)
register char *str; register const char *str;
register unsigned int len; register unsigned int len;
{ {
static struct kwtable wordlist[] = static struct kwtable wordlist[] =
{ {
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {""}, {""}, {""}, {""}, {""}, {""},
{"end", kEND, kEND, EXPR_END}, {"end", kEND, kEND, EXPR_END},
{"else", kELSE, kELSE, EXPR_BEG}, {"else", kELSE, kELSE, EXPR_BEG},
{"case", kCASE, kCASE, EXPR_BEG}, {"case", kCASE, kCASE, EXPR_BEG},
{"ensure", kENSURE, kENSURE, EXPR_BEG}, {"ensure", kENSURE, kENSURE, EXPR_BEG},
{"module", kMODULE, kMODULE, EXPR_BEG}, {"module", kMODULE, kMODULE, EXPR_BEG},
{"elsif", kELSIF, kELSIF, EXPR_BEG}, {"elsif", kELSIF, kELSIF, EXPR_BEG},
{"def", kDEF, kDEF, EXPR_FNAME}, {"def", kDEF, kDEF, EXPR_FNAME},
{"rescue", kRESCUE, kRESCUE, EXPR_MID}, {"rescue", kRESCUE, kRESCUE, EXPR_MID},
{"not", kNOT, kNOT, EXPR_BEG}, {"not", kNOT, kNOT, EXPR_BEG},
{"then", kTHEN, kTHEN, EXPR_BEG}, {"then", kTHEN, kTHEN, EXPR_BEG},
{"yield", kYIELD, kYIELD, EXPR_END}, {"yield", kYIELD, kYIELD, EXPR_END},
{"for", kFOR, kFOR, EXPR_BEG}, {"for", kFOR, kFOR, EXPR_BEG},
{"self", kSELF, kSELF, EXPR_END}, {"self", kSELF, kSELF, EXPR_END},
{"false", kFALSE, kFALSE, EXPR_END}, {"false", kFALSE, kFALSE, EXPR_END},
{"retry", kRETRY, kRETRY, EXPR_END}, {"retry", kRETRY, kRETRY, EXPR_END},
{"return", kRETURN, kRETURN, EXPR_MID}, {"return", kRETURN, kRETURN, EXPR_MID},
{"true", kTRUE, kTRUE, EXPR_END}, {"true", kTRUE, kTRUE, EXPR_END},
{"if", kIF, kIF_MOD, EXPR_BEG}, {"if", kIF, kIF_MOD, EXPR_BEG},
{"defined?", kDEFINED, kDEFINED, EXPR_END}, {"defined?", kDEFINED, kDEFINED, EXPR_END},
{"super", kSUPER, kSUPER, EXPR_END}, {"super", kSUPER, kSUPER, EXPR_END},
{"undef", kUNDEF, kUNDEF, EXPR_FNAME}, {"undef", kUNDEF, kUNDEF, EXPR_FNAME},
{"break", kBREAK, kBREAK, EXPR_END}, {"break", kBREAK, kBREAK, EXPR_END},
{"in", kIN, kIN, EXPR_BEG}, {"in", kIN, kIN, EXPR_BEG},
{"do", kDO, kDO, EXPR_BEG}, {"do", kDO, kDO, EXPR_BEG},
{"nil", kNIL, kNIL, EXPR_END}, {"nil", kNIL, kNIL, EXPR_END},
{"until", kUNTIL, kUNTIL_MOD, EXPR_BEG}, {"until", kUNTIL, kUNTIL_MOD, EXPR_BEG},
{"unless", kUNLESS, kUNLESS_MOD, EXPR_BEG}, {"unless", kUNLESS, kUNLESS_MOD, EXPR_BEG},
{"or", kOR, kOR, EXPR_BEG}, {"or", kOR, kOR, EXPR_BEG},
{"next", kNEXT, kNEXT, EXPR_END}, {"next", kNEXT, kNEXT, EXPR_END},
{"when", kWHEN, kWHEN, EXPR_BEG}, {"when", kWHEN, kWHEN, EXPR_BEG},
{"redo", kREDO, kREDO, EXPR_END}, {"redo", kREDO, kREDO, EXPR_END},
{"and", kAND, kAND, EXPR_BEG}, {"and", kAND, kAND, EXPR_BEG},
{"begin", kBEGIN, kBEGIN, EXPR_BEG}, {"begin", kBEGIN, kBEGIN, EXPR_BEG},
{"__LINE__", k__LINE__, k__LINE__, EXPR_END}, {"__LINE__", k__LINE__, k__LINE__, EXPR_END},
{"class", kCLASS, kCLASS, EXPR_CLASS}, {"class", kCLASS, kCLASS, EXPR_CLASS},
{"__FILE__", k__FILE__, k__FILE__, EXPR_END}, {"__FILE__", k__FILE__, k__FILE__, EXPR_END},
{"END", klEND, klEND, EXPR_END}, {"END", klEND, klEND, EXPR_END},
{"BEGIN", klBEGIN, klBEGIN, EXPR_END}, {"BEGIN", klBEGIN, klBEGIN, EXPR_END},
{"while", kWHILE, kWHILE_MOD, EXPR_BEG}, {"while", kWHILE, kWHILE_MOD, EXPR_BEG},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{"",}, {""},
{"alias", kALIAS, kALIAS, EXPR_FNAME}, {"alias", kALIAS, kALIAS, EXPR_FNAME}
}; };
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
@ -109,9 +122,9 @@ rb_reserved_word (str, len)
if (key <= MAX_HASH_VALUE && key >= 0) if (key <= MAX_HASH_VALUE && key >= 0)
{ {
register char *s = wordlist[key].name; register const char *s = wordlist[key].name;
if (*s == *str && !strcmp (str + 1, s + 1)) if (*str == *s && !strcmp (str + 1, s + 1))
return &wordlist[key]; return &wordlist[key];
} }
} }

31
lib/Env.rb Normal file
View file

@ -0,0 +1,31 @@
# Env.rb -- imports environment variables as global variables
#
# Usage:
#
# require 'Env'
# p $USER
# $USER = "matz"
# p ENV["USER"]
for k,v in ENV
next unless /^[a-zA-Z][_a-zA-Z0-9]*/ =~ k
eval <<EOS
$#{k} = %q!#{v}!
trace_var "$#{k}", proc{|v|
ENV[%q!#{k}!] = v;
$#{k} = %q!#{v}!
if v == nil
untrace_var "$#{k}"
end
}
EOS
end
if __FILE__ == $0
p $TERM
$TERM = nil
p $TERM
p ENV["TERM"]
$TERM = "foo"
p ENV["TERM"]
end

48
lib/README Normal file
View file

@ -0,0 +1,48 @@
English.rb access global variables by english names
Env.rb access environment variables as globals
README this file
base64.rb encode/decode base64 (obsolete)
cgi-lib.rb decode CGI data
complex.rb complex number suppor
date.rb date object (compatible)
date2.rb yet another (better) date object
debug.rb ruby debugger
delegate.rb delegate messages to other object
e2mmap.rb exception utilities
eregex.rb extended regular expression (just a proof of concept)
final.rb add finalizer to the object (simple)
finalize.rb add finalizer to the object
find.rb traverse directory tree
ftools.rb file tools
ftplib.rb ftp access library
getoptlong.rb GNU getoptlong compatible
getopts.rb parse command line options
importenv.rb access environment variables as globals
jcode.rb japanese text handling (replace String methods)
mailread.rb read mail headers
mathn.rb extended math operation
matrix.rb matrix calculation library
mkmf.rb Makefile maker
monitor.rb exclusive region monitor for thread
mutex_m.rb mutex mixin
observer.rb observer desing pattern library (provides Observable)
open3.rb open subprocess connection stdin/stdout/stderr
ostruct.rb python style object
parsearg.rb argument parser using getopts
parsedate.rb parse date string
ping.rb check whether host is up, using TCP echo.
profile.rb ruby profiler
pstore.rb persistent object strage using marshal
rational.rb rational number support
readbytes.rb define IO#readbytes
shell.rb shell like operation under Ruby (imcomplete)
shellwords.rb split into words like shell
singleton.rb singleton design pattern library
sync.rb 2 phase lock
telnet.rb telnet library
tempfile.rb temporary file that automatically removed
thread.rb thread support
thwait.rb thread syncronization class
timeout.rb provids timeout
tracer.rb execution tracer
weakref.rb weak reference class

View file

@ -1,63 +1,163 @@
# =begin
# Get CGI String
#
# EXAMPLE:
# require "cgi-lib.rb"
# foo = CGI.new
# foo['field'] <== value of 'field'
# foo.keys <== array of fields
# and foo has Hash class methods
# if running on Windows(IIS or PWS) then change cwd. = simple CGI support library
if ENV['SERVER_SOFTWARE'] =~ /^Microsoft-/ then
Dir.chdir ENV['PATH_TRANSLATED'].sub(/[^\\]+$/, '') = example
end
== get form values
require "cgi-lib.rb"
query = CGI.new
query['field'] # <== value of 'field'
query.keys # <== array of fields
and query has Hash class methods
== get cookie values
require "cgi-lib.rb"
query = CGI.new
query.cookie['name'] # <== cookie value of 'name'
query.cookie.keys # <== all cookie names
and query.cookie has Hash class methods
== print HTTP header and HTML string to $>
require "cgi-lib.rb"
CGI::print{
CGI::tag("HTML"){
CGI::tag("HEAD"){ CGI::tag("TITLE"){"TITLE"} } +
CGI::tag("BODY"){
CGI::tag("FORM", {"ACTION"=>"test.rb", "METHOD"=>"POST"}){
CGI::tag("INPUT", {"TYPE"=>"submit", "VALUE"=>"submit"})
} +
CGI::tag("HR")
}
}
}
== make raw cookie string
require "cgi-lib.rb"
cookie1 = CGI::cookie({'name' => 'name',
'value' => 'value',
'path' => 'path', # optional
'domain' => 'domain', # optional
'expires' => Time.now, # optional
'secure' => true # optional
})
CGI::print("Content-Type: text/html", cookie1, cookie2){ "string" }
== print HTTP header and string to $>
require "cgi-lib.rb"
CGI::print{ "string" }
# == CGI::print("Content-Type: text/html"){ "string" }
CGI::print("Content-Type: text/html", cookie1, cookie2){ "string" }
=== NPH (no-parse-header) mode
require "cgi-lib.rb"
CGI::print("nph"){ "string" }
# == CGI::print("nph", "Content-Type: text/html"){ "string" }
CGI::print("nph", "Content-Type: text/html", cookie1, cookie2){ "string" }
== make HTML tag string
require "cgi-lib.rb"
CGI::tag("element", {"attribute_name"=>"attribute_value"}){"content"}
== make HTTP header string
require "cgi-lib.rb"
CGI::header # == CGI::header("Content-Type: text/html")
CGI::header("Content-Type: text/html", cookie1, cookie2)
=== NPH (no-parse-header) mode
CGI::header("nph") # == CGI::header("nph", "Content-Type: text/html")
CGI::header("nph", "Content-Type: text/html", cookie1, cookie2)
== escape url encode
require "cgi-lib.rb"
url_encoded_string = CGI::escape("string")
== unescape url encoded
require "cgi-lib.rb"
string = CGI::unescape("url encoded string")
== escape HTML &"<>
require "cgi-lib.rb"
CGI::escapeHTML("string")
=end
require "delegate" require "delegate"
class CGI < SimpleDelegator class CGI < SimpleDelegator
attr("inputs") CR = "\015"
LF = "\012"
EOL = CR + LF
# original is CGI.pm
def read_from_cmdline
require "shellwords.rb"
words = Shellwords.shellwords(if not ARGV.empty? then
ARGV.join(' ')
else
STDERR.print "(offline mode: enter name=value pairs on standard input)\n" if STDIN.tty?
readlines.join(' ').gsub(/\n/, '')
end.gsub(/\\=/, '%3D').gsub(/\\&/, '%26'))
if words.find{|x| x =~ /=/} then words.join('&') else words.join('+') end
end
# escape url encode # escape url encode
def escape(str) def escape(str)
str.gsub!(/[^a-zA-Z0-9_\-.]/n){ sprintf("%%%02X", $&.unpack("C")[0]) } str.gsub(/[^a-zA-Z0-9_\-.]/n){ sprintf("%%%02X", $&.unpack("C")[0]) }
str
end end
# unescape url encoded # unescape url encoded
def unescape(str) def unescape(str)
str.gsub! /\+/, ' ' str.gsub(/\+/, ' ').gsub(/%([0-9a-fA-F]{2})/){ [$1.hex].pack("c") }
str.gsub!(/%([0-9a-fA-F]{2})/){ [$1.hex].pack("c") } end
str
# escape HTML
def escapeHTML(str)
str.gsub(/&/, "&amp;").gsub(/\"/, "&quot;").gsub(/>/, "&gt;").gsub(/</, "&lt;")
end
module_function :escape, :unescape, :escapeHTML
# offline mode. read name=value pairs on standard input.
def read_from_cmdline
require "shellwords.rb"
words = Shellwords.shellwords(
if not ARGV.empty?
ARGV.join(' ')
else
STDERR.print "(offline mode: enter name=value pairs on standard input)\n" if STDIN.tty?
readlines.join(' ').gsub(/\n/, '')
end.gsub(/\\=/, '%3D').gsub(/\\&/, '%26'))
if words.find{|x| x =~ /=/} then words.join('&') else words.join('+') end
end end
module_function :escape, :unescape
def initialize(input = $stdin) def initialize(input = $stdin)
@inputs = {} @inputs = {}
@cookie = {}
case ENV['REQUEST_METHOD'] case ENV['REQUEST_METHOD']
when "GET" when "GET"
# exception messages should be printed to stdout.
STDERR.reopen(STDOUT)
ENV['QUERY_STRING'] or "" ENV['QUERY_STRING'] or ""
when "POST" when "POST"
# exception messages should be printed to stdout. input.read(Integer(ENV['CONTENT_LENGTH'])) or ""
STDERR.reopen(STDOUT)
input.read Integer(ENV['CONTENT_LENGTH'])
else else
read_from_cmdline read_from_cmdline
end.split(/&/).each do |x| end.split(/&/).each do |x|
@ -70,27 +170,92 @@ class CGI < SimpleDelegator
end end
super(@inputs) super(@inputs)
if ENV.has_key?('HTTP_COOKIE') or ENV.has_key?('COOKIE')
(ENV['HTTP_COOKIE'] or ENV['COOKIE']).split("; ").each do |x|
key, val = x.split(/=/,2)
key = unescape(key)
val = val.split(/&/).collect{|x|unescape(x)}.join("\0")
if @cookie.include?(key)
@cookie[key] += "\0" + val
else
@cookie[key] = val
end
end
end
end end
def CGI.message(msg, title = "") attr("inputs")
print "Content-type: text/html\n\n" attr("cookie")
print "<html><head><title>"
print title # make HTML tag string
print "</title></head><body>\n" def CGI::tag(element, attributes = {})
print msg "<" + escapeHTML(element) + attributes.collect{|name, value|
print "</body></html>\n" " " + escapeHTML(name) + '="' + escapeHTML(value) + '"'
TRUE }.to_s + ">" +
(iterator? ? yield.to_s + "</" + escapeHTML(element) + ">" : "")
end end
def CGI.error # make raw cookie string
m = $!.to_s.dup def CGI::cookie(options)
m.gsub!(/&/, '&amp;') "Set-Cookie: " + options['name'] + '=' + escape(options['value']) +
m.gsub!(/</, '&lt;') (options['domain'] ? '; domain=' + options['domain'] : '') +
m.gsub!(/>/, '&gt;') (options['path'] ? '; path=' + options['path'] : '') +
msgs = ["<pre>ERROR: <strong>#{m}</strong>"] (options['expires'] ? '; expires=' + options['expires'].strftime("%a, %d %b %Y %X %Z") : '') +
msgs << $@ (options['secure'] ? '; secure' : '')
msgs << "</pre>" end
CGI.message(msgs.join("\n"), "ERROR")
# make HTTP header string
def CGI::header(*options)
if ENV['MOD_RUBY']
options.each{|option|
option.sub(/(.*?): (.*)/){
Apache::request[$1] = $2
}
}
Apache::request.send_http_header
''
else
if options.delete("nph") or (ENV['SERVER_SOFTWARE'] =~ /IIS/)
[(ENV['SERVER_PROTOCOL'] or "HTTP/1.0") + " 200 OK",
"Date: " + Time.now.gmtime.strftime("%a, %d %b %Y %X %Z"),
"Server: " + (ENV['SERVER_SOFTWARE'] or ""),
"Connection: close"] +
(options.empty? ? ["Content-Type: text/html"] : options)
else
options.empty? ? ["Content-Type: text/html"] : options
end.join(EOL) + EOL + EOL
end
end
# print HTTP header and string to $>
def CGI::print(*options)
$>.print CGI::header(*options) + yield.to_s
end
# print message to $>
def CGI::message(message, title = "", header = ["Content-Type: text/html"])
if message.kind_of?(Hash)
title = message['title']
header = message['header']
message = message['body']
end
CGI::print(*header){
CGI::tag("HTML"){
CGI::tag("HEAD"){ CGI.tag("TITLE"){ title } } +
CGI::tag("BODY"){ message }
}
}
true
end
# print error message to $> and exit
def CGI::error
CGI::message({'title'=>'ERROR', 'body'=>
CGI::tag("PRE"){
"ERROR: " + CGI::tag("STRONG"){ escapeHTML($!.to_s) } + "\n" + escapeHTML($@.join("\n"))
}
})
exit exit
end end
end end

View file

@ -72,6 +72,8 @@ class Complex < Numeric
end end
def initialize(a, b = 0) def initialize(a, b = 0)
raise "non numeric 1st arg `#{a.inspect}'" if !a.kind_of? Numeric
raise "non numeric 2nd arg `#{b.inspect}'" if !b.kind_of? Numeric
@real = a @real = a
@image = b @image = b
end end
@ -84,7 +86,7 @@ class Complex < Numeric
elsif Complex.generic?(other) elsif Complex.generic?(other)
Complex(@real + other, @image) Complex(@real + other, @image)
else else
x , y = a.coerce(self) x , y = other.coerce(self)
x + y x + y
end end
end end
@ -97,7 +99,7 @@ class Complex < Numeric
elsif Complex.generic?(other) elsif Complex.generic?(other)
Complex(@real - other, @image) Complex(@real - other, @image)
else else
x , y = a.coerce(self) x , y = other.coerce(self)
x - y x - y
end end
end end
@ -110,7 +112,7 @@ class Complex < Numeric
elsif Complex.generic?(other) elsif Complex.generic?(other)
Complex(@real * other, @image * other) Complex(@real * other, @image * other)
else else
x , y = a.coerce(self) x , y = other.coerce(self)
x * y x * y
end end
end end
@ -121,7 +123,7 @@ class Complex < Numeric
elsif Complex.generic?(other) elsif Complex.generic?(other)
Complex(@real / other, @image / other) Complex(@real / other, @image / other)
else else
x , y = a.coerce(self) x , y = other.coerce(self)
x / y x / y
end end
end end
@ -163,7 +165,7 @@ class Complex < Numeric
r, theta = polar r, theta = polar
Complex.polar(r.power!(other), theta * other) Complex.polar(r.power!(other), theta * other)
else else
x , y = a.coerce(self) x , y = other.coerce(self)
x / y x / y
end end
end end
@ -174,7 +176,7 @@ class Complex < Numeric
elsif Complex.generic?(other) elsif Complex.generic?(other)
Complex(@real % other, @image % other) Complex(@real % other, @image % other)
else else
x , y = a.coerce(self) x , y = other.coerce(self)
x % y x % y
end end
end end
@ -187,7 +189,7 @@ class Complex < Numeric
elsif Complex.generic?(other) elsif Complex.generic?(other)
Complex(@real.divmod(other), @image.divmod(other)) Complex(@real.divmod(other), @image.divmod(other))
else else
x , y = a.coerce(self) x , y = other.coerce(self)
x.divmod(y) x.divmod(y)
end end
end end
@ -222,7 +224,7 @@ class Complex < Numeric
elsif Complex.generic?(other) elsif Complex.generic?(other)
@real == other and @image == 0 @real == other and @image == 0
else else
x , y = a.coerce(self) x , y = other.coerce(self)
x == y x == y
end end
end end

267
lib/date2.rb Normal file
View file

@ -0,0 +1,267 @@
# date2.rb: Written by Tadayoshi Funaba 1998, 1999
# $Id: date2.rb,v 1.13 1999/08/11 01:10:02 tadf Exp $
class Date
include Comparable
MONTHNAMES = [ nil, 'January', 'February', 'March',
'April', 'May', 'June', 'July', 'August',
'September', 'October', 'November', 'December' ]
DAYNAMES = [ 'Sunday', 'Monday', 'Tuesday',
'Wednesday', 'Thursday', 'Friday', 'Saturday' ]
ITALY = 2299161 # Oct 15, 1582
ENGLAND = 2361222 # Sept 14, 1752
class << self
def os? (jd, sg)
case sg
when Numeric; jd < sg
else; not sg
end
end
def ns? (jd, sg) not os?(jd, sg) end
def civil_to_jd(y, m, d, sg=true)
if m <= 2
y -= 1
m += 12
end
a = (y / 100).to_i
b = 2 - a + (a / 4).to_i
jd = (365.25 * (y + 4716)).to_i +
(30.6001 * (m + 1)).to_i +
d + b - 1524
if os?(jd, sg)
jd -= b
end
jd
end
def jd_to_civil(jd, sg=true)
if os?(jd, sg)
a = jd
else
x = ((jd - 1867216.25) / 36524.25).to_i
a = jd + 1 + x - (x / 4).to_i
end
b = a + 1524
c = ((b - 122.1) / 365.25).to_i
d = (365.25 * c).to_i
e = ((b - d) / 30.6001).to_i
dom = b - d - (30.6001 * e).to_i
if e <= 13
m = e - 1
y = c - 4716
else
m = e - 13
y = c - 4715
end
return y, m, dom
end
def ordinal_to_jd(y, d, sg=true)
civil_to_jd(y, 1, d, sg)
end
def jd_to_ordinal(jd, sg=true)
y = jd_to_civil(jd, sg)[0]
pl = civil_to_jd(y - 1, 12, 31, ns?(jd, sg))
doy = jd - pl
return y, doy
end
def mjd_to_jd(mjd) mjd + 2400000.5 end
def jd_to_mjd(jd) jd - 2400000.5 end
def tjd_to_jd(tjd) tjd + 2440000.5 end
def jd_to_tjd(jd) jd - 2440000.5 end
def julian_leap? (y) y % 4 == 0 end
def gregorian_leap? (y) y % 4 == 0 and y % 100 != 0 or y % 400 == 0 end
alias_method :leap?, :gregorian_leap?
def exist3? (y, m, d, sg=ITALY)
if m < 0
m += 13
end
if d < 0
ljd = nil
31.downto 1 do |ld|
break if ljd = exist3?(y, m, ld, sg)
end
x = y * 12 + m
ny = x / 12
nm = x % 12 + 1
d = jd_to_civil(civil_to_jd(ny, nm, 1, ns?(ljd, sg)) + d,
ns?(ljd, sg))[-1]
end
jd = civil_to_jd(y, m, d, sg)
if [y, m, d] == jd_to_civil(jd, sg)
jd
end
end
alias_method :exist?, :exist3?
def new3(y=-4712, m=1, d=1, sg=ITALY)
unless jd = exist3?(y, m, d, sg)
fail ArgumentError, 'invalid date'
end
new(jd, sg)
end
def exist2? (y, d, sg=ITALY)
if d < 0
ljd = nil
366.downto 1 do |ld|
break if ljd = exist2?(y, ld, sg)
end
ny = y + 1
d = jd_to_ordinal(ordinal_to_jd(ny, 1, ns?(ljd, sg)) + d,
ns?(ljd, sg))[-1]
end
jd = ordinal_to_jd(y, d, sg)
if [y, d] == jd_to_ordinal(jd, sg)
jd
end
end
def new2(y=-4712, d=1, sg=ITALY)
unless jd = exist2?(y, d, sg)
fail ArgumentError, 'invalid date'
end
new(jd, sg)
end
def today(sg=ITALY)
new(civil_to_jd(*(Time.now.to_a[3..5].reverse << sg)), sg)
end
end
def initialize(jd=0, sg=ITALY) @jd, @sg = jd, sg end
def jd() @jd end
def mjd
def self.mjd() @mjd end
@mjd = Date.jd_to_mjd(@jd)
end
def tjd
def self.tjd() @tjd end
@tjd = Date.jd_to_tjd(@jd)
end
def civil
def self.year() @year end
def self.mon() @mon end
def self.month() @mon end
def self.mday() @mday end
def self.day() @mday end
@year, @mon, @mday = Date.jd_to_civil(@jd, @sg)
end
private :civil
def year
civil
@year
end
def yday
def self.yday() @yday end
@yday = Date.jd_to_ordinal(@jd, @sg)[-1]
@yday
end
def mon
civil
@mon
end
alias_method :month, :mon
def mday
civil
@mday
end
alias_method :day, :mday
def wday
def self.wday() @wday end
@wday = (@jd + 1) % 7
end
def os? () Date.os?(@jd, @sg) end
def ns? () Date.ns?(@jd, @sg) end
def leap?
def self.leap?() @leap_p end
@leap_p = Date.jd_to_civil(Date.civil_to_jd(year, 3, 1, ns?) - 1,
ns?)[-1] == 29
end
def + (other)
case other
when Numeric; return Date.new(@jd + other, @sg)
end
fail TypeError, 'expected numeric'
end
def - (other)
case other
when Numeric; return Date.new(@jd - other, @sg)
when Date; return @jd - other.jd
end
fail TypeError, 'expected numeric or date'
end
def <=> (other)
case other
when Numeric; return @jd <=> other
when Date; return @jd <=> other.jd
end
fail TypeError, 'expected numeric or date'
end
def downto(min)
@jd.downto(min.jd) do |jd|
yield Date.new(jd, @sg)
end
self
end
def upto(max)
@jd.upto(max.jd) do |jd|
yield Date.new(jd, @sg)
end
self
end
def step(limit, step)
@jd.step(limit.jd, step) do |jd|
yield Date.new(jd, @sg)
end
self
end
def succ() self + 1 end
alias_method :next, :succ
def eql? (other) self == other end
def hash() @jd end
def inspect() format('#<Date: %s,%s>', @jd, @sg) end
def to_s() format('%.4d-%02d-%02d', year, mon, mday) end
def _dump(limit) Marshal.dump([@jd, @sg], -1) end
def Date._load(str) Date.new(*Marshal.load(str)) end
end

View file

@ -1,13 +1,29 @@
class DEBUGGER__ class DEBUGGER__
begin
require 'readline'
def readline(prompt, hist)
Readline::readline(prompt, hist)
end
rescue LoadError
def readline(prompt, hist)
STDOUT.print prompt
STDOUT.flush
line = STDIN.gets
line.chomp!
line
end
USE_READLINE = false
end
trap("INT") { DEBUGGER__::CONTEXT.interrupt } trap("INT") { DEBUGGER__::CONTEXT.interrupt }
$DEBUG = TRUE $DEBUG = true
def initialize def initialize
@break_points = [] @break_points = []
@display = []
@stop_next = 1 @stop_next = 1
@frames = [nil] @frames = [nil]
@frame_pos = nil
@last_file = nil @last_file = nil
@last = [nil, nil]
@scripts = {} @scripts = {}
end end
@ -23,185 +39,271 @@ class DEBUGGER__
val val
rescue rescue
at = caller(0) at = caller(0)
printf "%s:%s\n", at.shift, $! STDOUT.printf "%s:%s\n", at.shift, $!
for i in at for i in at
break if i =~ /`debug_(eval|command)'$/ #` break if i =~ /`debug_(eval|command)'$/ #`
printf "\tfrom %s\n", i STDOUT.printf "\tfrom %s\n", i
end end
end end
end end
def debug_command(file, line, id, binding) def debug_command(file, line, id, binding)
frame_pos = 0
binding_file = file
binding_line = line
previus_line = nil
if (ENV['EMACS'] == 't') if (ENV['EMACS'] == 't')
printf "\032\032%s:%d:\n", file, line STDOUT.printf "\032\032%s:%d:\n", binding_file, binding_line
else else
printf "%s:%d:%s", file, line, line_at(file, line) STDOUT.printf "%s:%d:%s", binding_file, binding_line,
line_at(binding_file, binding_line)
end end
@frames[-1] = binding @frames[0] = binding
STDOUT.print "(rdb:-) " display_expressions(binding)
STDOUT.flush while input = readline("(rdb:-) ", true)
while input = STDIN.gets
input.chop!
if input == "" if input == ""
input = DEBUG_LAST_CMD[0] input = DEBUG_LAST_CMD[0]
else else
DEBUG_LAST_CMD[0] = input DEBUG_LAST_CMD[0] = input
end end
case input case input
when /^b(reak)?\s+(([^:\n]+:)?.+)/ when /^b(?:reak)?\s+((?:[^:\n]+:)?.+)$/
pos = $2 pos = $1
if pos.index ":" if pos.index(":")
file, pos = pos.split(":") file, pos = pos.split(":")
end end
file = File.basename(file) file = File.basename(file)
if pos =~ /^\d+$/ if pos =~ /^\d+$/
pname = pos pname = pos
pos = Integer(pos) pos = pos.to_i
else else
pname = pos = pos.intern.id2name pname = pos = pos.intern.id2name
end end
printf "Set breakpoint %d at %s:%s\n", @break_points.size, file, pname @break_points.push [true, 0, file, pos]
@break_points.push [file, pos] STDOUT.printf "Set breakpoint %d at %s:%s\n", @break_points.size, file,
when /^b(reak)?$/, /^info b(reak)?$/ pname
n = 0
for f, p in @break_points when /^wat(?:ch)?\s+(.+)$/
printf "%d %s:%s\n", n, f, p exp = $1
@break_points.push [true, 1, exp]
STDOUT.printf "Set watchpoint %d\n", @break_points.size, exp
when /^b(?:reak)?$/, /^info b(?:reak)?$/
n = 1
STDOUT.print "breakpoints:\n"
for b in @break_points
if b[0] and (b[1] == 0)
STDOUT.printf " %d %s:%s\n", n, b[2], b[3]
end
n += 1 n += 1
end end
when /^del(ete)?(\s+(\d+))?$/ n = 1
pos = $3 STDOUT.print "\n"
STDOUT.print "watchpoints:\n"
for b in @break_points
if b[0] and (b[1] == 1)
STDOUT.printf " %d %s\n", n, b[2]
end
n += 1
end
STDOUT.print "\n"
when /^del(?:ete)?(?:\s+(\d+))?$/
pos = $1
unless pos unless pos
STDOUT.print "clear all breakpoints? (y/n) " input = readline("clear all breakpoints? (y/n) ", false)
STDOUT.flush
input = STDIN.gets.chop!
if input == "y" if input == "y"
for n in @break_points.indexes for b in @break_points
@break_points[n] = nil b[0] = false
end end
end end
else else
pos = Integer(pos) pos = pos.to_i
if @break_points[pos] if @break_points[pos-1]
bp = @break_points[pos] @break_points[pos-1][0] = false
printf "Clear breakpoint %d at %s:%s\n", pos, bp[0], bp[1]
@break_points[pos] = nil
else else
printf "Breakpoint %d is not defined\n", pos STDOUT.printf "Breakpoint %d is not defined\n", pos
end end
end end
when /^c(ont)?$/
when /^disp(?:lay)?\s+(.+)$/
exp = $1
@display.push.push [true, exp]
STDOUT.printf " %d: %s = %s\n", @display.size, exp,
debug_eval(exp, binding).to_s
when /^disp(?:lay)?$/, /^info disp(?:lay)?$/
display_expressions(binding)
when /^undisp(?:lay)?(?:\s+(\d+))?$/
pos = $1
unless pos
input = readline("clear all expressions? (y/n) ", false)
if input == "y"
for d in @display
d[0] = false
end
end
else
pos = pos.to_i
if @display[pos-1]
@display[pos-1][0] = false
else
STDOUT.printf "display expression %d is not defined\n", pos
end
end
when /^c(?:ont)?$/
return return
when /^s(tep)?\s*(\d+)?$/
when /^s(?:tep)?(?:\s+(\d+))?$/
if $1 if $1
lev = Integer($1) lev = $1.to_i
else else
lev = 1 lev = 1
end end
@stop_next = lev @stop_next = lev
return return
when /^n(ext)?\s*(\d+)?$/
when /^n(?:ext)?(?:\s+(\d+))?$/
if $1 if $1
lev = Integer($1) lev = $1.to_i
else else
lev = 1 lev = 1
end end
@stop_next = lev @stop_next = lev
@no_step = @frames.size @no_step = @frames.size - frame_pos
return return
when /^up\s*(\d+)?$/
if $1 when /^w(?:here)?$/, /^f(?:rame)?$/
lev = Integer($1) at = caller(0)
else 0.upto(@frames.size - 1) do |n|
lev = 1 if frame_pos == n
STDOUT.printf "--> #%d %s\n", n, at[-(@frames.size - n)]
else
STDOUT.printf " #%d %s\n", n, at[-(@frames.size - n)]
end
end end
unless @frame_pos
@frame_pos = @frames.size - 1 when /^l(?:ist)?(?:\s+(.+))?$/
if not $1
b = previus_line ? previus_line + 10 : binding_line - 5
e = b + 9
elsif $1 == '-'
b = previus_line ? previus_line - 10 : binding_line - 5
e = b + 9
else
b, e = $1.split(/[-,]/)
if e
b = b.to_i
e = e.to_i
else
b = b.to_i - 5
e = b + 9
end
end
previus_line = b
STDOUT.printf "[%d, %d] in %s\n", b, e, binding_file
line_at(binding_file, binding_line)
if lines = @scripts[binding_file] and lines != true
n = 0
b.upto(e) do |n|
if n > 0 && lines[n-1]
if n == binding_line
STDOUT.printf "=> %d %s\n", n, lines[n-1].chomp
else
STDOUT.printf " %d %s\n", n, lines[n-1].chomp
end
end
end
else
STDOUT.printf "no sourcefile available for %s\n", binding_file
end
when /^up(?:\s+(\d+))?$/
previus_line = nil
if $1
lev = $1.to_i
else
lev = 1
end
frame_pos += lev
if frame_pos >= @frames.size
frame_pos = @frames.size - 1
STDOUT.print "at toplevel\n"
end end
@frame_pos -= lev binding = @frames[frame_pos]
if @frame_pos < 0 info, binding_file, binding_line = frame_info(frame_pos)
STDOUT.print "at toplevel\n" STDOUT.printf "#%d %s\n", frame_pos, info
@frame_pos = 0
else when /^down(?:\s+(\d+))?$/
binding = @frames[@frame_pos] previus_line = nil
if $1
lev = $1.to_i
else
lev = 1
end
frame_pos -= lev
if frame_pos < 0
frame_pos = 0
STDOUT.print "at stack bottom\n"
end end
when /^down\s*(\d+)??$/ binding = @frames[frame_pos]
if $1 info, binding_file, binding_line = frame_info(frame_pos)
lev = Integer($1) STDOUT.printf "#%d %s\n", frame_pos, info
else
lev = 1 when /^fi(?:nish)?$/
end @finish_pos = @frames.size - frame_pos
if lev >= @frames.size or @frame_pos and @frame_pos+lev >= @frames.size frame_pos = 0
STDOUT.print "at stack bottom\n"
@frame_pos = nil
else
@frame_pos += lev
binding = @frames[@frame_pos]
end
when /^fin(ish)?$/
@finish_pos = @frames.size
return return
when /^q(uit)?$/
STDOUT.print "really quit? (y/n) " when /^q(?:uit)?$/
STDOUT.flush input = readline("really quit? (y/n) ", false)
input = STDIN.gets.chop!
exit if input == "y" exit if input == "y"
when /^where$/
at = caller(4)
for i in at
printf " %s\n", i
end
when /^l(ist)?(\s+(.*))?$/
if $3
b, e = $3.split(/[-,]/)
b = Integer(b)-1
if e
e = Integer(e)-1
else
e = b + 10
end
end
unless b
b = line - 1
e = line + 9
end
p [b,e]
line_at(file, line)
if lines = @scripts[file] and lines != TRUE
n = b+1
for l in lines[b..e]
printf "%4d %s", n, l
n += 1
end
else
printf "no sourcefile available for %s\n", file
end
when /^p\s+/ when /^p\s+/
p debug_eval($', binding) #' p debug_eval($', binding)
else else
v = debug_eval(input, binding) v = debug_eval(input, binding)
p v unless v == nil p v unless (v == nil)
end end
STDOUT.print "(rdb:-) "
STDOUT.flush
end end
end end
def display_expressions(binding)
n = 1
for d in @display
if d[0]
STDOUT.printf "%d: %s = %s\n", n, d[1], debug_eval(d[1], binding).to_s
end
n += 1
end
end
def frame_info(pos = 0)
info = caller(0)[-(@frames.size - pos)]
info.sub(/:in `.*'$/, "") =~ /^(.*):(\d+)$/ #`
[info, $1, $2.to_i]
end
def line_at(file, line) def line_at(file, line)
lines = @scripts[file] lines = @scripts[file]
if lines if lines
return "\n" if lines == TRUE return "\n" if lines == true
line = lines[line-1] line = lines[line-1]
return "\n" unless line return "\n" unless line
return line return line
end end
save = $DEBUG save = $DEBUG
begin begin
$DEBUG = FALSE $DEBUG = false
f = open(file) f = open(file)
lines = @scripts[file] = f.readlines lines = @scripts[file] = f.readlines
rescue rescue
$DEBUG = save $DEBUG = save
@scripts[file] = TRUE @scripts[file] = true
return "\n" return "\n"
end end
line = lines[line-1] line = lines[line-1]
@ -219,19 +321,44 @@ class DEBUGGER__
def check_break_points(file, pos, binding, id) def check_break_points(file, pos, binding, id)
file = File.basename(file) file = File.basename(file)
if @break_points.include? [file, pos] n = 1
index = @break_points.index([file, pos]) for b in @break_points
printf "Breakpoint %d, %s at %s:%s\n", if b[0]
index, debug_funcname(id), file, pos if b[1] == 0 and b[2] == file and b[3] == pos
return TRUE STDOUT.printf "breakpoint %d, %s at %s:%s\n", n, debug_funcname(id),
file, pos
return true
elsif b[1] == 1 and debug_eval(b[2], binding)
STDOUT.printf "watchpoint %d, %s at %s:%s\n", n, debug_funcname(id),
file, pos
return true
end
end
n += 1
end end
return FALSE return false
end
def excn_handle(file, line, id, binding)
fs = @frames.size
tb = caller(0)[-fs..-1]
STDOUT.printf "%s\n", $!
for i in tb
STDOUT.printf "\tfrom %s\n", i
end
debug_command(file, line, id, binding)
end end
def trace_func(event, file, line, id, binding) def trace_func(event, file, line, id, binding)
if event == 'line' case event
if @no_step == nil or @no_step >= @frames.size when 'line'
if !@no_step or @frames.size == @no_step
@stop_next -= 1 @stop_next -= 1
elsif @frames.size < @no_step
@stop_next = 0 # break here before leaving...
else
# nothing to do. skipped.
end end
if @stop_next == 0 if @stop_next == 0
if [file, line] == @last if [file, line] == @last
@ -245,21 +372,25 @@ class DEBUGGER__
if check_break_points(file, line, binding, id) if check_break_points(file, line, binding, id)
debug_command(file, line, id, binding) debug_command(file, line, id, binding)
end end
end
if event == 'call' when 'call'
@frames.push binding @frames.unshift binding
if check_break_points(file, id.id2name, binding, id) if check_break_points(file, id.id2name, binding, id)
debug_command(file, line, id, binding) debug_command(file, line, id, binding)
end end
end
if event == 'class' when 'class'
@frames.push binding @frames.unshift binding
end
if event == 'return' or event == 'end' when 'return', 'end'
if @finish_pos == @frames.size if @frames.size == @finish_pos
@stop_next = 1 @stop_next = 1
end end
@frames.pop @frames.shift
when 'raise'
excn_handle(file, line, id, binding)
end end
@last_file = file @last_file = file
end end
@ -267,6 +398,6 @@ class DEBUGGER__
CONTEXT = new CONTEXT = new
end end
set_trace_func proc{|event, file, line, id, binding| set_trace_func proc{|event, file, line, id, binding,*rest|
DEBUGGER__::CONTEXT.trace_func event, file, line, id, binding DEBUGGER__::CONTEXT.trace_func event, file, line, id, binding
} }

View file

@ -34,14 +34,8 @@ class Delegator
begin begin
__getobj__.__send__(:#{method}, *args, &block) __getobj__.__send__(:#{method}, *args, &block)
rescue Exception rescue Exception
c = -caller(0).size $@.delete_if{|s| /:in `__getobj__'$/ =~ s} #`
if /:in `__getobj__'$/ =~ $@[c-1] #` $@.delete_if{|s| /^\\(eval\\):/ =~ s}
n = 1
else
c -= 1
n = 2
end
$@[c,n] = nil
raise raise
end end
end end

View file

@ -1,17 +1,46 @@
# #
# e2mmap.rb - for ruby 1.1 # e2mmap.rb - for ruby 1.1
# $Release Version: 1.2$ # $Release Version: 2.0$
# $Revision: 1.8 $ # $Revision: 1.10 $
# $Date: 1998/08/19 15:22:22 $ # $Date: 1999/02/17 12:33:17 $
# by Keiju ISHITSUKA # by Keiju ISHITSUKA
# #
# -- # --
# Usage: # Usage:
# #
# U1)
# class Foo # class Foo
# extend Exception2MassageMapper # extend Exception2MassageMapper
# def_e2message ExistingExceptionClass, "message..."
# def_exception :NewExceptionClass, "message..."[, superclass] # def_exception :NewExceptionClass, "message..."[, superclass]
# ...
# end
#
# U2)
# module Error
# extend Exception2MassageMapper
# def_e2meggage ExistingExceptionClass, "message..." # def_e2meggage ExistingExceptionClass, "message..."
# def_exception :NewExceptionClass, "message..."[, superclass]
# ...
# end
# class Foo
# include Exp
# ...
# end
#
# foo = Foo.new
# foo.Fail ....
#
# U3)
# module Error
# extend Exception2MassageMapper
# def_e2message ExistingExceptionClass, "message..."
# def_exception :NewExceptionClass, "message..."[, superclass]
# ...
# end
# class Foo
# extend Exception2MessageMapper
# include Error
# ... # ...
# end # end
# #
@ -19,113 +48,149 @@
# Foo.Fail ExistingExceptionClass, arg... # Foo.Fail ExistingExceptionClass, arg...
# #
# #
if VERSION < "1.1" fail "Use Ruby 1.1" if VERSION < "1.1"
require "e2mmap1_0.rb"
else module Exception2MessageMapper
@RCS_ID='-$Id: e2mmap.rb,v 1.10 1999/02/17 12:33:17 keiju Exp keiju $-'
E2MM = Exception2MessageMapper
def E2MM.extend_object(cl)
super
cl.bind(self) unless cl == E2MM
end
module Exception2MessageMapper # 以前との互換性のために残してある.
@RCS_ID='-$Id: e2mmap.rb,v 1.8 1998/08/19 15:22:22 keiju Exp keiju $-' def E2MM.extend_to(b)
c = eval("self", b)
E2MM = Exception2MessageMapper c.extend(self)
end
def E2MM.extend_object(cl) def bind(cl)
super self.module_eval %[
cl.bind(self) def Raise(err = nil, *rest)
end Exception2MessageMapper.Raise(self.type, err, *rest)
# backward compatibility
def E2MM.extend_to(b)
c = eval("self", b)
c.extend(self)
end
# public :fail
alias fail! fail
#def fail(err = nil, *rest)
# super
#end
def Fail(err = nil, *rest)
Exception2MessageMapper.Fail Exception2MessageMapper::ErrNotRegisteredException, err.inspect
end
def bind(cl)
self.module_eval %q^
E2MM_ErrorMSG = {} unless self.const_defined?(:E2MM_ErrorMSG)
# fail(err, *rest)
# err: Exception
# rest: Parameter accompanied with the exception
#
def self.Fail(err = nil, *rest)
if form = E2MM_ErrorMSG[err]
$! = err.new(sprintf(form, *rest))
$@ = caller(0) if $@.nil?
$@.shift
# e2mm_fail()
raise()
# elsif self == Exception2MessageMapper
# fail Exception2MessageMapper::ErrNotRegisteredException, err.to_s
else
# print "super\n"
super
end
end
# ²áµî¤Î¸ß´¹À­¤Î¤¿¤á
def self.fail(err = nil, *rest)
if form = E2MM_ErrorMSG[err]
$! = err.new(sprintf(form, *rest))
$@ = caller(0) if $@.nil?
$@.shift
# e2mm_fail()
raise()
# elsif self == Exception2MessageMapper
# fail Exception2MessageMapper::ErrNotRegisteredException, err.to_s
else
# print "super\n"
super
end
end
class << self
public :fail
end
# def_exception(c, m)
# c: exception
# m: message_form
#
def self.def_e2message(c, m)
E2MM_ErrorMSG[c] = m
end
# def_exception(c, m)
# n: exception_name
# m: message_form
# s: superclass_of_exception (default: Exception)
# defines excaption named ``c'', whose message is ``m''.
#
#def def_exception(n, m)
def self.def_exception(n, m, s = nil)
n = n.id2name if n.kind_of?(Fixnum)
unless s
if defined?(StandardError)
s = StandardError
else
s = Exception
end
end
e = Class.new(s)
const_set(n, e)
E2MM_ErrorMSG[e] = m
# const_get(:E2MM_ErrorMSG)[e] = m
end
^
end end
alias Fail Raise
extend E2MM
def_exception(:ErrNotClassOrModule, "Not Class or Module") def self.append_features(mod)
def_exception(:ErrNotRegisteredException, "not registerd exception(%s)") super
mod.extend Exception2MessageMapper
end
]
end
# Fail(err, *rest)
# err: 例外
# rest: メッセージに渡すパラメータ
#
def Raise(err = nil, *rest)
E2MM.Raise(self, err, *rest)
end
alias Fail Raise
# 過去の互換性のため
alias fail! fail
def fail(err = nil, *rest)
begin
E2MM.Fail(self, err, *rest)
rescue E2MM::ErrNotRegisteredException
super
end end
end
class << self
public :fail
end
# def_e2message(c, m)
# c: exception
# m: message_form
# 例外cのメッセージをmとする.
#
def def_e2message(c, m)
E2MM.def_e2message(self, c, m)
end
# def_exception(c, m)
# n: exception_name
# m: message_form
# s: 例外スーパークラス(デフォルト: StandardError)
# 例外名``c''をもつ例外を定義し, そのメッセージをmとする.
#
def def_exception(n, m, s = StandardError)
E2MM.def_exception(self, n, m, s)
end
#
# Private definitions.
#
# {[class, exp] => message, ...}
@MessageMap = {}
# E2MM.def_exception(k, e, m)
# k: 例外を定義するクラス
# e: exception
# m: message_form
# 例外cのメッセージをmとする.
#
def E2MM.def_e2message(k, c, m)
E2MM.instance_eval{@MessageMap[[k, c]] = m}
c
end
# E2MM.def_exception(k, c, m)
# k: 例外を定義するクラス
# n: exception_name
# m: message_form
# s: 例外スーパークラス(デフォルト: StandardError)
# 例外名``c''をもつ例外を定義し, そのメッセージをmとする.
#
def E2MM.def_exception(k, n, m, s = StandardError)
n = n.id2name if n.kind_of?(Fixnum)
e = Class.new(s)
E2MM.instance_eval{@MessageMap[[k, e]] = m}
k.const_set(n, e)
end
# Fail(klass, err, *rest)
# klass: 例外の定義されているクラス
# err: 例外
# rest: メッセージに渡すパラメータ
#
def E2MM.Raise(klass = E2MM, err = nil, *rest)
if form = e2mm_message(klass, err)
$! = err.new(sprintf(form, *rest))
$@ = caller(1) if $@.nil?
#p $@
#p __FILE__
$@.shift if $@[0] =~ /^#{Regexp.quote(__FILE__)}:/
raise
else
E2MM.Fail E2MM, ErrNotRegisteredException, err.inspect
end
end
class <<E2MM
alias Fail Raise
end
def E2MM.e2mm_message(klass, exp)
for c in klass.ancestors
if mes = @MessageMap[[c,exp]]
p mes
m = klass.instance_eval('"' + mes + '"')
return m
end
end
nil
end
class <<self
alias message e2mm_message
end
E2MM.def_exception(E2MM,
:ErrNotRegisteredException,
"not registerd exception(%s)")
end end

41
lib/final.rb Normal file
View file

@ -0,0 +1,41 @@
#
# $Id$
# Copyright (C) 1998 Yukihiro Matsumoto. All rights reserved.
# The ObjectSpace extension:
#
# ObjectSpace.define_finalizer(obj, proc=lambda())
#
# Defines the finalizer for the specified object.
#
# ObjectSpace.undefine_finalizer(obj)
#
# Removes the finalizers for the object. If multiple finalizers are
# defined for the object, all finalizers will be removed.
#
module ObjectSpace
Finalizers = {}
def define_finalizer(obj, proc=lambda())
ObjectSpace.call_finalizer(obj)
if assoc = Finalizers[obj.id]
assoc.push(proc)
else
Finalizers[obj.id] = [proc]
end
end
def undefine_finalizer(obj)
Finalizers.delete(obj.id)
end
module_function :define_finalizer, :undefine_finalizer
Generic_Finalizer = proc {|id|
if Finalizers.key? id
for proc in Finalizers[id]
proc.call(id)
end
Finalizers.delete(id)
end
}
add_finalizer Generic_Finalizer
end

View file

@ -157,7 +157,7 @@ module Finalizer
# method to call finalize_* safely. # method to call finalize_* safely.
def safe def safe
old_status = Thread.critical old_status = Thread.critical
Thread.critical = TRUE Thread.critical = true
ObjectSpace.remove_finalizer(@proc) ObjectSpace.remove_finalizer(@proc)
yield yield
ObjectSpace.add_finalizer(@proc) ObjectSpace.add_finalizer(@proc)

View file

@ -24,6 +24,9 @@ class << File
fsize = 1024 if fsize < 512 fsize = 1024 if fsize < 512
fsize = TOO_BIG if fsize > TOO_BIG fsize = TOO_BIG if fsize > TOO_BIG
fmode = stat(from).mode
tpath = to
from = open(from, "r") from = open(from, "r")
from.binmode from.binmode
to = open(to, "w") to = open(to, "w")
@ -47,6 +50,7 @@ class << File
to.close to.close
from.close from.close
end end
chmod(fmode, tpath)
ret ret
end end
@ -63,13 +67,24 @@ class << File
to = catname(from, to) to = catname(from, to)
$stderr.print from, " -> ", to, "\n" if verbose $stderr.print from, " -> ", to, "\n" if verbose
if PLATFORM =~ /djgpp|cygwin|mswin32/ and FileTest.file? to if RUBY_PLATFORM =~ /djgpp|cygwin|mswin32/ and FileTest.file? to
unlink to unlink to
end end
fstat = stat(from)
begin begin
rename from, to rename from, to
rescue rescue
syscopy from, to and unlink from begin
symlink File.readlink(from), to and unlink from
rescue
from_stat = stat(from)
syscopy from, to and unlink from
utime(from_stat.atime, from_stat.mtime, to)
begin
chown(fstat.uid, fstat.gid, tpath)
rescue
end
end
end end
end end
@ -98,7 +113,8 @@ class << File
if fr = from.read(fsize) if fr = from.read(fsize)
tr = to.read(fr.size) tr = to.read(fr.size)
else else
ret = !to.read(fsize) ret = to.read(fsize)
ret = !ret || ret.length == 0
break break
end end
end end
@ -137,7 +153,9 @@ class << File
parent = dirname(dir) parent = dirname(dir)
makedirs parent unless FileTest.directory? parent makedirs parent unless FileTest.directory? parent
$stderr.print "mkdir ", dir, "\n" if verbose $stderr.print "mkdir ", dir, "\n" if verbose
Dir.mkdir dir, mode if basename(dir) != ""
Dir.mkdir dir, mode
end
end end
end end
@ -154,7 +172,7 @@ class << File
def install(from, to, mode = nil, verbose = false) def install(from, to, mode = nil, verbose = false)
to = catname(from, to) to = catname(from, to)
unless FileTest.exist? to and cmp from, to unless FileTest.exist? to and cmp from, to
unlink to if FileTest.exist? to safe_unlink to if FileTest.exist? to
cp from, to, verbose cp from, to, verbose
chmod mode, to, verbose if mode chmod mode, to, verbose if mode
end end

View file

@ -150,16 +150,23 @@ class FTP
end end
def sendport(host, port) def sendport(host, port)
hbytes = host.split(".") af = (@sock.peeraddr)[0]
pbytes = [port / 256, port % 256] if af == "AF_INET"
bytes = hbytes + pbytes hbytes = host.split(".")
cmd = "PORT " + bytes.join(",") pbytes = [port / 256, port % 256]
bytes = hbytes + pbytes
cmd = "PORT " + bytes.join(",")
elsif af == "AF_INET6"
cmd = "EPRT |2|" + host + "|" + sprintf("%d", port) + "|"
else
raise FTPProtoError, host
end
voidcmd(cmd) voidcmd(cmd)
end end
private :sendport private :sendport
def makeport def makeport
sock = TCPserver.open(0) sock = TCPserver.open(@sock.addr[3], 0)
port = sock.addr[1] port = sock.addr[1]
host = TCPsocket.getaddress(@sock.addr[2]) host = TCPsocket.getaddress(@sock.addr[2])
resp = sendport(host, port) resp = sendport(host, port)
@ -167,9 +174,20 @@ class FTP
end end
private :makeport private :makeport
def makepasv
if @sock.peeraddr[0] == "AF_INET"
host, port = parse227(sendcmd("PASV"))
else
host, port = parse229(sendcmd("EPSV"))
# host, port = parse228(sendcmd("LPSV"))
end
return host, port
end
private :makepasv
def transfercmd(cmd) def transfercmd(cmd)
if @passive if @passive
host, port = parse227(sendcmd("PASV")) host, port = makepasv
conn = open_socket(host, port) conn = open_socket(host, port)
resp = sendcmd(cmd) resp = sendcmd(cmd)
if resp[0] != ?1 if resp[0] != ?1
@ -293,11 +311,7 @@ class FTP
buf = file.gets buf = file.gets
break if buf == nil break if buf == nil
if buf[-2, 2] != CRLF if buf[-2, 2] != CRLF
if buf[-1] == ?\r or buf = buf.chop + CRLF
buf[-1] == ?\n
buf = buf[0 .. -2]
end
buf = buf + CRLF
end end
conn.write(buf) conn.write(buf)
callback.call(buf) if use_callback callback.call(buf) if use_callback
@ -545,6 +559,57 @@ class FTP
end end
private :parse227 private :parse227
def parse228(resp)
if resp[0, 3] != "228"
raise FTPReplyError, resp
end
left = resp.index("(")
right = resp.index(")")
if left == nil or right == nil
raise FTPProtoError, resp
end
numbers = resp[left + 1 .. right - 1].split(",")
if numbers[0] == "4"
if numbers.length != 9 || numbers[1] != "4" || numbers[2 + 4] != "2"
raise FTPProtoError, resp
end
host = numbers[2, 4].join(".")
port = (numbers[7].to_i << 8) + numbers[8].to_i
elsif numbers[0] == "6"
if numbers.length != 21 || numbers[1] != "16" || numbers[2 + 16] != "2"
raise FTPProtoError, resp
end
v6 = ["", "", "", "", "", "", "", ""]
for i in 0 .. 7
v6[i] = sprintf("%02x%02x", numbers[(i * 2) + 2].to_i,
numbers[(i * 2) + 3].to_i)
end
host = v6[0, 8].join(":")
port = (numbers[19].to_i << 8) + numbers[20].to_i
end
return host, port
end
private :parse228
def parse229(resp)
if resp[0, 3] != "229"
raise FTPReplyError, resp
end
left = resp.index("(")
right = resp.index(")")
if left == nil or right == nil
raise FTPProtoError, resp
end
numbers = resp[left + 1 .. right - 1].split(resp[left + 1, 1])
if numbers.length != 4
raise FTPProtoError, resp
end
port = numbers[3].to_i
host = (@sock.peeraddr())[3]
return host, port
end
private :parse228
def parse257(resp) def parse257(resp)
if resp[0, 3] != "257" if resp[0, 3] != "257"
raise FTPReplyError, resp raise FTPReplyError, resp

473
lib/getoptlong.rb Normal file
View file

@ -0,0 +1,473 @@
# -*- Ruby -*-
# Copyright (C) 1998 Motoyuki Kasahara
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
#
# Documents and latest version of `getoptlong.rb' are found at:
# http://www.sra.co.jp/people/m-kasahr/ruby/getoptlong/
#
#
# Parse command line options just like GNU getopt_long().
#
class GetoptLong
#
# Orderings.
#
ORDERINGS = [REQUIRE_ORDER = 0, PERMUTE = 1, RETURN_IN_ORDER = 2]
#
# Argument flags.
#
ARGUMENT_FLAGS = [NO_ARGUMENT = 0, REQUIRED_ARGUMENT = 1,
OPTIONAL_ARGUMENT = 2]
#
# Status codes.
#
STATUS_YET, STATUS_STARTED, STATUS_TERMINATED = 0..2
#
# Error types.
#
class AmbigousOption < StandardError; end
class NeedlessArgument < StandardError; end
class MissingArgument < StandardError; end
class InvalidOption < StandardError; end
#
# Initializer.
#
def initialize(*arguments)
#
# Current ordering.
#
if ENV.include?('POSIXLY_CORRECT')
@ordering = REQUIRE_ORDER
else
@ordering = PERMUTE
end
#
# Hash table of option names.
# Keyes of the table are option names, and their values are canonical
# names of the options.
#
@canonical_names = Hash.new
#
# Hash table of argument flags.
# Keyes of the table are option names, and their values are argument
# flags of the options.
#
@argument_flags = Hash.new
#
# Whether error messages are output to stderr.
#
@quiet = FALSE
#
# Status code.
#
@status = STATUS_YET
#
# Error code.
#
@error = nil
#
# Error message.
#
@error_message = nil
#
# Rest of catinated short options.
#
@rest_singles = ''
#
# List of non-option-arguments.
# Append them to ARGV when option processing is terminated.
#
@non_option_arguments = Array.new
if 0 < arguments.length
set_options(*arguments)
end
end
#
# Set ordering.
#
def ordering=(ordering)
#
# The method is failed if option processing has already started.
#
if @status != STATUS_YET
set_error(ArgumentError, "argument error")
raise RuntimeError,
"invoke ordering=, but option processing has already started"
end
#
# Check ordering.
#
if !ORDERINGS.include?(ordering)
raise ArgumentError, "invalid ordering `#{ordering}'"
end
if ordering == PERMUTE && ENV.include?('POSIXLY_CORRECT')
@ordering = REQUIRE_ORDER
else
@ordering = ordering
end
end
#
# Return ordering.
#
attr_reader :ordering
#
# Set options
#
def set_options(*arguments)
#
# The method is failed if option processing has already started.
#
if @status != STATUS_YET
raise RuntimeError,
"invoke set_options, but option processing has already started"
end
#
# Clear tables of option names and argument flags.
#
@canonical_names.clear
@argument_flags.clear
arguments.each do |arg|
#
# Each argument must be an Array.
#
if !arg.is_a?(Array)
raise ArgumentError, "the option list contains non-Array argument"
end
#
# Find an argument flag and it set to `argument_flag'.
#
argument_flag = nil
arg.each do |i|
if ARGUMENT_FLAGS.include?(i)
if argument_flag != nil
raise ArgumentError, "too many argument-flags"
end
argument_flag = i
end
end
raise ArgumentError, "no argument-flag" if argument_flag == nil
canonical_name = nil
arg.each do |i|
#
# Check an option name.
#
next if i == argument_flag
begin
if !i.is_a?(String) || i !~ /^-([^-]|-.+)$/
raise ArgumentError, "an invalid option `#{i}'"
end
if (@canonical_names.include?(i))
raise ArgumentError, "option redefined `#{i}'"
end
rescue
@canonical_names.clear
@argument_flags.clear
raise
end
#
# Register the option (`i') to the `@canonical_names' and
# `@canonical_names' Hashes.
#
if canonical_name == nil
canonical_name = i
end
@canonical_names[i] = canonical_name
@argument_flags[i] = argument_flag
end
raise ArgumentError, "no option name" if canonical_name == nil
end
return self
end
#
# Set/Unset `quit' mode.
#
attr_writer :quiet
#
# Return the flag of `quiet' mode.
#
attr_reader :quiet
#
# `quiet?' is an alias of `quiet'.
#
alias quiet? quiet
#
# Termintate option processing.
#
def terminate
return if @status == STATUS_TERMINATED
raise RuntimeError, "an error has occured" if @error != nil
@status = STATUS_TERMINATED
@non_option_arguments.reverse_each do |argument|
ARGV.unshift(argument)
end
@canonical_names = nil
@argument_flags = nil
@rest_singles = nil
@non_option_arguments = nil
return self
end
#
# Examine whether option processing is termintated or not.
#
def terminated?
return @status == STATUS_TERMINATED
end
#
# Set an error (protected).
#
def set_error(type, message)
$stderr.print("#{$0}: #{message}\n") if !@quiet
@error = type
@error_message = message
@canonical_names = nil
@argument_flags = nil
@rest_singles = nil
@non_option_arguments = nil
raise type, message
end
protected :set_error
#
# Examine whether an option processing is failed.
#
attr_reader :error
#
# `error?' is an alias of `error'.
#
alias error? error
#
# Return an error message.
#
def error_message
return @error_message
end
#
# Get next option name and its argument as an array.
#
def get
name, argument = nil, ''
#
# Check status.
#
return if @error != nil
case @status
when STATUS_YET
@status = STATUS_STARTED
when STATUS_TERMINATED
return
end
#
# Get next option argument.
#
if 0 < @rest_singles.length
$_ = '-' + @rest_singles
elsif (ARGV.length == 0)
terminate
return nil
elsif @ordering == PERMUTE
while 0 < ARGV.length && ARGV[0] !~ /^-./
@non_option_arguments.push(ARGV.shift)
end
if ARGV.length == 0
terminate
return
end
$_ = ARGV.shift
elsif @ordering == REQUIRE_ORDER
if (ARGV[0] !~ /^-./)
terminate
return nil
end
$_ = ARGV.shift
else
$_ = ARGV.shift
end
#
# Check the special argument `--'.
# `--' indicates the end of the option list.
#
if $_ == '--' && @rest_singles.length == 0
terminate
return nil
end
#
# Check for long and short options.
#
if /^(--[^=]+)/ && @rest_singles.length == 0
#
# This is a long style option, which start with `--'.
#
pattern = $1
if @canonical_names.include?(pattern)
name = pattern
else
#
# The option `name' is not registered in `@canonical_names'.
# It may be an abbreviated.
#
match_count = 0
@canonical_names.each_key do |key|
if key.index(pattern) == 0
name = key
match_count += 1
end
end
if 2 <= match_count
set_error(AmbigousOption, "option `#{$_}' is ambiguous")
elsif match_count == 0
set_error(InvalidOption, "unrecognized option `#{$_}'")
end
end
#
# Check an argument to the option.
#
if @argument_flags[name] == REQUIRED_ARGUMENT
if /=(.*)$/
argument = $1
elsif 0 < ARGV.length
argument = ARGV.shift
else
set_error(MissingArgument, "option `#{$_}' requires an argument")
end
elsif @argument_flags[name] == OPTIONAL_ARGUMENT
if /=(.*)$/
argument = $1
elsif 0 < ARGV.length && ARGV[0] !~ /^-./
argument = ARGV.shift
else
argument = ''
end
elsif /=(.*)$/
set_error(NeedlessArgument,
"option `#{name}' doesn't allow an argument")
end
elsif /^(-(.))(.*)/
#
# This is a short style option, which start with `-' (not `--').
# Short options may be catinated (e.g. `-l -g' is equivalent to
# `-lg').
#
name, ch, @rest_singles = $1, $2, $3
if @canonical_names.include?(name)
#
# The option `name' is found in `@canonical_names'.
# Check its argument.
#
if @argument_flags[name] == REQUIRED_ARGUMENT
if 0 < @rest_singles.length
argument = @rest_singles
@rest_singles = ''
elsif 0 < ARGV.length
argument = ARGV.shift
else
# 1003.2 specifies the format of this message.
set_error(MissingArgument, "option requires an argument -- #{ch}")
end
elsif @argument_flags[name] == OPTIONAL_ARGUMENT
if 0 < @rest_singles.length
argument = @rest_singles
@rest_singles = ''
elsif 0 < ARGV.length && ARGV[0] !~ /^-./
argument = ARGV.shift
else
argument = ''
end
end
else
#
# This is an invalid option.
# 1003.2 specifies the format of this message.
#
if ENV.include?('POSIXLY_CORRECT')
set_error(InvalidOption, "illegal option -- #{ch}")
else
set_error(InvalidOption, "invalid option -- #{ch}")
end
end
else
#
# This is a non-option argument.
# Only RETURN_IN_ORDER falled into here.
#
return '', $_
end
return @canonical_names[name], argument
end
#
# `get_option' is an alias of `get'.
#
alias get_option get
#
# Iterator version of `get'.
#
def each
loop do
name, argument = get_option
break if name == nil
yield name, argument
end
end
#
# `each_option' is an alias of `each'.
#
alias each_option each
end

View file

@ -15,7 +15,7 @@ $RCS_ID=%q$Header$
def isSingle(lopt) def isSingle(lopt)
if lopt.index(":") if lopt.index(":")
if lopt.split(":")[0].length == 1 if lopt.split(":")[0].length == 1
return TRUE return true
end end
end end
return nil return nil
@ -87,13 +87,13 @@ def getopts(single_opts, *options)
return nil return nil
end end
setOption(compare, ARGV[1]) setOption(compare, ARGV[1])
opts[compare] = TRUE opts[compare] = true
ARGV.shift ARGV.shift
count += 1 count += 1
break break
elsif lo == compare elsif lo == compare
setOption(compare, TRUE) setOption(compare, true)
opts[compare] = TRUE opts[compare] = true
count += 1 count += 1
break break
end end
@ -106,19 +106,19 @@ def getopts(single_opts, *options)
for idx in 1..(ARGV[0].length - 1) for idx in 1..(ARGV[0].length - 1)
compare = ARGV[0][idx, 1] compare = ARGV[0][idx, 1]
if single_opts && compare =~ "[" + single_opts + "]" if single_opts && compare =~ "[" + single_opts + "]"
setOption(compare, TRUE) setOption(compare, true)
opts[compare] = TRUE opts[compare] = true
count += 1 count += 1
elsif single_colon != "" && compare =~ "[" + single_colon + "]" elsif single_colon != "" && compare =~ "[" + single_colon + "]"
if ARGV[0][idx..-1].length > 1 if ARGV[0][idx..-1].length > 1
setOption(compare, ARGV[0][(idx + 1)..-1]) setOption(compare, ARGV[0][(idx + 1)..-1])
opts[compare] = TRUE opts[compare] = true
count += 1 count += 1
elsif ARGV.length <= 1 elsif ARGV.length <= 1
return nil return nil
else else
setOption(compare, ARGV[1]) setOption(compare, ARGV[1])
opts[compare] = TRUE opts[compare] = true
ARGV.shift ARGV.shift
count += 1 count += 1
end end
@ -127,7 +127,7 @@ def getopts(single_opts, *options)
end end
else else
compare = ARGV[0] compare = ARGV[0]
opts[compare] = TRUE opts[compare] = true
newargv << ARGV[0] newargv << ARGV[0]
end end

View file

@ -12,9 +12,10 @@ class String
private :original_succ private :original_succ
def mbchar? def mbchar?
if $KCODE =~ /^s/i case $KCODE[0]
when ?s, ?S
self =~ /[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc]/n self =~ /[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc]/n
elsif $KCODE =~ /^e/i when ?e, ?E
self =~ /[\xa1-\xfe][\xa1-\xfe]/n self =~ /[\xa1-\xfe][\xa1-\xfe]/n
else else
false false
@ -22,16 +23,15 @@ class String
end end
def succ def succ
if self[-2] && self[-2] & 0x80 != 0 if self[-2] and self[-2, 2].mbchar?
s = self.dup s = self.dup
s[-1] += 1 s[-1] += 1
s[-1] += 1 if !s.mbchar? s[-1] += 1 unless s[-2, 2].mbchar?
return s return s
else else
original_succ original_succ
end end
end end
alias next succ
def upto(to) def upto(to)
return if self > to return if self > to
@ -58,9 +58,11 @@ class String
return nil return nil
end end
def _expand_ch private
def _expand_ch str
a = [] a = []
self.scan(/(.|\n)-(.|\n)|(.|\n)/) do |r| str.scan(/(.|\n)-(.|\n)|(.|\n)/) do |r|
if $3 if $3
a.push $3 a.push $3
elsif $1.length != $2.length elsif $1.length != $2.length
@ -74,32 +76,35 @@ class String
a a
end end
def expand_ch_hash from, to
h = {}
afrom = _expand_ch(from)
ato = _expand_ch(to)
afrom.each_with_index do |x,i| h[x] = ato[i] || ato[-1] end
h
end
def bsquote(str)
str.gsub(/\\/, '\\\\\\\\')
end
HashCache = {}
TrPatternCache = {}
DeletePatternCache = {}
SqueezePatternCache = {}
public
def tr!(from, to) def tr!(from, to)
return self.delete!(from) if to.length == 0 return self.delete!(from) if to.length == 0
if from =~ /^\^/ pattern = TrPatternCache[from] ||= /[#{bsquote(from)}]/
comp=TRUE if from[0] == ?^
from = $' last = /.$/.match(to)[0]
end self.gsub!(pattern, last)
afrom = from._expand_ch
ato = to._expand_ch
i = 0
if comp
self.gsub!(/(.|\n)/) do |c|
unless afrom.include?(c)
ato[-1]
else
c
end
end
else else
self.gsub!(/(.|\n)/) do |c| h = HashCache[from + "::" + to] ||= expand_ch_hash(from, to)
if i = afrom.index(c) self.gsub!(pattern) do |c| h[c] end
if i < ato.size then ato[i] else ato[-1] end
else
c
end
end
end end
end end
@ -108,22 +113,7 @@ class String
end end
def delete!(del) def delete!(del)
if del =~ /^\^/ self.gsub!(DeletePatternCache[del] ||= /[#{bsquote(del)}]+/, '')
comp=TRUE
del = $'
end
adel = del._expand_ch
if comp
self.gsub!(/(.|\n)/) do |c|
next unless adel.include?(c)
c
end
else
self.gsub!(/(.|\n)/) do |c|
next if adel.include?(c)
c
end
end
end end
def delete(del) def delete(del)
@ -131,27 +121,13 @@ class String
end end
def squeeze!(del=nil) def squeeze!(del=nil)
if del pattern =
if del =~ /^\^/ if del
comp=TRUE SqueezePatternCache[del] ||= /([#{bsquote(del)}])\1+/
del = $'
end
adel = del._expand_ch
if comp
self.gsub!(/(.|\n)\1+/) do
next unless adel.include?($1)
$&
end
else else
for c in adel /(.|\n)\1+/
cq = Regexp.quote(c)
self.gsub!(/#{cq}(#{cq})+/, cq)
end
end end
self self.gsub!(pattern, '\1')
else
self.gsub!(/(.|\n)\1+/, '\1')
end
end end
def squeeze(del=nil) def squeeze(del=nil)
@ -160,30 +136,14 @@ class String
def tr_s!(from, to) def tr_s!(from, to)
return self.delete!(from) if to.length == 0 return self.delete!(from) if to.length == 0
if from =~ /^\^/
comp=TRUE pattern = SqueezePatternCache[from] ||= /([#{bsquote(from)}])\1+"/
from = $' if from[0] == ?^
end last = /.$/.match(to)[0]
afrom = from._expand_ch self.gsub!(pattern, last)
ato = to._expand_ch else
i = 0 h = HashCache[from + "::" + to] ||= expand_ch_hash(from, to)
c = nil self.gsub!(pattern) do h[$1] end
last = nil
self.gsub!(/(.|\n)/) do |c|
if comp
unless afrom.include?(c)
ato[-1]
else
c
end
elsif i = afrom.index(c)
c = if i < ato.size then ato[i] else ato[-1] end
next if c == last
last = c
else
last = nil
c
end
end end
end end
@ -191,18 +151,17 @@ class String
(str = self.dup).tr_s!(from,to) or str (str = self.dup).tr_s!(from,to) or str
end end
alias original_chop! chop!
private :original_chop!
def chop! def chop!
if self =~ /(.)$/ and $1.size == 2 self.gsub!(/(?:.|\r?\n)\z/, '')
original_chop!
end
original_chop!
end end
def chop def chop
(str = self.dup).chop! or str (str = self.dup).chop! or str
end end
def jcount(str)
self.delete("^#{str}").jlength
end
end end
$VERBOSE = $vsave $VERBOSE = $vsave

View file

@ -43,6 +43,6 @@ class Mail
end end
def [](field) def [](field)
@header[field] @header[field.capitalize]
end end
end end

View file

@ -121,7 +121,7 @@ class Bignum
end end
class Rational class Rational
Unify = TRUE Unify = true
alias power! ** alias power! **
@ -304,6 +304,6 @@ module Math
end end
class Complex class Complex
Unify = TRUE Unify = true
end end

View file

@ -1,8 +1,9 @@
#!/usr/local/bin/ruby
# #
# matrix.rb - # matrix.rb -
# $Release Version: 1.0$ # $Release Version: 1.0$
# $Revision: 1.6 $ # $Revision: 1.8 $
# $Date: 1998/07/31 03:39:49 $ # $Date: 1999/02/17 12:34:19 $
# Original Version from Smalltalk-80 version # Original Version from Smalltalk-80 version
# on July 23, 1985 at 8:37:17 am # on July 23, 1985 at 8:37:17 am
# by Keiju ISHITSUKA # by Keiju ISHITSUKA
@ -17,6 +18,8 @@
# : # :
# rown] # rown]
# #
# column: Îó
# row: ¹Ô
# #
# module ExceptionForMatrix:: # module ExceptionForMatrix::
# Exceptions: # Exceptions:
@ -36,7 +39,7 @@
# creates a matrix where `rows' indicates rows. # creates a matrix where `rows' indicates rows.
# `rows' is an array of arrays, # `rows' is an array of arrays,
# e.g, Matrix[[11, 12], [21, 22]] # e.g, Matrix[[11, 12], [21, 22]]
# Matrix.rows(rows, copy = TRUE) # Matrix.rows(rows, copy = true)
# creates a matrix where `rows' indicates rows. # creates a matrix where `rows' indicates rows.
# if optional argument `copy' is false, use the array as # if optional argument `copy' is false, use the array as
# internal structure of the metrix without copying. # internal structure of the metrix without copying.
@ -142,7 +145,7 @@
# #
# INSTANCE CREATION: # INSTANCE CREATION:
# Vector.[](*array) # Vector.[](*array)
# Vector.elements(array, copy = TRUE) # Vector.elements(array, copy = true)
# ACCSESSING: # ACCSESSING:
# [](i) # [](i)
# size # size
@ -173,29 +176,29 @@
require "e2mmap.rb" require "e2mmap.rb"
module ExceptionForMatrix module ExceptionForMatrix
Exception2MessageMapper.extend_to(binding) extend Exception2MessageMapper
def_e2message(TypeError, "wrong argument type %s (expected %s)") def_e2message(TypeError, "wrong argument type %s (expected %s)")
def_e2message(ArgumentError, "Wrong # of arguments(%d for %d)") def_e2message(ArgumentError, "Wrong # of arguments(%d for %d)")
def_exception("ErrDimensionMismatch", "\#{self.type} dimemsion mismatch") def_exception("ErrDimensionMismatch", "\#{self.name} dimension mismatch")
def_exception("ErrNotRegular", "Not Regular Matrix") def_exception("ErrNotRegular", "Not Regular Matrix")
def_exception("ErrOperationNotDefined", "This operation(%s) can\\'t defined") def_exception("ErrOperationNotDefined", "This operation(%s) can\\'t defined")
end end
class Matrix class Matrix
@RCS_ID='-$Id: matrix.rb,v 1.6 1998/07/31 03:39:49 keiju Exp keiju $-' @RCS_ID='-$Id: matrix.rb,v 1.8 1999/02/17 12:34:19 keiju Exp keiju $-'
# extend Exception2MessageMapper
include ExceptionForMatrix include ExceptionForMatrix
# instance creations # instance creations
private_class_method :new private_class_method :new
def Matrix.[](*rows) def Matrix.[](*rows)
new(:init_rows, rows, FALSE) new(:init_rows, rows, false)
end end
def Matrix.rows(rows, copy = TRUE) def Matrix.rows(rows, copy = true)
new(:init_rows, rows, copy) new(:init_rows, rows, copy)
end end
@ -207,7 +210,7 @@ class Matrix
columns[j][i] columns[j][i]
} }
} }
Matrix.rows(rows, FALSE) Matrix.rows(rows, false)
end end
def Matrix.diagonal(*values) def Matrix.diagonal(*values)
@ -218,8 +221,7 @@ class Matrix
row[j] = values[j] row[j] = values[j]
row row
} }
self rows(rows, false)
rows(rows, FALSE)
end end
def Matrix.scalar(n, value) def Matrix.scalar(n, value)
@ -241,11 +243,11 @@ class Matrix
def Matrix.row_vector(row) def Matrix.row_vector(row)
case row case row
when Vector when Vector
Matrix.rows([row.to_a], FALSE) Matrix.rows([row.to_a], false)
when Array when Array
Matrix.rows([row.dup], FALSE) Matrix.rows([row.dup], false)
else else
Matrix.row([[row]], FALSE) Matrix.row([[row]], false)
end end
end end
@ -310,13 +312,13 @@ class Matrix
|i| |i|
@rows[i][j] @rows[i][j]
} }
Vector.elements(col, FALSE) Vector.elements(col, false)
end end
end end
def collect def collect
rows = @rows.collect{|row| row.collect{|e| yield e}} rows = @rows.collect{|row| row.collect{|e| yield e}}
Matrix.rows(rows, FALSE) Matrix.rows(rows, false)
end end
alias map collect alias map collect
@ -337,14 +339,14 @@ class Matrix
from_col = param[2] from_col = param[2]
size_col = param[3] size_col = param[3]
else else
Matrix.fail ArgumentError, param.inspect Matrix.Raise ArgumentError, param.inspect
end end
rows = @rows[from_row, size_row].collect{ rows = @rows[from_row, size_row].collect{
|row| |row|
row[from_col, size_col] row[from_col, size_col]
} }
Matrix.rows(rows, FALSE) Matrix.rows(rows, false)
end end
# TESTING # TESTING
@ -362,20 +364,20 @@ class Matrix
# COMPARING # COMPARING
def ==(other) def ==(other)
return FALSE unless Matrix === other return false unless Matrix === other
other.compare_by_row_vectors(@rows) other.compare_by_row_vectors(@rows)
end end
alias eql? == alias eql? ==
def compare_by_row_vectors(rows) def compare_by_row_vectors(rows)
return FALSE unless @rows.size == rows.size return false unless @rows.size == rows.size
0.upto(@rows.size - 1) do 0.upto(@rows.size - 1) do
|i| |i|
return FALSE unless @rows[i] == rows[i] return false unless @rows[i] == rows[i]
end end
TRUE true
end end
def clone def clone
@ -404,13 +406,13 @@ class Matrix
e * m e * m
} }
} }
return Matrix.rows(rows, FALSE) return Matrix.rows(rows, false)
when Vector when Vector
m = Matrix.column_vector(m) m = Matrix.column_vector(m)
r = self * m r = self * m
return r.column(0) return r.column(0)
when Matrix when Matrix
Matrix.fail ErrDimensionMismatch if column_size != m.row_size Matrix.Raise ErrDimensionMismatch if column_size != m.row_size
rows = (0 .. row_size - 1).collect { rows = (0 .. row_size - 1).collect {
|i| |i|
@ -424,7 +426,7 @@ class Matrix
vij vij
} }
} }
return Matrix.rows(rows, FALSE) return Matrix.rows(rows, false)
else else
x, y = m.coerce(self) x, y = m.coerce(self)
return x * y return x * y
@ -434,7 +436,7 @@ class Matrix
def +(m) def +(m)
case m case m
when Numeric when Numeric
Matrix.fail ErrOperationNotDefined, "+" Matrix.Raise ErrOperationNotDefined, "+"
when Vector when Vector
m = Matrix.column_vector(m) m = Matrix.column_vector(m)
when Matrix when Matrix
@ -443,7 +445,7 @@ class Matrix
return x + y return x + y
end end
Matrix.fail ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size Matrix.Raise ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size
rows = (0 .. row_size - 1).collect { rows = (0 .. row_size - 1).collect {
|i| |i|
@ -452,13 +454,13 @@ class Matrix
self[i, j] + m[i, j] self[i, j] + m[i, j]
} }
} }
Matrix.rows(rows, FALSE) Matrix.rows(rows, false)
end end
def -(m) def -(m)
case m case m
when Numeric when Numeric
Matrix.fail ErrOperationNotDefined, "-" Matrix.Raise ErrOperationNotDefined, "-"
when Vector when Vector
m = Matrix.column_vector(m) m = Matrix.column_vector(m)
when Matrix when Matrix
@ -467,7 +469,7 @@ class Matrix
return x - y return x - y
end end
Matrix.fail ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size Matrix.Raise ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size
rows = (0 .. row_size - 1).collect { rows = (0 .. row_size - 1).collect {
|i| |i|
@ -476,7 +478,7 @@ class Matrix
self[i, j] - m[i, j] self[i, j] - m[i, j]
} }
} }
Matrix.rows(rows, FALSE) Matrix.rows(rows, false)
end end
def /(other) def /(other)
@ -489,7 +491,7 @@ class Matrix
e / other e / other
} }
} }
return Matrix.rows(rows, FALSE) return Matrix.rows(rows, false)
when Matrix when Matrix
return self * other.inverse return self * other.inverse
else else
@ -499,7 +501,7 @@ class Matrix
end end
def inverse def inverse
Matrix.fail ErrDimensionMismatch unless square? Matrix.Raise ErrDimensionMismatch unless square?
Matrix.I(row_size).inverse_from(self) Matrix.I(row_size).inverse_from(self)
end end
alias inv inverse alias inv inverse
@ -512,7 +514,7 @@ class Matrix
if (akk = a[k][k]) == 0 if (akk = a[k][k]) == 0
i = k i = k
begin begin
fail ErrNotRegular if (i += 1) > size Matrix.Raise ErrNotRegular if (i += 1) > size
end while a[i][k] == 0 end while a[i][k] == 0
a[i], a[k] = a[k], a[i] a[i], a[k] = a[k], a[i]
@rows[i], @rows[k] = @rows[k], @rows[i] @rows[i], @rows[k] = @rows[k], @rows[i]
@ -568,9 +570,9 @@ class Matrix
end end
z z
elsif other.kind_of?(Float) || defined?(Rational) && other.kind_of?(Rational) elsif other.kind_of?(Float) || defined?(Rational) && other.kind_of?(Rational)
fail ErrOperationNotDefined, "**" Matrix.Raise ErrOperationNotDefined, "**"
else else
fail ErrOperationNotDefined, "**" Matrix.Raise ErrOperationNotDefined, "**"
end end
end end
@ -618,10 +620,10 @@ class Matrix
begin begin
if (akk = a[k][k]) == 0 if (akk = a[k][k]) == 0
i = -1 i = -1
nothing = FALSE nothing = false
begin begin
if (i += 1) > column_size - 1 if (i += 1) > column_size - 1
nothing = TRUE nothing = true
break break
end end
end while a[i][k] == 0 end while a[i][k] == 0
@ -663,6 +665,8 @@ class Matrix
case other case other
when Numeric when Numeric
return Scalar.new(other), self return Scalar.new(other), self
else
raise TypeError, "#{type} can't be coerced into #{other.type}"
end end
end end
@ -725,7 +729,7 @@ class Matrix
when Numeric when Numeric
Scalar.new(@value + other) Scalar.new(@value + other)
when Vector, Matrix when Vector, Matrix
Scalar.fail WrongArgType, other.type, "Numeric or Scalar" Scalar.Raise WrongArgType, other.type, "Numeric or Scalar"
when Scalar when Scalar
Scalar.new(@value + other.value) Scalar.new(@value + other.value)
else else
@ -739,7 +743,7 @@ class Matrix
when Numeric when Numeric
Scalar.new(@value - other) Scalar.new(@value - other)
when Vector, Matrix when Vector, Matrix
Scalar.fail WrongArgType, other.type, "Numeric or Scalar" Scalar.Raise WrongArgType, other.type, "Numeric or Scalar"
when Scalar when Scalar
Scalar.new(@value - other.value) Scalar.new(@value - other.value)
else else
@ -765,7 +769,7 @@ class Matrix
when Numeric when Numeric
Scalar.new(@value / other) Scalar.new(@value / other)
when Vector when Vector
Scalar.fail WrongArgType, other.type, "Numeric or Scalar or Matrix" Scalar.Raise WrongArgType, other.type, "Numeric or Scalar or Matrix"
when Matrix when Matrix
self * _M.inverse self * _M.inverse
else else
@ -779,7 +783,7 @@ class Matrix
when Numeric when Numeric
Scalar.new(@value ** other) Scalar.new(@value ** other)
when Vector when Vector
Scalar.fail WrongArgType, other.type, "Numeric or Scalar or Matrix" Scalar.Raise WrongArgType, other.type, "Numeric or Scalar or Matrix"
when Matrix when Matrix
other.powered_by(self) other.powered_by(self)
else else
@ -802,10 +806,10 @@ class Vector
private_class_method :new private_class_method :new
def Vector.[](*array) def Vector.[](*array)
new(:init_elements, array, FALSE) new(:init_elements, array, copy = false)
end end
def Vector.elements(array, copy = TRUE) def Vector.elements(array, copy = true)
new(:init_elements, array, copy) new(:init_elements, array, copy)
end end
@ -833,7 +837,7 @@ class Vector
# ENUMRATIONS # ENUMRATIONS
def each2(v) def each2(v)
Vector.fail ErrDimensionMismatch if size != v.size Vector.Raise ErrDimensionMismatch if size != v.size
0.upto(size - 1) do 0.upto(size - 1) do
|i| |i|
yield @elements[i], v[i] yield @elements[i], v[i]
@ -841,7 +845,7 @@ class Vector
end end
def collect2(v) def collect2(v)
Vector.fail ErrDimensionMismatch if size != v.size Vector.Raise ErrDimensionMismatch if size != v.size
(0 .. size - 1).collect do (0 .. size - 1).collect do
|i| |i|
yield @elements[i], v[i] yield @elements[i], v[i]
@ -850,7 +854,7 @@ class Vector
# COMPARING # COMPARING
def ==(other) def ==(other)
return FALSE unless Vector === other return false unless Vector === other
other.compare_by(@elements) other.compare_by(@elements)
end end
@ -870,15 +874,15 @@ class Vector
# ARITHMETIC # ARITHMETIC
def *(x) "is matrix or number" def *(x) # is matrix or number
case x case x
when Numeric when Numeric
els = @elements.collect{|e| e * x} els = @elements.collect{|e| e * x}
Vector.elements(els, FALSE) Vector.elements(els, false)
when Matrix when Matrix
self.covector * x self.covector * x
else else
s, x = X.corece(self) s, x = X.coerce(self)
s * x s * x
end end
end end
@ -886,16 +890,16 @@ class Vector
def +(v) def +(v)
case v case v
when Vector when Vector
Vector.fail ErrDimensionMismatch if size != v.size Vector.Raise ErrDimensionMismatch if size != v.size
els = collect2(v) { els = collect2(v) {
|v1, v2| |v1, v2|
v1 + v2 v1 + v2
} }
Vector.elements(els, FALSE) Vector.elements(els, false)
when Matrix when Matrix
Matrix.column_vector(self) + v Matrix.column_vector(self) + v
else else
s, x = v.corece(self) s, x = v.coerce(self)
s + x s + x
end end
end end
@ -903,16 +907,16 @@ class Vector
def -(v) def -(v)
case v case v
when Vector when Vector
Vector.fail ErrDimensionMismatch if size != v.size Vector.Raise ErrDimensionMismatch if size != v.size
els = collect2(v) { els = collect2(v) {
|v1, v2| |v1, v2|
v1 - v2 v1 - v2
} }
Vector.elements(els, FALSE) Vector.elements(els, false)
when Matrix when Matrix
Matrix.column_vector(self) - v Matrix.column_vector(self) - v
else else
s, x = v.corece(self) s, x = v.coerce(self)
s - x s - x
end end
end end
@ -920,7 +924,7 @@ class Vector
# VECTOR FUNCTIONS # VECTOR FUNCTIONS
def inner_product(v) def inner_product(v)
Vector.fail ErrDimensionMismatch if size != v.size Vector.Raise ErrDimensionMismatch if size != v.size
p = 0 p = 0
each2(v) { each2(v) {
@ -935,7 +939,7 @@ class Vector
|v| |v|
yield v yield v
} }
Vector.elements(els, FALSE) Vector.elements(els, false)
end end
alias map collect alias map collect
@ -944,7 +948,7 @@ class Vector
|v1, v2| |v1, v2|
yield v1, v2 yield v1, v2
} }
Vector.elements(els, FALSE) Vector.elements(els, false)
end end
def r def r
@ -980,6 +984,8 @@ class Vector
case other case other
when Numeric when Numeric
return Scalar.new(other), self return Scalar.new(other), self
else
raise TypeError, "#{type} can't be coerced into #{other.type}"
end end
end end

View file

@ -6,7 +6,9 @@ require 'find'
include Config include Config
$found = false; SRC_EXT = ["c", "cc", "m", "cxx", "cpp", "C"]
$cache_mod = false
$lib_cache = {} $lib_cache = {}
$lib_found = {} $lib_found = {}
$func_cache = {} $func_cache = {}
@ -31,14 +33,8 @@ if File.exist?($config_cache) then
end end
$srcdir = CONFIG["srcdir"] $srcdir = CONFIG["srcdir"]
$libdir = CONFIG["libdir"]+"/"+CONFIG["ruby_install_name"] $libdir = CONFIG["libdir"]+"/ruby/"+CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
$archdir = $libdir+"/"+CONFIG["arch"] $archdir = $libdir+"/"+CONFIG["arch"]
$install = CONFIG["INSTALL_PROGRAM"]
$install_data = CONFIG["INSTALL_DATA"]
if $install !~ /^\// then
$install = CONFIG["srcdir"]+"/"+$install
$install_data = CONFIG["srcdir"]+"/"+$install_data
end
if File.exist? $archdir + "/ruby.h" if File.exist? $archdir + "/ruby.h"
$hdrdir = $archdir $hdrdir = $archdir
@ -48,18 +44,22 @@ else
STDERR.print "can't find header files for ruby.\n" STDERR.print "can't find header files for ruby.\n"
exit 1 exit 1
end end
$topdir = $hdrdir
$hdrdir.gsub!('/', '\\') if RUBY_PLATFORM =~ /mswin32/
CFLAGS = CONFIG["CFLAGS"] CFLAGS = CONFIG["CFLAGS"]
if PLATFORM == "m68k-human" if RUBY_PLATFORM == "m68k-human"
CFLAGS.gsub!(/-c..-stack=[0-9]+ */, '') CFLAGS.gsub!(/-c..-stack=[0-9]+ */, '')
elsif RUBY_PLATFORM =~ /-nextstep|-rhapsody/
CFLAGS.gsub!( /-arch\s\w*/, '' )
end end
if /win32|djgpp|mingw32|m68k-human/i =~ PLATFORM if /win32|djgpp|mingw32|m68k-human|i386-os2_emx/i =~ RUBY_PLATFORM
$null = open("nul", "w") $null = open("nul", "w")
else else
$null = open("/dev/null", "w") $null = open("/dev/null", "w")
end end
LINK = "#{CONFIG['CC']} -o conftest -I#{$srcdir} -I#{CONFIG['includedir']} #{CFLAGS} %s #{CONFIG['LDFLAGS']} %s conftest.c #{CONFIG['LIBS']} %s" LINK = "#{CONFIG['CC']} -o conftest -I#{$hdrdir} #{CFLAGS} -I#{CONFIG['includedir']} %s #{CONFIG['LDFLAGS']} %s conftest.c %s %s #{CONFIG['LIBS']}"
CPP = "#{CONFIG['CPP']} -E -I#{$srcdir} -I#{CONFIG['includedir']} #{CFLAGS} %s conftest.c" CPP = "#{CONFIG['CPP']} -E -I#{$hdrdir} #{CFLAGS} -I#{CONFIG['includedir']} %s %s conftest.c"
$orgerr = $stderr.dup $orgerr = $stderr.dup
$orgout = $stdout.dup $orgout = $stdout.dup
@ -76,29 +76,84 @@ def xsystem command
return r return r
end end
def try_link(libs) def try_link0(src, opt="")
xsystem(format(LINK, $CFLAGS, $LDFLAGS, libs)) cfile = open("conftest.c", "w")
cfile.print src
cfile.close
xsystem(format(LINK, $CFLAGS, $LDFLAGS, opt, $LOCAL_LIBS))
end end
def try_cpp def try_link(src, opt="")
xsystem(format(CPP, $CFLAGS)) begin
try_link0(src, opt)
ensure
system "rm -f conftest*"
end
end end
def install_rb(mfile) def try_cpp(src, opt="")
cfile = open("conftest.c", "w")
cfile.print src
cfile.close
begin
xsystem(format(CPP, $CFLAGS, opt))
ensure
system "rm -f conftest*"
end
end
def egrep_cpp(pat, src, opt="")
cfile = open("conftest.c", "w")
cfile.print src
cfile.close
begin
xsystem(format(CPP+"|egrep #{pat}", $CFLAGS, opt))
ensure
system "rm -f conftest*"
end
end
def try_run(src, opt="")
begin
if try_link0(src, opt)
if xsystem("./conftest")
true
else
false
end
else
nil
end
ensure
system "rm -f conftest*"
end
end
def install_rb(mfile, srcdir = nil)
libdir = "lib"
libdir = srcdir + "/" + libdir if srcdir
path = [] path = []
dir = [] dir = []
Find.find("lib") do |f| Find.find(libdir) do |f|
next unless /\.rb$/ =~ f next unless /\.rb$/ =~ f
f = f[4..-1] f = f[libdir.length+1..-1]
path.push f path.push f
dir |= File.dirname(f) dir |= File.dirname(f)
end end
for f in dir for f in dir
next if f == "." next if f == "."
mfile.printf "\t@test -d $(libdir)/%s || mkdir $(libdir)/%s\n", f, f mfile.printf "\t@$(RUBY) -r ftools -e 'File::makedirs(*ARGV)' $(libdir)/%s\n", f
end end
for f in path for f in path
mfile.printf "\t$(INSTALL_DATA) lib/%s $(libdir)/%s\n", f, f mfile.printf "\t@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0644, true)' lib/%s $(libdir)/%s\n", f, f
end
end
def append_library(libs, lib)
if /mswin32/ =~ RUBY_PLATFORM
lib + ".lib " + libs
else
"-l" + lib + " " + libs
end end
end end
@ -107,55 +162,75 @@ def have_library(lib, func="main")
STDOUT.flush STDOUT.flush
if $lib_cache[lib] if $lib_cache[lib]
if $lib_cache[lib] == "yes" if $lib_cache[lib] == "yes"
if $libs $libs = append_library($libs, lib)
$libs = "-l" + lib + " " + $libs
else
$libs = "-l" + lib
end
print "(cached) yes\n" print "(cached) yes\n"
return TRUE return true
else else
print "(cached) no\n" print "(cached) no\n"
return FALSE return false
end end
end end
if func && func != "" if func && func != ""
cfile = open("conftest.c", "w") libs = append_library($libs, lib)
cfile.printf "\ if /mswin32/ =~ RUBY_PLATFORM
r = try_link(<<"SRC", libs)
#include <windows.h>
#include <winsock.h>
int main() { return 0; } int main() { return 0; }
int t() { %s(); return 0; } int t() { #{func}(); return 0; }
", func SRC
cfile.close unless r
r = try_link(<<"SRC", libs)
begin #include <windows.h>
if $libs #include <winsock.h>
libs = "-l" + lib + " " + $libs int main() { return 0; }
else int t() { void ((*p)()); p = (void ((*)()))#{func}; return 0; }
libs = "-l" + lib SRC
end end
unless try_link(libs) else
$lib_cache[lib] = 'no' r = try_link(<<"SRC", libs)
$cache_mod = TRUE int main() { return 0; }
print "no\n" int t() { #{func}(); return 0; }
return FALSE SRC
end end
ensure unless r
system "rm -f conftest*" $lib_cache[lib] = 'no'
$cache_mod = true
print "no\n"
return false
end end
else else
if $libs libs = append_library($libs, lib)
libs = "-l" + lib + " " + $libs
else
libs = "-l" + lib
end
end end
$libs = libs $libs = libs
$lib_cache[lib] = 'yes' $lib_cache[lib] = 'yes'
$cache_mod = TRUE $cache_mod = true
print "yes\n" print "yes\n"
return TRUE return true
end
def find_library(lib, func, *paths)
printf "checking for %s() in -l%s... ", func, lib
STDOUT.flush
ldflags = $LDFLAGS
libs = append_library($libs, lib)
until try_link(<<"SRC", libs)
int main() { return 0; }
int t() { #{func}(); return 0; }
SRC
if paths.size == 0
$LDFLAGS = ldflags
print "no\n"
return false
end
$LDFLAGS = ldflags + " -L"+paths.shift
end
$libs = libs
print "yes\n"
return true
end end
def have_func(func) def have_func(func)
@ -165,39 +240,47 @@ def have_func(func)
if $func_cache[func] == "yes" if $func_cache[func] == "yes"
$defs.push(format("-DHAVE_%s", func.upcase)) $defs.push(format("-DHAVE_%s", func.upcase))
print "(cached) yes\n" print "(cached) yes\n"
return TRUE return true
else else
print "(cached) no\n" print "(cached) no\n"
return FALSE return false
end end
end end
cfile = open("conftest.c", "w")
cfile.printf "\
char %s();
int main() { return 0; }
int t() { %s(); return 0; }
", func, func
cfile.close
libs = $libs libs = $libs
libs = "" if libs == nil
begin if /mswin32/ =~ RUBY_PLATFORM
unless try_link(libs) r = try_link(<<"SRC", libs)
$func_found[func] = 'no' #include <windows.h>
$found = TRUE #include <winsock.h>
print "no\n" int main() { return 0; }
return FALSE int t() { #{func}(); return 0; }
SRC
unless r
r = try_link(<<"SRC", libs)
#include <windows.h>
#include <winsock.h>
int main() { return 0; }
int t() { void ((*p)()); p = (void ((*)()))#{func}; return 0; }
SRC
end end
ensure else
system "rm -f conftest*" r = try_link(<<"SRC", libs)
int main() { return 0; }
int t() { #{func}(); return 0; }
SRC
end
unless r
$func_found[func] = 'no'
$cache_mod = true
print "no\n"
return false
end end
$defs.push(format("-DHAVE_%s", func.upcase)) $defs.push(format("-DHAVE_%s", func.upcase))
$func_found[func] = 'yes' $func_found[func] = 'yes'
$found = TRUE $cache_mod = true
print "yes\n" print "yes\n"
return TRUE return true
end end
def have_header(header) def have_header(header)
@ -208,35 +291,59 @@ def have_header(header)
header.tr!("a-z./\055", "A-Z___") header.tr!("a-z./\055", "A-Z___")
$defs.push(format("-DHAVE_%s", header)) $defs.push(format("-DHAVE_%s", header))
print "(cached) yes\n" print "(cached) yes\n"
return TRUE return true
else else
print "(cached) no\n" print "(cached) no\n"
return FALSE return false
end end
end end
cfile = open("conftest.c", "w") unless try_cpp(<<"SRC")
cfile.printf "\ #include <#{header}>
#include <%s> SRC
", header $hdr_found[header] = 'no'
cfile.close $cache_mod = true
print "no\n"
begin return false
unless try_cpp
$hdr_found[header] = 'no'
$found = TRUE
print "no\n"
return FALSE
end
ensure
system "rm -f conftest*"
end end
$hdr_found[header] = 'yes' $hdr_found[header] = 'yes'
header.tr!("a-z./\055", "A-Z___") header.tr!("a-z./\055", "A-Z___")
$defs.push(format("-DHAVE_%s", header)) $defs.push(format("-DHAVE_%s", header))
$found = TRUE $cache_mod = true
print "yes\n" print "yes\n"
return TRUE return true
end
def arg_config(config, default=nil)
unless defined? $configure_args
$configure_args = {}
for arg in CONFIG["configure_args"].split + ARGV
next unless /^--/ =~ arg
if /=/ =~ arg
$configure_args[$`] = $'
else
$configure_args[arg] = true
end
end
end
$configure_args.fetch(config, default)
end
def with_config(config, default=nil)
unless /^--with-/ =~ config
config = '--with-' + config
end
arg_config(config, default)
end
def enable_config(config, default=nil)
if arg_config("--enable-"+config, default)
true
elsif arg_config("--disable-"+config, false)
false
else
default
end
end end
def create_header() def create_header()
@ -252,28 +359,58 @@ def create_header()
end end
end end
def dir_config(target)
dir = with_config("%s-dir"%target)
if dir
idir = " -I"+dir+"/include"
ldir = " -L"+dir+"/lib"
end
unless idir
dir = with_config("%s-include"%target)
idir = " -I"+dir if dir
end
unless ldir
dir = with_config("%s-lib"%target)
ldir = " -L"+dir if dir
end
$CFLAGS += idir if idir
$LDFLAGS += ldir if ldir
end
def create_makefile(target) def create_makefile(target)
print "creating Makefile\n" print "creating Makefile\n"
system "rm -f conftest*"
STDOUT.flush STDOUT.flush
if $libs and CONFIG["DLEXT"] == "o" if CONFIG["DLEXT"] == $OBJEXT
libs = $libs.split libs = $libs.split
for lib in libs for lib in libs
lib.sub!(/-l(.*)/, '"lib\1.a"') lib.sub!(/-l(.*)/, '"lib\1.a"')
end end
$defs.push(format("-DEXTLIB='%s'", libs.join(","))) $defs.push(format("-DEXTLIB='%s'", libs.join(",")))
end end
$libs = "" unless $libs
$DLDFLAGS = CONFIG["DLDFLAGS"] $DLDFLAGS = CONFIG["DLDFLAGS"]
if PLATFORM =~ /beos/ if RUBY_PLATFORM =~ /beos/
$libs = $libs + " -lruby" $libs = $libs + " -lruby"
$DLDFLAGS = $DLDFLAGS + " -L" + CONFIG["prefix"] + "/lib" $DLDFLAGS = $DLDFLAGS + " -L" + CONFIG["prefix"] + "/lib"
end end
defflag = ''
if RUBY_PLATFORM =~ /cygwin/
if File.exist? target + ".def"
defflag = "--def=" + target + ".def"
end
$libs = $libs + " " + CONFIG["LIBRUBYARG"]
$DLDFLAGS = $DLDFLAGS + " -L$(topdir)"
end
unless $objs then unless $objs then
$objs = Dir["*.{c,cc}"] $objs = []
for f in $objs for f in Dir["*.{#{SRC_EXT.join(%q{,})}}"]
f.sub!(/\.(c|cc)$/, ".o") f = File.basename(f)
f.sub!(/(#{SRC_EXT.join(%q{|})})$/, $OBJEXT)
$objs.push f
end end
end end
$objs = $objs.join(" ") $objs = $objs.join(" ")
@ -285,15 +422,15 @@ SHELL = /bin/sh
#### Start of system configuration section. #### #### Start of system configuration section. ####
srcdir = #{$srcdir} srcdir = #{$srcdir}
topdir = #{$topdir}
hdrdir = #{$hdrdir} hdrdir = #{$hdrdir}
CC = #{CONFIG["CC"]} CC = #{CONFIG["CC"]}
prefix = #{CONFIG["prefix"]} CFLAGS = #{CONFIG["CCDLFLAGS"]} -I$(hdrdir) #{CFLAGS} #{$CFLAGS} -I#{CONFIG["includedir"]} #{$defs.join(" ")}
CFLAGS = #{CONFIG["CCDLFLAGS"]} -I$(hdrdir) -I#{CONFIG["includedir"]} #{CFLAGS} #{$CFLAGS} #{$defs.join(" ")}
CXXFLAGS = $(CFLAGS) CXXFLAGS = $(CFLAGS)
DLDFLAGS = #{$DLDFLAGS} #{$LDFLAGS} DLDFLAGS = #{$DLDFLAGS} #{$LDFLAGS}
LDSHARED = #{CONFIG["LDSHARED"]} LDSHARED = #{CONFIG["LDSHARED"]} #{defflag}
prefix = #{CONFIG["prefix"]} prefix = #{CONFIG["prefix"]}
exec_prefix = #{CONFIG["exec_prefix"]} exec_prefix = #{CONFIG["exec_prefix"]}
@ -302,49 +439,47 @@ archdir = #{$archdir}
#### End of system configuration section. #### #### End of system configuration section. ####
LOCAL_LIBS = #{$local_libs} LOCAL_LIBS = #{$LOCAL_LIBS} #{$local_flags}
LIBS = #{$libs} LIBS = #{$libs}
OBJS = #{$objs} OBJS = #{$objs}
TARGET = #{target}.#{CONFIG["DLEXT"]} TARGET = #{target}
DLLIB = $(TARGET).#{CONFIG["DLEXT"]}
INSTALL = #{$install} RUBY = #{CONFIG["ruby_install_name"]}
INSTALL_DATA = #{$install_data}
binsuffix = #{CONFIG["binsuffix"]} EXEEXT = #{CONFIG["EXEEXT"]}
all: $(TARGET) all: $(DLLIB)
clean:; @rm -f *.o *.so *.sl clean:; @rm -f *.#{$OBJEXT} *.so *.sl *.a $(DLLIB)
@rm -f $(TARGET).lib $(TARGET).exp
@rm -f Makefile extconf.h conftest.* @rm -f Makefile extconf.h conftest.*
@rm -f core ruby$(binsuffix) *~ @rm -f core ruby$(EXEEXT) *~
realclean: clean realclean: clean
install: $(archdir)/$(TARGET) install: $(archdir)/$(DLLIB)
$(archdir)/$(TARGET): $(TARGET) $(archdir)/$(DLLIB): $(DLLIB)
@test -d $(libdir) || mkdir $(libdir) @$(RUBY) -r ftools -e 'File::makedirs(*ARGV)' $(libdir) $(archdir)
@test -d $(archdir) || mkdir $(archdir) @$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0555, true)' $(DLLIB) $(archdir)/$(DLLIB)
$(INSTALL) $(TARGET) $(archdir)/$(TARGET)
EOMF EOMF
install_rb(mfile) install_rb(mfile)
mfile.printf "\n" mfile.printf "\n"
if CONFIG["DLEXT"] != "o" if CONFIG["DLEXT"] != $OBJEXT
mfile.printf <<EOMF mfile.printf <<EOMF
$(TARGET): $(OBJS) $(DLLIB): $(OBJS)
$(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LIBS) $(LOCAL_LIBS) $(LDSHARED) $(DLDFLAGS) -o $(DLLIB) $(OBJS) $(LIBS) $(LOCAL_LIBS)
EOMF EOMF
elsif not File.exist?(target + ".c") and not File.exist?(target + ".cc") or elsif not File.exist?(target + ".c") and not File.exist?(target + ".cc")
mfile.print "$(TARGET): $(OBJS)\n" mfile.print "$(DLLIB): $(OBJS)\n"
case PLATFORM case RUBY_PLATFORM
when "m68k-human" when "m68k-human"
mfile.printf "ar cru $(TARGET) $(OBJS)\n" mfile.printf "ar cru $(DLLIB) $(OBJS)\n"
when /-nextstep/
mfile.printf "cc -r $(CFLAGS) -o $(TARGET) $(OBJS)\n"
else else
mfile.printf "ld $(DLDFLAGS) -r -o $(TARGET) $(OBJS)\n" mfile.printf "ld $(DLDFLAGS) -r -o $(DLLIB) $(OBJS)\n"
end end
end end
@ -352,13 +487,13 @@ EOMF
dfile = open("depend", "r") dfile = open("depend", "r")
mfile.printf "###\n" mfile.printf "###\n"
while line = dfile.gets() while line = dfile.gets()
mfile.print line mfile.printf "%s", line.gsub(/\.o/, ".#{$OBJEXT}")
end end
dfile.close dfile.close
end end
mfile.close mfile.close
if $found if $cache_mod
begin begin
f = open($config_cache, "w") f = open($config_cache, "w")
for k,v in $lib_cache for k,v in $lib_cache
@ -384,18 +519,47 @@ EOMF
end end
end end
if PLATFORM =~ /beos/ if RUBY_PLATFORM =~ /beos/
print "creating ruby.def\n" if RUBY_PLATFORM =~ /^powerpc/ then
open("ruby.def", "w") do |file| deffilename = "ruby.exp"
file.print("EXPORTS\n") if PLATFORM =~ /^i/ else
deffilename = "ruby.def"
end
print "creating #{deffilename}\n"
open(deffilename, "w") do |file|
file.print("EXPORTS\n") if RUBY_PLATFORM =~ /^i/
file.print("Init_#{target}\n") file.print("Init_#{target}\n")
end end
end end
end end
$libs = PLATFORM =~ /cygwin32|beos/ ? nil : "-lc" $OBJEXT = CONFIG["OBJEXT"]
$objs = nil $objs = nil
$local_libs = "" $libs = "-lc"
$CFLAGS = "" $local_flags = ""
$LDFLAGS = "" case RUBY_PLATFORM
when /cygwin|beos|openstep|nextstep|rhapsody/
$libs = ""
when /mswin32/
$libs = ""
$local_flags = "rubymw.lib -link /LIBPATH:$(topdir) /EXPORT:Init_$(TARGET)"
end
$LOCAL_LIBS = ""
$defs = [] $defs = []
dir = with_config("opt-dir")
if dir
idir = "-I"+dir+"/include"
ldir = "-L"+dir+"/lib"
end
unless idir
dir = with_config("opt-include")
idir = "-I"+dir if dir
end
unless ldir
dir = with_config("opt-lib")
ldir = "-L"+dir if dir
end
$CFLAGS = idir || ""
$LDFLAGS = ldir || ""

229
lib/monitor.rb Normal file
View file

@ -0,0 +1,229 @@
=begin
monitor.rb
Author: Shugo Maeda <shugo@netlab.co.jp>
Version: 1.2.1
USAGE:
foo = Foo.new
foo.extend(MonitorMixin)
cond = foo.new_cond
thread1:
foo.synchronize {
...
cond.wait_until { foo.done? }
...
}
thread2:
foo.synchronize {
foo.do_something
cond.signal
}
=end
module MonitorMixin
module Accessible
protected
attr_accessor :mon_owner, :mon_count
attr_reader :mon_entering_queue, :mon_waiting_queue
end
module Initializable
protected
def mon_initialize
@mon_owner = nil
@mon_count = 0
@mon_entering_queue = []
@mon_waiting_queue = []
end
end
class ConditionVariable
class Timeout < Exception; end
include Accessible
def wait(timeout = nil)
if @monitor.mon_owner != Thread.current
raise ThreadError, "current thread not owner"
end
Thread.critical = true
count = @monitor.mon_count
@monitor.mon_count = 0
@monitor.mon_owner = nil
if @monitor.mon_waiting_queue.empty?
t = @monitor.mon_entering_queue.shift
else
t = @monitor.mon_waiting_queue.shift
end
t.wakeup if t
@waiters.push(Thread.current)
if timeout
t = Thread.current
timeout_thread = Thread.start {
sleep(timeout)
t.raise(Timeout.new)
}
end
begin
Thread.stop
rescue Timeout
@waiters.delete(Thread.current)
ensure
if timeout && timeout_thread.alive?
Thread.kill(timeout_thread)
end
end
Thread.critical = true
while @monitor.mon_owner &&
@monitor.mon_owner != Thread.current
@monitor.mon_waiting_queue.push(Thread.current)
Thread.stop
Thread.critical = true
end
@monitor.mon_owner = Thread.current
@monitor.mon_count = count
Thread.critical = false
end
def wait_while
while yield
wait
end
end
def wait_until
until yield
wait
end
end
def signal
if @monitor.mon_owner != Thread.current
raise ThreadError, "current thread not owner"
end
Thread.critical = true
t = @waiters.shift
t.wakeup if t
Thread.critical = false
Thread.pass
end
def broadcast
if @monitor.mon_owner != Thread.current
raise ThreadError, "current thread not owner"
end
Thread.critical = true
for t in @waiters
t.wakeup
end
@waiters.clear
Thread.critical = false
Thread.pass
end
def count_waiters
return @waiters.length
end
private
def initialize(monitor)
@monitor = monitor
@waiters = []
end
end
include Accessible
include Initializable
extend Initializable
def self.extend_object(obj)
super(obj)
obj.mon_initialize
end
def try_mon_enter
result = false
Thread.critical = true
if mon_owner.nil?
self.mon_owner = Thread.current
end
if mon_owner == Thread.current
self.mon_count += 1
result = true
end
Thread.critical = false
return result
end
def mon_enter
Thread.critical = true
while mon_owner != nil && mon_owner != Thread.current
mon_entering_queue.push(Thread.current)
Thread.stop
Thread.critical = true
end
self.mon_owner = Thread.current
self.mon_count += 1
Thread.critical = false
end
def mon_exit
if mon_owner != Thread.current
raise ThreadError, "current thread not owner"
end
Thread.critical = true
self.mon_count -= 1
if mon_count == 0
self.mon_owner = nil
if mon_waiting_queue.empty?
t = mon_entering_queue.shift
else
t = mon_waiting_queue.shift
end
end
t.wakeup if t
Thread.critical = false
Thread.pass
end
def mon_synchronize
mon_enter
begin
yield
ensure
mon_exit
end
end
alias synchronize mon_synchronize
def new_cond
return ConditionVariable.new(self)
end
private
def initialize(*args)
super
mon_initialize
end
end
class Monitor
include MonitorMixin
alias try_enter try_mon_enter
alias enter mon_enter
alias exit mon_exit
alias owner mon_owner
end
# Local variables:
# mode: Ruby
# tab-width: 8
# End:

View file

@ -12,54 +12,27 @@
# obj = Object.new # obj = Object.new
# obj.extend Mutex_m # obj.extend Mutex_m
# ... # ...
# 後はMutexと同じ使い方 # extended object can be handled like Mutex
# #
require "finalize"
module Mutex_m module Mutex_m
def Mutex_m.extendable_module(obj) def Mutex_m.append_features(cl)
if Fixnum === obj or TRUE === obj or FALSE === obj or nil == obj super
raise TypeError, "Mutex_m can't extend to this class(#{obj.type})" unless cl.instance_of?(Module)
else cl.module_eval %q{
begin alias locked? mu_locked?
obj.instance_eval "@mu_locked" alias lock mu_lock
For_general_object alias unlock mu_unlock
rescue TypeError alias try_lock mu_try_lock
For_primitive_object alias synchronize mu_synchronize
end }
end end
end return self
def Mutex_m.includable_module(cl)
begin
dummy = cl.new
Mutex_m.extendable_module(dummy)
rescue NameError
# newが定義されていない時は, DATAとみなす.
For_primitive_object
end
end
def Mutex_m.extend_class(cl)
return super if cl.instance_of?(Module)
# モジュールの時は何もしない. クラスの場合, 適切なモジュールの決定
# とaliasを行う.
real = includable_module(cl)
cl.module_eval %q{
include real
alias locked? mu_locked?
alias lock mu_lock
alias unlock mu_unlock
alias try_lock mu_try_lock
alias synchronize mu_synchronize
}
end end
def Mutex_m.extend_object(obj) def Mutex_m.extend_object(obj)
obj.extend(Mutex_m.extendable_module(obj)) super
obj.mu_extended
end end
def mu_extended def mu_extended
@ -76,6 +49,7 @@ module Mutex_m
alias synchronize mu_synchronize alias synchronize mu_synchronize
end" end"
end end
initialize
end end
# locking # locking
@ -88,132 +62,50 @@ module Mutex_m
end end
end end
# internal class def mu_locked?
module For_general_object @mu_locked
include Mutex_m
def For_general_object.extend_object(obj)
super
obj.mu_extended
end
def mu_extended
super
@mu_waiting = []
@mu_locked = FALSE;
end
def mu_locked?
@mu_locked
end
def mu_try_lock
result = FALSE
Thread.critical = TRUE
unless @mu_locked
@mu_locked = TRUE
result = TRUE
end
Thread.critical = FALSE
result
end
def mu_lock
while (Thread.critical = TRUE; @mu_locked)
@mu_waiting.push Thread.current
Thread.stop
end
@mu_locked = TRUE
Thread.critical = FALSE
self
end
def mu_unlock
return unless @mu_locked
Thread.critical = TRUE
wait = @mu_waiting
@mu_waiting = []
@mu_locked = FALSE
Thread.critical = FALSE
for w in wait
w.run
end
self
end
end end
module For_primitive_object def mu_try_lock
include Mutex_m result = false
Mu_Locked = Hash.new Thread.critical = true
unless @mu_locked
def For_primitive_object.extend_object(obj) @mu_locked = true
super result = true
obj.mu_extended
Finalizer.add(obj, For_primitive_object, :mu_finalize)
end end
Thread.critical = false
def mu_extended result
super end
initialize
def mu_lock
while (Thread.critical = true; @mu_locked)
@mu_waiting.push Thread.current
Thread.stop
end end
@mu_locked = true
def For_primitive_object.mu_finalize(id) Thread.critical = false
Thread.critical = TRUE self
if wait = Mu_Locked.delete(id) end
# wait == [] ときだけ GCされるので, for w in wait は意味なし.
Thread.critical = FALSE def mu_unlock
for w in wait return unless @mu_locked
w.run Thread.critical = true
end wait = @mu_waiting
else @mu_waiting = []
Thread.critical = FALSE @mu_locked = false
end Thread.critical = false
self for w in wait
end w.run
def mu_locked?
Mu_Locked.key?(self.id)
end
def mu_try_lock
Thread.critical = TRUE
if Mu_Locked.key?(self.id)
ret = FALSE
else
Mu_Locked[self.id] = []
Finalizer.add(self, For_primitive_object, :mu_finalize)
ret = TRUE
end
Thread.critical = FALSE
ret
end
def mu_lock
while (Thread.critical = TRUE; w = Mu_Locked[self.id])
w.push Thread.current
Thread.stop
end
Mu_Locked[self.id] = []
Finalizer.add(self, For_primitive_object, :mu_finalize)
Thread.critical = FALSE
self
end
def mu_unlock
Thread.critical = TRUE
if wait = Mu_Locked.delete(self.id)
Finalizer.delete(self, For_primitive_object, :mu_finalize)
Thread.critical = FALSE
for w in wait
w.run
end
else
Thread.critical = FALSE
end
self
end end
self
end
private
def initialize(*args)
ret = super
@mu_waiting = []
@mu_locked = false;
return ret
end end
end end

View file

@ -23,7 +23,7 @@ module Observable
0 0
end end
end end
def changed(state=TRUE) def changed(state=true)
@observer_state = state @observer_state = state
end end
def changed? def changed?
@ -36,7 +36,7 @@ module Observable
i.update(*arg) i.update(*arg)
end end
end end
@observer_state = FALSE @observer_state = false
end end
end end
end end

55
lib/open3.rb Normal file
View file

@ -0,0 +1,55 @@
# Usage:
# require "open3"
#
# in, out, err = Open3.popen3('nroff -man')
# or
# include Open3
# in, out, err = popen3('nroff -man')
#
module Open3
#[stdin, stdout, stderr] = popen3(command);
def popen3(cmd)
pw = IO::pipe # pipe[0] for read, pipe[1] for write
pr = IO::pipe
pe = IO::pipe
pid = fork
if pid == nil then # child
pw[1].close
STDIN.reopen(pw[0])
pw[0].close
pr[0].close
STDOUT.reopen(pr[1])
pr[1].close
pe[0].close
STDERR.reopen(pe[1])
pe[1].close
exec(cmd)
exit
else
pw[0].close
pr[1].close
pe[1].close
pi = [ pw[1], pr[0], pe[0] ]
end
end
module_function :popen3
end
if $0 == __FILE__
a = Open3.popen3("nroff -man")
Thread.start do
while gets
a[0].print $_
end
a[0].close
end
while a[1].gets
print ":", $_
end
end

View file

@ -8,8 +8,8 @@ module ParseDate
'sun' => 0, 'mon' => 1, 'tue' => 2, 'wed' => 3, 'sun' => 0, 'mon' => 1, 'tue' => 2, 'wed' => 3,
'thu' => 4, 'fri' => 5, 'sat' => 6 } 'thu' => 4, 'fri' => 5, 'sat' => 6 }
DAYPAT = DAYS.keys.join('|') DAYPAT = DAYS.keys.join('|')
def parsedate(date) def parsedate(date, guess=false)
# part of ISO 8601 # part of ISO 8601
# yyyy-mm-dd | yyyy-mm | yyyy # yyyy-mm-dd | yyyy-mm | yyyy
# date hh:mm:ss | date Thh:mm:ss # date hh:mm:ss | date Thh:mm:ss
@ -46,7 +46,7 @@ module ParseDate
if $3 if $3
year = $3.to_i year = $3.to_i
end end
elsif date.sub!(/(#{MONTHPAT})\S*\s+(\d+)\S*\s*,?(?:\s+(\d+))?/i, ' ') elsif date.sub!(/(#{MONTHPAT})\S*\s+(\d+)\S*,?(?:\s+(\d+))?/i, ' ')
mon = MONTHS[$1.downcase] mon = MONTHS[$1.downcase]
mday = $2.to_i mday = $2.to_i
if $3 if $3
@ -58,6 +58,23 @@ module ParseDate
if $3 if $3
year = $3.to_i year = $3.to_i
end end
elsif date.sub!(/(\d+)-(#{MONTHPAT})-(\d+)/i, ' ')
mday = $1.to_i
mon = MONTHS[$2.downcase]
year = $3.to_i
end
if guess
if year < 100
if year >= 69
year += 1900
else
year += 2000
end
end
elsif date.sub!(/(\d+)-(#{MONTHPAT})-(\d+)/i, ' ')
mday = $1.to_i
mon = MONTHS[$2.downcase]
year = $3.to_i
end end
return year, mon, mday, hour, min, sec, zone, wday return year, mon, mday, hour, min, sec, zone, wday
end end

55
lib/profile.rb Normal file
View file

@ -0,0 +1,55 @@
module Profiler__
Start = Float(Time.times[0])
top = "toplevel".intern
Stack = [[0, 0, top]]
MAP = {top => [1, 0, 0, "#toplevel"]}
p = proc{|event, file, line, id, binding, klass|
case event
when "call", "c-call"
now = Float(Time.times[0])
Stack.push [now, 0.0, id]
when "return", "c-return"
now = Float(Time.times[0])
tick = Stack.pop
data = MAP[id]
unless data
name = klass.to_s
if name.nil? then name = '' end
if klass.kind_of? Class
name += "#"
else
name += "."
end
data = [0.0, 0.0, 0.0, name+id.id2name]
MAP[id] = data
end
data[0] += 1
cost = now - tick[0]
data[1] += cost
data[2] += cost - tick[1]
Stack[-1][1] += cost
end
}
END {
set_trace_func nil
total = Float(Time.times[0]) - Start
if total == 0 then total = 0.01 end
MAP[:toplevel][1] = total
# f = open("./rmon.out", "w")
f = STDERR
data = MAP.values.sort!{|a,b| b[2] <=> a[2]}
sum = 0
f.printf " %% cumulative self self total\n"
f.printf " time seconds seconds calls ms/call ms/call name\n"
for d in data
sum += d[2]
f.printf "%6.2f %8.2f %8.2f %8d ", d[2]/total*100, sum, d[2], d[0]
f.printf "%8.2f %8.2f %s\n", d[2]*1000/d[0], d[1]*1000/d[0], d[3]
end
p total
f.close
}
set_trace_func p
end

View file

@ -77,7 +77,7 @@ class Rational < Numeric
@denominator = den @denominator = den
else else
@numerator = num.to_i @numerator = num.to_i
@denoninator = den.to_i @denominator = den.to_i
end end
end end

36
lib/readbytes.rb Normal file
View file

@ -0,0 +1,36 @@
# readbytes.rb
#
# add IO#readbytes, which reads fixed sized data.
# it guarantees read data size.
class TruncatedDataError<IOError
def initialize(mesg, data)
@data = data
super(mesg)
end
attr_reader :data
end
class IO
def readbytes(n)
str = read(n)
if str == nil
raise EOFError, "End of file reached"
end
if str.size < n
raise TruncatedDataError.new("data truncated", str)
end
str
end
end
if __FILE__ == $0
begin
loop do
print STDIN.readbytes(6)
end
rescue TruncatedDataError
p $!.data
raise
end
end

View file

@ -17,7 +17,7 @@ module Shellwords
words = [] words = []
while line != '' while line != ''
field = '' field = ''
while TRUE while true
if line.sub! /^"(([^"\\]|\\.)*)"/, '' then #" if line.sub! /^"(([^"\\]|\\.)*)"/, '' then #"
snippet = $1 snippet = $1
snippet.gsub! /\\(.)/, '\1' snippet.gsub! /\\(.)/, '\1'

37
lib/singleton.rb Normal file
View file

@ -0,0 +1,37 @@
# Singleton module that ensures only one object to be allocated.
#
# Usage:
# class SomeSingletonClass
# include Singleton
# #....
# end
# a = SomeSingletonClass.instance
# b = SomeSingletonClass.instance # a and b are same object
# p [a,b]
# a = SomeSingletonClass.new # error (`new' is private)
module Singleton
def Singleton.append_features(klass)
klass.private_class_method(:new)
klass.instance_eval %{
def instance
unless @__instance__
@__instance__ = new
end
return @__instance__
end
}
end
end
if __FILE__ == $0
class SomeSingletonClass
include Singleton
#....
end
a = SomeSingletonClass.instance
b = SomeSingletonClass.instance # a and b are same object
p [a,b]
a = SomeSingletonClass.new # error (`new' is private)
end

View file

@ -1,5 +1,5 @@
# #
# sync.rb - カウント付2-フェーズロッククラス # sync.rb - 2 phase lock with counter
# $Release Version: 0.2$ # $Release Version: 0.2$
# $Revision$ # $Revision$
# $Date$ # $Date$
@ -44,8 +44,6 @@ unless defined? Thread
fail "Thread not available for this ruby interpreter" fail "Thread not available for this ruby interpreter"
end end
require "final"
module Sync_m module Sync_m
RCS_ID='-$Header$-' RCS_ID='-$Header$-'
@ -54,7 +52,7 @@ module Sync_m
SH = :SH SH = :SH
EX = :EX EX = :EX
# 例外定義 # exceptions
class Err < StandardError class Err < StandardError
def Err.Fail(*opt) def Err.Fail(*opt)
fail self, sprintf(self::Message, *opt) fail self, sprintf(self::Message, *opt)
@ -78,51 +76,27 @@ module Sync_m
end end
end end
# include and extend initialize methods. def Sync_m.append_features(cl)
def Sync_m.extendable_module(obj) super
if Fixnum === obj or TRUE === obj or FALSE === obj or nil == obj unless cl.instance_of?(Module)
raise TypeError, "Sync_m can't extend to this class(#{obj.type})" # do nothing for Modules
else # make aliases and include the proper module.
begin cl.module_eval %q{
obj.instance_eval "@sync_locked" alias locked? sync_locked?
For_general_object alias shared? sync_shared?
rescue TypeError alias exclusive? sync_exclusive?
For_primitive_object alias lock sync_lock
end alias unlock sync_unlock
alias try_lock sync_try_lock
alias synchronize sync_synchronize
}
end end
end return self
def Sync_m.includable_module(cl)
begin
dummy = cl.new
Sync_m.extendable_module(dummy)
rescue NameError
# newが定義されていない時は, DATAとみなす.
For_primitive_object
end
end
def Sync_m.extend_class(cl)
return super if cl.instance_of?(Module)
# モジュールの時は何もしない. クラスの場合, 適切なモジュールの決定
# とaliasを行う.
real = includable_module(cl)
cl.module_eval %q{
include real
alias locked? sync_locked?
alias shared? sync_shared?
alias exclusive? sync_exclusive?
alias lock sync_lock
alias unlock sync_unlock
alias try_lock sync_try_lock
alias synchronize sync_synchronize
}
end end
def Sync_m.extend_object(obj) def Sync_m.extend_object(obj)
obj.extend(Sync_m.extendable_module(obj)) super
obj.sync_extended
end end
def sync_extended def sync_extended
@ -143,6 +117,7 @@ module Sync_m
alias synchronize sync_synchronize alias synchronize sync_synchronize
end" end"
end end
initialize
end end
# accessing # accessing
@ -162,16 +137,16 @@ module Sync_m
def sync_try_lock(mode = EX) def sync_try_lock(mode = EX)
return unlock if sync_mode == UN return unlock if sync_mode == UN
Thread.critical = TRUE Thread.critical = true
ret = sync_try_lock_sub(sync_mode) ret = sync_try_lock_sub(sync_mode)
Thread.critical = FALSE Thread.critical = false
ret ret
end end
def sync_lock(m = EX) def sync_lock(m = EX)
return unlock if m == UN return unlock if m == UN
until (Thread.critical = TRUE; sync_try_lock_sub(m)) until (Thread.critical = true; sync_try_lock_sub(m))
if sync_sh_locker[Thread.current] if sync_sh_locker[Thread.current]
sync_upgrade_waiting.push [Thread.current, sync_sh_locker[Thread.current]] sync_upgrade_waiting.push [Thread.current, sync_sh_locker[Thread.current]]
sync_sh_locker.delete(Thread.current) sync_sh_locker.delete(Thread.current)
@ -180,23 +155,23 @@ module Sync_m
end end
Thread.stop Thread.stop
end end
Thread.critical = FALSE Thread.critical = false
self self
end end
def sync_unlock(m = EX) def sync_unlock(m = EX)
Thread.critical = TRUE Thread.critical = true
if sync_mode == UN if sync_mode == UN
Thread.critical = FALSE Thread.critical = false
Err::UnknownLocker.Fail(Thread.current) Err::UnknownLocker.Fail(Thread.current)
end end
m = sync_mode if m == EX and sync_mode == SH m = sync_mode if m == EX and sync_mode == SH
runnable = FALSE runnable = false
case m case m
when UN when UN
Thread.critical = FALSE Thread.critical = false
Err::UnknownLocker.Fail(Thread.current) Err::UnknownLocker.Fail(Thread.current)
when EX when EX
@ -208,7 +183,7 @@ module Sync_m
else else
self.sync_mode = UN self.sync_mode = UN
end end
runnable = TRUE runnable = true
end end
else else
Err::UnknownLocker.Fail(Thread.current) Err::UnknownLocker.Fail(Thread.current)
@ -222,7 +197,7 @@ module Sync_m
sync_sh_locker.delete(Thread.current) sync_sh_locker.delete(Thread.current)
if sync_sh_locker.empty? and sync_ex_count == 0 if sync_sh_locker.empty? and sync_ex_count == 0
self.sync_mode = UN self.sync_mode = UN
runnable = TRUE runnable = true
end end
end end
end end
@ -235,7 +210,7 @@ module Sync_m
end end
wait = sync_upgrade_waiting wait = sync_upgrade_waiting
self.sync_upgrade_waiting = [] self.sync_upgrade_waiting = []
Thread.critical = FALSE Thread.critical = false
for w, v in wait for w, v in wait
w.run w.run
@ -243,59 +218,17 @@ module Sync_m
else else
wait = sync_waiting wait = sync_waiting
self.sync_waiting = [] self.sync_waiting = []
Thread.critical = FALSE Thread.critical = false
for w in wait for w in wait
w.run w.run
end end
end end
end end
Thread.critical = FALSE Thread.critical = false
self self
end end
def sync_try_lock_sub(m)
case m
when SH
case sync_mode
when UN
self.sync_mode = m
sync_sh_locker[Thread.current] = 1
ret = TRUE
when SH
count = 0 unless count = sync_sh_locker[Thread.current]
sync_sh_locker[Thread.current] = count + 1
ret = TRUE
when EX
# 既に, モードがEXである時は, 必ずEXロックとなる.
if sync_ex_locker == Thread.current
self.sync_ex_count = sync_ex_count + 1
ret = TRUE
else
ret = FALSE
end
end
when EX
if sync_mode == UN or
sync_mode == SH && sync_sh_locker.size == 1 && sync_sh_locker.include?(Thread.current)
self.sync_mode = m
self.sync_ex_locker = Thread.current
self.sync_ex_count = 1
ret = TRUE
elsif sync_mode == EX && sync_ex_locker == Thread.current
self.sync_ex_count = sync_ex_count + 1
ret = TRUE
else
ret = FALSE
end
else
Thread.critical = FALSE
Err::LockModeFailer.Fail mode
end
return ret
end
private :sync_try_lock_sub
def sync_synchronize(mode = EX) def sync_synchronize(mode = EX)
sync_lock(mode) sync_lock(mode)
begin begin
@ -305,133 +238,76 @@ module Sync_m
end end
end end
# internal class attr :sync_mode, true
module For_primitive_object attr :sync_waiting, true
include Sync_m attr :sync_upgrade_waiting, true
attr :sync_sh_locker, true
LockState = Struct.new("LockState", attr :sync_ex_locker, true
:mode, attr :sync_ex_count, true
:waiting,
:upgrade_waiting,
:sh_locker,
:ex_locker,
:ex_count)
Sync_Locked = Hash.new
def For_primitive_object.extend_object(obj)
super
obj.sync_extended
# Changed to use `final.rb'.
# Finalizer.add(obj, For_primitive_object, :sync_finalize)
ObjectSpace.define_finalizer(obj) do |id|
For_primitive_object.sync_finalize(id)
end
end
def initialize
super
Sync_Locked[id] = LockState.new(UN, [], [], Hash.new, nil, 0 )
self
end
def sync_extended
super
initialize
end
def For_primitive_object.sync_finalize(id)
wait = Sync_Locked.delete(id)
# waiting == [] ときだけ GCされるので, 待ち行列の解放は意味がない.
end
def sync_mode
Sync_Locked[id].mode
end
def sync_mode=(value)
Sync_Locked[id].mode = value
end
def sync_waiting private
Sync_Locked[id].waiting
end def initialize(*args)
def sync_waiting=(v) ret = super
Sync_Locked[id].waiting = v @sync_mode = UN
end @sync_waiting = []
@sync_upgrade_waiting = []
def sync_upgrade_waiting @sync_sh_locker = Hash.new
Sync_Locked[id].upgrade_waiting @sync_ex_locker = nil
end @sync_ex_count = 0
def sync_upgrade_waiting=(v) return ret
Sync_Locked[id].upgrade_waiting = v
end
def sync_sh_locker
Sync_Locked[id].sh_locker
end
def sync_sh_locker=(v)
Sync_Locked[id].sh_locker = v
end
def sync_ex_locker
Sync_Locked[id].ex_locker
end
def sync_ex_locker=(value)
Sync_Locked[id].ex_locker = value
end
def sync_ex_count
Sync_Locked[id].ex_count
end
def sync_ex_count=(value)
Sync_Locked[id].ex_count = value
end
end end
module For_general_object def sync_try_lock_sub(m)
include Sync_m case m
when SH
def For_general_object.extend_object(obj) case sync_mode
super when UN
obj.sync_extended self.sync_mode = m
sync_sh_locker[Thread.current] = 1
ret = true
when SH
count = 0 unless count = sync_sh_locker[Thread.current]
sync_sh_locker[Thread.current] = count + 1
ret = true
when EX
# in EX mode, lock will upgrade to EX lock
if sync_ex_locker == Thread.current
self.sync_ex_count = sync_ex_count + 1
ret = true
else
ret = false
end
end
when EX
if sync_mode == UN or
sync_mode == SH && sync_sh_locker.size == 1 && sync_sh_locker.include?(Thread.current)
self.sync_mode = m
self.sync_ex_locker = Thread.current
self.sync_ex_count = 1
ret = true
elsif sync_mode == EX && sync_ex_locker == Thread.current
self.sync_ex_count = sync_ex_count + 1
ret = true
else
ret = false
end
else
Thread.critical = false
Err::LockModeFailer.Fail mode
end end
return ret
def initialize
super
@sync_mode = UN
@sync_waiting = []
@sync_upgrade_waiting = []
@sync_sh_locker = Hash.new
@sync_ex_locker = nil
@sync_ex_count = 0
self
end
def sync_extended
super
initialize
end
attr :sync_mode, TRUE
attr :sync_waiting, TRUE
attr :sync_upgrade_waiting, TRUE
attr :sync_sh_locker, TRUE
attr :sync_ex_locker, TRUE
attr :sync_ex_count, TRUE
end end
end end
Synchronizer_m = Sync_m Synchronizer_m = Sync_m
class Sync class Sync
Sync_m.extend_class self include Sync_m
#include Sync_m
private
def initialize def initialize
super super
end end
end end
Synchronizer = Sync Synchronizer = Sync

636
lib/telnet.rb Normal file
View file

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

94
lib/tempfile.rb Normal file
View file

@ -0,0 +1,94 @@
#
# $Id$
#
# The class for temporary files.
# o creates a temporary file, which name is "basename.pid.n" with mode "w+".
# o Tempfile objects can be used like IO object.
# o with tmpfile.close(true) created temporary files are removed.
# o created files are also removed on script termination.
# o with Tempfile#open, you can reopen the temporary file.
# o file mode of the temporary files are 0600.
require 'delegate'
require 'final'
class Tempfile < SimpleDelegator
Max_try = 10
def Tempfile.callback(path)
lambda{
print "removing ", path, "..." if $DEBUG
if File.exist?(path)
File.unlink(path)
end
if File.exist?(path + '.lock')
Dir.rmdir(path + '.lock')
end
print "done\n" if $DEBUG
}
end
def initialize(basename, tmpdir=ENV['TMPDIR']||ENV['TMP']||ENV['TEMP']||'/tmp')
umask = File.umask(0177)
begin
n = 0
while true
begin
tmpname = sprintf('%s/%s%d.%d', tmpdir, basename, $$, n)
lock = tmpname + '.lock'
unless File.exist?(tmpname) or File.exist?(lock)
Dir.mkdir(lock)
break
end
rescue
raise "cannot generate tmpfile `%s'" % tmpname if n >= Max_try
#sleep(1)
end
n += 1
end
@clean_files = Tempfile.callback(tmpname)
ObjectSpace.define_finalizer(self, @clean_files)
@tmpfile = File.open(tmpname, 'w+')
@tmpname = tmpname
super(@tmpfile)
Dir.rmdir(lock)
ensure
File.umask(umask)
end
end
def Tempfile.open(*args)
Tempfile.new(*args)
end
def open
@tmpfile.close if @tmpfile
@tmpfile = File.open(@tmpname, 'r+')
__setobj__(@tmpfile)
end
def close(real=false)
@tmpfile.close if @tmpfile
@tmpfile = nil
if real
@clean_files.call
ObjectSpace.undefine_finalizer(self)
end
end
def path
@tmpname
end
end
if __FILE__ == $0
# $DEBUG = true
f = Tempfile.new("foo")
f.print("foo\n")
f.close
f.open
p f.gets # => "foo\n"
f.close(true)
end

View file

@ -17,6 +17,16 @@ if $DEBUG
Thread.abort_on_exception = true Thread.abort_on_exception = true
end end
def Thread.exclusive
begin
Thread.critical = true
r = yield
ensure
Thread.critical = false
end
r
end
class Mutex class Mutex
def initialize def initialize
@waiting = [] @waiting = []
@ -52,10 +62,10 @@ class Mutex
def unlock def unlock
return unless @locked return unless @locked
Thread.critical = TRUE Thread.critical = true
t = @waiting.shift t = @waiting.shift
@locked = FALSE @locked = false
Thread.critical = FALSE Thread.critical = false
t.run if t t.run if t
self self
end end
@ -68,39 +78,46 @@ class Mutex
unlock unlock
end end
end end
def exclusive_unlock
return unless @locked
Thread.exclusive do
t = @waiting.shift
@locked = false
t.wakeup if t
yield
end
self
end
end end
class ConditionVariable class ConditionVariable
def initialize def initialize
@waiters = [] @waiters = []
@waiters_mutex = Mutex.new
@waiters.taint # enable tainted comunication
self.taint
end end
def wait(mutex) def wait(mutex)
mutex.unlock mutex.exclusive_unlock do
@waiters_mutex.synchronize {
@waiters.push(Thread.current) @waiters.push(Thread.current)
} Thread.stop
Thread.stop end
mutex.lock mutex.lock
end end
def signal def signal
@waiters_mutex.synchronize { t = @waiters.shift
t = @waiters.shift t.run if t
t.run if t
}
end end
def broadcast def broadcast
@waiters_mutex.synchronize { waiters0 = nil
for t in @waiters Thread.exclusive do
t.run waiters0 = @waiters.dup
end
@waiters.clear @waiters.clear
} end
for t in waiters0
t.run
end
end end
end end
@ -120,6 +137,7 @@ class Queue
Thread.critical = false Thread.critical = false
t.run if t t.run if t
end end
alias enq push
def pop non_block=false def pop non_block=false
Thread.critical = true Thread.critical = true
@ -139,11 +157,17 @@ class Queue
Thread.critical = false Thread.critical = false
end end
end end
alias shift pop
alias deq pop
def empty? def empty?
@que.length == 0 @que.length == 0
end end
def clear
@que.replace([])
end
def length def length
@que.length @que.length
end end
@ -168,14 +192,14 @@ class SizedQueue<Queue
end end
def max=(max) def max=(max)
Thread.critical = TRUE Thread.critical = true
if @max >= max if @max >= max
@max = max @max = max
Thread.critical = FALSE Thread.critical = false
else else
diff = max - @max diff = max - @max
@max = max @max = max
Thread.critical = FALSE Thread.critical = false
diff.times do diff.times do
t = @queue_wait.shift t = @queue_wait.shift
t.run if t t.run if t

42
lib/timeout.rb Normal file
View file

@ -0,0 +1,42 @@
#
# timeout.rb -- execution timeout
#
#= SYNOPSIS
#
# require 'timeout'
# status = timeout(5) {
# # something may take time
# }
#
#= DESCRIPTION
#
# timeout executes the block. If the block execution terminates successfully
# before timeout, it returns true. If not, it terminates the execution and
# raise TimeoutError exception.
#
#== Parameters
#
# : timout
#
# The time in seconds to wait for block teminatation.
#
#=end
class TimeoutError<StandardError
end
Thread.abort_on_exception = true
def timeout(sec)
begin
x = Thread.current
y = Thread.start {
sleep sec
x.raise TimeoutError, "execution expired" if x.status
}
yield sec
return true
ensure
Thread.kill y if y.status
end
end

View file

@ -54,7 +54,7 @@ class Tracer
off off
end end
else else
set_trace_func proc{|event, file, line, id, binding| set_trace_func proc{|event, file, line, id, binding, klass|
trace_func event, file, line, id, binding trace_func event, file, line, id, binding
} }
print "Trace on\n" if Tracer.verbose? print "Trace on\n" if Tracer.verbose?

View file

@ -2,11 +2,12 @@
# #
# Usage: # Usage:
# foo = Object.new # foo = Object.new
# foo.hash # foo = Object.new
# p foo.to_s # original's class
# foo = WeakRef.new(foo) # foo = WeakRef.new(foo)
# foo.hash # p foo.to_s # should be same class
# ObjectSpace.garbage_collect # ObjectSpace.garbage_collect
# foo.hash # => Raises WeakRef::RefError (because original GC'ed) # p foo.to_s # should raise exception (recycled)
require "delegate" require "delegate"
@ -15,27 +16,31 @@ class WeakRef<Delegator
class RefError<StandardError class RefError<StandardError
end end
ID_MAP = {} ID_MAP = {} # obj -> [ref,...]
ID_REV_MAP = {} ID_REV_MAP = {} # ref -> obj
ObjectSpace.add_finalizer(lambda{|id| ObjectSpace.add_finalizer(lambda{|id|
rid = ID_MAP[id] rids = ID_MAP[id]
if rid if rids
ID_REV_MAP[rid] = nil for rid in rids
ID_REV_MAP[rid] = nil
end
ID_MAP[id] = nil ID_MAP[id] = nil
end end
rid = ID_REV_MAP[id] rid = ID_REV_MAP[id]
if rid if rid
ID_REV_MAP[id] = nil ID_REV_MAP[id] = nil
ID_MAP[rid] = nil ID_MAP[rid].delete(id)
ID_MAP[rid] = nil if ID_MAP[rid].empty?
end end
}) })
def initialize(orig) def initialize(orig)
super super
@__id = orig.__id__ @__id = orig.__id__
ObjectSpace.call_finalizer orig ObjectSpace.call_finalizer orig
ObjectSpace.call_finalizer self ObjectSpace.call_finalizer self
ID_MAP[@__id] = self.__id__ ID_MAP[@__id] = [] unless ID_MAP[@__id]
ID_MAP[@__id].concat self.__id__
ID_REV_MAP[self.id] = @__id ID_REV_MAP[self.id] = @__id
end end
@ -60,10 +65,11 @@ class WeakRef<Delegator
end end
if __FILE__ == $0 if __FILE__ == $0
require 'thread'
foo = Object.new foo = Object.new
p foo.hash # original's hash value p foo.to_s # original's class
foo = WeakRef.new(foo) foo = WeakRef.new(foo)
p foo.hash # should be same hash value p foo.to_s # should be same class
ObjectSpace.garbage_collect ObjectSpace.garbage_collect
p foo.hash # should raise exception (recycled) p foo.to_s # should raise exception (recycled)
end end

9
main.c
View file

@ -11,13 +11,17 @@
#include "ruby.h" #include "ruby.h"
#ifdef DJGPP #ifdef DJGPP
unsigned int _stklen = 0x100000; unsigned int _stklen = 0x180000;
#endif #endif
#ifdef __human68k__ #ifdef __human68k__
int _stacksize = 131072; int _stacksize = 131072;
#endif #endif
#if defined(__MACOS__) && defined(__MWERKS__)
#include <console.h>
#endif
int int
main(argc, argv, envp) main(argc, argv, envp)
int argc; int argc;
@ -26,6 +30,9 @@ main(argc, argv, envp)
#if defined(NT) #if defined(NT)
NtInitialize(&argc, &argv); NtInitialize(&argc, &argv);
#endif #endif
#if defined(__MACOS__) && defined(__MWERKS__)
argc = ccommand(&argv);
#endif
ruby_init(); ruby_init();
ruby_options(argc, argv); ruby_options(argc, argv);

View file

@ -12,8 +12,12 @@
#include "rubyio.h" #include "rubyio.h"
#include "st.h" #include "st.h"
#ifndef atof
double strtod();
#endif
#define MARSHAL_MAJOR 4 #define MARSHAL_MAJOR 4
#define MARSHAL_MINOR 0 #define MARSHAL_MINOR 1
#define TYPE_NIL '0' #define TYPE_NIL '0'
#define TYPE_TRUE 'T' #define TYPE_TRUE 'T'
@ -37,8 +41,6 @@
#define TYPE_LINK '@' #define TYPE_LINK '@'
VALUE rb_path2class _((char*));
static ID s_dump, s_load; static ID s_dump, s_load;
struct dump_arg { struct dump_arg {
@ -164,7 +166,7 @@ w_unique(s, arg)
static void w_object _((VALUE,struct dump_arg*,int)); static void w_object _((VALUE,struct dump_arg*,int));
static int static int
rb_hash_each(key, value, arg) hash_each(key, value, arg)
VALUE key, value; VALUE key, value;
struct dump_call_arg *arg; struct dump_call_arg *arg;
{ {
@ -174,7 +176,7 @@ rb_hash_each(key, value, arg)
} }
static int static int
rb_obj_each(id, value, arg) obj_each(id, value, arg)
ID id; ID id;
VALUE value; VALUE value;
struct dump_call_arg *arg; struct dump_call_arg *arg;
@ -249,9 +251,9 @@ w_object(obj, arg, limit)
w_byte(TYPE_USERDEF, arg); w_byte(TYPE_USERDEF, arg);
w_unique(rb_class2name(CLASS_OF(obj)), arg); w_unique(rb_class2name(CLASS_OF(obj)), arg);
v = rb_funcall(obj, s_dump, 1, limit); v = rb_funcall(obj, s_dump, 1, INT2NUM(limit));
if (TYPE(v) != T_STRING) { if (TYPE(v) != T_STRING) {
rb_raise(rb_eTypeError, "_dump_to must return String"); rb_raise(rb_eTypeError, "_dump() must return String");
} }
w_bytes(RSTRING(v)->ptr, RSTRING(v)->len, arg); w_bytes(RSTRING(v)->ptr, RSTRING(v)->len, arg);
return; return;
@ -320,7 +322,7 @@ w_object(obj, arg, limit)
w_uclass(obj, rb_cHash, arg); w_uclass(obj, rb_cHash, arg);
w_byte(TYPE_HASH, arg); w_byte(TYPE_HASH, arg);
w_long(RHASH(obj)->tbl->num_entries, arg); w_long(RHASH(obj)->tbl->num_entries, arg);
st_foreach(RHASH(obj)->tbl, rb_hash_each, &c_arg); st_foreach(RHASH(obj)->tbl, hash_each, &c_arg);
break; break;
case T_STRUCT: case T_STRUCT:
@ -357,7 +359,7 @@ w_object(obj, arg, limit)
w_unique(path, arg); w_unique(path, arg);
if (ROBJECT(obj)->iv_tbl) { if (ROBJECT(obj)->iv_tbl) {
w_long(ROBJECT(obj)->iv_tbl->num_entries, arg); w_long(ROBJECT(obj)->iv_tbl->num_entries, arg);
st_foreach(ROBJECT(obj)->iv_tbl, rb_obj_each, &c_arg); st_foreach(ROBJECT(obj)->iv_tbl, obj_each, &c_arg);
} }
else { else {
w_long(0, arg); w_long(0, arg);
@ -455,9 +457,19 @@ static int
r_byte(arg) r_byte(arg)
struct load_arg *arg; struct load_arg *arg;
{ {
if (arg->fp) return getc(arg->fp); int c;
if (arg->ptr < arg->end) return *(unsigned char*)arg->ptr++;
return EOF; if (arg->fp) {
c = rb_getc(arg->fp);
if (c == EOF) rb_eof_error();
}
else if (arg->ptr < arg->end) {
c = *(unsigned char*)arg->ptr++;
}
else {
rb_raise(rb_eArgError, "marshal data too short");
}
return c;
} }
static unsigned short static unsigned short
@ -602,10 +614,6 @@ r_object(arg)
int type = r_byte(arg); int type = r_byte(arg);
switch (type) { switch (type) {
case EOF:
rb_eof_error();
return Qnil;
case TYPE_LINK: case TYPE_LINK:
if (st_lookup(arg->data, r_long(arg), &v)) { if (st_lookup(arg->data, r_long(arg), &v)) {
return v; return v;
@ -641,13 +649,10 @@ r_object(arg)
case TYPE_FLOAT: case TYPE_FLOAT:
{ {
#ifndef atof
double atof();
#endif
char *buf; char *buf;
r_bytes(buf, arg); r_bytes(buf, arg);
v = rb_float_new(atof(buf)); v = rb_float_new(strtod(buf, 0));
return r_regist(v, arg); return r_regist(v, arg);
} }
@ -754,7 +759,7 @@ r_object(arg)
v = rb_funcall(klass, s_load, 1, r_string(arg)); v = rb_funcall(klass, s_load, 1, r_string(arg));
return r_regist(v, arg); return r_regist(v, arg);
} }
rb_raise(rb_eTypeError, "class %s needs to have method `_load_from'", rb_raise(rb_eTypeError, "class %s needs to have method `_load'",
rb_class2name(klass)); rb_class2name(klass));
} }
break; break;
@ -850,7 +855,7 @@ marshal_load(argc, argv)
v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg); v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg);
} }
else { else {
rb_raise(rb_eTypeError, "Old marshal file format (can't read)"); rb_raise(rb_eTypeError, "old marshal file format (can't read)");
} }
return v; return v;

2
math.c
View file

@ -6,7 +6,7 @@
$Date$ $Date$
created at: Tue Jan 25 14:12:56 JST 1994 created at: Tue Jan 25 14:12:56 JST 1994
Copyright (C) 1993-1998 Yukihiro Matsumoto Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/ ************************************************/

5
misc/README Normal file
View file

@ -0,0 +1,5 @@
README this file
inf-ruby.el program to run ruby under emacs
ruby-mode.el ruby mode for emacs
rubydb2x.el ruby debugger support for emacs 19.2x or before
rubydb3x.el ruby debugger support for emacs 19.3x or later

322
misc/inf-ruby.el Normal file
View file

@ -0,0 +1,322 @@
;;; -*-Emacs-Lisp-*-
;;;
;;; $Id$
;;; $Author$
;;; $Date$
;;;
;;; Inferior Ruby Mode - ruby process in a buffer.
;;; adapted from cmuscheme.el
;;;
;;; Usage:
;;;
;;; (0) check ruby-program-name variable that can run your environment.
;;;
;;; (1) modify .emacs to use ruby-mode
;;; for example :
;;;
;;; (autoload 'ruby-mode "ruby-mode"
;;; "Mode for editing ruby source files")
;;; (setq auto-mode-alist
;;; (append '(("\\.rb$" . ruby-mode)) auto-mode-alist))
;;; (setq interpreter-mode-alist (append '(("^#!.*ruby" . ruby-mode))
;;; interpreter-mode-alist))
;;;
;;; (2) set to road inf-ruby and set inf-ruby key definition in ruby-mode.
;;;
;;; (autoload 'run-ruby "inf-ruby"
;;; "Run an inferior Ruby process")
;;; (autoload 'inf-ruby-keys "inf-ruby"
;;; "Set local key defs for inf-ruby in ruby-mode")
;;; (add-hook 'ruby-mode-hook
;;; '(lambda ()
;;; (inf-ruby-keys)
;;; ))
;;;
;;; HISTORY
;;; senda - 8 Apr 1998: Created.
;;; $Log$
;;; Revision 1.2 1999/08/13 05:45:18 matz
;;; 1.4.0
;;;
;;; Revision 1.1.1.1.2.1 1999/07/15 07:59:59 matz
;;; 990715
;;;
;;; Revision 1.1.1.1 1999/01/20 04:59:36 matz
;;; ruby 1.3 cycle
;;;
;;; Revision 1.1.2.1 1998/12/16 07:30:36 matz
;;; first public release of 1.1d (pre1.2) series
;;;
;;; Revision 1.4 1998/05/20 02:45:58 senda
;;; default program to irb
;;;
;;; Revision 1.3 1998/04/10 04:11:30 senda
;;; modification by Matsumoto san (1.1b9_09)
;;; remove-in-string defined
;;; global variable :
;;; inferior-ruby-first-prompt-pattern
;;; inferior-ruby-prompt-pattern
;;; defined
;;;
;;; Revision 1.2 1998/04/09 07:53:42 senda
;;; remove M-C-x in inferior-ruby-mode
;;;
;;; Revision 1.1 1998/04/09 07:28:36 senda
;;; Initial revision
;;;
;;;
(require 'comint)
(require 'ruby-mode)
;;
;; you may change these variables
;;
;(defvar ruby-program-name "rbc --noreadline"
; "*Program invoked by the run-ruby command")
;
;(defvar inferior-ruby-first-prompt-pattern "^rbc0> *"
; "first prompt regex pattern of ruby interpreter.")
;
;(defvar inferior-ruby-prompt-pattern "^\\(rbc.[>*\"'] *\\)+"
; "prompt regex pattern of ruby interpreter.")
;;;; for irb
(defvar ruby-program-name "irb --inf-ruby-mode"
"*Program invoked by the run-ruby command")
(defvar inferior-ruby-first-prompt-pattern "^irb(.*)[0-9:]+0> *"
"first prompt regex pattern of ruby interpreter.")
(defvar inferior-ruby-prompt-pattern "^\\(irb(.*)[0-9:]+[>*\"'] *\\)+"
"prompt regex pattern of ruby interpreter.")
;;
;; mode variables
;;
(defvar inferior-ruby-mode-hook nil
"*Hook for customising inferior-ruby mode.")
(defvar inferior-ruby-mode-map nil
"*Mode map for inferior-ruby-mode")
(cond ((not inferior-ruby-mode-map)
(setq inferior-ruby-mode-map
(copy-keymap comint-mode-map))
; (define-key inferior-ruby-mode-map "\M-\C-x" ;gnu convention
; 'ruby-send-definition)
; (define-key inferior-ruby-mode-map "\C-x\C-e" 'ruby-send-last-sexp)
(define-key inferior-ruby-mode-map "\C-c\C-l" 'ruby-load-file)
))
(defun inf-ruby-keys ()
"Set local key defs for inf-ruby in ruby-mode"
(define-key ruby-mode-map "\M-\C-x" 'ruby-send-definition)
; (define-key ruby-mode-map "\C-x\C-e" 'ruby-send-last-sexp)
(define-key ruby-mode-map "\C-c\C-e" 'ruby-send-definition)
(define-key ruby-mode-map "\C-c\M-e" 'ruby-send-definition-and-go)
(define-key ruby-mode-map "\C-c\C-r" 'ruby-send-region)
(define-key ruby-mode-map "\C-c\M-r" 'ruby-send-region-and-go)
(define-key ruby-mode-map "\C-c\C-z" 'switch-to-ruby)
(define-key ruby-mode-map "\C-c\C-l" 'ruby-load-file)
(define-key ruby-mode-map "\C-c\C-s" 'run-ruby)
)
(defvar ruby-buffer nil "current ruby (actually irb) process buffer.")
(defun inferior-ruby-mode ()
"Major mode for interacting with an inferior ruby (irb) process.
The following commands are available:
\\{inferior-ruby-mode-map}
A ruby process can be fired up with M-x run-ruby.
Customisation: Entry to this mode runs the hooks on comint-mode-hook and
inferior-ruby-mode-hook (in that order).
You can send text to the inferior ruby process from other buffers containing
Ruby source.
switch-to-ruby switches the current buffer to the ruby process buffer.
ruby-send-definition sends the current definition to the ruby process.
ruby-send-region sends the current region to the ruby process.
ruby-send-definition-and-go, ruby-send-region-and-go,
switch to the ruby process buffer after sending their text.
For information on running multiple processes in multiple buffers, see
documentation for variable ruby-buffer.
Commands:
Return after the end of the process' output sends the text from the
end of process to point.
Return before the end of the process' output copies the sexp ending at point
to the end of the process' output, and sends it.
Delete converts tabs to spaces as it moves back.
Tab indents for ruby; with argument, shifts rest
of expression rigidly with the current line.
C-M-q does Tab on each line starting within following expression.
Paragraphs are separated only by blank lines. # start comments.
If you accidentally suspend your process, use \\[comint-continue-subjob]
to continue it."
(interactive)
(comint-mode)
;; Customise in inferior-ruby-mode-hook
;(setq comint-prompt-regexp "^[^>\n]*>+ *")
(setq comint-prompt-regexp inferior-ruby-prompt-pattern)
;;(scheme-mode-variables)
(ruby-mode-variables)
(setq major-mode 'inferior-ruby-mode)
(setq mode-name "Inferior Ruby")
(setq mode-line-process '(":%s"))
(use-local-map inferior-ruby-mode-map)
(setq comint-input-filter (function ruby-input-filter))
(setq comint-get-old-input (function ruby-get-old-input))
(run-hooks 'inferior-ruby-mode-hook))
(defvar inferior-ruby-filter-regexp "\\`\\s *\\S ?\\S ?\\s *\\'"
"*Input matching this regexp are not saved on the history list.
Defaults to a regexp ignoring all inputs of 0, 1, or 2 letters.")
(defun ruby-input-filter (str)
"Don't save anything matching inferior-ruby-filter-regexp"
(not (string-match inferior-ruby-filter-regexp str)))
;; adapted from replace-in-string in XEmacs (subr.el)
(defun remove-in-string (str regexp)
"Remove all matches in STR for REGEXP and returns the new string."
(let ((rtn-str "") (start 0) match prev-start)
(while (setq match (string-match regexp str start))
(setq prev-start start
start (match-end 0)
rtn-str (concat rtn-str (substring str prev-start match))))
(concat rtn-str (substring str start))))
(defun ruby-get-old-input ()
"Snarf the sexp ending at point"
(save-excursion
(let ((end (point)))
(re-search-backward inferior-ruby-first-prompt-pattern)
(remove-in-string (buffer-substring (point) end)
inferior-ruby-prompt-pattern)
)))
(defun ruby-args-to-list (string)
(let ((where (string-match "[ \t]" string)))
(cond ((null where) (list string))
((not (= where 0))
(cons (substring string 0 where)
(ruby-args-to-list (substring string (+ 1 where)
(length string)))))
(t (let ((pos (string-match "[^ \t]" string)))
(if (null pos)
nil
(ruby-args-to-list (substring string pos
(length string)))))))))
(defun run-ruby (cmd)
"Run an inferior Ruby process, input and output via buffer *ruby*.
If there is a process already running in `*ruby*', switch to that buffer.
With argument, allows you to edit the command line (default is value
of `ruby-program-name'). Runs the hooks `inferior-ruby-mode-hook'
\(after the `comint-mode-hook' is run).
\(Type \\[describe-mode] in the process buffer for a list of commands.)"
(interactive (list (if current-prefix-arg
(read-string "Run Ruby: " ruby-program-name)
ruby-program-name)))
(if (not (comint-check-proc "*ruby*"))
(let ((cmdlist (ruby-args-to-list cmd)))
(set-buffer (apply 'make-comint "ruby" (car cmdlist)
nil (cdr cmdlist)))
(inferior-ruby-mode)))
(setq ruby-program-name cmd)
(setq ruby-buffer "*ruby*")
(pop-to-buffer "*ruby*"))
(defun ruby-send-region (start end)
"Send the current region to the inferior Ruby process."
(interactive "r")
(comint-send-region (ruby-proc) start end)
(comint-send-string (ruby-proc) "\n"))
(defun ruby-send-definition ()
"Send the current definition to the inferior Ruby process."
(interactive)
(save-excursion
(ruby-end-of-defun)
(let ((end (point)))
(ruby-beginning-of-defun)
(ruby-send-region (point) end))))
;(defun ruby-send-last-sexp ()
; "Send the previous sexp to the inferior Ruby process."
; (interactive)
; (ruby-send-region (save-excursion (backward-sexp) (point)) (point)))
(defun switch-to-ruby (eob-p)
"Switch to the ruby process buffer.
With argument, positions cursor at end of buffer."
(interactive "P")
(if (get-buffer ruby-buffer)
(pop-to-buffer ruby-buffer)
(error "No current process buffer. See variable ruby-buffer."))
(cond (eob-p
(push-mark)
(goto-char (point-max)))))
(defun ruby-send-region-and-go (start end)
"Send the current region to the inferior Ruby process.
Then switch to the process buffer."
(interactive "r")
(ruby-send-region start end)
(switch-to-ruby t))
(defun ruby-send-definition-and-go ()
"Send the current definition to the inferior Ruby.
Then switch to the process buffer."
(interactive)
(ruby-send-definition)
(switch-to-ruby t))
(defvar ruby-source-modes '(ruby-mode)
"*Used to determine if a buffer contains Ruby source code.
If it's loaded into a buffer that is in one of these major modes, it's
considered a ruby source file by ruby-load-file.
Used by these commands to determine defaults.")
(defvar ruby-prev-l/c-dir/file nil
"Caches the last (directory . file) pair.
Caches the last pair used in the last ruby-load-file command.
Used for determining the default in the
next one.")
(defun ruby-load-file (file-name)
"Load a Ruby file into the inferior Ruby process."
(interactive (comint-get-source "Load Ruby file: " ruby-prev-l/c-dir/file
ruby-source-modes t)) ; T because LOAD
; needs an exact name
(comint-check-source file-name) ; Check to see if buffer needs saved.
(setq ruby-prev-l/c-dir/file (cons (file-name-directory file-name)
(file-name-nondirectory file-name)))
(comint-send-string (ruby-proc) (concat "(load \""
file-name
"\"\)\n")))
(defun ruby-proc ()
"Returns the current ruby process. See variable ruby-buffer."
(let ((proc (get-buffer-process (if (eq major-mode 'inferior-ruby-mode)
(current-buffer)
ruby-buffer))))
(or proc
(error "No current process. See variable ruby-buffer"))))
;;; Do the user's customisation...
(defvar inf-ruby-load-hook nil
"This hook is run when inf-ruby is loaded in.
This is a good place to put keybindings.")
(run-hooks 'inf-ruby-load-hook)
(provide 'inf-ruby)
;;; inf-ruby.el ends here

724
misc/ruby-mode.el Normal file
View file

@ -0,0 +1,724 @@
;;;
;;; ruby-mode.el -
;;;
;;; $Author$
;;; $Date$
;;; created at: Fri Feb 4 14:49:13 JST 1994
;;;
(defconst ruby-mode-revision "$Revision$")
(defconst ruby-mode-version
(progn
(string-match "[0-9.]+" ruby-mode-revision)
(substring ruby-mode-revision (match-beginning 0) (match-end 0))))
(defconst ruby-block-beg-re
"class\\|module\\|def\\|if\\|unless\\|case\\|while\\|until\\|for\\|begin\\|do"
)
(defconst ruby-indent-beg-re
"\\(\\s *\\(class\\|module\\|def\\)\\)\\|if\\|unless\\|case\\|while\\|until\\|for\\|begin"
)
(defconst ruby-modifier-re
"if\\|unless\\|while\\|until"
)
(defconst ruby-block-mid-re
"then\\|else\\|elsif\\|when\\|rescue\\|ensure"
)
(defconst ruby-block-op-re
"and\\|or\\|not"
)
(defconst ruby-block-end-re "end")
(defconst ruby-delimiter
(concat "[?$/%(){}#\"'`.:]\\|\\[\\|\\]\\|\\<\\("
ruby-block-beg-re
"\\|" ruby-block-end-re
"\\)\\>\\|^=begin")
)
(defconst ruby-negative
(concat "^[ \t]*\\(\\(" ruby-block-mid-re "\\)\\>\\|\\("
ruby-block-end-re "\\)\\>\\|\\}\\|\\]\\)")
)
(defconst ruby-operator-chars ",.+*/%-&|^~=<>:")
(defconst ruby-operator-re (concat "[" ruby-operator-chars "]"))
(defconst ruby-symbol-chars "a-zA-Z0-9_")
(defconst ruby-symbol-re (concat "[" ruby-symbol-chars "]"))
(defvar ruby-mode-abbrev-table nil
"Abbrev table in use in ruby-mode buffers.")
(define-abbrev-table 'ruby-mode-abbrev-table ())
(defvar ruby-mode-map nil "Keymap used in ruby mode.")
(if ruby-mode-map
nil
(setq ruby-mode-map (make-sparse-keymap))
(define-key ruby-mode-map "{" 'ruby-electric-brace)
(define-key ruby-mode-map "}" 'ruby-electric-brace)
(define-key ruby-mode-map "\e\C-a" 'ruby-beginning-of-defun)
(define-key ruby-mode-map "\e\C-e" 'ruby-end-of-defun)
(define-key ruby-mode-map "\e\C-b" 'ruby-beginning-of-block)
(define-key ruby-mode-map "\e\C-f" 'ruby-end-of-block)
(define-key ruby-mode-map "\e\C-p" 'ruby-beginning-of-block)
(define-key ruby-mode-map "\e\C-n" 'ruby-end-of-block)
(define-key ruby-mode-map "\e\C-h" 'ruby-mark-defun)
(define-key ruby-mode-map "\t" 'ruby-indent-command)
(define-key ruby-mode-map "\C-c\C-e" 'ruby-insert-end)
(define-key ruby-mode-map "\C-j" 'ruby-reindent-then-newline-and-indent)
(define-key ruby-mode-map "\C-m" 'newline))
(defvar ruby-mode-syntax-table nil
"Syntax table in use in ruby-mode buffers.")
(if ruby-mode-syntax-table
()
(setq ruby-mode-syntax-table (make-syntax-table))
(modify-syntax-entry ?\' "\"" ruby-mode-syntax-table)
(modify-syntax-entry ?\" "\"" ruby-mode-syntax-table)
(modify-syntax-entry ?\` "\"" ruby-mode-syntax-table)
(modify-syntax-entry ?# "<" ruby-mode-syntax-table)
(modify-syntax-entry ?\n ">" ruby-mode-syntax-table)
(modify-syntax-entry ?\\ "\\" ruby-mode-syntax-table)
(modify-syntax-entry ?$ "." ruby-mode-syntax-table)
(modify-syntax-entry ?? "_" ruby-mode-syntax-table)
(modify-syntax-entry ?_ "_" ruby-mode-syntax-table)
(modify-syntax-entry ?< "." ruby-mode-syntax-table)
(modify-syntax-entry ?> "." ruby-mode-syntax-table)
(modify-syntax-entry ?& "." ruby-mode-syntax-table)
(modify-syntax-entry ?| "." ruby-mode-syntax-table)
(modify-syntax-entry ?% "." ruby-mode-syntax-table)
(modify-syntax-entry ?= "." ruby-mode-syntax-table)
(modify-syntax-entry ?/ "." ruby-mode-syntax-table)
(modify-syntax-entry ?+ "." ruby-mode-syntax-table)
(modify-syntax-entry ?* "." ruby-mode-syntax-table)
(modify-syntax-entry ?- "." ruby-mode-syntax-table)
(modify-syntax-entry ?\; "." ruby-mode-syntax-table)
(modify-syntax-entry ?\( "()" ruby-mode-syntax-table)
(modify-syntax-entry ?\) ")(" ruby-mode-syntax-table)
(modify-syntax-entry ?\{ "(}" ruby-mode-syntax-table)
(modify-syntax-entry ?\} "){" ruby-mode-syntax-table)
(modify-syntax-entry ?\[ "(]" ruby-mode-syntax-table)
(modify-syntax-entry ?\] ")[" ruby-mode-syntax-table)
)
(defvar ruby-indent-level 2
"*Indentation of ruby statements.")
(defun ruby-mode-variables ()
(set-syntax-table ruby-mode-syntax-table)
(setq local-abbrev-table ruby-mode-abbrev-table)
(make-local-variable 'indent-line-function)
(setq indent-line-function 'ruby-indent-line)
(make-local-variable 'require-final-newline)
(setq require-final-newline t)
(make-variable-buffer-local 'comment-start)
(setq comment-start "# ")
(make-variable-buffer-local 'comment-end)
(setq comment-end "")
(make-variable-buffer-local 'comment-column)
(setq comment-column 32)
(make-variable-buffer-local 'comment-start-skip)
(setq comment-start-skip "\\(^\\|\\s-\\);?#+ *")
(make-local-variable 'parse-sexp-ignore-comments)
(setq parse-sexp-ignore-comments t)
(make-local-variable 'paragraph-start)
(setq paragraph-start (concat "$\\|" page-delimiter))
(make-local-variable 'paragraph-separate)
(setq paragraph-separate paragraph-start)
(make-local-variable 'paragraph-ignore-fill-prefix)
(setq paragraph-ignore-fill-prefix t))
(defun ruby-mode ()
"Major mode for editing ruby scripts.
\\[ruby-indent-command] properly indents subexpressions of multi-line
class, module, def, if, while, for, do, and case statements, taking
nesting into account.
The variable ruby-indent-level controls the amount of indentation.
\\{ruby-mode-map}"
(interactive)
(kill-all-local-variables)
(use-local-map ruby-mode-map)
(setq mode-name "Ruby")
(setq major-mode 'ruby-mode)
(ruby-mode-variables)
(run-hooks 'ruby-mode-hook))
(defun ruby-current-indentation ()
(save-excursion
(beginning-of-line)
(back-to-indentation)
(current-column)))
(defun ruby-indent-line (&optional flag)
"Correct indentation of the current ruby line."
(ruby-indent-to (ruby-calculate-indent)))
(defun ruby-indent-command ()
(interactive)
(ruby-indent-line t))
(defun ruby-indent-to (x)
(if x
(let (shift top beg)
(and (< x 0)
(error "invalid nest"))
(setq shift (current-column))
(beginning-of-line)
(setq beg (point))
(back-to-indentation)
(setq top (current-column))
(skip-chars-backward " \t")
(cond
((>= x shift)
(setq shift 0))
((>= shift top)
(setq shift (- shift top)))
(t (setq shift 0)))
(if (and (bolp)
(= x top))
(move-to-column (+ x shift))
(move-to-column top)
(delete-region beg (point))
(beginning-of-line)
(indent-to x)
(move-to-column (+ x shift))))))
(defun ruby-expr-beg (&optional modifier)
(save-excursion
(if (looking-at "\\?")
(progn
(or (bolp) (forward-char -1))
(not (looking-at "\\sw")))
(store-match-data nil)
(skip-chars-backward " \t")
(or (bolp) (forward-char -1))
(or (bolp)
(looking-at ruby-operator-re)
(looking-at "[\\[({]")
(and (not modifier) (looking-at "[!?]"))
(and (looking-at ruby-symbol-re)
(forward-word -1)
(if (and (not modifier) (bolp))
t
(if (or (looking-at ruby-block-beg-re)
(looking-at ruby-block-op-re)
(looking-at ruby-block-mid-re))
(progn
(goto-char (match-end 0))
(looking-at "\\>"))
(looking-at "[a-zA-Z][a-zA-z0-9_]* +/[^ \t]"))))))))
(defun ruby-parse-region (start end)
(let ((indent-point end)
(indent 0)
(in-string nil)
(in-paren nil)
(depth 0)
(nest nil)
(pcol nil))
(save-excursion
(if start
(goto-char start)
(ruby-beginning-of-indent))
(save-restriction
(narrow-to-region (point) end)
(while (and (> indent-point (point))
(re-search-forward ruby-delimiter indent-point t))
(or depth (setq depth 0))
(let ((pnt (point)) w)
(goto-char (match-beginning 0))
(cond
((or (looking-at "\"") ;skip string
(looking-at "'")
(looking-at "`"))
(setq w (char-after (point)))
(cond
((and (not (eobp))
(re-search-forward (format "[^\\]\\(\\\\\\\\\\)*%c" w) indent-point t))
nil)
(t
(setq in-string (point))
(goto-char indent-point))))
((looking-at "/")
(cond
((and (not (eobp)) (ruby-expr-beg))
(if (re-search-forward "[^\\]/" indent-point t)
nil
(setq in-string (point))
(goto-char indent-point)))
(t
(goto-char pnt))))
((looking-at "%")
(cond
((and (not (eobp)) (ruby-expr-beg)
(not (looking-at "%="))
(looking-at "%[Qqrxw]?\\(.\\)"))
(setq w (buffer-substring (match-beginning 1)
(match-end 1)))
(cond
((string= w "[") (setq w "]"))
((string= w "{") (setq w "}"))
((string= w "(") (setq w ")"))
((string= w "<") (setq w ">")))
(goto-char (match-end 0))
(if (search-forward w indent-point t)
nil
(setq in-string (point))
(goto-char indent-point)))
(t
(goto-char pnt))))
((looking-at "\\?") ;skip ?char
(cond
((ruby-expr-beg)
(looking-at "?\\(\\\\C-\\|\\\\M-\\)*.")
(goto-char (match-end 0)))
(t
(goto-char pnt))))
((looking-at "\\$") ;skip $char
(goto-char pnt)
(forward-char 1))
((looking-at "#") ;skip comment
(forward-line 1)
(goto-char (point))
)
((looking-at "(")
(setq nest (cons (cons (char-after (point)) pnt) nest))
(setq pcol (cons (cons pnt depth) pcol))
(setq depth 0)
(goto-char pnt)
)
((looking-at "[\\[{]")
(setq nest (cons (cons (char-after (point)) pnt) nest))
(setq depth (1+ depth))
(goto-char pnt)
)
((looking-at ")")
(setq nest (cdr nest))
(setq depth (cdr (car pcol)))
(setq pcol (cdr pcol))
(goto-char pnt))
((looking-at "[])}]")
(setq nest (cdr nest))
(setq depth (1- depth))
(goto-char pnt))
((looking-at ruby-block-end-re)
(if (or (and (not (bolp))
(progn
(forward-char -1)
(eq ?_ (char-after (point)))))
(progn
(goto-char pnt)
(setq w (char-after (point)))
(or (eq ?_ w)
(eq ?! w)
(eq ?? w))))
nil
(setq nest (cdr nest))
(setq depth (1- depth)))
(goto-char pnt))
((looking-at "def\\s +[^(\n;]*")
(if (or (bolp)
(progn
(forward-char -1)
(not (eq ?_ (char-after (point))))))
(progn
(setq nest (cons (cons nil pnt) nest))
(setq depth (1+ depth))))
(goto-char (match-end 0)))
((looking-at ruby-block-beg-re)
(and
(or (bolp)
(progn
(forward-char -1)
(not (eq ?_ (char-after (point))))))
(goto-char pnt)
(setq w (char-after (point)))
(not (eq ?_ w))
(not (eq ?! w))
(not (eq ?? w))
(skip-chars-forward " \t")
(if (not (eolp))
(progn
(goto-char (match-beginning 0))
(if (looking-at ruby-modifier-re)
(ruby-expr-beg t)
t))
t)
(goto-char pnt)
(setq nest (cons (cons nil pnt) nest))
(setq depth (1+ depth)))
(goto-char pnt))
((looking-at ":\\([a-zA-Z_][a-zA-Z_0-9]*\\)?")
(goto-char (match-end 0)))
((or (looking-at "\\.")
(looking-at "\\.\\.\\.?")
(looking-at "\\.[0-9]+")
(looking-at "\\.[a-zA-Z_0-9]+"))
(goto-char (match-end 0)))
((looking-at "^=begin")
(if (re-search-forward "^=end" indent-point t)
(forward-line 1)
(setq in-string (match-end 0))
(goto-char indent-point)))
(t
(error (format "bad string %s"
(buffer-substring (point) pnt)
)))))))
(list in-string (car nest) depth (car (car pcol))))))
(defun ruby-indent-size (pos nest)
(+ pos (* (if nest nest 1) ruby-indent-level)))
(defun ruby-calculate-indent (&optional parse-start)
(save-excursion
(beginning-of-line)
(let ((indent-point (point))
(case-fold-search nil)
state bol eol
(indent 0))
(if parse-start
(goto-char parse-start)
(ruby-beginning-of-indent)
(setq parse-start (point)))
(back-to-indentation)
(setq indent (current-column))
(setq state (ruby-parse-region parse-start indent-point))
(cond
((nth 0 state) ; within string
(setq indent nil)) ; do nothing
((car (nth 1 state)) ; in paren
(goto-char (cdr (nth 1 state)))
(if (eq (car (nth 1 state)) ?\( )
(let ((column (current-column))
(s (ruby-parse-region (point) indent-point)))
(cond
((and (nth 2 s) (> (nth 2 s) 0))
(goto-char (cdr (nth 1 s)))
(forward-word -1)
(setq indent (ruby-indent-size (current-column) (nth 2 state))))
(t
(setq indent (current-column)))))
(cond
((nth 3 state)
(goto-char (nth 3 state))
(setq indent (ruby-indent-size (current-column) (nth 2 state))))
(t
(goto-char parse-start)
(back-to-indentation)
(setq indent (ruby-indent-size (current-column) (nth 2 state)))))
))
((and (nth 2 state)(> (nth 2 state) 0)) ; in nest
(if (null (cdr (nth 1 state)))
(error "invalid nest"))
(goto-char (cdr (nth 1 state)))
(forward-word -1) ; skip back a keyword
(cond
((looking-at "do") ; iter block is a special case
(cond
((nth 3 state)
(goto-char (nth 3 state))
(setq indent (ruby-indent-size (current-column) (nth 2 state))))
(t
(goto-char parse-start)
(back-to-indentation)
(setq indent (ruby-indent-size (current-column) (nth 2 state))))))
(t
(setq indent (+ (current-column) ruby-indent-level)))))
((and (nth 2 state) (< (nth 2 state) 0)) ; in negative nest
(setq indent (ruby-indent-size (current-column) (nth 2 state)))))
(cond
(indent
(goto-char indent-point)
(end-of-line)
(setq eol (point))
(beginning-of-line)
(cond
((re-search-forward ruby-negative eol t)
(and (not (eq ?_ (char-after (match-end 0))))
(setq indent (- indent ruby-indent-level))))
;;operator terminated lines
((and
(save-excursion
(beginning-of-line)
(not (bobp)))
(or (null (car (nth 1 state))) ;not in parens
(and (eq (car (nth 1 state)) ?\{)
(save-excursion ;except non-block braces
(goto-char (cdr (nth 1 state)))
(or (bobp) (forward-char -1))
(not (ruby-expr-beg))))))
;; goto beginning of non-empty no-comment line
(let (end done)
(while (not done)
(skip-chars-backward " \t\n")
(setq end (point))
(beginning-of-line)
(if (re-search-forward "^\\s *#" end t)
(beginning-of-line)
(setq done t))))
(setq bol (point))
(end-of-line)
(skip-chars-backward " \t")
(and (re-search-backward "#" (save-excursion
(beginning-of-line)
(point)) t)
(setq state (ruby-parse-region parse-start (point)))
(nth 0 state)
(goto-char (nth 0 state)))
(or (bobp) (forward-char -1))
(and
(or (and (looking-at ruby-symbol-re)
(skip-chars-backward ruby-symbol-chars)
(looking-at ruby-block-op-re)
(save-excursion
(goto-char (match-end 0))
(not (looking-at "[a-z_]"))))
(and (looking-at ruby-operator-re)
(or (not (eq ?/ (char-after (point))))
(null (nth 0 (ruby-parse-region parse-start (point)))))
(not (eq (char-after (1- (point))) ?$))
(or (not (eq ?| (char-after (point))))
(save-excursion
(or (eolp) (forward-char -1))
(and (search-backward "|")
(skip-chars-backward " \t\n")
(and (not (eolp))
(progn
(forward-char -1)
(not (looking-at "\\{")))
(progn
(forward-word -1)
(not (looking-at "do\\>[^_]")))))))))
(setq indent (+ indent ruby-indent-level)))))))
indent)))
(defun ruby-electric-brace (arg)
(interactive "P")
(self-insert-command (prefix-numeric-value arg))
(ruby-indent-line t))
(defun ruby-beginning-of-defun (&optional arg)
"Move backward to next beginning-of-defun.
With argument, do this that many times.
Returns t unless search stops due to end of buffer."
(interactive "p")
(and (re-search-backward (concat "^\\(" ruby-block-beg-re "\\)\\b")
nil 'move (or arg 1))
(progn (beginning-of-line) t)))
(defun ruby-beginning-of-indent ()
(and (re-search-backward (concat "^\\(" ruby-indent-beg-re "\\)\\b")
nil 'move)
(progn
(beginning-of-line)
t)))
(defun ruby-end-of-defun (&optional arg)
"Move forward to next end of defun.
An end of a defun is found by moving forward from the beginning of one."
(interactive "p")
(and (re-search-forward (concat "^\\(" ruby-block-end-re "\\)\\($\\|\\b[^_]\\)")
nil 'move (or arg 1))
(progn (beginning-of-line) t))
(forward-line 1))
(defun ruby-move-to-block (n)
(let (start pos done down)
(setq start (ruby-calculate-indent))
(if (eobp)
nil
(while (and (not (bobp)) (not done))
(forward-line n)
(cond
((looking-at "^$"))
((looking-at "^\\s *#"))
(t
(setq pos (current-indentation))
(cond
((< start pos)
(setq down t))
((and down (= pos start))
(setq done t))
((> start pos)
(setq done t)))))
(if done
(progn
(back-to-indentation)
(if (looking-at ruby-block-mid-re)
(setq done nil)))))))
(back-to-indentation))
(defun ruby-beginning-of-block ()
"Move backward to next beginning-of-block"
(interactive)
(ruby-move-to-block -1))
(defun ruby-end-of-block ()
"Move forward to next beginning-of-block"
(interactive)
(ruby-move-to-block 1))
(defun ruby-reindent-then-newline-and-indent ()
(interactive "*")
(save-excursion
(delete-region (point) (progn (skip-chars-backward " \t") (point))))
(newline)
(save-excursion
(forward-line -1)
(indent-according-to-mode))
(indent-according-to-mode))
(fset 'ruby-encomment-region (symbol-function 'comment-region))
(defun ruby-decomment-region (beg end)
(interactive "r")
(save-excursion
(goto-char beg)
(while (re-search-forward "^\\([ \t]*\\)#" end t)
(replace-match "\\1" nil nil)
(save-excursion
(ruby-indent-line)))))
(defun ruby-insert-end ()
(interactive)
(insert "end")
(ruby-indent-line t)
(end-of-line))
(defun ruby-mark-defun ()
"Put mark at end of this Ruby function, point at beginning."
(interactive)
(push-mark (point))
(ruby-end-of-defun)
(push-mark (point) nil t)
(ruby-beginning-of-defun)
(re-search-backward "^\n" (- (point) 1) t))
(cond
((featurep 'font-lock)
(or (boundp 'font-lock-variable-name-face)
(setq font-lock-variable-name-face font-lock-type-face))
(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)))
(defun ruby-font-lock-docs (limit)
(if (re-search-forward "^=begin\\s *$" limit t)
(let (beg)
(beginning-of-line)
(setq beg (point))
(forward-line 1)
(if (re-search-forward "^=end\\s *$" limit t)
(progn
(set-match-data (list beg (point)))
t)))))
(defvar ruby-font-lock-keywords
(list
(cons (concat
"\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\("
(mapconcat
'identity
'("alias"
"and"
"begin"
"break"
"case"
"catch"
"class"
"def"
"do"
"elsif"
"else"
"fail"
"ensure"
"for"
"end"
"if"
"in"
"module"
"next"
"not"
"or"
"raise"
"redo"
"rescue"
"retry"
"return"
"then"
"throw"
"self"
"super"
"unless"
"undef"
"until"
"when"
"while"
)
"\\|")
"\\)\\>[^_]")
2)
;; variables
'("\\b\\(nil\\|self\\|true\\|false\\)\\b"
1 font-lock-variable-name-face)
;; variables
'("[$@].\\(\\w\\|_\\)*"
0 font-lock-variable-name-face)
;; embedded document
'(ruby-font-lock-docs
0 font-lock-comment-face t)
;; constants
'("\\(^\\|[^_]\\)\\b\\([A-Z]+\\(\\w\\|_\\)*\\)"
2 font-lock-type-face)
;; functions
'("^\\s *def\\s *\\<\\(\\(\\w\\|_\\)+\\(\\.\\|::\\)\\)?\\(\\(\\w\\|_\\)+\\??\\)\\>"
4 font-lock-function-name-face t)
;; symbols
'("\\(^\\|[^:]\\)\\(:\\(\\w\\|_\\)+\\??\\)\\b"
2 font-lock-reference-face))
"*Additional expressions to highlight in ruby mode."))
((featurep 'hilit19)
(hilit-set-mode-patterns
'ruby-mode
'(("[^$\\?]\\(\"[^\\\"]*\\(\\\\\\(.\\|\n\\)[^\\\"]*\\)*\"\\)" 1 string)
("[^$\\?]\\('[^\\']*\\(\\\\\\(.\\|\n\\)[^\\']*\\)*'\\)" 1 string)
("[^$\\?]\\(`[^\\`]*\\(\\\\\\(.\\|\n\\)[^\\`]*\\)*`\\)" 1 string)
("^\\s *#.*$" nil comment)
("[^$@?\\]\\(#[^$@{\n].*$\\)" 1 comment)
("[^a-zA-Z_]\\(\\?\\(\\\\[CM]-\\)*.\\)" 1 string)
("^\\s *\\(require\\|load\\).*$" nil include)
("^\\s *\\(include\\|alias\\|undef\\).*$" nil decl)
("^\\s *\\<\\(class\\|def\\|module\\)\\>" "[)\n;]" defun)
("[^_]\\<\\(begin\\|case\\|else\\|elsif\\|end\\|ensure\\|for\\|if\\|unless\\|rescue\\|then\\|when\\|while\\|until\\|do\\)\\>[^_]" 1 defun)
("[^_]\\<\\(and\\|break\\|next\\|raise\\|fail\\|in\\|not\\|or\\|redo\\|retry\\|return\\|super\\|yield\\|catch\\|throw\\|self\\|nil\\)\\>[^_]" 1 keyword)
("\\$\\(.\\|\\sw+\\)" nil type)
("[$@].[a-zA-Z_0-9]*" nil struct)
("^__END__" nil label))))
)
(provide 'ruby-mode)

104
misc/rubydb2x.el Normal file
View file

@ -0,0 +1,104 @@
(require 'gud)
(provide 'rubydb)
;; ======================================================================
;; rubydb functions
;;; History of argument lists passed to rubydb.
(defvar gud-rubydb-history nil)
(defun gud-rubydb-massage-args (file args)
(cons "-I" (cons "." (cons "-r" (cons "debug" (cons file args))))))
;; There's no guarantee that Emacs will hand the filter the entire
;; marker at once; it could be broken up across several strings. We
;; might even receive a big chunk with several markers in it. If we
;; receive a chunk of text which looks like it might contain the
;; beginning of a marker, we save it here between calls to the
;; filter.
(defvar gud-rubydb-marker-acc "")
(defun gud-rubydb-marker-filter (string)
(save-match-data
(setq gud-marker-acc (concat gud-marker-acc string))
(let ((output ""))
;; Process all the complete markers in this chunk.
(while (string-match "\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n"
gud-marker-acc)
(setq
;; Extract the frame position from the marker.
gud-last-frame
(cons (substring gud-marker-acc (match-beginning 1) (match-end 1))
(string-to-int (substring gud-marker-acc
(match-beginning 2)
(match-end 2))))
;; Append any text before the marker to the output we're going
;; to return - we don't include the marker in this text.
output (concat output
(substring gud-marker-acc 0 (match-beginning 0)))
;; Set the accumulator to the remaining text.
gud-marker-acc (substring gud-marker-acc (match-end 0))))
;; Does the remaining text look like it might end with the
;; beginning of another marker? If it does, then keep it in
;; gud-marker-acc until we receive the rest of it. Since we
;; know the full marker regexp above failed, it's pretty simple to
;; test for marker starts.
(if (string-match "\032.*\\'" gud-marker-acc)
(progn
;; Everything before the potential marker start can be output.
(setq output (concat output (substring gud-marker-acc
0 (match-beginning 0))))
;; Everything after, we save, to combine with later input.
(setq gud-marker-acc
(substring gud-marker-acc (match-beginning 0))))
(setq output (concat output gud-marker-acc)
gud-marker-acc ""))
output)))
(defun gud-rubydb-find-file (f)
(find-file-noselect f))
(defvar rubydb-command-name "ruby"
"File name for executing ruby.")
;;;###autoload
(defun rubydb (command-line)
"Run rubydb on program FILE in buffer *gud-FILE*.
The directory containing FILE becomes the initial working directory
and source-file directory for your debugger."
(interactive
(list (read-from-minibuffer "Run rubydb (like this): "
(if (consp gud-rubydb-history)
(car gud-rubydb-history)
(concat rubydb-command-name " "))
nil nil
'(gud-rubydb-history . 1))))
(gud-overload-functions '((gud-massage-args . gud-rubydb-massage-args)
(gud-marker-filter . gud-rubydb-marker-filter)
(gud-find-file . gud-rubydb-find-file)
))
(gud-common-init command-line)
(gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.")
; (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line")
(gud-def gud-step "s" "\C-s" "Step one source line with display.")
(gud-def gud-next "n" "\C-n" "Step one line (skip functions).")
(gud-def gud-cont "c" "\C-r" "Continue with display.")
(gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
(gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
(gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
(gud-def gud-print "p %e" "\C-p" "Evaluate ruby expression at point.")
(setq comint-prompt-regexp "^(rdb:-) ")
(setq paragraph-start comint-prompt-regexp)
(run-hooks 'rubydb-mode-hook)
)

113
misc/rubydb3x.el Normal file
View file

@ -0,0 +1,113 @@
(require 'gud)
(provide 'rubydb)
;; ======================================================================
;; rubydb functions
;;; History of argument lists passed to rubydb.
(defvar gud-rubydb-history nil)
(if (fboundp 'gud-overload-functions)
(defun gud-rubydb-massage-args (file args)
(cons "-r" (cons "debug" (cons file args))))
(defun gud-rubydb-massage-args (file args)
(cons "-r" (cons "debug" args))))
;; There's no guarantee that Emacs will hand the filter the entire
;; marker at once; it could be broken up across several strings. We
;; might even receive a big chunk with several markers in it. If we
;; receive a chunk of text which looks like it might contain the
;; beginning of a marker, we save it here between calls to the
;; filter.
(defvar gud-rubydb-marker-acc "")
(make-variable-buffer-local 'gud-rubydb-marker-acc)
(defun gud-rubydb-marker-filter (string)
(setq gud-rubydb-marker-acc (concat gud-rubydb-marker-acc string))
(let ((output ""))
;; Process all the complete markers in this chunk.
(while (string-match "\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n"
gud-rubydb-marker-acc)
(setq
;; Extract the frame position from the marker.
gud-last-frame
(cons (substring gud-rubydb-marker-acc (match-beginning 1) (match-end 1))
(string-to-int (substring gud-rubydb-marker-acc
(match-beginning 2)
(match-end 2))))
;; Append any text before the marker to the output we're going
;; to return - we don't include the marker in this text.
output (concat output
(substring gud-rubydb-marker-acc 0 (match-beginning 0)))
;; Set the accumulator to the remaining text.
gud-rubydb-marker-acc (substring gud-rubydb-marker-acc (match-end 0))))
;; Does the remaining text look like it might end with the
;; beginning of another marker? If it does, then keep it in
;; gud-rubydb-marker-acc until we receive the rest of it. Since we
;; know the full marker regexp above failed, it's pretty simple to
;; test for marker starts.
(if (string-match "\032.*\\'" gud-rubydb-marker-acc)
(progn
;; Everything before the potential marker start can be output.
(setq output (concat output (substring gud-rubydb-marker-acc
0 (match-beginning 0))))
;; Everything after, we save, to combine with later input.
(setq gud-rubydb-marker-acc
(substring gud-rubydb-marker-acc (match-beginning 0))))
(setq output (concat output gud-rubydb-marker-acc)
gud-rubydb-marker-acc ""))
output))
(defun gud-rubydb-find-file (f)
(save-excursion
(let ((buf (find-file-noselect f)))
(set-buffer buf)
;; (gud-make-debug-menu)
buf)))
(defvar rubydb-command-name "ruby"
"File name for executing ruby.")
;;;###autoload
(defun rubydb (command-line)
"Run rubydb on program FILE in buffer *gud-FILE*.
The directory containing FILE becomes the initial working directory
and source-file directory for your debugger."
(interactive
(list (read-from-minibuffer "Run rubydb (like this): "
(if (consp gud-rubydb-history)
(car gud-rubydb-history)
(concat rubydb-command-name " "))
nil nil
'(gud-rubydb-history . 1))))
(if (not (fboundp 'gud-overload-functions))
(gud-common-init command-line 'gud-rubydb-massage-args
'gud-rubydb-marker-filter 'gud-rubydb-find-file)
(gud-overload-functions '((gud-massage-args . gud-rubydb-massage-args)
(gud-marker-filter . gud-rubydb-marker-filter)
(gud-find-file . gud-rubydb-find-file)))
(gud-common-init command-line rubydb-command-name))
(gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.")
; (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line")
(gud-def gud-step "s" "\C-s" "Step one source line with display.")
(gud-def gud-next "n" "\C-n" "Step one line (skip functions).")
(gud-def gud-cont "c" "\C-r" "Continue with display.")
(gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
(gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
(gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
(gud-def gud-print "p %e" "\C-p" "Evaluate ruby expression at point.")
(setq comint-prompt-regexp "^(rdb:-) ")
(set (make-local-variable 'paragraph-start) comint-prompt-regexp)
(run-hooks 'rubydb-mode-hook)
)

View file

@ -1,36 +1,61 @@
/* /*
* Copyright (c) 1991, Larry Wall * Public domain dup2() lookalike
* by Curtis Jackson @ AT&T Technologies, Burlington, NC
* electronic address: burl!rcj
* *
* You may distribute under the terms of either the GNU General Public * dup2 performs the following functions:
* License or the Artistic License, as specified in the README file. *
* Check to make sure that fd1 is a valid open file descriptor.
* Check to see if fd2 is already open; if so, close it.
* Duplicate fd1 onto fd2; checking to make sure fd2 is a valid fd.
* Return fd2 if all went well; return BADEXIT otherwise.
*/ */
#include "defines.h" #include "config.h"
#if defined(HAVE_FCNTL) && defined(F_DUPFD) #if defined(HAVE_FCNTL)
# include <fcntl.h> # include <fcntl.h>
#endif #endif
#if !defined(HAVE_FCNTL) || !defined(F_DUPFD)
# include <errno.h>
#endif
#define BADEXIT -1
int int
dup2(oldfd,newfd) dup2(fd1, fd2)
int oldfd; int fd1, fd2;
int newfd;
{ {
#if defined(HAVE_FCNTL) && defined(F_DUPFD) #if defined(HAVE_FCNTL) && defined(F_DUPFD)
close(newfd); if (fd1 != fd2) {
return fcntl(oldfd, F_DUPFD, newfd); #ifdef F_GETFL
if (fcntl(fd1, F_GETFL) < 0)
return BADEXIT;
if (fcntl(fd2, F_GETFL) >= 0)
close(fd2);
#else #else
int fdtmp[256]; close(fd2);
int fdx = 0; #endif
int fd; if (fcntl(fd1, F_DUPFD, fd2) < 0)
return BADEXIT;
}
return fd2;
#else
extern int errno;
int i, fd, fds[256];
if (oldfd == newfd) if (fd1 == fd2) return 0;
return 0; close(fd2);
close(newfd); for (i=0; i<256; i++) {
while ((fd = dup(oldfd)) != newfd) /* good enough for low fd's */ fd = fds[i] = dup(fd1);
fdtmp[fdx++] = fd; if (fd == fd2) break;
while (fdx > 0) }
close(fdtmp[--fdx]); while (i) {
return 0; close(fds[i--]);
}
if (fd == fd2) return 0;
errno = EMFILE;
return BADEXIT;
#endif #endif
} }

6
missing/finite.c Normal file
View file

@ -0,0 +1,6 @@
int
finite(n)
double n;
{
return !isnan(n) && !isinf(n);
}

199
missing/fnmatch.c Normal file
View file

@ -0,0 +1,199 @@
/*
* Copyright (c) 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Guido van Rossum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
#endif /* LIBC_SCCS and not lint */
/*
* Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
* Compares a filename or pathname to a pattern.
*/
#include "missing/fnmatch.h"
#include <string.h>
#define EOS '\0'
static char *rangematch();
int
fnmatch(pattern, string, flags)
char *pattern;
char *string;
int flags;
{
char *stringstart;
char c, test;
for (stringstart = string;;) {
switch (c = *pattern++) {
case EOS:
return (*string == EOS ? 0 : FNM_NOMATCH);
case '?':
if (*string == EOS) {
return (FNM_NOMATCH);
}
if (*string == '/' && (flags & FNM_PATHNAME)) {
return (FNM_NOMATCH);
}
if (*string == '.' && (flags & FNM_PERIOD) &&
(string == stringstart ||
((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
return (FNM_NOMATCH);
}
++string;
break;
case '*':
c = *pattern;
/* Collapse multiple stars. */
while (c == '*') {
c = *++pattern;
}
if (*string == '.' && (flags & FNM_PERIOD) &&
(string == stringstart ||
((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
return (FNM_NOMATCH);
}
/* Optimize for pattern with * at end or before /. */
if (c == EOS) {
if (flags & FNM_PATHNAME) {
return (strchr(string, '/') == NULL ? 0 : FNM_NOMATCH);
}
else {
return (0);
}
}
else if (c == '/' && flags & FNM_PATHNAME) {
if ((string = strchr(string, '/')) == NULL) {
return (FNM_NOMATCH);
}
break;
}
/* General case, use recursion. */
while ((test = *string) != EOS) {
if (!fnmatch(pattern, string, flags & ~FNM_PERIOD)) {
return (0);
}
if (test == '/' && flags & FNM_PATHNAME) {
break;
}
++string;
}
return (FNM_NOMATCH);
case '[':
if (*string == EOS) {
return (FNM_NOMATCH);
}
if (*string == '/' && flags & FNM_PATHNAME) {
return (FNM_NOMATCH);
}
if (*string == '.' && (flags & FNM_PERIOD) &&
(string == stringstart ||
((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
return (FNM_NOMATCH);
}
if ((pattern = rangematch(pattern, *string, flags)) == NULL) {
return (FNM_NOMATCH);
}
++string;
break;
case '\\':
if (!(flags & FNM_NOESCAPE)) {
if ((c = *pattern++) == EOS) {
c = '\\';
--pattern;
}
}
/* FALLTHROUGH */
default:
if (c != *string) {
return (FNM_NOMATCH);
}
string++;
break;
}
/* NOTREACHED */
}
}
static char*
rangematch(pattern, test, flags)
char *pattern;
int test, flags;
{
int negate, ok;
char c, c2;
/*
* A bracket expression starting with an unquoted circumflex
* character produces unspecified results (IEEE 1003.2-1992,
* 3.13.2). This implementation treats it like '!', for
* consistency with the regular expression syntax.
* J.T. Conklin (conklin@ngai.kaleida.com)
*/
if ((negate = (*pattern == '!' || *pattern == '^'))) {
++pattern;
}
for (ok = 0; (c = *pattern++) != ']';) {
if (c == '\\' && !(flags & FNM_NOESCAPE)) {
c = *pattern++;
}
if (c == EOS) {
return (NULL);
}
if (*pattern == '-' && (c2 = *(pattern + 1)) != EOS && c2 != ']') {
pattern += 2;
if (c2 == '\\' && !(flags & FNM_NOESCAPE)) {
c2 = *pattern++;
}
if (c2 == EOS) {
return (NULL);
}
if (c <= test && test <= c2) {
ok = 1;
}
}
else if (c == test) {
ok = 1;
}
}
return (ok == negate ? NULL : pattern);
}

57
missing/fnmatch.h Normal file
View file

@ -0,0 +1,57 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)fnmatch.h 8.1 (Berkeley) 6/2/93
*/
/* This file has been modified by matz@netlab.co.jp */
#ifndef _FNMATCH_H_
#define _FNMATCH_H_
#ifdef __cplusplus
extern "C" {
#endif
#define FNM_NOMATCH 1 /* Match failed. */
#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
#define FNM_PERIOD 0x04 /* Period must be matched by period. */
int fnmatch();
#ifdef __cplusplus
}
#endif
#endif /* !_FNMATCH_H_ */

44
missing/isinf.c Normal file
View file

@ -0,0 +1,44 @@
#ifdef __osf__
#define _IEEE 1
#include <nan.h>
int
isinf(n)
double n;
{
if (IsNANorINF(n) && IsINF(n)) {
return 1;
} else {
return 0;
}
}
#else
#include "config.h"
#ifdef HAVE_STRING_H
# include <string.h>
#else
# include <strings.h>
#endif
static double zero() { return 0.0; }
static double one() { return 1.0; }
static double inf() { return one() / zero(); }
int
isinf(n)
double n;
{
static double pinf = 0.0;
static double ninf = 0.0;
if (pinf == 0.0) {
pinf = inf();
ninf = -pinf;
}
return memcmp(&n, &pinf, sizeof n) == 0
|| memcmp(&n, &ninf, sizeof n) == 0;
}
#endif

16
missing/isnan.c Normal file
View file

@ -0,0 +1,16 @@
static int double_ne();
int
isnan(n)
double n;
{
return double_ne(n, n);
}
static
int
double_ne(n1, n2)
double n1, n2;
{
return n1 != n2;
}

21
missing/memcmp.c Normal file
View file

@ -0,0 +1,21 @@
/*
* memcmp --- compare memories.
*
*/
int
memcmp(s1,s2,len)
char *s1;
char *s2;
register int len;
{
register unsigned char *a = (unsigned char*)s1;
register unsigned char *b = (unsigned char*)s2;
register int tmp;
while (len--) {
if (tmp = *a++ - *b++)
return tmp;
}
return 0;
}

111
missing/os2.c Normal file
View file

@ -0,0 +1,111 @@
#include "ruby.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <process.h>
#include <limits.h>
#include <errno.h>
#define INCL_DOS
#include <os2.h>
int
chown(char *path, int owner, int group)
{
return 0;
}
int
link(char *from, char *to)
{
return -1;
}
typedef char* CHARP;
int
do_spawn(cmd)
char *cmd;
{
register char **a;
register char *s;
char **argv;
char *shell, *sw, *cmd2;
int status;
if ((shell = getenv("RUBYSHELL")) != NULL && *shell != '\0') {
s = shell;
do
*s = isupper(*s) ? tolower(*s) : *s;
while (*++s);
if (strstr(shell, "cmd") || strstr(shell, "4os2"))
sw = "/c";
else
sw = "-c";
} else if ((shell = getenv("SHELL")) != NULL && *shell != '\0') {
s = shell;
do
*s = isupper(*s) ? tolower(*s) : *s;
while (*++s);
if (strstr(shell, "cmd") || strstr(shell, "4os2"))
sw = "/c";
else
sw = "-c";
} else if ((shell = getenv("COMSPEC")) != NULL && *shell != '\0') {
s = shell;
do
*s = isupper(*s) ? tolower(*s) : *s;
while (*++s);
if (strstr(shell, "cmd") || strstr(shell, "4os2"))
sw = "/c";
else
sw = "-c";
}
/* see if there are shell metacharacters in it */
/*SUPPRESS 530*/
/* for (s = cmd; *s && isalpha(*s); s++) ;
if (*s == '=')
goto doshell; */
for (s = cmd; *s; s++) {
if (*sw == '-' && *s != ' ' &&
!isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
if (*s == '\n' && !s[1]) {
*s = '\0';
break;
}
goto doshell;
} else if (*sw == '/' && *s != ' ' &&
!isalpha(*s) && index("^()<>|&\n",*s)) {
if (*s == '\n' && !s[1]) {
*s = '\0';
break;
}
doshell:
status = spawnlp(P_WAIT,shell,shell,sw,cmd,(char*)NULL);
return status;
}
}
argv = ALLOC_N(CHARP,(strlen(cmd) / 2 + 2));
cmd2 = ALLOC_N(char, (strlen(cmd) + 1));
strcpy(cmd2, cmd);
a = argv;
for (s = cmd2; *s;) {
while (*s && isspace(*s)) s++;
if (*s)
*(a++) = s;
while (*s && !isspace(*s)) s++;
if (*s)
*s++ = '\0';
}
*a = NULL;
if (argv[0]) {
if ((status = spawnvp(P_WAIT, argv[0], argv)) == -1) {
free(argv);
free(cmd2);
return -1;
}
}
free(cmd2);
free(argv);
return status;
}

View file

@ -1,6 +1,5 @@
#include <ctype.h> #include <ctype.h>
#define min(a,b) (((a)>(b))?(b):(a))
int int
strcasecmp(p1, p2) strcasecmp(p1, p2)
char *p1, *p2; char *p1, *p2;

45
missing/strchr.c Normal file
View file

@ -0,0 +1,45 @@
/*
* strchr --- search a string for a character
*
* We supply this routine for those systems that aren't standard yet.
*/
#include <stdio.h>
char *
strchr(str, c)
register const char *str, c;
{
if (c == '\0') {
/* thanks to Mike Brennan ... */
do {
if (*str == c)
return (char *) str;
} while (*str++);
} else {
for (; *str; str++)
if (*str == c)
return (char *) str;
}
return NULL;
}
/*
* strrchr --- find the last occurrence of a character in a string
*
* We supply this routine for those systems that aren't standard yet.
*/
char *
strrchr(str, c)
register const char *str, c;
{
register const char *save = NULL;
for (; *str; str++)
if (*str == c)
save = str;
return (char *) save;
}

View file

@ -45,6 +45,8 @@
* January 1996 * January 1996
*/ */
#include "config.h"
#ifndef GAWK #ifndef GAWK
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <ctype.h>
@ -92,23 +94,25 @@
#ifndef __STDC__ #ifndef __STDC__
#define const /**/ #define const /**/
extern void *malloc();
extern void *realloc();
extern void tzset(); extern void tzset();
extern char *strchr();
extern char *getenv();
static int weeknumber(); static int weeknumber();
adddecl(static int iso8601wknum();) adddecl(static int iso8601wknum();)
#else #else
extern void *malloc(unsigned count);
extern void *realloc(void *ptr, unsigned count);
extern void tzset(void); extern void tzset(void);
extern char *strchr(const char *str, int ch);
extern char *getenv(const char *v);
static int weeknumber(const struct tm *timeptr, int firstweekday); static int weeknumber(const struct tm *timeptr, int firstweekday);
adddecl(static int iso8601wknum(const struct tm *timeptr);) adddecl(static int iso8601wknum(const struct tm *timeptr);)
#endif #endif
#ifdef STDC_HEADERS
#include <stdlib.h>
#include <string.h>
#else
extern void *malloc();
extern void *realloc();
extern char *getenv();
extern char *strchr();
#endif
#ifdef __GNUC__ #ifdef __GNUC__
#define inline __inline__ #define inline __inline__
#else #else
@ -348,8 +352,8 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
strcpy(tbuf, ampm[1]); strcpy(tbuf, ampm[1]);
break; break;
case 'S': /* second, 00 - 61 */ case 'S': /* second, 00 - 60 */
i = range(0, timeptr->tm_sec, 61); i = range(0, timeptr->tm_sec, 60);
sprintf(tbuf, "%02d", i); sprintf(tbuf, "%02d", i);
break; break;
@ -504,7 +508,7 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
#ifdef VMS_EXT #ifdef VMS_EXT
case 'v': /* date as dd-bbb-YYYY */ case 'v': /* date as dd-bbb-YYYY */
sprintf(tbuf, "%02d-%3.3s-%4d", sprintf(tbuf, "%2d-%3.3s-%4d",
range(1, timeptr->tm_mday, 31), range(1, timeptr->tm_mday, 31),
months_a[range(0, timeptr->tm_mon, 11)], months_a[range(0, timeptr->tm_mon, 11)],
timeptr->tm_year + 1900); timeptr->tm_year + 1900);
@ -562,7 +566,7 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
else else
sprintf(tbuf, "%02d", y % 100); sprintf(tbuf, "%02d", y % 100);
break; break;
#endif ISO_DATE_EXT #endif /* ISO_DATE_EXT */
default: default:
tbuf[0] = '%'; tbuf[0] = '%';
tbuf[1] = *format; tbuf[1] = *format;
@ -826,7 +830,7 @@ static char *array[] =
"(%%M) minute (00..59) %M", "(%%M) minute (00..59) %M",
"(%%O) Locale extensions (ignored) %O", "(%%O) Locale extensions (ignored) %O",
"(%%R) time, 24-hour (%%H:%%M) %R", "(%%R) time, 24-hour (%%H:%%M) %R",
"(%%S) second (00..61) %S", "(%%S) second (00..60) %S",
"(%%T) time, 24-hour (%%H:%%M:%%S) %T", "(%%T) time, 24-hour (%%H:%%M:%%S) %T",
"(%%U) week of year, Sunday as first day of week (00..53) %U", "(%%U) week of year, Sunday as first day of week (00..53) %U",
"(%%V) week of year according to ISO 8601 %V", "(%%V) week of year according to ISO 8601 %V",

18
missing/strncasecmp.c Normal file
View file

@ -0,0 +1,18 @@
#include <ctype.h>
int
strncasecmp(p1, p2, len)
char *p1;
char *p2;
int len;
{
for (; len != 0; len--, p1++, p2++) {
if (toupper(*p1) != toupper(*p2)) {
return toupper(*p1) - toupper(*p2);
}
if (*p1 == '\0') {
return 0;
}
}
return 0;
}

266
missing/strtod.c Normal file
View file

@ -0,0 +1,266 @@
/*
* strtod.c --
*
* Source code for the "strtod" library procedure.
*
* Copyright (c) 1988-1993 The Regents of the University of California.
* Copyright (c) 1994 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* RCS: @(#) $Id$
*/
#include "config.h"
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include <ctype.h>
#include <errno.h>
extern int errno;
#ifndef __STDC__
# ifdef __GNUC__
# define const __const__
# else
# define const
# endif
#endif
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#ifndef NULL
#define NULL 0
#endif
static int maxExponent = 511; /* Largest possible base 10 exponent. Any
* exponent larger than this will already
* produce underflow or overflow, so there's
* no need to worry about additional digits.
*/
static double powersOf10[] = { /* Table giving binary powers of 10. Entry */
10., /* is 10^2^i. Used to convert decimal */
100., /* exponents into floating-point numbers. */
1.0e4,
1.0e8,
1.0e16,
1.0e32,
1.0e64,
1.0e128,
1.0e256
};
/*
*----------------------------------------------------------------------
*
* strtod --
*
* This procedure converts a floating-point number from an ASCII
* decimal representation to internal double-precision format.
*
* Results:
* The return value is the double-precision floating-point
* representation of the characters in string. If endPtr isn't
* NULL, then *endPtr is filled in with the address of the
* next character after the last one that was part of the
* floating-point number.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
double
strtod(string, endPtr)
const char *string; /* A decimal ASCII floating-point number,
* optionally preceded by white space.
* Must have form "-I.FE-X", where I is the
* integer part of the mantissa, F is the
* fractional part of the mantissa, and X
* is the exponent. Either of the signs
* may be "+", "-", or omitted. Either I
* or F may be omitted, or both. The decimal
* point isn't necessary unless F is present.
* The "E" may actually be an "e". E and X
* may both be omitted (but not just one).
*/
char **endPtr; /* If non-NULL, store terminating character's
* address here. */
{
int sign, expSign = FALSE;
double fraction, dblExp, *d;
register const char *p;
register int c;
int exp = 0; /* Exponent read from "EX" field. */
int fracExp = 0; /* Exponent that derives from the fractional
* part. Under normal circumstatnces, it is
* the negative of the number of digits in F.
* However, if I is very long, the last digits
* of I get dropped (otherwise a long I with a
* large negative exponent could cause an
* unnecessary overflow on I alone). In this
* case, fracExp is incremented one for each
* dropped digit. */
int mantSize; /* Number of digits in mantissa. */
int decPt; /* Number of mantissa digits BEFORE decimal
* point. */
const char *pExp; /* Temporarily holds location of exponent
* in string. */
/*
* Strip off leading blanks and check for a sign.
*/
p = string;
while (isspace(*p)) {
p += 1;
}
if (*p == '-') {
sign = TRUE;
p += 1;
} else {
if (*p == '+') {
p += 1;
}
sign = FALSE;
}
/*
* Count the number of digits in the mantissa (including the decimal
* point), and also locate the decimal point.
*/
decPt = -1;
for (mantSize = 0; ; mantSize += 1)
{
c = *p;
if (!isdigit(c)) {
if ((c != '.') || (decPt >= 0)) {
break;
}
decPt = mantSize;
}
p += 1;
}
/*
* Now suck up the digits in the mantissa. Use two integers to
* collect 9 digits each (this is faster than using floating-point).
* If the mantissa has more than 18 digits, ignore the extras, since
* they can't affect the value anyway.
*/
pExp = p;
p -= mantSize;
if (decPt < 0) {
decPt = mantSize;
} else {
mantSize -= 1; /* One of the digits was the point. */
}
if (mantSize > 18) {
fracExp = decPt - 18;
mantSize = 18;
} else {
fracExp = decPt - mantSize;
}
if (mantSize == 0) {
fraction = 0.0;
p = string;
goto done;
} else {
int frac1, frac2;
frac1 = 0;
for ( ; mantSize > 9; mantSize -= 1)
{
c = *p;
p += 1;
if (c == '.') {
c = *p;
p += 1;
}
frac1 = 10*frac1 + (c - '0');
}
frac2 = 0;
for (; mantSize > 0; mantSize -= 1)
{
c = *p;
p += 1;
if (c == '.') {
c = *p;
p += 1;
}
frac2 = 10*frac2 + (c - '0');
}
fraction = (1.0e9 * frac1) + frac2;
}
/*
* Skim off the exponent.
*/
p = pExp;
if ((*p == 'E') || (*p == 'e')) {
p += 1;
if (*p == '-') {
expSign = TRUE;
p += 1;
} else {
if (*p == '+') {
p += 1;
}
expSign = FALSE;
}
while (isdigit(*p)) {
exp = exp * 10 + (*p - '0');
p += 1;
}
}
if (expSign) {
exp = fracExp - exp;
} else {
exp = fracExp + exp;
}
/*
* Generate a floating-point number that represents the exponent.
* Do this by processing the exponent one bit at a time to combine
* many powers of 2 of 10. Then combine the exponent with the
* fraction.
*/
if (exp < 0) {
expSign = TRUE;
exp = -exp;
} else {
expSign = FALSE;
}
if (exp > maxExponent) {
exp = maxExponent;
errno = ERANGE;
}
dblExp = 1.0;
for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
if (exp & 01) {
dblExp *= *d;
}
}
if (expSign) {
fraction /= dblExp;
} else {
fraction *= dblExp;
}
done:
if (endPtr != NULL) {
*endPtr = (char *) p;
}
if (sign) {
return -fraction;
}
return fraction;
}

1128
missing/vsnprintf.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,7 @@ version = VERSION
config = open(rbconfig_rb, "w") config = open(rbconfig_rb, "w")
$stdout.reopen(config) $stdout.reopen(config)
fast = {'prefix'=>TRUE, 'INSTALL'=>TRUE, 'binsuffix'=>TRUE} fast = {'prefix'=>TRUE, 'INSTALL'=>TRUE, 'EXEEXT'=>TRUE}
print %[ print %[
module Config module Config
@ -23,6 +23,7 @@ module Config
print " CONFIG = {}\n" print " CONFIG = {}\n"
v_fast = [] v_fast = []
v_others = [] v_others = []
has_version = false
File.foreach "config.status" do |$_| File.foreach "config.status" do |$_|
next if /^#/ next if /^#/
if /^s%@program_transform_name@%s,(.*)%g$/ if /^s%@program_transform_name@%s,(.*)%g$/
@ -33,7 +34,7 @@ File.foreach "config.status" do |$_|
val = $2 || "" val = $2 || ""
next if name =~ /^(INSTALL|DEFS|configure_input|srcdir|top_srcdir)$/ next if name =~ /^(INSTALL|DEFS|configure_input|srcdir|top_srcdir)$/
v = " CONFIG[\"" + name + "\"] = " + v = " CONFIG[\"" + name + "\"] = " +
val.sub(/^\s*(.*)\s*$/, '"\1"').gsub(/\$[{(]?([^})]+)[})]?/) { val.sub(/^\s*(.*)\s*$/, '"\1"').gsub(/\$\{?([^(){}]+)\}?/) {
"\#{CONFIG[\\\"#{$1}\\\"]}" "\#{CONFIG[\\\"#{$1}\\\"]}"
} + "\n" } + "\n"
if fast[name] if fast[name]
@ -41,6 +42,7 @@ File.foreach "config.status" do |$_|
else else
v_others << v v_others << v
end end
has_version = true if name == "MAJOR"
if /DEFS/ if /DEFS/
val.split(/\s*-D/).each do |i| val.split(/\s*-D/).each do |i|
if i =~ /(.*)=(\\")?([^\\]*)(\\")?/ if i =~ /(.*)=(\\")?([^\\]*)(\\")?/
@ -55,23 +57,36 @@ File.foreach "config.status" do |$_|
end end
end end
elsif /^ac_given_srcdir=(.*)/ elsif /^ac_given_srcdir=(.*)/
path = $1 v_fast << " CONFIG[\"srcdir\"] = \"" + File.expand_path($1) + "\"\n"
cwd = Dir.pwd
begin
Dir.chdir path
v_fast << " CONFIG[\"srcdir\"] = \"" + Dir.pwd + "\"\n"
ensure
Dir.chdir cwd
end
elsif /^ac_given_INSTALL=(.*)/ elsif /^ac_given_INSTALL=(.*)/
v_fast << " CONFIG[\"INSTALL\"] = " + $1 + "\n" v_fast << " CONFIG[\"INSTALL\"] = " + $1 + "\n"
end end
# break if /^CEOF/ # break if /^CEOF/
end end
if not has_version
VERSION.scan(/(\d+)\.(\d+)\.(\d+)/) {
print " CONFIG[\"MAJOR\"] = \"" + $1 + "\"\n"
print " CONFIG[\"MINOR\"] = \"" + $2 + "\"\n"
print " CONFIG[\"TEENY\"] = \"" + $3 + "\"\n"
}
end
print v_fast, v_others print v_fast, v_others
Dir.chdir File.dirname($0) print <<EOS
print " CONFIG[\"compile_dir\"] = \"#{Dir.pwd}\"\n" CONFIG["compile_dir"] = "#{Dir.pwd}"
print "end\n" CONFIG.each_value do |val|
val.gsub!(/\\$\\(([^()]+)\\)/) do |var|
key = $1
if CONFIG.key? key
"\#{CONFIG[\\\"\#{key}\\\"]}"
else
var
end
end
end
end
EOS
config.close config.close
# vi:set sw=2: # vi:set sw=2:

22
node.h
View file

@ -6,7 +6,7 @@
$Date$ $Date$
created at: Fri May 28 15:14:02 JST 1993 created at: Fri May 28 15:14:02 JST 1993
Copyright (C) 1993-1998 Yukihiro Matsumoto Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/ ************************************************/
@ -144,7 +144,7 @@ typedef struct RNode {
RNODE(n)->flags=((RNODE(n)->flags&~FL_UMASK)|(((t)<<FL_USHIFT)&FL_UMASK)) RNODE(n)->flags=((RNODE(n)->flags&~FL_UMASK)|(((t)<<FL_USHIFT)&FL_UMASK))
#define NODE_LSHIFT (FL_USHIFT+8) #define NODE_LSHIFT (FL_USHIFT+8)
#define NODE_LMASK ((1<<(sizeof(NODE*)*CHAR_BIT-NODE_LSHIFT))-1) #define NODE_LMASK (((long)1<<(sizeof(NODE*)*CHAR_BIT-NODE_LSHIFT))-1)
#define nd_line(n) (((RNODE(n))->flags>>NODE_LSHIFT)&NODE_LMASK) #define nd_line(n) (((RNODE(n))->flags>>NODE_LSHIFT)&NODE_LMASK)
#define nd_set_line(n,l) \ #define nd_set_line(n,l) \
RNODE(n)->flags=((RNODE(n)->flags&~(-1<<NODE_LSHIFT))|(((l)&NODE_LMASK)<<NODE_LSHIFT)) RNODE(n)->flags=((RNODE(n)->flags&~(-1<<NODE_LSHIFT))|(((l)&NODE_LMASK)<<NODE_LSHIFT))
@ -225,17 +225,9 @@ typedef struct RNode {
#define NEW_RFUNC(b1,b2) NEW_SCOPE(block_append(b1,b2)) #define NEW_RFUNC(b1,b2) NEW_SCOPE(block_append(b1,b2))
#define NEW_SCOPE(b) rb_node_newnode(NODE_SCOPE,local_tbl(),cur_cref,(b)) #define NEW_SCOPE(b) rb_node_newnode(NODE_SCOPE,local_tbl(),cur_cref,(b))
#define NEW_BLOCK(a) rb_node_newnode(NODE_BLOCK,a,0,0) #define NEW_BLOCK(a) rb_node_newnode(NODE_BLOCK,a,0,0)
#ifdef NOBLOCK_RECUR
#define NEW_IF(c,t,e) block_append(c,rb_node_newnode(NODE_IF,0,t,e))
#else
#define NEW_IF(c,t,e) rb_node_newnode(NODE_IF,c,t,e) #define NEW_IF(c,t,e) rb_node_newnode(NODE_IF,c,t,e)
#endif
#define NEW_UNLESS(c,t,e) NEW_IF(c,e,t) #define NEW_UNLESS(c,t,e) NEW_IF(c,e,t)
#ifdef NOBLOCK_RECUR
#define NEW_CASE(h,b) block_append(h,rb_node_newnode(NODE_CASE,0,b,0))
#else
#define NEW_CASE(h,b) rb_node_newnode(NODE_CASE,h,b,0) #define NEW_CASE(h,b) rb_node_newnode(NODE_CASE,h,b,0)
#endif
#define NEW_WHEN(c,t,e) rb_node_newnode(NODE_WHEN,c,t,e) #define NEW_WHEN(c,t,e) rb_node_newnode(NODE_WHEN,c,t,e)
#define NEW_OPT_N(b) rb_node_newnode(NODE_OPT_N,0,b,0) #define NEW_OPT_N(b) rb_node_newnode(NODE_OPT_N,0,b,0)
#define NEW_WHILE(c,b,n) rb_node_newnode(NODE_WHILE,c,b,n) #define NEW_WHILE(c,b,n) rb_node_newnode(NODE_WHILE,c,b,n)
@ -285,11 +277,7 @@ typedef struct RNode {
#define NEW_XSTR(s) rb_node_newnode(NODE_XSTR,s,0,0) #define NEW_XSTR(s) rb_node_newnode(NODE_XSTR,s,0,0)
#define NEW_DXSTR(s) rb_node_newnode(NODE_DXSTR,s,0,0) #define NEW_DXSTR(s) rb_node_newnode(NODE_DXSTR,s,0,0)
#define NEW_EVSTR(s,l) rb_node_newnode(NODE_EVSTR,rb_str_new(s,l),0,0) #define NEW_EVSTR(s,l) rb_node_newnode(NODE_EVSTR,rb_str_new(s,l),0,0)
#ifdef NOBLOCK_RECUR_incomplete
#define NEW_CALL(r,m,a) block_append(r,rb_node_newnode(NODE_CALL,0,m,a))
#else
#define NEW_CALL(r,m,a) rb_node_newnode(NODE_CALL,r,m,a) #define NEW_CALL(r,m,a) rb_node_newnode(NODE_CALL,r,m,a)
#endif
#define NEW_FCALL(m,a) rb_node_newnode(NODE_FCALL,0,m,a) #define NEW_FCALL(m,a) rb_node_newnode(NODE_FCALL,0,m,a)
#define NEW_VCALL(m) rb_node_newnode(NODE_VCALL,0,m,0) #define NEW_VCALL(m) rb_node_newnode(NODE_VCALL,0,m,0)
#define NEW_SUPER(a) rb_node_newnode(NODE_SUPER,0,0,a) #define NEW_SUPER(a) rb_node_newnode(NODE_SUPER,0,0,a)
@ -331,9 +319,9 @@ VALUE rb_method_booundp();
#define NOEX_PRIVATE 2 #define NOEX_PRIVATE 2
#define NOEX_PROTECTED 4 #define NOEX_PROTECTED 4
NODE *rb_compile_cstr _((char *, char *, int)); NODE *rb_compile_cstr _((const char*, const char*, int, int));
NODE *rb_compile_string _((char *, VALUE)); NODE *rb_compile_string _((const char*, VALUE, int));
NODE *rb_compile_file _((char *, VALUE, int)); NODE *rb_compile_file _((const char*, VALUE, int));
void rb_add_method _((VALUE, ID, NODE *, int)); void rb_add_method _((VALUE, ID, NODE *, int));
NODE *rb_node_newnode(); NODE *rb_node_newnode();

Some files were not shown because too many files have changed in this diff Show more