diff options
-rw-r--r-- | ChangeLog | 1799 | ||||
-rw-r--r-- | MANIFEST | 30 | ||||
-rw-r--r-- | Makefile.in | 30 | ||||
-rw-r--r-- | README | 182 | ||||
-rw-r--r-- | README.EXT | 973 | ||||
-rw-r--r-- | README.jp | 159 | ||||
-rw-r--r-- | ToDo | 8 | ||||
-rw-r--r-- | array.c | 459 | ||||
-rw-r--r-- | bignum.c | 440 | ||||
-rw-r--r-- | class.c | 45 | ||||
-rw-r--r-- | compar.c | 10 | ||||
-rw-r--r-- | config.dj | 35 | ||||
-rwxr-xr-x | config.guess | 139 | ||||
-rwxr-xr-x | config.sub | 177 | ||||
-rw-r--r-- | configure.bat | 5 | ||||
-rw-r--r-- | configure.in | 242 | ||||
-rw-r--r-- | defines.h | 13 | ||||
-rw-r--r-- | dir.c | 64 | ||||
-rw-r--r-- | dln.c | 161 | ||||
-rw-r--r-- | enum.c | 100 | ||||
-rw-r--r-- | env.h | 7 | ||||
-rw-r--r-- | error.c | 714 | ||||
-rw-r--r-- | eval.c | 3252 | ||||
-rw-r--r-- | ext/Setup | 4 | ||||
-rw-r--r-- | ext/Setup.dj | 8 | ||||
-rw-r--r-- | ext/dbm/MANIFEST | 1 | ||||
-rw-r--r-- | ext/dbm/dbm.c | 188 | ||||
-rw-r--r-- | ext/dbm/dbm.doc | 107 | ||||
-rw-r--r-- | ext/dbm/extconf.rb | 2 | ||||
-rw-r--r-- | ext/etc/etc.c | 36 | ||||
-rw-r--r-- | ext/extmk.rb.in | 148 | ||||
-rw-r--r-- | ext/kconv/MANIFEST | 2 | ||||
-rw-r--r-- | ext/kconv/kconv.c | 1934 | ||||
-rw-r--r-- | ext/marshal/MANIFEST | 1 | ||||
-rw-r--r-- | ext/marshal/extconf.rb | 2 | ||||
-rw-r--r-- | ext/marshal/marshal.c | 519 | ||||
-rw-r--r-- | ext/marshal/marshal.doc | 5 | ||||
-rw-r--r-- | ext/md5/MANIFEST | 6 | ||||
-rw-r--r-- | ext/md5/depend | 2 | ||||
-rw-r--r-- | ext/md5/md5.doc | 36 | ||||
-rw-r--r-- | ext/md5/md5.h | 86 | ||||
-rw-r--r-- | ext/md5/md5c.c | 337 | ||||
-rw-r--r-- | ext/md5/md5init.c | 90 | ||||
-rw-r--r-- | ext/socket/MANIFEST | 1 | ||||
-rw-r--r-- | ext/socket/extconf.rb | 7 | ||||
-rw-r--r-- | ext/socket/socket.c | 426 | ||||
-rw-r--r-- | ext/socket/socket.doc | 227 | ||||
-rw-r--r-- | ext/tkutil/MANIFEST | 2 | ||||
-rw-r--r-- | ext/tkutil/depend | 1 | ||||
-rw-r--r-- | ext/tkutil/extconf.rb | 11 | ||||
-rw-r--r-- | ext/tkutil/tkutil.c | 1 | ||||
-rw-r--r-- | file.c | 403 | ||||
-rw-r--r-- | gc.c | 171 | ||||
-rw-r--r-- | glob.c | 8 | ||||
-rw-r--r-- | hash.c | 137 | ||||
-rw-r--r-- | inits.c | 8 | ||||
-rw-r--r-- | io.c | 885 | ||||
-rw-r--r-- | io.h | 14 | ||||
-rw-r--r-- | lib/base64.rb | 2 | ||||
-rw-r--r-- | lib/cgi-lib.rb | 56 | ||||
-rw-r--r-- | lib/complex.rb | 490 | ||||
-rw-r--r-- | lib/find.rb | 47 | ||||
-rw-r--r-- | lib/getopts.rb | 173 | ||||
-rw-r--r-- | lib/jcode.rb | 174 | ||||
-rw-r--r-- | lib/mailread.rb | 19 | ||||
-rw-r--r-- | lib/mathn.rb | 307 | ||||
-rw-r--r-- | lib/observer.rb | 40 | ||||
-rw-r--r-- | lib/parsearg.rb | 103 | ||||
-rw-r--r-- | lib/rational.rb | 361 | ||||
-rw-r--r-- | lib/safe.rb | 78 | ||||
-rw-r--r-- | lib/thread.rb | 153 | ||||
-rw-r--r-- | lib/tk.rb | 557 | ||||
-rw-r--r-- | lib/tkcanvas.rb | 47 | ||||
-rw-r--r-- | lib/tkcore.rb | 521 | ||||
-rw-r--r-- | lib/tkentry.rb | 2 | ||||
-rw-r--r-- | lib/tkscrollbox.rb | 27 | ||||
-rw-r--r-- | lib/tktext.rb | 18 | ||||
-rw-r--r-- | lib/tkthcore.rb | 546 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | math.c | 9 | ||||
-rw-r--r-- | missing/flock.c | 90 | ||||
-rw-r--r-- | missing/mkdir.c | 4 | ||||
-rw-r--r-- | missing/setenv.c | 4 | ||||
-rw-r--r-- | missing/strftime.c | 1094 | ||||
-rw-r--r-- | node.h | 84 | ||||
-rw-r--r-- | numeric.c | 417 | ||||
-rw-r--r-- | object.c | 384 | ||||
-rw-r--r-- | pack.c | 74 | ||||
-rw-r--r-- | parse.y | 1586 | ||||
-rw-r--r-- | process.c | 386 | ||||
-rw-r--r-- | random.c | 28 | ||||
-rw-r--r-- | range.c | 153 | ||||
-rw-r--r-- | re.c | 247 | ||||
-rw-r--r-- | re.h | 2 | ||||
-rw-r--r-- | regex.c | 76 | ||||
-rw-r--r-- | regex.h | 2 | ||||
-rw-r--r-- | ruby.c | 239 | ||||
-rw-r--r-- | ruby.h | 123 | ||||
-rw-r--r-- | ruby.texi | 5044 | ||||
-rw-r--r-- | sample/clnt.rb | 6 | ||||
-rw-r--r-- | sample/dir.rb | 4 | ||||
-rw-r--r-- | sample/eval.rb | 41 | ||||
-rw-r--r-- | sample/evaldef.rb | 26 | ||||
-rw-r--r-- | sample/export.rb | 2 | ||||
-rw-r--r-- | sample/fact.rb | 8 | ||||
-rwxr-xr-x | sample/from.rb | 14 | ||||
-rw-r--r-- | sample/fullpath.pl | 22 | ||||
-rw-r--r-- | sample/fullpath.rb | 6 | ||||
-rwxr-xr-x | sample/getopts.test | 25 | ||||
-rw-r--r-- | sample/io.rb | 4 | ||||
-rwxr-xr-x | sample/less.rb | 4 | ||||
-rw-r--r-- | sample/list.rb | 14 | ||||
-rwxr-xr-x | sample/mpart.rb | 6 | ||||
-rw-r--r-- | sample/observ.rb | 31 | ||||
-rw-r--r-- | sample/philos.rb | 54 | ||||
-rw-r--r-- | sample/pi.rb | 18 | ||||
-rw-r--r-- | sample/rcs.rb | 2 | ||||
-rw-r--r-- | sample/regx.rb | 23 | ||||
-rw-r--r-- | sample/ruby-mode.el | 575 | ||||
-rw-r--r-- | sample/sieve.rb | 2 | ||||
-rw-r--r-- | sample/svr.rb | 2 | ||||
-rw-r--r-- | sample/test.rb | 981 | ||||
-rwxr-xr-x | sample/time.rb | 2 | ||||
-rw-r--r-- | sample/tkbiff.rb | 46 | ||||
-rw-r--r-- | sample/tkbrowse.rb | 8 | ||||
-rw-r--r-- | sample/tkfrom.rb | 13 | ||||
-rw-r--r-- | sample/tkline.rb | 25 | ||||
-rw-r--r-- | sample/trojan.pl | 12 | ||||
-rw-r--r-- | sample/tsvr.rb | 23 | ||||
-rwxr-xr-x | sample/uumerge.rb | 8 | ||||
-rw-r--r-- | sig.h | 46 | ||||
-rw-r--r-- | signal.c | 161 | ||||
-rw-r--r-- | sprintf.c | 72 | ||||
-rw-r--r-- | st.c | 202 | ||||
-rw-r--r-- | st.h | 22 | ||||
-rw-r--r-- | string.c | 674 | ||||
-rw-r--r-- | struct.c | 95 | ||||
-rw-r--r-- | time.c | 251 | ||||
-rw-r--r-- | top.sed | 37 | ||||
-rw-r--r-- | util.c | 2 | ||||
-rw-r--r-- | util.h | 2 | ||||
-rw-r--r-- | variable.c | 206 | ||||
-rw-r--r-- | version.c | 8 | ||||
-rw-r--r-- | version.h | 4 |
144 files changed, 20373 insertions, 12047 deletions
@@ -1,5 +1,1771 @@ +Tue Dec 24 15:20:58 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.4-961224 + + * configure.in: char¤¬unsigned¤«¤É¤¦¤«¤â¥Á¥§¥Ã¥¯ + + * regex.c (SIGN_EXTEND_CHAR): __CHAR_UNSIGNED__¤Ë¤âÂбþ + + * pack.c (pack_unpack): ÌÀ¼¨Åª¤Ësigned char¤ò»ØÄê¡¥ + +Mon Dec 23 14:41:23 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ruby.c (load_file): ɸ½àÆþÎϤ«¤é¤Î¥¹¥¯¥ê¥×¥È¤Ç°ì»þ¥Õ¥¡¥¤¥ë¤ò»È¤ï + ¤Ê¤¤¤è¤¦¤Ë + + * object.c (f_integer): `0x', `0'¤Ê¤É¤Çbase¤ò²ò¼á¤¹¤ë¤è¤¦¤Ë¡¥ + +Fri Dec 20 01:44:39 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * Makefile.in (flock.o): flock¤ËÂбþ + +Thu Dec 19 20:13:32 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.4-961219 + +Wed Dec 18 00:06:48 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * glob.c (glob_filename): strrchr¤¬¥Þ¥¯¥í¤Î¾ì¹ç¤ËÂбþ + + * configure.in: <sys/select.h>¤ò¥Á¥§¥Ã¥¯ + + * ext/kconv/kconv.c: 1.62¥Ù¡¼¥¹¤Ë + + * ext/kconv/kconv.c: Kconv¥â¥¸¥å¡¼¥ë + + * string.c (str_substr): len¤¬¸µ¤Îʸ»úÎó¤è¤êŤ¤»þ¤ËÂбþ + + * parse.y (iterator): ¡Ö$bar do .. end¡×¤Ê¤É¤Ïµö¤µ¤Ê¤¤¤è¤¦¤Ë + + * parse.y (iterator): FID(foo!,foo?)¤òdo·Á¼°¤Î¥¤¥Æ¥ì¡¼¥¿¤Ë¤Ç¤¤ë¡¥ + + * missing/flock.c (flock): lockf()¤ò»È¤Ã¤ÆÂåÂØ + + * file.c (file_flock): flock¤ò¼ÂÁõ + +Tue Dec 17 12:13:38 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.4-961217 + +Fri Dec 13 02:05:03 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * configure.in: RUBYLIB¤Î¥«¥ì¥ó¥È¤ò¸å²ó¤·(@mix/awk offline) + + * dln.c: AIX¤ËÂбþ¤·¤¿¡©(@mix/awk offline) + + * eval.c (thread_schedule): critical section¤Ç¤âÌÀ¼¨Åª¤Ê¥³¥ó¥Æ¥¥¹ + ¥È¥¹¥¤¥Ã¥Á¤Ïµ¯¤¤Ê¤¤¤È¤Þ¤º¤¤ + + * re.c (reg_search): match¤Ë¼ºÇÔ¤·¤¿»þ¤Ë$~¤ònil¤Ë¡¥ + + * re.c (reg_search): Ëè²ómatch¤òÀ¸À®¤¹¤ë¤è¤¦¤Ë + +Thu Dec 12 17:03:30 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * numeric.c (flo_to_s): 2.0.to_s -> 2.0¤Ë + + * eval.c (thread_save_context): $_, $~¤òthreadËè¤ËÊݸ + + * eval.c (thread_kill): main thread¤Ç¤Ïexit(0) + + * string.c (str_split_method): ´Ö°ã¤Ã¤¿·ë²Ì¤òÊÖ¤·¤Æ¤¤¤¿ + +Thu Dec 12 15:32:48 1996 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> + + * dir.c: CYGWIN32Âбþ + + * ext/socket/socket.c: CYGWIN32Âбþ + + * io.c: CYGWIN32Âбþ + +Thu Dec 12 14:43:51 1996 Jun Kuroda <j_kuro@pluto.ai.kutech.ac.jp> + + * lib/tk.rb: wish4.2¤âõº÷¸õÊä¤Ë´Þ¤á¤ë + + * config.guess: JCCÂбþ + +Thu Dec 12 00:41:17 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.4-961212 + + * parse.y (parse_string): """..."""¤Ï¤ä¤Ï¤ê̵¤¯¤¹¤³¤È¤Ë¤·¤¿ + + * parse.y (parse_regx): %r|...|¤Çterminator¤ò \ ¤Ç¥¨¥¹¥±¡¼¥×¤Ç¤¤ë + ¤è¤¦¤Ë + + * signal.c (posix_signal): sigaction¤ò»È¤¦signal + + * configure.in: posix signal/bsd signal¤Î¸¡½Ð + +Wed Dec 11 17:47:35 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (thread_schedule): critical section¤Ç¤Ï¥³¥ó¥Æ¥¥¹¥È¥¹¥¤¥Ã + ¥Á¤¬µ¯¤¤Ê¤¤¤è¤¦¤Ë + + * lib/thread.rb: SharedMutex¥¯¥é¥¹ + + * lib/jcode.rb: String#scan¤ò»È¤¦¤è¤¦¤Ë + +Tue Dec 10 12:21:28 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.3-961210 + + * string.c (str_split_method): Àµµ¬É½¸½¤Ë()¤ò´Þ¤à»þ¤Ë¥Ð¥° + + * lib/jcode.rb: ¤Á¤ç¤Ã¤È¤Þ¤·¤Ë¤Ê¤Ã¤¿ + + * string.c (tr_setup_table): ÃÖ´¹Ê¸»ú¤¬Ã»¤¹¤®¤ë(2ʸ»ú)¤Î¤È¤¤Î¥Ð¥° + +Mon Dec 9 11:38:04 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * string.c (str_scan): ʸ»úÎó¤Î¥Þ¥Ã¥Á¤ò¹Ô¤¦¡¥¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¤âư + ºî¤¹¤ë + + * regex.c (re_copy_registers): allocated¤¬½é´ü²½¤µ¤ì¤Æ¤¤¤Ê¤«¤Ã¤¿ + + * re.c (match_to_s): $~¤Îʸ»úÎó²½ + + * re.c (match_to_a): $~¤òÇÛÎ󲽤Ǥ¤ë¤è¤¦¤Ë + + * re.c (match_getter): ¥ì¥¸¥¹¥¿¤¬½é´ü²½¤µ¤ì¤Æ¤¤¤Ê¤«¤Ã¤¿ + +Thu Dec 5 11:06:10 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * string.c (str_split_method): ¥Þ¥Ã¥Á¤·¤Ê¤«¤Ã¤¿³ç¸Ì¤Ï¶õʸ»úÎó¤ò + push¤¹¤ë¤Ù¤¤Ç¤Ï¤Ê¤¤ + + * string.c (str_succ): ¥¢¥ë¥Õ¥¡¥Ù¥Ã¥È¤ò´Þ¤Þ¤Ê¤¤Ê¸»ú¤ËÂбþ + +Wed Dec 4 10:48:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.3-961204 + + * io.c (io_binmode): DJGPP¤Ç¤ÎbinmodeÂбþ + + * sprintf.c (f_sprintf): int¤ÎÈϰϤοôÃͤÏľÀÜsprintf¤ÇÊÑ´¹¤¹¤ë + + * sprintf.c (f_sprintf): "%02s"¤ËÍê¤é¤Ê¤¤ + + * re.c (reg_search): index¤ÇSEGV + +Tue Dec 3 10:09:36 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.3-961203 + + * ext/extmk.rb.in (install): INSTALL_DATA¤«¤éINSTALL¤ËÊѹ¹ + + * dln.c: hpuxÂбþ + + * string.c (str_aset_method): Éé¤ÎÃͤò´Þ¤àÈϰϤǤâÎã³°¤òµ¯¤³¤µ¤Ê¤¤ + + * array.c (ary_replace): Éé¤ÎÃͤò´Þ¤àÈϰϤǤâÎã³°¤òµ¯¤³¤µ¤Ê¤¤ + + * array.c (beg_len): beg==end¤Î»þ¡¤Ä¹¤µ0¤Ë + +Mon Dec 2 14:07:12 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * configure.in: HP shlÂбþ + + * string.c (str_upto): beg > end¤Î»þ̵¸Â¥ë¡¼¥×¤ËÍî¤Á¤ë¤Î¤ò»ß¤á¤¿ + + * range.c (range_each): String#upto¤¬ºÆÄêµÁ¤µ¤ì¤¿¾ì¹ç¤ËÂбþ + + * string.c (str_split_method): "ABC".split(/(B)/)¤¬¸íưºî + +Sat Nov 30 01:43:52 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (rb_eval): undef¤ÇSEGV + +Fri Nov 29 12:17:59 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * sample/ruby-mode.el (ruby-parse-region): %Q#..#¤Ê¤É¤ËÂбþ¡¥¤·¤« + ¤·¡¤¶èÀÚ¤êʸ»ú¤¬±é»»»Ò¤Ç¹ÔËö¤Ë¤¢¤ë¾ì¹ç¤Ë¤ÏÂбþ¤Ç¤¤Ê¤«¤Ã¤¿¡¥ + + * re.c (reg_raise): Îã³°¤Ç¤â¥¹¥é¥Ã¥·¥å¤ò¥¨¥¹¥±¡¼¥× + + * re.c (reg_inspect): ¥¹¥é¥Ã¥·¥å¤ò¥¨¥¹¥±¡¼¥× + + * parse.y (parse_string): `%[QqXxRr](.)..\1'¤Ê¤ëʸ»úÎó·Á¼°(¥Æ¥¹¥È + ºÎÍÑ) + + * parse.y (parse_qstring): '''...'''¤Î·Á¼° + + * ext/dbm/dbm.c (Init_dbm): ½Ò¸ìkey?,value?¤ÎÄɲà + + * ext/dbm/dbm.c (Init_dbm): includes->include? + + * hash.c (Init_Hash): ½Ò¸ìkey?,value?,include?¤ÎÄɲà + + * eval.c (rb_eval): elseÀ᤬¼Â¹Ô¤µ¤ì¤Ê¤¤(¤¦¡¼¤ó) + + * string.c (str_sub_iter_s): ¥¤¥Æ¥ì¡¼¥¿¥Ö¥í¥Ã¥¯Æâ¤Ç¥Þ¥Ã¥Á¤¬¹Ô¤ï¤ì + ¤ë¤È°ÌÃÖ¤¬¤º¤ì¤ë(»þ¤Ë̵¸Â¥ë¡¼¥×¤ËÍî¤Á¤ë) + + * string.c (str_resize): len¤¬0¤Î»þsize¤ÎÄ´À°¤¬¹Ô¤ï¤ì¤Ê¤«¤Ã¤¿ + +Thu Nov 28 00:59:54 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.3-961128 + + * parse.y (parse_string): 3-quote style¤Îʸ»úÎó(Îã:"""abc"d"e""") + + * configure.in (EXTSTATIC): ext¤òÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë»þ¤Ë¤Ïruby¤Ïdll¤ò + »È¤¦¤è¤¦¤Ë + + * io.c (Init_IO): gets¤Î°ú¿ô¤¬´Ö°ã¤Ã¤Æ¤¤¤¿ + + * string.c (str_each_line): RS¤òÌÀ¼¨Åª¤Ë»ØÄê¤Ç¤¤ë¤è¤¦¤Ë + +Wed Nov 27 12:37:46 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.3-961127 + + * eval.c (rb_eval): iver defined? ¤Çself¤ò»ØÄꤹ¤ë¤Î¤ò˺¤ì¤¿ + + * io.c: getsÅù¤ÇRS¤òÌÀ¼¨Åª¤Ë»ØÄê¤Ç¤¤ë¤è¤¦¤Ë + + * ext/extmk.rb.in (install): static link¤Ë¼ºÇÔ + +Tue Nov 26 10:33:04 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.3-961126 + + * string.c (str_sub_s): ÃÖ´¹¸å¤Îʸ»úÎ󍵤¬´Ö°ã¤Ã¤Æ¤¤¤¿ + +Mon Nov 25 09:11:22 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * numeric.c (fix_rshift): 32°Ê¾å¤Î±¦¥·¥Õ¥È¤Ç0¤òÊÖ¤¹¤è¤¦¤Ë(C¤Î + rshift¤Ï(x>>(y%32))¤òÊÖ¤·¤Æ¤¤¤¿)¡¥ + + * string.c (str_gsub): ÃÖ´¹¤¬¹Ô¤ï¤ì¤Ê¤¤¾ì¹ç¤¬¤¢¤Ã¤¿ + + * string.c (str_resize): ËÜÅö¤ËɬÍפʻþ¤À¤±realloc + +Thu Nov 21 04:13:21 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * configure.in (EXTSTATIC): --with-static-linked-ext¤ÇÁ´¤Æ¤Î¥â¥¸¥å¡¼ + ¥ë¤òÀÅŪ¥ê¥ó¥¯¤¹¤ë¤è¤¦¤Ë + + * pack.c (pack_unpack): ¹ÔËö¤Î²þ¹Ô¤¬¤Ê¤¤»þ¤Ë¤â¥Á¥§¥Ã¥¯¥µ¥à¤ò¥¹¥¥Ã + ¥×¤¹¤ë¤è¤¦¤Ë + +Wed Nov 20 96 21:42:51 1996 Yasuo OHBA <jammy@shljapan.co.jp> + + * configure.in: freebsdÂбþ + +Wed Nov 20 10:24:24 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ext/extmk.rb.in (install): Ä̾ï¥ê¥ó¥¯ÍѤÎLDFLAGS¤È¥À¥¤¥Ê¥ß¥Ã¥¯¥ê + ¥ó¥¯ÍѤÎDLDFALGS¤òʬΥ + + * ext/extmk.rb.in (install): ¥³¥ó¥Ñ¥¤¥ë¤ÎÀ®¸ù¤·¤¿¤â¤Î¤òÀÅŪ¥ê¥ó¥¯ + ¤Î¥ê¥¹¥È¤ËÄɲ乤ë + + * eval.c (f_missing): ¥ª¥Ö¥¸¥§¥¯¥È¤Îʸ»úÎóɽ¸½¤¬Ä¹¤¹¤®¤ë»þ¥Ð¥Ã¥Õ¥¡ + ¤ò½ñ¤ÄÙ¤·¤Æ¤¤¤¿ + + * process.c (proc_exec_v): fork¤·¤¿¸åÎã³°¤òȯÀ¸¤µ¤»¤Æ¤Ï¤¤¤±¤Ê¤¤ + +Tue Nov 19 13:28:15 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.3-961119 + + * eval.c (mod_method_defined): Module#method_defined? ¤ÎÄɲà + + * parse.y (call_args): °ú¿ô¤¬Í£°ì¤Î¥³¥Þ¥ó¥É¥³¡¼¥ë¤Ç¤¢¤ë»þ¤Î¥Ð¥°(Ìá + ¤êÃͤ¬Å¸³«¤µ¤ì¤Æ¤·¤Þ¤¦) + +Mon Nov 18 13:28:18 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * string.c (str_sub): ¼ºÇÔ¤·¤¿»þ¤Ënil¤òÊÖ¤·¤Æ¤¤¤¿ + + * string.c (str_split_method): ¸¡º÷³«»Ï°ÌÃÖ¤¬°Üư¤·¤Æ¤Ê¤«¤Ã¤¿ + + * ext/socket/socket.c (sock_s_getservbyaname): ¤Þ¤À´Ö°ã¤Ã¤Æ¤¤¤¿ + + * version 0.99.3-961118 + + * string.c (str_sub_s): ¸µ¤Îʸ»úÎó¤òÃÖ´¹¤¹¤ë¤Î¤ò»ß¤á¤¿ + + * pack.c (encodes): Îΰ賰¤ò¥¢¥¯¥»¥¹¤·¤Æ¤¤¤¿ + +Fri Nov 15 17:10:35 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * bignum.c (big_divmod): Bignum¤¬°ú¿ô¤Î¾ì¹ç¤ÎÂбþ˺¤ì + + * sample/ruby-mode.el (ruby-expr-beg): word?·Á¼°¤Ø¤ÎÂбþ¤¬ÉÔ´°Á´ + +Wed Nov 13 15:42:40 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * string.c (str_tr_s_bang): tr_s¤Çtr¤¬¹Ô¤ï¤ì¤Æ¤¤¤Ê¤«¤Ã¤¿ + + * eval.c (rb_eval): autoload¥¯¥é¥¹¤Î¥Á¥§¥Ã¥¯ + + * string.c (f_sub): sub¤¬sub!¤ÈƱ¤¸Æ°ºî¤Ë¤Ê¤Ã¤Æ¤¤¤¿ + + * eval.c (thread_sleep): stop¤Èsleep¤ÎʬΥ + +Mon Nov 11 13:53:19 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.3-961111 + + * numeric.c (fix_step): to, step¤¬À°¿ô°Ê³°¤Î¾ì¹ç¤ËÂбþ + + * eval.c (rb_call): dynamic var¤¬dynamic scoping¤Ë¤Ê¤Ã¤Æ¤¤¤¿(¤³¤ì + ¤Ï¤Þ¤º¤¤) + + * string.c (str_chop_bang): Ťµ0¤Îʸ»úÎó¤Îchop¤Ç¡¤Îΰ賰¤Î¥¢¥¯¥» + ¥¹¤¬È¯À¸¤·¤Æ¤¤¤¿¡¥ + + * parse.y (yyerror): ³ä¤êÅö¤Æ¤¿Îΰ賰¤ò¥¢¥¯¥»¥¹¤·¤Æ¤¤¤¿ + +Fri Nov 8 11:54:46 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (thread_yield): scope¤òheap¤Ë¥³¥Ô¡¼ + +Thu Nov 7 09:56:53 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * numeric.c (num_coerce): ¤È¤ê¤¢¤¨¤ºÎ¾ÊÕ¤òFloat¤ËÊÑ´¹¤¹¤ë¤³¤È¤Ë + +Wed Nov 6 10:45:13 1996 Yasuo OHBA <jammy@shljapan.co.jp> + + * lib/parsearg.rb: Âè2°ú¿ô¤òÊѹ¹¡¥ + +Tue Nov 5 14:21:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.3-961105 + +Sat Nov 2 01:11:40 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * bignum.c (big_pow): typo (dy -> dx) + + * bignum.c (big_divmod): ÃΤé¤Ê¤¤·¿¤Ïfloat¤ËÊÑ´¹¤·¤Æ¤ß¤ë + + * numeric.c (fix_lshift): ¶³¦¾ò·ï¤Î¥Ð¥°(Éé¤Ë¤Ê¤Ã¤Æ¤¤¤¿) + + * bignum.c (big_pow): ̵Â̤Êfloat¤Ø¤ÎÊÑ´¹¤ò¤Ê¤¯¤·¤¿ + + * math.c (math_atan2): typo(x -> y) + +Fri Nov 1 15:30:59 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ext/socket/socket.c (sock_gethostname): gethostname¤¬¤Ê¤¤»þ¤Ë¤Ï + uname¤ò»È¤Ã¤Æ¥Û¥¹¥È̾¤òÆÀ¤ë + + * ext/etc/etc.c (etc_getlogin): getlogin¤¬NULL¤òÊÖ¤·¤Æ¤â´Ä¶ÊÑ¿ô¤ò + Ä´¤Ù¤ë¤è¤¦¤Ë + + * object.c (krn_clone): ¥ª¥Ö¥¸¥§¥¯¥È¤Î¥Õ¥é¥°¤â¥³¥Ô¡¼ + + * hash.c (rb_cmp): ¥Ï¥Ã¥·¥å¤ÎÈæ³Ó¤ò`=='¤Ç¤Ê¤¯`eql?'¤ËÊѹ¹ + + * math.c (Need_Float): Float()¤ò»È¤Ã¤ÆÊÑ´¹¤¹¤ë + + * compar.c (cmp_gt): °ÊÁ°¤Î±¦ÊÕ¤òÊÖ¤¹»ÅÍͤÎ̾»Ä¤¬»Ä¤Ã¤Æ¤¤¤¿ + +Thu Oct 31 12:55:51 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.3-961031 + + * numeric.c (Init_Numeric): typo + + * eval.c (error_print): Ť¹¤®¤ëtrace back¤òÅÓÃæ¾Êά¤¹¤ë + + * regex.c (re_compile_pattern): Á´³Ñ¤Îrange¤ËÂбþ + +Wed Oct 30 03:03:18 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.3-961030 + + * io.c (f_ungetc): ´Ø¿ô¤òÄɲà + + * eval.c (dyna_var_asgn): returnÃÍ˺¤ì + +Tue Oct 29 10:05:28 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * string.c (f_split): ´Ø¿ôsplit¤òÄɲà + + * eval.c (rb_call): ¥Í¥¹¥È¤·¤¿³°Â¦¤Î¥¯¥é¥¹/¥â¥¸¥å¡¼¥ë¤ÎÄê¿ô¤ò»²¾È + ¤Ç¤¤ë¤è¤¦¤Ë + +Mon Oct 28 09:51:03 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * string.c (str_sub): offset¤¬Ê¸»ú¤ÎËöÈø¤Ë¤¢¤ë»þ¤Î¥Á¥§¥Ã¥¯ + + * regex.c (re_match): ³ä¤êÅö¤Æ¤ë¥ì¥¸¥¹¥¿¤Î¿ô¤¬1¿¤«¤Ã¤¿ + + * io.c (io_gets): $/ = ""¤Îưºî¤òperl¤Ë¹ç¤ï¤»¤ë(awk¤È¤Ï¤Á¤ç¤Ã¤È°ã + ¤¦¤é¤·¤¤) + + * io.c (io_gets): $/ = nil¤Î»þ¾¯¤·¹â®²½ + + * string.c (str_split_method): ³ç¸Ì¤¬null¤Ë¥Þ¥Ã¥Á¤·¤¿»þ¤Ë¤â̵»ë¤· + ¤Ê¤¤¤è¤¦¤Ë + + * string.c (str_split_method): ³ç¸Ì¤Ë¥Þ¥Ã¥Á¤·¤¿Ê¬¤Ïlimit¤Î¿ô¤Ë´Þ¤á + ¤Ê¤¤¤è¤¦¤Ë¡¥ + + * numeric.c (num_coerce_bin): coerce¤ÎÄêµÁ¤òÊѹ¹¡¤2Í×ÁǤÎÇÛÎó + [x,y]¤òÊÖ¤¹¤è¤¦¤Ë + + * sample/ruby-mode.el (ruby-calculate-indent): "do |aa|"¤ÎÂбþ¤ò²þ + Á±¤·¤¿¡¥ + +Sat Oct 26 01:43:51 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ext/marshal/marshal.c (w_object): ¥Ó¥ë¥È¥¤¥ó¥¯¥é¥¹¤Î¥µ¥Ö¥¯¥é¥¹¤ò + Àµ¤·¤¯Éüµì¤Ç¤¤ë¤è¤¦¤Ë + + * ext/marshal/marshal.c (w_object): ¥æ¡¼¥¶ÄêµÁdump¤ÎÍ¥Àè + + * numeric.c (flo_coerce): Float()¤ò»È¤Ã¤ÆÄêµÁ + + * numeric.c (Init_Numeric): Numeric¤Înew¤Îundef¤Ï¤Þ¤º¤¤ + + * ext/marshal/marshal.c (w_symbol): ¥·¥ó¥Ü¥ë¤ÎÆâÍÆ(ʸ»úÎó)¤Ï°ìÅÙ¤· + ¤«¥Õ¥¡¥¤¥ë¤Ë½ñ¤½Ð¤µ¤Ê¤¤¡¥ + + * sample/ruby-mode.el (ruby-parse-region): if/while½¤¾þ»Ò¤ËÂбþ¤· + ¤Ê¤¯¤Ê¤Ã¤Æ¤¤¤¿ + + * bignum.c (Init_Bignum): Bignum.new¤ò½ü¤¯ + + * eval.c (rb_eval): °ú¿ôɾ²Á¸å¤Ë¥Õ¥¡¥¤¥ë̾¤È¹ÔÈÖ¹æ¤òºÆÀßÄê + + * numeric.c (flo_div): typo + + * sample/ruby-mode.el (ruby-parse-region): def /, def `¤ËÂбþ + +Fri Oct 25 09:26:29 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * sample/ruby-mode.el (ruby-calculate-indent): "do |aa|"¤ËÂбþ + + * array.c (ary_aset): index¤¬fixnum¤Î¾ì¹ç¤Á¤ç¤Ã¤È¹â®²½ + + * eval.c (thread_fd_writable): ½ñ¤¹þ¤ßÁ°¤Îselect¥Á¥§¥Ã¥¯ + + * array.c (ary_assoc): ̵¸Â¥ë¡¼¥×¤ËÍî¤Á¤¿ + + * eval.c (thread_wait_for): select¤¬¥¨¥é¡¼½ªÎ»¤·¤¿»þ¡¤linux°Ê³°¤Ç + ¤Îưºî¤¬Àµ¤·¤¯¤Ê¤«¤Ã¤¿¡¥ + +Thu Oct 24 08:26:48 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (backtrace): `$@'¤òʸ»úÎ󤫤éÇÛÎó¤ËÊѹ¹¤·¤¿¡¥ + + * eval.c (eval): evalÃæ¤ÎÎ㳰ȯÀ¸°ÌÃÖ¤òÊݸ¤¹¤ë + + * bignum.c (bigsub): ¥ª¥Ú¥é¥ó¥É¤ÎÂç¾®Èæ³Ó¤Î¼ºÇÔ + + * re.c (reg_search): ľÀÜ»²¾È¤¬¤Ê¤¤»þ¤Ë¤â`$~'¤¬¥»¥Ã¥È¤µ¤ì¤ë¤è¤¦¤Ë + +Wed Oct 23 10:40:10 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.2-961023 + + * ext/marshal/marshal.c (r_bytes): malloc¤ò¤ä¤á¡¤alloca¤ò»È¤¦ + + * sample/ruby-mode.el (ruby-calculate-indent): ³ç¸Ì¤ÎÂбþ¤òÊѹ¹¡¥ + ()Æâ¤Ç¤Ï¥¤¥ó¥Ç¥ó¥È¤ò¥ì¥Ù¥ë¤ò¹ç¤ï¤»¤ë¤è¤¦¤Ë + +Tue Oct 22 12:59:11 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * hash.c (hash_s_new): size¤ò»ØÄê¤Ç¤¤ë¤è¤¦¤Ë + + * ext/marshal/marshal.c (w_object): dump¤¹¤ë¿¼¤µÀ©¸Â¤ò»ØÄê¤Ç¤¤ë¤è + ¤¦¤Ë + + * array.c (ary_s_new): size¤ò»ØÄꤷ¤¿»þ¤Î½é´ü²½Ëº¤ì + + * object.c (f_float): big2dbl¤ÎÀë¸À˺¤ì¡¥ + + * bignum.c (bigsub): Â礤µ¤Î¶á¤¤BignumƱ»Î¤Î±é»»¤Ç·ë²Ì¤¬Éé¤Ë¤Ê¤ë + ¾ì¹ç¤Ë´Ö°ã¤¤¤¬¤¢¤Ã¤¿¡¥ + + * array.c (ary_aset): ÃÖ´¹Àè¤ÈÃÖ´¹¸µ¤¬Æ±¤¸Ä¹¤µ¤Î»þÆâÍÆ¤ò + shift(memmove)¤·¤Ê¤¤¤è¤¦¤Ë¡¥ + + * ext/marshal/marshal.c (marshal_dump): ¥Õ¥¡¥¤¥ë¥Õ¥©¡¼¥Þ¥Ã¥È¤Ë¥Ð¡¼ + ¥¸¥ç¥ó¤òËä¤á¹þ¤à¤è¤¦¤Ë + + * ext/marshal/marshal.c (tmpnam): linux-aout-dlnÍѤËÄêµÁ + +Mon Oct 21 08:40:20 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ext/socket/socket.c (sock_s_gethostbyname): hostent¹½Â¤ÂΤξðÊó + ¤òÊÖ¤¹ + (sock_s_gethostbyaddr): IP¥¢¥É¥ì¥¹¤«¤éhostent¹½Â¤ÂΤòÆÀ¤ë + (sock_s_getservbyaname): getservbyname(3) + +Fri Oct 18 10:37:36 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * sample/ruby-mode.el (ruby-indent-to): °ÜưÀ襫¥é¥à¤¬Éé¤Ë¤Ê¤ë¥Ð¥° + + * eval.c (compile): eval¤Ç¸µ¥½¡¼¥¹¤Î¹ÔÈÖ¹æ¤Ç¥¨¥é¡¼¤òɽ¼¨¤¹¤ë + +Thu Oct 17 09:52:28 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (eval): eval¤Çʸˡ¥¨¥é¡¼¤¬¤¢¤Ã¤¿»þ¤ËSEGV + + * lib/safe.rb: Restricted.eval¤ÎÃæ¤À¤±À©¸Â¤ò²Ã¤¨¤ë¡¥ + + * eval.c (error_print): ¥Ð¥Ã¥¯¥È¥ì¡¼¥¹¤Î½ÐÎÏ¡¥caller¤ÇÎ㳰ȯÀ¸°ÌÃÖ + ¤òÄ´À°¤·¤¿»þ¤ËÌäÂ꤬½Ð¤ë(¤½¤ó¤Ê¤³¤È¤ò¤·¤Ê¤±¤ì¤ÐÎɤ¤¤Î¤À¤¬¡Ä) + + * eval.c (make_backtrace): ¥Ð¥Ã¥¯¥È¥ì¡¼¥¹¤ÎÀ¸À® + +Wed Oct 16 12:56:22 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ruby-man-0.99.2-jp/index.html: ÆüËܸìÈǥɥ¥å¥á¥ó¥È¤Î´°À®(Ť«¤Ã¤¿¡Ä) + + * re.c (reg_regcomp): $=¤¬nil¤Î»þ¤Î½èÍý + + * string.c (f_chop): $_¤ËÂФ¹¤ëchop + +Tue Oct 15 11:04:23 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.2-961015 + +Mon Oct 14 18:22:38 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (thread_schedule): BOWÂбþ¡¥select¤¬-1¤òÊÖ¤·¤¿»þ¤Ë¥Ð¥°(¼Â + ¤Ïdo .. while¤¬continue¤ÇÀèÆ¬¤Ë¥¸¥ã¥ó¥×¤¹¤ë¤È»×¤¤¹þ¤ó¤Ç¤¤¤¿¡¥¾ò + ·ï¤ÎľÁ°¤À¤Ã¤¿¤Î¤Í ^^);;;;; + + * sample/ruby-mode.el (ruby-mode-syntax-table): ?¤Îsyntax¤¬"/"¤Ç¤Ï + ¤Þ¤º¤¤¤é¤·¤¤ + + * hash.c (rb_hash): name conflict + +Fri Oct 11 00:23:05 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.2-961011 + + * ext/marshal/marshal.c (w_object): ·ë¶Éư¤¤¤Æ¤¤¤Ê¤«¤Ã¤¿½Û´Ä¥ª¥Ö¥¸¥§ + ¥¯¥ÈÂбþ¤ò³°¤·¤¿¡¥ + + * hash.c (rb_hash): Fixnum¤Èʸ»úÎó¤Î¹â®²½ + + * ext/marshal/marshal.c (w_object): ̵Â̤ʥǡ¼¥¿¤Îºï½ü(¥Õ¥©¡¼¥Þ¥Ã + ¥È¤ÎÈó¸ß´¹À) + + * io.c (io_readline): Ìá¤êÃͤÎÉÔÈ÷ + + * ext/marshal/marshal.c (marshal_dumps): MSDOSÂбþ + + * ruby.c (load_file): MSDOSÂбþ + +Wed Oct 9 17:46:27 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ext/extmk.rb.in (install): ̵Â̤ʥ³¥Ô¡¼¤òÈò¤±¤ë + + * string.c (str_sub_method): ¥Þ¥Ã¥Á¤¬¤Ê¤«¤Ã¤¿»þ¤ÎString#sub¤ÎÃͤ¬ + °ã¤Ã¤Æ¤¤¤¿¡¥ + + * eval.c (obj_extend): extend¤·¤¿»þ¤Ëobject_extended¤ò¸Æ¤Ö¤è¤¦¤Ë + +Tue Oct 8 00:55:38 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (thread_alloc): ³äÅö¤ÎÊ¿¶Ñ²½ + + * eval.c (thread_schedule): join¤Î¥Ð¥°¤ò½¤Àµ + + * eval.c (thread_wait_for): select¤Ø¤Î³ä¹þ¤ß¤Ê¤É¤ËÂбþ + + * eval.c (thread_select): linux¤Îselect¤Îµóư¤ËÂбþ(timeout¤¬ÊѲ½ + ¤¹¤ë) + +Mon Oct 7 09:47:19 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.2-961007 + + * eval.c (PUSH_BLOCK): the_class¤ÎÊݸ¤ò˺¤ì¤Æ¤¤¤¿¡¥ + + * ext/dbm/dbm.c (fdbm_store): size¤ÎÊݸ¤¹¤ë¾ì½ê¤¬´Ö°ã¤Ã¤Æ¤¤¤¿ + + * ext/socket/socket.c (s_accept): threadÂбþ¤·¤Æ¤¤¤Ê¤«¤Ã¤¿ + +Sat Oct 5 01:32:27 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * io.c (io_readchar): EOF¤ÇÎã³°¤òȯÀ¸¤µ¤»¤ë + +Fri Oct 4 11:59:54 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ext/marshal/marshal.c (w_object): Hash¤ÈObject¤ÎÉüµì¤ËɬÍפʥϥà + ¥·¥å¥Æ¡¼¥Ö¥ë¤¬ÅϤµ¤ì¤Æ¤¤¤Ê¤«¤Ã¤¿¡¥ + + * variable.c (rb_path2class): ¥æ¡¼¥¶ÄêµÁ¥¯¥é¥¹¤ÎÉüµì¤Ë¼ºÇÔ¤·¤Æ¤¤¤¿ + + * variable.c (rb_path2class): ¥¯¥é¥¹¤¬Â¸ºß¤·¤Ê¤¤»þ¤Î¥¨¥é¡¼¤òFatal + ¤«¤éNameError¤Ø¡¥ + + * range.c (range_s_new): first,last¤¬Î¾ÊýNumeric¤Î»þ¥¨¥é¡¼¤Ë¤Ê¤Ã¤Æ + ¤¤¤¿¡¥ + + * range.c: start->first, end->last + +Wed Oct 2 02:02:46 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * file.c: DJGPP¤Çchmod,chown¤ò»È¤¨¤ë¤è¤¦¤Ë(¤Ã¤ÆDOS¤Ëchown¤¬¤¢¤ë¤Î¤«?) + + * class.c (rb_singleton_class): ¥Ó¥ë¥È¥¤¥ó¥¯¥é¥¹¤âextend¤·¤¿¤êÆÃ°Û + ¥á¥½¥Ã¥É¤òÄɲä·¤¿¤ê¤Ç¤¤ë¤è¤¦¤Ë + + * variable.c (rb_set_class_path): ¥æ¡¼¥¶ÄêµÁ¤Î¥È¥Ã¥×¥ì¥Ù¥ë¥¯¥é¥¹¤Ë + path¤òÀßÄꤷ¤Ê¤¤ + + * eval.c (eval): Îã³°¤¬RuntimeError¤Ë²½¤±¤Æ¤¤¤¿ + + * eval.c (eval): evalÃæ¤ÎÎã³°¤Îɽ¸½¤Î²þÁ± + + * eval.c (eval): eval_with_binding¤È¤Î°ìËܲ½ + + * eval.c (rb_eval): ¥¯¥é¥¹/¥â¥¸¥å¡¼¥ëÄêµÁ¤ÎÃæ¤«¤éÄêµÁÃæ¤Î¥¯¥é¥¹/¥â + ¥¸¥å¡¼¥ë¤¬»²¾È¤Ç¤¤ë¤è¤¦¤Ë + +Tue Oct 1 01:40:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.2-961001 + + * parse.y: cur_cref¤¬2ÅÙÀë¸À¤µ¤ì¤Æ¤¤¤¿ + + * signal.c (trap): SIGSEGV¡¤SIGBUS¤Î¤Ê¤¤µ¡¼ï¤ËÂбþ + + * io.c (Init_IO): °ú¿ô¥¿¥¤¥×¤Î»ØÄê´Ö°ã¤¤ + +Mon Sep 30 15:28:00 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.2-960930 + + * config.guess,config.sub: $host_os¤¬Àµ¤·¤¯ÀßÄꤵ¤ì¤Ê¤¤ + + * eval.c (rb_eval): yield¤ÇÀµ¤·¤¯¤Ê¤¤self¤¬ÀßÄꤵ¤ì¤Æ¤¤¤¿ + + * eval.c (ruby_run): toplevel¤ÎÎã³°½èÍý¤Î¥Ð¥° + +Mon Sep 30 09:13:26 1996 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> + + * djgppÂбþ + +Sat Sep 28 02:45:10 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.2-960928 + + * sample/ruby-mode.el (ruby-beginning-of-block): ¥Ö¥í¥Ã¥¯¤ÎÀèÆ¬¤Ë + °Üư(Àµ¤·¤¯¥¤¥ó¥Ç¥ó¥È¤·¤Æ¤¤¤Ê¤¤¤Èưºî¤·¤Ê¤¤) + (ruby-end-of-block): Ʊ¾å + + * eval.c (class_s_new): Class#new¤¬¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ð¤ì¤¿»þ¤Ï + initialize¤â¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ð¤ì¤ë¤è¤¦¤Ë + + * signal.c (sigsegv): SEGV¤Çbacktrace¤òɽ¼¨¤¹¤ë¤è¤¦¤Ë + +Fri Sep 27 09:51:07 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.2-960927 + + * eval.c (error_print): °ú¿ô¤Î¤Ê¤¤raise¤Ç¥á¥Ã¥»¡¼¥¸¤¬Àµ¤·¤¯É½¼¨¤µ + ¤ì¤ë¤è¤¦¤Ë¡¥ + + * eval.c (rb_longjmp): mesg¤¬nil¤Î»þRuntimeError¤òÀ¸À®¤¹¤ë¡¥ + + * eval.c (f_raise): °ú¿ô¤¬¤Ê¤¤»þ¤ËÂбþ + + * eval.c (thread_mark): stack¾å¤Ë¤Ê¤¤¥Ç¡¼¥¿¤Î¥¢¥É¥ì¥¹ÊÑ´¹¤ò¹Ô¤Ã¤Æ + ¤¤¤¿¡¥ + + * eval.c (Init_Thread): ³ä¹þ¤ß¤Î´Ö³Ö¤¬1ÉäÈŤ¹¤®¤¿¡¥ + +Thu Sep 26 16:02:45 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (thread_schedule): °ìÅÙ¥Ú¥ó¥Ç¥£¥ó¥°¤Ë¤Ê¤ë¤È¥Õ¥é¥°¤¬¥¯¥ê¥¢ + ¤µ¤ì¤Æ¤¤¤Ê¤«¤Ã¤¿¡¥ + + * process.c (rb_proc_exec): system/exec¤Î°ú¿ô¤¬¶õʸ»úÎó¤Ç¤¢¤Ã¤¿¾ì + ¹ç¡¤Îã³°¤òȯÀ¸¤¹¤Ù¤¤À¤Ã¤¿¡¥ + + * config.sub/config.guess: ¿·¤·¤¤¤â¤Î¤ËÃÖ¤´¹¤¨ + +Thu Sep 26 15:41:35 1996 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> + + * io.c (next_argv): -i.bak¤òBOW¤ÈDOS¤ËÂбþ¡¥ + +Thu Sep 26 01:31:43 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * io.c (io_sysread): EOF¤ÇÎã³° + + * io.c (f_readline): EOF¤ÇÎã³°¤òȯÀ¸¤¹¤ë¤è¤¦¤Ë¡¥gets¤Ï¸ß´¹À¤Î¤¿¤á + nil¤òÊÖ¤¹¤Þ¤Þ¤Ë¤¹¤ë + + * eval.c (proc_call): lambda¤«¤é¤Îreturn¤ÇIN_BLOCK¥Õ¥é¥°¤¬Î©¤Ã¤¿¤Þ + ¤Þ¤À¤Ã¤¿ + + * eval.c (PUSH_BLOCK2): thread¤ËÂбþ¤¹¤ë¤¿¤áBlock¤ò°ìÅÙstack¤Ë¥³¥Ô¡¼ + +Wed Sep 25 11:54:11 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (method_call): Const::method()·Á¼°¤ò»È¤¨¤ë¤è¤¦¤Ë¤·¤Æ¤ß¤¿¡¥ + °ú¿ô³ç¸Ì¤Ï¾Êά¤Ç¤¤Ê¤¤¡¥ + + * sample/test.rb: Process.kill¤Î¸ºß¤ò³Î¤«¤á¤Æ¤«¤é¥Æ¥¹¥È¤ò¹Ô¤¦ + + * eval.c (eval_with_binding): Âè2°ú¿ô¤È¤·¤Æbinding(¤Þ¤¿¤Ïlambda)¤ò + Í¿¤¨¤ë¤È¤½¤Î´Ä¶¤Çeval¤ò¼Â¹Ô¤¹¤ë¤è¤¦¤Ë¤·¤¿ + + * eval.c (f_binding): ¸½ºß¤Îbinding¤òÊÖ¤¹´Ø¿ô + + * eval.c: block¹½Â¤ÂΤËthe_class¤òÊݸ¤¹¤ë¥á¥ó¥Ð¤òÄɲà + + * process.c (Init_process): kill,wait,waitpid¤òProcess¤Ë°Üư + +Tue Sep 24 02:44:43 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * sample/ruby-mode.el: ¤¤¤í¤¤¤íÌäÂ꤬¿¤¤¤Î¤Ç°ÊÁ°¤Î¹â®²½¤ÏÇË´þ¡¥ + Ê̤Υ¢¥×¥í¡¼¥Á¤ò»È¤Ã¤¿¡¥ + + * lib/tk.rb (Tk.pack): Ê£¿ô¤Î¥¦¥£¥ó¥É¥¦¤ò¼õ¤±ÉÕ¤±¤ëpack + +Sat Sep 21 11:08:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (exprs): ¶õʸ¤â¼õ¤±ÉÕ¤±¤ë¤è¤¦¤Ëʸˡ¤òÊѹ¹¡¥º£¤Þ¤Ç¤Ï²þ¹Ô + ¤ÎϢ³¤À¤±¤¬µö¤µ¤ì¤Æ¤¤¤¿¡¥ + +Fri Sep 20 11:39:18 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * Fail¤ÎÂçȾ¤ò̾Á°¤Ä¤Îã³°¤ËÊѹ¹¡¥ + + * re.c (Init_Regexp): ̾Á°¤Ä¤Îã³°¤òƳÆþ¡¥ + + * eval.c (f_missing): Object¤Ïinspect¤·¤Ê¤¤¡¥ + + * object.c (inspect_i): Object#inspect¤Çloop¤ËÂбþ¡¥ + + * regex.c (re_search): /^$/¤¬""¤Ë¥Þ¥Ã¥Á¤·¤Ê¤«¤Ã¤¿¡¥ + +Thu Sep 19 19:25:12 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * regex.c (re_search): /^$/¤¬Èó¶õ¹Ô¤Ë¥Þ¥Ã¥Á¤·¤Æ¤¤¤¿¡¥ + +Tue Sep 17 10:28:11 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.2-960917 + +Mon Sep 16 10:47:56 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * sample/ruby-mode.el (ruby-calculate-indent): ±é»»»Ò·Ñ³¤Î¾ì¹ç¤Î + ʸ»úÎó¤ÎȽÄê¤Î¥Ð¥° + + * sample/ruby-mode.el (ruby-calculate-indent): else¤Ê¤É¤Î¼¡¤Î¹Ô¤Î + ¥¤¥ó¥Ç¥ó¥È·×»»¤òÀµ¤·¤¯¡¥ + +Sat Sep 14 08:37:19 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.2-960914 + +Fri Sep 13 08:06:03 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ext/socket/socket.c (tcpaddr): portÈÖ¹æ¤Ëntohs¤ò¤Ä¤±Ëº¤ì + + * dln.c (link_undef): ¥Æ¡¼¥Ö¥ë¤Î¼ïÎब´Ö°ã¤Ã¤Æ¤¤¤¿¡¥ + + * bignum.c (bigadd): °ú¤»»¤¬È¯À¸¤¹¤ë»þ¤Ë·×»»°ã¤¤¤¬µ¯¤¤Æ¤¤¤¿¡¥ + + * parse.y (iter_do_block): do..end¤Ç¤âdynamic variable¤ò¡¥ + + * bignum.c (big_pow): ¤è¤êÀµ³Î¤Ê·×»»¤ò(À°¿ôƱ»Î¤Ç¤Ïfloat¤ËÊÑ´¹¤·¤Ê + ¤¤)¡¥ + +Thu Sep 12 13:11:55 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * variable.c (rb_set_class_path): String¥¯¥é¥¹¤¬½é´ü²½¤µ¤ì¤ëÁ°¤Ë + String¤òºî¤Ã¤Æ¤¤¤¿¡¥Áȹþ¤ß¥¯¥é¥¹¤Ë¤Ïpath¤Ï¤¤¤é¤Ê¤¤ + + * parse.y (yylex): 0.1¤¬0¤Ë¤Ê¤Ã¤Æ¤¤¤¿ + + * parse.y (yylex): ¹ÔÈÖ¹æ¤ÎÉÔÀ°¹ç + + * gc.c (oblist_live_obj): º£¡ÖÀ¸¤¤Æ¤¤¤ë¡×Á´Éô¤Î¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹ + ¥¤¥Æ¥ì¡¼¥¿¡¥¤½¤Î¥¯¥é¥¹(¤Þ¤¿¤Ï¥µ¥Ö¥¯¥é¥¹)¤ÎÁ´Éô¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤òÊÖ + ¤¹each_object_of¤âÄêµÁ¤·¤¿¡¥ + + * class.c (rb_define_class_id): ̵Â̤ʥ¯¥é¥¹¤ò³ä¤êÅö¤Æ¤Æ¤¤¤¿¡¥·ë²Ì + ¤È¤·¤ÆÌ¤½é´ü²½¤Î¥¯¥é¥¹¥ª¥Ö¥¸¥§¥¯¥È¤¬Â¸ºß¤·¤Æ¤¤¤¿¡¥ + +Wed Sep 11 00:56:23 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (yylex): octal¤ÎÄê¿ô¤Î¸¡½Ð¤ò¤è¤êÀµ³Î¤Ë(090¤Ï¥¨¥é¡¼¤È¤«)¡¥ + + * bignum.c (big_minus): y¤¬x¤è¤êÂ礤¤¾ì¹ç¤Ë¥¨¥é¡¼¡¥ + + * parse.y (yylex): ¥¨¥é¡¼¹ÔÈÖ¹æ¤Îɽ¼¨¤ò¤è¤êÀµ³Î¤Ë + + * sample/ruby-mode.el (ruby-expr-beg): ÊÑ¿ô̾¤¬1ʸ»ú¤Î»þ¸íưºî¤·¤Æ + ¤¤¤¿¡¥ + + * sample/ruby-mode.el (ruby-calculate-indent): ?/¤Ç¥ë¡¼¥×¤ËÍî¤Á¤¤ + ¤¿¥Ð¥°¤ò½¤Àµ¡¥ + + * enum.c (enum_min,enum_max): sort¤Î¤è¤¦¤Ë¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¤âưºî¤¹ + ¤ë¤è¤¦¤Ë¡¥ + + * enum.c (enum_find_all): typo + +Tue Sep 10 12:07:12 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * node.h (nd_line): NODE¤Îline¤òflags¤Ë²¡¤·¹þ¤á¤Æ¥ª¥Ö¥¸¥§¥¯¥È¥µ¥¤ + ¥º¤ò¾®¤µ¤¯¤·¤¿¡¥À©¸Â:32bit int¤Î¥Þ¥·¥ó¤Î¾ì¹ç¡¤¥Õ¥¡¥¤¥ë¤Î¹Ô¿ô¤¬ + 32767¤ò±Û¤¨¤ë¤ÈÀµ¾ï¤Ëɽ¼¨¤µ¤ì¤Ê¤¤¡¥ + + * st.c: hash¤Ècompare¤Î´Ø¿ô¥á¥ó¥Ð¤ò¹½Â¤ÂΤ˥ѥ寡¤¥¯¥é¥¹Åª¤Ê»È¤¤ + Êý¤ò¹Ô¤¦¡¥1 table¤¢¤¿¤ê4 byte¤ÎÀáÌó¡¥ + +Mon Sep 9 16:35:54 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * file.c (file_truncate): Ä󶡤µ¤ì¤Ê¤¤»þ¤Ë¤ÏÆÃÊ̤ÊÎã³°¤òȯÀ¸¤¹¤ë¤è + ¤¦¤Ë¡¥ + + * eval.c (Init_Proc): ÉÔŬÀڤʰÌÃÖ¤Îlocal-jump¤òÎã³°¤Ë¡¥ + +Sat Sep 7 17:06:15 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (proc_call): ¤Þ¤À¥¹¥³¡¼¥×¤¬¥¹¥¿¥Ã¥¯¾å¤Ë¤¢¤ë»þ¤Ë¤Ï¶É½êæ½Ð + ¤ò͸ú¤Ë¤¹¤ë¡¥¤³¤ì¤Ç¡¤proc¤òÀ¸À®¤·¤Æcall¤¹¤ë¤³¤È¤Ï¡¤¥¹¥³¡¼¥×¤òæ + ½Ð¤·¤Ê¤¤¸Â¤ê¡¤yield¤ÈƱ¤¸°ÕÌ£¤ò»ý¤Ä¤³¤È¤Ë¤Ê¤ë¡¥ + +Fri Sep 6 13:30:59 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * sample/ruby-mode.el (ruby-indent-to): ¥¤¥ó¥Ç¥ó¥È¤¬ÊѤï¤é¤Ê¤¤»þ¤Ë + ¤Ï¥Ð¥Ã¥Õ¥¡¤òÊѹ¹¤·¤Ê¤¤¡¥ + (ruby-calculate-indent): ¤Þ¤ºÊ¸»úÎó¤ÎÆâÉô¤«È½ÃǤ·¤Æ¤«¤é¡¤Á°¤Î¹Ô + ¤«¤é¥Ñ¡¼¥º¤ò¹Ô¤¦¡¥defun¤¬Â礤¯¤Ê¤Ã¤¿»þ¤Î¹â®²½¡¥ + (ruby-in-string-p): ʸ»úÎó¤ÎÆâÉô¤«¤É¤¦¤«¤òȽÃǤ¹¤ë´Ø¿ô(°ÊÁ°¤Î + parse¤«¤éʬΥ) + (ruby-parse-region): ʸ»úÎó¤ËÂФ¹¤ë½èÍý¤ò¤Ï¤º¤¹¡¥ + (ruby-beginning-of-block): ¥Ö¥í¥Ã¥¯¤ÎÀèÆ¬¤Ë + (ruby-end-of-block): ¥Ö¥í¥Ã¥¯¤ÎËöÈø¤Ë(ÃÙ¤¤¡Ä) + +Thu Sep 5 14:23:07 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * file.c (file_s_split): [dirname,basename]¤Ësplit¤¹¤ë¡¥ + + * eval.c (rb_eval): eval¤ÎÃæ¤Ç¤âÄê¿ô¤ÎÃͤ¬Àµ¤·¤¯¤Ê¤ë¤è¤¦¤Ë¡¥¤³¤ì¤Ç + Äê¿ô¤Ë´Ø¤·¤Æ¤ÏÀÅŪ¤Ê¥¹¥³¡¼¥×¤¬Êݾڤµ¤ì¤ë¤è¤¦¤Ë¤Ê¤Ã¤¿¡¥ + + * st.c (rehash): ¥Ï¥Ã¥·¥å³ÈÂç¤Î·Ï¿ô¤ò2¤«¤é1.79¤Ë¡¥³ä»»¤¬¤è¤êÎɤ¤ÃÍ + ¤òÊÖ¤¹¤è¤¦¤Ë¡¥ + +Thu Sep 5 00:32:07 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (class_superclass) ¥¯¥é¥¹¤Î¥¹¡¼¥Ñ¡¼¥¯¥é¥¹¤òÊÖ¤¹¥á¥½¥Ã¥É¡¥ + +Wed Sep 4 16:54:56 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * random.c (f_rand): Bignum¤älong¤ÎÈϰϤò±Û¤¨¤ëFloat¤ËÂФ¹¤ëÍð¿ô¤â + ȯÀ¸¤Ç¤¤ë¤è¤¦¤Ë¡¥ + + * struct.c (struct_alloc): Fatal¤Ç¤Ï¤Ê¤¯Îã³°¤òȯÀ¸¤µ¤»¤ë¤è¤¦¤Ë(ÄÌ + ¾ï¤Î»ÈÍѤÇȯÀ¸¤·¤¦¤ë)¡¥ + + * struct.c (struct_s_members): Struct¤ÎÆÃ°Û¥á¥½¥Ã¥É¤Ç¤Ï¤Ê¤¯¡¤À¸À® + ¤µ¤ì¤¿Struct¥¯¥é¥¹¤ÎÆÃ°Û¥á¥½¥Ã¥É¤Ë¤·¤¿¡¥ + + * st.c (st_init_table): rubyÀìÍѤ˥ѥé¥á¥¿¤ò¸ÇÄê¤Ë¤·¤¿(¥µ¥¤ + ¥º¤¬¸º¤Ã¤¿) + +Mon Sep 2 11:37:59 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * array.c (ary_shift): capa¤¬¤¢¤Þ¤ê¤Ë¤âÂ礤¤»þ¤Ë¤ÏÎΰè¤òREALLOC + (ary_pop): Ʊ¾å + + * string.c (str_inspect): multibyte character Âбþ¤Ë¥ß¥¹¡¥ + (str_inspect): unsigned char¤Ë¤·¤Ê¤¤¤ÈÉ乿ŏ³«¤µ¤ì¤Æ¤·¤Þ¤¦ + + * parse.y (primary): `::'¤òprimary¤Ë°Üư Foo::Bar.Baz¤¬¥¨¥é¡¼¤Ë¤Ê + ¤é¤Ê¤¤¤è¤¦¤Ë¡¥ + + * parse.y (primary): ¥ª¥Ú¥ì¡¼¥¿·Á¼°¤ÎÆÃ°Û¥á¥½¥Ã¥É¤¬ÄêµÁ¤Ç¤¤Ê¤¤ + + * random.c (f_rand): max¤¬0¤Î»þ¤ËÂбþ + + * io.c (io_printf): ´Ø¿ô¤òÄêµÁ¤·¤Æ¤¤¤¿¤¬¥¤¥ó¥¿¥×¥ê¥¿¤ËÅÐÏ¿¤·¤Æ¤¤¤Ê + ¤«¤Ã¤¿¡¥ + + * file.c (file_s_basename): Âè2°ú¿ô¤¬Ìµ¤¤»þ¤Ë¥¨¥é¡¼¡¥ + +Thu Aug 29 10:49:40 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (expr): ¥¤¥Æ¥ì¡¼¥¿¤Î¿··Á¼°¤Ë¡Ömethod do .. end¡×·Á¼°¤òºÎ + ÍѤ·¤¿¡¥¤â¤Á¤í¤óÀΤηÁ¼°¤â͸ú¡¥ + + * sample/ruby-mode.el (ruby-calculate-indent): end¤Î¿ô¤ÎÊý¤¬Â¿¤¤¾ì + ¹ç¤Ë¤â¥¨¥é¡¼¤òµ¯¤³¤µ¤Ê¤¤¤è¤¦¤Ë¡¥ + +Wed Aug 28 09:41:36 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * numeric.c (upto,downto,step,times): Âоݤ¬fixnum¤ÎÈϰϤò±Û¤¨¤Æ¤â + ưºî¤¹¤ë¤è¤¦¤Ë¡¥ + +Mon Aug 26 10:04:37 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * missing/setenv.c (envix): typo(missing `== 0' for memcmp) + + * dir.c (dir_foreach): foreach(dir open -> read loop -> close¤Þ¤Ç) + + * io.c (io_foreach): foreach(file open -> read loop -> close¤Þ¤Ç) + + * Fatal¤Î¤¦¤ÁÊ᪲Äǽ¤Ê¤¤¤¯¤Ä¤«¤òÎã³°¤Ë¡¥ + +Sat Aug 24 23:56:37 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * bignum.c (bigdivmod): FIX2INT -> INT2FIX Âç´Ö°ã¤¤ + +Fri Aug 23 18:13:03 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * regex.c (re_free_registers): allocate¤·¤Æ¤¤¤Ê¤¤»þ¤Ë¤ÏÅöÁ³ free + ¤·¤Æ¤Ï¤¤¤±¤Ê¤¤¡¥ + +Thu Aug 22 01:20:35 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (thread_create): ³°Â¦¤«¤é¶¯À©½ªÎ»¤µ¤»¤é¤ì¤¿thread¤Ï + cleanup¤¹¤ëɬÍפ¬Ìµ¤¤¡¥ + +Wed Aug 21 09:57:28 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (thread_create): thread¤ò½ªÎ»¤µ¤»¤¿Âç°èæ½Ð¤Î¾ðÊó¤ò + main_thread¤ËÅϤ¹¤è¤¦¤Ë¡¥ + + * parse.y (call_args): ºÇ½ª°ú¿ô¤Ë³ç¸Ì¤ò¾Êά¤·¤¿¥á¥½¥Ã¥É¸Æ½Ð¤·¤òÃÖ + ¤±¤ë¤è¤¦¤Ë(Îã: print foo bar, baz == print(foo(bar,baz))) + +Tue Aug 20 13:37:16 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (masign): ¿½ÅÂåÆþ¤Èrest°ú¿ô¤Îưºî¤ò¹ç¤ï¤»¤Æ¶õ¤ÎÇÛÎó¤òÂå + Æþ¤¹¤ë¤è¤¦¤Ë¡¥ + + * parse.y (arg): defined?¤Î¶¯ÅÙ¤ò¤â¤¦¤Á¤ç¤Ã¤È¶¯¤¯ + + * eval.c (error_print): -w¤ÇÎ㳰̾¤âɽ¼¨¤¹¤ë¤è¤¦¤Ë + + * eval.c (rb_eval): ¿·¹½Ê¸¤ËÂбþ + (handle_rescue): Ê᪤¹¤ëÎã³°¤ò kind_of? ¤ÇƱÄê + + * parse.y (primary): rescue¤Î¹½Ê¸¤òÊѹ¹(ƱÄê°ú¿ô¤ÎÄɲá¤Ê£¿ôrescue) + + * Fail()¤Î¤«¤Ê¤ê¤òŬÅö¤ÊÎã³°¤ò»È¤¦¤è¤¦¤Ë + + * eval.c (thread_interrupt): Interrupt(º£¤Ïnon-local jump)¤Ï + main-thread¤ËÁ÷¤é¤ì¤ë¤è¤¦¤Ë¡¥ + + * eval.c (rb_longjmp): $! ¤ÎÆâÍÆ¤òʸ»úÎ󤫤éÎã³°¥¯¥é¥¹¤ËÊѹ¹ + (rb_raise): rb_fail ¤«¤é̾¾ÎÊѹ¹ + (rb_interrupt): Îã³°²½ + (rb_exit): Îã³°²½ + + * error.c (Init_Exception): Îã³°¥¯¥é¥¹¤Î¿·Àß(ʸ»úÎó¤Î¥µ¥Ö¥¯¥é¥¹) + +Mon Aug 19 19:40:52 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * signal.c (trap): ¸Å¤¤¥Ï¥ó¥É¥é¤òÊÖ¤¹¤è¤¦¤Ë¡¥ + +Wed Aug 14 00:07:18 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (rb_trap_eval): ¥Ï¥ó¥É¥é¤Î¤¿¤á¤Ëthread¤òfork¤¹¤ë¤³¤È¤ò»ß + ¤á¤¿¡¥ + + * eval.c (thread_mark): threadËè¤Î $!, $@ ¤ò¥Þ¡¼¥¯¤·Ëº¤ì + + * ext/dbm/dbm.c (fdbm_delete): ¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ð¤ì¤¿¾ì¹ç¡¤Í×ÁÇ + ¤¬Ìµ¤±¤ì¤Ð¥Ö¥í¥Ã¥¯¤òɾ²Á¤¹¤ë¡¥ + + * hash.c (hash_delete): ¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ð¤ì¤¿¾ì¹ç¡¤Í×ÁǤ¬Ìµ¤±¤ì + ¤Ð¥Ö¥í¥Ã¥¯¤òɾ²Á¤¹¤ë¡¥ + + * array.c (ary_delete): ¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ð¤ì¤¿¾ì¹ç¡¤Í×ÁǤ¬Ìµ¤±¤ì + ¤Ð¥Ö¥í¥Ã¥¯¤òɾ²Á¤¹¤ë¡¥ + + * eval.c (rb_interrupt): SIGINT¤Î¥Ç¥Õ¥©¥ë¥È¤òexit¤«¤éÆÃÊ̤ÊÂç°èæ + ½Ð¤Ë¡¥¤ä¤Ï¤ê³ä¤ê¹þ¤Þ¤ì¤¿°ÌÃÖ¤Îɽ¼¨¤¬Ìµ¤¤¤Î¤Ï¼ä¤·¤¤¤Î¤Ç¡¥ + +Tue Aug 13 01:34:00 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (rb_exit): sub-threadÆâ¤Ç¤Îexit¤âstatus¤òÊݸ¤¹¤ë¤è¤¦¤Ë + (thread_create): ¼«threadÆâ¤Îexit¤ËÂбþ + + * signal.c (sighandle): SIGINT¤Î¥Ç¥Õ¥©¥ë¥È¥Ï¥ó¥É¥é¤Ïexit¤¹¤ë¤è¤¦¤Ë + (°ÊÁ°¤ÏÎã³°¤òȯÀ¸¤·¤Æ¤¤¤¿)¡¥ + + * Îã³°¤Î°ìÉô¤òFatal¤Ë¡¥ + + * string.c (str_aset): ʸ»úÎó¤ÎÃÖ´¹¤ÎÂоݤ¬Éôʬʸ»úÎó¤Ç¤Ê¤«¤Ã¤¿»þ¡¤ + Îã³°¤òȯÀ¸¤µ¤»¤Ê¤¤¤è¤¦¤Ë + + * eval.c (proc_call): Proc¤ÎÃæ¤«¤ébreak/next¤ÏÄ̤·¡¤Â¾¤Î¤â¤Î¤ÏÄ̤µ + ¤Ê¤¤¤è¤¦¤Ë + +Mon Aug 12 14:15:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * object.c (krn_type): ʸ»úÎó¤òÊÖ¤¹ + + * eval.c (thread_create): sub-threadÆâ¤Ç¤Îexit¤ËÂбþ + + * numeric.c (fix_type): ʸ»úÎó¤òÊÖ¤¹ + + * io.c (f_p): ¥Ç¥Ð¥Ã¥°Íѥǡ¼¥¿É½¼¨¥á¥½¥Ã¥É + + * eval.c (f_missing): nil/TRUE/FALSE¤òÆÃḚ̂·¤¤ + + * string.c (str_inspect): Ť¤Ê¸»úÎó¤òû½Ìɽ¼¨¡¥inspect¤ÎƯ¤¤ò + human readable string¤ÎÀ¸À®¤ËÅý°ì(re-generatable string ¤ÏÀµ¼°¤Ë + ̵¤¯¤Ê¤Ã¤¿)¡¥ + +Sat Aug 10 16:54:21 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * object.c (Init_Object): kernel/nil/false/true¤Î¥¯¥é¥¹Ì¾¤òÊѹ¹(¾® + ʸ»ú¤Ë)¡¤ruby¥¹¥¯¥ê¥×¥È¤«¤é¥¢¥¯¥»¥¹¤Ç¤¤Ê¤¤¤è¤¦¤Ë¡¥ + + * eval.c (rb_eval): CONSTANT¤Î¥¢¥¯¥»¥¹Àè¤òñ½ã²½¡¥cref¤ò»È¤ï¤Ê¤¤¡¥ + + * eval.c (f_eval): ÆÃ°Û¥á¥½¥Ã¥ÉÆâ¤Ç¤âÄê¿ô¤ÎÃͤ¬Àµ¤·¤¯¤Ê¤ë¤è¤¦¤Ë + +Fri Aug 9 12:23:17 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * array.c (ary_concat): append -> concat String¤Ë¹ç¤ï¤»¤¿ + + * parse.y (yylex): `$;'¤¬»È¤¨¤Ê¤«¤Ã¤¿¡¥ + + * array.c (ary_push_method): Ê£¿ô°ú¿ô¤ò¼õ¤±ÉÕ¤±¤ë¤è¤¦¤Ë¡¥ + (ary_unshift): Ê£¿ô°ú¿ô¤ò¼õ¤±ÉÕ¤±¤ë¤è¤¦¤Ë¡¥ + + * io.c (io_popen): IO.popen¤Çcommand pipe¤¬³«¤±¤ë¤è¤¦¤Ë¡¥ + + * object.c (Init_Object): Kernel¤ÈNil¤òruby script¤«¤é¥¢¥¯¥»¥¹¤Ç¤ + ¤Ê¤¤¤è¤¦¤Ë¡¥ + +Thu Aug 8 01:21:47 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * object.c (f_integer): À°¿ô¤Ø¤ÎÊÑ´¹´Ø¿ô + (f_float): ¼Â¿ô¤Ø¤ÎÊÑ´¹´Ø¿ô + (f_string): ʸ»úÎ󤨤ÎÊÑ´¹´Ø¿ô + (f_array): ÇÛÎ󤨤ÎÊÑ´¹´Ø¿ô + + * bignum.c (big_to_i): FIXNUM¤ÎÈϰϤǤʤ¤»þ¤ÏBignum¤Î¤Þ¤ÞÊÖ¤¹¤è¤¦ + ¤ËÊѹ¹¡¥ + +Wed Aug 7 09:28:38 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99.1-960807 + + * parse.y (mlhs): ¡Ö*foo = 1,2,3¡×¥¿¥¤¥×¤Î¿½ÅÂåÆþ¤â²Äǽ¤Ë¡¥ + + * object.c (Init_Object): ¥¯¥é¥¹True/False¤òruby script¤«¤é¥¢¥¯¥» + ¥¹¤Ç¤¤Ê¤¤¤è¤¦¤Ë¡¥ + + * object.c (nil_inspect): inspectɽ¸½¤Ï"nil"¤Ë + + * io.c (io_print): nil¤Îprint¤ònil¤Ë¡¥ + + * object.c (nil_to_s): nil¤Îʸ»úÎóɽ¸½¤ò""¤Ë¡¥ + +Tue Aug 6 01:12:32 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * dir.c (dir_s_open): file descripter¤¬Â¤ê¤Ê¤¤»þ¤Ë¤Ïgc¤·¤Æ¤«¤é¤â + ¤¦°ìÅÙopen¤·¤Æ¤ß¤ë¡¥ + + * io.c (rb_fopen): ¤¹¤Ù¤Æ¤Îfopen()¤Ë¤Ä¤¤¤Æfile descripter¤¬Â¤ê¤Ê + ¤¤»þ¤Ë¤Ïgc¤·¤Æ¤«¤é¤â¤¦°ìÅÙopen¤·¤Æ¤ß¤ë¡¥ + + * ext/socket/socket.c (Init_socket): Äê¿ô¤ÎÄɲᥠ+ + * sample/ruby-mode.el (ruby-indent-to): ¥¤¥ó¥Ç¥ó¥È¸å¤Î¥«¡¼¥½¥ë°ÌÃÖ + ¤ÎÄ´À°¤òÀµ¤·¤¯¡¥ + + * gc.c (gc): ³ä¹þ¤ß¥Á¥§¥Ã¥¯¤ò¹Ô¤ï¤Ê¤¤(C¥³¡¼¥É¤ÎÃæ¤Ç°Â¿´¤·¤Æ + malloc()¤¬»È¤¨¤Ê¤¯¤Ê¤ë¤Î¤Ç)¡¥ + + * st.c (call_hash_func): signal¤Èthread¤Ë¤è¤ë³ä¹þ¤ß¤ËÂбþ¡¥ + + * sig.h (DEFER_INTS): ³ä¹þ¤ß¶Ø»ß¶è´Ö¤Î»ØÄê + + * eval.c (f_require): thread¤Ë¤è¤ërequire¤Î¶¥¹ç¤ËÂбþ(ºÇ½é¤Î + require¤¬½ªÎ»¤¹¤ë¤Þ¤Ç¾¤Îthread¤ÏÂÔ¤Ä)¡¥ + + * bignum.c (str2inum): 0x80000000¤ÎÃͤ¬Éé¤Ë¤Ê¤Ã¤Æ¤¤¤¿ + + * sprintf.c (f_sprintf): ʸ»úÎóËöÈø¡¤¹ÔËö¤ÎñÆÈ¤Î`%'¤ËÂбþ + + * bignum.c (big_cmp): Èæ³Ó¤Î·ë²Ì¤¬µÕ¤Ë¤Ê¤ë»þ¤¬¤¢¤Ã¤¿¡¥ + +Mon Aug 5 10:58:13 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * process.c (proc_exec_v): Îã³°¤Î¥á¥Ã¥»¡¼¥¸¤òʬ¤«¤ê¤ä¤¹¤¯¡¥ + + * ext/dbm/dbm.c (fdbm_store): nil¤ò³ÊǼ¤¹¤ë¤ÈÍ×ÁǤκï½ü¤Ë¤Ê¤ë + + * ext/dbm/dbm.c: ¥µ¥¤¥º¤ò¥¥ã¥Ã¥·¥å¡¥ + +Sat Aug 3 01:52:52 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (rb_fail): `fail'¤¬°ú¿ô̵¤·¤Ç¸Æ¤Ð¤ì¤¿»þ¤À¤±°ÊÁ°¤Î`$@'¤òÊÝ + ¸¤¹¤ë¤è¤¦¤Ë¡¥ + + * eval.c (f_fail): frame¤ÎÄ´À° + +Fri Aug 2 11:26:21 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ext/socket/socket.c (bsock_setopt): val¤È¤·¤ÆTRUE/FALSE/Fixnum¤â + ¼õ¤±ÉÕ¤±¤ë¤è¤¦¤Ë¡¥ + + * ext/socket/socket.c (Init_socket): SO_REUSEADDRÅù¤ÎÄê¿ô¤ÎÄɲà + + * ext/md5/md5init.c: md5¥â¥¸¥å¡¼¥ë(½é¤ÎÊ£¿ô¥Õ¥¡¥¤¥ë¤«¤é¤Ê¤ë¥â¥¸¥å¡¼ + ¥ë¤Ç¤â¤¢¤ë) + + * ruby.h (Make_Data_Struct): Data: object¤ÎinstanceÊÑ¿ô¤Ë³ÊǼ -> + Data·¿¤ÎObject¤Ë(Dir,Time,Proc,Thread,DBM) + +Thu Aug 1 11:38:44 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ext/dbm/dbm.c (fdbm_store): value¤¬Ê¸»ú¤Ç̵¤¤»þ¤ËÂбþ + +Wed Jul 31 10:53:42 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ext/socket/socket.c (open_inet): htons¤¬É¬ÍפǤ¢¤Ã¤¿ + (tcpaddr): ntohl¤ÇÊÑ´¹¤·¤¿ + + * process.c (rb_proc_exec): execvp -> execv + +Tue Jul 30 17:48:33 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c: `$?'¤òthread local¤Ë + + * Makefile.in (install): install»þ¤Ëstrip¤ò¹Ô¤¦ + + * configure.in: install»þ¤Îstrip¤Î¸¡½Ð + + * configure.in: NEXTSTEPÂбþ + + * version 0.99.1-960730 + +Tue Jul 30 16:40:35 1996 SHIROYAMA Takayuki <psi@fortune.nest.or.jp> + + * dln.c (dln_load): NeXT dln(mach-o)Âбþ¡¥configure¤Ï̤Âбþ + +Tue Jul 30 09:46:51 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * process.c (f_system): Ê£¿ô°ú¿ô¤â¤È¤ì¤ë¤è¤¦¤Ë + + * process.c (f_exec): Ê£¿ô°ú¿ô¤â¤È¤ì¤ë¤è¤¦¤Ë + + * array.c (ary_append): ÇÛÎó(¤Þ¤¿¤ÏEnum)¤ÎÍ×ÁǤòÇ˲õŪ¤ËÄɲà + + * array.c (ary_plus): Enum¤Ï¤½¤ÎÍ×ÁǤòÄɲà + + * file.c (file_s_open): File.open¤òÄɲà + + * struct.c (struct_new): FIX2INT¤ò˺¤ì¤Æ¤¤¤¿ + + * file.c (Init_File): exists? -> exist? + + * object.c (obj_is_kind_of): is_kind_of? -> kind_of?, is_a? + + * object.c (obj_is_instance_of): is_instance_of? -> instance_of? + +Mon Jul 29 16:40:02 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (parse_regx): ¼°Å¸³«¤ò¹Ô¤Ã¤¿¾ì¹ç¡¤casefold¤ÎÀßÄ꤬¤Ç¤¤Æ + ¤¤¤Ê¤«¤Ã¤¿¡¥ + + * object.c (true_type): TRUE/FALSE¤Ëtype¤ò¼ÂÁõ¡¥ + + * parse.y (read_escape): 3ʸ»ú°ÊÆâ¤Îoctal¤ËÂбþ(\0¤È¤«) + +Fri Jul 26 00:31:45 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * array.c (ary_reverse_bang): in-place¤ÇÇÛÎó¤òȿž¤µ¤»¤ë + (ary_sort_bang): in-place¤Çsort¤¹¤ë + (ary_sort): sort¤·¤¿ÇÛÎó¤òÊÖ¤¹¤è¤¦¤Ë + (ary_delete_at): »ØÄꤷ¤¿°ÌÃÖ¤ÎÍ×ÁǤòºï½ü¤¹¤ë + + * eval.c (rb_call): stack¿¼¤µ¥Á¥§¥Ã¥¯¤òËè²ó¤Ï¹Ô¤ï¤Ê¤¤¤è¤¦¤Ë + + * error.c (Warning): ¼Â¹ÔÃæ¤Îwarning¤¬É½¼¨¤µ¤ì¤Æ¤¤¤Ê¤«¤Ã¤¿ + + * eval.c (compile): Î㳰ȯÀ¸¤òʬΥ¡¥ + + * eval.c (f_eval): ÊÑ¿ôrb_in_eval¤òÀµ¤·¤¯´ÉÍý¤¹¤ë¤è¤¦¤Ë + + * ext/dbm/dbm.c (fdbm_store): ³ÊǼ¤¹¤ëkey¤òʸ»úÎó¤ËÊÑ´¹ + + * eval.c (rb_call): ̵¸ÂºÆµ¢¤Î¥Á¥§¥Ã¥¯¤òÂç°èæ½Ð¤ò¹Ô¤¦C method¤Ë¤â + Âбþ¤µ¤»¤¿¡¥thread¤Îstack¿¼¤µ¥Á¥§¥Ã¥¯¥ë¡¼¥Á¥ó¤òήÍÑ¡¥ + + * parse.y (yylex): Âè1°ú¿ô¤Îunary -/+¤ÎȽÄ꤬´Ö°ã¤Ã¤Æ¤¤¤¿¡¥ + + * parse.y (yylex): unary +¤Ç¿ô»ú¤ò;·×¤ËÆÉ¤ó¤Ç¤¤¤¿(ex. +5 -> 55) + +Thu Jul 25 12:15:04 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (yylex): Û£Ëæ¤Ç¤Ê¤¤°ú¿ô¤ËÂФ·¤Æ·Ù¹ð¤ò½Ð¤·¤Æ¤¤¤¿¡¥ + + * eval.c (iterator_p): °ú¿ô¤Ç¸Æ¤ó¤Ç¤âÀµ¤·¤¤·ë²Ì¤òÊÖ¤¹¤è¤¦¤Ë¡¥ + + * parse.y: break/next/redo/retry¤Î¥á¥½¥Ã¥É²½¡¥ + + * sample/ruby-mode.el (ruby-calculate-indent): nest¤Î¥Á¥§¥Ã¥¯¥ß¥¹ + + * sample/ruby-mode.el (ruby-parse-region): ͽÌó¸ì¤Î¥Á¥§¥Ã¥¯¤ò¶¯²½ + + * parse.y (primary): unless/until¤ÎÉü³è + +Tue Jul 23 18:50:10 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * array.c (Array#empty?), Hash.c (Hash#empty?), ext/dbm/dbm.c (DBM#empty?): + ¶õ¤ÎȽÄê½Ò¸ì + + * eval.c (f_unless): if¤ÎµÕ¤ò¤¹¤ë¥¤¥Æ¥ì¡¼¥¿ + + * eval.c (f_until): while¤ÎµÕ¤ò¤¹¤ë¥¤¥Æ¥ì¡¼¥¿ + + * parse.y: not¤ÎÍ¥Àè½ç°Ì¤òand/or¤è¤ê¹â¤¯ + + * parse.y (expr): `!'¤ò°ú¿ô³ç¸Ì¤ò¾Êά¤·¤¿call¤Ç¤â͸ú¤Ë + +Mon Jul 22 10:15:38 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99-960722 + + * array.c (ary_print_on): OFS¤ÎNIL¥Á¥§¥Ã¥¯¤¬ÉÔ´°Á´ + + * ruby.c (load_file): ɸ½àÆþÎϤ«¤é¤Î¥¹¥¯¥ê¥×¥È¤¬¶õ¤Î»þ¤ËÂбþ¡¥ + + * ruby.c (proc_options): -w¤Ç¤Ï°ú¿ô̵¤·¤Î»þ¤Ë¤Ïɸ½àÆþÎϤ«¤é¥¹¥¯¥ê + ¥×¥È¤ò¤È¤ë(-v¤Ç¤Ï¤¿¤ó¤Ë½ªÎ»¤¹¤ë)¡¥ + + * array.c (ary_compact): nil¤ÎÍ×ÁǤò¼è¤ê½ü¤¯¥á¥½¥Ã¥É + + * array.c (ary_nitems): nil¤Ç¤Ê¤¤Í×ÁǤò¿ô¤¨¤ë¥á¥½¥Ã¥É + +Sun Jul 20 00:51:53 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ruby.c (proc_options): -w option¤òÄɲà + + * parse.y: {}¤¬ÊĤ¸¤Æ¤¤¤Ê¤¤»þ¤Ë¤ÏŸ³«¤·¤Ê¤¤Ê¸»úÎó¤ò + +Fri Jul 19 16:16:05 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99-960719 + + * lib/find.rb: ÀÐÄÍÈÇ(prune¤Î³ÈÄ¥ÉÕ¤) + + * file.c (test_l): lstat¤ÇÄ´¤Ù¤Ê¤¤¤È¤Í¡¥ + + * eval.c (f_throw): Âè2°ú¿ô¤ò¾Êά²Äǽ¤Ë¡¥ + + * parse.y (str_extend): {}¤Î¥Í¥¹¥È¤ËÂбþ + +Thu Jul 18 18:25:46 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99-960718 + + * parse.y (str_extend): ʸ»úÎóÃæ¤Î¼°Å¸³«¤Ë \" ' ` / ¤ò´Þ¤à»ö¤¬¤Ç¤ + ¤ë¤è¤¦¤Ë¡¥ + +Tue Jul 16 15:55:31 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * sample/ruby-mode.el (ruby-parse-region): Àµµ¬É½¸½Æâ¤Î¥¨¥¹¥±¡¼¥× + ¤ËÂбþ + + * version 0.99-960716 + +Fri Jul 12 10:06:19 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * io.c (f_select): °ú¿ô¤Îclose check. + + * ruby.c (load_file): #!¹Ô¤Î°ú¿ô¥Á¥§¥Ã¥¯¤òÂè1°ú¿ô¤Ë¸ÂÄê(¼Â¤ò¤¤¤¦¤È + DOS²þ¹ÔÂкö) + +Wed Jul 10 17:18:35 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99-960710 + + * time.c (time_s_timegm/time_s_timelocal): »þ´Ö¤òÀ¸À®¤¹¤ë¥á¥½¥Ã¥É + +Mon Jun 17 15:59:20 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99-960617 + + * parse.y (yyerror): ¥¨¥é¡¼É½¼¨¤Î´Êά²½¡¥ + +Wed Jun 12 14:11:01 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * signal.c (rb_trap_exit): trap 0¤Ïthread¤òÀ¸À®¤»¤º¤Ë½èÍý¤¹¤ë¡¥ + +Fri Jun 7 10:17:01 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * array.c/hash.c (indexes): ÇÛÎó1°ú¿ô¤Î¥Ñ¥¿¡¼¥ó¤ò̵¤¯¤·¤¿¡¥ÇÛÎó¤Î + ¾ì¹ç¤Ï`*ary'¤ò»È¤Ã¤Æ¤â¤é¤ª¤¦¡¥ + + * eval.c (thread_wait_threads): main_thread¤¬½ªÎ»¤¹¤ëÁ°¤Ë¾¤Î + thread¤òÂÔ¤Ä(¶¯À©Åª¤Ë¤Ï½ªÎ»¤µ¤»¤Ê¤¤)¡¥ + (ruby_run): ¾¤Îthread¤òÂԤäƤ¤¤ë´Ö¤Ë¥·¥°¥Ê¥ë¤¬Í褿¤é¡¤Á´thread + ¤ò¶¯À©½ªÎ»¤µ¤»¤ë¡¥ + + * eval.c (rb_fail): ¥á¥½¥Ã¥É̾¤ò`$!'¤ËËä¤á¹þ¤à¡¥ + + * eval.c (thread_create): main_thread¤Î¥³¥ó¥Æ¥¯¥¹¥È¤¬¥»¡¼¥Ö¤µ¤ì¤Ê + ¤¤¾ì¹ç¤¬¤¢¤Ã¤¿¡¥ + + * process.c (f_sleep): »þ´Ö¤ò»ØÄꤻ¤º¡¤thread¤¬¤Ò¤È¤Ä¤·¤«¤Ê¤¤¾õ¶· + ¤Ë¤âÂбþ¡¥ + + * eval.c (thread_create): create¸å¡¤fn¤ò¸Æ¤Ó½Ð¤¹Á°¤Ëcontext switch + ¤¬µ¯¤¤ë¤È°ã¤¦context¤Çfn¤¬¼Â¹Ô¤µ¤ì¤Æ¤·¤Þ¤¦¥Ð¥°¡¥ + +Mon Jun 3 08:03:17 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * struct.c (struct_s_def): ¥á¥ó¥Ð¤Î»ØÄê¤òʸ»úÎ󡤥·¥ó¥Ü¥ë(FIXNUM) + ÁÐÊý¤Ç²Äǽ¤Ë¤·¤¿¡¥ + + * ext/etc/etc.c (Init_etc): ¹½Â¤ÂÎ¥ª¥Ö¥¸¥§¥¯¥È¤òGC¤«¤éÊݸ¤¿¡¥ + + * error.c (rb_sys_fail): nil/FALSE¤ò°ú¿ô¤È¤·¤Æ¼õ¤±ÉÕ¤±¤ë¤è¤¦¤Ë¡¥ + +Thu May 30 16:19:08 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (thread_select): EINTR¤ËÂбþ¡¥ + +Wed May 29 11:04:51 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (f_catch): catch/throw¤ò¼ÂÁõ¤·¤¿¡¥ + +Tue May 28 13:30:52 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99-960528 + + * eval.c (thread_cleanup): main thread¤¬½ªÎ»¤¹¤ë¤È¾¤Îthread¤â½ªÎ» + ¤¹¤ë¤³¤È¤ÎÌÀ³Î²½¡¥ + + * signal.c (trap): SIGINT¤Î¥Ç¥Õ¥©¥ë¥È¤ÎÀßÄê¥ß¥¹(ËÜÅö¤ËSIG_DFL¤Ç¤Ï + ¤Þ¤º¤«¤Ã¤¿)¡¥ruby¤Ç¤Ï¤Á¤ã¤ó¤È¥Ï¥ó¥É¥ë¤·¤Ê¤¤¤È¡¥ + + * eval.c (thread_interrupt): SIGINT¤Ïmain_thread¤ËÎã³°¤òȯÀ¸¤µ¤»¤ë + ¤è¤¦¤Ë¡¥ + +Mon May 27 15:13:31 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (thread_status): thread¤Î¾õÂÖ¤òÊÖ¤¹¥á¥½¥Ã¥É¡¥thread¤Î½ªÎ» + ¤òÂÔ¤¿¤Ê¤¤¡¥ + + * eval.c (thread_value): °ì¼ï¤Îpromise¤ò¼ÂÁõ¤¹¤ë¤¿¤á¤Î¥á¥½¥Ã¥É¡¥ + + * eval.c (thread_join): ÂԤäƤ¤¤ëthread¤¬Îã³°¤òµ¯¤³¤·¤¿»þ¤Ë¤Ï¡¤ + join¤¬¤½¤ÎÎã³°¤òȯÀ¸¤¹¤ë¤è¤¦¤Ë¡¥ + + * eval.c (thread_create): thread¤Ç¤ÎÎã³°¤òpropagate¤·¤Ê¤¤¤è¤¦¤Ë¡¥ + +Fri May 24 10:47:53 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * enum.c (Init_Enumerable): `size' as alias to the `length' + + * eval.c (thread_save_context): `$@', `$!'¤ò¥¹¥ì¥Ã¥ÉËè¤Ë¥»¡¼¥Ö¡¥ + + * eval.c (superclass): ¥¨¥é¡¼É½¼¨¤ò¤è¤ê¿ÆÀڤˡ¥ + +Thu May 23 10:38:41 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.99-960523 + + * eval.c (superclass): ¥¨¥é¡¼»þ¤Ë¥¹¡¼¥Ñ¡¼¥¯¥é¥¹Ì¾¤ò(ʬ¤«¤ì¤Ð)ɽ¼¨ + ¤¹¤ë¤è¤¦¤Ë¡¥ + +Wed May 22 19:48:42 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (superclass): ¥¹¡¼¥Ñ¡¼¥¯¥é¥¹¤Î»ØÄê»Ò¤ò`:'¤«¤é`<'¤ËÊѹ¹¡¥ + +Tue May 21 09:27:59 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * lib/thread.rb: thread¤ò¥µ¥Ý¡¼¥È¤¹¤ë¥¯¥é¥¹(Mutex, Queue)¡¥ + +Mon May 20 09:39:49 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * time.c (time_cmp): ÉâÆ°¾®¿ôÅÀ¿ô¤â°·¤¨¤ë¤è¤¦¤Ë¡¥ + (time_minus): Time - Time¤¬ÉâÆ°¾®¿ôÅÀ¿ô¤òÊÖ¤¹¤è¤¦¤Ë¡¥ + +Fri May 17 15:40:10 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * process.c (rb_proc_exec): ThreadÂбþ»þ¤Ëexec¤ÎľÁ°¤Ë + ITIMER_VIRTUAL¤ò¥ê¥»¥Ã¥È¤¹¤ë¡¥ + +Tue May 14 02:12:44 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * signal.c (sighandle): SIGINT¤ËÂФ·¤Æ¥Ç¥Õ¥©¥ë¥È¤ÇÎã³°¤òȯÀ¸¤µ¤»¤ë + ¤Î¤ò¤ä¤á¡¤status 130¤Çexit¤¹¤ë¤è¤¦¤Ë¤·¤¿¡¥ + + * eval.c (thread_schedule): Thread¤Î¥Ð¥°¤Ï¤Û¤È¤ó¤É¤È¤ì¤¿¤è¤¦¤À¡¥ + +Fri May 10 11:21:08 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (thread_schedule): ¥æ¡¼¥¶¥ì¥Ù¥ëThreadµ¡Ç½¡¥¸úΨ¤Ï¤È¤â¤«¤¯ + °Ü¿¢À¤Ï¤¢¤ë¡¥º£¸å¡¤thread´Ö¤ÎÄÌ¿®µ¡Ç½¤ò¼ÂÁõ¤¹¤ëͽÄê¡¥ + +Thu May 2 21:22:31 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * time.c (time_timeval): struct timeval¤òľÀÜÊÖ¤¹¤è¤¦¤Ë(staticÊÑ¿ô + ¤ò»È¤ï¤Ê¤¤)¡¥ + +Wed May 1 17:27:32 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * process.c (f_sleep): À°¿ô°Ê³°¤Îtime¤ò»ØÄê¤Ç¤¤ë¤è¤¦¤Ë¡¥ + +Thu Apr 25 08:19:15 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * file.c (file_s_dirname): ¥Õ¥¡¥¤¥ë̾¤¬"/"¤ò´Þ¤Þ¤Ê¤¤»þ¡¤"."¤òÊÖ¤¹ + ¤è¤¦¤Ë(GNU dirname¤Î»ÅÍÍ)¡¥ + + * file.c (file_s_basename): ¤Þ¤Ànil¤È0¤òº®Æ±¤·¤Æ¤¤¤ë¥½¡¼¥¹¤¬»Ä¤Ã¤Æ + ¤¤¤¿¡¥ + + * parse.y (exprs): ¥¨¥é¡¼¥ê¥«¥Ð¥ê¤òÄɲᥠ+ +Wed Apr 24 15:51:05 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * string.c (str_chop_bang): CRLF¤Î¾ì¹ç2 bytes¤òchop!¤¹¤ë¤è¤¦¤Ë¡¥ + + * ext/socket/socket.c (tcp_svr_s_open): ¤Þ¤Ànil¤È0¤òº®Æ±¤·¤Æ¤¤¤ë¥½¡¼ + ¥¹¤¬»Ä¤Ã¤Æ¤¤¤¿¡¥ + +Tue Apr 23 18:14:25 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * pack.c (pack_pack): "A/a"¤Î¥Ð¥°¡¥Í¾·×¤Êpadding¤¬Æþ¤Ã¤Æ¤¤¤¿¡¥ + +Thu Apr 18 13:02:11 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * configure.in: ¥¢¡¼¥¥Æ¥¯¥Á¥ã°Í¸Éô¤òÊ̥ǥ£¥ì¥¯¥È¥ê¤Ë¥¤¥ó¥¹¥È¡¼¥ë + ¤¹¤ë¤è¤¦¤Ë¡¥ + + * parse.y (yyerror): ¥¨¥é¡¼È¯À¸»þ¤Ë¥¨¥é¡¼¹Ô¤È¤½¤Î°ÌÃÖ¤òɽ¼¨¤¹¤ë¤è + ¤¦¤Ë¡¥ + +Wed Apr 17 14:22:42 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * defines.h: SAFE_SIGHANDLE¤ò̵¤¯¤·¡¤´í¸±¤ÊÁªÂò¤Ï¤Ç¤¤Ê¤¤¤è¤¦¤Ë¡¥ + + * io.c (io_ungetc): ¿·µ¡Ç½¡¥ + + * ruby.c (load_file): ¥Õ¥¡¥¤¥ë¤«¤é¤ÎÆÉ¤ß¹þ¤ßÊý¼°¤¬ÊѤï¤Ã¤¿¤Î¤ËÂбþ¡¥ + + * parse.y (compile_file): ¥Õ¥¡¥¤¥ë¤«¤é¤ÎÆþÎϤò°ìÅÙÁ´ÉôÆÉ¤ß¹þ¤à¤Î¤ò + »ß¤á¤Æ¡¤gets¤ò»È¤¦¤³¤È¤Ë¤·¤¿¡¥ + +Wed Apr 10 17:40:11 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.98 + +Tue Apr 9 09:54:30 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (iter_block): ¥¤¥Æ¥ì¡¼¥¿¥Ö¥í¥Ã¥¯¤Î»ØÄê¤ò¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤· + ¤Ë¸ÂÄꡥʸˡ¤ÎÌÀ³Î²½¡¥ + + * eval.c (rb_eval): ¾ò·ï¼°¤ÎÀµµ¬É½¸½¤ÎÈæ³Ó¤òinline²½¡¥ + + * eval.c (rb_eval): defined? ¤Î ÄêµÁ¾ðÊó(¼ïÊÌ)¤òʸ»úÎó¤ÇÊÖ¤¹¡¥ + + * node.h: NODE_BEGIN -> NODE_RESCUE, NODE_ENSURE¤ËʬΥ¡¥ + + * eval.c (rb_eval): option -n/-p¤Î¥È¥Ã¥×¥ì¥Ù¥ë¥ë¡¼¥×¤ÎinlineŸ³«¡¥ + + * parse.y (cond0): ¾ò·ï¼°Ãæ¤Îʸ»úÎó¤ÏÈæ³Ó¤ÎÂоݤȤ·¤Ê¤¤ + +Wed Mar 27 12:33:54 1996 Tairo Nomura <tairo@hucom.tp.titech.ac.jp> + + * defines.h: NeXTÂбþ + +Wed Mar 27 10:02:44 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y: ͽÌó¸ì¤ÎÊѹ¹ continue -> next + +Mon Mar 25 07:34:37 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (parse_regx): o(once)¥ª¥×¥·¥ç¥ó¤òÄɲᥠ+ +Fri Mar 22 14:25:35 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.97d + + * eval.c (dyna_var_defined): ưŪ¥í¡¼¥«¥ëÊÑ¿ô¤ÎÄêµÁ¥Á¥§¥Ã¥¯Íѥ롼 + ¥Á¥ó¡¥ + + * parse.y (gettable): eval()¤ÎÃæ¤Ç¤ÎưŪ¥í¡¼¥«¥ëÊÑ¿ô(´û¤ËÃͤò»ý¤Ã + ¤Æ¤¤¤ë¤â¤Î)¤Î¸¡½Ð¤Ë¼ºÇÔ¤·¤Æ¤¤¤¿¡¥ + +Tue Mar 19 10:46:47 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.97c + + * re.c (reg_s_new): compile»þ¤Ësegmentation fault¡¥ + + * parse.y (str_extend): ¤¤¤Ä¤âeval¤¹¤ë¤è¤¦¤Ë¡¥ + +Wed Mar 13 11:00:42 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (str_extend): ʸ»úÎóÃæ¤Î¼°Å¸³«¤ÎÉÔÈ÷¤ò̵¤¯¤·¤¿¡¥ + + * parse.y: ²¼¼ê¤Ê¥¨¥é¡¼¥ê¥«¥Ð¥ê¤ò³°¤·¤¿¡¥ + +Tue Mar 12 12:30:20 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (rescue): ´Ö°ã¤Ã¤Æensure¤Ç¤âÎã³°¤òÊ᪤·¤Æ¤¤¤¿¡¥ + +Wed Mar 6 12:11:03 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * parse.y (var_extend): ÊÑ¿ôŸ³«"#{}"¤Ç¡¤Ç¤°Õ¤Î¼°¤ò½ñ¤±¤ë¤è¤¦¤Ë¤· + ¤¿¡¤¤³¤ì¤Ç¡ÖÊÑ¿ô¡×Ÿ³«¤Ç¤Ï̵¤¯¤Ê¤Ã¤Á¤ã¤Ã¤¿¤Ê¤¢¡¥ + + * regex.c (init_syntax_once): `_'¤òword¤ËÄɲᥠ+ + * regex.c (re_compile_pattern): `\w',`\W'¤ÎȽÄê¤òsyntax table¤ò»È + ¤¦¤è¤¦¤Ë¡¥ + +Tue Feb 27 10:15:32 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * object.c (obj_inspect): ɽ¼¨¤¹¤ë¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤¬Ìµ¤¤»þ¤Ë¤Ï¡¤ + to_s¤ò»È¤¦¡¥ + + * configure.in: dln¤Î¸¡½Ð¤ò¼«Æ°Åª¤Ë¡¥ + +Mon Feb 26 19:55:33 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ruby.c (readin): read(2)¤Ç°ìÅ٤˥ե¡¥¤¥ë¤¬ÆÉ¤ß¹þ¤á¤Ê¤¤¾ì¹ç¤ËÂбþ¡¥ + +Sat Feb 24 14:47:18 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.97b + +Fri Feb 23 11:26:02 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * class.c (rb_define_module): C¸À¸ì¤ÇÄêµÁ¤µ¤ì¤¿¥â¥¸¥å¡¼¥ë¤ÎPATH¤Î + ÀßÄê˺¤ì¡¥Ê¸»úÎ󲽤Çcore dump¡¥ + + * eval.c (mod_include): Ìá¤êÃͤònil¤Ë¡¥ + + * version 0.97a + +Thu Feb 22 21:03:42 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * array.c (ary_times): ¡ÖÇÛÎó*ʸ»úÎó¡×¤¬join¤ÈƱ¤¸Æ¯¤¤ò¤¹¤ë¤è¤¦¤Ë¡¥ + +Wed Feb 21 11:18:09 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * configure.in : fileCount¤òcache¡¥ + + * configure.in : Linux¤ÇELF´Ä¶¤ò¼«Æ°Åª¤Ë¸¡½Ð¤Ç¤¤ë¤è¤¦¡¥ + +Tue Feb 20 11:18:09 1996 Mitsuhide Satou <mit-sato@aries.bekkoame.or.jp> + + * FreeBSD dynamic linkÂбþ¡¥ + +Fri Feb 16 08:50:01 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * object.c (obj_inspect): ¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤ò»ý¤¿¤Ê¤¤¥ª¥Ö¥¸¥§¥¯¥È¤â + Àµ¤·¤¯É½¼¨¤µ¤ì¤ë¤è¤¦¤Ë¡¥ + +Wed Feb 14 16:56:44 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (rb_eval): ¾ò·ï¼°¤Î`2..2'¤Ê¤Éº¸ÊÕÀ®Î©Ä¾¸å¤Ë±¦ÊÕ¤¬À®Î©¤¹¤ë + ¥Ñ¥¿¡¼¥ó¤Ë¥Ð¥°¡¥ + +Tue Feb 13 18:22:22 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.97 + +Fri Feb 9 21:32:55 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * lib/tkscrollbox.rb: ¥¹¥¯¥í¡¼¥ë¤Çtcl¤ÎÀßÄê¤ò¹Ô¤¤¡¤ruby<->wish¤ÎÉÔ + ÍפÊÄÌ¿®¤ò̵¤¯¤·¤¿¡¥ + +Wed Feb 7 10:26:52 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * string.c (str_aref): index¤òunsigned int¤Ç¤È¤Ã¤Æ¤¤¤¿¡¥ + + * string.c (str_aref): Èϰϳ°¤Îindex¤ËÂФ·¤Ænil¤òÊÖ¤¹¡¥ + + * parse.y (special_local_set): `$_'¤¬Àë¸À̵¤·¤Ë»È¤ï¤ì¤¿¾ì¹ç¤ËÂбþ¡¥ + ´Ø¿ô¤òvariable.c¤«¤é°Üư¡¥ + + * string.c (str_sub): ÃÖ´¹³«»Ï°ÌÃÖ¤¬´Ö°ã¤Ã¤Æ¤¤¤¿¡¥ + +Tue Feb 6 16:17:31 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * sample/ruby-mode.el (ruby-parse-region): ¥³¥á¥ó¥È¤ÎÆÉ¤ßÈô¤Ð¤·¤Î + ¥Ð¥°¡¥ + +Fri Feb 2 18:35:28 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * variable.c (lastline_get): `$_'¤ò`$~'¤ÈƱ¤¸¤è¤¦¤ËSCOPE¥í¡¼¥«¥ë¤Ê + ÊÑ¿ô¤Ë¤·¤¿¡¥ + +Thu Feb 1 14:14:07 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * file.c: stat¤Îcache¤ò¤ä¤á¤¿¡¥ + +Wed Jan 31 07:13:08 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (proc_s_new): proc¤ÎÃæ¤Çyield¤ò¸Æ¤Ð¤ì¤¿»þ¤Ëcore dump¤·¤Æ + ¤¤¤¿¡¥¤È¤ê¤¢¤¨¤ºÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥ + + * variable.c (rb_class2path): singleton class¤ËÂбþ¡¥ + + * ext/etc/etc.c (Init_etc): struct_define¤Î¥¿¡¼¥ß¥Í¡¼¥¿¤¬nil¤À¤Ã¤¿ + (0¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤)¡¥ + + * ext/marshal/marshal.c: TRUE/FALSE¤òÅǤ½Ð¤»¤ë¤è¤¦¤Ë¡¥ + + * eval.c (rb_get_method_body): ¥¥ã¥Ã¥·¥å¤ÎaliasÂбþ¡¤¤¤¤Þ¤Þ¤Ç¤Ï + alias¤Ï¥¥ã¥Ã¥·¥å¤ËÆþ¤Ã¤Æ¤¤¤Ê¤«¤Ã¤¿¡¥ + +Tue Jan 30 09:55:13 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (rb_eval): NODE_BLOCK - tail recursive(¤È¤¤¤¦¤Û¤É¤Ç¤â¤Ê¤¤ + ¤¬)¡¥ + + * io.c (io_pipe): pipe(2)¤ò¼ÂÁõ¤·¤¿¡¥ + + * eval.c (rb_eval): Qself¤ò¤Ê¤¯¤·¤¿¡¥threadÂбþ¤Ø¤ÎÂè°ìÊâ¡¥Àè¤Ï±ó + ¤¤¤¬¡Ä¡¥ + + * eval.c (proc_call): proc¤ÎÃæ¤Ç¤Îreturn¤Ïproc¤Î½ªÎ»¤ò°ÕÌ£¤¹¤ë¤è¤¦ + ¤Ë¡¥¤¿¤À¤·¡¤proc¤«¤é¤Îyield¤ÎÃæ¤Ç¤Îreturn¤ÏÎã³°¤òȯÀ¸¤¹¤ë¡¥ + +Wed Jan 24 11:33:48 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.96a + + * dir.c (dir_each): `$_'¤ÎÃͤòÊѹ¹¤¹¤ë¤Î¤ò¤ä¤á¤¿¡¥ + + * io.c (f_readlines): nil¤ÈFALSE¤ÎʬΥ¤Î¤¢¤ª¤ê¤Ç̵¸Â¥ë¡¼¥×¤ËÍî¤Á¤Æ + ¤¤¤¿¡¥ + + * ruby.c (ruby_options): $0¤ÎÀßÄê¥ß¥¹¡¥ + +Tue Jan 23 15:28:21 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (rb_eval): ``¤Ïʸ»úÎó¤ò°ú¿ô¤È¤¹¤ë¥á¥½¥Ã¥É(`)¸Æ¤Ó½Ð¤·¤Î¥· + ¥ó¥¿¥Ã¥¯¥¹¥·¥å¥¬¡¼¤Ç¤¢¤ë¤È¤·¤¿¡¥ + + * ruby.c (addpath): `-I'¥ª¥×¥·¥ç¥ó¤Ç¥Ç¥£¥ì¥¯¥È¥ê¤¬¡ÖÁ°¤Ë¡×Äɲ䵤ì + ¤ë¤è¤¦¤ËÊѹ¹¡¥ + +Fri Jan 19 11:23:12 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * dln.c (load_1): N_INDRÂбþ(½ÐÍ褿¤è¤¦¤Êµ¤¤¬¤¹¤ë)¡¥ + +Thu Jan 18 18:14:20 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * ruby.texi: FALSE¤Ènil¤ÎʬΥ¤òÈ¿±Ç¤·¤¿¡¥ + +Tue Jan 16 17:39:23 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.96 - ¤È¤ê¤¢¤¨¤ºnil¤ÈFALSE¤ò¶èÊ̤¹¤ëÈÇ + +Wed Jan 10 15:31:48 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * re.c (reg_match): ¥Þ¥Ã¥Á¤·¤Ê¤«¤Ã¤¿»þ¤ÎÌá¤êÃͤÏFALSE¡¥ + + * object.c (rb_equal): `0 == nil'¤¬TRUE¤Ë¤Ê¤ë¥Ð¥°¡¥ + +Tue Jan 9 00:44:58 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * nil¤ÈFALSE¤¬Ê¬Î¥²Äǽ¤ËÊѹ¹¡¥ + + * nil¤ÈFALSE¤È0¤Î¶èÊ̤ò¸·Ì©¤Ë¡¥ + + * struct.c (struct_new): °ú¿ô¤ò0¤Ç½ª¤ëɬÍפ¬Ìµ¤¯¤Ê¤Ã¤¿¡¥ + + * object.c (inspect_i): ¥ª¥Ö¥¸¥§¥¯¥È¤Î¥Á¥§¥Ã¥¯¤Î¥Ð¥°(Fixnum¤Çcore + dump¤·¤Æ¤¤¤¿)¡¥ + + * range.c (range_to_s): Range¤Îɽ¼¨¤ò²þÁ±¡¥ + + * object.c (true_inspect): TRUE¤Îɽ¼¨¤ò`TRUE'¤Ë¡¥ + +Mon Jan 8 15:02:33 1996 Yukihiro Matsumoto <matz@caelum.co.jp> + + * numeric.c (fix_mul): divide by zero error¤¬È¯À¸¤·¤¿(¥ª¡¼¥Ð¡¼¥Õ¥í¡¼ + ¸¡½Ð¤Î¥Ð¥°) + + * texinfo.tex¤ò¥Ñ¥Ã¥±¡¼¥¸¤Ë´Þ¤á¤¿¡¥ + +Sun Dec 31 00:08:49 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (rb_eval): `::'¤Ç¤Ï¡¤¤½¤Î¥¯¥é¥¹¤ÇÄêµÁ¤µ¤ì¤¿Äê¿ô¤ò»²¾È¤¹¤ë + ¤è¤¦¤ËÊѹ¹¡¥ + + * string.c (Init_String): each¤òeach_line¤ËÌᤷ¤¿¡¥ + +Thu Dec 28 12:31:55 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * eval.c (rb_eval): case¤Î±é»»»Ò¤ò`=~'¤«¤é`==='¤Ë¡¥ + + * variable.c (rb_const_set): ¥¯¥é¥¹Äê¿ô¤ÎºÆÄêµÁ¤òµö¤¹(Ʊ¤¸¥¯¥é¥¹¤Ç + ¤ÏÉÔ²Ä)¡¥·Ù¹ð¤Ï½Ð¤¹¡¥ + +Wed Dec 27 13:27:52 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.95c + + * ext/tkutil/tkutil.c: wish¤¬¤¢¤Ã¤Æ¤â¤Ê¤¯¤Æ¤â°ì±þ¥³¥ó¥Ñ¥¤¥ë¤À¤±¤Ï + ¤¹¤ë¤è¤¦¤Ë¡¥ + + * lib/tk.rb: ´Ä¶ÊÑ¿ôPATH¤«¤é{wish|wish4.0}¤òõ¤¹¤è¤¦¤Ë¡¥ + +Tue Dec 26 01:03:42 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * sample/ruby-mode.el (ruby-parse-region): Àµµ¬É½¸½¤Î¸¡½Ð¶¯²½¡¥ + + * numeric.c (fix_mul): ¾è»»¤Î¥ª¡¼¥Ð¡¼¥Õ¥í¡¼¸¡½Ð¥¢¥ë¥´¥ê¥º¥à¤Î¥Ð¥°¡¥ + + * ext/extmk.rb.in: ./install-sh¤ò»È¤¦¾ì¹ç¤ÎPATH¤òÄ´À°¡¥ + + * Makefile.in (install): lib/*.rb¤ò°ì¤Ä¤º¤Ä¥¤¥ó¥¹¥È¡¼¥ë¡¥ + + * io.c (io_each_line): ¥¤¥Æ¥ì¡¼¥¿¤ÎÌá¤êÃͤònil¤ÇÅý°ì¡¥ + +Fri Dec 22 10:34:32 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + + * version 0.95b + + * variable.c (f_untrace_var): Âè2°ú¿ô¤ò»ØÄꤹ¤ë¤ÈÆÃÄê¤Îtrace¤òºï½ü + ¤Ç¤¤ë¤è¤¦¤Ë¡¥ + + * variable.c (f_trace_var): Âè2°ú¿ô¤¬nil¤Î»þ¡¤trace¤òºï½ü¤¹¤ë¡¥ + + * lib/tk.rb (file_readable/file_writable): Âè2°ú¿ô¤ònil¤Ë¤¹¤ë¤³¤È + ¤Ë¤è¤ëevent handler¤Îºï½ü¡¥ + + * parse.y (variable): ¥É¥¥å¥á¥ó¥È¤Ë`__FILE__'¤È`__LINE__'¤¬»Ä¤Ã¤Æ + ¤¤¤¿¡¥`caller(0)'¤ÇÂåÍѤ·¤¿¤Ï¤º¤À¤Ã¤¿¤Î¤Ë¡¥ + + * eval.c (f_eval): $!¤Î¥ê¥»¥Ã¥È¡¥ + + * error.c (err_sprintf): ¾¡¼ê¤Ë"\n"¤òÉղ乤ë¤Î¤ò»ß¤á¤¿¡¥ + + * parse.y (f_arglist): °ú¿ô¥ê¥¹¥Èľ¸å¤Îif/while¤ÎÆÉ¤ß´Ö°ã¤¤¡¥ + lex_state¤ÎÃͤ¬ÀßÄꤵ¤ì¤Æ¤¤¤Ê¤«¤Ã¤¿¡¥ + Thu Dec 21 00:56:57 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + * version 0.95a - ^^;;; + + * lib/tkscrollbox.rb: ¥Ñ¥Ã¥±¡¼¥¸¤ËÆþ¤Ã¤Æ¤Ê¤«¤Ã¤¿¡¥ + + * configure.in: FILE structure¤Î¥Á¥§¥Ã¥¯¤Ë¥Ð¥°¡¥ + + * Makefile.in (clean): ext°Ê²¼¤òinstall¤·¤Æ¤¤¤¿¡¥ + + * ext/socket/extconf.rb: Solaris¤Ë¤ª¤±¤ë-lnls¤Î¥Á¥§¥Ã¥¯¡¥ + + * array.c (beg_len): ¥Ð¥°¤¬¤¢¤Ã¤¿¡Ä¡¥Èᤷ¤¤¡¥ + * version 0.95 - fj.sources¤Ë * eval.c (rb_eval): rescue¤Î¥í¥¸¥Ã¥¯¤òrb_rescue()¤Ë°ì¸µ²½¡¥ @@ -204,8 +1970,8 @@ Fri Oct 13 13:19:19 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * string.c (str_strip_bang): ʸ»úÎó¤Î¸å¤í¤ÎŤµ¤ÎÄ´À°¤¬¹Ô¤ï¤ì¤Æ¤¤ ¤Ê¤«¤Ã¤¿¡¥ - * re.c (reg_search): $&, $1...¤Î¤Ï¥í¡¼¥«¥ë¤Ë«Çû¤¹¤ë¤è¤¦¤Ë¤Ê¤Ã¤¿¡¥ - ¸Æ¤Ó½Ð¤·¤¿¥á¥½¥Ã¥É¤Ç¤Î¥Þ¥Ã¥Á¤Ï¸½¥¹¥³¡¼¥×¤Î$&¤Ê¤É¤ÎÃͤ˱ƶÁ¤·¤Ê¤¤¡¥ + * re.c (reg_search): $&, $1...¤Ï¥í¡¼¥«¥ë¤Ë«Çû¤¹¤ë¤è¤¦¤Ë¤Ê¤Ã¤¿¡¥¸Æ + ¤Ó½Ð¤·¤¿¥á¥½¥Ã¥É¤Ç¤Î¥Þ¥Ã¥Á¤Ï¸½¥¹¥³¡¼¥×¤Î$&¤Ê¤É¤ÎÃͤ˱ƶÁ¤·¤Ê¤¤¡¥ ¥Þ¥Ã¥Á¤Î¾ðÊó¤ò¥¹¥³¡¼¥×³°¤ÇÆÀ¤¿¤¤¤È¤¤Ë¤Ï$~¤ò»È¤Ã¤ÆÂ«Çû¾ðÊó¤ò»ý¤Á ½Ð¤¹É¬Íפ¬¤¢¤ë¡¥ @@ -352,7 +2118,7 @@ Thu Sep 14 18:00:59 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * object.c (obj_is_instance_of): is_member_of¤«¤é̾¾ÎÊѹ¹¡¥ -Wed Sep 13 15:44:35 1995 Yukihiro Matsumoto <matz@caelum.co.jp> + Wed Sep 13 15:44:35 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * string.c (Fstr_tr_bang): Èϰϳ°¤Îʸ»ú¤ËÂФ¹¤ëÊÑ´¹¥Ð¥°¡¥ @@ -441,7 +2207,7 @@ Fri Aug 11 14:37:03 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * io.c: ¥Þ¥¯¥íREAD_DATA_PENDING¤ÎÄêµÁ¤òÊѹ¹(LinuxÂбþ) - * io.c (io_fptr_finalize): ftpr¤Î³«Êü»þ¤Î½èÍý¤ò»ØÄê¤Ç¤¤ë¤è¤¦¤Ë¡¥ + * io.c (io_fptr_finalize): fptr¤Î³«Êü»þ¤Î½èÍý¤ò»ØÄê¤Ç¤¤ë¤è¤¦¤Ë¡¥ Wed Aug 9 16:52:41 1995 Yukihiro Matsumoto <matz@caelum.co.jp> @@ -722,8 +2488,8 @@ Thu May 18 12:27:23 1995 Yukihiro Matsumoto <matz@ix-02> ¤¤ÌäÂê¤â¤¢¤Ã¤¿¡¥·ë²Ì¤È¤·¤Ætr¤ò½ñ¤´¹¤¨¤¿¤Î¤Ç¡¤copyright¤ÎÌäÂê¤Ï ̵¤¯¤Ê¤Ã¤¿(¤È»×¤¦)¡¥ - * gc.c (gc): the_scope¤ò¥Þ¡¼¥¯¤·¤Æ¤¤¤Ê¤«¤Ã¤¿¤Î¤Ç¡¤¥í¡¼¥«¥ëÊÑ¿ô¤¬´Ö - °ã¤Ã¤Æ³«Êü¤µ¤ì¤ë¾ì¹ç¤¬¤¢¤Ã¤¿¡¥ + * gc.c (gc): the_scope¤ò¥Þ¡¼¥¯¤·¤Æ¤¤¤Ê¤«¤Ã¤¿¤Î¤Ç¡¤¥í¡¼¥«¥ëÊÑ¿ô¤Î»Ø + ¤·¤Æ¤¤¤ë¥ª¥Ö¥¸¥§¥¯¥È¤¬´Ö°ã¤Ã¤Æ³«Êü¤µ¤ì¤ë¾ì¹ç¤¬¤¢¤Ã¤¿¡¥ * gc.c (mark_locations_array): ¼ã´³¤Î¹â®²½¡¥ @@ -789,8 +2555,8 @@ Thu Apr 20 12:31:24 1995 Yukihiro Matsumoto (matz@ix-02) * env.h, gc.c, regex.c: IRIX¤Ø¤Î°Ü¿¢Âбþ - * configure: pic¤òÀ¸À®¤¹¤ëoption¤Î¸¡½Ð¤Î¤¿¤á¡¤¥·¥¹¥Æ¥à¥¿¥¤¥×¤ò¥Á¥§¥Ã - ¥¯¤¹¤ë¤è¤¦¤Ë¡¥ + * configure: dlopenÍѤËpic¤òÀ¸À®¤¹¤ëoption¤Î¸¡½Ð¤Î¤¿¤á¡¤¥·¥¹¥Æ¥à¥¿ + ¥¤¥×¤ò¥Á¥§¥Ã¥¯¤¹¤ë¤è¤¦¤Ë¡¥ Tue Apr 18 19:08:17 1995 Yukihiro Matsumoto (matz@ix-02) @@ -808,7 +2574,7 @@ Mon Apr 10 18:36:06 1995 Yukihiro Matsumoto (matz@ix-02) Fri Apr 7 13:51:08 1995 Yukihiro Matsumoto (matz@ix-02) * cons.c->assoc.c: cons¤Î;·×¤Êµ¡Ç½¤Ï³°¤·¤Æpair¤È¤·¤Æ¤Îµ¡Ç½¤À¤±¤ò - »Ä¤·¤¿¡¥enumerable¤òinclude¤¹¤ë¤Î¤â¤ä¤á¤¿¡¥ + »Ä¤·¤¿¡¥Enumerable¤òinclude¤¹¤ë¤Î¤â¤ä¤á¤¿¡¥ * string.c(esub): ʸ»úÎóÃÖ´¹¥¤¥Æ¥ì¡¼¥¿¡¥perl¤Îs///e¤ÎÁêÅö¤¹¤ë¡¥ @@ -885,8 +2651,8 @@ Fri Mar 10 18:35:46 1995 Yukihiro Matsumoto (matz@ix-02) * eval.c: Math¤Î¤è¤¦¤Ê¥â¥¸¥å¡¼¥ë¤Ï¼«Ê¬¼«¿È¤Çextend¤¹¤ë¡¥ - * eval.c: ¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤·¤¿´û¤ËƱ̾¤Î¤â¤Î¤¬¤¢¤ì¤ÐÄɲÃÄê - µÁ¤È¤Ê¤ë¤è¤¦¤Ë¡¥¤¿¤À¤·¡¥super¥¯¥é¥¹¤Î°ã¤¤¤Ê¤É¤Ï¥Á¥§¥Ã¥¯¤¹¤ë¡¥ + * eval.c: ¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë»þ¡¤´û¤ËƱ̾¤Î¤â¤Î¤¬¤¢¤ì¤ÐÄÉ + ²ÃÄêµÁ¤È¤Ê¤ë¤è¤¦¤Ë¡¥¤¿¤À¤·¡¥super¥¯¥é¥¹¤Î°ã¤¤¤Ê¤É¤Ï¥Á¥§¥Ã¥¯¤¹¤ë¡¥ * regex.c: debug. @@ -933,8 +2699,8 @@ Thu Feb 23 11:19:19 1995 Yukihiro Matsumoto (matz@ix-02) * eval.c(rb_clear_cache): ¥¥ã¥Ã¥·¥å¤Î¥¯¥ê¥¢¤·Ëº¤ì¤¬¤¢¤Ã¤¿¡¥ * eval.c: Äê¿ô¤Î¥¹¥³¡¼¥×¤ò¥¯¥é¥¹Æâ¤ÎÀÅŪ¥¹¥³¡¼¥×¤ËÊѹ¹¤·¤¿¡¥¤³¤ì¤Ë - ¤è¤Ã¤Æ¡¤ÆÃ°Û¥á¥½¥Ã¥É¤«¤é¤Ï»²¾È¤µ¤ì¤ëÄê¿ô¤Ï¡¤¥ì¥·¡¼¥Ð¤Î¥¯¥é¥¹¤Ç¤Ï - ¤Ê¤¯¡¤ÄêµÁ¤µ¤ì¤¿¥¹¥³¡¼¥×¤Î¥¯¥é¥¹¤ÎÄê¿ô¤È¤Ê¤ë¡¥ + ¤è¤Ã¤Æ¡¤ÆÃ°Û¥á¥½¥Ã¥É¤«¤é»²¾È¤µ¤ì¤ëÄê¿ô¤Ï¡¤¥ì¥·¡¼¥Ð¤Î¥¯¥é¥¹¤Ç¤Ï¤Ê + ¤¯¡¤ÄêµÁ¤µ¤ì¤¿¥¹¥³¡¼¥×¤Î¥¯¥é¥¹¤ÎÄê¿ô¤È¤Ê¤ë¡¥ Wed Feb 22 00:51:38 1995 Yukihiro Matsumoto (matz@dyna) @@ -985,8 +2751,9 @@ Fri Feb 10 16:30:00 1995 Yukihiro Matsumoto (matz@ix-02) * ruby.c(load_file): script¤òÆÉ¤ß¹þ¤à»þ¤À¤±"#!"¤Î²òÀϤò¹Ô¤¦¤è¤¦¤Ë¡¥ - * ruby.c(readin): ¥Õ¥¡¥¤¥ëÆÉ¤ß¹þ¤ß»þ¤ËÀèÆ¬¤Ë"#!"¤¬¤¢¤ê¡¤ruby¤Ë°ú¿ô - ¤¬Í¿¤¨¤é¤ì¤Æ¤¤¤ì¤Ð¡¤¤½¤Î°ú¿ô¤â͸ú¤Ë¤Ê¤ë¡¥ + * ruby.c(readin): ¥Õ¥¡¥¤¥ëÆÉ¤ß¹þ¤ß»þ¤ËÀèÆ¬¤Ë"#!"¤¬¤¢¤ê¡¤¤½¤Î¹Ô¤¬ + "ruby"¤È¤¤¤¦Ê¸»úÎó¤ò´Þ¤à»þ¡¤ruby¤Ë°ú¿ô¤¬Í¿¤¨¤é¤ì¤Æ¤¤¤ì¤Ð¡¤¤½¤Î°ú + ¿ô¤â͸ú¤Ë¤Ê¤ë¡¥ * parse.y(yylex): ¥³¥á¥ó¥È¹Ô¤Î½ª¤ê¤¬`\'¤Ç¤¢¤Ã¤¿»þ¡¤¼¡¤Î¹Ô¤Ë·Ñ³¤· ¤Æ¤¤¤ë¤È¤ß¤Ê¤¹¤è¤¦¤Ë¤·¤¿¡¥ @@ -1056,7 +2823,7 @@ Tue Jan 17 11:11:27 1995 Yukihiro Matsumoto (matz@ix-02) À¤ò·Ñ¾µ¤¹¤ë¡¥ºÇ½é¤ÎÄêµÁ¤Î»þ¤Ïº£¤Þ¤Ç¤ÈƱ¤¸¥Ç¥Õ¥©¥ë¥È(¥È¥Ã¥×¥ì¥Ù ¥ë¤Ç´Ø¿ôŪ¡¤¥¯¥é¥¹ÄêµÁÆâ¤ÇÄ̾ï¥á¥½¥Ã¥É)¡¥ - * object.c(Class::new): ¥ª¥Ö¥¸¥§¥¯¥È¤ÎÀ¸À®»þ¤Ë´Ø¿ôŪ¥á¥½¥Ã¥É + * object.c(Class#new): ¥ª¥Ö¥¸¥§¥¯¥È¤ÎÀ¸À®»þ¤Ë´Ø¿ôŪ¥á¥½¥Ã¥É init_object¤¬É¬¤º¸Æ¤Ð¤ì¤ë¤è¤¦¤ËÊѹ¹¡¥ * eval.c: ̤ÄêµÁ¤Î¥á¥½¥Ã¥É¤ËÂФ·¤Æunknown¥á¥½¥Ã¥É¤¬¸Æ¤Ð¤ì¤ë¤è¤¦¤Ë @@ -2,6 +2,7 @@ ChangeLog MANIFEST Makefile.in README +README.jp README.EXT ToDo array.c @@ -9,7 +10,9 @@ bignum.c class.c compar.c configure +configure.bat configure.in +config.dj config.guess config.sub defines.h @@ -47,7 +50,6 @@ regex.c regex.h ruby.c ruby.h -ruby.texi sig.h signal.c sprintf.c @@ -56,27 +58,41 @@ st.h string.c struct.c time.c +top.sed util.h util.c variable.c version.c version.h ext/Setup +ext/Setup.dj ext/extmk.rb.in lib/base64.rb +lib/cgi-lib.rb +lib/complex.rb lib/find.rb lib/getopts.rb +lib/jcode.rb lib/mailread.rb +lib/mathn.rb +lib/observer.rb lib/parsearg.rb lib/parsedate.rb +lib/rational.rb +lib/safe.rb +lib/thread.rb lib/tk.rb +lib/tkcore.rb lib/tkcanvas.rb +lib/tkclass.rb lib/tkentry.rb +lib/tkscrollbox.rb lib/tktext.rb -lib/tkclass.rb +lib/tkthcore.rb missing/alloca.c missing/crypt.c missing/dup2.c +missing/flock.c missing/memmove.c missing/mkdir.c missing/nt.c @@ -93,16 +109,16 @@ sample/cbreak.rb sample/clnt.rb sample/dbm.rb sample/dir.rb -sample/evaldef.rb +sample/eval.rb sample/export.rb sample/exyacc.rb +sample/fact.rb sample/fib.awk sample/fib.pl sample/fib.rb sample/fib.scm sample/freq.rb sample/from.rb -sample/fullpath.pl sample/fullpath.rb sample/getopts.test sample/io.rb @@ -113,12 +129,16 @@ sample/list3.rb sample/marshal.rb sample/mkproto.rb sample/mpart.rb +sample/observ.rb sample/occur.pl sample/occur.rb sample/occur2.rb +sample/philos.rb +sample/pi.rb sample/rcs.awk sample/rcs.dat sample/rcs.rb +sample/regx.rb sample/ruby-mode.el sample/sieve.rb sample/svr.rb @@ -131,6 +151,6 @@ sample/tkfrom.rb sample/tkhello.rb sample/tkline.rb sample/tktimer.rb -sample/trojan.pl sample/trojan.rb +sample/tsvr.rb sample/uumerge.rb diff --git a/Makefile.in b/Makefile.in index 81e3feca79..aa018968ff 100644 --- a/Makefile.in +++ b/Makefile.in @@ -77,30 +77,30 @@ extruby: miniruby ext/Setup @if test -z "$$UNDER_EXTMAKE_RB"; \ then echo "Compiling ext modules"; \ UNDER_EXTMAKE_RB=yes; export UNDER_EXTMAKE_RB; \ - cd ext; ../miniruby ./extmk.rb; fi + cd ext; ../miniruby ./extmk.rb @EXTSTATIC@; fi $(PROGRAM): $(OBJS) @rm -f $(PROGRAM) $(PURIFY) $(CC) $(STATIC) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM) -$(bindir)/ruby: extruby - $(INSTALL_PROGRAM) ruby $(bindir)/ruby - strip $(bindir)/ruby - -install: $(bindir)/ruby +install:; $(INSTALL_PROGRAM) ruby $(bindir)/ruby + @-@STRIP@ $(bindir)/ruby + @test -d $(libdir) || mkdir $(libdir) cd ext; ../miniruby ./extmk.rb install - $(INSTALL_DATA) lib/*.rb $(libdir) + @for rb in `grep '^lib/' MANIFEST`; do \ + $(INSTALL_DATA) $$rb $(libdir); \ + done clean:; @rm -f $(OBJS) @rm -f ext/extinit.c ext/extinit.o - cd ext; ../ruby ./extmk.rb install + cd ext; ../miniruby ./extmk.rb clean realclean: clean @rm -f Makefile ext/extmk.rb @rm -f config.cache config.h config.log config.status @rm -f core ruby miniruby *~ -test:; @-./ruby sample/test.rb > ./ruby_test 2>&1;\ +test:; @-./ruby sample/test.rb > ./ruby_test 2>&1; \ if grep '^end of test' ./ruby_test > /dev/null; then \ echo "test succeeded"; \ else \ @@ -122,6 +122,9 @@ crypt.o: missing/crypt.c dup2.o: missing/dup2.c $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/dup2.c +flock.o: missing/flock.c + $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/flock.c + memmove.o: missing/memmove.c $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/memmove.c @@ -162,22 +165,21 @@ bignum.o: bignum.c ruby.h config.h defines.h class.o: class.c ruby.h config.h defines.h node.h st.h compar.o: compar.c ruby.h config.h defines.h dir.o: dir.c ruby.h config.h defines.h -dln.o: dln.c config.h defines.h dln.h +dln.o: dln.c config.h defines.h dln.h st.h dmyext.o: dmyext.c -dummy.o: dummy.c config.h dln.c defines.h dln.h enum.o: enum.c ruby.h config.h defines.h error.o: error.c ruby.h config.h defines.h env.h eval.o: eval.c ruby.h config.h defines.h env.h node.h sig.h st.h dln.h file.o: file.c ruby.h config.h defines.h io.h sig.h fnmatch.o: fnmatch.c config.h fnmatch.h -gc.o: gc.c ruby.h config.h defines.h env.h st.h node.h re.h regex.h +gc.o: gc.c ruby.h config.h defines.h env.h sig.h st.h node.h re.h regex.h glob.o: glob.c config.h fnmatch.h hash.o: hash.c ruby.h config.h defines.h st.h inits.o: inits.c ruby.h config.h defines.h io.o: io.c ruby.h config.h defines.h io.h sig.h main.o: main.c math.o: math.c ruby.h config.h defines.h -numeric.o: numeric.c ruby.h config.h defines.h env.h +numeric.o: numeric.c ruby.h config.h defines.h object.o: object.c ruby.h config.h defines.h st.h pack.o: pack.c ruby.h config.h defines.h process.o: process.c ruby.h config.h defines.h sig.h st.h @@ -190,7 +192,7 @@ signal.o: signal.c ruby.h config.h defines.h sig.h sprintf.o: sprintf.c ruby.h config.h defines.h st.o: st.c config.h st.h string.o: string.c ruby.h config.h defines.h re.h regex.h -struct.o: struct.c ruby.h config.h defines.h env.h +struct.o: struct.c ruby.h config.h defines.h time.o: time.c ruby.h config.h defines.h util.o: util.c defines.h config.h util.h variable.o: variable.c ruby.h config.h defines.h env.h st.h @@ -1,151 +1,115 @@ -* Ruby¤È¤Ï +* What's Ruby -Ruby¤Ï¥·¥ó¥×¥ë¤«¤Ä¶¯ÎϤʥª¥Ö¥¸¥§¥¯¥È»Ø¸þ¥¹¥¯¥ê¥×¥È¸À¸ì¤Ç¤¹¡¥ -Ruby¤ÏºÇ½é¤«¤é½ã¿è¤Ê¥ª¥Ö¥¸¥§¥¯¥È»Ø¸þ¸À¸ì¤È¤·¤ÆÀ߷פµ¤ì¤Æ¤¤¤Þ -¤¹¤«¤é¡¤¥ª¥Ö¥¸¥§¥¯¥È»Ø¸þ¥×¥í¥°¥é¥ß¥ó¥°¤ò¼ê·Ú¤Ë¹Ô¤¦»ö¤¬½ÐÍè¤Þ -¤¹¡¥¤â¤Á¤í¤óÄ̾ï¤Î¼ê³¤·¿¤Î¥×¥í¥°¥é¥ß¥ó¥°¤â²Äǽ¤Ç¤¹¡¥ +Ruby is the interpreted scripting language for quick and +easy object-oriented programming. It has many features to +process text files and to do system management tasks (as in +perl). It is simple, straight-forward, and extensible. -Ruby¤Ï¥Æ¥¥¹¥È½èÍý´Ø·¸¤ÎǽÎϤʤɤËÍ¥¤ì¡¤perl¤ÈƱ¤¸¤¯¤é¤¤¶¯ÎÏ -¤Ç¤¹¡¥¤µ¤é¤Ë¥·¥ó¥×¥ë¤Êʸˡ¤È¡¤Îã³°½èÍý¤ä¥¤¥Æ¥ì¡¼¥¿¤Ê¤É¤Îµ¡¹½ -¤Ë¤è¤Ã¤Æ¡¤¤è¤êʬ¤«¤ê¤ä¤¹¤¤¥×¥í¥°¥é¥ß¥ó¥°¤¬½ÐÍè¤Þ¤¹¡¥ +* Features of ruby -* Ruby¤ÎÆÃĹ¡¥ + + Simple Syntax + + *Normal* Object-Oriented features(ex. class, method calls) + + *Advanced* Object-Oriented features(ex. Mix-in, Singleton-method) + + Operator Overloading + + Exception Handling + + Iterators and Closures + + Garbage Collection + + Dynamic Loading of Object files(on some architecture) + + Highly Portable(works on many UNIX machines) - + ¥·¥ó¥×¥ë¤Êʸˡ - + ÉáÄ̤Υª¥Ö¥¸¥§¥¯¥È»Ø¸þµ¡Ç½(¥¯¥é¥¹¡¤¥á¥½¥Ã¥É¥³¡¼¥ë¤Ê¤É) - + ÆÃ¼ì¤Ê¥ª¥Ö¥¸¥§¥¯¥È»Ø¸þµ¡Ç½(Mixin, ÆÃ°Û¥á¥½¥Ã¥É¤Ê¤É) - + ±é»»»Ò¥ª¡¼¥Ð¡¼¥í¡¼¥É - + Îã³°½èÍýµ¡Ç½ - + ¥¤¥Æ¥ì¡¼¥¿¤È¥¯¥í¡¼¥¸¥ã - + ¥¬¡¼¥Ù¡¼¥¸¥³¥ì¥¯¥¿ - + ¥À¥¤¥Ê¥ß¥Ã¥¯¥í¡¼¥Ç¥£¥ó¥° (¥¢¡¼¥¥Æ¥¯¥Á¥ã¤Ë¤è¤ë) - + °Ü¿¢À¤¬¹â¤¤¡¥Â¿¤¯¤ÎUNIX¾å¤Çư¤¯ +* How to get ruby -* Æþ¼êË¡ +** by ftp -** ftp¤Ç +The ruby distribution can be found on -°Ê²¼¤Î¾ì½ê¤Ë¤ª¤¤¤Æ¤¢¤ê¤Þ¤¹¡¥ + ftp://ftp.caelum.co.jp/pub/lang/ruby/ - ftp://ftp.kk.info.kanagawa-u.ac.jp/pub/languages/ruby/ +** by mail -** ¥á¥¤¥ë¤Ç - -°Ê²¼¤Î¥¢¥É¥ì¥¹¤Ë`send'¤È¤¤¤¦Subject¤Î¥á¥¤¥ë¤òÁ÷¤Ã¤Æ²¼¤µ¤¤¡¥ +Send the mail which subject is 'send' to the address below. ruby-archive@caelum.co.jp -ËÜʸ¤Ë¤Ï²¿¤ò½ñ¤¤¤Æ¤â¹½¤¤¤Þ¤»¤ó¡¥ÀÞ¤êÊÖ¤·¡¤ºÇ¿·ÈǤÎruby¤¬Á÷¤Ã -¤ÆÍè¤Þ¤¹¡¥ - -* ¥á¥¤¥ê¥ó¥°¥ê¥¹¥È - - Ruby¤Ë´Ø¤ï¤ëÏÃÂê¤Î¤¿¤á¤Î¥á¥¤¥ê¥ó¥°¥ê¥¹¥È¤ò²òÀ⤷¤Þ¤·¤¿¡¥¥¢ - ¥É¥ì¥¹¤Ï - - ruby-list@caelum.co.jp - - ¤Ç¤¹¡¥¤³¤Î¥¢¥É¥ì¥¹¤Ë¥á¥¤¥ë¤òÁ÷¤ì¤Ð¡¤¼«Æ°Åª¤ËÅÐÏ¿¤µ¤ì¤Þ¤¹¡¥ - -* ¥³¥ó¥Ñ¥¤¥ë¡¦¥¤¥ó¥¹¥È¡¼¥ë - -°Ê²¼¤Î¼ê½ç¤Ç¹Ô¤Ã¤Æ¤¯¤À¤µ¤¤¡¥ - - 1. configure¤ò¼Â¹Ô¤·¤ÆMakefile¤Ê¤É¤òÀ¸À®¤¹¤ë - - 2. (ɬÍפʤé¤Ð)defines.h¤òÊÔ½¸¤¹¤ë - - ¿ʬ¡¤É¬Í×̵¤¤¤È»×¤¤¤Þ¤¹¡¥ - - 3. (ɬÍפʤé¤Ð)ext/Setup¤ËÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ò - »ØÄꤹ¤ë +You will receive the uuencoded gzipped tar file of the newest ruby +distribution. - ext/Setup¤Ëµ½Ò¤·¤¿¥â¥¸¥å¡¼¥ë¤ÏÀÅŪ¤Ë¥ê¥ó¥¯¤µ¤ì¤Þ¤¹¡¥ +* How to compile and install - ¥À¥¤¥Ê¥ß¥Ã¥¯¥í¡¼¥Ç¥£¥ó¥°¤ò¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤Ê¤¤¥¢¡¼¥¥Æ¥¯ - ¥Á¥ã¤Ç¤ÏSetup¤Î1¹ÔÌܤΡÖoption nodynamic¡×¤È¤¤¤¦¹Ô¤Î¥³ - ¥á¥ó¥È¤ò³°¤¹É¬Íפ¬¤¢¤ê¤Þ¤¹¡¥¤Þ¤¿¡¤¤³¤Î¥¢¡¼¥¥Æ¥¯¥Á¥ã¤Ç - ³ÈÄ¥¥â¥¸¥å¡¼¥ë¤òÍøÍѤ¹¤ë¤¿¤á¤Ë¤Ï¡¤¤¢¤é¤«¤¸¤áÀÅŪ¤Ë¥ê¥ó - ¥¯¤·¤Æ¤ª¤¯É¬Íפ¬¤¢¤ê¤Þ¤¹¡¥ +This is what you need to do to compile and install ruby: - 4. make¤ò¼Â¹Ô¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¤¹¤ë + 1. Run ./configure, which will generate config.h and Makefile. - 5. make test¤Ç¥Æ¥¹¥È¤ò¹Ô¤¦¡¥ + 2. Edit defines.h if you need. Probably this step will not need. - ¡Ötest succeeded¡×¤Èɽ¼¨¤µ¤ì¤ì¤ÐÀ®¸ù¤Ç¤¹¡¥ + 3. Remove comment mark(#) before the module names from ext/Setup, if + you want to link modules statically. - 6. make install + If you want to link all the extension modules, remove comment + mark from the line "#option nodynamic". -¤â¤·¡¤¥³¥ó¥Ñ¥¤¥ë»þ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤¿¾ì¹ç¤Ë¤Ï¥¨¥é¡¼¤Î¥í¥°¤È¥Þ -¥·¥ó¡¤OS¤Î¼ïÎà¤ò´Þ¤à¤Ç¤¤ë¤À¤±¾Ü¤·¤¤¥ì¥Ý¡¼¥È¤òºî¼Ô¤ËÁ÷¤Ã¤Æ¤¯ -¤À¤µ¤ë¤È¾¤ÎÊý¤Î¤¿¤á¤Ë¤â¤Ê¤ê¤Þ¤¹¡¥ + 4. Run make. -* °Ü¿¢ + 5. Optionally, run 'make test' to check that the compiled ruby + interpreter works well. If you see the message "test succeeded", + your ruby works as it should. -UNIX¤Ç¤¢¤ì¤Ðconfigure¤¬¤Û¤È¤ó¤É¤Îº¹°Û¤òµÛ¼ý¤·¤Æ¤¯¤ì¤ë¤Ï¤º¤Ç -¤¹¤¬¡¤»×¤ï¤Ì¸«Íî¤È¤·¤¬¤¢¤Ã¤¿¾ì¹ç(¤¢¤ë¤Ë°ã¤¤¤Ê¤¤)¡¤ºî¼Ô¤Ë¤½¤Î -¤³¤È¤ò¥ì¥Ý¡¼¥È¤¹¤ì¤Ð¡¤²ò·è¤Ç¤¤ë¤«¤âÃΤì¤Þ¤»¤ó¡¥ + 6. Run 'make install' -¥¢¡¼¥¯¥Æ¥¯¥Á¥ã¤Ë¤â¤Ã¤È¤â°Í¸¤¹¤ë¤Î¤ÏGCÉô¤Ç¤¹¡¥ruby¤ÎGC¤ÏÂÐ¾Ý -¤Î¥¢¡¼¥¥Æ¥¯¥Á¥ã¤¬setjmp()¤Ë¤è¤Ã¤Æ¡¤Á´¤Æ¤Î¥ì¥¸¥¹¥¿¤ò jmp_buf -¤Ë³ÊǼ¤¹¤ë¤³¤È¤È¡¤jmp_buf¤È¥¹¥¿¥Ã¥¯¤¬32bit¥¢¥é¥¤¥ó¥á¥ó¥È¤µ¤ì -¤Æ¤¤¤ë¤³¤È¤ò²¾Äꤷ¤Æ¤¤¤Þ¤¹¡¥Á°¼Ô¤¬À®Î©¤·¤Ê¤¤¾ì¹ç¤ÎÂбþ¤Ïº¤Æñ -¤ò¶Ë¤á¤ë¤Ç¤·¤ç¤¦¡¥¸å¼Ô¤Î²ò·è¤ÏÈæ³ÓŪ´Êñ¤Ç¡¤gc.c¤Ç¥¹¥¿¥Ã¥¯¤ò -¥Þ¡¼¥¯¤·¤Æ¤¤¤ëÉôʬ¤Ë¥¢¥é¥¤¥ó¥á¥ó¥È¤Î¥Ð¥¤¥È¿ô¤À¤±¤º¤é¤·¤Æ¥Þ¡¼ -¥¯¤¹¤ë¥³¡¼¥É¤òÄɲ乤ë¤À¤±¤ÇºÑ¤ß¤Þ¤¹¡¥¡Ödefined(THINK_C)¡×¤Ç -³ç¤é¤ì¤Æ¤¤¤ëÉôʬ¤ò»²¹Í¤Ë¤·¤Æ¤¯¤À¤µ¤¤ +If you fail to compile ruby, please send the detailed error report with +the error log and machine/OS type, to help others. -# ¼ÂºÝ¤Ë¤Ïruby¤ÏThink C¤Ç¥³¥ó¥Ñ¥¤¥ë¤Ç¤¤Þ¤»¤ó¡¥ +* Copying -sparc°Ê³°¤Î¥ì¥¸¥¹¥¿¥¦¥£¥ó¥É¥¦¤ò»ý¤ÄCPU¤Ç¤Ï¡¤¥ì¥¸¥¹¥¿¥¦¥£¥ó¥É -¥¦¤ò¥Õ¥é¥Ã¥·¥å¤¹¤ë¥³¡¼¥É¤òÄɲ乤ëɬÍפ¬¤¢¤ë¤«¤âÃΤì¤Þ¤»¤ó¡¥ +Ruby is copyrighted by Yukihiro Matsumoto <matz@caelum.co.jp>. -* ÇÛÉÛ¾ò·ï +This source is distributed under the conditions blow: -Ruby¤ÎÇÛÉۤ˴ؤ·¤ÆÃøºî¸¢ÊÝ»ý¼Ô¤Ç¤¢¤ëºî¼Ô<matz@caelum.co.jp> -¤Ï°Ê²¼¤Î¾ò·ï¤ò¤Ä¤±¤Þ¤¹¡¥ + 1. You may make and give away verbatim copies of the source form of + the software without restriction, provided that you do not modify + the original distribution file. - + ¹¹¿· + If you want to distribute the modified version in any way, contact + the author. - ¤¤¤«¤Ê¤ëÌÜŪ¤Ç¤¢¤ì¼«Í³¤Ç¤¹¡¥¤¿¤À¤·¡¤µ¡Ç½³ÈÄ¥¤ä¥Ð¥°½¤Àµ¤Ï - ºî¼Ô¤Ø¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¤ò´üÂÔ¤·¤Þ¤¹(¤â¤Á¤í¤ó¶¯À©¤Ç¤Ï¤¢¤ê - ¤Þ¤»¤ó)¡¥ + 2. You may distribute the software in object code or executable + form, provided that you distribute it with instructions on where + to get the software. - + ¾¤Î¥×¥í¥°¥é¥à¤Ø¤Î°úÍÑ + 3. You may modify the software in any way, provided that you do not + distribute the modified version. - ¤¤¤«¤Ê¤ëÌÜŪ¤Ç¤¢¤ì¼«Í³¤Ç¤¹¡¥¤¿¤À¤·¡¤ruby¤Ë´Þ¤Þ¤ì¤ë¾¤Îºî - ¼Ô¤Ë¤è¤ë¥³¡¼¥É¤Ï¡¤¤½¤ì¤¾¤ì¤Îºî¼Ô¤Î°Õ¸þ¤Ë¤è¤ëÀ©¸Â¤¬²Ã¤¨¤é - ¤ì¤Þ¤¹¡¥¶ñÂÎŪ¤Ë¤Ïgc.c(°ìÉô)¡¤regex.[ch]¡¤fnmatch.[ch]¡¤ - glob.c, st.[ch]¤Èmissing¥Ç¥£¥ì¥¯¥È¥ê²¼¤Î¥Õ¥¡¥¤¥ë·²¤¬³ºÅö - ¤·¤Þ¤¹¡¥ + 4. You may modify and include the part of the software into any other + software (possibly commercial). But some files in the + distribution are not written by the author, so that they are not + under this terms. They are gc.c(partly)¡¤regex.[ch]¡¤fnmatch.[ch]¡¤ + glob.c, st.[ch] and somme files under ./missing directory. See + each files for the condition. - + ºÆÇÛÉÛ + 5. The scripts and library files supplied as input to or produced as + output from the software do not automatically fall under the + copyright of the software, but belong to whomever generated them, + and may be sold commercially, and may be aggregated with this + software. - ÇÛÉÛ¤·¤¿¾õÂÖ¤ò°Ý»ý¤¹¤ë¸Â¤ê¼«Í³¤Ç¤¹¡¥Êѹ¹¤ò¹Ô¤Ã¤¿¤â¤Î¤òºÆ - ÇÛÉÛ¤¹¤ë¤³¤È¤ò´õ˾¤¹¤ë»þ¤Ë¤Ïºî¼Ô¤ËÏ¢Íí¤·¤Æ¤¯¤À¤µ¤¤¡¥¥ª¥ê - ¥¸¥Ê¥ë¤Îruby¤ÈÌÀ³Î¤Ë¶èÊ̤Ǥ¤ë¤è¤¦¤Ç¤¢¤ì¤Ð¡¤ºÆÇÛÉÛ¤òǧ¤á - ¤ëÊý¿Ë¤Ç¤¹¡¥ + 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + PURPOSE. - Êѹ¹¤ò¹Ô¤Ê¤ï¤Ê¤¤ruby¤ò¥³¥ó¥Ñ¥¤¥ë¤·¤¿¥Ð¥¤¥Ê¥ê¤ÎÇÛÉÛ¤Ï¶Ø»ß - ¤·¤Þ¤»¤ó¤¬¡¤¥³¥ó¥Ñ¥¤¥ë¾ò·ï¤Ëµ¯°ø¤¹¤ë¥È¥é¥Ö¥ë¤ò¸º¤é¤¹¤¿¤á - ¤Ë¡¤¥³¥ó¥Ñ¥¤¥ë»þ¤Î¾ðÊó¤ò¤Ç¤¤ë¤À¤±¾Ü¤·¤¯ÌÀµ¤¹¤ë»ö¤ò´õ˾ - ¤·¤Þ¤¹¡¥ +* ruby home-page - + Ruby¥¹¥¯¥ê¥×¥È¤Î¸¢Íø + The URL of the ruby home-page is: - Á´¤Æ¤Îruby¥¹¥¯¥ê¥×¥È¤Î¸¢Íø¤Ï¤½¤ì¤¾¤ì¤ÎÃøºî¼Ô¤Ë°¤·¤Þ¤¹¡¥ - ºî¼Ô¤Ï¤³¤ì¤é¤Ë´Ø¤·¤Æ°ìÀڤθ¢Íø¤ò¼çÄ¥¤·¤Þ¤»¤ó¡¥¤Þ¤¿ruby¤Ë - ÁȤ߹þ¤à¤¿¤á¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë´Ø¤·¤Æ¤âƱÍͤǤ¹¡¥ + http://www.caelum.co.jp/~matz/ruby/index-en.html - + ̵ÊÝ¾Ú +* The Author - Ruby¤Ï̵ÊݾڤǤ¹¡¥ºî¼Ô¤Ïruby¤ò¥µ¥Ý¡¼¥È¤¹¤ë°Õ»Ö¤Ï¤¢¤ê¤Þ¤¹ - ¤¬¡¤ruby¼«¿È¤Î¥Ð¥°¤¢¤ë¤¤¤Ïruby¥¹¥¯¥ê¥×¥È¤Î¥Ð¥°¤Ê¤É¤«¤éȯ - À¸¤¹¤ë¤¤¤«¤Ê¤ë»³²¤ËÂФ·¤Æ¤âÀÕǤ¤ò»ý¤Á¤Þ¤»¤ó¡¥ +Feel free to send comments and bug reports to the author. Here is the +author's latest mail address: -* Ãø¼Ô + matz@ruby.club.or.jp -¥³¥á¥ó¥È¡¤¥Ð¥°¥ì¥Ý¡¼¥È¤½¤Î¾¤Ï matz@caelum.co.jp ¤Þ¤Ç¡¥ ------------------------------------------------------- created at: Thu Aug 3 11:57:36 JST 1995 Local variables: diff --git a/README.EXT b/README.EXT index efa627a24a..fdf8c96af7 100644 --- a/README.EXT +++ b/README.EXT @@ -1,308 +1,1029 @@ .\" README.EXT - -*- Text -*- created at: Mon Aug 7 16:45:54 JST 1995 -Ruby¤ò³ÈÄ¥¤¹¤ë¤¿¤á¤ÎÊýË¡¤ò²òÀ⤹¤ë¡¥ +ruby¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Îºî¤êÊý¤òÀâÌÀ¤·¤Þ¤¹¡¥ + +1¡¥´ðÁÃÃμ± + +C¤ÎÊÑ¿ô¤Ë¤Ï·¿¤¬¤¢¤ê¡¤¥Ç¡¼¥¿¤Ë¤Ï·¿¤¬¤¢¤ê¤Þ¤»¤ó¡¥¤Ç¤¹¤«¤é¡¤¤¿ +¤È¤¨¤Ð¥Ý¥¤¥ó¥¿¤òint¤ÎÊÑ¿ô¤ËÂåÆþ¤¹¤ë¤È¡¤¤½¤ÎÃͤÏÀ°¿ô¤È¤·¤Æ¼è +¤ê°·¤ï¤ì¤Þ¤¹¡¥µÕ¤Ëruby¤ÎÊÑ¿ô¤Ë¤Ï·¿¤¬¤Ê¤¯¡¤¥Ç¡¼¥¿¤Ë·¿¤¬¤¢¤ê¤Þ +¤¹¡¥¤³¤Î°ã¤¤¤Î¤¿¤á¡¤C¤Èruby¤ÏÁê¸ß¤ËÊÑ´¹¤·¤Ê¤±¤ì¤Ð¡¤¤ª¸ß¤¤¤Î +¥Ç¡¼¥¿¤ò¥¢¥¯¥»¥¹¤Ç¤¤Þ¤»¤ó¡¥ + +ruby¤Î¥Ç¡¼¥¿¤ÏVALUE¤È¤¤¤¦C¤Î·¿¤Çɽ¸½¤µ¤ì¤Þ¤¹¡¥VALUE·¿¤Î¥Ç¡¼ +¥¿¤Ï¤½¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤ò¼«Ê¬¤ÇÃΤäƤ¤¤Þ¤¹¡¥¤³¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤È +¤¤¤¦¤Î¤Ï¥Ç¡¼¥¿(¥ª¥Ö¥¸¥§¥¯¥È)¤Î¼ÂºÝ¤Î¹½Â¤¤ò°ÕÌ£¤·¤Æ¤¤¤Æ¡¤ruby +¤Î¥¯¥é¥¹¤È¤Ï¤Þ¤¿°ã¤Ã¤¿¤â¤Î¤Ç¤¹¡¥ + +VALUE¤«¤éC¤Ë¤È¤Ã¤Æ°ÕÌ£¤Î¤¢¤ë¥Ç¡¼¥¿¤ò¼è¤ê½Ð¤¹¤¿¤á¤Ë¤Ï + + (1) VALUE¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤òÃΤë + (2) VALUE¤òC¤Î¥Ç¡¼¥¿¤ËÊÑ´¹¤¹¤ë + +¤ÎξÊý¤¬É¬ÍפǤ¹¡¥(1)¤ò˺¤ì¤ë¤È´Ö°ã¤Ã¤¿¥Ç¡¼¥¿¤ÎÊÑ´¹¤¬¹Ô¤ï¤ì +¤Æ¡¤ºÇ°¥×¥í¥°¥é¥à¤¬core dump¤·¤Þ¤¹¡¥ + +1.1 ¥Ç¡¼¥¿¥¿¥¤¥× + +ruby¤Ë¤Ï¥æ¡¼¥¶¤¬»È¤¦²ÄǽÀ¤Î¤¢¤ë°Ê²¼¤Î¥¿¥¤¥×¤¬¤¢¤ê¤Þ¤¹¡¥ -Ruby¤ÏC¥³¡¼¥É¤ò½ñ¤¯¤³¤È¤Ë¤è¤Ã¤Æ¡¤´Êñ¤Ëµ¡Ç½¤òÄɲäǤ¤ë¡¥¤ª¤ª¤Þ¤«¤Ê¼ê -½ç¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥ + T_NIL nil + T_OBJECT Ä̾ï¤Î¥ª¥Ö¥¸¥§¥¯¥È + T_CLASS ¥¯¥é¥¹ + T_MODULE ¥â¥¸¥å¡¼¥ë + T_FLOAT ÉâÆ°¾®¿ôÅÀ¿ô + T_STRING ʸ»úÎó + T_REGEXP Àµµ¬É½¸½ + T_ARRAY ÇÛÎó + T_FIXNUM Fixnum(31bitĹÀ°¿ô) + T_HASH Ï¢ÁÛÇÛÎó + T_STRUCT (ruby¤Î)¹½Â¤ÂÎ + T_BIGNUM ¿ÇÜĹÀ°¿ô + T_TRUE ¿¿ + T_FALSE µ¶ + T_DATA ¥Ç¡¼¥¿ - 1. ¥Õ¥¡¥¤¥ë¤òÍѰդ¹¤ë +¤½¤Î¾¤ËÆâÉô¤ÇÍøÍѤµ¤ì¤Æ¤¤¤ë°Ê²¼¤Î¥¿¥¤¥×¤¬¤¢¤ê¤Þ¤¹¡¥ - ext¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¤Ë³ÈÄ¥¥â¥¸¥å¡¼¥ëÍѤΥǥ£¥ì¥¯¥È¥ê¤òÍѰդ·¤Æ¡¤¤½ - ¤ÎÇÛ²¼¤Ë°Ê²¼¤Î¥Õ¥¡¥¤¥ë¤òÍѰդ¹¤ëɬÍפ¬¤¢¤ë¡¥ + T_ICLASS + T_MATCH + T_VARMAP + T_SCOPE + T_NODE - + MANIFEST¡¥É¬Íפʥե¡¥¤¥ë¤Î°ìÍ÷¡¥ +¤¤¤¯¤Ä¤«¤Î¥¿¥¤¥×¤ÏC¤Î¹½Â¤ÂΤǼÂÁõ¤µ¤ì¤Æ¤¤¤Þ¤¹¡¥ - ɬ¤ºÉ¬Íס¥°ì»þŪ¤Ê¥Õ¥¡¥¤¥ë°Ê³°¤ÎÁ´¤Æ¤Î¥Õ¥¡¥¤¥ë̾¤ò1¹Ô1¥Õ¥¡¥¤¥ë - ¤Î·Á¼°¤Çµ½Ò¤¹¤ë¤³¤È¡¥ +1.2 VALUE¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤ò¥Á¥§¥Ã¥¯¤¹¤ë - + C¤Î¥½¡¼¥¹¥Õ¥¡¥¤¥ë¡¥ +ruby.h¤Ç¤ÏTYPE()¤È¤¤¤¦¥Þ¥¯¥í¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤Æ¡¤VALUE¤Î¥Ç¡¼¥¿ +¥¿¥¤¥×¤òÃΤ뤳¤È¤¬½ÐÍè¤Þ¤¹¡¥TYPE()¥Þ¥¯¥í¤Ï¾å¤Ç¾Ò²ð¤·¤¿T_XXXX +¤Î·Á¼°¤ÎÄê¿ô¤òÊÖ¤·¤Þ¤¹¡¥VALUE¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤Ë±þ¤¸¤Æ½èÍý¤¹¤ë +¾ì¹ç¤Ë¤Ï¡¤TYPE()¤ÎÃͤÇʬ´ô¤¹¤ë¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥ - ¥â¥¸¥å¡¼¥ë¤¬1¥Õ¥¡¥¤¥ë¤À¤±¤«¤é¤Ê¤ë»þ¤Ï¥â¥¸¥å¡¼¥ë̾¤ÈƱ¤¸Ì¾Á°¤Î¥Õ¥¡ - ¥¤¥ë̾(¥â¥¸¥å¡¼¥ë.c)¤ò¤Ä¤±¤ë¡¥µÕ¤Ë¥â¥¸¥å¡¼¥ë¤¬Ê£¿ô¤«¤é¤Ê¤ë»þ¤Ï - ¥â¥¸¥å¡¼¥ë̾¤Î¤Ä¤¤¤¿¥½¡¼¥¹¥Õ¥¡¥¤¥ë¤ÏÈò¤±¤ë¤³¤È¡¥ + switch (TYPE(obj)) { + case T_FIXNUM: + /* FIXNUM¤Î½èÍý */ + break; + case T_STRING: + /* ʸ»úÎó¤Î½èÍý */ + break; + case T_ARRAY: + /* ÇÛÎó¤Î½èÍý */ + break; + default: + /* Îã³°¤òȯÀ¸¤µ¤»¤ë */ + Fail("not valid value"); + break; + } - + extconf.rb(optional)¡¥ÀßÄêÍÑ¥Õ¥¡¥¤¥ë¡¥ +¤½¤ì¤È¥Ç¡¼¥¿¥¿¥¤¥×¤ò¥Á¥§¥Ã¥¯¤·¤Æ¡¤Àµ¤·¤¯¤Ê¤±¤ì¤ÐÎã³°¤òȯÀ¸¤¹ +¤ë´Ø¿ô¤¬ÍѰդµ¤ì¤Æ¤¤¤Þ¤¹¡¥ - ´Ø¿ô¤ä¥é¥¤¥Ö¥é¥ê¡¤¥Ø¥Ã¥À¤Î¸ºß¥Á¥§¥Ã¥¯¤ò¤·¤¿¤ê¡¤¥â¥¸¥å¡¼¥ë̾¤Ê - ¤É¤òÀßÄꤹ¤ë¡¥¤³¤Î¥Õ¥¡¥¤¥ë¤¬Ìµ¤±¤ì¤ÐÁ´¤Æ¥Ç¥Õ¥©¥ë¥È¤Ç¥³¥ó¥Ñ¥¤¥ë - ¤µ¤ì¤ë¡¥ + void Check_Type(VALUE value, int type) - + depend(optional)¡¥Makefile¤Ë¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë¤¿¤á¤Î¥Õ¥¡ - ¥¤¥ë¤Î°Í¸´Ø·¸¤òµ½Ò¤·¤¿¥Õ¥¡¥¤¥ë¡¥ +¤³¤Î´Ø¿ô¤Ïvalue¤¬type¤Ç̵¤±¤ì¤Ð¡¤Îã³°¤òȯÀ¸¤µ¤»¤Þ¤¹¡¥°ú¿ô¤È +¤·¤ÆÍ¿¤¨¤é¤ì¤¿VALUE¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤¬Àµ¤·¤¤¤«¤É¤¦¤«¥Á¥§¥Ã¥¯¤¹ +¤ë¤¿¤á¤Ë¤Ï¡¤¤³¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥ - `gcc -MM *.c > depend'¤È¤¹¤ì¤Ð¼«Æ°Åª¤ËÀ¸À®¤Ç¤¤ë¡¥ +1.3 VALUE¤òC¤Î¥Ç¡¼¥¿¤ËÊÑ´¹¤¹¤ë - 2. C¤Î¥½¡¼¥¹¥Õ¥¡¥¤¥ë¤òÍѰդ¹¤ë +¥Ç¡¼¥¿¥¿¥¤¥×¤¬T_NIL, T_FALSE, T_TRUE¤Ç¤¢¤ë»þ¡¤¥Ç¡¼¥¿¤Ï¤½¤ì¤¾ +¤ìnil, FALSE, TRUE¤Ç¤¹¡¥¤³¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ï¤Ò¤È +¤Ä¤º¤Ä¤·¤«Â¸ºß¤·¤Þ¤»¤ó¡¥ - ɬ¤º¡ÖInit_¥â¥¸¥å¡¼¥ë̾¡×¤È¤¤¤¦´Ø¿ô¤òÍѰդ·¡¤¤½¤ÎÃæ¤Ç¡¤ÊÑ¿ô¤ä¥¯¥é - ¥¹¤ÎÄêµÁ¤ä¡¤¥¯¥é¥¹¤Ø¤Î¥á¥½¥Ã¥É¤ÎÅÐÏ¿¤Ê¤É¤Î½é´ü²½¤ò¹Ô¤¦¤³¤È¡¥¤³¤Î - ´Ø¿ô¤Î¸Æ¤Ó½Ð¤·¤Ï¥¤¥ó¥¿¥×¥ê¥¿¤Î½é´ü²½»þ(ÀÅŪ¥ê¥ó¥¯¤Î¾ì¹ç)¤«¥â¥¸¥å¡¼ - ¥ë¤Î¥í¡¼¥É»þ(ưŪ¥ê¥ó¥¯¤Î¾ì¹ç)¤Ë¼«Æ°Åª¤Ë¹Ô¤ï¤ì¤ë¡¥ +¥Ç¡¼¥¿¥¿¥¤¥×¤¬T_FIXNUM¤Î»þ¡¤¤³¤ì¤Ï31bit¤Î¥µ¥¤¥º¤ò»ý¤ÄÀ°¿ô¤Ç +¤¹¡¥FIXNUM¤òC¤ÎÀ°¿ô¤ËÊÑ´¹¤¹¤ë¤¿¤á¤Ë¤Ï¥Þ¥¯¥í¡ÖFIX2INT()¡×¤ò»È +¤¤¤Þ¤¹¡¥¤½¤ì¤«¤é¡¤FIXNUM¤Ë¸Â¤é¤ºruby¤Î¥Ç¡¼¥¿¤òÀ°¿ô¤ËÊÑ´¹¤¹¤ë +¡ÖNUM2INT()¡×¤È¤¤¤¦¥Þ¥¯¥í¤¬¤¢¤ê¤Þ¤¹¡¥¤³¤Î¥Þ¥¯¥í¤Ï¥Ç¡¼¥¿¥¿¥¤ +¥×¤Î¥Á¥§¥Ã¥¯Ìµ¤·¤Ç»È¤¨¤Þ¤¹(À°¿ô¤ËÊÑ´¹¤Ç¤¤Ê¤¤¾ì¹ç¤Ë¤ÏÎã³°¤¬ +ȯÀ¸¤¹¤ë)¡¥ -* Ruby API +¤½¤ì°Ê³°¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤ÏÂбþ¤¹¤ëC¤Î¹½Â¤ÂΤ¬¤¢¤ê¤Þ¤¹¡¥Âбþ¤¹ +¤ë¹½Â¤ÂΤΤ¢¤ëVALUE¤Ï¤½¤Î¤Þ¤Þ¥¥ã¥¹¥È(·¿ÊÑ´¹)¤¹¤ì¤Ð¹½Â¤ÂΤΠ+¥Ý¥¤¥ó¥¿¤ËÊÑ´¹¤Ç¤¤Þ¤¹¡¥ -C¸À¸ì¤«¤éRuby¤Îµ¡Ç½¤òÍøÍѤ¹¤ëAPI¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥ +¹½Â¤ÂΤϡÖstruct RXxxxx¡×¤È¤¤¤¦Ì¾Á°¤Çruby.h¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤Þ +¤¹¡¥Î㤨¤Ðʸ»úÎó¤Ï¡Östruct RString¡×¤Ç¤¹¡¥¼ÂºÝ¤Ë»È¤¦²ÄǽÀ¤¬ +¤¢¤ë¤Î¤Ïʸ»úÎó¤ÈÇÛÎ󤯤餤¤À¤È»×¤¤¤Þ¤¹¡¥ + +ruby.h¤Ç¤Ï¹½Â¤ÂΤإ¥ã¥¹¥È¤¹¤ë¥Þ¥¯¥í¤â¡ÖRXXXXX()¡×(Á´ÉôÂçʸ +»ú¤Ë¤·¤¿¤â¤Î)¤È¤¤¤¦Ì¾Á°¤ÇÄ󶡤µ¤ì¤Æ¤¤¤Þ¤¹(Îã: RSTRING())¡¥ + +Î㤨¤Ð¡¤Ê¸»úÎóstr¤ÎŤµ¤òÆÀ¤ë¤¿¤á¤Ë¤Ï¡ÖRSTRING(str)->len¡×¤È +¤·¡¤Ê¸»úÎóstr¤òchar*¤È¤·¤ÆÆÀ¤ë¤¿¤á¤Ë¤Ï¡ÖRSTRING(str)->ptr¡× +¤È¤·¤Þ¤¹¡¥ÇÛÎó¤Î¾ì¹ç¤Ë¤Ï¡¤¤½¤ì¤¾¤ì¡ÖRARRAT(str)->len¡×¡¤ +¡ÖRARRAT(str)->ptr¡×¤È¤Ê¤ê¤Þ¤¹¡¥ + +ruby¤Î¹½Â¤ÂΤòľÀÜ¥¢¥¯¥»¥¹¤¹¤ë»þ¤Ëµ¤¤ò¤Ä¤±¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¤³ +¤È¤Ï¡¤ÇÛÎó¤äʸ»úÎó¤Î¹½Â¤ÂΤÎÃæ¿È¤Ï»²¾È¤¹¤ë¤À¤±¤Ç¡¤Ä¾ÀÜÊѹ¹¤· +¤Ê¤¤¤³¤È¤Ç¤¹¡¥Ä¾ÀÜÊѹ¹¤·¤¿¾ì¹ç¡¤¥ª¥Ö¥¸¥§¥¯¥È¤ÎÆâÍÆ¤ÎÀ°¹çÀ¤¬ +¤È¤ì¤Ê¤¯¤Ê¤Ã¤Æ¡¤»×¤ï¤Ì¥Ð¥°¤Î¸¶°ø¤Ë¤Ê¤ê¤Þ¤¹¡¥ + +1.4 C¤Î¥Ç¡¼¥¿¤òVALUE¤ËÊÑ´¹¤¹¤ë + +VALUE¤Î¼ÂºÝ¤Î¹½Â¤¤Ï + + * FIXNUM¤Î¾ì¹ç + + 1bit±¦¥·¥Õ¥È¤·¤Æ¡¤LSB¤òΩ¤Æ¤ë¡¥ + + * ¤½¤Î¾¤Î¥Ý¥¤¥ó¥¿¤Î¾ì¹ç + + ¤½¤Î¤Þ¤ÞVALUE¤Ë¥¥ã¥¹¥È¤¹¤ë¡¥ + +¤È¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥¤è¤Ã¤Æ¡¤LSB¤ò¥Á¥§¥Ã¥¯¤¹¤ì¤ÐVALUE¤¬FIXNUM¤«¤É +¤¦¤«¤ï¤«¤ë¤ï¤±¤Ç¤¹(¥Ý¥¤¥ó¥¿¤ÎLSB¤¬Î©¤Ã¤Æ¤¤¤Ê¤¤¤³¤È¤ò²¾Äꤷ¤Æ +¤¤¤ë)¡¥ + +¤Ç¤¹¤«¤é¡¤FIXNUM°Ê³°¤Îruby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Î¹½Â¤ÂΤÏñ¤ËVALUE +¤Ë¥¥ã¥¹¥È¤¹¤ë¤À¤±¤ÇVALUE¤ËÊÑ´¹½ÐÍè¤Þ¤¹¡¥¤¿¤À¤·¡¤Ç¤°Õ¤Î¹½Â¤ +ÂΤ¬VALUE¤Ë¥¥ã¥¹¥È½ÐÍè¤ë¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡¥¥¥ã¥¹¥È¤¹¤ë¤Î +¤Ïruby¤ÎÃΤäƤ¤¤ë¹½Â¤ÂÎ(ruby.h¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ëstruct RXxxx +¤Î¤â¤Î)¤À¤±¤Ë¤·¤Æ¤ª¤¤¤Æ¤¯¤À¤µ¤¤¡¥ + +FIXNUM¤Ë´Ø¤·¤Æ¤ÏÊÑ´¹¥Þ¥¯¥í¤ò·Ðͳ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥C¤ÎÀ°¿ô +¤«¤éVALUE¤ËÊÑ´¹¤¹¤ë¥Þ¥¯¥í¤Ï°Ê²¼¤Î¤â¤Î¤¬¤¢¤ê¤Þ¤¹¡¥É¬Íפ˱þ¤¸ +¤Æ»È¤¤Ê¬¤±¤Æ¤¯¤À¤µ¤¤¡¥ + + INT2FIX() ¤â¤È¤ÎÀ°¿ô¤¬31bit°ÊÆâ¤Ë¼ý¤Þ¤ë»þ + INT2NUM() Ǥ°Õ¤ÎÀ°¿ô¤«¤éVALUE¤Ø + +INT2NUM()¤ÏÀ°¿ô¤¬FIXNUM¤ÎÈϰϤ˼ý¤Þ¤é¤Ê¤¤¾ì¹ç¡¤Bignum¤ËÊÑ´¹ +¤·¤Æ¤¯¤ì¤Þ¤¹(¤¬¡¤¾¯¤·ÃÙ¤¤)¡¥ + +1.5 ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë + +ÀèÄø¤â½Ò¤Ù¤¿Ä̤ꡤruby¤Î¹½Â¤ÂΤò¥¢¥¯¥»¥¹¤¹¤ë»þ¤ËÆâÍÆ¤Î¹¹¿·¤ò +¹Ô¤¦¤³¤È¤Ï´«¤á¤é¤ì¤Þ¤»¤ó¡¥¤Ç¡¤ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë»þ¤Ë¤Ï +ruby¤¬ÍѰդ·¤Æ¤¤¤ë´Ø¿ô¤òÍѤ¤¤Æ¤¯¤À¤µ¤¤¡¥ + +¤³¤³¤Ç¤Ï¤â¤Ã¤È¤â»È¤ï¤ì¤ë¤Ç¤¢¤í¤¦Ê¸»úÎó¤ÈÇÛÎó¤ÎÀ¸À®/Áàºî¤ò¹Ô +¤¤´Ø¿ô¤ò¤¢¤²¤Þ¤¹(Á´Éô¤Ç¤Ï¤Ê¤¤¤Ç¤¹)¡¥ + + ʸ»úÎó¤ËÂФ¹¤ë´Ø¿ô + + str_new(char *ptr, int len) + + ¿·¤·¤¤ruby¤Îʸ»úÎó¤òÀ¸À®¤¹¤ë¡¥ + + str_new2(char *ptr) + + C¤Îʸ»úÎ󤫤éruby¤Îʸ»úÎó¤òÀ¸À®¤¹¤ë¡¥¤³¤Î´Ø¿ô¤Îµ¡Ç½¤Ï + str_new(ptr, strlen(ptr))¤ÈƱÅù¤Ç¤¢¤ë¡¥ + + str_cat(VALUE str, char *ptr, int len) + + ruby¤Îʸ»úÎóstr¤Ëlen¥Ð¥¤¥È¤Îʸ»úÎóptr¤òÄɲ乤롥 + + ÇÛÎó¤ËÂФ¹¤ë´Ø¿ô + + ary_new() + + Í×ÁǤ¬0¤ÎÇÛÎó¤òÀ¸À®¤¹¤ë¡¥ + + ary_new2(int len) + + Í×ÁǤ¬0¤ÎÇÛÎó¤òÀ¸À®¤¹¤ë¡¥lenÍ×ÁÇʬ¤ÎÎΰè¤ò¤¢¤é¤«¤¸¤á³ä¤ê + Åö¤Æ¤Æ¤ª¤¯¡¥ + + ary_new3(int n, ...) + + °ú¿ô¤Ç»ØÄꤷ¤¿nÍ×ÁǤò´Þ¤àÇÛÎó¤òÀ¸À®¤¹¤ë¡¥ + + ary_new4(int n, VALUE elts[]) + + ÇÛÎó¤ÇÍ¿¤¨¤¿nÍ×ÁǤÎÇÛÎó¤òÀ¸À®¤¹¤ë¡¥ + + ary_push(VALUE ary) + ary_pop(VALUE ary, VALUE val) + ary_shift(VALUE ary) + ary_unshift(VALUE ary, VALUE val) + ary_entry(VALUE ary, int idx) + + Array¤ÎƱ̾¤Î¥á¥½¥Ã¥É¤ÈƱ¤¸Æ¯¤¤ò¤¹¤ë´Ø¿ô¡¥Âè1°ú¿ô¤Ïɬ¤º + ÇÛÎó¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡¥ + +2¡¥ruby¤Îµ¡Ç½¤ò»È¤¦ + +¸¶ÍýŪ¤Ëruby¤Ç½ñ¤±¤ë¤³¤È¤ÏC¤Ç¤â½ñ¤±¤Þ¤¹¡¥ruby¤½¤Î¤â¤Î¤¬C¤Çµ +½Ò¤µ¤ì¤Æ¤¤¤ë¤ó¤Ç¤¹¤«¤é¡¤ÅöÁ³¤È¤¤¤¨¤ÐÅöÁ³¤Ê¤ó¤Ç¤¹¤±¤É¡¥¤³¤³¤Ç +¤Ïruby¤Î³ÈÄ¥¤Ë»È¤¦¤³¤È¤¬Â¿¤¤¤À¤í¤¦¤Èͽ¬¤µ¤ì¤ëµ¡Ç½¤òÃæ¿´¤Ë¾Ò +²ð¤·¤Þ¤¹¡¥ + +2.1 ruby¤Ëµ¡Ç½¤òÄɲ乤ë + +ruby¤ÇÄ󶡤µ¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤¨¤Ðruby¥¤¥ó¥¿¥×¥ê¥¿¤Ë¿·¤·¤¤µ¡Ç½ +¤òÄɲ乤뤳¤È¤¬¤Ç¤¤Þ¤¹¡¥ruby¤Ç¤Ï°Ê²¼¤Îµ¡Ç½¤òÄɲä¹¤ë´Ø¿ô¤¬ +Ä󶡤µ¤ì¤Æ¤¤¤Þ¤¹¡¥ + + * ¥¯¥é¥¹¡¤¥â¥¸¥å¡¼¥ë + * ¥á¥½¥Ã¥É¡¤ÆÃ°Û¥á¥½¥Ã¥É¤Ê¤É + * Äê¿ô + +¤Ç¤Ï½ç¤Ë¾Ò²ð¤·¤Þ¤¹¡¥ + +2.1.1 ¥¯¥é¥¹/¥â¥¸¥å¡¼¥ëÄêµÁ + +¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¤¿¤á¤Ë¤Ï¡¤°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥ + + VALUE rb_define_class(char *name, VALUE super) + VALUE rb_define_module(char *name) + +¤³¤ì¤é¤Î´Ø¿ô¤Ï¿·¤·¤¯ÄêµÁ¤µ¤ì¤¿¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤òÊÖ¤·¤Þ¤¹¡¥ +¥á¥½¥Ã¥É¤äÄê¿ô¤ÎÄêµÁ¤Ë¤³¤ì¤é¤ÎÃͤ¬É¬ÍפʤΤǡ¤¤Û¤È¤ó¤É¤Î¾ì¹ç +¤ÏÌá¤êÃͤòÊÑ¿ô¤Ë³ÊǼ¤·¤Æ¤ª¤¯É¬Íפ¬¤¢¤ë¤Ç¤·¤ç¤¦¡¥ + +2.1.2 ¥á¥½¥Ã¥É/ÆÃ°Û¥á¥½¥Ã¥ÉÄêµÁ + +¥á¥½¥Ã¥É¤äÆÃ°Û¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥ + + void rb_define_method(VALUE class, char *name, + VALUE (*func)(), int argc) + + void rb_define_sigleton_method(VALUE object, char *name, + VALUE (*func)(), int argc) + + +ǰ¤Î¤¿¤áÀâÌÀ¤¹¤ë¤È¡ÖÆÃ°Û¥á¥½¥Ã¥É¡×¤È¤Ï¡¤¤½¤ÎÆÃÄê¤Î¥ª¥Ö¥¸¥§¥¯ +¥È¤ËÂФ·¤Æ¤À¤±Í¸ú¤Ê¥á¥½¥Ã¥É¤Ç¤¹¡¥ruby¤Ç¤Ï¤è¤¯Smalltalk¤Ë¤ª +¤±¤ë¥¯¥é¥¹¥á¥½¥Ã¥É¤È¤·¤Æ¡¤¥¯¥é¥¹¤ËÂФ¹¤ëÆÃ°Û¥á¥½¥Ã¥É¤¬»È¤ï¤ì +¤Þ¤¹¡¥ + +¤³¤ì¤é¤Î´Ø¿ô¤Î argc¤È¤¤¤¦°ú¿ô¤ÏC¤Î´Ø¿ô¤ØÅϤµ¤ì¤ë°ú¿ô¤Î¿ô(¤È +·Á¼°)¤ò·è¤á¤Þ¤¹¡¥argc¤¬Àµ¤Î»þ¤Ï´Ø¿ô¤Ë°ú¤ÅϤ¹°ú¿ô¤Î¿ô¤ò°ÕÌ£ +¤·¤Þ¤¹¡¥16¸Ä°Ê¾å¤Î°ú¿ô¤Ï»È¤¨¤Þ¤»¤ó(¤¬¡¤Íפê¤Þ¤»¤ó¤è¤Í¡¤¤½¤ó +¤Ê¤Ë)¡¥ + +argc¤¬Éé¤Î»þ¤Ï°ú¿ô¤Î¿ô¤Ç¤Ï¤Ê¤¯¡¤·Á¼°¤ò»ØÄꤷ¤¿¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥ +argc¤¬-1¤Î»þ¤Ï°ú¿ô¤òÇÛÎó¤ËÆþ¤ì¤ÆÅϤµ¤ì¤Þ¤¹¡¥argc¤¬-2¤Î»þ¤Ï°ú +¿ô¤Ïruby¤ÎÇÛÎó¤È¤·¤ÆÅϤµ¤ì¤Þ¤¹¡¥ + +¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ï¤â¤¦Æó¤Ä¤¢¤ê¤Þ¤¹¡¥¤Ò¤È¤Ä¤Ïprivate¥á +¥½¥Ã¥É¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ç¡¤°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¤Ç¤¹¡¥ + + void rb_define_private_method(VALUE class, char *name, + VALUE (*func)(), int argc) + +private¥á¥½¥Ã¥É¤È¤Ï´Ø¿ô·Á¼°¤Ç¤·¤«¸Æ¤Ó½Ð¤¹¤³¤È¤Î½ÐÍè¤Ê¤¤¥á¥½¥Ã +¥É¤Ç¤¹¡¥ + +¤â¤¦¤Ò¤È¤Ä¤Ï¥â¥¸¥å¡¼¥ë´Ø¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¤Ç¤¹¡¥¥â¥¸¥å¡¼¥ë´Ø¿ô +¤È¤Ï¥â¥¸¥å¡¼¥ë¤ÎÆÃ°Û¥á¥½¥Ã¥É¤Ç¤¢¤ê¡¤Æ±»þ¤Ëprivate¥á¥½¥Ã¥É¤Ç +¤â¤¢¤ë¤â¤Î¤Ç¤¹¡¥Îã¤ò¤¢¤²¤ë¤ÈMath¥â¥¸¥å¡¼¥ë¤Îsqrt()¤Ê¤É¤¬¤¢¤² +¤é¤ì¤Þ¤¹¡¥¤³¤Î¥á¥½¥Ã¥É¤Ï + + Math.sqrt(4) + +¤È¤¤¤¦·Á¼°¤Ç¤â + + include Math + sqrt(4) + +¤È¤¤¤¦·Á¼°¤Ç¤â»È¤¨¤Þ¤¹¡¥¥â¥¸¥å¡¼¥ë´Ø¿ô¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ï°Ê²¼¤Î +Ä̤ê¤Ç¤¹¡¥ + + void rb_define_module_method(VALUE module, char *name, + VALUE (*func)(), int argc) + +2.1.3 Äê¿ôÄêµÁ + +³ÈÄ¥¥â¥¸¥å¡¼¥ë¤¬É¬ÍפÊÄê¿ô¤Ï¤¢¤é¤«¤¸¤áÄêµÁ¤·¤Æ¤ª¤¤¤¿Êý¤¬Îɤ¤ +¤Ç¤·¤ç¤¦¡¥Äê¿ô¤òÄêµÁ¤¹¤ë´Ø¿ô¤ÏÆó¤Ä¤¢¤ê¤Þ¤¹¡¥ + + void rb_define_const(VALUE class, char *name, VALUE val) + void rb_define_global_const(char *name, VALUE val) + +Á°¼Ô¤ÏÆÃÄê¤Î¥¯¥é¥¹/¥â¥¸¥å¡¼¥ë¤Ë°¤¹¤ëÄê¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¡¤¸å +¼Ô¤Ï¥°¥í¡¼¥Ð¥ë¤ÊÄê¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¤Ç¤¹¡¥ + +2.2 ruby¤Îµ¡Ç½¤òC¤«¤é¸Æ¤Ó½Ð¤¹ + +´û¤Ë¡Ø1.5 ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë¡Ù¤Ç°ìÉô¾Ò²ð¤·¤¿¤è¤¦¤Ê´Ø¿ô¤ò +»È¤¨¤Ð¡¤ruby¤Îµ¡Ç½¤ò¼Â¸½¤·¤Æ¤¤¤ë´Ø¿ô¤òľÀܸƤӽФ¹¤³¤È¤¬½ÐÍè +¤Þ¤¹¡¥ + +# ¤³¤Î¤è¤¦¤Ê´Ø¿ô¤Î°ìÍ÷ɽ¤Ï¤¤¤Þ¤Î¤È¤³¤í¤¢¤ê¤Þ¤»¤ó¡¥¥½¡¼¥¹¤ò¸« +# ¤ë¤·¤«¤Ê¤¤¤Ç¤¹¤Í¡¥ + +¤½¤ì°Ê³°¤Ë¤âruby¤Îµ¡Ç½¤ò¸Æ¤Ó½Ð¤¹ÊýË¡¤Ï¤¤¤¯¤Ä¤«¤¢¤ê¤Þ¤¹¡¥ + +2.2.1 ruby¤Î¥×¥í¥°¥é¥à¤òeval¤¹¤ë + +C¤«¤éruby¤Îµ¡Ç½¤ò¸Æ¤Ó½Ð¤¹¤â¤Ã¤È¤â´Êñ¤ÊÊýË¡¤È¤·¤Æ¡¤Ê¸»úÎó¤Ç +Í¿¤¨¤é¤ì¤¿ruby¤Î¥×¥í¥°¥é¥à¤òɾ²Á¤¹¤ë´Ø¿ô¤¬¤¢¤ê¤Þ¤¹¡¥ + + VALUE rb_eval_string(char *str) + +¤³¤Îɾ²Á¤Ï¸½ºß¤Î´Ä¶¤Ç¹Ô¤ï¤ì¤Þ¤¹¡¥¤Ä¤Þ¤ê¡¤¸½ºß¤Î¥í¡¼¥«¥ëÊÑ¿ô +¤äself¤Ê¤É¤ò¼õ¤±·Ñ¤®¤Þ¤¹¡¥ + +2.2.2 ID¤Þ¤¿¤Ï¥·¥ó¥Ü¥ë + +C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤Ëruby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤³¤È¤â¤Ç¤¤Þ +¤¹¡¥¤½¤ÎÁ°¤Ë¡¤ruby¥¤¥ó¥¿¥×¥ê¥¿Æâ¤Ç¥á¥½¥Ã¥É¤äÊÑ¿ô̾¤ò»ØÄꤹ¤ë +»þ¤Ë»È¤ï¤ì¤Æ¤¤¤ëID¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Æ¤ª¤¤Þ¤·¤ç¤¦¡¥ + +ID¤È¤ÏÊÑ¿ô̾¡¤¥á¥½¥Ã¥É̾¤òɽ¤¹À°¿ô¤Ç¤¹¡¥ruby¤ÎÃæ¤Ç¤Ï + + :¼±ÊÌ»Ò + +¤Ç¥¢¥¯¥»¥¹¤Ç¤¤Þ¤¹¡¥C¤«¤é¤³¤ÎÀ°¿ô¤òÆÀ¤ë¤¿¤á¤Ë¤Ï´Ø¿ô + + rb_intern(char *name) + +¤ò»È¤¤¤Þ¤¹¡¥ + +2.2.3 C¤«¤éruby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹ + +C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤Ëruby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤¿¤á¤Ë¤Ï°Ê²¼ +¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥ + + VALUE rb_funcall(VALUE recv, ID mid, int argc, ...) + +¤³¤Î´Ø¿ô¤Ï¥ª¥Ö¥¸¥§¥¯¥Èrecv¤Îmid¤Ç»ØÄꤵ¤ì¤ë¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð +¤·¤Þ¤¹¡¥ + +2.2.4 ÊÑ¿ô/Äê¿ô¤ò»²¾È/¹¹¿·¤¹¤ë + +C¤«¤é´Ø¿ô¤ò»È¤Ã¤Æ»²¾È¡¦¹¹¿·¤Ç¤¤ë¤Î¤Ï¡¤¥¯¥é¥¹Äê¿ô¡¤¥¤¥ó¥¹¥¿ +¥ó¥¹ÊÑ¿ô¤Ç¤¹¡¥Âç°èÊÑ¿ô¤Ï°ìÉô¤Î¤â¤Î¤ÏC¤ÎÂç°èÊÑ¿ô¤È¤·¤Æ¥¢¥¯¥» +¥¹¤Ç¤¤Þ¤¹¡¥¥í¡¼¥«¥ëÊÑ¿ô¤ò»²¾È¤¹¤ëÊýË¡¤Ï¸ø³«¤·¤Æ¤¤¤Þ¤»¤ó¡¥ + +¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤ò»²¾È¡¦¹¹¿·¤¹¤ë´Ø¿ô¤Ï°Ê²¼¤ÎÄÌ +¤ê¤Ç¤¹¡¥ + + VALUE rb_ivar_get(VALUE obj, ID id) + VALUE rb_ivar_get(VALUE obj, ID id, VALUE val) + +id¤Ïrb_intern()¤ÇÆÀ¤é¤ì¤ë¤â¤Î¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥ + +¥¯¥é¥¹Äê¿ô¤ò»²¾È¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥ + + VALUE rb_const_get(VALUE obj, ID id) + +¥¯¥é¥¹Äê¿ô¤ò¿·¤·¤¯ÄêµÁ¤¹¤ë¤¿¤á¤Ë¤Ï¡Ø2.1.3 Äê¿ôÄêµÁ¡Ù¤Ç¾Ò²ð¤µ +¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥ + +3¡¥ruby¤ÈC¤È¤Î¾ðÊó¶¦Í + +C¸À¸ì¤Èruby¤Î´Ö¤Ç¾ðÊó¤ò¶¦Í¤¹¤ëÊýË¡¤Ë¤Ä¤¤¤Æ²òÀ⤷¤Þ¤¹¡¥ + +3.1 C¤«¤é»²¾È¤Ç¤¤ëruby¤ÎÄê¿ô + +°Ê²¼¤Îruby¤ÎÄê¿ô¤ÏC¤Î¥ì¥Ù¥ë¤«¤é»²¾È¤Ç¤¤ë¡¥ + + TRUE + FALSE + +¿¿µ¶ÃÍ¡¥FALSE¤ÏC¸À¸ì¤Ç¤âµ¶¤È¤ß¤Ê¤µ¤ì¤ë¡¥ + + Qnil + +C¸À¸ì¤«¤é¸«¤¿¡Önil¡×¡¥ + +3.2 C¤Èruby¤Ç¶¦Í¤µ¤ì¤ëÂç°èÊÑ¿ô + +C¤Èruby¤ÇÂç°èÊÑ¿ô¤ò»È¤Ã¤Æ¾ðÊó¤ò¶¦Í¤Ç¤¤Þ¤¹¡¥¶¦Í¤Ç¤¤ëÂç°è +ÊÑ¿ô¤Ë¤Ï¤¤¤¯¤Ä¤«¤Î¼ïÎब¤¢¤ê¤Þ¤¹¡¥¤½¤Î¤Ê¤«¤Ç¤â¤Ã¤È¤âÎɤ¯»È¤ï +¤ì¤ë¤È»×¤ï¤ì¤ë¤Î¤Ïrb_define_variable()¤Ç¤¹¡¥ + + void rb_define_variable(char *name, VALUE *var) + +¤³¤Î´Ø¿ô¤Ïruby¤ÈC¤È¤Ç¶¦Í¤¹¤ëÂç°èÊÑ¿ô¤òÄêµÁ¤·¤Þ¤¹¡¥ÊÑ¿ô̾¤¬ +`$'¤Ç»Ï¤Þ¤é¤Ê¤¤»þ¤Ë¤Ï¼«Æ°Åª¤ËÄɲ䵤ì¤Þ¤¹¡¥¤³¤ÎÊÑ¿ô¤ÎÃͤòÊÑ +¹¹¤¹¤ë¤È¼«Æ°Åª¤Ëruby¤ÎÂбþ¤¹¤ëÊÑ¿ô¤ÎÃͤâÊѤï¤ê¤Þ¤¹¡¥ + +¤Þ¤¿ruby¦¤«¤é¤Ï¹¹¿·¤Ç¤¤Ê¤¤ÊÑ¿ô¤â¤¢¤ê¤Þ¤¹¡¥¤³¤Îread only¤Î +ÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤ÇÄêµÁ¤·¤Þ¤¹¡¥ + + void rb_define_readonly_variable(char *name, VALUE *var) + +¤³¤ì¤éÊÑ¿ô¤Î¾¤Ëhook¤ò¤Ä¤±¤¿Âç°èÊÑ¿ô¤òÄêµÁ¤Ç¤¤Þ¤¹¡¥hookÉÕ¤ +¤ÎÂç°èÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤òÍѤ¤¤ÆÄêµÁ¤·¤Þ¤¹¡¥ + + void rb_define_hooked_variable(char *name, VALUE *var, + VALUE (*getter)(), VALUE (*setter)()) + +¤³¤Î´Ø¿ô¤ÏC¤Î´Ø¿ô¤Ë¤è¤Ã¤Æhook¤Î¤Ä¤±¤é¤ì¤¿Âç°èÊÑ¿ô¤òÄêµÁ¤·¤Þ +¤¹¡¥ÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ï´Ø¿ôgetter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì +¤¿»þ¤Ë¤Ï´Ø¿ôsetter¤¬¸Æ¤Ð¤ì¤Þ¤¹¡¥hook¤ò»ØÄꤷ¤Ê¤¤¾ì¹ç¤Ïgetter +¤äsetter¤Ë0¤ò»ØÄꤷ¤Æ¤¯¤À¤µ¤¤¡¥ + +# getter¤âsetter¤â0¤Ê¤é¤Ðrb_define_variable()¤ÈƱ¤¸Æ¯¤¤ò¤· +# ¤Þ¤¹¡¥ + +¤½¤ì¤«¤é¡¤C¤Î´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ëruby¤ÎÂç°èÊÑ¿ô¤òÄêµÁ¤¹¤ë +´Ø¿ô¤¬¤¢¤ê¤Þ¤¹¡¥ + + void rb_define_virtual_variable(char *name, + VALUE (*getter)(), VALUE (*setter)()) + +¤³¤Î´Ø¿ô¤Ë¤è¤Ã¤ÆÄêµÁ¤µ¤ì¤¿ruby¤ÎÂç°èÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ï +getter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter¤¬¸Æ¤Ð¤ì¤Þ¤¹¡¥ + +3.3 C¤Î¥Ç¡¼¥¿¤òruby¥ª¥Ö¥¸¥§¥¯¥È¤Ë¤¹¤ë + +C¤ÎÀ¤³¦¤ÇÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿(¹½Â¤ÂÎ)¤òruby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ +¼è¤ê°·¤¤¤¿¤¤¾ì¹ç¤¬¤¢¤ê¤¨¤Þ¤¹¡¥¤³¤Î¤è¤¦¤Ê¾ì¹ç¤Ë¤Ï¡¤Data¤È¤¤¤¦ +ruby¥ª¥Ö¥¸¥§¥¯¥È¤ËC¤Î¹½Â¤ÂÎ(¤Ø¤Î¥Ý¥¤¥ó¥¿)¤ò¤¯¤ë¤à¤³¤È¤Çruby +¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ¼è¤ê°·¤¨¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡¥ + +Data¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¤Æ¹½Â¤ÂΤòruby¥ª¥Ö¥¸¥§¥¯¥È¤Ë¥«¥×¥»¥ë +²½¤¹¤ë¤¿¤á¤Ë¤Ï¡¤°Ê²¼¤Î¥Þ¥¯¥í¤ò»È¤¤¤Þ¤¹¡¥ + + Make_Data_Struct(class, type, mark, free, sval) + +¤³¤³¤Çclass¤Ï¿·¤·¤¯À¸À®¤µ¤ì¤ë¥¤¥ó¥¹¥¿¥ó¥¹¤Î¥¯¥é¥¹¡¤¡¤type¤Ï +¥«¥×¥»¥ë²½¤¹¤ëC¤Î¥Ç¡¼¥¿¤Î·¿(¹½Â¤ÂÎ)¤Ç¤¹¡¥mark¤Ï¤³¤Î¹½Â¤ÂΤ¬ +ruby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ø¤Î»²¾È¤¬¤¢¤ë»þ¤Ë»È¤¦´Ø¿ô¤Ç¤¹¡¥¤½¤Î¤è¤¦¤Ê +»²¾È¤ò´Þ¤Þ¤Ê¤¤»þ¤Ë¤Ï0¤ò»ØÄꤷ¤Þ¤¹¡¥free¤Ï¤³¤Î¹½Â¤ÂΤ¬¤â¤¦ÉÔ +Íפˤʤä¿»þ¤Ë¸Æ¤Ð¤ì¤ë´Ø¿ô¤Ç¤¹¡¥¤³¤Î´Ø¿ô¤¬¥¬¡¼¥Ù¡¼¥¸¥³¥ì¥¯¥¿ +¤«¤é¸Æ¤Ð¤ì¤Þ¤¹¡¥sval¤Ïtype·¿¤ÎÊÑ¿ô¤Ç¡¤Make_Data_Struct¤ÎÃæ¤Ç +¥¢¥í¥±¡¼¥È¤µ¤ì¤Þ¤¹¡¥ + +¥Þ¥¯¥íMake_Data_Struct¤ÏData¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¤Æ¡¤¤½¤ì¤òÃÍ +¤È¤·¤ÆÊÖ¤·¤Þ¤¹¡¥ + +¤³¤Î¥Þ¥¯¥í¤ò¸Æ¤Ó½Ð¤¹¤Èsval¤Ë¹½Â¤ÂΤ¬malloc()¤µ¤ì¤ÆÂåÆþ¤µ¤ì¡¤ +¤«¤Ä¤½¤Î¹½Â¤ÂΤò¥«¥×¥»¥ë²½¤·¤¿Data¥ª¥Ö¥¸¥§¥¯¥È¤¬¥¤¥ó¥¹¥¿¥ó¥¹ +ÊÑ¿ô¤È¤·¤Æobj¤Ë¥»¥Ã¥È¤µ¤ì¤Þ¤¹¡¥ + +Data¥ª¥Ö¥¸¥§¥¯¥È¤«¤éC¥Ý¥¤¥ó¥¿¤ò¼è¤ê½Ð¤¹¤¿¤á¤Ë¤Ï°Ê²¼¤Î¥Þ¥¯¥í +¤ò»È¤¤¤Þ¤¹¡¥ + + Get_Data_Struct(obj, type, sval) + +Data¥ª¥Ö¥¸¥§¥¯¥È¤«¤étype·¿¤ÎC¥Ý¥¤¥ó¥¿¤ò¼è¤ê½Ð¤·¤Æ¡¤sval¤ËÂå +Æþ¤·¤Þ¤¹¡¥ + +¤³¤ì¤é¤ÎData¤Î»È¤¤Êý¤Ï¤Á¤ç¤Ã¤Èʬ¤«¤ê¤Ë¤¯¤¤¤Î¤Ç¡¤¸å¤ÇÀâÌÀ¤¹¤ë +ÎãÂê¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥ + +4¡¥ÎãÂê - dbm¥Ñ¥Ã¥±¡¼¥¸¤òºî¤ë + +¤³¤³¤Þ¤Ç¤ÎÀâÌÀ¤Ç¤È¤ê¤¢¤¨¤º³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ïºî¤ì¤ë¤Ï¤º¤Ç¤¹¡¥ +ruby¤Îext¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤¹¤Ç¤Ë´Þ¤Þ¤ì¤Æ¤¤¤ëdbm¥â¥¸¥å¡¼¥ë¤òÎã¤Ë +¤·¤ÆÃʳ¬Åª¤ËÀâÌÀ¤·¤Þ¤¹¡¥ + +(1) ¥Ç¥£¥ì¥¯¥È¥ê¤òºî¤ë + + % mkdir ext/dbm + +ruby¤òŸ³«¤·¤¿¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¡¤ext¥Ç¥£¥ì¥¯¥È¥ê¤ÎÃæ¤Ë³ÈÄ¥¥â +¥¸¥å¡¼¥ëÍѤΥǥ£¥ì¥¯¥È¥ê¤òºî¤ê¤Þ¤¹¡¥Ì¾Á°¤ÏŬÅö¤ËÁª¤ó¤Ç¹½¤¤¤Þ +¤»¤ó¡¥ + +(2) MANIFEST¥Õ¥¡¥¤¥ë¤òºî¤ë + + % cd ext/dbm + % touch MANIFEST + +³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¤Ë¤ÏMANIFEST¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬ +ɬÍפʤΤǡ¤¤È¤ê¤¢¤¨¤º¶õ¤Î¥Õ¥¡¥¤¥ë¤òºî¤Ã¤Æ¤ª¤¤Þ¤¹¡¥¸å¤Ç¤³¤Î +¥Õ¥¡¥¤¥ë¤Ë¤ÏɬÍפʥե¡¥¤¥ë°ìÍ÷¤¬Æþ¤ë¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥ + +MANIFEST¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤Ï¡¤make¤Î»þ¤Ë¥Ç¥£¥ì¥¯¥È¥ê¤¬³ÈÄ¥¥â¥¸¥å¡¼ +¥ë¤ò´Þ¤ó¤Ç¤¤¤ë¤«¤É¤¦¤«È½Äꤹ¤ë¤¿¤á¤Ë»È¤ï¤ì¤ì¤Æ¤¤¤Þ¤¹¡¥ + +(3) À߷פ¹¤ë + +¤Þ¤¢¡¤ÅöÁ³¤Ê¤ó¤Ç¤¹¤±¤É¡¤¤É¤¦¤¤¤¦µ¡Ç½¤ò¼Â¸½¤¹¤ë¤«¤É¤¦¤«¤Þ¤ºÀß +·×¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥¤É¤ó¤Ê¥¯¥é¥¹¤ò¤Ä¤¯¤ë¤«¡¤¤½¤Î¥¯¥é¥¹¤Ë¤Ï +¤É¤ó¤Ê¥á¥½¥Ã¥É¤¬¤¢¤ë¤«¡¤¥¯¥é¥¹¤¬Ä󶡤¹¤ëÄê¿ô¤Ê¤É¤Ë¤Ä¤¤¤ÆÀß·× +¤·¤Þ¤¹¡¥dbm¥¯¥é¥¹¤Ë¤Ä¤¤¤Æ¤Ïext/dbm.doc¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥ + +(4) C¥³¡¼¥É¤ò½ñ¤¯ + +³ÈÄ¥¥â¥¸¥å¡¼¥ëËÜÂΤȤʤëC¸À¸ì¤Î¥½¡¼¥¹¤ò½ñ¤¤Þ¤¹¡¥C¸À¸ì¤Î¥½¡¼ +¥¹¤¬¤Ò¤È¤Ä¤Î»þ¤Ë¤Ï¡Ö¥â¥¸¥å¡¼¥ë̾.c¡×¤òÁª¤Ö¤ÈÎɤ¤¤Ç¤·¤ç¤¦¡¥C +¸À¸ì¤Î¥½¡¼¥¹¤¬Ê£¿ô¤Î¾ì¹ç¤Ë¤ÏµÕ¤Ë¡Ö¥â¥¸¥å¡¼¥ë̾.c¡×¤È¤¤¤¦¥Õ¥¡ +¥¤¥ë̾¤ÏÈò¤±¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥¥ª¥Ö¥¸¥§¥¯¥È¥Õ¥¡¥¤¥ë¤È¥â¥¸¥å¡¼ +¥ëÀ¸À®»þ¤ËÃæ´ÖŪ¤ËÀ¸À®¤µ¤ì¤ë¡Ö¥â¥¸¥å¡¼¥ë̾.o¡×¤È¤¤¤¦¥Õ¥¡¥¤¥ë +¤È¤¬¾×ÆÍ¤¹¤ë¤«¤é¤Ç¤¹¡¥ + +ruby¤Ï³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ò¥í¡¼¥É¤¹¤ë»þ¤Ë¡ÖInit_¥â¥¸¥å¡¼¥ë̾¡×¤È +¤¤¤¦´Ø¿ô¤ò¼«Æ°Åª¤Ë¼Â¹Ô¤·¤Þ¤¹¡¥dbm¥â¥¸¥å¡¼¥ë¤Î¾ì¹ç¡ÖInit_dbm¡× +¤Ç¤¹¡¥¤³¤Î´Ø¿ô¤ÎÃæ¤Ç¥¯¥é¥¹¡¤¥â¥¸¥å¡¼¥ë¡¤¥á¥½¥Ã¥É¡¤Äê¿ô¤Ê¤É¤Î +ÄêµÁ¤ò¹Ô¤¤¤Þ¤¹¡¥dbm.c¤«¤é°ìÉô°úÍѤ·¤Þ¤¹¡¥ + +-- +Init_dbm() +{ + /* DBM¥¯¥é¥¹¤òÄêµÁ¤¹¤ë */ + cDBM = rb_define_class("DBM", cObject); + /* DBM¤ÏEnumerate¥â¥¸¥å¡¼¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë */ + rb_include_module(cDBM, mEnumerable); + + /* DBM¥¯¥é¥¹¤Î¥¯¥é¥¹¥á¥½¥Ã¥Éopen(): °ú¿ô¤ÏC¤ÎÇÛÎó¤Ç¼õ¤±¤ë */ + rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1); + + /* DBM¥¯¥é¥¹¤Î¥á¥½¥Ã¥Éclose(): °ú¿ô¤Ï¤Ê¤· */ + rb_define_method(cDBM, "close", fdbm_close, 0); + /* DBM¥¯¥é¥¹¤Î¥á¥½¥Ã¥É[]: °ú¿ô¤Ï1¸Ä */ + rb_define_method(cDBM, "[]", fdbm_fetch, 1); + : +} +-- + +DBM¥â¥¸¥å¡¼¥ë¤Ïdbm¤Î¥Ç¡¼¥¿¤ÈÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤Ë¤Ê¤ë¤Ï¤º¤Ç +¤¹¤«¤é¡¤C¤ÎÀ¤³¦¤Îdbm¤òruby¤ÎÀ¤³¦¤Ë¼è¤ê¹þ¤àɬÍפ¬¤¢¤ê¤Þ¤¹¡¥ + +dbm.c¤Ç¤ÏDBM¤Î¥Ç¡¼¥¿¤ò³ÊǼ¤¹¤ë¤¿¤á¤Ë°Ê²¼¤Î¤è¤¦¤Ê¹½Â¤ÂΤò»È¤Ã +¤Æ¤¤¤Þ¤¹¡¥ + +struct dbmdata { + int di_size; + DBM *di_dbm; +}; + +Ruby¤ÎDBM¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤¹¤ë¤¿¤á¤Ë¤Ï°Ê²¼¤Î¤è¤¦¤Ê¥³¡¼¥É¤ò +»È¤Ã¤Æ¤¤¤Þ¤¹¡¥ + + obj = Make_Data_Struct(class,struct dbmdata,0,free_dbm,dbmp); + dbmp->di_dbm = dbm; + dbmp->di_size = -1; + +DBM¥ª¥Ö¥¸¥§¥¯¥È¤«¤éC¤ÎDBM¥Ý¥¤¥ó¥¿¤ò¼è¤ê½Ð¤¹¤¿¤á¤Ë¤Ï°Ê²¼¤Î¤è +¤¦¤Ê¥Þ¥¯¥í¤ò»È¤Ã¤Æ¤¤¤Þ¤¹¡¥ + +#define GetDBM(obj, dbmp) {\ + Get_Data_Struct(obj, struct dbmdata, dbmp);\ + if (dbmp->di_dbm == 0) closeddbm();\ +} + +DBM¥¯¥é¥¹¤Ë¤Ï¤¿¤¯¤µ¤ó¥á¥½¥Ã¥É¤¬¤¢¤ê¤Þ¤¹¤¬¡¤Ê¬Îह¤ë¤È3¼ïÎà¤Î +°ú¿ô¤Î¼õ¤±Êý¤¬¤¢¤ê¤Þ¤¹¡¥¤Ò¤È¤Ä¤Ï°ú¿ô¤Î¿ô¤¬¸ÇÄê¤Î¤â¤Î¤Ç¡¤Îã¤È +¤·¤Æ¤Ïdelete¥á¥½¥Ã¥É¤¬¤¢¤ê¤Þ¤¹¡¥delete¥á¥½¥Ã¥É¤ò¼ÂÁõ¤·¤Æ¤¤¤ë +fdbm_delete()¤Ï¤³¤Î¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥ + +-- +static VALUE +fdbm_delete(obj, keystr) + VALUE obj, keystr; +{ + : +} +-- + +°ú¿ô¤Î¿ô¤¬¸ÇÄê¤Î¥¿¥¤¥×¤ÏÂè1°ú¿ô¤¬self¡¤Âè2°ú¿ô°Ê¹ß¤¬¥á¥½¥Ã¥É +¤Î°ú¿ô¤È¤Ê¤ê¤Þ¤¹¡¥ + +°ú¿ô¤Î¿ô¤¬ÉÔÄê¤Î¤â¤Î¤ÏC¤ÎÇÛÎó¤Ç¼õ¤±¤ë¤â¤Î¤Èruby¤ÎÇÛÎó¤Ç¼õ¤± +¤ë¤â¤Î¤È¤¬¤¢¤ê¤Þ¤¹¡¥dbm¥â¥¸¥å¡¼¥ë¤ÎÃæ¤Ç¡¤C¤ÎÇÛÎó¤Ç¼õ¤±¤ë¤â¤Î +¤ÏDBM¤Î¥¯¥é¥¹¥á¥½¥Ã¥É¤Ç¤¢¤ëopen()¤Ç¤¹¡¥¤³¤ì¤ò¼ÂÁõ¤·¤Æ¤¤¤ë´Ø +¿ôfdbm_s_open()¤Ï¤³¤¦¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥ + +-- +static VALUE +fdbm_s_open(argc, argv, class) + int argc; + VALUE *argv; + VALUE class; +{ + : + if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) { + mode = 0666; /* default value */ + } + : +} +-- + +¤³¤Î¥¿¥¤¥×¤Î´Ø¿ô¤ÏÂè1°ú¿ô¤¬Í¿¤¨¤é¤ì¤¿°ú¿ô¤Î¿ô¡¤Âè2°ú¿ô¤¬Í¿¤¨ +¤é¤ì¤¿°ú¿ô¤ÎÆþ¤Ã¤Æ¤¤¤ëÇÛÎó¤Ë¤Ê¤ê¤Þ¤¹¡¥self¤ÏÂè3°ú¿ô¤È¤·¤ÆÍ¿ +¤¨¤é¤ì¤Þ¤¹¡¥ + +¤³¤ÎÇÛÎó¤ÇÍ¿¤¨¤é¤ì¤¿°ú¿ô¤ò²òÀϤ¹¤ë¤¿¤á¤Î´Ø¿ô¤¬open()¤Ç¤â»È¤ï +¤ì¤Æ¤¤¤ërb_scan_args()¤Ç¤¹¡¥Âè3°ú¿ô¤Ë»ØÄꤷ¤¿¥Õ¥©¡¼¥Þ¥Ã¥È¤Ë +½¾¤¤¡¤Âè4ÊÑ¿ô°Ê¹ß¤Ë»ØÄꤷ¤¿ÊÑ¿ô¤ËÃͤòÂåÆþ¤·¤Æ¤¯¤ì¤Þ¤¹¡¥¤³¤Î +¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¡¤Âè1ʸ»úÌܤ¬¾Êά¤Ç¤¤Ê¤¤°ú¿ô¤Î¿ô¡¤Âè2ʸ»úÌܤ¬ +¾Êά¤Ç¤¤ë°ú¿ô¤Î¿ô¡¤Âè3ʸ»úÌܤ¬Âбþ¤¹¤ëÁê¼ê¤¬Ìµ¤¤¤¢¤Þ¤ê¤Î°ú +¿ô¤¬¤¢¤ë¤«¤É¤¦¤«¤ò¼¨¤¹"*"¤Ç¤¹¡¥2ʸ»úÌܤÈ3ʸ»úÌܤϾÊά¤Ç¤¤Þ +¤¹¡¥dbm.c¤ÎÎã¤Ç¤Ï¡¤¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï"11"¤Ç¤¹¤«¤é¡¤°ú¿ô¤ÏºÇÄã1¤Ä +¤Ç¡¤2¤Ä¤Þ¤Çµö¤µ¤ì¤ë¤È¤¤¤¦°ÕÌ£¤Ë¤Ê¤ê¤Þ¤¹¡¥¾Êά¤µ¤ì¤Æ¤¤¤ë»þ¤Î +ÊÑ¿ô¤ÎÃͤÏnil(C¸À¸ì¤Î¥ì¥Ù¥ë¤Ç¤ÏQnil)¤Ë¤Ê¤ê¤Þ¤¹¡¥ + +ruby¤ÎÇÛÎó¤Ç°ú¿ô¤ò¼õ¤±¼è¤ë¤â¤Î¤Ïindexes¤¬¤¢¤ê¤Þ¤¹¡¥¼ÂÁõ¤Ï¤³ +¤¦¤Ç¤¹¡¥ + +-- +static VALUE +fdbm_indexes(obj, args) + VALUE obj; + struct RArray *args; +{ + : +} +-- + +Âè1°ú¿ô¤Ïself¡¤Âè2°ú¿ô¤Ïruby¤ÎÇÛÎó¤Ç¤¹¡¥¤³¤³¤Ç¤Ï¥¥ã¥¹¥È¤ò¸º +¤é¤¹¤¿¤á struct RArray* ¤Ç¼õ¤±¤Æ¤¤¤Þ¤¹¤¬¡¤VALUE¤Ç¤âƱ¤¸¤³¤È +¤Ç¤¹¡¥ + +** Ãí°Õ»ö¹à + +ruby¤È¶¦Í¤Ï¤·¤Ê¤¤¤¬ruby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤ò³ÊǼ¤¹¤ë²ÄǽÀ¤Î¤¢¤ë +C¤ÎÂç°èÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤Æruby¥¤¥ó¥¿¥×¥ê¥¿¤ËÊÑ¿ô¤Î¸ºß +¤ò¶µ¤¨¤Æ¤¢¤²¤Æ¤¯¤À¤µ¤¤¡¥¤Ç¤Ê¤¤¤ÈGC¤Ç¥È¥é¥Ö¥ë¤òµ¯¤³¤¹²ÄǽÀ¤¬ +¤¢¤ê¤Þ¤¹¡¥ + + void rb_global_variable(VALUE *var) + +(5) extconf.rb¤òÍѰդ¹¤ë + +¤â¤·¥Ç¥£¥ì¥¯¥È¥ê¤Ë¡Öextconf.rb¡×¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ì¤Ð¡¤ +make»þ¤Ë¼Â¹Ô¤µ¤ì¤Þ¤¹¡¥¤Ê¤±¤ì¤ÐŬÅö¤ËMakefile¤¬À¸À®¤µ¤ì¤Þ¤¹¡¥ + +extconf.rb¤Ï¥â¥¸¥å¡¼¥ë¤Î¥³¥ó¥Ñ¥¤¥ë¤ËɬÍפʾò·ï¤Î¥Á¥§¥Ã¥¯¤Ê¤É +¤ò¹Ô¤¦¤³¤È¤¬ÌÜŪ¤Ç¤¹¡¥extconf.rb¤ÎÃæ¤Ç¤Ï°Ê²¼¤Îruby´Ø¿ô¤ò»È¤¦ +¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥ + + have_library(lib, func): ¥é¥¤¥Ö¥é¥ê¤Î¸ºß¥Á¥§¥Ã¥¯ + have_func(func): ´Ø¿ô¤Î¸ºß¥Á¥§¥Ã¥¯ + have_header(header): ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤Î¸ºß¥Á¥§¥Ã¥¯ + create_makefile(target): Makefile¤ÎÀ¸À® + +¥â¥¸¥å¡¼¥ë¤ò¥³¥ó¥Ñ¥¤¥ë¤¹¤ë¾ò·ï¤¬Â·¤ï¤Ê¤º¡¤¤½¤Î¥â¥¸¥å¡¼¥ë¤Ï¥³ +¥ó¥Ñ¥¤¥ë¤·¤Ê¤¤»þ¤Ë¤Ïcreate_makefile¤ò¸Æ¤Ð¤Ê¤±¤ì¤ÐÎɤ¤¡¥ + +(6) depend¤òÍѰդ¹¤ë + +¤â¤·¡¤¥Ç¥£¥ì¥¯¥È¥ê¤Ëdepend¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ì¤Ð¡¤ +Makefile¤¬°Í¸´Ø·¸¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤¯¤ì¤Þ¤¹¡¥ + + % gcc -MM *.c > depend + +¤Ê¤É¤Çºî¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥¤¢¤Ã¤ÆÂ»¤Ï̵¤¤¤Ç¤·¤ç¤¦¡¥ + +(7) MANIFEST¥Õ¥¡¥¤¥ë¤Ë¥Õ¥¡¥¤¥ë̾¤òÆþ¤ì¤ë + + % ls > MANIFEST + % vi MANIFEST + +*.o, *~¤Ê¤ÉÉÔɬÍפʥե¡¥¤¥ë°Ê³°¤ÏMANIFEST¤ËÄɲ䷤Ƥª¤¤Þ¤¹¡¥ +make»þ¤Ë¤ÏMANIFEST¤ÎÆâÍÆ¤Ï»²¾È¤·¤Þ¤»¤ó¤Î¤Ç¡¤¶õ¤Î¤Þ¤Þ¤Ç¤âÌäÂê +¤Ïµ¯¤¤Ê¤¤¤ó¤Ç¤¹¤±¤É¡¤¥Ñ¥Ã¥±¡¼¥¸¥ó¥°¤Î»þ¤Ë»²¾È¤¹¤ë¤³¤È¤¬¤¢¤ë +¤·¡¤É¬Íפʥե¡¥¤¥ë¤ò¶èÊ̤Ǥ¤ë¤ó¤Ç¡¤ÍѰդ·¤Æ¤ª¤¤¤¿Êý¤¬Îɤ¤¤Ç +¤·¤ç¤¦¡¥ + +(8) make¤¹¤ë + +ruby¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Çmake¤ò¼Â¹Ô¤¹¤ë¤ÈMakefile¤òÀ¸À®¤·¤Æ¤¯¤ì¤Þ +¤¹¡¥°ìÅÙMakefile¤¬À¸À®¤µ¤ì¤ì¤Ð³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Î +Ãæ¤Çmake¤¹¤ë¤³¤È¤¬¤Ç¤¤Þ¤¹¡¥extconf.rb¤ò½ñ¤´¹¤¨¤ë¤Ê¤É¤·¤Æ +Makefile¤ÎºÆÀ¸À®¤¬É¬Íפʻþ¤Ï¤Þ¤¿ruby¥Ç¥£¥ì¥¯¥È¥ê¤Çmake¤·¤Æ¤¯ +¤À¤µ¤¤¡¥ + +(9) ¥Ç¥Ð¥Ã¥° + +¤Þ¤¢¡¤¥Ç¥Ð¥Ã¥°¤·¤Ê¤¤¤Èư¤«¤Ê¤¤¤Ç¤·¤ç¤¦¤Í¡¥ext/Setup¤Ë¥Ç¥£¥ì +¥¯¥È¥ê̾¤ò½ñ¤¯¤ÈÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë¤Î¤Ç¥Ç¥Ð¥Ã¥¬¤¬»È¤¨¤ë¤è¤¦¤Ë¤Ê +¤ê¤Þ¤¹¡¥¤½¤Îʬ¥³¥ó¥Ñ¥¤¥ë¤¬ÃÙ¤¯¤Ê¤ê¤Þ¤¹¤±¤É¡¥ + +(10) ¤Ç¤¤¢¤¬¤ê + +¸å¤Ï¤³¤Ã¤½¤ê»È¤¦¤Ê¤ê¡¤¹¤¯¸ø³«¤¹¤ë¤Ê¤ê¡¤Çä¤ë¤Ê¤ê¡¤¤´¼«Í³¤Ë¤ª +»È¤¤¤¯¤À¤µ¤¤¡¥ruby¤Îºî¼Ô¤Ï³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë´Ø¤·¤Æ°ìÀڤθ¢Íø¤ò +¼çÄ¥¤·¤Þ¤»¤ó¡¥ + +Appendix A. ruby¤Î¥½¡¼¥¹¥³¡¼¥É¤ÎʬÎà + +ruby¤Î¥½¡¼¥¹¤Ï¤¤¤¯¤Ä¤«¤ËʬÎह¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥¤³¤Î¤¦¤Á¥¯¥é +¥¹¥é¥¤¥Ö¥é¥ê¤ÎÉôʬ¤Ï´ðËÜŪ¤Ë³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ÈƱ¤¸ºî¤êÊý¤Ë¤Ê¤Ã +¤Æ¤¤¤Þ¤¹¡¥¤³¤ì¤é¤Î¥½¡¼¥¹¤Ïº£¤Þ¤Ç¤ÎÀâÌÀ¤Ç¤Û¤È¤ó¤ÉÍý²ò¤Ç¤¤ë¤È +»×¤¤¤Þ¤¹¡¥ + +ruby¸À¸ì¤Î¥³¥¢ + + class.c + error.c + eval.c + gc.c + object.c + parse.y + variable.c + +¥æ¡¼¥Æ¥£¥ê¥Æ¥£´Ø¿ô + + dln.c + fnmatch.c + glob.c + regex.c + st.c + util.c + +ruby¥³¥Þ¥ó¥É¤Î¼ÂÁõ + + dmyext.c + inits.c + main.c + ruby.c + version.c + +¥¯¥é¥¹¥é¥¤¥Ö¥é¥ê + + array.c + bignum.c + compar.c + dir.c + enum.c + file.c + hash.c + io.c + math.c + numeric.c + pack.c + process.c + random.c + range.c + re.c + signal.c + sprintf.c + string.c + struct.c + time.c + +Appendix B. ³ÈÄ¥ÍÑ´Ø¿ô¥ê¥Õ¥¡¥ì¥ó¥¹ + +C¸À¸ì¤«¤éruby¤Îµ¡Ç½¤òÍøÍѤ¹¤ëAPI¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥ ** ·¿ VALUE - Ruby¥ª¥Ö¥¸¥§¥¯¥È¤òɽ¸½¤¹¤ë·¿¡¥É¬Íפ˱þ¤¸¤Æ¥¥ã¥¹¥È¤·¤ÆÍѤ¤¤ë¡¥ÁÈ¤ß - ¹þ¤ß·¿¤òɽ¸½¤¹¤ëC¤Î·¿¤Ïruby.h¤Ëµ½Ò¤·¤Æ¤¢¤ëR¤Ç»Ï¤Þ¤ë¹½Â¤ÂΤǤ¢¤ë¡¥ - VALUE·¿¤ò¤³¤ì¤é¤Ë¥¥ã¥¹¥È¤¹¤ë¤¿¤á¤ËR¤Ç»Ï¤Þ¤ë¹½Â¤ÂÎ̾¤òÁ´¤ÆÂçʸ»ú¤Ë - ¤·¤¿Ì¾Á°¤Î¥Þ¥¯¥í¤¬ÍѰդµ¤ì¤Æ¤¤¤ë¡¥ +ruby¥ª¥Ö¥¸¥§¥¯¥È¤òɽ¸½¤¹¤ë·¿¡¥É¬Íפ˱þ¤¸¤Æ¥¥ã¥¹¥È¤·¤ÆÍѤ¤¤ë¡¥ +ÁȤ߹þ¤ß·¿¤òɽ¸½¤¹¤ëC¤Î·¿¤Ïruby.h¤Ëµ½Ò¤·¤Æ¤¢¤ëR¤Ç»Ï¤Þ¤ë¹½Â¤ +ÂΤǤ¢¤ë¡¥VALUE·¿¤ò¤³¤ì¤é¤Ë¥¥ã¥¹¥È¤¹¤ë¤¿¤á¤ËR¤Ç»Ï¤Þ¤ë¹½Â¤ÂÎ +̾¤òÁ´¤ÆÂçʸ»ú¤Ë¤·¤¿Ì¾Á°¤Î¥Þ¥¯¥í¤¬ÍѰդµ¤ì¤Æ¤¤¤ë¡¥ ** ÊÑ¿ô¡¦Äê¿ô Qnil - Äê¿ô: nil¥ª¥Ö¥¸¥§¥¯¥È - - Qself - - ÊÑ¿ô: ¸½ºß¤Îself¥ª¥Ö¥¸¥§¥¯¥È¤ÎÃÍ¡¥°ìÈ̤˥᥽¥Ã¥É¤Ë¤Ïself¤ò»Ø¤¹°ú¿ô - ¤¬Í¿¤¨¤é¤ì¤ë¤Î¤Ç, ¤³¤ÎÊÑ¿ô¤Ë¥¢¥¯¥»¥¹¤¹¤ëɬÍפϤʤ¤¡¥¤³¤ÎÊÑ¿ô¤ÎÃͤò - Êѹ¹¤¹¤ë»þ¤Ï°Ê¸å¤Îself¤ÎÃͤ½¤Î¤â¤Î¤¬ÊѤï¤Ã¤Æ¤·¤Þ¤¦¤Î¤Ç, ÆÃÊ̤ʻö¾ð - ¤¬¤Ê¤¤¸Â¤êÂåÆþ¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡¥ +Äê¿ô: nil¥ª¥Ö¥¸¥§¥¯¥È TRUE - Äê¿ô: t¥ª¥Ö¥¸¥§¥¯¥È(¿¿¤Î¥Ç¥Õ¥©¥ë¥ÈÃÍ) +Äê¿ô: TRUE¥ª¥Ö¥¸¥§¥¯¥È(¿¿¤Î¥Ç¥Õ¥©¥ë¥ÈÃÍ) FALSE - Äê¿ô: nil¥ª¥Ö¥¸¥§¥¯¥È +Äê¿ô: FALSE¥ª¥Ö¥¸¥§¥¯¥È ** C¥Ç¡¼¥¿¤Î¥«¥×¥»¥ë²½ VALUE data_new(void *sval, void (*mark)(), void (*free)()) - C¤ÎǤ°Õ¤Î¥Ý¥¤¥ó¥¿¤ò¥«¥×¥»¥ë²½¤·¤¿ruby¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡¥¤³¤Î¥Ý¥¤¥ó - ¥¿¤¬ruby¤«¤é¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¯¤Ê¤Ã¤¿»þ¡¤free¤Ç»ØÄꤷ¤¿´Ø¿ô¤¬¸Æ¤Ð¤ì¤ë¡¥ - ¤Þ¤¿¡¤¤³¤Î¥Ý¥¤¥ó¥¿¤Î»Ø¤¹¥Ç¡¼¥¿¤¬Â¾¤Îruby¥ª¥Ö¥¸¥§¥¯¥È¤ò»Ø¤·¤Æ¤¤¤ë¾ì - ¹ç¡¤mark¤Ë»ØÄꤹ¤ë´Ø¿ô¤Ç¥Þ¡¼¥¯¤¹¤ëɬÍפ¬¤¢¤ë¡¥ +C¤ÎǤ°Õ¤Î¥Ý¥¤¥ó¥¿¤ò¥«¥×¥»¥ë²½¤·¤¿ruby¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡¥¤³ +¤Î¥Ý¥¤¥ó¥¿¤¬ruby¤«¤é¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¯¤Ê¤Ã¤¿»þ¡¤free¤Ç»ØÄꤷ¤¿ +´Ø¿ô¤¬¸Æ¤Ð¤ì¤ë¡¥¤Þ¤¿¡¤¤³¤Î¥Ý¥¤¥ó¥¿¤Î»Ø¤¹¥Ç¡¼¥¿¤¬Â¾¤Îruby¥ª¥Ö +¥¸¥§¥¯¥È¤ò»Ø¤·¤Æ¤¤¤ë¾ì¹ç¡¤mark¤Ë»ØÄꤹ¤ë´Ø¿ô¤Ç¥Þ¡¼¥¯¤¹¤ëɬÍ× +¤¬¤¢¤ë¡¥ Make_Data_Struct(obj, iv, type, mark, free, sval) - type·¿¤Î¥á¥â¥ê¤òmalloc¤·¡¤ÊÑ¿ôsval¤ËÂåÆþ¤·¤¿¸å¡¤¤½¤ì¤ò¥«¥×¥»¥ë²½¤· - ¤¿¥Ç¡¼¥¿¤òobj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ôiv¤ËÂåÆþ¤¹¤ë¥Þ¥¯¥í¡¥ +type·¿¤Î¥á¥â¥ê¤òmalloc¤·¡¤ÊÑ¿ôsval¤ËÂåÆþ¤·¤¿¸å¡¤¤½¤ì¤ò¥«¥×¥» +¥ë²½¤·¤¿¥Ç¡¼¥¿¤òobj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ôiv¤ËÂåÆþ¤¹¤ë¥Þ¥¯¥í¡¥ Get_Data_Struct(obj, iv, type, sval) - obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ôiv¤¬»Ø¤¹¥Ç¡¼¥¿¤«¤étype·¿¤Î¥Ý¥¤¥ó¥¿¤ò¼è¤ê½Ð¤· - ÊÑ¿ôsval¤ËÂåÆþ¤¹¤ë¥Þ¥¯¥í¡¥ +obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ôiv¤¬»Ø¤¹¥Ç¡¼¥¿¤«¤étype·¿¤Î¥Ý¥¤¥ó¥¿¤ò¼è +¤ê½Ð¤·ÊÑ¿ôsval¤ËÂåÆþ¤¹¤ë¥Þ¥¯¥í¡¥ ** ¥¯¥é¥¹/¥â¥¸¥å¡¼¥ëÄêµÁ VALUE rb_define_class(char *name, VALUE super) - super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤Ruby¥¯¥é¥¹¤òÄêµÁ¤¹¤ë¡¥ +super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤ruby¥¯¥é¥¹¤òÄêµÁ¤¹¤ë¡¥ + + VALUE rb_define_class_under(VALUE module, char *name, VALUE super) + +super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤ruby¥¯¥é¥¹¤òÄêµÁ¤·¡¤module¤ÎÄê +¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥ VALUE rb_define_module(char *name) - ¿·¤·¤¤Ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¡¥ +¿·¤·¤¤ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¡¥ + + VALUE rb_define_module_under(VALUE module, char *name, VALUE super) + +¿·¤·¤¤ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤·¡¤module¤ÎÄê¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥ void rb_include_module(VALUE class, VALUE module) - ¥â¥¸¥å¡¼¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë¡¥class¤¬¤¹¤Ç¤Ëmodule¤ò¥¤¥ó¥¯¥ë¡¼¥É¤·¤Æ - ¤¤¤ë»þ¤Ë¤Ï²¿¤â¤·¤Ê¤¤(¿½Å¥¤¥ó¥¯¥ë¡¼¥É¤Î¶Ø»ß)¡¥ +¥â¥¸¥å¡¼¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë¡¥class¤¬¤¹¤Ç¤Ëmodule¤ò¥¤¥ó¥¯¥ë¡¼ +¥É¤·¤Æ¤¤¤ë»þ¤Ë¤Ï²¿¤â¤·¤Ê¤¤(¿½Å¥¤¥ó¥¯¥ë¡¼¥É¤Î¶Ø»ß)¡¥ void rb_extend_object(VALUE object, VALUE module) - ¥ª¥Ö¥¸¥§¥¯¥È¤ò¥â¥¸¥å¡¼¥ë(¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¥á¥½¥Ã¥É)¤Ç³ÈÄ¥¤¹¤ë¡¥ +¥ª¥Ö¥¸¥§¥¯¥È¤ò¥â¥¸¥å¡¼¥ë(¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¥á¥½¥Ã¥É)¤Ç³ÈÄ¥¤¹¤ë¡¥ ** Âç°èÊÑ¿ôÄêµÁ void rb_define_variable(char *name, VALUE *var) - Ruby¤ÈC¤È¤Ç¶¦Í¤¹¤ë¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô̾¤¬`$'¤Ç»Ï¤Þ¤é¤Ê - ¤¤»þ¤Ë¤Ï¼«Æ°Åª¤ËÄɲ䵤ì¤ë¡¥name¤È¤·¤Æruby¤Î¼±Ê̻ҤȤ·¤Æµö¤µ¤ì¤Ê¤¤ - ʸ»ú(Î㤨¤Ð` ')¤ò´Þ¤à¾ì¹ç¤Ë¤Ïruby¥×¥í¥°¥é¥à¤«¤é¤Ï¸«¤¨¤Ê¤¯¤Ê¤ë¡¥ +ruby¤ÈC¤È¤Ç¶¦Í¤¹¤ë¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô̾¤¬`$'¤Ç»Ï +¤Þ¤é¤Ê¤¤»þ¤Ë¤Ï¼«Æ°Åª¤ËÄɲ䵤ì¤ë¡¥name¤È¤·¤Æruby¤Î¼±Ê̻ҤȤ· +¤Æµö¤µ¤ì¤Ê¤¤Ê¸»ú(Î㤨¤Ð` ')¤ò´Þ¤à¾ì¹ç¤Ë¤Ïruby¥×¥í¥°¥é¥à¤«¤é +¤Ï¸«¤¨¤Ê¤¯¤Ê¤ë¡¥ void rb_define_readonly_variable(char *name, VALUE *var) - Ruby¤ÈC¤È¤Ç¶¦Í¤¹¤ëread only¤Î¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥read only¤Ç - ¤¢¤ë¤³¤È°Ê³°¤Ïrb_define_variable()¤ÈƱ¤¸¡¥ +ruby¤ÈC¤È¤Ç¶¦Í¤¹¤ëread only¤Î¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥read +only¤Ç¤¢¤ë¤³¤È°Ê³°¤Ïrb_define_variable()¤ÈƱ¤¸¡¥ void rb_define_virtual_variable(char *name, VALUE (*getter)(), VALUE (*setter)()) - ´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ëRubyÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ï - getter¤¬¡¤´Ø¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter¤¬¸Æ¤Ð¤ì¤ë¡¥ +´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ërubyÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ +¤Ë¤Ïgetter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter¤¬¸Æ¤Ð¤ì¤ë¡¥ void rb_define_hooked_variable(char *name, VALUE *var, VALUE (*getter)(), VALUE (*setter)()) - ´Ø¿ô¤Ë¤è¤Ã¤Æhook¤Î¤Ä¤±¤é¤ì¤¿¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô¤¬»²¾È¤µ - ¤ì¤¿»þ¤Ë¤Ïgetter¤¬¡¤´Ø¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter¤¬¸Æ¤Ð¤ì¤ë¡¥ - getter¤äsetter¤Ë0¤ò»ØÄꤷ¤¿»þ¤Ë¤Ïhook¤ò»ØÄꤷ¤Ê¤¤¤Î¤ÈƱ¤¸»ö¤Ë¤Ê¤ë¡¥ +´Ø¿ô¤Ë¤è¤Ã¤Æhook¤Î¤Ä¤±¤é¤ì¤¿¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô¤¬ +»²¾È¤µ¤ì¤¿»þ¤Ë¤Ïgetter¤¬¡¤´Ø¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter +¤¬¸Æ¤Ð¤ì¤ë¡¥getter¤äsetter¤Ë0¤ò»ØÄꤷ¤¿»þ¤Ë¤Ïhook¤ò»ØÄꤷ¤Ê +¤¤¤Î¤ÈƱ¤¸»ö¤Ë¤Ê¤ë¡¥ void rb_global_variable(VALUE *var) - GC¤Î¤¿¤á¡¤Ruby¥×¥í¥°¥é¥à¤«¤é¤Ï¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¤¤¬, Ruby¥ª¥Ö¥¸¥§¥¯¥È - ¤ò´Þ¤àÂç°èÊÑ¿ô¤ò¥Þ¡¼¥¯¤¹¤ë¡¥ +GC¤Î¤¿¤á¡¤ruby¥×¥í¥°¥é¥à¤«¤é¤Ï¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¤¤¬, ruby¥ª¥Ö¥¸¥§ +¥¯¥È¤ò´Þ¤àÂç°èÊÑ¿ô¤ò¥Þ¡¼¥¯¤¹¤ë¡¥ ** ¥¯¥é¥¹Äê¿ô void rb_define_const(VALUE class, char *name, VALUE val) - ¥¯¥é¥¹Äê¿ô¤òÄêµÁ¤¹¤ë¡¥ +¥¯¥é¥¹Äê¿ô¤òÄêµÁ¤¹¤ë¡¥ + + void rb_define_global_const(char *name, VALUE val) + +Âç°èÄê¿ô¤òÄêµÁ¤¹¤ë¡¥ + + rb_define_const(cKernal, name, val) + +¤ÈƱ¤¸°ÕÌ£¡¥ ** ¥á¥½¥Ã¥ÉÄêµÁ rb_define_method(VALUE class, char *name, VALUE (*func)(), int argc) - ¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥argc¤Ïself¤ò½ü¤¯°ú¿ô¤Î¿ô¡¥argc¤¬-1¤Î»þ, ´Ø¿ô¤Ë - ¤Ï°ú¿ô¤Î¿ô(self¤ò´Þ¤Þ¤Ê¤¤)¤òÂè1°ú¿ô, °ú¿ô¤ÎÇÛÎó¤òÂè2°ú¿ô¤È¤¹¤ë·Á¼° - ¤ÇÍ¿¤¨¤é¤ì¤ë(Âè3°ú¿ô¤Ïself)¡¥argc¤¬-2¤Î»þ, °ú¿ô¤Ïself, args(args¤Ï - °ú¿ô¤ò´Þ¤àruby¤ÎÇÛÎó)¤È¤¤¤¦·Á¼°¤ÇÍ¿¤¨¤é¤ì¤ë¡¥ +¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥argc¤Ïself¤ò½ü¤¯°ú¿ô¤Î¿ô¡¥argc¤¬-1¤Î»þ, +´Ø¿ô¤Ë¤Ï°ú¿ô¤Î¿ô(self¤ò´Þ¤Þ¤Ê¤¤)¤òÂè1°ú¿ô, °ú¿ô¤ÎÇÛÎó¤òÂè2°ú +¿ô¤È¤¹¤ë·Á¼°¤ÇÍ¿¤¨¤é¤ì¤ë(Âè3°ú¿ô¤Ïself)¡¥argc¤¬-2¤Î»þ, Âè1°ú +¿ô¤¬self, Âè2°ú¿ô¤¬args(args¤Ï°ú¿ô¤ò´Þ¤àruby¤ÎÇÛÎó)¤È¤¤¤¦·Á +¼°¤ÇÍ¿¤¨¤é¤ì¤ë¡¥ rb_define_private_method(VALUE class, char *name, VALUE (*func)(), int argc) - private¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¡¥ +private¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¡¥ rb_define_singleton_method(VALUE class, char *name, VALUE (*func)(), int argc) - ÆÃ°Û¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¡¥ +ÆÃ°Û¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¡¥ rb_scan_args(int atgc, VALUE *argv, char *fmt, ...) - argc,argv·Á¼°¤ÇÍ¿¤¨¤é¤ì¤¿°ú¿ô¤òʬ²ò¤¹¤ë¡¥fmt¤Ïɬ¿Ü°ú¿ô¤Î¿ô, Éղðú - ¿ô¤Î¿ô, »Ä¤ê¤Î°ú¿ô¤¬¤¢¤ë¤«¤ò»ØÄꤹ¤ëʸ»úÎó¤Ç, "¿ô»ú¿ô»ú*"¤È¤¤¤¦·Á¼° - ¤Ç¤¢¤ë¡¥ 2 ÈÖÌܤοô»ú¤È"*"¤Ï¤½¤ì¤¾¤ì¾Êά²Äǽ¤Ç¤¢¤ë¡¥É¬¿Ü°ú¿ô¤¬°ì¤Ä - ¤â¤Ê¤¤¾ì¹ç¤Ï0¤ò»ØÄꤹ¤ë¡¥Âè3°ú¿ô°Ê¹ß¤ÏÊÑ¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç, ³ºÅö¤¹¤ë - Í×ÁǤ¬¤½¤ÎÊÑ¿ô¤Ë³ÊǼ¤µ¤ì¤ë¡¥Éղðú¿ô¤ËÂбþ¤¹¤ë°ú¿ô¤¬Í¿¤¨¤é¤ì¤Æ¤¤¤Ê - ¤¤¾ì¹ç¤ÏÊÑ¿ô¤ËQnil¤¬ÂåÆþ¤µ¤ì¤ë¡¥ +argc,argv·Á¼°¤ÇÍ¿¤¨¤é¤ì¤¿°ú¿ô¤òʬ²ò¤¹¤ë¡¥fmt¤Ïɬ¿Ü°ú¿ô¤Î¿ô, +Éղðú¿ô¤Î¿ô, »Ä¤ê¤Î°ú¿ô¤¬¤¢¤ë¤«¤ò»ØÄꤹ¤ëʸ»úÎó¤Ç, "¿ô»ú¿ô +»ú*"¤È¤¤¤¦·Á¼°¤Ç¤¢¤ë¡¥ 2 ÈÖÌܤοô»ú¤È"*"¤Ï¤½¤ì¤¾¤ì¾Êά²Äǽ¤Ç +¤¢¤ë¡¥É¬¿Ü°ú¿ô¤¬°ì¤Ä¤â¤Ê¤¤¾ì¹ç¤Ï0¤ò»ØÄꤹ¤ë¡¥Âè3°ú¿ô°Ê¹ß¤ÏÊÑ +¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç, ³ºÅö¤¹¤ëÍ×ÁǤ¬¤½¤ÎÊÑ¿ô¤Ë³ÊǼ¤µ¤ì¤ë¡¥Éղðú +¿ô¤ËÂбþ¤¹¤ë°ú¿ô¤¬Í¿¤¨¤é¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤ÏÊÑ¿ô¤ËQnil¤¬ÂåÆþ¤µ¤ì +¤ë¡¥ -** Ruby¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤· +** ruby¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤· VALUE rb_funcall(VALUE recv, ID mid, int narg, ...) - ¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·¡¥Ê¸»úÎ󤫤émid¤òÆÀ¤ë¤¿¤á¤Ë¤Ïrb_intern()¤ò»È¤¦¡¥ +¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·¡¥Ê¸»úÎ󤫤émid¤òÆÀ¤ë¤¿¤á¤Ë¤Ïrb_intern()¤ò»È¤¦¡¥ VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv) - ¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·¡¥°ú¿ô¤òargc,argv·Á¼°¤ÇÅϤ¹¡¥ +¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·¡¥°ú¿ô¤òargc,argv·Á¼°¤ÇÅϤ¹¡¥ VALUE rb_eval_string(char *str) - ʸ»úÎó¤òruby¤È¥¹¥¯¥ê¥×¥È¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¡¦¼Â¹Ô¤¹¤ë¡¥ +ʸ»úÎó¤òruby¤È¥¹¥¯¥ê¥×¥È¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¡¦¼Â¹Ô¤¹¤ë¡¥ ID rb_intern(char *name) - ʸ»úÎó¤ËÂбþ¤¹¤ëID¤òÊÖ¤¹¡¥ +ʸ»úÎó¤ËÂбþ¤¹¤ëID¤òÊÖ¤¹¡¥ char *rb_id2name(ID id) - ID¤ËÂбþ¤¹¤ëʸ»úÎó¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥ +ID¤ËÂбþ¤¹¤ëʸ»úÎó¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥ char *rb_class2name(VALUE class) - class¤Î̾Á°¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥class¤¬Ì¾Á°¤ò»ý¤¿¤Ê¤¤»þ¤Ë¤Ï, °ìÈÖ¶á - ¤¤Ì¾Á°¤ò»ý¤Ä¥¯¥é¥¹¤Î̾Á°¤òÊÖ¤¹¡¥ +class¤Î̾Á°¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥class¤¬Ì¾Á°¤ò»ý¤¿¤Ê¤¤»þ¤Ë¤Ï, +ÁÄÀè¤òÁ̤äÆÌ¾Á°¤ò»ý¤Ä¥¯¥é¥¹¤Î̾Á°¤òÊÖ¤¹¡¥ ** ¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô VALUE rb_iv_get(VALUE obj, char *name) - obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤ÎÃͤòÆÀ¤ë¡¥`@'¤Ç»Ï¤Þ¤é¤Ê¤¤¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤Ï - Ruby¥×¥í¥°¥é¥à¤«¤é¥¢¥¯¥»¥¹¤Ç¤¤Ê¤¤¡Ö±£¤ì¤¿¡×¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤Ë¤Ê¤ë¡¥ +obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤ÎÃͤòÆÀ¤ë¡¥`@'¤Ç»Ï¤Þ¤é¤Ê¤¤¥¤¥ó¥¹¥¿¥ó¥¹ +ÊÑ¿ô¤Ï ruby¥×¥í¥°¥é¥à¤«¤é¥¢¥¯¥»¥¹¤Ç¤¤Ê¤¤¡Ö±£¤ì¤¿¡×¥¤¥ó¥¹¥¿ +¥ó¥¹ÊÑ¿ô¤Ë¤Ê¤ë¡¥ VALUE rb_iv_set(VALUE obj, char *name, VALUE val) - obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤òval¤Ë¥»¥Ã¥È¤¹¤ë¡¥ +obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤òval¤Ë¥»¥Ã¥È¤¹¤ë¡¥ ** À©¸æ¹½Â¤ VALUE rb_iterate(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2) - func2¤ò¥Ö¥í¥Ã¥¯¤È¤·¤ÆÀßÄꤷ, func1¤ò¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ö¡¥ func1¤Ë - ¤Ï arg1¤¬°ú¿ô¤È¤·¤ÆÅϤµ¤ì, func2¤Ë¤ÏÂè1°ú¿ô¤Ë¥¤¥Æ¥ì¡¼¥¿¤«¤éÍ¿¤¨¤é¤ì - ¤¿ÃÍ, Âè2°ú¿ô¤Ëarg2¤¬ÅϤµ¤ì¤ë¡¥ +func2¤ò¥Ö¥í¥Ã¥¯¤È¤·¤ÆÀßÄꤷ, func1¤ò¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ö¡¥ +func1¤Ë¤Ï arg1¤¬°ú¿ô¤È¤·¤ÆÅϤµ¤ì, func2¤Ë¤ÏÂè1°ú¿ô¤Ë¥¤¥Æ¥ì¡¼ +¥¿¤«¤éÍ¿¤¨¤é¤ì¤¿ÃÍ, Âè2°ú¿ô¤Ëarg2¤¬ÅϤµ¤ì¤ë¡¥ VALUE rb_yield(VALUE val) - val¤òÃͤȤ·¤Æ¥¤¥Æ¥ì¡¼¥¿¥Ö¥í¥Ã¥¯¤ò¸Æ¤Ó½Ð¤¹¡¥ +val¤òÃͤȤ·¤Æ¥¤¥Æ¥ì¡¼¥¿¥Ö¥í¥Ã¥¯¤ò¸Æ¤Ó½Ð¤¹¡¥ VALUE rb_rescue(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2) - ´Ø¿ôfunc1¤òarg1¤ò°ú¿ô¤Ë¸Æ¤Ó½Ð¤¹¡¥func1¤Î¼Â¹ÔÃæ¤ËÎã³°¤¬È¯À¸¤·¤¿»þ¤Ë - ¤Ï func2¤òarg2¤ò°ú¿ô¤È¤·¤Æ¸Æ¤Ö¡¥Ìá¤êÃͤÏÎã³°¤¬È¯À¸¤·¤Ê¤«¤Ã¤¿»þ¤Ï - func1¤ÎÌá¤êÃÍ, Îã³°¤¬È¯À¸¤·¤¿»þ¤Ë¤Ïfunc2¤ÎÌá¤êÃͤǤ¢¤ë¡¥ +´Ø¿ôfunc1¤òarg1¤ò°ú¿ô¤Ë¸Æ¤Ó½Ð¤¹¡¥func1¤Î¼Â¹ÔÃæ¤ËÎã³°¤¬È¯À¸¤· +¤¿»þ¤Ë¤Ï func2¤òarg2¤ò°ú¿ô¤È¤·¤Æ¸Æ¤Ö¡¥Ìá¤êÃͤÏÎã³°¤¬È¯À¸¤·¤Ê +¤«¤Ã¤¿»þ¤Ïfunc1¤ÎÌá¤êÃÍ, Îã³°¤¬È¯À¸¤·¤¿»þ¤Ë¤Ïfunc2¤ÎÌá¤êÃÍ¤Ç +¤¢¤ë¡¥ VALUE rb_ensure(VALUE (*func1)(), void *arg1, void (*func2)(), void *arg2) - ´Ø¿ôfunc1¤òarg1¤ò°ú¿ô¤È¤·¤Æ¼Â¹Ô¤·, ¼Â¹Ô½ªÎ»¸å(¤¿¤È¤¨Îã³°¤¬È¯À¸¤·¤Æ - ¤â) func2¤òarg2¤ò°ú¿ô¤È¤·¤Æ¼Â¹Ô¤¹¤ë¡¥Ìá¤êÃͤÏfunc1¤ÎÌá¤êÃͤǤ¢¤ë(Îã - ³°¤¬È¯À¸¤·¤¿»þ¤ÏÌá¤é¤Ê¤¤)¡¥ +´Ø¿ôfunc1¤òarg1¤ò°ú¿ô¤È¤·¤Æ¼Â¹Ô¤·, ¼Â¹Ô½ªÎ»¸å(¤¿¤È¤¨Îã³°¤¬È¯ +À¸¤·¤Æ¤â) func2¤òarg2¤ò°ú¿ô¤È¤·¤Æ¼Â¹Ô¤¹¤ë¡¥Ìá¤êÃͤÏfunc1¤ÎÌá +¤êÃͤǤ¢¤ë(Îã³°¤¬È¯À¸¤·¤¿»þ¤ÏÌá¤é¤Ê¤¤)¡¥ ** Îã³°¡¦¥¨¥é¡¼ void Warning(char *fmt, ...) - verbose»þ¤Ëɸ½à¥¨¥é¡¼½ÐÎϤ˷ٹð¾ðÊó¤òɽ¼¨¤¹¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥ +verbose»þ¤Ëɸ½à¥¨¥é¡¼½ÐÎϤ˷ٹð¾ðÊó¤òɽ¼¨¤¹¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥ void Fail(char *fmt, ...) - Îã³°¤òȯÀ¸¤µ¤»¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥ +Îã³°¤òȯÀ¸¤µ¤»¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥ void Fatal(char *fmt, ...) - Ã×̿ŪÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥Ä̾ï¤ÎÎã³°½èÍý¤Ï¹Ô¤Ê¤ï¤ì¤º, ¥¤¥ó¥¿¡¼¥×¥ê¥¿ - ¤¬½ªÎ»¤¹¤ë(¤¿¤À¤·ensure¤Ç»ØÄꤵ¤ì¤¿¥³¡¼¥É¤Ï½ªÎ»Á°¤Ë¼Â¹Ô¤µ¤ì¤ë)¡¥ +Ã×̿ŪÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥Ä̾ï¤ÎÎã³°½èÍý¤Ï¹Ô¤Ê¤ï¤ì¤º, ¥¤¥ó¥¿¡¼ +¥×¥ê¥¿¤¬½ªÎ»¤¹¤ë(¤¿¤À¤·ensure¤Ç»ØÄꤵ¤ì¤¿¥³¡¼¥É¤Ï½ªÎ»Á°¤Ë¼Â +¹Ô¤µ¤ì¤ë)¡¥ void Bug(char *fmt, ...) - ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ê¤É¥×¥í¥°¥é¥à¤Î¥Ð¥°¤Ç¤·¤«È¯À¸¤¹¤ë¤Ï¤º¤Î¤Ê¤¤¾õ¶·¤Î»þ - ¸Æ¤Ö¡¥¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ï¥³¥¢¥À¥ó¥×¤·Ä¾¤Á¤Ë½ªÎ»¤¹¤ë¡¥Îã³°½èÍý¤Ï°ìÀÚ¹Ô - ¤Ê¤ï¤ì¤Ê¤¤¡¥ +¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ê¤É¥×¥í¥°¥é¥à¤Î¥Ð¥°¤Ç¤·¤«È¯À¸¤¹¤ë¤Ï¤º¤Î¤Ê¤¤¾õ +¶·¤Î»þ¸Æ¤Ö¡¥¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ï¥³¥¢¥À¥ó¥×¤·Ä¾¤Á¤Ë½ªÎ»¤¹¤ë¡¥Îã³° +½èÍý¤Ï°ìÀڹԤʤï¤ì¤Ê¤¤¡¥ ** ruby¤Î½é´ü²½¡¦¼Â¹Ô -Ruby¤ò¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤ËËä¤á¹þ¤à¾ì¹ç¤Ë¤Ï°Ê²¼¤Î¥¤¥ó¥¿¥Õ¥§¡¼¥¹¤ò»È¤¦¡¥ÄÌ -¾ï¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë¤ÏɬÍפʤ¤¡¥ +ruby¤ò¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤ËËä¤á¹þ¤à¾ì¹ç¤Ë¤Ï°Ê²¼¤Î¥¤¥ó¥¿¥Õ¥§¡¼¥¹ +¤ò»È¤¦¡¥Ä̾ï¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë¤ÏɬÍפʤ¤¡¥ void ruby_init(int argc, char **argv, char **envp) - ruby¥¤¥ó¥¿¥×¥ê¥¿¤Î½é´ü²½¤ò¹Ô¤Ê¤¦¡¥ +ruby¥¤¥ó¥¿¥×¥ê¥¿¤Î½é´ü²½¤ò¹Ô¤Ê¤¦¡¥ void ruby_run() - ruby¥¤¥ó¥¿¥×¥ê¥¿¤ò¼Â¹Ô¤¹¤ë¡¥ +ruby¥¤¥ó¥¿¥×¥ê¥¿¤ò¼Â¹Ô¤¹¤ë¡¥ void ruby_script(char *name) - ruby¤Î¥¹¥¯¥ê¥×¥È̾($0)¤òÀßÄꤹ¤ë¡¥ +ruby¤Î¥¹¥¯¥ê¥×¥È̾($0)¤òÀßÄꤹ¤ë¡¥ -* extconf.rb¤Îµ½Ò +Appendix B. extconf.rb¤Ç»È¤¨¤ë´Ø¿ô¤¿¤Á -³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ë`extconf.rb'¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ë»þ¤Ë -¤Ï¡¤¤½¤ì¤¬¼Â¹Ô¤µ¤ì¡¤¥â¥¸¥å¡¼¥ë¤Î¥³¥ó¥Ñ¥¤¥ë¤ËɬÍפʾò·ï¤Î¥Á¥§¥Ã¥¯¤Ê¤É¤ò -¹Ô¤¦»ö¤¬½ÐÍè¤ë¡¥extconf.rb¤ÎÃæ¤Ç¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤¦»ö¤¬¤Ç¤¤ë¡¥ +extconf.rb¤ÎÃæ¤Ç¤ÏÍøÍѲÄǽ¤Ê¥³¥ó¥Ñ¥¤¥ë¾ò·ï¥Á¥§¥Ã¥¯¤Î´Ø¿ô¤Ï°Ê +²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥ have_library(lib, func) - ´Ø¿ôfunc¤òÄêµÁ¤·¤Æ¤¤¤ë¥é¥¤¥Ö¥é¥êlib¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥é¥¤¥Ö¥é¥ê - ¤¬Â¸ºß¤¹¤ë»þ¡¤TRUE¤òÊÖ¤¹¡¥ +´Ø¿ôfunc¤òÄêµÁ¤·¤Æ¤¤¤ë¥é¥¤¥Ö¥é¥êlib¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥é +¥¤¥Ö¥é¥ê¤¬Â¸ºß¤¹¤ë»þ¡¤TRUE¤òÊÖ¤¹¡¥ have_func(func) - ´Ø¿ôfunc¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥func¤¬É¸½à¤Ç¤Ï¥ê¥ó¥¯¤µ¤ì¤Ê¤¤¥é¥¤¥Ö¥é - ¥êÆâ¤Î¤â¤Î¤Ç¤¢¤ë»þ¤Ë¤ÏÀè¤Ëhave_library¤Ç¤½¤Î¥é¥¤¥Ö¥é¥ê¤ò¥Á¥§¥Ã¥¯¤· - ¤Æ¤ª¤¯»ö¡¥´Ø¿ô¤¬Â¸ºß¤¹¤ë»þ¡¤TRUE¤òÊÖ¤¹¡¥ +´Ø¿ôfunc¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥func¤¬É¸½à¤Ç¤Ï¥ê¥ó¥¯¤µ¤ì¤Ê¤¤¥é +¥¤¥Ö¥é¥êÆâ¤Î¤â¤Î¤Ç¤¢¤ë»þ¤Ë¤ÏÀè¤Ëhave_library¤Ç¤½¤Î¥é¥¤¥Ö¥é¥ê +¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤ª¤¯»ö¡¥´Ø¿ô¤¬Â¸ºß¤¹¤ë»þTRUE¤òÊÖ¤¹¡¥ have_header(header) - ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ë»þTRUE - ¤òÊÖ¤¹¡¥ +¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ë +»þTRUE¤òÊÖ¤¹¡¥ create_makefile(target) - ³ÈÄ¥¥â¥¸¥å¡¼¥ëÍѤÎMakefile¤òÀ¸À®¤¹¤ë¡¥¤³¤Î´Ø¿ô¤ò¸Æ¤Ð¤Ê¤±¤ì¤Ð¤½¤Î¥â - ¥¸¥å¡¼¥ë¤Ï¥³¥ó¥Ñ¥¤¥ë¤µ¤ì¤Ê¤¤¡¥ +³ÈÄ¥¥â¥¸¥å¡¼¥ëÍѤÎMakefile¤òÀ¸À®¤¹¤ë¡¥¤³¤Î´Ø¿ô¤ò¸Æ¤Ð¤Ê¤±¤ì¤Ð +¤½¤Î¥â¥¸¥å¡¼¥ë¤Ï¥³¥ó¥Ñ¥¤¥ë¤µ¤ì¤Ê¤¤¡¥target¤Ï¥â¥¸¥å¡¼¥ë̾¤òɽ +¤¹¡¥ /* * Local variables: - * fill-column: 70 + * fill-column: 60 * end: */ diff --git a/README.jp b/README.jp new file mode 100644 index 0000000000..06c0832b10 --- /dev/null +++ b/README.jp @@ -0,0 +1,159 @@ +* Ruby¤È¤Ï + +Ruby¤Ï¥·¥ó¥×¥ë¤«¤Ä¶¯ÎϤʥª¥Ö¥¸¥§¥¯¥È»Ø¸þ¥¹¥¯¥ê¥×¥È¸À¸ì¤Ç¤¹¡¥ +Ruby¤ÏºÇ½é¤«¤é½ã¿è¤Ê¥ª¥Ö¥¸¥§¥¯¥È»Ø¸þ¸À¸ì¤È¤·¤ÆÀ߷פµ¤ì¤Æ¤¤¤Þ +¤¹¤«¤é¡¤¥ª¥Ö¥¸¥§¥¯¥È»Ø¸þ¥×¥í¥°¥é¥ß¥ó¥°¤ò¼ê·Ú¤Ë¹Ô¤¦»ö¤¬½ÐÍè¤Þ +¤¹¡¥¤â¤Á¤í¤óÄ̾ï¤Î¼ê³¤·¿¤Î¥×¥í¥°¥é¥ß¥ó¥°¤â²Äǽ¤Ç¤¹¡¥ + +Ruby¤Ï¥Æ¥¥¹¥È½èÍý´Ø·¸¤ÎǽÎϤʤɤËÍ¥¤ì¡¤perl¤ÈƱ¤¸¤¯¤é¤¤¶¯ÎÏ +¤Ç¤¹¡¥¤µ¤é¤Ë¥·¥ó¥×¥ë¤Êʸˡ¤È¡¤Îã³°½èÍý¤ä¥¤¥Æ¥ì¡¼¥¿¤Ê¤É¤Îµ¡¹½ +¤Ë¤è¤Ã¤Æ¡¤¤è¤êʬ¤«¤ê¤ä¤¹¤¤¥×¥í¥°¥é¥ß¥ó¥°¤¬½ÐÍè¤Þ¤¹¡¥ + +* Ruby¤ÎÆÃĹ¡¥ + + + ¥·¥ó¥×¥ë¤Êʸˡ + + ÉáÄ̤Υª¥Ö¥¸¥§¥¯¥È»Ø¸þµ¡Ç½(¥¯¥é¥¹¡¤¥á¥½¥Ã¥É¥³¡¼¥ë¤Ê¤É) + + ÆÃ¼ì¤Ê¥ª¥Ö¥¸¥§¥¯¥È»Ø¸þµ¡Ç½(Mixin, ÆÃ°Û¥á¥½¥Ã¥É¤Ê¤É) + + ±é»»»Ò¥ª¡¼¥Ð¡¼¥í¡¼¥É + + Îã³°½èÍýµ¡Ç½ + + ¥¤¥Æ¥ì¡¼¥¿¤È¥¯¥í¡¼¥¸¥ã + + ¥¬¡¼¥Ù¡¼¥¸¥³¥ì¥¯¥¿ + + ¥À¥¤¥Ê¥ß¥Ã¥¯¥í¡¼¥Ç¥£¥ó¥° (¥¢¡¼¥¥Æ¥¯¥Á¥ã¤Ë¤è¤ë) + + °Ü¿¢À¤¬¹â¤¤¡¥Â¿¤¯¤ÎUNIX¾å¤Çư¤¯ + +* Æþ¼êË¡ + +** ftp¤Ç + +°Ê²¼¤Î¾ì½ê¤Ë¤ª¤¤¤Æ¤¢¤ê¤Þ¤¹¡¥ + + ftp://ftp.caelum.co.jp/pub/lang/ruby/ + +** ¥á¥¤¥ë¤Ç + +°Ê²¼¤Î¥¢¥É¥ì¥¹¤Ë`send'¤È¤¤¤¦Subject¤Î¥á¥¤¥ë¤òÁ÷¤Ã¤Æ²¼¤µ¤¤¡¥ + + ruby-archive@caelum.co.jp + +ËÜʸ¤Ë¤Ï²¿¤ò½ñ¤¤¤Æ¤â¹½¤¤¤Þ¤»¤ó¡¥ÀÞ¤êÊÖ¤·¡¤ºÇ¿·ÈǤÎruby¤¬Á÷¤Ã +¤ÆÍè¤Þ¤¹¡¥ + +* ¥Û¡¼¥à¥Ú¡¼¥¸ + + Ruby¤Î¥Û¡¼¥à¥Ú¡¼¥¸¤ÎURL¤Ï + + http://www.caelum.co.jp/~matz/ruby/ + + ¤Ç¤¹¡¥ + +* ¥á¥¤¥ê¥ó¥°¥ê¥¹¥È + + Ruby¤Ë´Ø¤ï¤ëÏÃÂê¤Î¤¿¤á¤Î¥á¥¤¥ê¥ó¥°¥ê¥¹¥È¤ò³«Àߤ·¤Þ¤·¤¿¡¥¥¢ + ¥É¥ì¥¹¤Ï + + ruby-list@caelum.co.jp + + ¤Ç¤¹¡¥¤³¤Î¥¢¥É¥ì¥¹¤Ë¥á¥¤¥ë¤òÁ÷¤ì¤Ð¡¤¼«Æ°Åª¤ËÅÐÏ¿¤µ¤ì¤Þ¤¹¡¥ + +* ¥³¥ó¥Ñ¥¤¥ë¡¦¥¤¥ó¥¹¥È¡¼¥ë + +°Ê²¼¤Î¼ê½ç¤Ç¹Ô¤Ã¤Æ¤¯¤À¤µ¤¤¡¥ + + 1. configure¤ò¼Â¹Ô¤·¤ÆMakefile¤Ê¤É¤òÀ¸À®¤¹¤ë + + 2. (ɬÍפʤé¤Ð)defines.h¤òÊÔ½¸¤¹¤ë + + ¿ʬ¡¤É¬Í×̵¤¤¤È»×¤¤¤Þ¤¹¡¥ + + 3. (ɬÍפʤé¤Ð)ext/Setup¤ËÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ò + »ØÄꤹ¤ë + + ext/Setup¤Ëµ½Ò¤·¤¿¥â¥¸¥å¡¼¥ë¤ÏÀÅŪ¤Ë¥ê¥ó¥¯¤µ¤ì¤Þ¤¹¡¥ + + ¥À¥¤¥Ê¥ß¥Ã¥¯¥í¡¼¥Ç¥£¥ó¥°¤ò¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤Ê¤¤¥¢¡¼¥¥Æ¥¯ + ¥Á¥ã¤Ç¤ÏSetup¤Î1¹ÔÌܤΡÖoption nodynamic¡×¤È¤¤¤¦¹Ô¤Î¥³ + ¥á¥ó¥È¤ò³°¤¹É¬Íפ¬¤¢¤ê¤Þ¤¹¡¥¤Þ¤¿¡¤¤³¤Î¥¢¡¼¥¥Æ¥¯¥Á¥ã¤Ç + ³ÈÄ¥¥â¥¸¥å¡¼¥ë¤òÍøÍѤ¹¤ë¤¿¤á¤Ë¤Ï¡¤¤¢¤é¤«¤¸¤áÀÅŪ¤Ë¥ê¥ó + ¥¯¤·¤Æ¤ª¤¯É¬Íפ¬¤¢¤ê¤Þ¤¹¡¥ + + 4. make¤ò¼Â¹Ô¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¤¹¤ë + + 5. make test¤Ç¥Æ¥¹¥È¤ò¹Ô¤¦¡¥ + + ¡Ötest succeeded¡×¤Èɽ¼¨¤µ¤ì¤ì¤ÐÀ®¸ù¤Ç¤¹¡¥¤¿¤À¤·¥Æ¥¹¥È + ¤ËÀ®¸ù¤·¤Æ¤â´°àú¤À¤ÈÊݾڤµ¤ì¤Æ¤¤¤ëÌõ¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡¥ + + 6. make install + +¤â¤·¡¤¥³¥ó¥Ñ¥¤¥ë»þ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤¿¾ì¹ç¤Ë¤Ï¥¨¥é¡¼¤Î¥í¥°¤È¥Þ +¥·¥ó¡¤OS¤Î¼ïÎà¤ò´Þ¤à¤Ç¤¤ë¤À¤±¾Ü¤·¤¤¥ì¥Ý¡¼¥È¤òºî¼Ô¤ËÁ÷¤Ã¤Æ¤¯ +¤À¤µ¤ë¤È¾¤ÎÊý¤Î¤¿¤á¤Ë¤â¤Ê¤ê¤Þ¤¹¡¥ + +* °Ü¿¢ + +UNIX¤Ç¤¢¤ì¤Ðconfigure¤¬¤Û¤È¤ó¤É¤Îº¹°Û¤òµÛ¼ý¤·¤Æ¤¯¤ì¤ë¤Ï¤º¤Ç +¤¹¤¬¡¤»×¤ï¤Ì¸«Íî¤È¤·¤¬¤¢¤Ã¤¿¾ì¹ç(¤¢¤ë¤Ë°ã¤¤¤Ê¤¤)¡¤ºî¼Ô¤Ë¤½¤Î +¤³¤È¤ò¥ì¥Ý¡¼¥È¤¹¤ì¤Ð¡¤²ò·è¤Ç¤¤ë¤«¤âÃΤì¤Þ¤»¤ó¡¥ + +¥¢¡¼¥¯¥Æ¥¯¥Á¥ã¤Ë¤â¤Ã¤È¤â°Í¸¤¹¤ë¤Î¤ÏGCÉô¤Ç¤¹¡¥ruby¤ÎGC¤ÏÂÐ¾Ý +¤Î¥¢¡¼¥¥Æ¥¯¥Á¥ã¤¬setjmp()¤Ë¤è¤Ã¤ÆÁ´¤Æ¤Î¥ì¥¸¥¹¥¿¤ò jmp_buf¤Ë +³ÊǼ¤¹¤ë¤³¤È¤È¡¤jmp_buf¤È¥¹¥¿¥Ã¥¯¤¬32bit¥¢¥é¥¤¥ó¥á¥ó¥È¤µ¤ì¤Æ +¤¤¤ë¤³¤È¤ò²¾Äꤷ¤Æ¤¤¤Þ¤¹¡¥ÆÃ¤ËÁ°¼Ô¤¬À®Î©¤·¤Ê¤¤¾ì¹ç¤ÎÂбþ¤ÏÈó +¾ï¤Ëº¤Æñ¤Ç¤·¤ç¤¦¡¥¸å¼Ô¤Î²ò·è¤ÏÈæ³ÓŪ´Êñ¤Ç¡¤gc.c¤Ç¥¹¥¿¥Ã¥¯¤ò +¥Þ¡¼¥¯¤·¤Æ¤¤¤ëÉôʬ¤Ë¥¢¥é¥¤¥ó¥á¥ó¥È¤Î¥Ð¥¤¥È¿ô¤À¤±¤º¤é¤·¤Æ¥Þ¡¼ +¥¯¤¹¤ë¥³¡¼¥É¤òÄɲ乤ë¤À¤±¤ÇºÑ¤ß¤Þ¤¹¡¥¡Ödefined(THINK_C)¡×¤Ç +³ç¤é¤ì¤Æ¤¤¤ëÉôʬ¤ò»²¹Í¤Ë¤·¤Æ¤¯¤À¤µ¤¤ + +# ¼ÂºÝ¤Ë¤Ïruby¤ÏThink C¤Ç¤Ï¥³¥ó¥Ñ¥¤¥ë¤Ç¤¤Þ¤»¤ó¡¥ + +¥ì¥¸¥¹¥¿¥¦¥£¥ó¥É¥¦¤ò»ý¤ÄCPU¤Ç¤Ï¡¤¥ì¥¸¥¹¥¿¥¦¥£¥ó¥É¥¦¤ò¥¹¥¿¥Ã +¥¯¤Ë¥Õ¥é¥Ã¥·¥å¤¹¤ë¥¢¥»¥ó¥Ö¥é¥³¡¼¥É¤òÄɲ乤ëɬÍפ¬¤¢¤ë¤«¤âÃÎ +¤ì¤Þ¤»¤ó¡¥ + +* ÇÛÉÛ¾ò·ï + +ºî¼Ô¤Ï°Ê²¼¤Î¾ò·ï¤Î¤â¤È¤Ëruby¤òÇÛÉÛ¤·¤Þ¤¹¡¥ + + + ºÆÇÛÉÛ + + ÇÛÉÛ¤·¤¿¾õÂÖ¤ò°Ý»ý¤¹¤ë¸Â¤ê¼«Í³¤Ç¤¹¡¥Êѹ¹¤ò¹Ô¤Ã¤¿¤â¤Î¤òºÆ + ÇÛÉÛ¤¹¤ë¤³¤È¤ò´õ˾¤¹¤ë»þ¤Ë¤Ïºî¼Ô¤ËÏ¢Íí¤·¤Æ¤¯¤À¤µ¤¤¡¥ + + Êѹ¹¤ò¹Ô¤Ê¤ï¤Ê¤¤ruby¤ò¥³¥ó¥Ñ¥¤¥ë¤·¤¿¥Ð¥¤¥Ê¥ê¤ÎÇÛÉÛ¤Ï¶Ø»ß + ¤·¤Þ¤»¤ó¤¬¡¤¥Ð¥¤¥Ê¥ê¤ò¼õ¤±¼è¤Ã¤¿¿Í¤¬¥½¡¼¥¹¤òÆþ¼ê¤Ç¤¤ë¤è + ¤¦¤Ë¡¤¥½¡¼¥¹¤ÎÆþ¼êË¡¤òÌÀ¼¨¤·¤Æ¤¯¤À¤µ¤¤¡¥ + + + Êѹ¹ + + ºÆÇÛÉÛ¤ò¹Ô¤ï¤Ê¤¤¸Â¤ê¡¤¤¤¤«¤Ê¤ëÌÜŪ¤Ç¤¢¤ì¼«Í³¤Ç¤¹¡¥¤¿¤À¤·¡¤ + µ¡Ç½³ÈÄ¥¤ä¥Ð¥°½¤Àµ¤Ïºî¼Ô¤Ø¤Î¥Õ¥£¡¼¥É¥Ð¥Ã¥¯¤ò´üÂÔ¤·¤Þ¤¹ + (¤â¤Á¤í¤ó¶¯À©¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó)¡¥ + + + ¾¤Î¥×¥í¥°¥é¥à¤Ø¤Î°úÍÑ + + ¤¤¤«¤Ê¤ëÌÜŪ¤Ç¤¢¤ì¼«Í³¤Ç¤¹¡¥¤¿¤À¤·¡¤ruby¤Ë´Þ¤Þ¤ì¤ë¾¤Îºî + ¼Ô¤Ë¤è¤ë¥³¡¼¥É¤Ï¡¤¤½¤ì¤¾¤ì¤Îºî¼Ô¤Î°Õ¸þ¤Ë¤è¤ëÀ©¸Â¤¬²Ã¤¨¤é + ¤ì¤Þ¤¹¡¥¶ñÂÎŪ¤Ë¤Ïgc.c(°ìÉô)¡¤regex.[ch]¡¤fnmatch.[ch]¡¤ + glob.c, st.[ch]¤Èmissing¥Ç¥£¥ì¥¯¥È¥ê²¼¤Î¥Õ¥¡¥¤¥ë·²¤¬³ºÅö + ¤·¤Þ¤¹¡¥ + + + Ruby¥¹¥¯¥ê¥×¥È¤Î¸¢Íø + + Á´¤Æ¤Îruby¥¹¥¯¥ê¥×¥È¤Î¸¢Íø¤Ï¤½¤ì¤¾¤ì¤ÎÃøºî¼Ô¤Ë°¤·¤Þ¤¹¡¥ + ºî¼Ô¤Ï¤³¤ì¤é¤Ë´Ø¤·¤Æ°ìÀڤθ¢Íø¤ò¼çÄ¥¤·¤Þ¤»¤ó¡¥¤Þ¤¿ruby¤Ë + ÁȤ߹þ¤à¤¿¤á¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë´Ø¤·¤Æ¤âƱÍͤǤ¹¡¥ + + + ̵ÊÝ¾Ú + + Ruby¤Ï̵ÊݾڤǤ¹¡¥ºî¼Ô¤Ïruby¤ò¥µ¥Ý¡¼¥È¤¹¤ë°Õ»Ö¤Ï¤¢¤ê¤Þ¤¹ + ¤¬¡¤ruby¼«¿È¤Î¥Ð¥°¤¢¤ë¤¤¤Ïruby¥¹¥¯¥ê¥×¥È¤Î¥Ð¥°¤Ê¤É¤«¤éȯ + À¸¤¹¤ë¤¤¤«¤Ê¤ë»³²¤ËÂФ·¤Æ¤âÀÕǤ¤ò»ý¤Á¤Þ¤»¤ó¡¥ + +* Ãø¼Ô + +¥³¥á¥ó¥È¡¤¥Ð¥°¥ì¥Ý¡¼¥È¤½¤Î¾¤Ï matz@ruby.club.or.jp ¤Þ¤Ç¡¥ +------------------------------------------------------- +created at: Thu Aug 3 11:57:36 JST 1995 +Local variables: +mode: indented-text +end: @@ -1,9 +1,7 @@ -* threadÂбþ -* Hand written parser(recursive decent) -* ¥¯¥é¥¹¥é¥¤¥Ö¥é¥ê¤Î¸«Ä¾¤·(UNIX°Í¸¤ò¸º¤é¤¹) +* """..."""¤È%Q#...#¤Î¤É¤Á¤é¤ò»Ä¤¹¤«¡¤¤¢¤ë¤¤¤ÏξÊý³è¤«¤¹¤« +* ¥Ñ¥Ã¥±¡¼¥¸¤Þ¤¿¤ÏÂç°èÊÑ¿ô¤Î¥¢¥¯¥»¥¹À©¸æ * formatµ¡Ç½ * here document * perl¤Î¤è¤¦¤Êsetuid check * write debugger for ruby -* re-write regex code for speed -* byte code interpretor +* re-write regex code for speed and copyright @@ -6,7 +6,7 @@ $Date: 1995/01/10 10:42:18 $ created at: Fri Aug 6 09:46:12 JST 1993 - Copyright (C) 1993-1995 Yukihiro Matsumoto + Copyright (C) 1993-1996 Yukihiro Matsumoto ************************************************/ @@ -18,6 +18,16 @@ VALUE rb_to_a(); #define ARY_DEFAULT_SIZE 16 +void +memclear(mem, size) + VALUE *mem; + int size; +{ + while (size--) { + *mem++ = Qnil; + } +} + VALUE ary_new2(len) int len; @@ -29,8 +39,10 @@ ary_new2(len) ary->capa = len; if (len == 0) ary->ptr = 0; - else + else { ary->ptr = ALLOC_N(VALUE, len); + memclear(ary->ptr, len); + } return (VALUE)ary; } @@ -53,7 +65,7 @@ ary_new3(n, va_alist) int i; if (n < 0) { - Fail("Negative number of items(%d)", n); + IndexError("Negative number of items(%d)", n); } ary = (struct RArray*)ary_new2(n<ARY_DEFAULT_SIZE?ARY_DEFAULT_SIZE:n); @@ -96,15 +108,20 @@ assoc_new(car, cdr) } static VALUE -ary_s_new(class) +ary_s_new(argc, argv, class) + int argc; + VALUE *argv; VALUE class; { + VALUE size; NEWOBJ(ary, struct RArray); OBJSETUP(ary, class, T_ARRAY); + rb_scan_args(argc, argv, "01", &size); ary->len = 0; - ary->capa = ARY_DEFAULT_SIZE; - ary->ptr = ALLOC_N(VALUE, ARY_DEFAULT_SIZE); + ary->capa = NIL_P(size)?ARY_DEFAULT_SIZE:NUM2INT(size); + ary->ptr = ALLOC_N(VALUE, ary->capa); + memclear(ary->ptr, ary->capa); return (VALUE)ary; } @@ -138,7 +155,7 @@ astore(ary, idx, val) VALUE val; { if (idx < 0) { - Fail("negative index for array"); + IndexError("negative index for array"); } if (idx >= ary->capa) { @@ -146,7 +163,7 @@ astore(ary, idx, val) REALLOC_N(ary->ptr, VALUE, ary->capa); } if (idx > ary->len) { - MEMZERO(ary->ptr+ary->len, VALUE, idx-ary->len+1); + memclear(ary->ptr+ary->len, idx-ary->len+1); } if (idx >= ary->len) { @@ -165,11 +182,14 @@ ary_push(ary, item) } static VALUE -ary_append(ary, item) +ary_push_method(argc, argv, ary) + int argc; + VALUE *argv; struct RArray *ary; - VALUE item; { - astore(ary, ary->len, item); + while (argc--) { + astore(ary, ary->len, *argv++); + } return (VALUE)ary; } @@ -178,6 +198,10 @@ ary_pop(ary) struct RArray *ary; { if (ary->len == 0) return Qnil; + if (ary->len * 10 < ary->capa && ary->capa > ARY_DEFAULT_SIZE) { + ary->capa = ary->len * 2; + REALLOC_N(ary->ptr, VALUE, ary->capa); + } return ary->ptr[--ary->len]; } @@ -194,6 +218,10 @@ ary_shift(ary) /* sliding items */ MEMMOVE(ary->ptr, ary->ptr+1, VALUE, ary->len); + if (ary->len * 10 < ary->capa && ary->capa > ARY_DEFAULT_SIZE) { + ary->capa = ary->len * 2; + REALLOC_N(ary->ptr, VALUE, ary->capa); + } return top; } @@ -215,6 +243,18 @@ ary_unshift(ary, item) return ary->ptr[0] = item; } +static VALUE +ary_unshift_method(argc, argv, ary) + int argc; + VALUE *argv; + VALUE ary; +{ + while (argc--) { + ary_unshift(ary, argv[argc]); + } + return (VALUE)ary; +} + VALUE ary_entry(ary, offset) struct RArray *ary; @@ -244,10 +284,10 @@ ary_subseq(ary, beg, len) if (beg < 0) beg = 0; } if (len < 0) { - Fail("negative length for sub-array(size: %d)", ary->len); + IndexError("negative length %d", ary->len); } if (len == 0) { - return ary_new(); + return ary_new2(0); } if (beg + len > ary->len) { len = ary->len - beg; @@ -270,6 +310,10 @@ beg_len(range, begp, lenp, len) if (!range_beg_end(range, &beg, &end)) return FALSE; + if ((beg > 0 && end > 0 || beg < 0 && end < 0) && beg > end) { + IndexError("end smaller than beg [%d..%d]", beg, end); + } + if (beg < 0) { beg = len + beg; if (beg < 0) beg = 0; @@ -281,10 +325,10 @@ beg_len(range, begp, lenp, len) else { if (end < 0) { end = len + end; - if (end < 0) end = 0; + if (end < 0) end = -1; } - if (len < end) end = len; - if (beg < end) { + if (end > len) end = len; + if (beg > end) { *lenp = 0; } else { @@ -301,10 +345,9 @@ ary_aref(argc, argv, ary) struct RArray *ary; { VALUE arg1, arg2; + int beg, len; if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) { - int beg, len; - beg = NUM2INT(arg1); len = NUM2INT(arg2); if (len <= 0) { @@ -315,17 +358,17 @@ ary_aref(argc, argv, ary) /* special case - speeding up */ if (FIXNUM_P(arg1)) { - return ary_entry(ary, NUM2INT(arg1)); + return ary_entry(ary, FIX2INT(arg1)); } - - /* check if idx is Range */ - { - int beg, len; - + else { + /* check if idx is Range */ if (beg_len(arg1, &beg, &len, ary->len)) { return ary_subseq(ary, beg, len); } } + if (TYPE(arg1) == T_BIGNUM) { + IndexError("index too big"); + } return ary_entry(ary, NUM2INT(arg1)); } @@ -340,7 +383,7 @@ ary_index(ary, val) if (rb_equal(ary->ptr[i], val)) return INT2FIX(i); } - return Qnil; /* should be FALSE? */ + return Qnil; } static VALUE @@ -351,8 +394,8 @@ ary_indexes(ary, args) VALUE new_ary; int i = 0; - if (!args || args->len == 1) { - args = (struct RArray*)rb_to_a(args->ptr[0]); + if (!args || NIL_P(args)) { + return ary_new2(0); } new_ary = ary_new2(args->len); @@ -365,6 +408,53 @@ ary_indexes(ary, args) return new_ary; } +static void +ary_replace(ary, beg, len, rpl) + struct RArray *ary, *rpl; + int beg, len; +{ + if (TYPE(rpl) != T_ARRAY) { + rpl = (struct RArray*)rb_to_a(rpl); + } + if (beg < 0) { + beg = ary->len + beg; + if (beg < 0) beg = 0; + } + if (beg >= ary->len) { + len = beg + rpl->len; + if (len >= ary->capa) { + ary->capa=len; + REALLOC_N(ary->ptr, VALUE, ary->capa); + } + memclear(ary->ptr+ary->len, beg-ary->len); + MEMCPY(ary->ptr+beg, rpl->ptr, VALUE, rpl->len); + ary->len = len; + } + else { + int alen; + + if (beg + len > ary->len) { + len = ary->len - beg; + } + if (len < 0) { + IndexError("negative length %d", ary->len); + } + + alen = ary->len + rpl->len - len; + if (alen >= ary->capa) { + ary->capa=alen; + REALLOC_N(ary->ptr, VALUE, ary->capa); + } + + if (len != RARRAY(rpl)->len) { + MEMMOVE(ary->ptr+beg+rpl->len, ary->ptr+beg+len, + VALUE, ary->len-(beg+len)); + ary->len = alen; + } + MEMCPY(ary->ptr+beg, rpl->ptr, VALUE, rpl->len); + } +} + static VALUE ary_aset(argc, argv, ary) int argc; @@ -374,90 +464,29 @@ ary_aset(argc, argv, ary) VALUE arg1, arg2; struct RArray *arg3; int offset; + int beg, len; if (rb_scan_args(argc, argv, "21", &arg1, &arg2, &arg3) == 3) { - int beg, len; - beg = NUM2INT(arg1); - if (TYPE(arg3) != T_ARRAY) { - arg3 = (struct RArray*)rb_to_a(arg3); - } - if (beg < 0) { - beg = ary->len + beg; - if (beg < 0) { - Fail("negative index for array(size: %d)", ary->len); - } - } - if (beg >= ary->len) { - len = beg + arg3->len; - if (len >= ary->capa) { - ary->capa=len; - REALLOC_N(ary->ptr, VALUE, ary->capa); - } - MEMZERO(ary->ptr+ary->len, VALUE, beg-ary->len); - MEMCPY(ary->ptr+beg, arg3->ptr, VALUE, arg3->len); - ary->len = len; - } - else { - int alen; - - len = NUM2INT(arg2); - if (beg + len > ary->len) { - len = ary->len - beg; - } - if (len < 0) { - Fail("negative length for sub-array(size: %d)", ary->len); - } - - alen = ary->len + arg3->len - len; - if (alen >= ary->capa) { - ary->capa=alen; - REALLOC_N(ary->ptr, VALUE, ary->capa); - } - - MEMMOVE(ary->ptr+beg+arg3->len, ary->ptr+beg+len, - VALUE, ary->len-(beg+len)); - MEMCPY(ary->ptr+beg, arg3->ptr, VALUE, arg3->len); - ary->len = alen; - } + len = NUM2INT(arg2); + ary_replace(ary, beg, len, arg3); return (VALUE)arg3; } - - /* check if idx is Range */ - { - int beg, len; - - if (beg_len(arg1, &beg, &len, ary->len)) { - Check_Type(arg2, T_ARRAY); - if (ary->len < beg) { - len = beg + RARRAY(arg2)->len; - if (len >= ary->capa) { - ary->capa=len; - REALLOC_N(ary->ptr, VALUE, ary->capa); - } - MEMZERO(ary->ptr+ary->len, VALUE, beg-ary->len); - MEMCPY(ary->ptr+beg, RARRAY(arg2)->ptr, VALUE, RARRAY(arg2)->len); - ary->len = len; - } - else { - int alen; - - alen = ary->len + RARRAY(arg2)->len - len; - if (alen >= ary->capa) { - ary->capa=alen; - REALLOC_N(ary->ptr, VALUE, ary->capa); - } - - MEMMOVE(ary->ptr+beg+RARRAY(arg2)->len, ary->ptr+beg+len, - VALUE, ary->len-(beg+len)); - MEMCPY(ary->ptr+beg, RARRAY(arg2)->ptr, VALUE, RARRAY(arg2)->len); - ary->len = alen; - } - return arg2; - } + else if (FIXNUM_P(arg1)) { + offset = FIX2INT(arg1); + goto fixnum; + } + else if (beg_len(arg1, &beg, &len, ary->len)) { + /* check if idx is Range */ + ary_replace(ary, beg, len, arg2); + return arg2; + } + if (TYPE(arg1) == T_BIGNUM) { + IndexError("index too big"); } offset = NUM2INT(arg1); + fixnum: if (offset < 0) { offset = ary->len + offset; } @@ -471,15 +500,10 @@ ary_each(ary) { int i; - if (iterator_p()) { - for (i=0; i<ary->len; i++) { - rb_yield(ary->ptr[i]); - } - return Qnil; - } - else { - return (VALUE)ary; + for (i=0; i<ary->len; i++) { + rb_yield(ary->ptr[i]); } + return Qnil; } static VALUE @@ -502,6 +526,15 @@ ary_length(ary) } static VALUE +ary_empty_p(ary) + struct RArray *ary; +{ + if (ary->len == 0) + return TRUE; + return FALSE; +} + +static VALUE ary_clone(ary) struct RArray *ary; { @@ -540,7 +573,7 @@ ary_join(ary, sep) default: tmp = obj_as_string(tmp); } - if (sep) str_cat(result, sep->ptr, sep->len); + if (!NIL_P(sep)) str_cat(result, sep->ptr, sep->len); str_cat(result, RSTRING(tmp)->ptr, RSTRING(tmp)->len); } @@ -556,9 +589,9 @@ ary_join_method(argc, argv, ary) VALUE sep; rb_scan_args(argc, argv, "01", &sep); - if (sep == Qnil) sep = OFS; + if (NIL_P(sep)) sep = OFS; - if (sep != Qnil) + if (!NIL_P(sep)) Check_Type(sep, T_STRING); return ary_join(ary, sep); @@ -569,7 +602,7 @@ ary_to_s(ary) VALUE ary; { VALUE str = ary_join(ary, OFS); - if (str == Qnil) return str_new(0, 0); + if (NIL_P(str)) return str_new(0, 0); return str; } @@ -581,7 +614,7 @@ ary_print_on(ary, port) int i; for (i=0; i<ary->len; i++) { - if (OFS && i>1) { + if (!NIL_P(OFS) && i>0) { io_write(port, OFS); } io_write(port, ary->ptr[i]); @@ -602,7 +635,7 @@ ary_inspect(ary) len = 1; for (i=0; i<ary->len; i++) { - s = rb_funcall(ary->ptr[i], rb_intern("inspect"), 0, 0); + s = rb_inspect(ary->ptr[i]); if (i > 0) str_cat(str, ", ", 2); str_cat(str, RSTRING(s)->ptr, RSTRING(s)->len); len += RSTRING(s)->len + 2; @@ -635,15 +668,27 @@ VALUE ary_reverse(ary) struct RArray *ary; { - VALUE ary2 = ary_new2(ary->len); - int i, j; + VALUE *p1, *p2; + VALUE tmp; + + p1 = ary->ptr; + p2 = p1 + ary->len - 1; /* points last item */ - for (i=ary->len-1, j=0; i >=0; i--, j++) { - RARRAY(ary2)->ptr[j] = ary->ptr[i]; + while (p1 < p2) { + tmp = *p1; + *p1 = *p2; + *p2 = tmp; + p1++; p2--; } - RARRAY(ary2)->len = ary->len; - return ary2; + return (VALUE)ary; +} + +static VALUE +ary_reverse_method(ary) + struct RArray *ary; +{ + return ary_reverse(ary_clone(ary)); } static ID cmp; @@ -662,19 +707,25 @@ sort_2(a, b) { VALUE retval; - if (!cmp) cmp = rb_intern("<=>"); retval = rb_funcall(*a, cmp, 1, *b); return NUM2INT(retval); } VALUE -ary_sort(ary) +ary_sort_bang(ary) struct RArray *ary; { qsort(ary->ptr, ary->len, sizeof(VALUE), iterator_p()?sort_1:sort_2); return (VALUE)ary; } +VALUE +ary_sort(ary) + VALUE ary; +{ + return ary_sort_bang(ary_clone(ary)); +} + static VALUE ary_delete(ary, item) struct RArray *ary; @@ -689,11 +740,40 @@ ary_delete(ary, item) } i2++; } - ary->len = i2; + if (ary->len == i2) { + if (iterator_p()) rb_yield(Qnil); + } + else { + ary->len = i2; + } return (VALUE)ary; } +VALUE +ary_delete_at(ary, at) + struct RArray *ary; + VALUE at; +{ + int i1, i2, pos; + VALUE del = Qnil; + + pos = NUM2INT(at); + for (i1 = i2 = 0; i1 < ary->len; i1++) { + if (i1 == pos) { + del = ary->ptr[i1]; + continue; + } + if (i1 != i2) { + ary->ptr[i2] = ary->ptr[i1]; + } + i2++; + } + ary->len = i2; + + return del; +} + static VALUE ary_delete_if(ary) struct RArray *ary; @@ -717,6 +797,10 @@ ary_clear(ary) struct RArray *ary; { ary->len = 0; + if (ARY_DEFAULT_SIZE*3 < ary->capa) { + ary->capa = ARY_DEFAULT_SIZE * 2; + REALLOC_N(ary->ptr, VALUE, ary->capa); + } return (VALUE)ary; } @@ -731,7 +815,7 @@ ary_fill(argc, argv, ary) VALUE *p, *pend; rb_scan_args(argc, argv, "12", &item, &arg1, &arg2); - if (arg2 == Qnil && beg_len(arg1, &beg, &len, ary->len)) { + if (NIL_P(arg2) && beg_len(arg1, &beg, &len, ary->len)) { /* beg and len set already */ } else { @@ -754,7 +838,7 @@ ary_fill(argc, argv, ary) REALLOC_N(ary->ptr, VALUE, ary->capa); } if (beg > ary->len) { - MEMZERO(ary->ptr+ary->len, VALUE, end-ary->len); + memclear(ary->ptr+ary->len, end-ary->len); } ary->len = end; } @@ -766,28 +850,43 @@ ary_fill(argc, argv, ary) return (VALUE)ary; } -static VALUE +VALUE ary_plus(x, y) struct RArray *x, *y; { struct RArray *z; - switch (TYPE(y)) { - case T_ARRAY: - z = (struct RArray*)ary_new2(x->len + y->len); - MEMCPY(z->ptr, x->ptr, VALUE, x->len); - MEMCPY(z->ptr+x->len, y->ptr, VALUE, y->len); - z->len = x->len + RARRAY(y)->len; - break; - - default: - z = (struct RArray*)ary_clone(x); - ary_push(z, y); - break; + if (TYPE(y) != T_ARRAY) { + return ary_plus(x, rb_to_a(y)); } + + z = (struct RArray*)ary_new2(x->len + y->len); + MEMCPY(z->ptr, x->ptr, VALUE, x->len); + MEMCPY(z->ptr+x->len, y->ptr, VALUE, y->len); + z->len = x->len + RARRAY(y)->len; return (VALUE)z; } +VALUE +ary_concat(x, y) + struct RArray *x, *y; +{ + struct RArray *z; + VALUE *p, *pend; + + if (TYPE(y) != T_ARRAY) { + return ary_concat(x, rb_to_a(y)); + } + + p = y->ptr; + pend = p + y->len; + while (p < pend) { + astore(x, x->len, *p); + p++; + } + return (VALUE)x; +} + static VALUE ary_times(ary, times) struct RArray *ary; @@ -796,6 +895,10 @@ ary_times(ary, times) struct RArray *ary2; int i, len; + if (TYPE(times) == T_STRING) { + return ary_join(ary, times); + } + len = NUM2INT(times) * ary->len; ary2 = (struct RArray*)ary_new2(len); ary2->len = len; @@ -820,8 +923,9 @@ ary_assoc(ary, key) && RARRAY(*p)->len > 1 && rb_equal(RARRAY(*p)->ptr[0], key)) return *p; + p++; } - return Qnil; /* should be FALSE? */ + return Qnil; } VALUE @@ -834,11 +938,12 @@ ary_rassoc(ary, value) p = ary->ptr; pend = p + ary->len; while (p < pend) { if (TYPE(*p) == T_ARRAY - && RARRAY(*p)->len > 2 + && RARRAY(*p)->len > 1 && rb_equal(RARRAY(*p)->ptr[1], value)) return *p; + p++; } - return Qnil; /* should be FALSE? */ + return Qnil; } static VALUE @@ -944,7 +1049,47 @@ ary_or(ary1, ary2) return ary3; } -extern VALUE cKernel; +static VALUE +ary_compact_bang(ary) + struct RArray *ary; +{ + VALUE *p, *t, *end; + + p = t = ary->ptr; + end = p + ary->len; + while (t < end) { + if (NIL_P(*t)) t++; + else *p++ = *t++; + } + ary->len = ary->capa = (p - ary->ptr); + REALLOC_N(ary->ptr, VALUE, ary->len); + + return (VALUE)ary; +} + +static VALUE +ary_compact(ary) + struct RArray *ary; +{ + return ary_compact_bang(ary_clone(ary)); +} + +static VALUE +ary_nitems(ary) + struct RArray *ary; +{ + int n = 0; + VALUE *p, *pend; + + p = ary->ptr; + pend = p + ary->len; + while (p < pend) { + if (!NIL_P(*p)) n++; + p++; + } + return INT2FIX(n); +} + extern VALUE mEnumerable; void @@ -953,7 +1098,7 @@ Init_Array() cArray = rb_define_class("Array", cObject); rb_include_module(cArray, mEnumerable); - rb_define_singleton_method(cArray, "new", ary_s_new, 0); + rb_define_singleton_method(cArray, "new", ary_s_new, -1); rb_define_singleton_method(cArray, "[]", ary_s_create, -1); rb_define_method(cArray, "to_s", ary_to_s, 0); rb_define_method(cArray, "inspect", ary_inspect, 0); @@ -965,26 +1110,32 @@ Init_Array() rb_define_method(cArray, "hash", ary_hash, 0); rb_define_method(cArray, "[]", ary_aref, -1); rb_define_method(cArray, "[]=", ary_aset, -1); - rb_define_method(cArray, "<<", ary_append, 1); - rb_define_method(cArray, "push", ary_push, 1); + rb_define_method(cArray, "concat", ary_concat, 1); + rb_define_method(cArray, "<<", ary_push, 1); + rb_define_method(cArray, "push", ary_push_method, -1); rb_define_method(cArray, "pop", ary_pop, 0); rb_define_method(cArray, "shift", ary_shift, 0); - rb_define_method(cArray, "unshift", ary_unshift, 1); + rb_define_method(cArray, "unshift", ary_unshift_method, -1); rb_define_method(cArray, "each", ary_each, 0); rb_define_method(cArray, "each_index", ary_each_index, 0); rb_define_method(cArray, "length", ary_length, 0); rb_define_alias(cArray, "size", "length"); + rb_define_method(cArray, "empty?", ary_empty_p, 0); rb_define_method(cArray, "index", ary_index, 1); rb_define_method(cArray, "indexes", ary_indexes, -2); rb_define_method(cArray, "clone", ary_clone, 0); rb_define_method(cArray, "join", ary_join_method, -1); - rb_define_method(cArray, "reverse", ary_reverse, 0); + rb_define_method(cArray, "reverse", ary_reverse_method, 0); + rb_define_method(cArray, "reverse!", ary_reverse, 0); rb_define_method(cArray, "sort", ary_sort, 0); + rb_define_method(cArray, "sort!", ary_sort_bang, 0); rb_define_method(cArray, "delete", ary_delete, 1); + rb_define_method(cArray, "delete_at", ary_delete_at, 1); rb_define_method(cArray, "delete_if", ary_delete_if, 0); rb_define_method(cArray, "clear", ary_clear, 0); rb_define_method(cArray, "fill", ary_fill, -1); - rb_define_method(cArray, "includes", ary_includes, 1); + rb_define_method(cArray, "include?", ary_includes, 1); + rb_define_method(cArray, "includes?", ary_includes, 1); /* obsolate */ rb_define_method(cArray, "assoc", ary_assoc, 1); rb_define_method(cArray, "rassoc", ary_rassoc, 1); @@ -995,4 +1146,10 @@ Init_Array() rb_define_method(cArray, "-", ary_diff, 1); rb_define_method(cArray, "&", ary_and, 1); rb_define_method(cArray, "|", ary_or, 1); + + rb_define_method(cArray, "compact", ary_compact, 0); + rb_define_method(cArray, "compact!", ary_compact_bang, 0); + rb_define_method(cArray, "nitems", ary_nitems, 0); + + cmp = rb_intern("<=>"); } @@ -40,15 +40,6 @@ bignew_1(class, len, sign) #define bignew(len,sign) bignew_1(cBignum,len,sign) -static VALUE -big_s_new(class, y) - VALUE class; - struct RBignum *y; -{ - Check_Type(y, T_BIGNUM); - return bignew_1(class, y->len, y->sign); -} - VALUE big_clone(x) struct RBignum *x; @@ -136,7 +127,7 @@ int2big(n) } big = (struct RBignum*)uint2big(n); if (neg) { - big->sign = FALSE; + big->sign = 0; } return (VALUE)big; } @@ -198,11 +189,20 @@ str2inum(str, base) } if (len <= (sizeof(VALUE)*CHAR_BIT)) { - int result = strtoul(str, 0, base); + UINT val = strtoul(str, 0, base); - if (!sign) result = -result; - if (FIXABLE(result)) return INT2FIX(result); - return int2big(result); + if (POSFIXABLE(val)) { + if (sign) return INT2FIX(val); + else { + int result = -(int)val; + return INT2FIX(result); + } + } + else { + VALUE big = uint2big(val); + RBIGNUM(big)->sign = sign; + return big; + } } len = (len/(sizeof(USHORT)*CHAR_BIT))+1; @@ -262,7 +262,7 @@ big2str(x, base) return fix2str(x, base); } i = x->len; - if (x->len == 0) return str_new2("0"); + if (i == 0) return str_new2("0"); if (base == 10) { j = (sizeof(USHORT)/sizeof(char)*CHAR_BIT*i*241L)/800+2; hbase = 10000; @@ -332,7 +332,7 @@ big2int(x) USHORT *ds; if (len > sizeof(long)/sizeof(USHORT)) - Fail("Bignum too big to convert into fixnum"); + ArgError("Bignum too big to convert into fixnum"); ds = BDIGITS(x); num = 0; while (len--) { @@ -347,12 +347,7 @@ VALUE big_to_i(x) VALUE x; { - int v = big2int(x); - - if (FIXABLE(v)) { - return INT2FIX(v); - } - return x; + return bignorm(x); } VALUE @@ -389,7 +384,9 @@ big2dbl(x) UINT i = x->len; USHORT *ds = BDIGITS(x); - while (i--) d = ds[i] + BIGRAD*d; + while (i--) { + d = ds[i] + BIGRAD*d; + } if (!x->sign) d = -d; return d; } @@ -402,6 +399,38 @@ big_to_f(x) } static VALUE +big_cmp(x, y) + struct RBignum *x, *y; +{ + int xlen = x->len; + + switch (TYPE(y)) { + case T_FIXNUM: + y = (struct RBignum*)int2big(FIX2INT(y)); + break; + + case T_BIGNUM: + break; + + default: + return num_coerce_bin(x, y); + } + + if (x->sign > y->sign) return INT2FIX(1); + if (x->sign < y->sign) return INT2FIX(-1); + if (xlen < y->len) + return (x->sign) ? INT2FIX(-1) : INT2FIX(1); + if (xlen > y->len) + return (x->sign) ? INT2FIX(1) : INT2FIX(-1); + + while(xlen-- && (BDIGITS(x)[xlen]==BDIGITS(y)[xlen])); + if (-1 == xlen) return INT2FIX(0); + return (BDIGITS(x)[xlen] > BDIGITS(y)[xlen]) ? + (x->sign ? INT2FIX(1) : INT2FIX(-1)) : + (x->sign ? INT2FIX(-1) : INT2FIX(1)); +} + +static VALUE big_uminus(x) struct RBignum *x; { @@ -413,6 +442,84 @@ big_uminus(x) } static VALUE +big_neg(x) + struct RBignum *x; +{ + VALUE z = big_clone(x); + UINT i = x->len; + USHORT *ds = BDIGITS(z); + + if (!x->sign) big_2comp(z); + while (i--) ds[i] = ~ds[i]; + if (x->sign) big_2comp(z); + RBIGNUM(z)->sign = !RBIGNUM(z)->sign; + + return bignorm(z); +} + +static VALUE +bigsub(x, y) + struct RBignum *x, *y; +{ + struct RBignum *z = 0; + USHORT *zds; + long num; + UINT i; + + i = x->len; + /* if x is larger than y, swap */ + if (x->len < y->len) { + z = x; x = y; y = z; /* swap x y */ + } + else if (x->len == y->len) { + while (i > 0) { + i--; + if (BDIGITS(x)[i] > BDIGITS(y)[i]) { + break; + } + if (BDIGITS(x)[i] < BDIGITS(y)[i]) { + z = x; x = y; y = z; /* swap x y */ + break; + } + } + } + + z = (struct RBignum*)bignew(x->len, (z == 0)?1:0); + zds = BDIGITS(z); + + i = x->len; + while (i--) zds[i] = BDIGITS(x)[i]; + + i = 0; num = 0; + do { + num += (long)zds[i] - BDIGITS(y)[i]; + if (num < 0) { + zds[i] = num + BIGRAD; + num = -1; + } + else { + zds[i] = BIGLO(num); + num = 0; + } + } while (++i < y->len); + if (num) { + while (num && i < x->len) { + num += zds[i]; + if (num < 0) { + zds[i++] = num + BIGRAD; + num = -1; + } + else { + zds[i++] = BIGLO(num); + num = 0; + } + } + } + + return bignorm(z); +} + +static VALUE bigadd(x, y, sign) struct RBignum *x, *y; char sign; @@ -422,6 +529,11 @@ bigadd(x, y, sign) long num; UINT i, len; + if (x->sign == (y->sign ^ sign)) { + if (y->sign == sign) return bigsub(y, x); + return bigsub(x, y); + } + if (x->len > y->len) { len = x->len + 1; } @@ -437,53 +549,18 @@ bigadd(x, y, sign) while (i--) zds[i] = BDIGITS(y)[i]; i = 0; num = 0; - if (x->sign == z->sign) { - do { - num += (long)zds[i] + BDIGITS(x)[i]; - zds[i++] = BIGLO(num); + do { + num += (long)zds[i] + BDIGITS(x)[i]; + zds[i++] = BIGLO(num); num = BIGDN(num); - } while (i < x->len); - if (num) { - while (i < y->len) { - num += zds[i]; - zds[i++] = BIGLO(num); - num = BIGDN(num); - } - BDIGITS(z)[i] = num; - } - } - else { - do { - num += (long)zds[i] - BDIGITS(x)[i]; - if (num < 0) { - zds[i] = num + BIGRAD; - num = -1; - } - else { - zds[i] = BIGLO(num); - num = 0; - } - } while (++i < x->len); - if (num && x->len == y->len) { - num = 1; i = 0; - z->sign = 1; - do { - num += (BIGRAD-1) - zds[i]; - zds[i++] = BIGLO(num); - num = BIGDN(num); - } while (i < y->len); - } - else while (i < y->len) { + } while (i < x->len); + if (num) { + while (i < y->len) { num += zds[i]; - if (num < 0) { - zds[i++] = num + BIGRAD; - num = -1; - } - else { - zds[i++] = BIGLO(num); - num = 0; - } + zds[i++] = BIGLO(num); + num = BIGDN(num); } + BDIGITS(z)[i] = num; } return bignorm(z); @@ -495,26 +572,40 @@ big_plus(x, y) { VALUE z; - if (FIXNUM_P(y)) y = int2big(FIX2INT(y)); - else { - Check_Type(x, T_BIGNUM); - } - z = bigadd(x, y, 1); + switch (TYPE(y)) { + case T_FIXNUM: + y = int2big(FIX2INT(y)); + /* fall through */ + case T_BIGNUM: + return bigadd(x, y, 1); - return z; + case T_FLOAT: + return float_new(big2dbl(x) + RFLOAT(y)->value); + + default: + return num_coerce_bin(x, y); + } } VALUE big_minus(x, y) VALUE x, y; { - if (FIXNUM_P(y)) y = int2big(FIX2INT(y)); - else { - Check_Type(y, T_BIGNUM); - } - x = bigadd(x, y, 0); + VALUE cmp; - return x; + switch (TYPE(y)) { + case T_FIXNUM: + y = int2big(FIX2INT(y)); + /* fall through */ + case T_BIGNUM: + return bigadd(x, y, 0); + + case T_FLOAT: + return float_new(big2dbl(x) - RFLOAT(y)->value); + + default: + return num_coerce_bin(x, y); + } } VALUE @@ -527,9 +618,19 @@ big_mul(x, y) USHORT *zds; if (FIXNUM_P(x)) x = (struct RBignum*)int2big(FIX2INT(x)); - if (FIXNUM_P(y)) y = (struct RBignum*)int2big(FIX2INT(y)); - else { - Check_Type(y, T_BIGNUM); + switch (TYPE(y)) { + case T_FIXNUM: + y = (struct RBignum*)int2big(FIX2INT(y)); + break; + + case T_BIGNUM: + break; + + case T_FLOAT: + return float_new(big2dbl(x) * RFLOAT(y)->value); + + default: + return num_coerce_bin(x, y); } j = x->len + y->len + 1; @@ -567,7 +668,7 @@ bigdivmod(x, y, div, mod) USHORT dd, q; yds = BDIGITS(y); - if (ny == 0 && yds[0] == 0) Fail("divided by 0"); + if (ny == 0 && yds[0] == 0) num_zerodiv(); if (nx < ny) { if (div) *div = INT2FIX(0); if (mod) *mod = bignorm(x); @@ -587,7 +688,7 @@ bigdivmod(x, y, div, mod) if (div) *div = bignorm(z); if (mod) { if (!y->sign) t2 = -t2; - *mod = FIX2INT(t2); + *mod = INT2FIX(t2); } return; } @@ -683,9 +784,19 @@ big_div(x, y) { VALUE z; - if (FIXNUM_P(y)) y = int2big(FIX2INT(y)); - else { - Check_Type(y, T_BIGNUM); + switch (TYPE(y)) { + case T_FIXNUM: + y = int2big(FIX2INT(y)); + break; + + case T_BIGNUM: + break; + + case T_FLOAT: + return float_new(big2dbl(x) / RFLOAT(y)->value); + + default: + return num_coerce_bin(x, y); } bigdivmod(x, y, &z, 0); @@ -698,9 +809,20 @@ big_mod(x, y) { VALUE z; - if (FIXNUM_P(y)) y = int2big(FIX2INT(y)); - else { - Check_Type(y, T_BIGNUM); + switch (TYPE(y)) { + case T_FIXNUM: + y = int2big(FIX2INT(y)); + break; + + case T_BIGNUM: + break; + + case T_FLOAT: + y = dbl2big(RFLOAT(y)->value); + break; + + default: + return num_coerce_bin(x, y); } bigdivmod(x, y, 0, &z); @@ -713,9 +835,20 @@ big_divmod(x, y) { VALUE div, mod; - if (FIXNUM_P(y)) y = int2big(FIX2INT(y)); - else { - Check_Type(y, T_BIGNUM); + switch (TYPE(y)) { + case T_FIXNUM: + y = int2big(FIX2INT(y)); + break; + + case T_FLOAT: + y = dbl2big(RFLOAT(y)->value); + break; + + case T_BIGNUM: + break; + + default: + return num_coerce_bin(x, y); } bigdivmod(x, y, &div, &mod); @@ -726,22 +859,37 @@ VALUE big_pow(x, y) VALUE x, y; { + double d; VALUE z; - int n; + + if (y == INT2FIX(0)) return INT2FIX(1); + switch (TYPE(y)) { + case T_FLOAT: + d = RFLOAT(y)->value; + break; - if (TYPE(y) == T_FLOAT) { - return float_new(pow(big2dbl(x), RFLOAT(y)->value)); - } - n = NUM2INT(y); - if (n == 0) return INT2FIX(1); - if (n < 0) { - return float_new(pow(big2dbl(x), (double)n)); + case T_BIGNUM: + if (RBIGNUM(y)->sign) goto pos_big; + d = big2dbl(y); + break; + + case T_FIXNUM: + if (FIX2INT(y) > 0) goto pos_big; + d = (double)FIX2INT(y); + break; + + default: + return num_coerce_bin(x, y); } + return float_new(pow(big2dbl(x), d)); + pos_big: z = x; - while (--n) { - while (!(n % 2)) { - n = n /2; + for (;;) { + y = rb_funcall(y, '-', 1, INT2FIX(1)); + if (y == INT2FIX(0)) break; + while (rb_funcall(y, '%', 1, INT2FIX(2)) == INT2FIX(0)) { + y = rb_funcall(y, '/', 1, INT2FIX(2)); x = big_mul(x, x); } z = big_mul(z, x); @@ -906,22 +1054,6 @@ big_xor(x, y) return bignorm(z); } -static VALUE -big_neg(x) - struct RBignum *x; -{ - VALUE z = big_clone(x); - UINT i = x->len; - USHORT *ds = BDIGITS(z); - - if (!x->sign) big_2comp(z); - while (i--) ds[i] = ~ds[i]; - if (x->sign) big_2comp(z); - RBIGNUM(z)->sign = !RBIGNUM(z)->sign; - - return bignorm(z); -} - static VALUE big_rshift(); VALUE @@ -1014,32 +1146,6 @@ big_aref(x, y) } static VALUE -big_cmp(x, y) - struct RBignum *x, *y; -{ - int xlen = x->len; - - if (FIXNUM_P(y)) { - y = (struct RBignum*)int2big(FIX2INT(y)); - } - else { - Check_Type(y, T_BIGNUM); - } - if (x->sign > y->sign) return INT2FIX(1); - if (x->sign < y->sign) return INT2FIX(-1); - if (xlen < y->len) - return (x->sign) ? INT2FIX(-1) : INT2FIX(1); - if (xlen > y->len) - return (x->sign) ? INT2FIX(1) : INT2FIX(-1); - - while(xlen-- && (BDIGITS(x)[xlen]==BDIGITS(y)[xlen])); - if (-1 == xlen) return INT2FIX(0); - return (BDIGITS(x)[xlen] < BDIGITS(y)[xlen]) ? - (x->sign ? INT2FIX(1) : INT2FIX(-1)) : - (x->sign ? INT2FIX(-1) : INT2FIX(1)); -} - -static VALUE big_hash(x) struct RBignum *x; { @@ -1059,13 +1165,12 @@ big_coerce(x, y) VALUE y; { if (FIXNUM_P(y)) { - return int2big(FIX2INT(y)); + return assoc_new(int2big(FIX2INT(y)), x); } else { - Fail("can't coerce %s to Bignum", rb_class2name(CLASS_OF(y))); + TypeError("can't coerce %s to Bignum", rb_class2name(CLASS_OF(y))); } /* not reached */ - return Qnil; } static VALUE @@ -1079,11 +1184,43 @@ big_abs(x) return (VALUE)x; } +/* !!!warnig!!!! + this is not really a random number!! +*/ + +VALUE +big_rand(max) + struct RBignum *max; +{ + struct RBignum *v; + int len; + + len = max->len; + v = RBIGNUM(bignew(len,1)); + while (len--) { +#ifdef HAVE_RANDOM + BDIGITS(v)[len] = random(); +#else + BDIGITS(v)[len] = rand(); +#endif + } + + return big_mod(v, max); +} + +static VALUE +big_size(big) + struct RBignum *big; +{ + return INT2FIX(big->len*2); +} + void Init_Bignum() { cBignum = rb_define_class("Bignum", cInteger); - rb_define_singleton_method(cBignum, "new", big_s_new, 1); + + rb_undef_method(CLASS_OF(cBignum), "new"); rb_define_method(cBignum, "to_s", big_to_s, 0); rb_define_method(cBignum, "coerce", big_coerce, 1); @@ -1107,5 +1244,6 @@ Init_Bignum() rb_define_method(cBignum, "hash", big_hash, 0); rb_define_method(cBignum, "to_i", big_to_i, 0); rb_define_method(cBignum, "to_f", big_to_f, 0); - rb_define_method(cBignum, "abs_f", big_abs, 0); + rb_define_method(cBignum, "abs", big_abs, 0); + rb_define_method(cBignum, "size", big_size, 0); } @@ -39,7 +39,7 @@ singleton_class_new(super) { struct RClass *cls = (struct RClass*)class_new(super); - FL_SET(cls, FL_SINGLE); + FL_SET(cls, FL_SINGLETON); return (VALUE)cls; } @@ -58,7 +58,7 @@ VALUE singleton_class_clone(class) struct RClass *class; { - if (!FL_TEST(class, FL_SINGLE)) + if (!FL_TEST(class, FL_SINGLETON)) return (VALUE)class; else { /* copy singleton(unnamed) class */ @@ -68,7 +68,7 @@ singleton_class_clone(class) clone->super = class->super; clone->m_tbl = new_idhash(); st_foreach(class->m_tbl, clone_method, clone->m_tbl); - FL_SET(clone, FL_SINGLE); + FL_SET(clone, FL_SINGLETON); return (VALUE)clone; } } @@ -78,7 +78,7 @@ rb_define_class_id(id, super) ID id; struct RBasic *super; { - struct RClass *cls = (struct RClass*)class_new(super); + struct RClass *cls; if (!super) super = (struct RBasic*)cClass; cls = (struct RClass*)class_new(super); @@ -100,7 +100,6 @@ rb_define_class(name, super) id = rb_intern(name); class = rb_define_class_id(id, super); st_add_direct(rb_class_tbl, id, class); - rb_set_class_path(class, 0, name); return class; } @@ -128,7 +127,7 @@ module_new() NEWOBJ(mdl, struct RClass); OBJSETUP(mdl, cModule, T_MODULE); - mdl->super = Qnil; + mdl->super = 0; mdl->m_tbl = new_idhash(); return (VALUE)mdl; @@ -171,6 +170,7 @@ rb_define_module_under(under, name) id = rb_intern(name); module = rb_define_module_id(id); rb_const_set(under, id, module); + rb_set_class_path(module, under, name); return module; } @@ -201,7 +201,7 @@ rb_include_module(class, module) { struct RClass *p; - if (!module) return; + if (NIL_P(module)) return; switch (TYPE(module)) { case T_MODULE: @@ -212,10 +212,8 @@ rb_include_module(class, module) } if (class == module) return; - if (BUILTIN_TYPE(class) == T_CLASS) { - rb_clear_cache(class); - } - + rb_clear_cache(); + while (module) { /* ignore if the module included already in superclasses */ for (p = class->super; p; p = p->super) { @@ -258,7 +256,7 @@ rb_undef_method(class, name) struct RClass *class; char *name; { - rb_add_method(class, rb_intern(name), Qnil, NOEX_PUBLIC); + rb_add_method(class, rb_intern(name), 0, NOEX_PUBLIC); } void @@ -275,18 +273,7 @@ VALUE rb_singleton_class(obj) struct RBasic *obj; { - switch (TYPE(obj)) { - case T_OBJECT: - case T_CLASS: - case T_MODULE: - case T_STRUCT: - break; - default: - Fail("can't define singleton method for built-in class"); - break; - } - - if (FL_TEST(obj->class, FL_SINGLE)) { + if (FL_TEST(obj->class, FL_SINGLETON)) { return (VALUE)obj->class; } return obj->class = singleton_class_new(obj->class); @@ -338,10 +325,10 @@ rb_define_attr(class, id, pub) attreq = rb_intern(buf); sprintf(buf, "@%s", name); attriv = rb_intern(buf); - if (rb_method_boundp(class, attr) == FALSE) { + if (!rb_method_boundp(class, attr)) { rb_add_method(class, attr, NEW_IVAR(attriv), 0); } - if (pub && rb_method_boundp(class, attreq) == FALSE) { + if (pub && !rb_method_boundp(class, attreq)) { rb_add_method(class, attreq, NEW_ATTRSET(attriv), 0); } } @@ -372,7 +359,7 @@ rb_scan_args(argc, argv, fmt, va_alist) if (isdigit(*p)) { n = *p - '0'; if (n > argc) - Fail("Wrong number of arguments (%d for %d)", argc, n); + ArgError("Wrong # of arguments (%d for %d)", argc, n); for (i=0; i<n; i++) { var = va_arg(vargs, VALUE*); *var = argv[i]; @@ -408,7 +395,7 @@ rb_scan_args(argc, argv, fmt, va_alist) } else if (*p == '\0') { if (argc > i) { - Fail("Wrong # of arguments(%d for %d)", argc, i); + ArgError("Wrong # of arguments(%d for %d)", argc, i); } } else { @@ -419,6 +406,6 @@ rb_scan_args(argc, argv, fmt, va_alist) return argc; error: - Fail("bad scan arg format: %s", fmt); + Fatal("bad scan arg format: %s", fmt); return 0; } @@ -6,7 +6,7 @@ $Date: 1994/10/14 06:19:05 $ created at: Thu Aug 26 14:39:48 JST 1993 - Copyright (C) 1993-1995 Yukihiro Matsumoto + Copyright (C) 1993-1996 Yukihiro Matsumoto ************************************************/ @@ -34,7 +34,7 @@ cmp_gt(x, y) VALUE c = rb_funcall(x, cmp, 1, y); int t = NUM2INT(c); - if (t > 0) return y; + if (t > 0) return TRUE; return FALSE; } @@ -45,7 +45,7 @@ cmp_ge(x, y) VALUE c = rb_funcall(x, cmp, 1, y); int t = NUM2INT(c); - if (t >= 0) return y; + if (t >= 0) return TRUE; return FALSE; } @@ -56,7 +56,7 @@ cmp_lt(x, y) VALUE c = rb_funcall(x, cmp, 1, y); int t = NUM2INT(c); - if (t < 0) return y; + if (t < 0) return TRUE; return FALSE; } @@ -67,7 +67,7 @@ cmp_le(x, y) VALUE c = rb_funcall(x, cmp, 1, y); int t = NUM2INT(c); - if (t <= 0) return y; + if (t <= 0) return TRUE; return FALSE; } diff --git a/config.dj b/config.dj new file mode 100644 index 0000000000..13f4e6ddb6 --- /dev/null +++ b/config.dj @@ -0,0 +1,35 @@ +#define THREAD 1 +#define HAVE_DIRENT_H 1 +#define HAVE_UNISTD_H 1 +#define HAVE_LIMITS_H 1 +#define HAVE_SYS_FILE_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_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_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 1 */ +/* #define HAVE_SETITIMER 1 */ +#define HAVE_GETGROUPS 1 +#define HAVE_SIGPROCMASK 1 +#define FILE_COUNT _cnt +#define DLEXT ".so" +#define RUBY_LIB ";/usr/local/lib/ruby;." +#define RUBY_ARCHLIB "/usr/local/lib/ruby/i386-msdos" diff --git a/config.guess b/config.guess index a3d6a9f1bf..ce6e12a8fd 100755 --- a/config.guess +++ b/config.guess @@ -1,6 +1,6 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +# Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc. # # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ # # 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. +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -51,14 +51,19 @@ trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15 # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - alpha:OSF1:V*:*) - # After 1.2, OSF1 uses "V1.3" for uname -r. - echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^V//'` - exit 0 ;; alpha:OSF1:*:*) + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo alpha-dec-osf${UNAME_RELEASE} - exit 0 ;; + echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//'` + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-cbm-sysv4 + exit 0;; amiga:NetBSD:*:*) echo m68k-cbm-netbsd${UNAME_RELEASE} exit 0 ;; @@ -75,6 +80,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in sun4*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but @@ -93,15 +101,30 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; + atari*:NetBSD:*:*) + echo m68k-atari-netbsd${UNAME_RELEASE} + exit 0 ;; + sun3*:NetBSD:*:*) + echo m68k-sun-netbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:NetBSD:*:*) + echo m68k-apple-netbsd${UNAME_RELEASE} + exit 0 ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit 0 ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; + mips:*:4*:UMIPS) + echo mips-mips-riscos4sysv + exit 0 ;; mips:*:5*:RISCos) echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit 0 ;; @@ -112,12 +135,17 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in echo m88k-motorola-sysv3 exit 0 ;; AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \ -o ${TARGET_BINARY_INTERFACE}x = x ] ; then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi + else echo i586-dg-dgux${UNAME_RELEASE} + fi exit 0 ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 @@ -169,10 +197,8 @@ EOF else IBM_ARCH=powerpc fi - if grep bos410 /usr/include/stdio.h >/dev/null 2>&1; then - IBM_REV=4.1 - elif grep bos411 /usr/include/stdio.h >/dev/null 2>&1; then - IBM_REV=4.1.1 + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` else IBM_REV=4.${UNAME_RELEASE} fi @@ -185,7 +211,7 @@ EOF echo romp-ibm-bsd4.4 exit 0 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit 0 ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx @@ -203,7 +229,7 @@ EOF case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/7?? | 9000/8?7 ) HP_ARCH=hppa1.1 ;; + 9000/7?? | 9000/8?[679] ) HP_ARCH=hppa1.1 ;; 9000/8?? ) HP_ARCH=hppa1.0 ;; esac HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` @@ -239,18 +265,21 @@ EOF rm -f dummy.c dummy echo unknown-hitachi-hiuxwe2 exit 0 ;; - 9000/7??:4.3bsd:*:* | 9000/8?7:4.3bsd:*:* ) + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit 0 ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; - hp7??:OSF1:*:* | hp8?7:OSF1:*:* ) + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit 0 ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; @@ -269,20 +298,23 @@ EOF C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit 0 ;; - CRAY*X-MP:UNICOS:*:*) + CRAY*X-MP:*:*:*) echo xmp-cray-unicos exit 0 ;; - CRAY*Y-MP:UNICOS:*:*) - echo ymp-cray-unicos - exit 0 ;; - CRAY-2:UNICOS:*:*) + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY*C90:*:*:*) + echo c90-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY-2:*:*:*) echo cray2-cray-unicos exit 0 ;; hp3[0-9][05]:NetBSD:*:*) echo m68k-hp-netbsd${UNAME_RELEASE} exit 0 ;; i[34]86:BSD/386:*:* | *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` @@ -290,11 +322,20 @@ EOF *:NetBSD:*:*) echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` exit 0 ;; + i*:CYGWIN*:*) + echo i386-pc-cygwin32 + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin32 + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; *:GNU:*:*) echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; *:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux + echo ${UNAME_MACHINE}-pc-linux exit 0 ;; # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions # are messed up and put the nodename in both sysname and nodename. @@ -305,23 +346,25 @@ EOF if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE} else - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE} + echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} fi exit 0 ;; i[34]86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` - echo ${UNAME_MACHINE}-unknown-isc$UNAME_REL + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL elif /bin/uname -X 2>/dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 - echo ${UNAME_MACHINE}-unknown-sco$UNAME_REL + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else - echo ${UNAME_MACHINE}-unknown-sysv32 + echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; Intel:Mach:3*:*) - echo i386-unknown-mach3 + echo i386-pc-mach3 exit 0 ;; paragon:*:*:*) echo i860-intel-osf1 @@ -345,19 +388,19 @@ EOF 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4 && exit 0 ;; - m680[234]0:LynxOS:2.2*:*) + m680[234]0:LynxOS:2.[23]*:*) echo m68k-lynx-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; - i[34]86:LynxOS:2.2*:*) + i[34]86:LynxOS:2.[23]*:*) echo i386-lynx-lynxos${UNAME_RELEASE} exit 0 ;; - TSUNAMI:LynxOS:2.2*:*) + TSUNAMI:LynxOS:2.[23]*:*) echo sparc-lynx-lynxos${UNAME_RELEASE} exit 0 ;; - rs6000:LynxOS:2.2*:*) + rs6000:LynxOS:2.[23]*:*) echo rs6000-lynx-lynxos${UNAME_RELEASE} exit 0 ;; RM*:SINIX-*:*:*) @@ -371,12 +414,29 @@ EOF echo ns32k-sni-sysv fi exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + R3000:*System_V*:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + powerpc:JCC_BSD+:*:*) + echo powerpc-jcc-bsd4.4 + exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 cat >dummy.c <<EOF +#ifdef _SEQUENT_ +# include <sys/types.h> +# include <sys/utsname.h> +#endif main () { #if defined (sony) @@ -427,7 +487,7 @@ main () #endif #if defined (__386BSD__) - printf ("i386-unknown-bsd\n"); exit (0); + printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) @@ -440,7 +500,18 @@ main () #endif #if defined (_SEQUENT_) - printf ("i386-sequent-ptx\n"); exit (0); + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + #endif #if defined (vax) diff --git a/config.sub b/config.sub index 5641cc1ce6..27819cc8dc 100755 --- a/config.sub +++ b/config.sub @@ -1,9 +1,9 @@ #! /bin/sh # Configuration validation subroutine script, version 1.1. -# Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +# Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. +# can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -17,7 +17,8 @@ # # 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. +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -40,6 +41,8 @@ # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. if [ x$1 = x ] @@ -61,11 +64,21 @@ case $1 in ;; esac -# Separate what the user gave into CPU-COMPANY and OS (if any). -basic_machine=`echo $1 | sed 's/-[^-]*$//'` -if [ $basic_machine != $1 ] -then os=`echo $1 | sed 's/.*-/-/'` -else os=; fi +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + linux-gnu*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also @@ -80,38 +93,43 @@ case $os in -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp ) + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple) os= basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; + -sco5) + os=sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; -sco4) os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-unknown/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos @@ -122,33 +140,43 @@ case $os in -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; + -psos*) + os=-psos + ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. - tahoe | i[345]86 | i860 | m68k | m68000 | m88k | ns32k | arm | pyramid \ + tahoe | i860 | m68k | m68000 | m88k | ns32k | arm \ + | arme[lb] | pyramid \ | tron | a29k | 580 | i960 | h8300 | hppa1.0 | hppa1.1 \ - | alpha | we32k | ns16k | clipper | sparclite | i370 | sh \ - | powerpc | sparc64 | 1750a | dsp16xx | mips64 | mipsel \ + | alpha | we32k | ns16k | clipper | i370 | sh \ + | powerpc | powerpcle | 1750a | dsp16xx | mips64 | mipsel \ | pdp11 | mips64el | mips64orion | mips64orionel \ - | sparc) - basic_machine=$basic_machine-unknown - ;; + | sparc | sparclet | sparclite | sparc64) + basic_machine=$basic_machine-unknown + ;; + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i[3456]86) + basic_machine=$basic_machine-pc + ;; # Object if more than one company name word. *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 ;; # Recognize the basic CPU types with company name. - vax-* | tahoe-* | i[345]86-* | i860-* | m68k-* | m68000-* | m88k-* \ + vax-* | tahoe-* | i[3456]86-* | i860-* | m68k-* | m68000-* | m88k-* \ | sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \ - | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \ | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \ | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \ | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \ - | pdp11-* | sh-* | powerpc-* | sparc64-* | mips64-* | mipsel-* \ + | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \ | mips64el-* | mips64orion-* | mips64orionel-*) ;; # Recognize the various machine names and aliases which stand @@ -188,6 +216,10 @@ case $basic_machine in basic_machine=m68k-apollo os=-sysv ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; balance) basic_machine=ns32k-sequent os=-dynix @@ -220,6 +252,10 @@ case $basic_machine in basic_machine=cray2-cray os=-unicos ;; + [ctj]90-cray) + basic_machine=c90-cray + os=-unicos + ;; crds | unos) basic_machine=m68k-crds ;; @@ -256,6 +292,10 @@ case $basic_machine in encore | umax | mmax) basic_machine=ns32k-encore ;; + ews4800) + basic_machine=mips-nec + os=-sysv4 + ;; fx2800) basic_machine=i860-alliant ;; @@ -306,20 +346,20 @@ case $basic_machine in os=-mvs ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? - i[345]86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'` + i[3456]86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; - i[345]86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'` + i[3456]86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; - i[345]86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'` + i[3456]86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; - i[345]86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-unknown/'` + i[3456]86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; iris | iris4d) @@ -417,14 +457,41 @@ case $basic_machine in pc532 | pc532-*) basic_machine=ns32k-pc532 ;; - pentium-*) - # We will change tis to say i586 once there has been - # time for various packages to start to recognize that. - basic_machine=i486-`echo $basic_machine | sed 's/^[^-]*-//'` + pentium | p5) + basic_machine=i586-intel + ;; + pentiumpro | p6) + basic_machine=i686-intel + ;; + pentium-* | p5-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + k5) + # We don't have specific support for AMD's K5 yet, so just call it a Pentium + basic_machine=i586-amd + ;; + nexen) + # We don't have specific support for Nexgen yet, so just call it a Pentium + basic_machine=i586-nexgen ;; pn) basic_machine=pn-gould ;; + power) basic_machine=rs6000-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; ps2) basic_machine=i386-ibm ;; @@ -519,6 +586,10 @@ case $basic_machine in basic_machine=m68k-wrs os=-vxworks ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; xmp) basic_machine=xmp-cray os=-unicos @@ -586,6 +657,8 @@ esac if [ x"$os" != x"" ] then case $os in + # First match some system type aliases + # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` @@ -597,21 +670,25 @@ case $os in os=-sysv4 ;; -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux|'` + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # 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. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[345]* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ - | -amigados* | -msdos* | -newsos* | -unicos* | -aos* \ + | -amigados* | -msdos* | -newsos* | -unicos* | -aof* | -aos* \ | -nindy* | -vxworks* | -ebmon* | -hms* | -mvs* | -clix* \ - | -riscos* | -linux* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -netbsd* | -freebsd* | -riscix* \ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta | -udi | -eabi) + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -cygwin32* | -pe* | -psos* | -moss* | -proelf* \ + | -linux*) + # Remember, each alternative MUST END IN *, to match a version number. ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` @@ -637,6 +714,9 @@ case $os in -ctix* | -uts*) os=-sysv ;; + -ns2 ) + os=-nextstep2 + ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` @@ -690,6 +770,9 @@ case $basic_machine in *-acorn) os=-riscix1.2 ;; + arm*-semi) + os=-aout + ;; pdp11-*) os=-none ;; @@ -741,6 +824,9 @@ case $basic_machine in m88k-omron*) os=-luna ;; + *-next ) + os=-nextstep + ;; *-sequent) os=-ptx ;; @@ -825,6 +911,9 @@ case $basic_machine in -vxworks*) vendor=wrs ;; + -aux*) + vendor=apple + ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; diff --git a/configure.bat b/configure.bat new file mode 100644 index 0000000000..84e5191bbe --- /dev/null +++ b/configure.bat @@ -0,0 +1,5 @@ +@echo off
+sed -f top.sed Makefile.in >Makefile
+sed -f top.sed ext/extmk.rb.in > ext\extmk.rb
+copy ext\Setup.dj ext\Setup
+copy config.dj config.h
diff --git a/configure.in b/configure.in index fc87754cb8..7f89f5e69c 100644 --- a/configure.in +++ b/configure.in @@ -21,6 +21,17 @@ then (it is also a good idea to do 'make clean' before compiling)) 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(THREAD) +fi + +AC_CANONICAL_HOST + dnl Checks for programs. AC_PROG_CC AC_PROG_GCC_TRADITIONAL @@ -29,19 +40,18 @@ AC_PROG_INSTALL AC_PROG_MAKE_SET # checks for UNIX variants that set C preprocessor variables -AC_AIX AC_MINIX dnl Checks for libraries. AC_CHECK_LIB(crypt, crypt) -AC_CHECK_LIB(dl, dlopen, [:]) # Dynamic linking for SunOS/Solaris and SYSV +AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX dnl Checks for header files. AC_HEADER_DIRENT AC_HEADER_STDC -AC_CHECK_HEADERS(limits.h sys/file.h sys/ioctl.h pwd.h\ - sys/time.h sys/times.h sys/param.h unistd.h\ +AC_CHECK_HEADERS(unistd.h limits.h sys/file.h sys/ioctl.h pwd.h sys/select.h\ + sys/time.h sys/times.h sys/param.h sys/wait.h\ syscall.h a.out.h string.h utime.h memory.h) dnl Checks for typedefs, structures, and compiler characteristics. @@ -57,40 +67,75 @@ AC_TYPE_SIGNAL AC_FUNC_ALLOCA AC_FUNC_VFORK AC_REPLACE_FUNCS(dup2 setenv memmove mkdir strerror strftime\ - strstr strtoul strdup crypt) + strstr strtoul strdup strcasecmp crypt flock) AC_CHECK_FUNCS(fmod killpg random wait4 waitpid syscall getcwd\ - truncate chsize times utimes fcntl\ + truncate chsize times utimes fcntl lockf setitimer\ setruid seteuid setreuid setrgid setegid setregid\ - getgroups getpriority sigprocmask dlopen) -if test "$ac_cv_func strftime" = no; then + getgroups getpgid getpriority dlopen sigprocmask sigaction) +if test "$ac_cv_func_strftime" = no; then AC_STRUCT_TIMEZONE AC_TRY_LINK([], [extern int daylight; int i = daylight;], AC_DEFINE(HAVE_DAYLIGHT)) fi +if test "$ac_cv_func_sigprocmask" = yes && test "$ac_cv_func_sigaction" = yes; then + AC_DEFINE(POSIX_SIGNAL) +else + AC_MSG_CHECKING(for BSD signal semantics) + AC_CACHE_VAL(rb_cv_bsd_signal, + [AC_TRY_RUN([ +#include <stdio.h> +#include <signal.h> + +void sig_handler(dummy) + int dummy; +{ +} + +int main(argc, argv) + int argc; + char ** argv; +{ + signal(SIGINT, sig_handler); + kill(getpid(), SIGINT); + kill(getpid(), SIGINT); + return 0; +} +], + rb_cv_bsd_signal=yes, + rb_cv_bsd_signal=no, + [:])]) + AC_MSG_RESULT($rb_cv_bsd_signal) + if test "$rb_cv_bsd_signal" = yes; then + AC_DEFINE(BSD_SIGNAL) + fi +fi + AC_C_BIGENDIAN +AC_CHAR_UNSIGNED AC_MSG_CHECKING([count field in FILE structures]) AC_CACHE_VAL(rb_cv_fcnt, [AC_TRY_COMPILE([#include <stdio.h>], [FILE *f = stdin; f->_cnt = 0;], rb_cv_fcnt="_cnt", ) -if test "$rb_cv_fcnt=" = ""; then +if test "$rb_cv_fcnt" = ""; then AC_TRY_COMPILE([#include <stdio.h>], [FILE *f = stdin; f->__cnt = 0;], rb_cv_fcnt="__cnt", ) fi -if test "$rb_cv_fcnt=" = ""; then +if test "$rb_cv_fcnt" = ""; then AC_TRY_COMPILE([#include <stdio.h>], [FILE *f = stdin; f->_r = 0;], rb_cv_fcnt="_r", ) fi -if test "$rb_cv_fcnt=" = ""; then +if test "$rb_cv_fcnt" = ""; then AC_TRY_COMPILE([#include <stdio.h>], - [FILE *f = stdin; f->readCount = 0;], rb_cv_fcnt="readCount", ) + [FILE *f = stdin; f->readCount = 0;], + rb_cv_fcnt="readCount", rb_cv_fcnt="not found") fi]) -if test "$rb_cv_fcnt"; then +if test "$rb_cv_fcnt" = "not found"; then + AC_MSG_RESULT([not found(OK if using GNU libc)]) +else AC_MSG_RESULT($rb_cv_fcnt) AC_DEFINE_UNQUOTED(FILE_COUNT, $rb_cv_fcnt) -else - AC_MSG_RESULT([not found(OK if using GNU libc)]) fi if test "$ac_cv_func_getpwent" = yes; then @@ -105,31 +150,45 @@ if test "$ac_cv_func_getpwent" = yes; then fi 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 yes) with_dln_a_out=yes;; *) with_dln_a_out=no;; esac], [with_dln_a_out=no]) -if test "$with_dln_a_out" = yes && test "$ac_cv_header_a_out_h" = yes; then - - AC_MSG_CHECKING(whether matz's dln works) - cat confdefs.h > config.h - AC_CACHE_VAL(rb_cv_dln_a_out, - [AC_TRY_COMPILE([ -#define USE_DLN_A_OUT -#include "dln.c" +case "$host_os" in + linux*) + AC_MSG_CHECKING(whether ELF binaries are produced) + AC_CACHE_VAL(rb_cv_linux_elf, + [AC_TRY_RUN([ +/* Test for whether ELF binaries are produced */ +#include <fcntl.h> +#include <stdlib.h> +main() { + char buffer[4]; + int i=open("conftest",O_RDONLY); + if(i==-1) + exit(1); /* fail */ + if(read(i,&buffer[0],4)<4) + exit(1); /* fail */ + if(buffer[0] != 127 || buffer[1] != 'E' || + buffer[2] != 'L' || buffer[3] != 'F') + exit(1); /* fail */ + exit(0); /* succeed (yes, it's ELF) */ +} ], - [], - rb_cv_dln_a_out=yes, - rb_cv_dln_a_out=no)]) - AC_MSG_RESULT($rb_cv_dln_a_out) - if test "$rb_cv_dln_a_out" = yes; then - AC_DEFINE(USE_DLN_A_OUT) - fi -else - rb_cv_dln_a_out=no -fi + rb_cv_linux_elf=yes, + rb_cv_linux_elf=no, + [:])]) + AC_MSG_RESULT($rb_cv_linux_elf) + if test "$rb_cv_linux_elf" = no; then + with_dln_a_out=yes + else + LDFLAGS="-rdynamic" + fi;; +esac + +AC_SUBST(DLDFLAGS)dnl AC_SUBST(STATIC)dnl AC_SUBST(CCDLFLAGS)dnl @@ -138,7 +197,63 @@ AC_SUBST(DLEXT)dnl STATIC= -if test "$rb_cv_dln_a_out" = yes; then +if test "$with_dln_a_out" != yes; then + rb_cv_dlopen=unknown + AC_MSG_CHECKING(whether OS depend dynamic link works) + if test "$GCC" = yes; then + CCDLFLAGS=-fpic + else + case "$host_os" in + hpux*) CCDLFLAGS='+z';; + solaris*|irix*) CCDLFLAGS='-K pic' ;; + sunos*) CCDLFLAGS='-pic' ;; + svr4*|esix*) CCDLFLAGS='-Kpic' ;; + *) CCDLFLAGS='' ;; + esac + fi + + case "$host_os" in + hpux*) DLDFLAGS="-E" + LDSHARED='ld -b' + LDFLAGS="-Wl,-E" + rb_cv_dlopen=yes;; + solaris*) LDSHARED='ld -G' + rb_cv_dlopen=yes;; + sunos*) LDSHARED='ld -assert nodefinitions' + rb_cv_dlopen=yes;; + svr4*|esix*) LDSHARED="ld -G" + rb_cv_dlopen=yes ;; + linux*) LDSHARED="gcc -shared" + rb_cv_dlopen=yes ;; + freebsd*) LDSHARED="ld -Bshareable" + rb_cv_dlopen=yes ;; + *) LDSHARED='ld' ;; + esac + AC_MSG_RESULT($rb_cv_dlopen) +fi + +dln_a_out_works=no +if test "$ac_cv_header_a_out_h" = yes; 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 + AC_CACHE_VAL(rb_cv_dln_a_out, + [AC_TRY_COMPILE([ +#define USE_DLN_A_OUT +#include "dln.c" +], + [], + rb_cv_dln_a_out=yes, + rb_cv_dln_a_out=no)]) + AC_MSG_RESULT($rb_cv_dln_a_out) + if test "$rb_cv_dln_a_out" = yes; then + dln_a_out_works=yes + AC_DEFINE(USE_DLN_A_OUT) + fi + fi +fi + +if test "$dln_a_out_works" = yes; then if test "$GCC" = yes; then STATIC=-static else @@ -147,45 +262,48 @@ if test "$rb_cv_dln_a_out" = yes; then DLEXT=o AC_DEFINE(DLEXT, ".o") CCDLFLAGS= - LDCMD= - else - - AC_CANONICAL_HOST case "$host_os" in hpux*) DLEXT=sl AC_DEFINE(DLEXT, ".sl");; + nextstep*) DLEXT=o + AC_DEFINE(DLEXT, ".o");; *) DLEXT=so AC_DEFINE(DLEXT, ".so");; esac +fi - if test "$GCC" = yes; then - CCDLFLAGS=-fpic - else - case "$host_os" in - hpux*) CCDLFLAGS='+z';; - solaris*|irix*) CCDLFLAGS='-K pic' ;; - sunos*) CCDLFLAGS='-pic' ;; - svr4*|esix*) CCDLFLAGS='-Kpic' ;; - *) CCDLFLAGS='' ;; - esac - fi - - case "$host_os" in - hpux*) LDSHARED='ld -b' ;; - solaris*) LDSHARED='ld -G' ;; - sunos*) LDSHARED='ld -assert nodefinitions' ;; - svr4*|esix*) LDSHARED="ld -G" ;; - linux*) LDSHARED="gcc-elf -shared" ;; - *) LDSHARED='ld' ;; - esac +AC_SUBST(STRIP)dnl +if test "$with_dln_a_out" = yes; then + STRIP=true +else + STRIP=strip fi +case "$host_os" in + linux*) + STRIP='strip -S -x';; + nextstep*) + STRIP='strip -A -n';; +esac + +EXTSTATIC= +AC_SUBST(EXTSTATIC)dnl +AC_ARG_WITH(static-linked-ext, + [--with-static-linked-ext link external modules statically], + [case $withval in + yes) STATIC= + EXTSTATIC=static;; + *) ;; + esac]) + if test "$prefix" = NONE; then - AC_DEFINE_UNQUOTED(RUBY_LIB, ".:${ac_default_prefix}/lib/ruby") -else - AC_DEFINE_UNQUOTED(RUBY_LIB, ".:${prefix}/lib/ruby") + prefix=$ac_default_prefix fi +AC_DEFINE_UNQUOTED(RUBY_LIB, "${prefix}/lib/ruby:.") +AC_SUBST(archlib)dnl +archlib="${prefix}/lib/ruby/${host_cpu}-${host_os}" +AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "$archlib") echo "creating config.h" cat confdefs.h > config.h @@ -16,10 +16,21 @@ #define EUC #undef SJIS -#define SAFE_SIGHANDLE +#ifdef NeXT +#define S_IXUSR _S_IXUSR /* execute/search permission, owner */ +#define S_IXGRP 0000010 /* execute/search permission, group */ +#define S_IXOTH 0000001 /* execute/search permission, other */ +#define S_ISREG(mode) (((mode) & (_S_IFMT)) == (_S_IFREG)) +#endif /* NeXT */ #ifdef NT #include "missing/nt.h" #endif +#ifdef sparc +#define FLUSH_REGISTER_WINDOWS asm("ta 3") +#else +#define FLUSH_REGISTER_WINDOWS /* empty */ +#endif + #endif @@ -6,7 +6,7 @@ $Date: 1995/01/10 10:42:28 $ created at: Wed Jan 5 09:51:01 JST 1994 - Copyright (C) 1993-1995 Yukihiro Matsumoto + Copyright (C) 1993-1996 Yukihiro Matsumoto ************************************************/ @@ -43,10 +43,11 @@ # endif #endif +#include <errno.h> + char *getenv(); static VALUE cDir; -static ID id_dir; static void free_dir(dir) @@ -66,11 +67,17 @@ dir_s_open(dir_class, dirname) Check_Type(dirname, T_STRING); dirp = opendir(dirname->ptr); - if (dirp == NULL) Fail("Can't open directory %s", dirname->ptr); + if (dirp == NULL) { + if (errno == EMFILE || errno == ENFILE) { + gc(); + dirp = opendir(dirname->ptr); + } + if (dirp == NULL) { + rb_sys_fail(dirname->ptr); + } + } - obj = obj_alloc(dir_class); - if (!id_dir) id_dir = rb_intern("dir"); - Make_Data_Struct(obj, id_dir, DIR*, 0, free_dir, d); + obj = Make_Data_Struct(dir_class, DIR*, 0, free_dir, d); *d = dirp; return obj; @@ -84,8 +91,7 @@ closeddir() #define GetDIR(obj, dirp) {\ DIR **_dp;\ - if (!id_dir) id_dir = rb_intern("dir");\ - Get_Data_Struct(obj, id_dir, DIR*, _dp);\ + Get_Data_Struct(obj, DIR*, _dp);\ dirp = *_dp;\ if (dirp == NULL) closeddir();\ } @@ -94,14 +100,14 @@ static VALUE dir_each(dir) VALUE dir; { - extern VALUE rb_lastline; DIR *dirp; struct dirent *dp; + VALUE file; GetDIR(dir, dirp); for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { - rb_lastline = str_new(dp->d_name, NAMLEN(dp)); - rb_yield(rb_lastline); + file = str_new(dp->d_name, NAMLEN(dp)); + rb_yield(file); } return dir; } @@ -113,9 +119,13 @@ dir_tell(dir) DIR *dirp; int pos; +#if !defined(__CYGWIN32__) GetDIR(dir, dirp); pos = telldir(dirp); return int2inum(pos); +#else + rb_notimplement(); +#endif } static VALUE @@ -124,9 +134,13 @@ dir_seek(dir, pos) { DIR *dirp; +#if !defined(__CYGWIN32__) GetDIR(dir, dirp); seekdir(dirp, NUM2INT(pos)); return dir; +#else + rb_notimplement(); +#endif } static VALUE @@ -146,8 +160,8 @@ dir_close(dir) { DIR **dirpp; - Get_Data_Struct(dir, id_dir, DIR*, dirpp); - if (*dirpp == NULL) Fail("already closed directory"); + Get_Data_Struct(dir, DIR*, dirpp); + if (*dirpp == NULL) closeddir(); closedir(*dirpp); *dirpp = NULL; @@ -176,7 +190,7 @@ dir_s_chdir(argc, argv, obj) } if (chdir(dist) < 0) - rb_sys_fail(Qnil); + rb_sys_fail(0); return INT2FIX(0); } @@ -189,9 +203,9 @@ dir_s_getwd(dir) char path[MAXPATHLEN]; #ifdef HAVE_GETCWD - if (getcwd(path, sizeof(path)) == 0) Fail(path); + if (getcwd(path, sizeof(path)) == 0) rb_sys_fail(path); #else - if (getwd(path) == 0) Fail(path); + if (getwd(path) == 0) rb_sys_fail(path); #endif return str_new2(path); @@ -201,12 +215,16 @@ static VALUE dir_s_chroot(dir, path) VALUE dir, path; { +#if !defined(DJGPP) && !defined(__CYGWIN32__) Check_Type(path, T_STRING); if (chroot(RSTRING(path)->ptr) == -1) - rb_sys_fail(Qnil); + rb_sys_fail(0); return INT2FIX(0); +#else + rb_notimplement(); +#endif } static VALUE @@ -346,6 +364,17 @@ dir_s_glob(dir, str) return ary; } +static VALUE +dir_foreach(io, dirname) + VALUE io; + struct RString *dirname; +{ + VALUE dir; + + dir = dir_s_open(cDir, dirname); + return rb_ensure(dir_each, dir, dir_close, dir); +} + void Init_Dir() { @@ -356,6 +385,7 @@ Init_Dir() rb_include_module(cDir, mEnumerable); rb_define_singleton_method(cDir, "open", dir_s_open, 1); + rb_define_singleton_method(cDir, "foreach", dir_foreach, 1); rb_define_method(cDir,"each", dir_each, 0); rb_define_method(cDir,"rewind", dir_rewind, 0); @@ -6,10 +6,14 @@ $Date: 1994/12/09 01:28:23 $ created at: Tue Jan 18 17:05:06 JST 1994 - Copyright (C) 1993-1995 Yukihiro Matsumoto + Copyright (C) 1993-1996 Yukihiro Matsumoto ************************************************/ +#ifdef _AIX +#pragma alloca +#endif + #include "config.h" #include "defines.h" #include "dln.h" @@ -57,7 +61,7 @@ int eaccess(); #endif #ifndef FUNCNAME_PATTERN -# if defined(hpux) || defined(__NetBSD__) || defined(__BORLANDC__) +# if defined(__hp9000s300) || defined(__NetBSD__) || defined(__BORLANDC__) || defined(__FreeBSD__) # define FUNCNAME_PATTERN "_Init_%.200s" # else # define FUNCNAME_PATTERN "Init_%.200s" @@ -276,7 +280,7 @@ sym_hash(hdrp, syms) struct nlist *sym = syms; struct nlist *end = syms + (hdrp->a_syms / sizeof(struct nlist)); - tbl = st_init_table(strcmp, st_strhash); + tbl = st_init_strtable(); if (tbl == NULL) { dln_errno = errno; return NULL; @@ -345,12 +349,11 @@ dln_init(prog) p++; } *p = '\0'; - printf("%s\n", buf); return dln_init(buf); } dln_init_p = 1; - undef_tbl = st_init_table(strcmp, st_strhash); + undef_tbl = st_init_strtable(); close(fd); return 0; @@ -462,7 +465,7 @@ link_undef(name, base, reloc) break; } if (reloc_tbl == NULL) { - reloc_tbl = st_init_table(ST_NUMCMP, ST_NUMHASH); + reloc_tbl = st_init_numtable(); } st_insert(reloc_tbl, u_no++, obj); } @@ -548,6 +551,25 @@ unlink_undef(name, value) st_foreach(reloc_tbl, reloc_undef, &arg); } +#ifdef N_INDR +struct indr_data { + char *name0, *name1; +}; + +static int +reloc_repl(no, undef, data) + int no; + struct undef *undef; + struct indr_data *data; +{ + if (strcmp(data->name0, undef->name) == 0) { + free(undef->name); + undef->name = strdup(data->name1); + } + return ST_CONTINUE; +} +#endif + static int load_1(fd, disp, need_init) int fd; @@ -581,6 +603,32 @@ load_1(fd, disp, need_init) struct nlist *old_sym; int value = sym->n_value; +#ifdef N_INDR + if (sym->n_type == (N_INDR | N_EXT)) { + char *key = sym->n_un.n_name; + + if (st_lookup(sym_tbl, sym[1].n_un.n_name, &old_sym)) { + if (st_delete(undef_tbl, &key, NULL)) { + unlink_undef(key, old_sym->n_value); + free(key); + } + } + else { + struct indr_data data; + + data.name0 = sym->n_un.n_name; + data.name1 = sym[1].n_un.n_name; + st_foreach(reloc_tbl, reloc_repl, &data); + + st_insert(undef_tbl, strdup(sym[1].n_un.n_name), NULL); + if (st_delete(undef_tbl, &key, NULL)) { + free(key); + } + } + sym += 2; + continue; + } +#endif if (sym->n_type == (N_UNDF | N_EXT)) { if (st_lookup(sym_tbl, sym->n_un.n_name, &old_sym) == 0) { old_sym = NULL; @@ -624,7 +672,7 @@ load_1(fd, disp, need_init) sym = syms; while (sym < end) { struct nlist *new_sym; - char *key; + char *key, *name; switch (sym->n_type) { case N_COMM: @@ -764,7 +812,7 @@ load_1(fd, disp, need_init) if (strcmp(name+1, "libs_to_be_linked") == 0) { libs_to_be_linked = (char**)sym->n_value; } - if (strcmp(name+1, buf) == 0) { + else if (strcmp(name+1, buf) == 0) { init_p = 1; ((int (*)())sym->n_value)(); } @@ -808,6 +856,7 @@ search_undef(key, value, lib_tbl) int value; st_table *lib_tbl; { +#if 0 static char *last = ""; int offset; @@ -817,6 +866,13 @@ search_undef(key, value, lib_tbl) target_offset = offset; } return ST_STOP; +#else + int offset; + + if (st_lookup(lib_tbl, key, &offset) == 0) return ST_CONTINUE; + target_offset = offset; + return ST_STOP; +#endif } struct symdef { @@ -879,7 +935,7 @@ load_lib(lib) if (strncmp(ahdr.ar_name, "__.SYMDEF", 9) == 0) { /* make hash table from __.SYMDEF */ - lib_tbl = st_init_table(strcmp, st_strhash); + lib_tbl = st_init_strtable(); data = (int*)xmalloc(size); if (data == NULL) goto syserr; size = read(fd, data, size); @@ -1020,6 +1076,11 @@ dln_sym(name) #include <ctype.h> /* for isdigit() */ #include <errno.h> /* for global errno */ #include <string.h> /* for strerror() */ +#include <sys/ldr.h> +#endif + +#ifdef NeXT +/*#include <mach-o/rld.h>*/ #endif static char * @@ -1095,8 +1156,8 @@ aix_loaderror(char *pathname) ERRBUF_APPEND("\n"); } errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */ - Fail(errbuf); -return; + LoadError(errbuf); + return; } #endif @@ -1125,9 +1186,12 @@ dln_load(file) # ifndef RTLD_LAZY # define RTLD_LAZY 1 # endif +# ifndef RTLD_GLOBAL +# define RTLD_GLOBAL 0 +# endif /* Load file */ - if ((handle = dlopen(file, RTLD_LAZY)) == NULL) { + if ((handle = dlopen(file, RTLD_LAZY|RTLD_GLOBAL)) == NULL) { goto failed; } @@ -1150,13 +1214,14 @@ dln_load(file) flags = BIND_DEFERRED; lib = shl_load(file, flags, 0); if (lib == NULL) { - char buf[256]; - Fail("Failed to load %.200s", file); + rb_sys_fail(file); } shl_findsym(&lib, buf, TYPE_PROCEDURE, (void*)&init_fct); if (init_fct == NULL) { - shl_findsym(&lib, buf, TYPE_DATA, (void*)&init_fct); + shl_findsym(&lib, buf, TYPE_UNDEFINED, (void*)&init_fct); if (init_fct == NULL) { + extern int errno; + errno = ENOSYM; rb_sys_fail(file); } } @@ -1179,14 +1244,54 @@ dln_load(file) } #endif /* _AIX */ +#ifdef NeXT +#define DLN_DEFINED +/*---------------------------------------------------- + By SHIROYAMA Takayuki Psi@fortune.nest.or.jp + + Special Thanks... + Yu tomoak-i@is.aist-nara.ac.jp, + Mi hisho@tasihara.nest.or.jp, + and... Miss ARAI Akino(^^;) + ----------------------------------------------------*/ + { + unsigned long init_address; + char *object_files[2] = {NULL, NULL}; + + void (*init_fct)(); + int len = strlen(file); + char *point; + char init_name[len +7]; + + object_files[0] = file; + + /* Load object file, if return value ==0 , load failed*/ + if(rld_load(NULL, NULL, object_files, NULL) == 0) { + LoadError("Failed to load %.200s", file); + } + + /* lookup the initial function */ + if(rld_lookup(NULL, buf, &init_address) == 0) { + LoadError("Failed to lookup Init function %.200s",file); + } + + /* Cannot call *init_address directory, so copy this value to + funtion pointer */ + + init_fct = (void(*)())init_address; + (*init_fct)(); + return ; + } +#endif + #ifndef DLN_DEFINED - Fail("dynamic link not supported"); + rb_notimplement("dynamic link not supported"); #endif #endif /* USE_DLN_A_OUT */ -#ifndef _AIX +#if !defined(_AIX) && !defined(NeXT) failed: - Fail("%s - %s", dln_strerror(), file); + LoadError("%s - %s", dln_strerror(), file); #endif } @@ -1228,8 +1333,7 @@ dln_find_1(fname, path, exe_flag) if (strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0) return fname; - for (dp = path;; dp = ++ep) - { + for (dp = path;; dp = ++ep) { register int l; int i; int fspace; @@ -1243,8 +1347,7 @@ dln_find_1(fname, path, exe_flag) l = ep - dp; bp = fbuf; fspace = sizeof fbuf - 2; - if (l > 0) - { + if (l > 0) { /* ** If the length of the component is zero length, ** start from the current directory. If the @@ -1253,13 +1356,11 @@ dln_find_1(fname, path, exe_flag) ** take the path literally. */ - if (*dp == '~' && (l == 1 || dp[1] == '/')) - { + if (*dp == '~' && (l == 1 || dp[1] == '/')) { char *home; home = getenv("HOME"); - if (home != NULL) - { + if (home != NULL) { i = strlen(home); if ((fspace -= i) < 0) goto toolong; @@ -1269,8 +1370,7 @@ dln_find_1(fname, path, exe_flag) dp++; l--; } - if (l > 0) - { + if (l > 0) { if ((fspace -= l) < 0) goto toolong; memcpy(bp, dp, l); @@ -1284,9 +1384,8 @@ dln_find_1(fname, path, exe_flag) /* now append the file name */ i = strlen(fname); - if ((fspace -= i) < 0) - { - toolong: + if ((fspace -= i) < 0) { + toolong: fprintf(stderr, "openpath: pathname too long (ignored)\n"); *bp = '\0'; fprintf(stderr, "\tDirectory \"%s\"\n", fbuf); @@ -6,20 +6,19 @@ $Date: 1995/01/10 10:42:29 $ created at: Fri Oct 1 15:15:19 JST 1993 - Copyright (C) 1993-1995 Yukihiro Matsumoto + Copyright (C) 1993-1996 Yukihiro Matsumoto ************************************************/ #include "ruby.h" VALUE mEnumerable; -static ID id_each, id_match, id_cmp; +static ID id_each, id_eqq, id_cmp; void rb_each(obj) VALUE obj; { - if (!id_each) id_each = rb_intern("each"); rb_funcall(obj, id_each, 0, 0); } @@ -27,8 +26,7 @@ static void grep_i(i, arg) VALUE i, *arg; { - if (!id_match) id_match = rb_intern("=~"); - if (rb_funcall(arg[0], id_match, 1, i)) { + if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) { ary_push(arg[1], i); } } @@ -37,8 +35,7 @@ static void grep_iter_i(i, pat) VALUE i, pat; { - if (!id_match) id_match = rb_intern("=~"); - if (rb_funcall(pat, id_match, 1, i)) { + if (RTEST(rb_funcall(pat, id_eqq, 1, i))) { rb_yield(i); } } @@ -61,33 +58,47 @@ enum_grep(obj, pat) } } +struct find_arg { + int found; + VALUE val; +}; + static void -find_i(i, foundp) +find_i(i, arg) VALUE i; - int *foundp; + struct find_arg *arg; { - if (rb_yield(i)) { - *foundp = TRUE; + if (RTEST(rb_yield(i))) { + arg->found = TRUE; + arg->val = i; rb_break(); } } static VALUE -enum_find(obj) +enum_find(argc, argv, obj) + int argc; + VALUE argv; VALUE obj; { - int enum_found; - - enum_found = FALSE; - rb_iterate(rb_each, obj, find_i, &enum_found); - return enum_found; + struct find_arg arg; + VALUE if_none; + + rb_scan_args(argc, argv, "01", &if_none); + arg.found = FALSE; + rb_iterate(rb_each, obj, find_i, &arg); + if (arg.found) { + return arg.val; + } + if (NIL_P(if_none)) return Qnil; + return rb_eval_cmd(if_none, Qnil); } static void find_all_i(i, tmp) VALUE i, tmp; { - if (rb_yield(i)) { + if (RTEST(rb_yield(i))) { ary_push(tmp, i); } } @@ -99,7 +110,7 @@ enum_find_all(obj) VALUE tmp; tmp = ary_new(); - rb_iterate(rb_each, obj, find_all_i, 0); + rb_iterate(rb_each, obj, find_all_i, tmp); return tmp; } @@ -111,7 +122,7 @@ collect_i(i, tmp) VALUE retval; retval = rb_yield(i); - if (retval) { + if (RTEST(retval)) { ary_push(tmp, retval); } } @@ -179,23 +190,37 @@ min_i(i, min) { VALUE cmp; - if (*min == Qnil) + if (NIL_P(*min)) *min = i; else { - if (!id_cmp) id_cmp = rb_intern("<=>"); cmp = rb_funcall(i, id_cmp, 1, *min); if (FIX2INT(cmp) < 0) *min = i; } } +static void +min_ii(i, min) + VALUE i, *min; +{ + VALUE cmp; + + if (NIL_P(*min)) + *min = i; + else { + cmp = rb_yield(assoc_new(i, *min)); + if (FIX2INT(cmp) < 0) + *min = i; + } +} + static VALUE enum_min(obj) VALUE obj; { VALUE min = Qnil; - rb_iterate(rb_each, obj, min_i, &min); + rb_iterate(rb_each, obj, iterator_p()?min_ii:min_i, &min); return min; } @@ -205,23 +230,37 @@ max_i(i, max) { VALUE cmp; - if (*max == Qnil) + if (NIL_P(*max)) *max = i; else { - if (!id_cmp) id_cmp = rb_intern("<=>"); cmp = rb_funcall(i, id_cmp, 1, *max); if (FIX2INT(cmp) > 0) *max = i; } } +static void +max_ii(i, max) + VALUE i, *max; +{ + VALUE cmp; + + if (NIL_P(*max)) + *max = i; + else { + cmp = rb_yield(assoc_new(i, *max)); + if (FIX2INT(cmp) > 0) + *max = i; + } +} + static VALUE enum_max(obj) VALUE obj; { VALUE max = Qnil; - rb_iterate(rb_each, obj, max_i, &max); + rb_iterate(rb_each, obj, iterator_p()?max_ii:max_i, &max); return max; } @@ -291,7 +330,7 @@ length_i(i, length) (*length)++; } -static VALUE +VALUE enum_length(obj) VALUE obj; { @@ -310,7 +349,7 @@ Init_Enumerable() rb_define_method(mEnumerable,"sort", enum_sort, 0); rb_define_method(mEnumerable,"grep", enum_grep, 1); - rb_define_method(mEnumerable,"find", enum_find, 0); + rb_define_method(mEnumerable,"find", enum_find, -1); rb_define_method(mEnumerable,"find_all", enum_find_all, 0); rb_define_method(mEnumerable,"collect", enum_collect, 0); rb_define_method(mEnumerable,"reverse", enum_reverse, 0); @@ -319,4 +358,9 @@ Init_Enumerable() rb_define_method(mEnumerable,"index", enum_index, 1); rb_define_method(mEnumerable,"member?", enum_member, 1); rb_define_method(mEnumerable,"length", enum_length, 0); + rb_define_method(mEnumerable,"size", enum_length, 0); + + id_eqq = rb_intern("==="); + id_each = rb_intern("each"); + id_cmp = rb_intern("<=>"); } @@ -16,9 +16,11 @@ extern struct FRAME { VALUE *argv; ID last_func; struct RClass *last_class; + VALUE cbase; struct FRAME *prev; char *file; int line; + int iter; } *the_frame; extern struct SCOPE { @@ -28,8 +30,9 @@ extern struct SCOPE { int flag; } *the_scope; -#define SCOPE_ALLOCA 0 -#define SCOPE_MALLOC 1 +#define SCOPE_ALLOCA 0 +#define SCOPE_MALLOC 1 +#define SCOPE_NOSTACK 2 extern int rb_in_eval; @@ -6,7 +6,7 @@ $Date: 1995/01/10 10:42:31 $ created at: Mon Aug 9 16:11:34 JST 1993 - Copyright (C) 1993-1995 Yukihiro Matsumoto + Copyright (C) 1993-1996 Yukihiro Matsumoto ************************************************/ @@ -32,32 +32,41 @@ err_sprintf(buf, fmt, args) sprintf(buf, "%s:%d: ", sourcefile, sourceline); vsprintf((char*)buf+strlen(buf), fmt, args); } - if (buf[strlen(buf)-1] != '\n') - strcat(buf, "\n"); } static void -err_print(fmt, args) - char *fmt; - va_list args; +err_append(s) + char *s; { - extern errstr; - char buf[BUFSIZ]; + extern VALUE errinfo; - err_sprintf(buf, fmt, args); if (rb_in_eval) { - if (errstr == Qnil) { - errstr = str_new2(buf); + if (NIL_P(errinfo)) { + errinfo = str_new2(s); } else { - str_cat(errstr, buf, strlen(buf)); + str_cat(errinfo, "\n", 1); + str_cat(errinfo, s, strlen(s)); } } else { - fputs(buf, stderr); + fputs(s, stderr); + fputs("\n", stderr); + fflush(stderr); } } +static void +err_print(fmt, args) + char *fmt; + va_list args; +{ + char buf[BUFSIZ]; + + err_sprintf(buf, fmt, args); + err_append(buf); +} + void Error(fmt, va_alist) char *fmt; @@ -71,18 +80,18 @@ Error(fmt, va_alist) nerrs++; } -int -yyerror(msg) - char *msg; +void +Error_Append(fmt, va_alist) + char *fmt; + va_dcl { - static char *f; - static int line; + va_list args; + char buf[BUFSIZ]; - if (line == sourceline && strcmp(f, sourcefile) == 0) - return; - f = sourcefile; line = sourceline; - Error("%s", msg); - return 0; + va_start(args); + vsprintf(buf, fmt, args); + va_end(args); + err_append(buf); } void @@ -103,32 +112,226 @@ Warning(fmt, va_alist) } void -Fatal(fmt, va_alist) +Bug(fmt, va_alist) char *fmt; va_dcl { + char buf[BUFSIZ]; va_list args; + sprintf(buf, "[BUG] %s", fmt); + rb_in_eval = 0; + va_start(args); - err_print(fmt, args); + err_print(buf, args); va_end(args); - rb_exit(1); + abort(); } +static struct types { + int type; + char *name; +} builtin_types[] = { + T_NIL, "nil", + T_OBJECT, "Object", + T_CLASS, "Class", + T_ICLASS, "iClass", /* internal use: mixed-in module holder */ + T_MODULE, "Module", + T_FLOAT, "Float", + T_STRING, "String", + T_REGEXP, "Regexp", + T_ARRAY, "Array", + T_FIXNUM, "Fixnum", + T_HASH, "Hash", + T_STRUCT, "Struct", + T_BIGNUM, "Bignum", + T_FILE, "File", + T_TRUE, "TRUE", + T_FALSE, "FALSE", + T_DATA, "Data", /* internal use: wrapped C pointers */ + T_MATCH, "Match", /* data of $~ */ + T_VARMAP, "Varmap", /* internal use: dynamic variables */ + T_SCOPE, "Scope", /* internal use: variable scope */ + T_NODE, "Node", /* internal use: syntax tree node */ + -1, 0, +}; + +extern void TypeError(); + void -Bug(fmt, va_alist) +Check_Type(x, t) + VALUE x; + int t; +{ + struct types *type = builtin_types; + + if (TYPE(x)!=(t)) { + while (type->type >= 0) { + if (type->type == t) { + TypeError("wrong argument type %s (expected %s)", + rb_class2name(CLASS_OF(x)), type->name); + } + type++; + } + Bug("unknown type 0x%x", t); + } +} + +/* exception classes */ +#include "errno.h" + +extern VALUE cString; +VALUE eGlobalExit, eException; +VALUE eSystemExit, eInterrupt, eFatal; +VALUE eRuntimeError; +VALUE eSyntaxError; +VALUE eTypeError; +VALUE eArgError; +VALUE eNameError; +VALUE eIndexError; +VALUE eNotImpError; +VALUE eLoadError; + +VALUE eSystemCallError; +VALUE mErrno; + +VALUE +exc_new0(etype, ptr, len) + VALUE etype; + char *ptr; + UINT len; +{ + NEWOBJ(exc, struct RString); + OBJSETUP(exc, etype, T_STRING); + + exc->len = len; + exc->orig = 0; + exc->ptr = ALLOC_N(char,len+1); + if (ptr) { + memcpy(exc->ptr, ptr, len); + } + exc->ptr[len] = '\0'; + return (VALUE)exc; +} + +VALUE +exc_new(etype, s) + VALUE etype; + char *s; +{ + return exc_new0(etype, s, strlen(s)); +} + +VALUE +exc_new2(etype, str) + VALUE etype; + struct RString *str; +{ + Check_Type(str, T_STRING); + return exc_new(etype, str->ptr, str->len); +} + +static VALUE +exc_s_new(argc, argv, etype) + int argc; + VALUE *argv; + VALUE etype; +{ + VALUE arg; + + if (rb_scan_args(argc, argv, "01", &arg) == 0) { + return exc_new0(etype, 0, 0); + } + Check_Type(arg, T_STRING); + return exc_new2(etype, arg); +} + +static VALUE *syserr_list; + +static void +set_syserr(i, name) + int i; + char *name; +{ + syserr_list[i] = rb_define_class_under(mErrno, name, eSystemCallError); + rb_global_variable(&syserr_list[i]); +} + +static void init_syserr(); + +void +Init_Exception() +{ + eGlobalExit = rb_define_class("GlobalExit", cString); + rb_define_method(eGlobalExit, "new", exc_s_new, -1); + + eSystemExit = rb_define_class("SystemExit", eGlobalExit); + eFatal = rb_define_class("fatal", eGlobalExit); + eInterrupt = rb_define_class("Interrupt", eGlobalExit); + + eException = rb_define_class("Exception", eGlobalExit); + eSyntaxError = rb_define_class("SyntaxError", eException); + eTypeError = rb_define_class("TypeError", eException); + eArgError = rb_define_class("ArgumentError", eException); + eNameError = rb_define_class("NameError", eException); + eIndexError = rb_define_class("IndexError", eException); + eNotImpError = rb_define_class("NotImplementError", eException); + eLoadError = rb_define_class("LoadError", eException); + + eRuntimeError = rb_define_class("RuntimeError", eException); + + init_syserr(); +} + +#define RAISE_ERROR(class) {\ + va_list args;\ + char buf[BUFSIZ];\ +\ + va_start(args);\ + vsprintf(buf, fmt, args);\ + va_end(args);\ +\ + rb_raise(exc_new(class, buf));\ +} + +void +Raise(exc, fmt, va_alist) char *fmt; va_dcl { - char buf[BUFSIZ]; - va_list args; + RAISE_ERROR(exc); +} - sprintf(buf, "[BUG] %s", fmt); +void +TypeError(fmt, va_alist) + char *fmt; + va_dcl +{ + RAISE_ERROR(eTypeError); +} - va_start(args); - err_print(buf, args); - va_end(args); - abort(); +void +ArgError(fmt, va_alist) + char *fmt; + va_dcl +{ + RAISE_ERROR(eArgError); +} + +void +NameError(fmt, va_alist) + char *fmt; + va_dcl +{ + RAISE_ERROR(eNameError); +} + +void +IndexError(fmt, va_alist) + char *fmt; + va_dcl +{ + RAISE_ERROR(eIndexError); } void @@ -136,6 +339,30 @@ Fail(fmt, va_alist) char *fmt; va_dcl { + RAISE_ERROR(eRuntimeError); +} + +void +rb_notimplement() +{ + Raise(eNotImpError, + "The %s() function is unimplemented on this machine", + rb_id2name(the_frame->last_func)); +} + +void +LoadError(fmt, va_alist) + char *fmt; + va_dcl +{ + RAISE_ERROR(eLoadError); +} + +void +Fatal(fmt, va_alist) + char *fmt; + va_dcl +{ va_list args; char buf[BUFSIZ]; @@ -143,7 +370,8 @@ Fail(fmt, va_alist) vsprintf(buf, fmt, args); va_end(args); - rb_fail(str_new2(buf)); + rb_in_eval = 0; + rb_fatal(exc_new(eFatal, buf)); } void @@ -153,39 +381,397 @@ rb_sys_fail(mesg) char *strerror(); char buf[BUFSIZ]; extern int errno; + int n = errno; - if (mesg == Qnil) - sprintf(buf, "%s", strerror(errno)); - else + if (RTEST(mesg)) sprintf(buf, "%s - %s", strerror(errno), mesg); + else + sprintf(buf, "%s", strerror(errno)); errno = 0; - rb_fail(str_new2(buf)); -} - -static char *builtin_types[] = { - "Nil", - "Object", - "Class", - "iClass", - "Module", - "Float", - "String", - "Regexp", - "Array", - "Fixnum", - "Hash", - "Struct", - "Bignum", - "Data", - "Match", -}; + if (!syserr_list[n]) { + char name[6]; -void -WrongType(x, t) - VALUE x; - int t; + sprintf(name, "E%03d", n); + set_syserr(n, name); + } + rb_raise(exc_new(syserr_list[n], buf)); +} + +extern int sys_nerr; + +static void +init_syserr() { - Fail("wrong argument type %s (expected %s)", - rb_class2name(CLASS_OF(x)), builtin_types[t]); + eSystemCallError = rb_define_class("SystemCallError", eException); + mErrno = rb_define_module("Errno"); + syserr_list = ALLOC_N(VALUE, sys_nerr+1); + MEMZERO(syserr_list, VALUE, sys_nerr+1); + +#ifdef EPERM + set_syserr(EPERM, "EPERM"); +#endif +#ifdef ENOENT + set_syserr(ENOENT, "ENOENT"); +#endif +#ifdef ESRCH + set_syserr(ESRCH, "ESRCH"); +#endif +#ifdef EINTR + set_syserr(EINTR, "EINTR"); +#endif +#ifdef EIO + set_syserr(EIO, "EIO"); +#endif +#ifdef ENXIO + set_syserr(ENXIO, "ENXIO"); +#endif +#ifdef E2BIG + set_syserr(E2BIG, "E2BIG"); +#endif +#ifdef ENOEXEC + set_syserr(ENOEXEC, "ENOEXEC"); +#endif +#ifdef EBADF + set_syserr(EBADF, "EBADF"); +#endif +#ifdef ECHILD + set_syserr(ECHILD, "ECHILD"); +#endif +#ifdef EAGAIN + set_syserr(EAGAIN, "EAGAIN"); +#endif +#ifdef ENOMEM + set_syserr(ENOMEM, "ENOMEM"); +#endif +#ifdef EACCES + set_syserr(EACCES, "EACCES"); +#endif +#ifdef EFAULT + set_syserr(EFAULT, "EFAULT"); +#endif +#ifdef ENOTBLK + set_syserr(ENOTBLK, "ENOTBLK"); +#endif +#ifdef EBUSY + set_syserr(EBUSY, "EBUSY"); +#endif +#ifdef EEXIST + set_syserr(EEXIST, "EEXIST"); +#endif +#ifdef EXDEV + set_syserr(EXDEV, "EXDEV"); +#endif +#ifdef ENODEV + set_syserr(ENODEV, "ENODEV"); +#endif +#ifdef ENOTDIR + set_syserr(ENOTDIR, "ENOTDIR"); +#endif +#ifdef EISDIR + set_syserr(EISDIR, "EISDIR"); +#endif +#ifdef EINVAL + set_syserr(EINVAL, "EINVAL"); +#endif +#ifdef ENFILE + set_syserr(ENFILE, "ENFILE"); +#endif +#ifdef EMFILE + set_syserr(EMFILE, "EMFILE"); +#endif +#ifdef ENOTTY + set_syserr(ENOTTY, "ENOTTY"); +#endif +#ifdef ETXTBSY + set_syserr(ETXTBSY, "ETXTBSY"); +#endif +#ifdef EFBIG + set_syserr(EFBIG, "EFBIG"); +#endif +#ifdef ENOSPC + set_syserr(ENOSPC, "ENOSPC"); +#endif +#ifdef ESPIPE + set_syserr(ESPIPE, "ESPIPE"); +#endif +#ifdef EROFS + set_syserr(EROFS, "EROFS"); +#endif +#ifdef EMLINK + set_syserr(EMLINK, "EMLINK"); +#endif +#ifdef EPIPE + set_syserr(EPIPE, "EPIPE"); +#endif +#ifdef EDOM + set_syserr(EDOM, "EDOM"); +#endif +#ifdef ERANGE + set_syserr(ERANGE, "ERANGE"); +#endif +#ifdef EDEADLK + set_syserr(EDEADLK, "EDEADLK"); +#endif +#ifdef ENAMETOOLONG + set_syserr(ENAMETOOLONG, "ENAMETOOLONG"); +#endif +#ifdef ENOLCK + set_syserr(ENOLCK, "ENOLCK"); +#endif +#ifdef ENOSYS + set_syserr(ENOSYS, "ENOSYS"); +#endif +#ifdef ENOTEMPTY + set_syserr(ENOTEMPTY, "ENOTEMPTY"); +#endif +#ifdef ELOOP + set_syserr(ELOOP, "ELOOP"); +#endif +#ifdef EWOULDBLOCK + set_syserr(EWOULDBLOCK, "EWOULDBLOCK"); +#endif +#ifdef ENOMSG + set_syserr(ENOMSG, "ENOMSG"); +#endif +#ifdef EIDRM + set_syserr(EIDRM, "EIDRM"); +#endif +#ifdef ECHRNG + set_syserr(ECHRNG, "ECHRNG"); +#endif +#ifdef EL2NSYNC + set_syserr(EL2NSYNC, "EL2NSYNC"); +#endif +#ifdef EL3HLT + set_syserr(EL3HLT, "EL3HLT"); +#endif +#ifdef EL3RST + set_syserr(EL3RST, "EL3RST"); +#endif +#ifdef ELNRNG + set_syserr(ELNRNG, "ELNRNG"); +#endif +#ifdef EUNATCH + set_syserr(EUNATCH, "EUNATCH"); +#endif +#ifdef ENOCSI + set_syserr(ENOCSI, "ENOCSI"); +#endif +#ifdef EL2HLT + set_syserr(EL2HLT, "EL2HLT"); +#endif +#ifdef EBADE + set_syserr(EBADE, "EBADE"); +#endif +#ifdef EBADR + set_syserr(EBADR, "EBADR"); +#endif +#ifdef EXFULL + set_syserr(EXFULL, "EXFULL"); +#endif +#ifdef ENOANO + set_syserr(ENOANO, "ENOANO"); +#endif +#ifdef EBADRQC + set_syserr(EBADRQC, "EBADRQC"); +#endif +#ifdef EBADSLT + set_syserr(EBADSLT, "EBADSLT"); +#endif +#ifdef EDEADLOCK + set_syserr(EDEADLOCK, "EDEADLOCK"); +#endif +#ifdef EBFONT + set_syserr(EBFONT, "EBFONT"); +#endif +#ifdef ENOSTR + set_syserr(ENOSTR, "ENOSTR"); +#endif +#ifdef ENODATA + set_syserr(ENODATA, "ENODATA"); +#endif +#ifdef ETIME + set_syserr(ETIME, "ETIME"); +#endif +#ifdef ENOSR + set_syserr(ENOSR, "ENOSR"); +#endif +#ifdef ENONET + set_syserr(ENONET, "ENONET"); +#endif +#ifdef ENOPKG + set_syserr(ENOPKG, "ENOPKG"); +#endif +#ifdef EREMOTE + set_syserr(EREMOTE, "EREMOTE"); +#endif +#ifdef ENOLINK + set_syserr(ENOLINK, "ENOLINK"); +#endif +#ifdef EADV + set_syserr(EADV, "EADV"); +#endif +#ifdef ESRMNT + set_syserr(ESRMNT, "ESRMNT"); +#endif +#ifdef ECOMM + set_syserr(ECOMM, "ECOMM"); +#endif +#ifdef EPROTO + set_syserr(EPROTO, "EPROTO"); +#endif +#ifdef EMULTIHOP + set_syserr(EMULTIHOP, "EMULTIHOP"); +#endif +#ifdef EDOTDOT + set_syserr(EDOTDOT, "EDOTDOT"); +#endif +#ifdef EBADMSG + set_syserr(EBADMSG, "EBADMSG"); +#endif +#ifdef EOVERFLOW + set_syserr(EOVERFLOW, "EOVERFLOW"); +#endif +#ifdef ENOTUNIQ + set_syserr(ENOTUNIQ, "ENOTUNIQ"); +#endif +#ifdef EBADFD + set_syserr(EBADFD, "EBADFD"); +#endif +#ifdef EREMCHG + set_syserr(EREMCHG, "EREMCHG"); +#endif +#ifdef ELIBACC + set_syserr(ELIBACC, "ELIBACC"); +#endif +#ifdef ELIBBAD + set_syserr(ELIBBAD, "ELIBBAD"); +#endif +#ifdef ELIBSCN + set_syserr(ELIBSCN, "ELIBSCN"); +#endif +#ifdef ELIBMAX + set_syserr(ELIBMAX, "ELIBMAX"); +#endif +#ifdef ELIBEXEC + set_syserr(ELIBEXEC, "ELIBEXEC"); +#endif +#ifdef EILSEQ + set_syserr(EILSEQ, "EILSEQ"); +#endif +#ifdef ERESTART + set_syserr(ERESTART, "ERESTART"); +#endif +#ifdef ESTRPIPE + set_syserr(ESTRPIPE, "ESTRPIPE"); +#endif +#ifdef EUSERS + set_syserr(EUSERS, "EUSERS"); +#endif +#ifdef ENOTSOCK + set_syserr(ENOTSOCK, "ENOTSOCK"); +#endif +#ifdef EDESTADDRREQ + set_syserr(EDESTADDRREQ, "EDESTADDRREQ"); +#endif +#ifdef EMSGSIZE + set_syserr(EMSGSIZE, "EMSGSIZE"); +#endif +#ifdef EPROTOTYPE + set_syserr(EPROTOTYPE, "EPROTOTYPE"); +#endif +#ifdef ENOPROTOOPT + set_syserr(ENOPROTOOPT, "ENOPROTOOPT"); +#endif +#ifdef EPROTONOSUPPORT + set_syserr(EPROTONOSUPPORT, "EPROTONOSUPPORT"); +#endif +#ifdef ESOCKTNOSUPPORT + set_syserr(ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT"); +#endif +#ifdef EOPNOTSUPP + set_syserr(EOPNOTSUPP, "EOPNOTSUPP"); +#endif +#ifdef EPFNOSUPPORT + set_syserr(EPFNOSUPPORT, "EPFNOSUPPORT"); +#endif +#ifdef EAFNOSUPPORT + set_syserr(EAFNOSUPPORT, "EAFNOSUPPORT"); +#endif +#ifdef EADDRINUSE + set_syserr(EADDRINUSE, "EADDRINUSE"); +#endif +#ifdef EADDRNOTAVAIL + set_syserr(EADDRNOTAVAIL, "EADDRNOTAVAIL"); +#endif +#ifdef ENETDOWN + set_syserr(ENETDOWN, "ENETDOWN"); +#endif +#ifdef ENETUNREACH + set_syserr(ENETUNREACH, "ENETUNREACH"); +#endif +#ifdef ENETRESET + set_syserr(ENETRESET, "ENETRESET"); +#endif +#ifdef ECONNABORTED + set_syserr(ECONNABORTED, "ECONNABORTED"); +#endif +#ifdef ECONNRESET + set_syserr(ECONNRESET, "ECONNRESET"); +#endif +#ifdef ENOBUFS + set_syserr(ENOBUFS, "ENOBUFS"); +#endif +#ifdef EISCONN + set_syserr(EISCONN, "EISCONN"); +#endif +#ifdef ENOTCONN + set_syserr(ENOTCONN, "ENOTCONN"); +#endif +#ifdef ESHUTDOWN + set_syserr(ESHUTDOWN, "ESHUTDOWN"); +#endif +#ifdef ETOOMANYREFS + set_syserr(ETOOMANYREFS, "ETOOMANYREFS"); +#endif +#ifdef ETIMEDOUT + set_syserr(ETIMEDOUT, "ETIMEDOUT"); +#endif +#ifdef ECONNREFUSED + set_syserr(ECONNREFUSED, "ECONNREFUSED"); +#endif +#ifdef EHOSTDOWN + set_syserr(EHOSTDOWN, "EHOSTDOWN"); +#endif +#ifdef EHOSTUNREACH + set_syserr(EHOSTUNREACH, "EHOSTUNREACH"); +#endif +#ifdef EALREADY + set_syserr(EALREADY, "EALREADY"); +#endif +#ifdef EINPROGRESS + set_syserr(EINPROGRESS, "EINPROGRESS"); +#endif +#ifdef ESTALE + set_syserr(ESTALE, "ESTALE"); +#endif +#ifdef EUCLEAN + set_syserr(EUCLEAN, "EUCLEAN"); +#endif +#ifdef ENOTNAM + set_syserr(ENOTNAM, "ENOTNAM"); +#endif +#ifdef ENAVAIL + set_syserr(ENAVAIL, "ENAVAIL"); +#endif +#ifdef EISNAM + set_syserr(EISNAM, "EISNAM"); +#endif +#ifdef EREMOTEIO + set_syserr(EREMOTEIO, "EREMOTEIO"); +#endif +#ifdef EDQUOT + set_syserr(EDQUOT, "EDQUOT"); +#endif } @@ -11,8 +11,8 @@ ************************************************/ #include "ruby.h" -#include "env.h" #include "node.h" +#include "env.h" #include "sig.h" #include <stdio.h> @@ -23,30 +23,21 @@ #ifdef HAVE_STRING_H # include <string.h> #else -char *strchr(); char *strrchr(); #endif -VALUE cProc; +static VALUE cProc; static VALUE proc_call(); -static void rb_clear_cache_body(); -static void rb_clear_cache_entry(); - -/* #define TEST /* prints cache miss */ -#ifdef TEST -#include <stdio.h> -#endif - #define CACHE_SIZE 0x200 #define CACHE_MASK 0x1ff #define EXPR1(c,m) ((((int)(c)>>3)^(m))&CACHE_MASK) struct cache_entry { /* method hash table. */ ID mid; /* method's id */ + ID mid0; /* method's original id */ struct RClass *class; /* receiver's class */ struct RClass *origin; /* where method defined */ - int nargs; /* # of args */ NODE *method; int noex; }; @@ -62,14 +53,7 @@ rb_add_method(class, mid, node, noex) { NODE *body; - if (class == Qnil) class = (struct RClass*)cObject; - if (st_lookup(class->m_tbl, mid, &body)) { - Warning("redefine %s", rb_id2name(mid)); - rb_clear_cache_body(body); - } - else { - rb_clear_cache_entry(class, mid); - } + if (NIL_P(class)) class = (struct RClass*)cObject; body = NEW_METHOD(node, noex); st_insert(class->m_tbl, mid, body); } @@ -83,7 +67,7 @@ search_method(class, id, origin) while (!st_lookup(class->m_tbl, id, &body)) { class = class->super; - if (class == Qnil) return Qnil; + if (!class) return 0; } if (origin) *origin = class; @@ -102,29 +86,25 @@ rb_get_method_body(classp, idp, noexp) struct RClass *origin; struct cache_entry *ent; - if ((body = search_method(class, id, &origin)) == FALSE) { - return Qnil; + if ((body = search_method(class, id, &origin)) == 0) { + return 0; } - if (body->nd_body == Qnil) return Qnil; + if (!body->nd_body) return 0; - ent = cache + EXPR1(class, id); -#ifdef TEST - if (ent->mid != 0) { - fprintf(stderr, "0x%x 0x%x %x\n", class, id, EXPR1(class, id)); - } -#endif /* store in cache */ + ent = cache + EXPR1(class, id); ent->class = class; ent->noex = body->nd_noex; body = body->nd_body; if (nd_type(body) == NODE_FBODY) { + ent->mid = id; *classp = ent->origin = (struct RClass*)body->nd_orig; - *idp = ent->mid = body->nd_mid; + *idp = ent->mid0 = body->nd_mid; body = ent->method = body->nd_head; } else { *classp = ent->origin = origin; - ent->mid = id; + ent->mid = ent->mid0 = id; ent->method = body; } @@ -142,17 +122,9 @@ rb_alias(class, name, def) if (name == def) return; body = search_method(class, def, &origin); - if (body == Qnil || body->nd_body == Qnil) { - Fail("undefined method `%s' for class `%s'", - rb_id2name(def), rb_class2name(class)); - } - - if (st_lookup(class->m_tbl, name, &old)) { - Warning("redefine %s", rb_id2name(name)); - rb_clear_cache_body(body); - } - else { - rb_clear_cache_entry(class, name); + if (!body || !body->nd_body) { + NameError("undefined method `%s' for class `%s'", + rb_id2name(def), rb_class2name(class)); } st_insert(class->m_tbl, name, @@ -170,9 +142,9 @@ rb_export_method(class, name, noex) struct RClass *origin; body = search_method(class, name, &origin); - if (body == Qnil) { - Fail("undefined method `%s' for class `%s'", - rb_id2name(name), rb_class2name(class)); + if (!body) { + NameError("undefined method `%s' for class `%s'", + rb_id2name(name), rb_class2name(class)); } if (body->nd_noex != noex) { if (class == origin) { @@ -200,85 +172,56 @@ method_boundp(class, id, ex) return FALSE; } -VALUE +int rb_method_boundp(class, id) struct RClass *class; ID id; { - return method_boundp(class, id, 0); -} - -static void -rb_clear_cache_body(body) - NODE *body; -{ - struct cache_entry *ent, *end; - - ent = cache; end = ent + CACHE_SIZE; - while (ent < end) { - if (ent->method == body) { - ent->class = Qnil; - ent->mid = Qnil; - } - ent++; - } -} - -static void -rb_clear_cache_entry(class, mid) - struct RClass *class; - ID mid; -{ - struct cache_entry *ent; - - /* is it in the method cache? */ - ent = cache + EXPR1(class, mid); - if (ent->mid == mid && ent->class == class) { - ent->class = Qnil; - ent->mid = Qnil; - } + if (method_boundp(class, id, NOEX_PRIVATE)) + return TRUE; + return FALSE; } void -rb_clear_cache(class) - struct RClass *class; +rb_clear_cache() { struct cache_entry *ent, *end; ent = cache; end = ent + CACHE_SIZE; while (ent < end) { - if (ent->origin == class) { - ent->class = Qnil; - ent->mid = Qnil; - } + ent->mid = 0; ent++; } } -static ID match, each, aref, aset; -VALUE errstr, errat; +static ID init, eqq, each, aref, aset; +VALUE errinfo = Qnil, errat = Qnil; extern NODE *eval_tree; extern int nerrs; -extern VALUE TopSelf; -VALUE Qself; - -#define PUSH_SELF(s) { \ - VALUE __saved_self__ = Qself; \ - Qself = s; \ +extern VALUE cKernel; +extern VALUE eGlobalExit; +extern VALUE eInterrupt; +extern VALUE eSystemExit; +extern VALUE eException; +extern VALUE eRuntimeError; +extern VALUE eSyntaxError; +static VALUE eLocalJumpError; -#define POP_SELF() Qself = __saved_self__; } +extern VALUE TopSelf; struct FRAME *the_frame; struct SCOPE *the_scope; static struct FRAME *top_frame; -static struct SCOPE *top_scope; +static struct SCOPE *top_scope; #define PUSH_FRAME() { \ struct FRAME _frame; \ _frame.prev = the_frame; \ _frame.file = sourcefile; \ _frame.line = sourceline; \ + _frame.iter = the_iter->iter; \ + _frame.cbase = the_frame->cbase; \ the_frame = &_frame; \ #define POP_FRAME() the_frame = _frame.prev; } @@ -289,6 +232,7 @@ struct BLOCK { VALUE self; struct FRAME frame; struct SCOPE *scope; + struct RClass *class; int level; int iter; struct RVarmap *d_vars; @@ -297,24 +241,29 @@ struct BLOCK { #define PUSH_BLOCK(v,b) { \ struct BLOCK _block; \ - _block.level = tag_level; \ + _block.level = (int)&prot_tag; \ _block.var = v; \ _block.body = b; \ - _block.self = Qself; \ + _block.self = self; \ _block.frame = *the_frame; \ + _block.class = the_class; \ _block.frame.file = sourcefile; \ _block.frame.line = sourceline; \ _block.scope = the_scope; \ _block.d_vars = the_dyna_vars; \ _block.prev = the_block; \ - _block.iter = iter->iter; \ + _block.iter = the_iter->iter; \ the_block = &_block; \ #define PUSH_BLOCK2(b) { \ - b->prev = the_block; \ - the_block = b; \ - -#define POP_BLOCK() the_block = the_block->prev; } + struct BLOCK _block; \ + _block = *b; \ + _block.prev = the_block; \ + the_block = &_block; + +#define POP_BLOCK() \ + the_block = the_block->prev; \ +} struct RVarmap *the_dyna_vars; #define PUSH_VARS() { \ @@ -324,13 +273,28 @@ struct RVarmap *the_dyna_vars; #define POP_VARS() the_dyna_vars = _old; } VALUE +dyna_var_defined(id) + ID id; +{ + struct RVarmap *vars = the_dyna_vars; + + while (vars && vars->id) { + if (vars->id == id) return TRUE; + vars = vars->next; + } + return FALSE; +} + +VALUE dyna_var_ref(id) ID id; { struct RVarmap *vars = the_dyna_vars; - while (vars) { - if (vars->id == id) return vars->val; + while (vars && vars->id) { + if (vars->id == id) { + return vars->val; + } vars = vars->next; } return Qnil; @@ -343,16 +307,16 @@ dyna_var_asgn(id, value) { struct RVarmap *vars = the_dyna_vars; - while (vars) { + while (vars && vars->id) { if (vars->id == id) { vars->val = value; - return; + return value; } vars = vars->next; } { NEWOBJ(_vars, struct RVarmap); - OBJSETUP(_vars, Qnil, T_VARMAP); + OBJSETUP(_vars, 0, T_VARMAP); _vars->id = id; _vars->val = value; _vars->next = the_dyna_vars; @@ -360,11 +324,22 @@ dyna_var_asgn(id, value) } return value; } - + +static VALUE +dyna_var_mark() +{ + NEWOBJ(_vars, struct RVarmap); + OBJSETUP(_vars, 0, T_VARMAP); + _vars->id = 0; + _vars->val = Qnil; + _vars->next = the_dyna_vars; + the_dyna_vars = _vars; +} + static struct iter { int iter; struct iter *prev; -} *iter; +} *the_iter; #define ITER_NOT 0 #define ITER_PRE 1 @@ -372,20 +347,16 @@ static struct iter { #define PUSH_ITER(i) { \ struct iter _iter; \ - _iter.prev = iter; \ + _iter.prev = the_iter; \ _iter.iter = (i); \ - iter = &_iter; \ + the_iter = &_iter; \ #define POP_ITER() \ - iter = _iter.prev; \ + the_iter = _iter.prev; \ } -static int tag_level, target_level; static struct tag { - int level; jmp_buf buf; - struct gc_list *gclist; - VALUE self; struct FRAME *frame; struct iter *iter; struct tag *prev; @@ -393,57 +364,50 @@ static struct tag { #define PUSH_TAG() { \ struct tag _tag; \ - _tag.level= ++tag_level; \ - _tag.self = Qself; \ _tag.frame = the_frame; \ - _tag.iter = iter; \ + _tag.iter = the_iter; \ _tag.prev = prot_tag; \ - prot_tag = &_tag; \ + prot_tag = &_tag; -#define EXEC_TAG() (setjmp(prot_tag->buf)) +#define EXEC_TAG() ((NODE*)setjmp(prot_tag->buf)) -#define JUMP_TAG(val) { \ - Qself = prot_tag->self; \ +#define JUMP_TAG(st) { \ the_frame = prot_tag->frame; \ - iter = prot_tag->iter; \ - longjmp(prot_tag->buf,(val)); \ + the_iter = prot_tag->iter; \ + longjmp(prot_tag->buf,(int)(st)); \ } +#define JUMP_TAG3(val,data1,data2) \ + JUMP_TAG(newnode(NODE_TAG,(val),(data1),(data2))) + +#define JUMP_TAG2(val,data) JUMP_TAG3((val),(data),0) + #define POP_TAG() \ - tag_level--; \ prot_tag = _tag.prev; \ } -#define TAG_RETURN 1 -#define TAG_BREAK 2 -#define TAG_CONTINUE 3 -#define TAG_RETRY 4 -#define TAG_REDO 5 -#define TAG_FAIL 6 -#define TAG_EXIT 7 +#define TAG_RETURN 0x1 +#define TAG_BREAK 0x2 +#define TAG_NEXT 0x3 +#define TAG_RETRY 0x4 +#define TAG_REDO 0x5 +#define TAG_RAISE 0x6 +#define TAG_THROW 0x7 +#define TAG_FATAL 0x8 -#define IN_BLOCK 0x08 +#define IN_BLOCK 0x10 struct RClass *the_class; -struct class_link { - struct RClass *class; - struct class_link *prev; -} *class_link; #define PUSH_CLASS() { \ - struct class_link _link; \ - _link.class = the_class; \ - _link.prev = class_link; \ - class_link = &_link \ + struct RClass *_class = the_class; \ -#define POP_CLASS() \ - the_class = class_link->class; \ - class_link = _link.prev; } +#define POP_CLASS() the_class = _class; } #define PUSH_SCOPE() { \ struct SCOPE *_old; \ NEWOBJ(_scope, struct SCOPE); \ - OBJSETUP(_scope, Qnil, T_SCOPE); \ + OBJSETUP(_scope, 0, T_SCOPE); \ _old = the_scope; \ the_scope = _scope; \ @@ -452,54 +416,96 @@ struct class_link { the_scope->local_vars = 0;\ the_scope->local_tbl = 0;\ }\ + the_scope->flag |= SCOPE_NOSTACK;\ the_scope = _old;\ } static VALUE rb_eval(); -static VALUE f_eval(); +static VALUE eval(); +static NODE *compile(); static VALUE rb_call(); VALUE rb_apply(); -VALUE rb_xstring(); -void rb_fail(); - -VALUE rb_rescue(); static void module_setup(); static VALUE masign(); static void asign(); -static VALUE last_val; - extern VALUE rb_stderr; extern int sourceline; extern char *sourcefile; -static ID last_func; static void -error_print(last_func) - ID last_func; +error_pos() { - if (errat) { - fwrite(RSTRING(errat)->ptr, 1, RSTRING(errat)->len, stderr); - if (last_func) { - fprintf(stderr, ":in `%s': ", rb_id2name(last_func)); + if (sourcefile) { + if (the_frame->last_func) { + fprintf(stderr, "%s:%d:in `%s': ", sourcefile, sourceline, + rb_id2name(the_frame->last_func)); } else { - fprintf(stderr, ": "); + fprintf(stderr, "%s:%d: ", sourcefile, sourceline); } } +} - if (errstr) { - fwrite(RSTRING(errstr)->ptr, 1, RSTRING(errstr)->len, stderr); - if (RSTRING(errstr)->ptr[RSTRING(errstr)->len - 1] != '\n') { - putc('\n', stderr); +static void +error_print(state) + NODE *state; +{ + struct FRAME *frame = the_frame; + VALUE etype; + + if (!NIL_P(errat)) { + VALUE mesg; + + switch (TYPE(errat)) { + case T_STRING: + mesg = errat; + errat = Qnil; + break; + case T_ARRAY: + mesg = RARRAY(errat)->ptr[0]; + break; } + fwrite(RSTRING(mesg)->ptr, 1, RSTRING(mesg)->len, stderr); + fprintf(stderr, ": "); + } + + etype = rb_class_path(CLASS_OF(errinfo)); + + if (verbose) { + fwrite(RSTRING(etype)->ptr, 1, RSTRING(etype)->len, stderr); + putc('|', stderr); + } + if (RSTRING(errinfo)->len == 0) { + fprintf(stderr, "unhandled exception.\n"); } else { - fprintf(stderr, "unhandled failure.\n"); + fwrite(RSTRING(errinfo)->ptr, 1, RSTRING(errinfo)->len, stderr); + if (RSTRING(errinfo)->ptr[RSTRING(errinfo)->len - 1] != '\n') { + putc('\n', stderr); + } + } + + if (!NIL_P(errat)) { + int i; + struct RArray *ep = RARRAY(errat); + +#define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5) +#define TRACE_HEAD 8 +#define TRACE_TAIL 5 + + for (i=1; i<ep->len; i++) { + fprintf(stderr, "\tfrom %s\n", RSTRING(ep->ptr[i])->ptr); + if (i == TRACE_HEAD && ep->len > TRACE_MAX) { + fprintf(stderr, "\t ... %d levels...\n", + ep->len - TRACE_HEAD - TRACE_TAIL); + i = ep->len - TRACE_TAIL; + } + } } } @@ -511,9 +517,12 @@ ruby_init(argc, argv, envp) int argc; char **argv, **envp; { - int state; static struct FRAME frame; + static struct iter iter; + NODE *state; + the_frame = top_frame = &frame; + the_iter = &iter; origenviron = environ; #ifdef NT @@ -526,144 +535,171 @@ ruby_init(argc, argv, envp) the_scope->local_tbl = 0; top_scope = the_scope; - PUSH_TAG(); - PUSH_ITER(ITER_NOT); + PUSH_TAG() if ((state = EXEC_TAG()) == 0) { rb_call_inits(); the_class = (struct RClass*)cObject; + the_frame->cbase = (VALUE)newnode(NODE_CREF,cObject,0,0); ruby_options(argc, argv, envp); } - POP_ITER(); POP_TAG(); + if (state) error_print(state); POP_SCOPE(); the_scope = top_scope; - - if (state == TAG_EXIT) { - rb_trap_exit(); - exit(FIX2UINT(last_val)); - } - if (state) { - error_print(last_func); - } } static VALUE -Eval() +eval_node(self) + VALUE self; { VALUE result = Qnil; NODE *tree; - int state; - if (!eval_tree) return Qnil; + if (!eval_tree) return FALSE; tree = eval_tree; eval_tree = 0; - result = rb_eval(tree); + result = rb_eval(self, tree); return result; } +int rb_in_eval; + +#ifdef THREAD +static void thread_cleanup(); +static void thread_wait_other_threads(); +#endif + +static int exit_status; + void ruby_run() { - int state; + NODE *state; + static NODE *ex; if (nerrs > 0) exit(nerrs); init_stack(); - rb_define_variable("$!", &errstr); errat = Qnil; /* clear for execution */ PUSH_TAG(); PUSH_ITER(ITER_NOT); if ((state = EXEC_TAG()) == 0) { - Eval(); + eval_node(TopSelf); + } + POP_ITER(); + POP_TAG(); + + if (state && !ex) ex = state; + PUSH_TAG(); + PUSH_ITER(ITER_NOT); + if ((state = EXEC_TAG()) == 0) { rb_trap_exit(); +#ifdef THREAD + thread_cleanup(); + thread_wait_other_threads(); +#endif + } + else { + ex = state; } POP_ITER(); POP_TAG(); - switch (state) { - case 0: - break; + if (!ex) { + exit(0); + } + + switch (ex->nd_tag) { case TAG_RETURN: - Fatal("unexpected return"); + error_pos(); + fprintf(stderr, "unexpected return\n"); + exit(1); break; - case TAG_CONTINUE: - Fatal("unexpected continue"); + case TAG_NEXT: + error_pos(); + fprintf(stderr, "unexpected next\n"); + exit(1); break; case TAG_BREAK: - Fatal("unexpected break"); + error_pos(); + fprintf(stderr, "unexpected break\n"); + exit(1); break; case TAG_REDO: - Fatal("unexpected redo"); + error_pos(); + fprintf(stderr, "unexpected redo\n"); + exit(1); break; case TAG_RETRY: - Fatal("retry outside of protect clause"); + error_pos(); + fprintf(stderr, "retry outside of protect clause\n"); + exit(1); break; - case TAG_FAIL: - error_print(last_func); + case TAG_RAISE: + case TAG_FATAL: + if (obj_is_kind_of(errinfo, eSystemExit)) { + exit(exit_status); + } + error_print(ex); exit(1); break; - case TAG_EXIT: - exit(FIX2UINT(last_val)); + case TAG_THROW: + error_pos(); + fprintf(stderr, "uncaught throw `%s'\n", rb_id2name(ex->nd_tlev)); + exit(1); break; default: - Bug("Unknown longjmp status %d", state); + Bug("Unknown longjmp status %d", ex->nd_tag); break; } - exit(0); } static void -syntax_error() +compile_error(at) + char *at; { VALUE mesg; - mesg = errstr; + mesg = errinfo; nerrs = 0; - errstr = str_new2("syntax error in eval():\n"); - str_cat(errstr, RSTRING(mesg)->ptr, RSTRING(mesg)->len); - rb_fail(errstr); + errinfo = exc_new(eSyntaxError, "compile error in "); + str_cat(errinfo, at, strlen(at)); + str_cat(errinfo, ":\n", 2); + str_cat(errinfo, RSTRING(mesg)->ptr, RSTRING(mesg)->len); + rb_raise(errinfo); } VALUE rb_eval_string(str) char *str; { + VALUE v; char *oldsrc = sourcefile; - lex_setsrc("(eval)", str, strlen(str)); - eval_tree = 0; - PUSH_VARS(); - yyparse(); - POP_VARS(); + sourcefile = "(eval)"; + v = eval(TopSelf, str_new2(str), Qnil); sourcefile = oldsrc; - if (nerrs == 0) { - return Eval(); - } - else { - syntax_error(); - } - return Qnil; /* not reached */ + + return v; } void rb_eval_cmd(cmd, arg) VALUE cmd, arg; { - int state; + NODE *state; struct SCOPE *saved_scope; if (TYPE(cmd) != T_STRING) { - if (TYPE(cmd) == T_OBJECT - && obj_is_kind_of(cmd, cProc)) { + if (obj_is_kind_of(cmd, cProc)) { proc_call(cmd, arg); return; } } - PUSH_SELF(TopSelf); PUSH_CLASS(); PUSH_TAG(); saved_scope = the_scope; @@ -672,31 +708,29 @@ rb_eval_cmd(cmd, arg) the_class = (struct RClass*)cObject; if ((state = EXEC_TAG()) == 0) { - f_eval(Qself, cmd); + eval(TopSelf, cmd, Qnil); } the_scope = saved_scope; POP_TAG(); POP_CLASS(); - POP_SELF(); - switch (state) { - case 0: - break; + if (state == 0) return; + switch (state->nd_tag) { case TAG_RETURN: - Fatal("unexpected return"); + Raise(eLocalJumpError, "unexpected return"); break; - case TAG_CONTINUE: - Fatal("unexpected continue"); + case TAG_NEXT: + Raise(eLocalJumpError, "unexpected next"); break; case TAG_BREAK: - Fatal("unexpected break"); + Raise(eLocalJumpError, "unexpected break"); break; case TAG_REDO: - Fatal("unexpected redo"); + Raise(eLocalJumpError, "unexpected redo"); break; case TAG_RETRY: - Fatal("retry outside of protect clause"); + Raise(eLocalJumpError, "retry outside of protect clause"); break; default: JUMP_TAG(state); @@ -709,8 +743,7 @@ rb_trap_eval(cmd, sig) VALUE cmd; int sig; { -#ifdef SAFE_SIGHANDLE - int state; + NODE *state; PUSH_TAG(); if ((state = EXEC_TAG()) == 0) { @@ -721,9 +754,74 @@ rb_trap_eval(cmd, sig) trap_immediate = 0; JUMP_TAG(state); } -#else - rb_eval_cmd(cmd, ary_new3(1, INT2FIX(sig))); -#endif +} + +static VALUE +superclass(self, node) + VALUE self; + NODE *node; +{ + VALUE val; + NODE *state; + + PUSH_TAG(); + if ((state = EXEC_TAG()) == 0) { + val = rb_eval(self, node); + } + POP_TAG(); + if ((state && state->nd_tag == TAG_RAISE) || !val || TYPE(val) != T_CLASS){ + switch (nd_type(node)) { + case NODE_COLON2: + TypeError("undefined superclass `%s'", rb_id2name(node->nd_mid)); + case NODE_CVAR: + case NODE_CONST: + TypeError("undefined superclass `%s'", rb_id2name(node->nd_vid)); + } + if (state) JUMP_TAG(state); + TypeError("superclass undefined"); + } + if (state) JUMP_TAG(state); + + return val; +} + +static VALUE +ev_const_defined(cref, id) + NODE *cref; + ID id; +{ + NODE *cbase = cref; + + while (cbase && cbase->nd_clss != cObject) { + struct RClass *class = RCLASS(cbase->nd_clss); + + if (class->iv_tbl && + st_lookup(class->iv_tbl, id, 0)) { + return TRUE; + } + cbase = cbase->nd_next; + } + return rb_const_defined(cref->nd_clss, id); +} + +static VALUE +ev_const_get(cref, id) + NODE *cref; + ID id; +{ + NODE *cbase = cref; + VALUE result; + + while (cbase && cbase->nd_clss != cObject) { + struct RClass *class = RCLASS(cbase->nd_clss); + + if (class->iv_tbl && + st_lookup(class->iv_tbl, id, &result)) { + return result; + } + cbase = cbase->nd_next; + } + return rb_const_get(cref->nd_clss, id); } #define SETUP_ARGS {\ @@ -739,9 +837,11 @@ rb_trap_eval(cmd, sig) n = node->nd_args;\ argv = ALLOCA_N(VALUE,argc);\ for (i=0;i<argc;i++) {\ - argv[i] = rb_eval(n->nd_head);\ + argv[i] = rb_eval(self,n->nd_head);\ n=n->nd_next;\ }\ + sourceline = nd_line(node);\ + sourcefile = node->file;\ }\ else {\ argc = 0;\ @@ -749,73 +849,111 @@ rb_trap_eval(cmd, sig) }\ }\ else {\ - VALUE args = rb_eval(n);\ + VALUE args = rb_eval(self,n);\ if (TYPE(args) != T_ARRAY)\ args = rb_to_a(args);\ argc = RARRAY(args)->len;\ argv = ALLOCA_N(VALUE, argc);\ MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);\ + sourceline = nd_line(node);\ + sourcefile = node->file;\ }\ } -#define RETURN(v) do { result = (v); goto finish; } while (0) +int +rb_test_false_or_nil(v) + VALUE v; +{ + return (v != Qnil) && (v != FALSE); +} + +static int handle_rescue(); +VALUE rb_yield_0(); static VALUE -rb_eval(node) +rb_eval(self, node) + VALUE self; register NODE *node; { - int state; + NODE *state; VALUE result = Qnil; +#define RETURN(v) { result = (v); goto finish; } + again: - if (node == Qnil) RETURN(Qnil); + if (!node) RETURN(Qnil); - sourceline = node->line; + sourceline = nd_line(node); sourcefile = node->file; switch (nd_type(node)) { case NODE_BLOCK: while (node) { - result = rb_eval(node->nd_head); + result = rb_eval(self, node->nd_head); node = node->nd_next; } break; + /* begin .. end without clauses */ + case NODE_BEGIN: + node = node->nd_body; + goto again; + + /* nodes for speed-up(default match) */ + case NODE_MATCH: + result = reg_match2(node->nd_head->nd_lit); + break; + + /* nodes for speed-up(top-level loop for -n/-p) */ + case NODE_OPT_N: + while (!NIL_P(f_gets())) { + rb_eval(self, node->nd_body); + } + RETURN(Qnil); + case NODE_SELF: - RETURN(Qself); + RETURN(self); case NODE_NIL: RETURN(Qnil); case NODE_IF: - if (rb_eval(node->nd_cond)) { + if (RTEST(rb_eval(self, node->nd_cond))) { node = node->nd_body; } else { node = node->nd_else; } - if (node) goto again; - RETURN(Qnil); + goto again; + + case NODE_UNLESS: + if (!RTEST(rb_eval(self, node->nd_cond))) { + node = node->nd_body; + } + else { + node = node->nd_else; + } + goto again; case NODE_CASE: { VALUE val; - val = rb_eval(node->nd_head); + val = rb_eval(self, node->nd_head); node = node->nd_body; while (node) { - if (nd_type(node) == NODE_WHEN) { - NODE *tag = node->nd_head; + NODE *tag; - while (tag) { - if (rb_funcall(rb_eval(tag->nd_head), match, 1, val)){ - RETURN(rb_eval(node->nd_body)); - } - tag = tag->nd_next; - } + if (nd_type(node) != NODE_WHEN) { + + RETURN(rb_eval(self, node)); } - else { - RETURN(rb_eval(node)); + tag = node->nd_head; + while (tag) { + if (RTEST(rb_funcall2(rb_eval(self, tag->nd_head),eqq,1,&val))){ + RETURN(rb_eval(self, node->nd_body)); + } + tag = tag->nd_next; } node = node->nd_next; } @@ -824,60 +962,62 @@ rb_eval(node) case NODE_WHILE: PUSH_TAG(); - switch (state = EXEC_TAG()) { - case 0: - while_cont: - while (rb_eval(node->nd_cond)) { + if ((state = EXEC_TAG()) == 0) { + while_next: + for (;;) { + if (node->nd_state && !RTEST(rb_eval(self, node->nd_cond))) + break; while_redo: - rb_eval(node->nd_body); + rb_eval(self, node->nd_body); + if (!node->nd_state && !RTEST(rb_eval(self, node->nd_cond))) + break; + } + } + else { + switch (state->nd_tag) { + case TAG_REDO: + state = 0; + goto while_redo; + case TAG_NEXT: + state = 0; + goto while_next; + default: + break; } - break; - case TAG_REDO: - state = 0; - goto while_redo; - case TAG_CONTINUE: - state = 0; - goto while_cont; - default: - break; } POP_TAG(); - switch (state) { - case 0: - case TAG_BREAK: - break; - default: + if (state && state->nd_tag != TAG_BREAK) { JUMP_TAG(state); - break; } RETURN(Qnil); - case NODE_WHILE2: + case NODE_UNTIL: PUSH_TAG(); - switch (state = EXEC_TAG()) { - case 0: - while2_cont: - do { - while2_redo: - rb_eval(node->nd_body); - } while (rb_eval(node->nd_cond)); - break; - case TAG_REDO: - state = 0; - goto while2_redo; - case TAG_CONTINUE: - state = 0; - goto while2_cont; - default: - case TAG_BREAK: - break; + if ((state = EXEC_TAG()) == 0) { + until_next: + for (;;) { + if (node->nd_state && RTEST(rb_eval(self, node->nd_cond))) + break; + until_redo: + rb_eval(self, node->nd_body); + if (!node->nd_state && RTEST(rb_eval(self, node->nd_cond))) + break; + } + } + else { + switch (state->nd_tag) { + case TAG_REDO: + state = 0; + goto while_redo; + case TAG_NEXT: + state = 0; + goto while_next; + default: + break; + } } POP_TAG(); - switch (state) { - case 0: - case TAG_BREAK: - break; - default: + if (state && state->nd_tag != TAG_BREAK) { JUMP_TAG(state); } RETURN(Qnil); @@ -885,6 +1025,8 @@ rb_eval(node) case NODE_ITER: case NODE_FOR: { + int tag_level; + iter_retry: PUSH_BLOCK(node->nd_var, node->nd_body); PUSH_TAG(); @@ -893,36 +1035,37 @@ rb_eval(node) if (state == 0) { if (nd_type(node) == NODE_ITER) { PUSH_ITER(ITER_PRE); - result = rb_eval(node->nd_iter); + result = rb_eval(self, node->nd_iter); POP_ITER(); } else { VALUE recv; - recv = rb_eval(node->nd_iter); + recv = rb_eval(self, node->nd_iter); PUSH_ITER(ITER_PRE); + sourceline = nd_line(node); + sourcefile = node->file; result = rb_call(CLASS_OF(recv),recv,each,0,0,0); POP_ITER(); } } POP_TAG(); + tag_level = the_block->level; POP_BLOCK(); - switch (state) { - case 0: - break; - + if (state == 0) break; + switch (state->nd_tag) { case TAG_RETRY: goto iter_retry; case IN_BLOCK|TAG_BREAK: - if (target_level != tag_level) { + if (state->nd_tlev != tag_level) { JUMP_TAG(state); } result = Qnil; break; case IN_BLOCK|TAG_RETURN: - if (target_level == tag_level) { - state &= ~IN_BLOCK; + if (state->nd_tlev == tag_level) { + state->nd_tag &= ~IN_BLOCK; } /* fall through */ default: @@ -931,79 +1074,91 @@ rb_eval(node) } break; - case NODE_FAIL: - { - VALUE mesg = rb_eval(node->nd_stts); - if (mesg) Check_Type(mesg, T_STRING); - rb_fail(mesg); - } - break; - case NODE_YIELD: - result = rb_yield(rb_eval(node->nd_stts)); + result = rb_yield_0(rb_eval(self, node->nd_stts), 0); break; - case NODE_BEGIN: - if (node->nd_resq == Qnil && node->nd_ensr == Qnil) { - node = node->nd_head; - goto again; + case NODE_RESCUE: + retry_entry: + PUSH_TAG(); + if ((state = EXEC_TAG()) == 0) { + result = rb_eval(self, node->nd_head); } - else { - VALUE (*r_proc)(); - - if (node->nd_resq == (NODE*)1) { - r_proc = 0; - } - else { - r_proc = rb_eval; - } - if (node->nd_ensr) { - PUSH_TAG(); - if ((state = EXEC_TAG()) == 0) { - result = rb_rescue(rb_eval, node->nd_head, r_proc, node->nd_resq); - } - POP_TAG(); - /* ensure clause */ - rb_eval(node->nd_ensr); - if (state) { - JUMP_TAG(state); + POP_TAG(); + if (state) { + if (state->nd_tag == TAG_RAISE) { + NODE *resq = node->nd_resq; + while (resq) { + if (handle_rescue(self, resq)) { + state = 0; + PUSH_TAG(); + if ((state = EXEC_TAG()) == 0) { + result = rb_eval(self, resq->nd_body); + } + POP_TAG(); + if (state == 0) { + errat = Qnil; + } + else if (state->nd_tag == TAG_RETRY) { + state = 0; + goto retry_entry; + } + break; + } + resq = resq->nd_head; /* next rescue */ } } - else { - result = rb_rescue(rb_eval, node->nd_head, r_proc, node->nd_resq); + if (state) { + JUMP_TAG(state); } } break; + case NODE_ENSURE: + PUSH_TAG(); + if ((state = EXEC_TAG()) == 0) { + result = rb_eval(self, node->nd_head); + } + POP_TAG(); + rb_eval(self, node->nd_ensr); + if (state) { + JUMP_TAG(state); + } + break; + case NODE_AND: - if ((result = rb_eval(node->nd_1st)) == FALSE) RETURN(result); + result = rb_eval(self, node->nd_1st); + if (!RTEST(result)) break; node = node->nd_2nd; goto again; case NODE_OR: - if ((result = rb_eval(node->nd_1st)) != FALSE) RETURN(result); + result = rb_eval(self, node->nd_1st); + if (RTEST(result)) break; node = node->nd_2nd; goto again; case NODE_NOT: - if (rb_eval(node->nd_body)) result = FALSE; + if (RTEST(rb_eval(self, node->nd_body))) result = FALSE; else result = TRUE; break; case NODE_DOT2: case NODE_DOT3: - RETURN(range_new(rb_eval(node->nd_beg), rb_eval(node->nd_end))); + RETURN(range_new(rb_eval(self, node->nd_beg), rb_eval(self, node->nd_end))); case NODE_FLIP2: /* like AWK */ if (node->nd_state == 0) { - if (rb_eval(node->nd_beg)) { - node->nd_state = rb_eval(node->nd_end)?0:1; + if (RTEST(rb_eval(self, node->nd_beg))) { + node->nd_state = rb_eval(self, node->nd_end)?0:1; result = TRUE; } - result = FALSE; + else { + result = FALSE; + } } else { - if (rb_eval(node->nd_end)) { + if (RTEST(rb_eval(self, node->nd_end))) { node->nd_state = 0; } result = TRUE; @@ -1012,39 +1167,22 @@ rb_eval(node) case NODE_FLIP3: /* like SED */ if (node->nd_state == 0) { - if (rb_eval(node->nd_beg)) { + if (RTEST(rb_eval(self, node->nd_beg))) { node->nd_state = 1; result = TRUE; } result = FALSE; } else { - if (rb_eval(node->nd_end)) { + if (RTEST(rb_eval(self, node->nd_end))) { node->nd_state = 0; } result = TRUE; } break; - case NODE_BREAK: - JUMP_TAG(TAG_BREAK); - break; - - case NODE_CONTINUE: - JUMP_TAG(TAG_CONTINUE); - break; - - case NODE_REDO: - JUMP_TAG(TAG_REDO); - break; - - case NODE_RETRY: - JUMP_TAG(TAG_RETRY); - break; - case NODE_RETURN: - if (node->nd_stts) last_val = rb_eval(node->nd_stts); - JUMP_TAG(TAG_RETURN); + JUMP_TAG2(TAG_RETURN,(node->nd_stts)?rb_eval(self, node->nd_stts):Qnil); break; case NODE_CALL: @@ -1053,7 +1191,7 @@ rb_eval(node) int argc; VALUE *argv; /* used in SETUP_ARGS */ PUSH_ITER(ITER_NOT); - recv = rb_eval(node->nd_recv); + recv = rb_eval(self, node->nd_recv); SETUP_ARGS; POP_ITER(); result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0); @@ -1067,7 +1205,7 @@ rb_eval(node) PUSH_ITER(ITER_NOT); SETUP_ARGS; POP_ITER(); - result = rb_call(CLASS_OF(Qself),Qself,node->nd_mid,argc,argv,1); + result = rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,1); } break; @@ -1086,8 +1224,8 @@ rb_eval(node) POP_ITER(); } - PUSH_ITER(iter->iter?ITER_PRE:ITER_NOT); - result = rb_call(the_frame->last_class->super, Qself, + PUSH_ITER(the_iter->iter?ITER_PRE:ITER_NOT); + result = rb_call(the_frame->last_class->super, self, the_frame->last_func, argc, argv, 1); POP_ITER(); } @@ -1095,11 +1233,14 @@ rb_eval(node) case NODE_SCOPE: { + VALUE save = the_frame->cbase; + PUSH_SCOPE(); PUSH_TAG(); - if (node->nd_cnt > 0) { - the_scope->local_vars = ALLOCA_N(VALUE, node->nd_cnt); - MEMZERO(the_scope->local_vars, VALUE, node->nd_cnt); + if (node->nd_rval) the_frame->cbase = (VALUE)node->nd_rval; + if (node->nd_tbl) { + the_scope->local_vars = ALLOCA_N(VALUE, node->nd_tbl[0]); + memclear(the_scope->local_vars, node->nd_tbl[0]); the_scope->local_tbl = node->nd_tbl; } else { @@ -1107,11 +1248,12 @@ rb_eval(node) the_scope->local_tbl = 0; } if ((state = EXEC_TAG()) == 0) { - result = rb_eval(node->nd_body); + result = rb_eval(self, node->nd_body); } POP_TAG(); POP_SCOPE(); - if (state != 0) JUMP_TAG(state); + the_frame->cbase = save; + if (state) JUMP_TAG(state); } break; @@ -1120,12 +1262,12 @@ rb_eval(node) VALUE recv, args, val; NODE *rval; - recv = rb_eval(node->nd_recv); + recv = rb_eval(self, node->nd_recv); rval = node->nd_args->nd_head; - args = rb_eval(node->nd_args->nd_next); + args = rb_eval(self, node->nd_args->nd_next); val = rb_apply(recv, aref, args); - val = rb_funcall(val, node->nd_mid, 1, rb_eval(rval)); + val = rb_funcall(val, node->nd_mid, 1, rb_eval(self, rval)); ary_push(args, val); rb_apply(recv, aset, args); result = val; @@ -1134,38 +1276,40 @@ rb_eval(node) case NODE_OP_ASGN2: { - ID id = node->nd_aid; + ID id = node->nd_next->nd_vid; VALUE recv, val; - recv = rb_funcall(rb_eval(node->nd_recv), id, 0); + recv = rb_eval(self, node->nd_recv); + val = rb_funcall(recv, id, 0); - id = id_attrset(id); + val = rb_funcall(recv, node->nd_next->nd_mid, 2, val, + rb_eval(self, node->nd_value)); - val = rb_eval(node->nd_value); - rb_funcall(recv, id, 1, val); + rb_funcall2(recv, id_attrset(id), 1, &val); result = val; } break; case NODE_MASGN: - result = masign(node, rb_eval(node->nd_value)); + result = masign(self, node, rb_eval(self, node->nd_value)); break; case NODE_LASGN: if (the_scope->local_vars == 0) Bug("unexpected local variable asignment"); - result = the_scope->local_vars[node->nd_cnt] = rb_eval(node->nd_value); + the_scope->local_vars[node->nd_cnt] = rb_eval(self, node->nd_value); + result = the_scope->local_vars[node->nd_cnt]; break; case NODE_DASGN: - result = dyna_var_asgn(node->nd_vid, rb_eval(node->nd_value)); + result = dyna_var_asgn(node->nd_vid, rb_eval(self, node->nd_value)); break; case NODE_GASGN: { VALUE val; - val = rb_eval(node->nd_value); + val = rb_eval(self, node->nd_value); rb_gvar_set(node->nd_entry, val); result = val; } @@ -1175,8 +1319,8 @@ rb_eval(node) { VALUE val; - val = rb_eval(node->nd_value); - rb_ivar_set(Qself, node->nd_vid, val); + val = rb_eval(self, node->nd_value); + rb_ivar_set(self, node->nd_vid, val); result = val; } break; @@ -1185,15 +1329,21 @@ rb_eval(node) { VALUE val; - val = rb_eval(node->nd_value); + val = rb_eval(self, node->nd_value); + /* check for static scope constants */ + if (verbose && ev_const_defined(the_frame->cbase, node->nd_vid)) { + Warning("already initialized constnant %s", + rb_id2name(node->nd_vid)); + } rb_const_set(the_class, node->nd_vid, val); result = val; } break; case NODE_LVAR: - if (the_scope->local_vars == 0) + if (the_scope->local_vars == 0) { Bug("unexpected local variable"); + } result = the_scope->local_vars[node->nd_cnt]; break; @@ -1206,18 +1356,13 @@ rb_eval(node) break; case NODE_IVAR: - result = rb_ivar_get(Qself, node->nd_vid); + result = rb_ivar_get(self, node->nd_vid); break; case NODE_CVAR: - { - VALUE val; - - val = rb_const_get(node->nd_rval->nd_clss, node->nd_vid); - nd_set_type(node, NODE_CONST); - node->nd_cval = val; - result = val; - } + result = ev_const_get(the_frame->cbase, node->nd_vid); + nd_set_type(node, NODE_CONST); + node->nd_cval = result; break; case NODE_CONST: @@ -1228,7 +1373,7 @@ rb_eval(node) { VALUE cls; - cls = rb_eval(node->nd_head); + cls = rb_eval(self, node->nd_head); switch (TYPE(cls)) { case T_CLASS: case T_MODULE: @@ -1237,7 +1382,7 @@ rb_eval(node) Check_Type(cls, T_CLASS); break; } - result = rb_const_get(cls, node->nd_mid); + result = rb_const_get_at(cls, node->nd_mid); } break; @@ -1273,11 +1418,11 @@ rb_eval(node) list = node->nd_head; while (list) { - key = rb_eval(list->nd_head); + key = rb_eval(self, list->nd_head); list = list->nd_next; if (list == 0) Bug("odd number list for Hash"); - val = rb_eval(list->nd_head); + val = rb_eval(self, list->nd_head); list = list->nd_next; hash_aset(hash, key, val); } @@ -1297,7 +1442,7 @@ rb_eval(node) i = node->nd_alen; ary = ary_new2(i); for (i=0;node;node=node->nd_next) { - RARRAY(ary)->ptr[i++] = rb_eval(node->nd_head); + RARRAY(ary)->ptr[i++] = rb_eval(self, node->nd_head); RARRAY(ary)->len = i; } @@ -1309,9 +1454,10 @@ rb_eval(node) result = str_new3(node->nd_lit); break; - case NODE_STR2: - case NODE_XSTR2: + case NODE_DSTR: + case NODE_DXSTR: case NODE_DREGX: + case NODE_DREGX_ONCE: { VALUE str, str2; NODE *list = node->nd_next; @@ -1322,7 +1468,15 @@ rb_eval(node) str2 = list->nd_head->nd_lit; } else { - str2 = rb_eval(list->nd_head); + if (nd_type(list->nd_head) == NODE_EVSTR) { + rb_in_eval++; + list->nd_head = compile(list->nd_head->nd_lit); + rb_in_eval--; + if (!node) { + compile_error("string expand"); + } + } + str2 = rb_eval(self, list->nd_head); } if (str2) { str2 = obj_as_string(str2); @@ -1330,22 +1484,29 @@ rb_eval(node) } list = list->nd_next; } - if (nd_type(node) == NODE_DREGX) { - VALUE re = reg_new(RSTRING(str)->ptr, RSTRING(str)->len, - node->nd_cflag); - result = re; - } - else if (nd_type(node) == NODE_XSTR2) { - result = rb_xstring(str); - } - else { + switch (nd_type(node)) { + case NODE_DREGX: + result = reg_new(RSTRING(str)->ptr, RSTRING(str)->len, + node->nd_cflag); + break; + case NODE_DREGX_ONCE: /* regexp expand once */ + result = reg_new(RSTRING(str)->ptr, RSTRING(str)->len, + node->nd_cflag); + nd_set_type(node, NODE_LIT); + node->nd_lit = result; + break; + case NODE_DXSTR: + result = rb_funcall(self, '`', 1, str); + break; + default: result = str; + break; } } break; case NODE_XSTR: - result = rb_xstring(node->nd_lit); + result = rb_funcall(self, '`', 1, node->nd_lit); break; case NODE_LIT: @@ -1354,8 +1515,8 @@ rb_eval(node) case NODE_ATTRSET: if (the_frame->argc != 1) - Fail("Wrong # of arguments(%d for 1)", the_frame->argc); - result = rb_ivar_set(Qself, node->nd_vid, the_frame->argv[0]); + ArgError("Wrong # of arguments(%d for 1)", the_frame->argc); + result = rb_ivar_set(self, node->nd_vid, the_frame->argv[0]); break; case NODE_DEFN: @@ -1365,9 +1526,17 @@ rb_eval(node) int noex; body = search_method(the_class, node->nd_mid, &origin); - if (body && verbose && origin != (VALUE)the_class - && body->nd_noex != node->nd_noex) { - Warning("change method %s's scope", rb_id2name(node->nd_mid)); + if (body) { + if (origin == (VALUE)the_class) { + Warning("redefine %s", rb_id2name(node->nd_mid)); + } + else { + if (body->nd_noex != node->nd_noex) { + Warning("change method %s's scope", + rb_id2name(node->nd_mid)); + } + } + rb_clear_cache(); } if (body) noex = body->nd_noex; @@ -1380,23 +1549,38 @@ rb_eval(node) case NODE_DEFS: if (node->nd_defn) { - VALUE recv = rb_eval(node->nd_recv); + VALUE recv = rb_eval(self, node->nd_recv); + VALUE class; + NODE *body; + + if (NIL_P(recv)) { + TypeError("Can't define method \"%s\" for nil", + rb_id2name(node->nd_mid)); + } - if (recv == Qnil) { - Fail("Can't define method \"%s\" for nil", - rb_id2name(node->nd_mid)); + class = rb_singleton_class(recv); + if (st_lookup(RCLASS(class)->m_tbl, node->nd_mid, &body)) { + Warning("redefine %s", rb_id2name(node->nd_mid)); } + rb_clear_cache(); rb_funcall(recv, rb_intern("singleton_method_added"), 1, INT2FIX(node->nd_mid)); - rb_add_method(rb_singleton_class(recv),node->nd_mid,node->nd_defn, - NOEX_PUBLIC); + rb_add_method(class, node->nd_mid, node->nd_defn, NOEX_PUBLIC); result = Qnil; } break; case NODE_UNDEF: - rb_add_method(the_class, node->nd_mid, Qnil, NOEX_PUBLIC); - result = Qnil; + { + NODE *body; + + if (st_lookup(the_class->m_tbl, node->nd_mid, &body)) { + Warning("redefine %s", rb_id2name(node->nd_mid)); + } + rb_clear_cache(); + rb_add_method(the_class, node->nd_mid, 0, NOEX_PUBLIC); + result = Qnil; + } break; case NODE_ALIAS: @@ -1410,35 +1594,33 @@ rb_eval(node) struct RClass *tmp; if (node->nd_super) { - super = rb_eval(node->nd_super); - if (super == Qnil || TYPE(super) != T_CLASS) { - Fail("superclass undefined"); - } + super = superclass(self, node->nd_super); } else { - super = Qnil; + super = 0; } - if (rb_const_defined(the_class, node->nd_cname)) { + if (!rb_autoload_defined(node->nd_cname) && + ev_const_defined(the_frame->cbase, node->nd_cname)) { class = rb_const_get(the_class, node->nd_cname); + if (TYPE(class) != T_CLASS) + TypeError("%s is not a class", rb_id2name(node->nd_cname)); if (super) { - if (TYPE(class) != T_CLASS) - Fail("%s is not a class", rb_id2name(node->nd_cname)); tmp = RCLASS(class)->super; - while (FL_TEST(tmp, FL_SINGLE)) { + while (FL_TEST(tmp, FL_SINGLETON)) { tmp = RCLASS(tmp)->super; } while (TYPE(tmp) == T_ICLASS) { tmp = RCLASS(tmp)->super; } if (tmp != RCLASS(super)) - Fail("superclass mismatch for %s", - rb_id2name(node->nd_cname)); + TypeError("superclass mismatch for %s", + rb_id2name(node->nd_cname)); } Warning("extending class %s", rb_id2name(node->nd_cname)); } else { - if (super == Qnil) super = cObject; + if (!super) super = cObject; class = rb_define_class_id(node->nd_cname, super); rb_const_set(the_class, node->nd_cname, class); rb_set_class_path(class,the_class,rb_id2name(node->nd_cname)); @@ -1453,10 +1635,11 @@ rb_eval(node) { VALUE module; - if (rb_const_defined(the_class, node->nd_cname)) { + if (!rb_autoload_defined(node->nd_cname) && + ev_const_defined(the_frame->cbase, node->nd_cname)) { module = rb_const_get(the_class, node->nd_cname); if (TYPE(module) != T_MODULE) - Fail("%s is not a module", rb_id2name(node->nd_cname)); + TypeError("%s is not a module", rb_id2name(node->nd_cname)); Warning("extending module %s", rb_id2name(node->nd_cname)); } else { @@ -1473,8 +1656,11 @@ rb_eval(node) case NODE_DEFINED: { VALUE obj; + char buf[20]; + char *desc = 0; node = node->nd_head; + switch (nd_type(node)) { case NODE_SUPER: case NODE_ZSUPER: @@ -1486,17 +1672,16 @@ rb_eval(node) break; case NODE_FCALL: - obj = CLASS_OF(Qself); + obj = CLASS_OF(self); goto check_bound; case NODE_CALL: PUSH_TAG(); if ((state = EXEC_TAG()) == 0) { - obj = rb_eval(node->nd_recv); + obj = rb_eval(self, node->nd_recv); } POP_TAG(); - if (state == TAG_FAIL) { - result = FALSE; + if (state) { break; } else { @@ -1505,27 +1690,23 @@ rb_eval(node) check_bound: if (method_boundp(obj, node->nd_mid, nd_type(node)== NODE_CALL)) { - result = TRUE; + desc = "method"; } - else result = FALSE; } break; case NODE_YIELD: - result = iterator_p(); + if (iterator_p()) { + desc = "iterator"; + } break; - case NODE_BREAK: - case NODE_CONTINUE: - case NODE_REDO: - case NODE_RETRY: - case NODE_SELF: + desc = "self"; break; case NODE_NIL: - case NODE_FAIL: - case NODE_ATTRSET: - case NODE_DEFINED: + desc = "nil"; break; + case NODE_ATTRSET: case NODE_OP_ASGN1: case NODE_OP_ASGN2: case NODE_MASGN: @@ -1534,60 +1715,80 @@ rb_eval(node) case NODE_GASGN: case NODE_IASGN: case NODE_CASGN: + desc = "asignment"; break; + case NODE_LVAR: + desc = "local-variable"; break; case NODE_DVAR: - result = TRUE; - break; + desc = "dynamic-local-variable"; break; case NODE_GVAR: - result = rb_gvar_defined(node->nd_entry); + if (rb_gvar_defined(node->nd_entry)) { + desc = "global-variable"; + } break; case NODE_IVAR: - result = rb_ivar_defined(node->nd_vid); + if (rb_ivar_defined(self, node->nd_vid)) { + desc = "instance-variable"; + } break; case NODE_CVAR: - result = rb_const_defined(node->nd_rval->nd_clss, node->nd_vid); - break; - - case NODE_CONST: - result = TRUE; + if (ev_const_defined(the_frame->cbase, node->nd_vid)) { + case NODE_CONST: /* jump in */ + desc = "class-constant"; + } break; case NODE_COLON2: PUSH_TAG(); if ((state = EXEC_TAG()) == 0) { - obj = rb_eval(node->nd_head); + obj = rb_eval(self, node->nd_head); } POP_TAG(); - if (state == TAG_FAIL) result = FALSE; + if (state) { + break; + } else { if (state) JUMP_TAG(state); - result = rb_const_defined(obj, node->nd_mid); + switch (TYPE(obj)) { + case T_CLASS: + case T_MODULE: + if (rb_const_defined_at(obj, node->nd_mid)) + desc = "class-constant"; + break; + } } break; case NODE_NTH_REF: - result = reg_nth_defined(node->nd_nth, MATCH_DATA); + if (reg_nth_defined(node->nd_nth, MATCH_DATA)) { + sprintf(buf, "$%d", node->nd_nth); + desc = buf; + } break; case NODE_BACK_REF: - result = reg_nth_defined(0, MATCH_DATA); + if (reg_nth_defined(0, MATCH_DATA)) { + sprintf(buf, "$%c", node->nd_nth); + desc = buf; + } break; default: PUSH_TAG(); if ((state = EXEC_TAG()) == 0) { - rb_eval(node); + rb_eval(self, node); } POP_TAG(); - if (state == TAG_FAIL) result = FALSE; + if (state) break; else { - if (state) JUMP_TAG(state); - result = TRUE; + desc = "expression"; } } + if (desc) result = str_new2(desc); + else result = FALSE; } break; @@ -1595,12 +1796,8 @@ rb_eval(node) Bug("unknown node type %d", nd_type(node)); } finish: -#ifdef SAFE_SIGHANDLE - if (trap_pending) { - rb_trap_exec(); - } -#endif - return result; /* not reached */ + CHECK_INTS; + return result; } static void @@ -1608,7 +1805,8 @@ module_setup(module, node) VALUE module; NODE *node; { - int state; + NODE *state; + VALUE save = the_frame->cbase; /* fill c-ref */ node->nd_clss = module; @@ -1616,12 +1814,12 @@ module_setup(module, node) PUSH_CLASS(); the_class = (struct RClass*)module; - PUSH_SELF((VALUE)the_class); PUSH_SCOPE(); - if (node->nd_cnt > 0) { - the_scope->local_vars = ALLOCA_N(VALUE, node->nd_cnt); - MEMZERO(the_scope->local_vars, VALUE, node->nd_cnt); + if (node->nd_rval) the_frame->cbase = node->nd_rval; + if (node->nd_tbl) { + the_scope->local_vars = ALLOCA_N(VALUE, node->nd_tbl[0]); + memclear(the_scope->local_vars, node->nd_tbl[0]); the_scope->local_tbl = node->nd_tbl; } else { @@ -1631,21 +1829,48 @@ module_setup(module, node) PUSH_TAG(); if ((state = EXEC_TAG()) == 0) { - rb_eval(node->nd_body); + rb_eval((VALUE)the_class, node->nd_body); } POP_TAG(); POP_SCOPE(); - POP_SELF(); POP_CLASS(); + the_frame->cbase = save; if (state) JUMP_TAG(state); } -VALUE -rb_responds_to(obj, id) +int +rb_respond_to(obj, id) VALUE obj; ID id; { - if (rb_method_boundp(CLASS_OF(obj), id)) { + if (rb_method_boundp(CLASS_OF(obj), id, 0)) { + return TRUE; + } + return FALSE; +} + +static VALUE +krn_respond_to(argc, argv, obj) + int argc; + VALUE *argv; + VALUE obj; +{ + VALUE mid, priv; + ID id; + + rb_scan_args(argc, argv, "11", &mid, &priv); + id = rb_to_id(mid); + if (rb_method_boundp(CLASS_OF(obj), id, !RTEST(priv))) { + return TRUE; + } + return FALSE; +} + +static VALUE +mod_method_defined(mod, mid) + VALUE mod, mid; +{ + if (rb_method_boundp(mod, rb_to_id(mid), TRUE)) { return TRUE; } return FALSE; @@ -1655,11 +1880,11 @@ void rb_exit(status) int status; { - last_val = INT2FIX(status); - if (prot_tag) - JUMP_TAG(TAG_EXIT); - rb_trap_exit(); - exit(FIX2UINT(last_val)); + if (prot_tag) { + exit_status = status; + rb_raise(exc_new(eSystemExit, "")); + } + exit(status); } static VALUE @@ -1671,71 +1896,141 @@ f_exit(argc, argv, obj) VALUE status; if (rb_scan_args(argc, argv, "01", &status) == 1) { - Need_Fixnum(status); + status = NUM2INT(status); } else { - status = INT2FIX(0); + status = 0; } - last_val = status; - JUMP_TAG(TAG_EXIT); - - return Qnil; /* not reached */ + rb_exit(status); + /* not reached */ } void rb_break() { - JUMP_TAG(TAG_BREAK); + JUMP_TAG2(TAG_BREAK, 0); } -void -rb_redo() +static VALUE +f_break() +{ + JUMP_TAG2(TAG_BREAK, 0); +} + +static VALUE +f_next() +{ + JUMP_TAG2(TAG_NEXT, 0); +} + +static VALUE +f_redo() +{ + JUMP_TAG2(TAG_REDO, 0); +} + +static VALUE +f_retry() +{ + JUMP_TAG2(TAG_RETRY, 0); +} + +#ifdef __GNUC__ +static volatile voidfn rb_longjmp; +#endif + +static VALUE make_backtrace(); + +static void +rb_longjmp(tag, mesg) + int tag; + VALUE mesg; { - JUMP_TAG(TAG_REDO); + if (NIL_P(errat) && NIL_P(mesg)) { + errinfo = exc_new(eRuntimeError, ""); + } + + if (sourcefile && (NIL_P(errat) || !NIL_P(mesg))) { + errat = make_backtrace(); + } + + if (!NIL_P(mesg)) { + if (obj_is_kind_of(mesg, eGlobalExit)) { + errinfo = mesg; + } + else { + errinfo = exc_new2(eRuntimeError, mesg); + } + str_freeze(errinfo); + } + + JUMP_TAG2(tag, 0); } void -rb_retry() +rb_raise(mesg) + VALUE mesg; { - JUMP_TAG(TAG_RETRY); + rb_longjmp(TAG_RAISE, mesg); } void -rb_fail(mesg) +rb_fatal(mesg) VALUE mesg; { - char buf[BUFSIZ]; + rb_longjmp(TAG_FATAL, mesg); +} - if (errat == Qnil && mesg == Qnil) { - errstr = Qnil; +void +rb_interrupt() +{ + rb_raise(exc_new(eInterrupt, "Interrupt")); +} + +static VALUE +f_raise(argc, argv) + int argc; + VALUE *argv; +{ + VALUE arg1, arg2; + VALUE etype, mesg; + + etype = eRuntimeError; + mesg = Qnil; + switch (rb_scan_args(argc, argv, "02", &arg1, &arg2)) { + case 1: + mesg = arg1; + break; + case 2: + etype = arg1; + mesg = arg2; + break; } - if (errat == Qnil && sourcefile) { - if (the_frame->last_func) { - last_func = the_frame->last_func; + if (!NIL_P(mesg)) { + Check_Type(mesg, T_STRING); + if (!obj_is_kind_of(mesg, eException)) { + mesg = exc_new2(etype, mesg); } - sprintf(buf, "%s:%d", sourcefile, sourceline); - errat = str_new2(buf); } - if (mesg) { - errstr = mesg; - } - if (prot_tag->level == 0) error_print(last_func); - JUMP_TAG(TAG_FAIL); + PUSH_FRAME(); /* fake frame */ + *the_frame = *_frame.prev->prev; + rb_raise(mesg); + POP_FRAME(); } -VALUE +int iterator_p() { - if (iter->iter) return TRUE; + if (the_frame->iter) return TRUE; return FALSE; } static VALUE f_iterator_p() { - if (iter->prev && iter->prev->iter) return TRUE; + if (the_frame->prev && the_frame->prev->iter) return TRUE; return FALSE; } @@ -1743,18 +2038,19 @@ VALUE rb_yield_0(val, self) VALUE val, self; { - struct BLOCK *block; NODE *node; - int state; + NODE *state; VALUE result = Qnil; + struct BLOCK *block; struct SCOPE *old_scope; struct FRAME frame; if (!iterator_p()) { - Fail("yield called out of iterator"); + Raise(eLocalJumpError, "yield called out of iterator"); } PUSH_VARS(); + PUSH_CLASS(); block = the_block; frame = block->frame; frame.prev = the_frame; @@ -1763,52 +2059,53 @@ rb_yield_0(val, self) the_scope = block->scope; the_block = block->prev; the_dyna_vars = block->d_vars; + the_class = block->class; + if (!self) self = block->self; + node = block->body; if (block->var) { if (nd_type(block->var) == NODE_MASGN) - masign(block->var, val); + masign(self, block->var, val); else - asign(block->var, val); + asign(self, block->var, val); } - node = block->body; - PUSH_ITER(block->iter); - PUSH_SELF(self?self:block->self); PUSH_TAG(); - switch (state = EXEC_TAG()) { + if ((state = EXEC_TAG()) == 0) { redo: - case 0: if (!node) { result = Qnil; } else if (nd_type(node) == NODE_CFUNC) { - result = (*node->nd_cfnc)(val,node->nd_argc); + result = (*node->nd_cfnc)(val,node->nd_argc,self); } else { - result = rb_eval(node); + result = rb_eval(self, node); + } + } + else { + switch (state->nd_tag) { + case TAG_REDO: + goto redo; + case TAG_NEXT: + state = 0; + break; + case TAG_BREAK: + case TAG_RETURN: + state->nd_tlev = block->level; + state->nd_tag = IN_BLOCK|state->nd_tag; + break; + default: + break; } - break; - case TAG_REDO: - goto redo; - case TAG_CONTINUE: - state = 0; - break; - case TAG_BREAK: - case TAG_RETURN: - target_level = block->level; - state = IN_BLOCK|state; - break; - default: - break; } POP_TAG(); - POP_SELF(); POP_ITER(); + POP_CLASS(); POP_VARS(); the_block = block; the_frame = the_frame->prev; the_scope = old_scope; if (state) JUMP_TAG(state); - return result; } @@ -1823,11 +2120,10 @@ static VALUE f_loop() { for (;;) { rb_yield(Qnil); } - return Qnil; } static VALUE -masign(node, val) +masign(self, node, val) NODE *node; VALUE val; { @@ -1842,30 +2138,31 @@ masign(node, val) } len = RARRAY(val)->len; for (i=0; list && i<len; i++) { - asign(list->nd_head, RARRAY(val)->ptr[i]); + asign(self, list->nd_head, RARRAY(val)->ptr[i]); list = list->nd_next; } if (node->nd_args) { if (!list && i<len) { - asign(node->nd_args, ary_new4(len-i, RARRAY(val)->ptr+i)); + asign(self, node->nd_args, ary_new4(len-i, RARRAY(val)->ptr+i)); } else { - asign(node->nd_args, Qnil); + asign(self, node->nd_args, ary_new2(0)); } } } else if (node->nd_args) { - asign(node->nd_args, Qnil); + asign(self, node->nd_args, Qnil); } while (list) { - asign(list->nd_head, Qnil); + asign(self, list->nd_head, Qnil); list = list->nd_next; } return val; } static void -asign(lhs, val) +asign(self, lhs, val) + VALUE self; NODE *lhs; VALUE val; { @@ -1875,7 +2172,7 @@ asign(lhs, val) break; case NODE_IASGN: - rb_ivar_set(Qself, lhs->nd_vid, val); + rb_ivar_set(self, lhs->nd_vid, val); break; case NODE_LASGN: @@ -1895,16 +2192,16 @@ asign(lhs, val) case NODE_CALL: { VALUE recv; - recv = rb_eval(lhs->nd_recv); - if (lhs->nd_args->nd_head == Qnil) { + recv = rb_eval(self, lhs->nd_recv); + if (!lhs->nd_args->nd_head) { /* attr set */ - rb_funcall(recv, lhs->nd_mid, 1, val); + rb_funcall2(recv, lhs->nd_mid, 1, &val); } else { /* array set */ VALUE args; - args = rb_eval(lhs->nd_args); + args = rb_eval(self, lhs->nd_args); RARRAY(args)->ptr[RARRAY(args)->len-1] = val; rb_apply(recv, lhs->nd_mid, args); } @@ -1922,13 +2219,15 @@ rb_iterate(it_proc, data1, bl_proc, data2) VALUE (*it_proc)(), (*bl_proc)(); void *data1, *data2; { - int state; + NODE *state; VALUE retval = Qnil; NODE *node = NEW_CFUNC(bl_proc, data2); + VALUE self = TopSelf; + int tag_level; iter_retry: PUSH_ITER(ITER_PRE); - PUSH_BLOCK(Qnil, node); + PUSH_BLOCK(0, node); PUSH_TAG(); state = EXEC_TAG(); @@ -1937,33 +2236,53 @@ rb_iterate(it_proc, data1, bl_proc, data2) } POP_TAG(); + tag_level = the_block->level; POP_BLOCK(); POP_ITER(); - switch (state) { - case 0: - break; + if (state) { + switch (state->nd_tag) { + case TAG_RETRY: + goto iter_retry; - case TAG_RETRY: - goto iter_retry; + case IN_BLOCK|TAG_BREAK: + if (state->nd_tlev != tag_level) { + JUMP_TAG(state); + } + retval = Qnil; + break; - case IN_BLOCK|TAG_BREAK: - if (target_level != tag_level) { + case IN_BLOCK|TAG_RETURN: + if (state->nd_tlev == tag_level) { + state->nd_tag &= ~IN_BLOCK; + } + /* fall through */ + default: JUMP_TAG(state); } - retval = Qnil; - break; + } + return retval; +} - case IN_BLOCK|TAG_RETURN: - if (target_level == tag_level) { - state &= ~IN_BLOCK; - } - /* fall through */ - default: - JUMP_TAG(state); +static int +handle_rescue(self, node) + VALUE self; + NODE *node; +{ + int argc; VALUE *argv; /* used in SETUP_ARGS */ + + if (!node->nd_args) { + return obj_is_kind_of(errinfo, eException); } - return retval; + PUSH_ITER(ITER_NOT); + SETUP_ARGS; + POP_ITER(); + while (argc--) { + if (obj_is_kind_of(errinfo, argv[0])) return 1; + argv++; + } + return 0; } VALUE @@ -1971,43 +2290,36 @@ rb_rescue(b_proc, data1, r_proc, data2) VALUE (*b_proc)(), (*r_proc)(); void *data1, *data2; { - int state; - VALUE result = Qnil; - volatile SIGHANDLE handle; + NODE *state; + VALUE result; PUSH_TAG(); - switch (state = EXEC_TAG()) { - case 0: - handle = sig_beg(); + if ((state = EXEC_TAG()) == 0) { retry_entry: result = (*b_proc)(data1); - break; - - case TAG_FAIL: - sig_end(handle); - if (r_proc) { - PUSH_TAG(); - state = EXEC_TAG(); - if (state == 0) { - result = (*r_proc)(data2); + } + else { + if (state->nd_tag == TAG_RAISE) { + if (r_proc) { + PUSH_TAG(); + state = EXEC_TAG(); + if (state == 0) { + result = (*r_proc)(data2, errinfo); + } + POP_TAG(); + if (state && state->nd_tag == TAG_RETRY) { + state = 0; + goto retry_entry; + } } - POP_TAG(); - if (state == TAG_RETRY) { - goto retry_entry; + else { + result = Qnil; + state = 0; + } + if (state == 0) { + errat = Qnil; } } - else { - state = 0; - } - if (state == 0) { - errat = Qnil; - last_func = 0; - } - break; - - default: - sig_end(handle); - break; } POP_TAG(); if (state) JUMP_TAG(state); @@ -2020,7 +2332,7 @@ rb_ensure(b_proc, data1, e_proc, data2) VALUE (*b_proc)(), (*e_proc)(); void *data1, *data2; { - int state; + NODE *state; VALUE result = Qnil; PUSH_TAG(); @@ -2030,7 +2342,7 @@ rb_ensure(b_proc, data1, e_proc, data2) POP_TAG(); (*e_proc)(data2); - if (state != 0) { + if (state) { JUMP_TAG(state); } return result; @@ -2044,7 +2356,7 @@ f_missing(argc, argv, obj) VALUE *argv; VALUE obj; { - VALUE desc; + VALUE desc = 0; ID id; char *format; struct FRAME *frame; @@ -2052,27 +2364,44 @@ f_missing(argc, argv, obj) id = FIX2INT(argv[0]); argc--; argv++; - if (TYPE(obj) == T_STRING) { - desc = krn_inspect(obj); - } - else { + switch (TYPE(obj)) { + case T_NIL: + format = "undefined method `%s' for nil"; + break; + case T_TRUE: + format = "undefined method `%s' for TRUE"; + break; + case T_FALSE: + format = "undefined method `%s' for FALSE"; + break; + case T_OBJECT: desc = obj_as_string(obj); + break; + default: + desc = rb_inspect(obj); + break; + } + if (desc) { + if (last_noex) + format = "private method `%s' called for %s(%s)"; + else if (argc == 0) { + format = "undefined local variable or method `%s' for %s(%s)"; + } + else { + format = "undefined method `%s' for %s(%s)"; + } + if (RSTRING(desc)->len > 65) { + desc = krn_to_s(obj); + } } - if (last_noex) - format = "method `%s' not available for %s(%s)"; - else - format = "undefined method `%s' for %s(%s)"; - /* fake frame */ - PUSH_FRAME(); - frame = the_frame->prev; - *the_frame = *frame->prev; - the_frame->prev = frame; - - Fail(format, - rb_id2name(id), - RSTRING(desc)->ptr, - rb_class2name(CLASS_OF(obj))); + PUSH_FRAME(); /* fake frame */ + *the_frame = *_frame.prev->prev; + + NameError(format, + rb_id2name(id), + desc?RSTRING(desc)->ptr:"", + desc?rb_class2name(CLASS_OF(obj)):""); POP_FRAME(); } @@ -2095,8 +2424,20 @@ rb_undefined(obj, id, argc, argv, noex) return rb_funcall2(obj, rb_intern("method_missing"), argc+1, nargv); } -#define STACK_LEVEL_MAX 10000 -static int stack_level; +#define STACK_LEVEL_MAX 655350 +extern VALUE *gc_stack_start; +static int +stack_length() +{ + VALUE pos; + +#ifdef sparc + return gc_stack_start - &pos + 0x80; +#else + return (&pos < gc_stack_start) ? gc_stack_start - &pos + : &pos - gc_stack_start; +#endif +} static VALUE rb_call(class, recv, mid, argc, argv, scope) @@ -2109,38 +2450,30 @@ rb_call(class, recv, mid, argc, argv, scope) { NODE *body; int noex; - VALUE result = Qnil; + ID id = mid; struct cache_entry *ent; + VALUE result = Qnil; int itr; enum node_type type; + static int tick; /* is it in the method cache? */ ent = cache + EXPR1(class, mid); if (ent->mid == mid && ent->class == class) { class = ent->origin; - mid = ent->mid; - body = ent->method; + id = ent->mid0; noex = ent->noex; + body = ent->method; } - else { - ID id = mid; - - if ((body = rb_get_method_body(&class, &id, &noex)) == FALSE) { - return rb_undefined(recv, mid, argc, argv, 0); - } - mid = id; + else if ((body = rb_get_method_body(&class, &id, &noex)) == 0) { + return rb_undefined(recv, mid, argc, argv, 0); } - switch (noex) { - case NOEX_PUBLIC: - break; - case NOEX_PRIVATE: - if (scope == 0) /* receiver specified */ - return rb_undefined(recv, mid, argc, argv, 1); - break; - } + /* receiver specified form for private method */ + if (noex == NOEX_PRIVATE && scope == 0) + return rb_undefined(recv, mid, argc, argv, 1); - switch (iter->iter) { + switch (the_iter->iter) { case ITER_PRE: itr = ITER_CUR; break; @@ -2153,16 +2486,15 @@ rb_call(class, recv, mid, argc, argv, scope) type = nd_type(body); if (type == NODE_ZSUPER) { /* for re-scoped method */ - return rb_call(class->super, recv, mid, argc, argv, scope?scope:1); + return rb_call(class->super, recv, id, argc, argv, scope?scope:1); } - if (stack_level++ > STACK_LEVEL_MAX) - Fail("stack level too deep"); + if (++tick % 1000 == 0 && stack_length() > STACK_LEVEL_MAX) + Fatal("stack level too deep"); PUSH_ITER(itr); - PUSH_SELF(recv); PUSH_FRAME(); - the_frame->last_func = mid; + the_frame->last_func = id; the_frame->last_class = class; the_frame->argc = argc; the_frame->argv = argv; @@ -2173,7 +2505,7 @@ rb_call(class, recv, mid, argc, argv, scope) int len = body->nd_argc; if (len >= 0 && argc != len) { - Fail("Wrong # of arguments(%d for %d)", argc, len); + ArgError("Wrong # of arguments(%d for %d)", argc, len); } switch (len) { @@ -2273,7 +2605,7 @@ rb_call(class, recv, mid, argc, argv, scope) len, rb_class2name(class), rb_id2name(mid)); } else { - Fail("too many arguments(%d)", len); + ArgError("too many arguments(%d)", len); } break; } @@ -2283,19 +2615,20 @@ rb_call(class, recv, mid, argc, argv, scope) /* for attr get/set */ case NODE_ATTRSET: case NODE_IVAR: - result = rb_eval(body); + result = rb_eval(recv, body); break; default: { - int state; + NODE *state; VALUE *local_vars; PUSH_SCOPE(); - if (body->nd_cnt > 0) { - local_vars = ALLOCA_N(VALUE, body->nd_cnt); - MEMZERO(local_vars, VALUE, body->nd_cnt); + if (body->nd_rval) the_frame->cbase = body->nd_rval; + if (body->nd_tbl) { + local_vars = ALLOCA_N(VALUE, body->nd_tbl[0]); + memclear(local_vars, body->nd_tbl[0]); the_scope->local_tbl = body->nd_tbl; the_scope->local_vars = local_vars; } @@ -2306,6 +2639,8 @@ rb_call(class, recv, mid, argc, argv, scope) body = body->nd_body; PUSH_TAG(); + PUSH_VARS(); + dyna_var_mark(); state = EXEC_TAG(); if (state == 0) { if (nd_type(body) == NODE_BLOCK) { @@ -2321,7 +2656,7 @@ rb_call(class, recv, mid, argc, argv, scope) if (i > argc || (node->nd_rest == -1 && i+(node->nd_opt?node->nd_opt->nd_alen:0)<argc)){ - Fail("Wrong # of arguments(%d for %d)", argc, i); + ArgError("Wrong # of arguments(%d for %d)", argc, i); } if (local_vars) { @@ -2333,56 +2668,54 @@ rb_call(class, recv, mid, argc, argv, scope) NODE *opt = node->nd_opt; while (opt && argc) { - asign(opt->nd_head, *argv); + asign(recv, opt->nd_head, *argv); argv++; argc--; opt = opt->nd_next; } - rb_eval(opt); + rb_eval(recv, opt); } if (node->nd_rest >= 0) { if (argc > 0) local_vars[node->nd_rest]=ary_new4(argc,argv); else - local_vars[node->nd_rest] = ary_new2(0); + local_vars[node->nd_rest]=ary_new2(0); } } } else if (nd_type(body) == NODE_ARGS) { body = 0; } - result = rb_eval(body); + result = rb_eval(recv, body); } + POP_VARS(); POP_TAG(); POP_SCOPE(); - switch (state) { - case 0: - break; - case TAG_CONTINUE: - Fatal("unexpected continue"); - break; - case TAG_BREAK: - Fatal("unexpected break"); - break; - case TAG_REDO: - Fatal("unexpected redo"); - break; - case TAG_RETURN: - result = last_val; - break; - case TAG_RETRY: - if (!iterator_p()) { - Fatal("retry outside of rescue clause"); + if (state) { + switch (state->nd_tag) { + case TAG_NEXT: + Raise(eLocalJumpError, "unexpected next"); + break; + case TAG_BREAK: + Raise(eLocalJumpError, "unexpected break"); + break; + case TAG_REDO: + Raise(eLocalJumpError, "unexpected redo"); + break; + case TAG_RETURN: + result = state->nd_tval; + break; + case TAG_RETRY: + if (!iterator_p()) { + Raise(eLocalJumpError, "retry outside of rescue clause"); + } + default: + JUMP_TAG(state); } - default: - stack_level--; - JUMP_TAG(state); } } } POP_FRAME(); - POP_SELF(); POP_ITER(); - stack_level--; return result; } @@ -2410,7 +2743,7 @@ f_send(argc, argv, recv) VALUE vid; ID mid; - if (argc == 0) Fail("no method name given"); + if (argc == 0) ArgError("no method name given"); vid = argv[0]; argc--; argv++; if (TYPE(vid) == T_STRING) { @@ -2463,26 +2796,31 @@ rb_funcall2(recv, mid, argc, argv) } static VALUE -f_caller(argc, argv) - int argc; - VALUE *argv; +backtrace(lev) + int lev; { - VALUE level; struct FRAME *frame = the_frame; - int lev, n; char buf[BUFSIZ]; + VALUE ary; - rb_scan_args(argc, argv, "01", &level); - if (level == Qnil) lev = 1; - else lev = NUM2INT(level); - n = lev; - if (n < 0) Fail("negative level(%d)", n); + ary = ary_new(); + if (lev < 0) { + if (frame->last_func) { + sprintf(buf, "%s:%d:in `%s'", sourcefile, sourceline, + rb_id2name(frame->last_func)); + } + else { + sprintf(buf, "%s:%d", sourcefile, sourceline); + } + ary_push(ary, str_new2(buf)); + } else { - while (n-- > 0) { + while (lev-- > 0) { frame = frame->prev; if (!frame) return Qnil; } - if (!frame->file) return Qnil; + } + while (frame && frame->file) { if (frame->prev && frame->prev->last_func) { sprintf(buf, "%s:%d:in `%s'", frame->file, frame->line, @@ -2491,73 +2829,169 @@ f_caller(argc, argv) else { sprintf(buf, "%s:%d", frame->file, frame->line); } + ary_push(ary, str_new2(buf)); + frame = frame->prev; } - return str_new2(buf); + return ary; +} + +static VALUE +f_caller(argc, argv) + int argc; + VALUE *argv; +{ + VALUE level; + struct FRAME *frame = the_frame; + int lev; + + rb_scan_args(argc, argv, "01", &level); + + if (NIL_P(level)) lev = 1; + else lev = NUM2INT(level); + if (lev < 0) ArgError("negative level(%d)", lev); + + return backtrace(lev); } void rb_backtrace() { - VALUE c, lev; - int n = 0; + int i, lev; + VALUE ary, c; - lev = INT2FIX(n); - while (c = f_caller(1, &lev)) { - printf("%s\n", RSTRING(c)->ptr); - n++; - lev = INT2FIX(n); + lev = INT2FIX(0); + ary = backtrace(-1); + for (i=0; i<RARRAY(ary)->len; i++) { + printf("\tfrom %s\n", RSTRING(RARRAY(ary)->ptr)->ptr); } } +static VALUE +make_backtrace() +{ + VALUE lev; + + lev = INT2FIX(0); + return backtrace(-1); +} + ID rb_frame_last_func() { return the_frame->last_func; } -int rb_in_eval = 0; +static NODE* +compile(src) + struct RString *src; +{ + NODE *node; + + Check_Type(src, T_STRING); + + errinfo = Qnil; + node = compile_string(sourcefile, src->ptr, src->len); + + if (nerrs == 0) return node; + return 0; +} + +static void blk_free(); static VALUE -f_eval(obj, src) - VALUE obj; +eval(self, src, scope) + VALUE self; struct RString *src; + struct RData *scope; { + struct BLOCK *data; VALUE result = Qnil; - int state; NODE *node; + NODE *state; + struct BLOCK *old_block; + struct SCOPE *old_scope; + struct FRAME frame; + char *file = sourcefile; + int line = sourceline; - Check_Type(src, T_STRING); PUSH_TAG(); - rb_in_eval = 1; - node = eval_tree; - PUSH_CLASS(); + if (!NIL_P(scope)) { + if (TYPE(scope) != T_DATA || scope->dfree != blk_free) { + TypeError("wrong argument type %s (expected Proc/Binding)", + rb_class2name(CLASS_OF(scope))); + } + + Get_Data_Struct(scope, struct BLOCK, data); + + /* PUSH BLOCK from data */ + frame = data->frame; + frame.prev = the_frame; + the_frame = &(frame); + old_scope = the_scope; + the_scope = data->scope; + old_block = the_block; + the_block = data->prev; + the_dyna_vars = data->d_vars; + the_class = data->class; + self = data->self; + } + + rb_in_eval++; if (TYPE(the_class) == T_ICLASS) { the_class = (struct RClass*)RBASIC(the_class)->class; } - if ((state = EXEC_TAG()) == 0) { - lex_setsrc("(eval)", src->ptr, src->len); - eval_tree = 0; - PUSH_VARS(); - yyparse(); - POP_VARS(); - if (nerrs == 0) { - result = Eval(); + if (!compile(src)) { + rb_in_eval--; + compile_error("eval()"); } + result = eval_node(self); + } + if (!NIL_P(scope)) { + the_frame = the_frame->prev; + the_scope = old_scope; + the_block = old_block; } - eval_tree = node; POP_CLASS(); POP_TAG(); - if (state) JUMP_TAG(state); - - if (nerrs > 0) { - syntax_error(); + rb_in_eval--; + if (state) { + VALUE err ; + + switch (state->nd_tag) { + case TAG_RAISE: + sourcefile = file; + sourceline = line; + if (strcmp(sourcefile, "(eval)") == 0) { + err = errat; + if (sourceline != 1) { + str_cat(err, ": ", 2); + str_cat(err, RSTRING(errinfo)->ptr, RSTRING(errinfo)->len); + } + errat = Qnil; + rb_raise(exc_new2(CLASS_OF(errinfo), err)); + } + rb_raise(Qnil); + } + JUMP_TAG(state); } return result; } +static VALUE +f_eval(argc, argv, self) + int argc; + VALUE *argv; + VALUE self; +{ + VALUE src, scope; + + rb_scan_args(argc, argv, "11", &src, &scope); + return eval(self, src, scope); +} + VALUE rb_load_path; char *dln_find_file(); @@ -2567,20 +3001,18 @@ find_file(file) char *file; { extern VALUE rb_load_path; - VALUE sep, vpath; + VALUE vpath; char *path; if (file[0] == '/') return file; if (rb_load_path) { Check_Type(rb_load_path, T_ARRAY); - sep = str_new2(":"); - vpath = ary_join(rb_load_path, sep); + vpath = ary_join(rb_load_path, str_new2(":")); path = RSTRING(vpath)->ptr; - sep = Qnil; } else { - path = Qnil; + path = 0; } return dln_find_file(file, path); @@ -2591,36 +3023,39 @@ f_load(obj, fname) VALUE obj; struct RString *fname; { - int state, in_eval = rb_in_eval; + NODE *state; char *file, *src; + volatile ID last_func; Check_Type(fname, T_STRING); file = find_file(fname->ptr); - if (!file) Fail("No such file to load -- %s", fname->ptr); + if (!file) LoadError("No such file to load -- %s", fname->ptr); - PUSH_SELF(TopSelf); PUSH_TAG(); PUSH_CLASS(); the_class = (struct RClass*)cObject; PUSH_SCOPE(); the_scope->local_vars = top_scope->local_vars; the_scope->local_tbl = top_scope->local_tbl; - rb_in_eval = 1; + state = EXEC_TAG(); + last_func = the_frame->last_func; + the_frame->last_func = 0; if (state == 0) { + rb_in_eval++; rb_load_file(file); + rb_in_eval--; if (nerrs == 0) { - Eval(); + eval_node(TopSelf); } } + the_frame->last_func = last_func; top_scope->flag = the_scope->flag; POP_SCOPE(); POP_CLASS(); POP_TAG(); - POP_SELF(); - rb_in_eval = in_eval; if (nerrs > 0) { - rb_fail(errstr); + rb_raise(errinfo); } if (state) JUMP_TAG(state); @@ -2629,16 +3064,17 @@ f_load(obj, fname) static VALUE rb_features; -static VALUE +static int rb_provided(feature) char *feature; { + struct RArray *features = RARRAY(rb_features); VALUE *p, *pend; char *f; int len; - p = RARRAY(rb_features)->ptr; - pend = p + RARRAY(rb_features)->len; + p = features->ptr; + pend = p + features->len; while (p < pend) { Check_Type(*p, T_STRING); f = RSTRING(*p)->ptr; @@ -2653,6 +3089,11 @@ rb_provided(feature) return FALSE; } +#ifdef THREAD +static int thread_loading(); +static void thread_loading_done(); +#endif + void rb_provide(feature) char *feature; @@ -2670,7 +3111,8 @@ f_require(obj, fname) VALUE load; Check_Type(fname, T_STRING); - if (rb_provided(fname->ptr)) return FALSE; + if (rb_provided(fname->ptr)) + return FALSE; ext = strrchr(fname->ptr, '.'); if (ext) { @@ -2680,9 +3122,9 @@ f_require(obj, fname) if (file) goto rb_load; } else if (strcmp(".o", ext) == 0) { - feature = fname->ptr; + file = feature = fname->ptr; if (strcmp(".o", DLEXT) != 0) { - buf = ALLOCA_N(char, strlen(fname->ptr) + 3); + buf = ALLOCA_N(char, strlen(fname->ptr)+sizeof(DLEXT)+1); strcpy(buf, feature); ext = strrchr(buf, '.'); strcpy(ext, DLEXT); @@ -2696,7 +3138,7 @@ f_require(obj, fname) if (file) goto dyna_load; } } - buf = ALLOCA_N(char, strlen(fname->ptr) + 4); + buf = ALLOCA_N(char, strlen(fname->ptr) + 5); sprintf(buf, "%s.rb", fname->ptr); file = find_file(buf); if (file) { @@ -2710,58 +3152,80 @@ f_require(obj, fname) feature = buf; goto dyna_load; } - Fail("No such file to load -- %s", fname->ptr); + LoadError("No such file to load -- %s", fname->ptr); dyna_load: - load = str_new2(file); - file = RSTRING(load)->ptr; - dln_load(file); - rb_provide(feature); +#ifdef THREAD + if (thread_loading(feature)) return FALSE; + else { + NODE *state; + PUSH_TAG(); + if ((state = EXEC_TAG()) == 0) { +#endif + load = str_new2(file); + file = RSTRING(load)->ptr; + dln_load(file); + rb_provide(feature); +#ifdef THREAD + } + POP_TAG(); + thread_loading_done(); + if (state) JUMP_TAG(state); + } +#endif return TRUE; rb_load: - f_load(obj, fname); - rb_provide(feature); +#ifdef THREAD + if (thread_loading(feature)) return FALSE; + else { + NODE *state; + PUSH_TAG(); + if ((state = EXEC_TAG()) == 0) { +#endif + f_load(obj, fname); + rb_provide(feature); +#ifdef THREAD + } + POP_TAG(); + thread_loading_done(); + if (state) JUMP_TAG(state); + } +#endif return TRUE; } static void -set_method_visibility(argc, argv, ex) +set_method_visibility(self, argc, argv, ex) + VALUE self; int argc; VALUE *argv; int ex; { - VALUE self = Qself; int i; - ID id; for (i=0; i<argc; i++) { - if (FIXNUM_P(argv[i])) { - id = FIX2INT(argv[i]); - } - else { - Check_Type(argv[i], T_STRING); - id = rb_intern(RSTRING(argv[i])->ptr); - } - rb_export_method(self, id, ex); + rb_export_method(self, rb_to_id(argv[i]), ex); } } static VALUE -mod_public(argc, argv) +mod_public(argc, argv, module) int argc; VALUE *argv; + VALUE module; { - set_method_visibility(argc, argv, NOEX_PUBLIC); + set_method_visibility(module, argc, argv, NOEX_PUBLIC); return Qnil; } static VALUE -mod_private(argc, argv) +mod_private(argc, argv, module) int argc; VALUE *argv; + VALUE module; { - set_method_visibility(argc, argv, NOEX_PRIVATE); + set_method_visibility(module, argc, argv, NOEX_PRIVATE); return Qnil; } @@ -2775,19 +3239,13 @@ mod_modfunc(argc, argv, module) ID id; NODE *body, *old; - set_method_visibility(argc, argv, NOEX_PRIVATE); + set_method_visibility(module, argc, argv, NOEX_PRIVATE); for (i=0; i<argc; i++) { - if (FIXNUM_P(argv[i])) { - id = FIX2INT(argv[i]); - } - else { - Check_Type(argv[i], T_STRING); - id = rb_intern(RSTRING(argv[i])->ptr); - } + id = rb_to_id(argv[i]); body = search_method(module, id, 0); if (body == 0 || body->nd_body == 0) { - Fail("undefined method `%s' for module `%s'", - rb_id2name(id), rb_class2name(module)); + NameError("undefined method `%s' for module `%s'", + rb_id2name(id), rb_class2name(module)); } rb_add_method(rb_singleton_class(module), id, body->nd_body, NOEX_PUBLIC); } @@ -2806,7 +3264,21 @@ mod_include(argc, argv, module) Check_Type(argv[i], T_MODULE); rb_include_module(module, argv[i]); } - return (VALUE)module; + return Qnil; +} + +VALUE /* moved from object.c for push_iter */ +class_s_new(argc, argv, class) + int argc; + VALUE *argv; + VALUE class; +{ + VALUE obj = obj_alloc(class); + + PUSH_ITER(iterator_p()?ITER_PRE:ITER_NOT); + rb_funcall2(obj, init, argc, argv); + POP_ITER(); + return obj; } static VALUE @@ -2823,7 +3295,13 @@ obj_extend(argc, argv, obj) VALUE *argv; VALUE obj; { - return mod_include(argc, argv, rb_singleton_class(obj)); + int i; + + mod_include(argc, argv, rb_singleton_class(obj)); + for (i=0; i<argc; i++) { + rb_funcall(argv[i], rb_intern("object_extended"), 1, obj); + } + return Qnil; } void @@ -2833,16 +3311,66 @@ rb_extend_object(obj, module) rb_include_module(rb_singleton_class(obj), module); } -extern VALUE cKernel; extern VALUE cModule; VALUE f_trace_var(); VALUE f_untrace_var(); +extern VALUE rb_str_setter(); + +static VALUE +errat_setter(val, id, var) + VALUE val; + ID id; + VALUE *var; +{ + if (!NIL_P(val) && TYPE(val) != T_ARRAY) { + TypeError("value of $@ must be Array of String"); + } + return *var = val; +} + +static VALUE +f_catch(dmy, tag) +{ + NODE *state; + ID t; + VALUE val; + + t = rb_to_id(tag); + PUSH_TAG(); + if ((state = EXEC_TAG()) == 0) { + val = rb_yield(tag); + } + POP_TAG(); + if (state) { + if (state->nd_tag == TAG_THROW && state->nd_tlev == t) { + return state->nd_tval; + } + JUMP_TAG(state); + } + return val; +} + +static VALUE +f_throw(argc, argv) + int argc; + VALUE *argv; +{ + VALUE tag, value; + ID t; + + rb_scan_args(argc, argv, "11", &tag, &value); + t = rb_to_id(tag); + JUMP_TAG3(TAG_THROW, value, t); + /* not reached */ +} + void Init_eval() { - match = rb_intern("=~"); + init = rb_intern("initialize"); + eqq = rb_intern("==="); each = rb_intern("each"); aref = rb_intern("[]"); @@ -2851,25 +3379,49 @@ Init_eval() rb_global_variable(&top_scope); rb_global_variable(&eval_tree); rb_global_variable(&the_dyna_vars); - rb_define_private_method(cKernel, "exit", f_exit, -1); - rb_define_private_method(cKernel, "eval", f_eval, 1); + + rb_define_hooked_variable("$@", &errat, 0, errat_setter); + rb_define_hooked_variable("$!", &errinfo, 0, rb_str_setter); + + rb_define_private_method(cKernel, "eval", f_eval, -1); rb_define_private_method(cKernel, "iterator?", f_iterator_p, 0); rb_define_private_method(cKernel, "method_missing", f_missing, -1); rb_define_private_method(cKernel, "loop", f_loop, 0); + + rb_define_method(cKernel, "respond_to?", krn_respond_to, -1); + + rb_define_private_method(cKernel, "break", f_break, 0); + rb_define_alias(cKernel, "break!", "break"); + rb_define_private_method(cKernel, "next", f_next, 0); + rb_define_alias(cKernel, "next!", "next"); + rb_define_alias(cKernel, "continue", "next"); + rb_define_private_method(cKernel, "redo", f_redo, 0); + rb_define_alias(cKernel, "redo!", "redo"); + rb_define_private_method(cKernel, "retry", f_retry, 0); + rb_define_alias(cKernel, "retry!", "retry"); + rb_define_private_method(cKernel, "raise", f_raise, -1); + rb_define_alias(cKernel, "fail", "raise"); + rb_define_private_method(cKernel, "caller", f_caller, -1); + rb_define_private_method(cKernel, "exit", f_exit, -1); + + rb_define_private_method(cKernel, "catch", f_catch, 1); + rb_define_private_method(cKernel, "throw", f_throw, -1); + rb_define_method(cKernel, "send", f_send, -1); rb_define_method(cModule, "include", mod_include, -1); rb_define_method(cModule, "public", mod_public, -1); rb_define_method(cModule, "private", mod_private, -1); rb_define_method(cModule, "module_function", mod_modfunc, -1); + rb_define_method(cModule, "method_defined?", mod_method_defined, 1); rb_define_method(CLASS_OF(TopSelf), "include", top_include, -1); rb_define_method(cObject, "extend", obj_extend, -1); rb_define_private_method(cKernel, "trace_var", f_trace_var, -1); - rb_define_private_method(cKernel, "untrace_var", f_untrace_var, 1); + rb_define_private_method(cKernel, "untrace_var", f_untrace_var, -1); } VALUE f_autoload(); @@ -2909,8 +3461,6 @@ scope_dup(scope) } } -static ID blkdata; - static void blk_mark(data) struct BLOCK *data; @@ -2931,6 +3481,29 @@ blk_free(data) } static VALUE +f_binding(self) + VALUE self; +{ + extern VALUE cData; + struct BLOCK *data; + VALUE bind; + + PUSH_BLOCK(0,0); + bind = Make_Data_Struct(cData, struct BLOCK, blk_mark, blk_free, data); + MEMCPY(data, the_block, struct BLOCK, 1); + + data->iter = ITER_NOT; + data->frame.last_func = 0; + data->frame.argv = ALLOC_N(VALUE, data->frame.argc); + MEMCPY(data->frame.argv, the_block->frame.argv, VALUE, data->frame.argc); + + scope_dup(data->scope); + POP_BLOCK(); + + return bind; +} + +static VALUE proc_s_new(class) VALUE class; { @@ -2938,15 +3511,13 @@ proc_s_new(class) struct BLOCK *data; if (!iterator_p() && !f_iterator_p()) { - Fail("tryed to create Procedure-Object out of iterator"); + ArgError("tryed to create Procedure-Object out of iterator"); } - proc = obj_alloc(class); - - if (!blkdata) blkdata = rb_intern("blk"); - Make_Data_Struct(proc, blkdata, struct BLOCK, blk_mark, blk_free, data); - MEMCPY(data, the_block, struct BLOCK, 1); + proc = Make_Data_Struct(class, struct BLOCK, blk_mark, blk_free, data); + *data = *the_block; + data->iter = ITER_NOT; data->frame.argv = ALLOC_N(VALUE, data->frame.argc); MEMCPY(data->frame.argv, the_block->frame.argv, VALUE, data->frame.argc); @@ -2967,7 +3538,8 @@ proc_call(proc, args) { struct BLOCK *data; VALUE result = Qnil; - int state; + NODE *state; + int tag_level; if (TYPE(args) == T_ARRAY) { switch (RARRAY(args)->len) { @@ -2980,11 +3552,12 @@ proc_call(proc, args) } } - Get_Data_Struct(proc, blkdata, struct BLOCK, data); + Get_Data_Struct(proc, struct BLOCK, data); /* PUSH BLOCK from data */ PUSH_BLOCK2(data); PUSH_ITER(ITER_CUR); + the_frame->iter = ITER_CUR; PUSH_TAG(); state = EXEC_TAG(); @@ -2994,34 +3567,1047 @@ proc_call(proc, args) POP_TAG(); POP_ITER(); + tag_level = the_block->level; POP_BLOCK(); - switch (state) { - case 0: - break; - case TAG_BREAK: - case IN_BLOCK|TAG_BREAK: - Fail("break from block-closure"); - break; - case TAG_RETURN: - case IN_BLOCK|TAG_RETURN: - Fail("return from block-closure"); - break; - default: + if (state) { + if (data->scope && (data->scope->flag & SCOPE_NOSTACK)) { + /* orphan procedure */ + switch (state->nd_tag) { + case TAG_BREAK: /* never happen */ + break; + case IN_BLOCK|TAG_BREAK: + if (state->nd_tlev != tag_level) + Raise(eLocalJumpError, "break from proc-closure"); + break; + case TAG_RETRY: + Raise(eLocalJumpError, "retry from proc-closure"); + break; + case TAG_RETURN: /* never happen */ + case IN_BLOCK|TAG_RETURN: + Raise(eLocalJumpError, "return from proc-closure"); + break; + } + } + else { + state->nd_tag &= ~IN_BLOCK; + } JUMP_TAG(state); } - return result; } void Init_Proc() { - cProc = rb_define_class("Proc", cObject); + eLocalJumpError = rb_define_class("LocalJumpError", eException); + cProc = rb_define_class("Proc", cObject); rb_define_singleton_method(cProc, "new", proc_s_new, 0); rb_define_method(cProc, "call", proc_call, -2); - rb_define_private_method(cKernel, "lambda", f_lambda, 0); rb_define_private_method(cKernel, "proc", f_lambda, 0); + rb_define_private_method(cKernel, "lambda", f_lambda, 0); + rb_define_private_method(cKernel, "binding", f_binding, 0); } + +#ifdef THREAD + +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif + +int thread_pending = 0; + +static VALUE cThread; + +#include <sys/types.h> +#include <sys/time.h> +#include <signal.h> +#include <errno.h> + +extern VALUE last_status; + +enum thread_status { + THREAD_RUNNABLE, + THREAD_STOPPED, + THREAD_TO_KILL, + THREAD_KILLED, +}; + +#define WAIT_FD (1<<0) +#define WAIT_TIME (1<<1) +#define WAIT_JOIN (1<<2) + +/* +infty, for this purpose */ +#define DELAY_INFTY 1E30 + +typedef struct thread * thread_t; + +struct thread { + struct thread *next, *prev; + jmp_buf context; + VALUE (*func)(); + void *arg; + + VALUE result; + + int stk_len; + int stk_max; + VALUE*stk_ptr; + VALUE*stk_pos; + + struct FRAME *frame; + struct SCOPE *scope; + struct RClass *class; + struct RVarmap *dyna_vars; + struct BLOCK *block; + struct iter *iter; + struct tag *tag; + + char *file; + int line; + + VALUE errat, errinfo; + VALUE last_status; + VALUE last_line; + VALUE last_match; + + enum thread_status status; + int wait_for; + int fd; + double delay; + thread_t join; + VALUE thread; +}; + +static thread_t curr_thread; +static int num_waiting_on_fd; +static int num_waiting_on_timer; +static int num_waiting_on_join; + +thread_curr() {return (int)curr_thread;} + +#define FOREACH_THREAD(x) x = curr_thread; do { x = x->next; +#define END_FOREACH(x) } while (x != curr_thread) + +/* Return the current time as a floating-point number */ +static double +timeofday() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6; +} + +static thread_t main_thread; + +#define ADJ(addr) (void*)(((VALUE*)(addr)-th->stk_pos)+th->stk_ptr) +#define STACK(addr) (th->stk_pos<(addr) && (addr)<th->stk_pos+th->stk_len) + +static void +thread_mark(th) + thread_t th; +{ + struct FRAME *frame; + struct BLOCK *block; + + gc_mark(th->result); + gc_mark_locations(th->stk_ptr, th->stk_ptr+th->stk_len); +#ifdef THINK_C + gc_mark_locations(th->stk_ptr+2, th->stk_ptr+th->stk_len+2); +#endif + gc_mark(th->thread); + if (th->join) gc_mark(th->join->thread); + + gc_mark(th->scope); + gc_mark(th->dyna_vars); + gc_mark(th->errat); + gc_mark(th->errinfo); + gc_mark(th->last_line); + gc_mark(th->last_match); + + /* mark data in copied stack */ + frame = th->frame; + while (frame && frame != top_frame) { + frame = ADJ(frame); + if (frame->argv && !STACK(frame->argv)) { + gc_mark_frame(frame); + } + frame = frame->prev; + } + block = th->block; + while (block) { + block = ADJ(block); + if (block->frame.argv && !STACK(block->frame.argv)) { + gc_mark_frame(&block->frame); + } + block = block->prev; + } +} + +void +gc_mark_threads() +{ + thread_t th; + + FOREACH_THREAD(th) { + thread_mark(th); + } END_FOREACH(th); +} + +static void +thread_free(th) + thread_t th; +{ + if (th->stk_ptr) free(th->stk_ptr); + th->stk_ptr = 0; +} + +static thread_t +thread_check(data) + struct RData *data; +{ + if (TYPE(data) != T_DATA || data->dfree != thread_free) { + TypeError("wrong argument type %s (expected Thread)", + rb_class2name(CLASS_OF(data))); + } + return (thread_t)data->data; +} + +VALUE lastline_get(); +void lastline_set(); +VALUE backref_get(); +void backref_set(); + +static int +thread_save_context(th) + thread_t th; +{ + VALUE v; + + th->stk_len = stack_length(); + th->stk_pos = (gc_stack_start<(VALUE*)&v)?gc_stack_start + :gc_stack_start - th->stk_len; + if (th->stk_len > th->stk_max) { + th->stk_max = th->stk_len; + REALLOC_N(th->stk_ptr, VALUE, th->stk_max); + } + FLUSH_REGISTER_WINDOWS; + MEMCPY(th->stk_ptr, th->stk_pos, VALUE, th->stk_len); + + th->frame = the_frame; + th->scope = the_scope; + th->class = the_class; + th->dyna_vars = the_dyna_vars; + th->block = the_block; + th->iter = the_iter; + th->tag = prot_tag; + th->errat = errat; + th->errinfo = errinfo; + th->last_status = last_status; + th->last_line = lastline_get(); + th->last_match = backref_get(); + + th->file = sourcefile; + th->line = sourceline; +} + +static void thread_restore_context(); + +static void +stack_extend(th, exit) + thread_t th; + int exit; +{ + VALUE space[1024]; + + memset(space, 0, 1); /* prevent array from optimization */ + thread_restore_context(th, exit); +} + +static void +thread_restore_context(th, exit) + thread_t th; + int exit; +{ + VALUE v; + static thread_t tmp; + static int ex; + + if (!th->stk_ptr) Bug("unsaved context"); + + if (&v < gc_stack_start) { + /* Stack grows downward */ + if (&v > th->stk_pos) stack_extend(th, exit); + } + else { + /* Stack grows upward */ + if (&v < th->stk_pos + th->stk_len) stack_extend(th, exit); + } + + the_frame = th->frame; + the_scope = th->scope; + the_class = th->class; + the_dyna_vars = th->dyna_vars; + the_block = th->block; + the_iter = th->iter; + prot_tag = th->tag; + the_class = th->class; + errat = th->errat; + errinfo = th->errinfo; + last_status = th->last_status; + + lastline_set(th->last_line); + backref_set(th->last_match); + + sourcefile = th->file; + sourceline = th->line; + + tmp = th; + ex = exit; + FLUSH_REGISTER_WINDOWS; + MEMCPY(tmp->stk_pos, tmp->stk_ptr, VALUE, tmp->stk_len); + + switch (ex) { + case 1: + JUMP_TAG2(TAG_FATAL, INT2FIX(0)); + break; + + case 2: + rb_interrupt(); + break; + + default: + longjmp(tmp->context, 1); + } +} + +static void +thread_ready(th) + thread_t th; +{ + /* The thread is no longer waiting on anything */ + if (th->wait_for & WAIT_FD) { + num_waiting_on_fd--; + } + if (th->wait_for & WAIT_TIME) { + num_waiting_on_timer--; + } + if (th->wait_for & WAIT_JOIN) { + num_waiting_on_join--; + } + th->wait_for = 0; + th->status = THREAD_RUNNABLE; +} + +static void +thread_remove() +{ + thread_ready(curr_thread); + curr_thread->status = THREAD_KILLED; + curr_thread->prev->next = curr_thread->next; + curr_thread->next->prev = curr_thread->prev; + thread_schedule(); +} + +static int +thread_dead(th) + thread_t th; +{ + return th->status == THREAD_KILLED; +} + +void +thread_schedule() +{ + thread_t next; + thread_t th; + thread_t curr; + + thread_pending = 0; + if (curr_thread == curr_thread->next) return; + + next = 0; + curr = curr_thread; /* real current thread */ + + if (curr_thread->status == THREAD_KILLED) { + curr_thread = curr_thread->prev; + } + + again: + FOREACH_THREAD(th) { + if (th->status != THREAD_STOPPED && th->status != THREAD_KILLED) { + next = th; + break; + } + } + END_FOREACH(th); + + if (num_waiting_on_join) { + FOREACH_THREAD(th) { + if ((th->wait_for & WAIT_JOIN) && thread_dead(th->join)) { + th->join = 0; + th->wait_for &= ~WAIT_JOIN; + th->status = THREAD_RUNNABLE; + num_waiting_on_join--; + if (!next) next = th; + } + } + END_FOREACH(th); + } + + if (num_waiting_on_fd > 0 || num_waiting_on_timer > 0) { + fd_set readfds; + struct timeval delay_tv, *delay_ptr; + double delay, now; + + int n, max; + + do { + select_err: + max = 0; + FD_ZERO(&readfds); + if (num_waiting_on_fd > 0) { + FOREACH_THREAD(th) { + if (th->wait_for & WAIT_FD) { + FD_SET(th->fd, &readfds); + if (th->fd > max) max = th->fd; + } + } + END_FOREACH(th); + } + + delay = DELAY_INFTY; + if (num_waiting_on_timer > 0) { + now = timeofday(); + FOREACH_THREAD(th) { + if (th->wait_for & WAIT_TIME) { + if (th->delay <= now) { + th->delay = 0.0; + th->wait_for &= ~WAIT_TIME; + th->status = THREAD_RUNNABLE; + num_waiting_on_timer--; + next = th; + } else if (th->delay < delay) { + delay = th->delay; + } + } + } + END_FOREACH(th); + } + /* Do the select if needed */ + if (num_waiting_on_fd > 0 || !next) { + /* Convert delay to a timeval */ + /* If a thread is runnable, just poll */ + if (next) { + delay_tv.tv_sec = 0; + delay_tv.tv_usec = 0; + delay_ptr = &delay_tv; + } + else if (delay == DELAY_INFTY) { + delay_ptr = 0; + } + else { + delay -= now; + delay_tv.tv_sec = (unsigned int)delay; + delay_tv.tv_usec = (delay - (double)delay_tv.tv_sec) * 1e6; + delay_ptr = &delay_tv; + } + n = select(max+1, &readfds, 0, 0, delay_ptr); + if (n > 0) { + /* Some descriptors are ready. + Make the corresponding threads runnable. */ + FOREACH_THREAD(th) + if ((th->wait_for&WAIT_FD) + && FD_ISSET(th->fd, &readfds)) { + /* Wake up only one thread per fd. */ + FD_CLR(th->fd, &readfds); + th->status = THREAD_RUNNABLE; + th->fd = 0; + th->wait_for &= ~WAIT_FD; + num_waiting_on_fd--; + if (!next) next = th; /* Found one. */ + } + END_FOREACH(th); + } + if (n < 0 && !next) goto select_err; + } + /* The delays for some of the threads should have expired. + Go through the loop once more, to check the delays. */ + } while (!next && delay != DELAY_INFTY); + } + + if (!next) { + FOREACH_THREAD(th) { + fprintf(stderr, "%s:%d:deadlock 0x%x: %d:%d %s\n", + th->file, th->line, th->thread, th->status, + th->wait_for, th==main_thread?"(main)":""); + } + END_FOREACH(th); + Fatal("Thread: deadlock"); + } + if (next == curr) { + return; + } + + /* context switch */ + if (curr == curr_thread) { + thread_save_context(curr); + if (setjmp(curr->context)) { + return; + } + } + + curr_thread = next; + if (next->status == THREAD_TO_KILL) { + /* execute ensure-clause if any */ + thread_restore_context(next, 1); + } + thread_restore_context(next, 0); +} + +void +thread_wait_fd(fd) + int fd; +{ + if (curr_thread == curr_thread->next) return; + + curr_thread->status = THREAD_STOPPED; + curr_thread->fd = fd; + num_waiting_on_fd++; + curr_thread->wait_for |= WAIT_FD; + thread_schedule(); +} + +void +thread_fd_writable(fd) + int fd; +{ + struct timeval zero; + fd_set fds; + + zero.tv_sec = zero.tv_usec = 0; + if (curr_thread == curr_thread->next) return; + + for (;;) { + FD_ZERO(&fds); + FD_SET(fd, &fds); + if (select(fd+1, 0, &fds, 0, &zero) == 1) break; + thread_schedule(); + } +} + +void +thread_wait_for(time) + struct timeval time; +{ + double date; + + if (curr_thread == curr_thread->next) { + int n; +#ifndef linux + double d, limit; + limit = timeofday()+(double)time.tv_sec+(double)time.tv_usec*1e-6; +#endif + for (;;) { + TRAP_BEG; + n = select(0, 0, 0, 0, &time); + TRAP_END; + if (n == 0) return; + +#ifndef linux + d = limit - timeofday(); + + time.tv_sec = (int)d; + time.tv_usec = (int)((d - (int)d)*1e6); + if (time.tv_usec < 0) { + time.tv_usec += 1e6; + time.tv_sec -= 1; + } + if (time.tv_sec < 0) return; +#endif + } + } + + date = timeofday() + (double)time.tv_sec + (double)time.tv_usec*1e-6; + curr_thread->status = THREAD_STOPPED; + curr_thread->delay = date; + num_waiting_on_timer++; + curr_thread->wait_for |= WAIT_TIME; + thread_schedule(); +} + +void thread_sleep(); + +int +thread_select(max, read, write, except, timeout) + int max; + fd_set *read, *write, *except; + struct timeval *timeout; +{ + double limit; + struct timeval zero; + fd_set r, *rp, w, *wp, x, *xp; + int n; + + if (!read && !write && !except) { + if (!timeout) { + thread_sleep(); + return; + } + thread_wait_for(*timeout); + return 0; + } + + if (timeout) { + limit = timeofday()+ + (double)timeout->tv_sec+(double)timeout->tv_usec*1e-6; + } + + if (curr_thread == curr_thread->next) { /* no other thread */ +#ifndef linux + struct timeval tv, *tvp = timeout; + + if (timeout) { + tv = *timeout; + tvp = &tv; + } + for (;;) { + TRAP_BEG; + n = select(max, read, write, except, tvp); + TRAP_END; + if (n < 0 && errno == EINTR) { + if (timeout) { + double d = timeofday() - limit; + + tv.tv_sec = (unsigned int)d; + tv.tv_usec = (d - (double)tv.tv_sec) * 1e6; + } + continue; + } + return n; + } +#else + for (;;) { + TRAP_BEG; + n = select(max, read, write, except, timeout); + TRAP_END; + if (n < 0 && errno == EINTR) { + continue; + } + return n; + } +#endif + + } + + for (;;) { + zero.tv_sec = zero.tv_usec = 0; + if (read) {rp = &r; r = *read;} else {rp = 0;} + if (write) {wp = &w; w = *write;} else {wp = 0;} + if (except) {xp = &x; x = *except;} else {xp = 0;} + n = select(max, rp, wp, xp, &zero); + if (n > 0) { + /* write back fds */ + if (read) {*read = r;} + if (write) {*write = w;} + if (except) {*except = x;} + return n; + } + if (n < 0 && errno != EINTR) { + return n; + } + if (timeout) { + if (timeout->tv_sec == 0 && timeout->tv_usec == 0) return 0; + if (limit <= timeofday()) return 0; + } + + thread_schedule(); + CHECK_INTS; + } +} + +static VALUE +thread_join(dmy, data) + VALUE dmy; + struct RData *data; +{ + thread_t th = thread_check(data); + + if (thread_dead(th)) return Qnil; + if ((th->wait_for & WAIT_JOIN) && th->join == curr_thread) + Fatal("Thread.join: deadlock"); + curr_thread->status = THREAD_STOPPED; + curr_thread->join = th; + num_waiting_on_join++; + curr_thread->wait_for |= WAIT_JOIN; + thread_schedule(); + + return Qnil; +} + +static VALUE +thread_current() +{ + return curr_thread->thread; +} + +int +th_cur() +{ + return (int)curr_thread; +} + +static VALUE +thread_run(data) + struct RData *data; +{ + thread_t th = thread_check(data); + + if (th->status == THREAD_KILLED) Fail("killed thread"); + thread_ready(th); + thread_schedule(); + + return (VALUE)data; +} + +static VALUE +thread_kill(data) + struct RData *data; +{ + thread_t th = thread_check(data); + + if (th->status == THREAD_TO_KILL) return Qnil; + if (th->status == THREAD_KILLED) return Qnil; + if (th == th->next || th == main_thread) rb_exit(0); + + thread_ready(th); + th->status = THREAD_TO_KILL; + thread_schedule(); + /* not reached */ +} + +static VALUE +thread_s_kill(obj, th) + VALUE obj, th; +{ + return thread_kill(th); +} + +static VALUE +thread_exit() +{ + return thread_kill(curr_thread->thread); +} + +static VALUE +thread_stop_method(data) + struct RData *data; +{ + thread_t th = thread_check(data); + + th->status = THREAD_STOPPED; + thread_schedule(); + + return Qnil; +} + +static void +thread_stop() +{ + thread_stop_method(curr_thread->thread); +} + +void +thread_sleep() +{ + if (curr_thread == curr_thread->next) { + TRAP_BEG; + sleep((32767<<16)+32767); + TRAP_END; + return; + } + thread_stop_method(curr_thread->thread); +} + +static thread_t +thread_alloc() +{ + thread_t th; + + th = ALLOC(struct thread); + th->status = THREAD_RUNNABLE; + th->func = 0; + th->arg = 0; + + th->status = 0; + th->result = 0; + th->errinfo = Qnil; + th->errat = Qnil; + + th->stk_ptr = 0; + th->stk_len = 0; + th->stk_max = 0; + th->wait_for = 0; + th->fd = 0; + th->delay = 0.0; + th->join = 0; + + th->frame = 0; + th->scope = 0; + th->class = 0; + th->dyna_vars = 0; + th->block = 0; + th->iter = 0; + th->tag = 0; + + th->thread = data_object_alloc(cThread, th, 0, thread_free); + + if (curr_thread) { + th->prev = curr_thread; + curr_thread->next->prev = th; + th->next = curr_thread->next; + curr_thread->next = th; + } + else { + curr_thread = th->prev = th->next = th; + th->status = THREAD_RUNNABLE; + } + + return th; +} + +VALUE +thread_create(fn, arg) + VALUE (*fn)(); + void *arg; +{ + thread_t th = thread_alloc(); + NODE *state; + + thread_save_context(curr_thread); + if (setjmp(curr_thread->context)) { + return th->thread; + } + + th->func = fn; + th->arg = arg; + + PUSH_TAG(); + if ((state = EXEC_TAG()) == 0) { + thread_save_context(th); + if (setjmp(th->context) == 0) { + curr_thread = th; + th->result = (*th->func)(th->arg, th); + } + } + POP_TAG(); + if (state && th->status != THREAD_TO_KILL) { + /* global exit within this thread */ + main_thread->errat = errat; + main_thread->errinfo = errinfo; + thread_cleanup(); + } + thread_remove(); +} + +static void +thread_yield(arg, th) + thread_t th; +{ + scope_dup(the_block->scope); + rb_yield(th->thread); +} + +static VALUE +thread_start() +{ + if (!iterator_p()) { + Raise(eLocalJumpError, "must be called as iterator"); + } + return thread_create(thread_yield, 0); +} + +static VALUE +thread_value(data) + struct RData *data; +{ + thread_t th = thread_check(data); + + thread_join(0, data); + return th->result; +} + +static VALUE +thread_status(data) + struct RData *data; +{ + thread_t th = thread_check(data); + + return thread_dead(th)?FALSE:TRUE; +} + +static VALUE +thread_stopped(data) + struct RData *data; +{ + thread_t th = thread_check(data); + + if (thread_dead(th)) return TRUE; + if (th->status == THREAD_STOPPED) return TRUE; + return FALSE; +} + +static void +thread_wait_other_threads() +{ + /* wait other threads to terminate */ + while (curr_thread != curr_thread->next) { + thread_schedule(); + } +} + +static void +thread_cleanup() +{ + thread_t th; + + FOREACH_THREAD(th) { + if (th != curr_thread && th->status != THREAD_KILLED) { + th->status = THREAD_TO_KILL; + th->wait_for = 0; + } + } + END_FOREACH(th); +} + +int thread_critical; + +static VALUE +thread_exclusive() +{ + NODE *state; + + thread_critical++; + + PUSH_TAG(); + if ((state = EXEC_TAG()) == 0) { + rb_yield(Qnil); + } + POP_TAG(); + thread_critical--; + + if (state) JUMP_TAG(state); + thread_schedule(); + return Qnil; +} + +void +thread_interrupt() +{ + thread_t th = main_thread; + + thread_ready(main_thread); + if (th == curr_thread) { + rb_interrupt(); + } + curr_thread = main_thread; + thread_restore_context(curr_thread, 2); +} + +static thread_t loading_thread; +static int loading_nest; + +static int +thread_loading(feature) + char *feature; +{ + if (curr_thread != curr_thread->next && loading_thread) { + while (loading_thread != curr_thread) { + thread_schedule(); + CHECK_INTS; + } + if (rb_provided(feature)) return TRUE; /* no need to load */ + } + + loading_thread = curr_thread; + loading_nest++; + + return FALSE; +} + +static void +thread_loading_done() +{ + if (--loading_nest == 0) { + loading_thread = 0; + } +} + +#if defined(HAVE_SETITIMER) && !defined(__BOW__) +static void +catch_timer(sig) + int sig; +{ +#if !defined(POSIX_SIGNAL) && !defined(BSD_SIGNAL) + signal(sig, catch_timer); +#endif + if (!thread_critical) { + if (trap_immediate) { + trap_immediate = 0; + thread_schedule(); + } + else thread_pending = 1; + } +} +#else +int thread_tick = THREAD_TICK; +#endif + +void +Init_Thread() +{ + cThread = rb_define_class("Thread", cObject); + + rb_define_singleton_method(cThread, "new", thread_start, 0); + rb_define_singleton_method(cThread, "start", thread_start, 0); + rb_define_singleton_method(cThread, "fork", thread_start, 0); + + rb_define_singleton_method(cThread, "stop", thread_stop, 0); + rb_define_singleton_method(cThread, "kill", thread_s_kill, 1); + rb_define_singleton_method(cThread, "exit", thread_exit, 0); + rb_define_singleton_method(cThread, "pass", thread_schedule, 0); + rb_define_singleton_method(cThread, "join", thread_join, 1); + rb_define_singleton_method(cThread, "current", thread_current, 0); + rb_define_singleton_method(cThread, "exclusive", thread_exclusive, 0); + + rb_define_method(cThread, "run", thread_run, 0); + rb_define_method(cThread, "stop", thread_stop_method, 0); + rb_define_method(cThread, "exit", thread_kill, 0); + rb_define_method(cThread, "value", thread_value, 0); + rb_define_method(cThread, "status", thread_status, 0); + rb_define_method(cThread, "stop?", thread_stopped, 0); + rb_define_method(cThread, "stopped?", thread_stopped, 0); + + /* allocate main thread */ + main_thread = thread_alloc(); + +#if defined(HAVE_SETITIMER) && !defined(__BOW__) + { + struct itimerval tval; + +#ifdef POSIX_SIGNAL + posix_signal(SIGVTALRM, catch_timer); +#else + signal(SIGVTALRM, catch_timer); +#endif + + tval.it_interval.tv_sec = 0; + tval.it_interval.tv_usec = 50000; + tval.it_value = tval.it_interval; + setitimer(ITIMER_VIRTUAL, &tval, NULL); + } +#endif +} +#endif @@ -2,6 +2,8 @@ #dbm #etc +#kconv #marshal +#md5 #socket -tkutil +#tkutil diff --git a/ext/Setup.dj b/ext/Setup.dj new file mode 100644 index 0000000000..eb60525de0 --- /dev/null +++ b/ext/Setup.dj @@ -0,0 +1,8 @@ +option nodynamic + +dbm +#etc +marshal +md5 +#socket +#tkutil diff --git a/ext/dbm/MANIFEST b/ext/dbm/MANIFEST index 141b8dd601..8beec6783d 100644 --- a/ext/dbm/MANIFEST +++ b/ext/dbm/MANIFEST @@ -1,5 +1,4 @@ MANIFEST dbm.c -dbm.doc depend extconf.rb diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c index dbdd99c0ca..5d8a12e3f9 100644 --- a/ext/dbm/dbm.c +++ b/ext/dbm/dbm.c @@ -17,10 +17,14 @@ #include <errno.h> VALUE cDBM; -static ID id_dbm; extern VALUE mEnumerable; +struct dbmdata { + int di_size; + DBM *di_dbm; +}; + static void closeddbm() { @@ -28,24 +32,15 @@ closeddbm() } #define GetDBM(obj, dbmp) {\ - DBM **_dbm;\ - Get_Data_Struct(obj, id_dbm, DBM*, _dbm);\ - dbmp = *_dbm;\ - if (dbmp == Qnil) closeddbm();\ + Get_Data_Struct(obj, struct dbmdata, dbmp);\ + if (dbmp->di_dbm == 0) closeddbm();\ } static void free_dbm(dbmp) - DBM **dbmp; + struct dbmdata *dbmp; { - if (*dbmp) dbm_close(*dbmp); -} - -#define MakeDBM(obj, dp) {\ - DBM **_dbm;\ - if (!id_dbm) id_dbm = rb_intern("dbm");\ - Make_Data_Struct(obj,id_dbm,DBM*,Qnil,free_dbm,_dbm);\ - *_dbm=dp;\ + if (dbmp->di_dbm) dbm_close(dbmp->di_dbm); } static VALUE @@ -55,7 +50,8 @@ fdbm_s_open(argc, argv, class) VALUE class; { VALUE file, vmode; - DBM *dbm, **dbm2; + DBM *dbm; + struct dbmdata *dbmp; int mode; VALUE obj; @@ -70,7 +66,7 @@ fdbm_s_open(argc, argv, class) } Check_Type(file, T_STRING); - dbm = Qnil; + dbm = 0; if (mode >= 0) dbm = dbm_open(RSTRING(file)->ptr, O_RDWR|O_CREAT, mode); if (!dbm) @@ -83,8 +79,9 @@ fdbm_s_open(argc, argv, class) rb_sys_fail(RSTRING(file)->ptr); } - obj = obj_alloc(class); - MakeDBM(obj, dbm); + obj = Make_Data_Struct(class,struct dbmdata,0,free_dbm,dbmp); + dbmp->di_dbm = dbm; + dbmp->di_size = -1; return obj; } @@ -93,12 +90,12 @@ static VALUE fdbm_close(obj) VALUE obj; { - DBM **dbmp; + struct dbmdata *dbmp; - Get_Data_Struct(obj, id_dbm, DBM*, dbmp); - if (*dbmp == Qnil) Fail("already closed DBM file"); - dbm_close(*dbmp); - *dbmp = Qnil; + Get_Data_Struct(obj, struct dbmdata, dbmp); + if (dbmp->di_dbm == 0) closeddbm(); + dbm_close(dbmp->di_dbm); + dbmp->di_dbm = 0; return Qnil; } @@ -108,15 +105,17 @@ fdbm_fetch(obj, keystr) VALUE obj, keystr; { datum key, value; + struct dbmdata *dbmp; DBM *dbm; Check_Type(keystr, T_STRING); key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; value = dbm_fetch(dbm, key); - if (value.dptr == Qnil) { + if (value.dptr == 0) { return Qnil; } return str_new(value.dptr, value.dsize); @@ -128,38 +127,47 @@ fdbm_indexes(obj, args) struct RArray *args; { VALUE *p, *pend; - struct RArray *new; + VALUE new; int i = 0; - if (!args || args->len == 1 && TYPE(args->ptr) != T_ARRAY) { - args = (struct RArray*)rb_to_a(args->ptr[0]); - } - - new = (struct RArray*)ary_new2(args->len); + args = (struct RArray*)rb_to_a(args); + new = ary_new2(args->len); p = args->ptr; pend = p + args->len; while (p < pend) { - new->ptr[i++] = fdbm_fetch(obj, *p++); - new->len = i; + ary_push(new, fdbm_fetch(obj, *p++)); } - return (VALUE)new; + return new; } static VALUE fdbm_delete(obj, keystr) VALUE obj, keystr; { - datum key; + datum key, value; + struct dbmdata *dbmp; DBM *dbm; Check_Type(keystr, T_STRING); key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; + + value = dbm_fetch(dbm, key); + if (value.dptr == 0) { + if (iterator_p()) rb_yield(Qnil); + return Qnil; + } + if (dbm_delete(dbm, key)) { + dbmp->di_size = -1; Fail("dbm_delete failed"); } + else if (dbmp->di_size >= 0) { + dbmp->di_size--; + } return obj; } @@ -168,10 +176,12 @@ fdbm_shift(obj) VALUE obj; { datum key, val; + struct dbmdata *dbmp; DBM *dbm; VALUE keystr, valstr; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; key = dbm_firstkey(dbm); if (!key.dptr) return Qnil; @@ -188,17 +198,19 @@ fdbm_delete_if(obj) VALUE obj; { datum key, val; + struct dbmdata *dbmp; DBM *dbm; VALUE keystr, valstr; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { val = dbm_fetch(dbm, key); keystr = str_new(key.dptr, key.dsize); valstr = str_new(val.dptr, val.dsize); - if (rb_yield(assoc_new(keystr, valstr)) - && dbm_delete(dbm, key)) { - Fail("dbm_delete failed"); + if (RTEST(rb_yield(assoc_new(keystr, valstr)))) { + if (dbm_delete(dbm, key)) { + Fail("dbm_delete failed"); + } } } return obj; @@ -209,9 +221,12 @@ fdbm_clear(obj) VALUE obj; { datum key; + struct dbmdata *dbmp; DBM *dbm; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; + dbmp->di_size = -1; for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { if (dbm_delete(dbm, key)) { Fail("dbm_delete failed"); @@ -225,6 +240,7 @@ fdbm_store(obj, keystr, valstr) VALUE obj, keystr, valstr; { datum key, val; + struct dbmdata *dbmp; DBM *dbm; if (valstr == Qnil) { @@ -232,19 +248,26 @@ fdbm_store(obj, keystr, valstr) return Qnil; } - Check_Type(keystr, T_STRING); + keystr = obj_as_string(keystr); + key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; - Check_Type(valstr, T_STRING); + + if (NIL_P(valstr)) return fdbm_delete(obj, keystr); + + valstr = obj_as_string(valstr); val.dptr = RSTRING(valstr)->ptr; val.dsize = RSTRING(valstr)->len; - GetDBM(obj, dbm); + Get_Data_Struct(obj, struct dbmdata, dbmp); + dbmp->di_size = -1; + dbm = dbmp->di_dbm; if (dbm_store(dbm, key, val, DBM_REPLACE)) { dbm_clearerr(dbm); if (errno == EPERM) rb_sys_fail(Qnil); Fail("dbm_store failed"); } + return valstr; } @@ -253,24 +276,56 @@ fdbm_length(obj) VALUE obj; { datum key; + struct dbmdata *dbmp; DBM *dbm; int i = 0; - GetDBM(obj, dbm); + Get_Data_Struct(obj, struct dbmdata, dbmp); + if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size); + dbm = dbmp->di_dbm; + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { i++; } + dbmp->di_size = i; + return INT2FIX(i); } static VALUE +fdbm_empty(obj) + VALUE obj; +{ + datum key; + struct dbmdata *dbmp; + DBM *dbm; + int i = 0; + + Get_Data_Struct(obj, struct dbmdata, dbmp); + if (dbmp->di_size < 0) { + dbm = dbmp->di_dbm; + + for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { + i++; + } + } + else { + i = dbmp->di_size; + } + if (i == 0) return TRUE; + return FALSE; +} + +static VALUE fdbm_each_value(obj) VALUE obj; { datum key, val; + struct dbmdata *dbmp; DBM *dbm; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { val = dbm_fetch(dbm, key); rb_yield(str_new(val.dptr, val.dsize)); @@ -283,9 +338,11 @@ fdbm_each_key(obj) VALUE obj; { datum key; + struct dbmdata *dbmp; DBM *dbm; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { rb_yield(str_new(key.dptr, key.dsize)); } @@ -298,9 +355,11 @@ fdbm_each_pair(obj) { datum key, val; DBM *dbm; + struct dbmdata *dbmp; VALUE keystr, valstr; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { val = dbm_fetch(dbm, key); @@ -317,11 +376,14 @@ fdbm_keys(obj) VALUE obj; { datum key; + struct dbmdata *dbmp; DBM *dbm; VALUE ary; + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; + ary = ary_new(); - GetDBM(obj, dbm); for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { ary_push(ary, str_new(key.dptr, key.dsize)); } @@ -334,11 +396,14 @@ fdbm_values(obj) VALUE obj; { datum key, val; + struct dbmdata *dbmp; DBM *dbm; VALUE ary; + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; + ary = ary_new(); - GetDBM(obj, dbm); for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { val = dbm_fetch(dbm, key); ary_push(ary, str_new(val.dptr, val.dsize)); @@ -352,13 +417,15 @@ fdbm_has_key(obj, keystr) VALUE obj, keystr; { datum key, val; + struct dbmdata *dbmp; DBM *dbm; Check_Type(keystr, T_STRING); key.dptr = RSTRING(keystr)->ptr; key.dsize = RSTRING(keystr)->len; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; val = dbm_fetch(dbm, key); if (val.dptr) return TRUE; return FALSE; @@ -369,13 +436,15 @@ fdbm_has_value(obj, valstr) VALUE obj, valstr; { datum key, val; + struct dbmdata *dbmp; DBM *dbm; Check_Type(valstr, T_STRING); val.dptr = RSTRING(valstr)->ptr; val.dsize = RSTRING(valstr)->len; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { val = dbm_fetch(dbm, key); if (val.dsize == RSTRING(valstr)->len && @@ -390,10 +459,12 @@ fdbm_to_a(obj) VALUE obj; { datum key, val; + struct dbmdata *dbmp; DBM *dbm; VALUE ary; - GetDBM(obj, dbm); + GetDBM(obj, dbmp); + dbm = dbmp->di_dbm; ary = ary_new(); for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) { @@ -417,6 +488,7 @@ Init_dbm() rb_define_method(cDBM, "indexes", fdbm_indexes, -2); rb_define_method(cDBM, "length", fdbm_length, 0); rb_define_alias(cDBM, "size", "length"); + rb_define_method(cDBM, "empty?", fdbm_empty, 0); rb_define_method(cDBM, "each", fdbm_each_pair, 0); rb_define_method(cDBM, "each_value", fdbm_each_value, 0); rb_define_method(cDBM, "each_key", fdbm_each_key, 0); @@ -427,9 +499,11 @@ Init_dbm() rb_define_method(cDBM, "delete", fdbm_delete, 1); rb_define_method(cDBM, "delete_if", fdbm_delete_if, 0); rb_define_method(cDBM, "clear", fdbm_clear, 0); - rb_define_method(cDBM, "includes", fdbm_has_key, 1); - rb_define_method(cDBM, "has_key", fdbm_has_key, 1); - rb_define_method(cDBM, "has_value", fdbm_has_value, 1); + rb_define_method(cDBM, "include?", fdbm_has_key, 1); + rb_define_method(cDBM, "has_key?", fdbm_has_key, 1); + rb_define_method(cDBM, "has_value?", fdbm_has_value, 1); + rb_define_method(cDBM, "key?", fdbm_has_key, 1); + rb_define_method(cDBM, "value?", fdbm_has_value, 1); rb_define_method(cDBM, "to_a", fdbm_to_a, 0); } diff --git a/ext/dbm/dbm.doc b/ext/dbm/dbm.doc deleted file mode 100644 index 45f174b7aa..0000000000 --- a/ext/dbm/dbm.doc +++ /dev/null @@ -1,107 +0,0 @@ -.\" dbm.doc - -*- Indented-Text -*- created at: Thu Mar 23 20:28:31 JST 1995 - -** DBM(¥¯¥é¥¹) - -NDBM¥Õ¥¡¥¤¥ë¤ò¥¢¥¯¥»¥¹¤¹¤ë¥¯¥é¥¹¡¥¥¡¼¡¤¥Ç¡¼¥¿¤È¤â¤Ëʸ»úÎó¤Ç¤Ê¤±¤ì¤Ð¤Ê -¤é¤Ê¤¤¤È¤¤¤¦À©¸Â¤È¡¤¥Ç¡¼¥¿¤¬¥Õ¥¡¥¤¥ë¤ËÊݸ¤µ¤ì¤ë¤È¤¤¤¦ÅÀ¤ò½ü¤¤¤Æ¤Ï -Dict¥¯¥é¥¹¤ÈÁ´¤¯Æ±Íͤ˰·¤¦¤³¤È¤¬¤Ç¤¤ë¡¥NDBM¤òÈ÷¤¨¤Æ¤¤¤Ê¤¤¥·¥¹¥Æ¥à¤Ç¤Ï -¤³¤Î¥¯¥é¥¹¤ÏÄêµÁ¤µ¤ì¤Ê¤¤¡¥ - -SuperClass: Object - -Included Modules: Enumerable - -Methods: - - self [key] - - key¤ò¥¡¼¤È¤¹¤ëÃͤòÊÖ¤¹¡¥ - - self [key]= value - - key¤ò¥¡¼¤È¤·¤Æ¡¤value¤ò³ÊǼ¤¹¤ë¡¥value¤È¤·¤Ænil¤ò»ØÄꤹ¤ë¤È¡¤ - key¤ËÂФ¹¤ë¹àÌܤκï½ü¤È¤Ê¤ë¡¥ - - clear - - DBM¥Õ¥¡¥¤¥ë¤ÎÃæ¿È¤ò¶õ¤Ë¤¹¤ë¡¥ - - close - - DBM¥Õ¥¡¥¤¥ë¤ò¥¯¥í¡¼¥º¤¹¤ë¡¥°Ê¸å¤ÎÁàºî¤ÏÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥ - - delete(key) - - key¤ò¥¡¼¤È¤¹¤ëÁȤòºï½ü¤¹¤ë¡¥ - - delete_if - - Í×ÁǤòºï½ü¤¹¤ë¥¤¥Æ¥ì¡¼¥¿¡¥key::value¤È¤¤¤¦¥Ú¥¢¤òÍ¿¤¨¤Æ¡¤¥Ö¥í¥Ã - ¥¯¤òɾ²Á¤·¤¿Ãͤ¬¿¿¤Î»þ¡¤³ºÅö¤¹¤ë¹àÌܤòºï½ü¤¹¤ë¡¥ - - each - each_pair - - key::value¤Ê¤ë¥Ú¥¢¤òÍ¿¤¨¤ë¥¤¥Æ¥ì¡¼¥¿¡¥ - - each_key - - Á´¤Æ¤Îkey¤ËÂФ·¤Æ·«¤êÊÖ¤¹¥¤¥Æ¥ì¡¼¥¿¡¥ - - each_value - - Á´¤Æ¤Îvalue¤ËÂФ·¤Æ·«¤êÊÖ¤¹¥¤¥Æ¥ì¡¼¥¿¡¥ - - has_key(key) - includes(key) - - key¤¬¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Ë¸ºß¤¹¤ë»þ¡¤¿¿¤òÊÖ¤¹ - - has_value(value) - - value¤òÃͤȤ¹¤ëÁȤ¬¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Ë¸ºß¤¹¤ë»þ¡¤¿¿¤ò - ÊÖ¤¹ - - indexes(ary) - indexes(key-1, ..., key-n) - - 1ÈÖÌܤηÁ¼°¤Ç¤Ïʸ»úÎó¤ÎÇÛÎó¤ò°ú¿ô¤È¤·¤Æ¼õ¤±¤Æ¡¤¤½¤ÎÍ×ÁǤò¥¡¼ - ¤È¤¹¤ëÍ×ÁǤò´Þ¤àÇÛÎó¤òÊÖ¤¹¡¥2ÈÖÌܤηÁ¼°¤Ç¤Ï³Æ°ú¿ô¤ÎÃͤò¥¡¼¤È - ¤¹¤ëÍ×ÁǤò´Þ¤àÇÛÎó¤òÊÖ¤¹. - - keys - - ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Ë¸ºß¤¹¤ë¥¡¼Á´¤Æ¤ò´Þ¤àÇÛÎó¤òÊÖ¤¹¡¥ - - length - size - - ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤ÎÍ×ÁǤοô¤òÊÖ¤¹¡¥(Ãí°Õ:¸½ºß¤Î¼Â¸½¤Ç¤ÏÍ×ÁÇ¿ô¤ò¿ô - ¤¨¤ë¤¿¤á¤Ë¥Ç¡¼¥¿¥Ù¡¼¥¹¤òÁ´Éô¸¡º÷¤¹¤ë¤Î¤Ç¡¤·ë¹½¥³¥¹¥È¤¬¹â¤¤¡¥µ¤ - ¤ò¤Ä¤±¤Æ»È¤¦¤³¤È.) - - shift - - ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤ÎÍ×ÁǤò°ì¤Ä¼è¤ê½Ð¤·(¥Ç¡¼¥¿¥Ù¡¼¥¹¤«¤éºï½ü¤¹¤ë)¡¤ - key::value¤È¤¤¤¦¥Ú¥¢¤òÊÖ¤¹¡¥ - - to_a - - ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Îkey-value¥Ú¥¢¤òÍ×ÁǤȤ¹¤ëÇÛÎó¤òÊÖ¤¹¡¥ - - values - - ¥Ç¡¼¥¿¥Ù¡¼¥¹Ãæ¤Ë¸ºß¤¹¤ëÃÍÁ´¤Æ¤ò´Þ¤àÇÛÎó¤òÊÖ¤¹¡¥ - -Single Methods: - - open(dbname[, mode]) - - dbname¤Ç»ØÄꤷ¤¿¥Ç¡¼¥¿¥Ù¡¼¥¹¤ò¥â¡¼¥É¤òmode¤ËÀßÄꤷ¤Æ¥ª¡¼¥×¥ó¤¹ - ¤ë¡¥mode¤Î¾ÊάÃͤÏ0666¤Ç¤¢¤ë¡¥mode¤È¤·¤Ænil¤ò»ØÄꤹ¤ë¤È¥Ç¡¼¥¿ - ¥Ù¡¼¥¹¤¬´û¤Ë¸ºß¤·¤Ê¤¤»þ¤Ë¤Ï¿·¤¿¤Ë¥ª¡¼¥×¥ó¤»¤º¡¤nil¤òÊÖ¤¹¡¥ - -------------------------------------------------------- -Local variables: -fill-column: 70 -end: diff --git a/ext/dbm/extconf.rb b/ext/dbm/extconf.rb index 5105cd662f..2302ee2d5d 100644 --- a/ext/dbm/extconf.rb +++ b/ext/dbm/extconf.rb @@ -1,4 +1,4 @@ -have_library("dbm", "dbm_open") +have_library("gdbm", "dbm_open") or have_library("dbm", "dbm_open") if have_func("dbm_open") create_makefile("dbm") end diff --git a/ext/etc/etc.c b/ext/etc/etc.c index e4e4098f8a..524800bd03 100644 --- a/ext/etc/etc.c +++ b/ext/etc/etc.c @@ -24,12 +24,16 @@ static VALUE etc_getlogin(obj) VALUE obj; { + char *getenv(); + char *login; + #ifdef HAVE_GETLOGIN char *getlogin(); - char *login = getlogin(); + + login = getlogin(); + if (!login) login = getenv("USER"); #else - char *getenv(); - char *login = getenv("USER"); + login = getenv("USER"); #endif if (login) @@ -42,7 +46,7 @@ static VALUE setup_passwd(pwd) struct passwd *pwd; { - if (pwd == Qnil) rb_sys_fail("/etc/passwd"); + if (pwd == 0) rb_sys_fail("/etc/passwd"); return struct_new(sPasswd, str_new2(pwd->pw_name), str_new2(pwd->pw_passwd), @@ -69,7 +73,8 @@ setup_passwd(pwd) #ifdef PW_EXPIRE INT2FIX(pwd->pw_expire), #endif - Qnil); + 0 /*dummy*/ + ); } #endif @@ -91,7 +96,7 @@ etc_getpwuid(argc, argv, obj) uid = getuid(); } pwd = getpwuid(uid); - if (pwd == Qnil) Fail("can't find user for %d", uid); + if (pwd == 0) Fail("can't find user for %d", uid); return setup_passwd(pwd); #else return Qnil; @@ -107,7 +112,7 @@ etc_getpwnam(obj, nam) Check_Type(nam, T_STRING); pwd = getpwnam(RSTRING(nam)->ptr); - if (pwd == Qnil) Fail("can't find user for %s", RSTRING(nam)->ptr); + if (pwd == 0) Fail("can't find user for %s", RSTRING(nam)->ptr); return setup_passwd(pwd); #else return Qnil; @@ -130,7 +135,7 @@ etc_passwd(obj) return obj; } pw = getpwent(); - if (pw == Qnil) Fail("can't fetch next -- /etc/passwd"); + if (pw == 0) Fail("can't fetch next -- /etc/passwd"); return setup_passwd(pw); #else return Qnil; @@ -155,8 +160,7 @@ setup_group(grp) str_new2(grp->gr_name), str_new2(grp->gr_passwd), INT2FIX(grp->gr_gid), - mem, - Qnil); + mem); } #endif @@ -170,7 +174,7 @@ etc_getgrgid(obj, id) gid = NUM2INT(id); grp = getgrgid(gid); - if (grp == Qnil) Fail("can't find group for %d", gid); + if (grp == 0) Fail("can't find group for %d", gid); return setup_group(grp); #else return Qnil; @@ -186,7 +190,7 @@ etc_getgrnam(obj, nam) Check_Type(nam, T_STRING); grp = getgrnam(RSTRING(nam)->ptr); - if (grp == Qnil) Fail("can't find group for %s", RSTRING(nam)->ptr); + if (grp == 0) Fail("can't find group for %s", RSTRING(nam)->ptr); return setup_group(grp); #else return Qnil; @@ -214,7 +218,7 @@ etc_group(obj) #endif } -VALUE mEtc; +static VALUE mEtc; void Init_etc() @@ -252,9 +256,11 @@ Init_etc() #ifdef PW_EXPIRE "expire", #endif - Qnil); + 0); + rb_global_variable(&sPasswd); #ifdef HAVE_GETGRENT - sGroup = struct_define("Group", "name", "passwd", "gid", "mem", Qnil); + sGroup = struct_define("Group", "name", "passwd", "gid", "mem", 0); + rb_global_variable(&sGroup); #endif } diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in index b61ccd222f..bd4eed306b 100644 --- a/ext/extmk.rb.in +++ b/ext/extmk.rb.in @@ -1,21 +1,24 @@ #! /usr/local/bin/ruby -if $ARGV[0] == 'install' +if ARGV[0] == 'static' + $force_static = TRUE + ARGV.shift +elsif ARGV[0] == 'install' $install = TRUE - $ARGV.shift -end - -if $ARGV[0] == 'clean' + ARGV.shift +elsif ARGV[0] == 'clean' $clean = TRUE - $ARGV.shift + ARGV.shift end +$extlist = [] + $cache_mod = FALSE; $lib_cache = {} $func_cache = {} $hdr_cache = {} -if File.exists?("config.cache") then +if File.exist?("config.cache") then f = open("config.cache", "r") while f.gets case $_ @@ -31,10 +34,10 @@ if File.exists?("config.cache") then end def older(file1, file2) - if !File.exists?(file1) then + if !File.exist?(file1) then return TRUE end - if !File.exists?(file2) then + if !File.exist?(file2) then return FALSE end if File.mtime(file1) < File.mtime(file2) @@ -61,7 +64,7 @@ def have_library(lib, func) end cfile = open("conftest.c", "w") - printf cfile, "\ + cfile.printf "\ int main() { return 0; } int t() { %s(); return 0; } ", func @@ -99,7 +102,7 @@ def have_func(func) end cfile = open("conftest.c", "w") - printf cfile, "\ + cfile.printf "\ char %s(); int main() { return 0; } int t() { %s(); return 0; } @@ -136,7 +139,7 @@ def have_header(header) end cfile = open("conftest.c", "w") - printf cfile, "\ + cfile.printf "\ #include <%s> ", header cfile.close @@ -162,7 +165,7 @@ def create_header() hfile = open("extconf.h", "w") for line in $defs line =~ /^-D(.*)/ - printf hfile, "#define %s 1\n", $1 + hfile.printf "#define %s 1\n", $1 end hfile.close end @@ -180,7 +183,7 @@ def create_makefile(target) $libs = "" if not $libs mfile = open("Makefile", "w") - printf mfile, "\ + mfile.printf "\ SHELL = /bin/sh #### Start of system configuration section. #### @@ -191,36 +194,37 @@ VPATH = @srcdir@ CC = @CC@ CFLAGS = %s #$CFLAGS %s +LDFLAGS = @LDFLAGS@ +DLDFLAGS = @DLDFLAGS@ LDSHARED = @LDSHARED@ ", if $static then "" else "@CCDLFLAGS@" end, $defs.join(" ") - printf mfile, "\ + mfile.printf "\ prefix = @prefix@ -binprefix = exec_prefix = @exec_prefix@ bindir = $(exec_prefix)/bin -libdir = @prefix@/lib/ruby +libdir = @archlib@ @SET_MAKE@ #### End of system configuration section. #### " - printf mfile, "LIBS = %s\n", $libs - printf mfile, "OBJS = " + mfile.printf "LIBS = %s\n", $libs + mfile.printf "OBJS = " if !$objs then $objs = Dir["*.c"] for f in $objs f.sub!(/\.c$/, ".o") end end - printf mfile, $objs.join(" ") - printf mfile, "\n" + mfile.printf $objs.join(" ") + mfile.printf "\n" - printf mfile, "\ + dots = if "@INSTALL@" =~ /^\// then "" else "../" end + mfile.printf "\ TARGET = %s.%s -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ +INSTALL = %s@INSTALL@ all: $(TARGET) @@ -229,56 +233,53 @@ clean:; @rm -f *.o *.so *.sl @rm -f core ruby *~ realclean: clean -", target, if $static then "o" else "@DLEXT@" end +", target, + if $static then "o" else "@DLEXT@" end, dots if !$static - printf mfile, "\ + mfile.printf "\ install: $(libdir)/$(TARGET) $(libdir)/$(TARGET): $(TARGET) @test -d $(libdir) || mkdir $(libdir) - $(INSTALL_DATA) $(TARGET) $(libdir)/$(TARGET) + $(INSTALL) $(TARGET) $(libdir)/$(TARGET) " else - printf mfile, "\ + mfile.printf "\ install:; " end if !$static && "@DLEXT@" != "o" - printf mfile, "\ + mfile.printf "\ $(TARGET): $(OBJS) - $(LDSHARED) -o $(TARGET) $(OBJS) $(LIBS) + $(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LIBS) " - elsif !File.exists?(target + ".c") - printf mfile, "\ + elsif !File.exist?(target + ".c") + mfile.printf "\ $(TARGET): $(OBJS) - ld $(LDDLFLAGS) -r $(TARGET) $(OBJS) + ld $(LDFLAGS) -r -o $(TARGET) $(OBJS) " end - if File.exists?("depend") + if File.exist?("depend") dfile = open("depend", "r") - printf mfile, "###\n" + mfile.printf "###\n" while line = dfile.gets() - printf mfile, "%s", line + mfile.printf "%s", line end dfile.close end mfile.close if $static - $extinit += format("\ -\tInit_%s();\n\ -\trb_provide(\"%s.o\");\n\ -", target, target) - $extobjs += format("ext/%s/%s.o ", $static, target) + $extlist.push [$static,target] end end def extmake(target) - if $static_ext[target] + if $force_static or $static_ext[target] $static = target else $static = FALSE @@ -294,19 +295,19 @@ def extmake(target) begin Dir.chdir target if $static_ext.size > 0 || - !File.exists?("./Makefile") || + !File.exist?("./Makefile") || older("./Makefile", "../Setup") || older("./Makefile", "../extmk.rb") || older("./Makefile", "./extconf.rb") then $defs = [] - if File.exists?("extconf.rb") + if File.exist?("extconf.rb") load "extconf.rb" else create_makefile(target); end end - if File.exists?("./Makefile") + if File.exist?("./Makefile") if $install system "make install" elsif $clean @@ -328,10 +329,10 @@ if File.file? "./Setup" while f.gets() $_.chop! sub!(/#.*$/, '') - continue if /^\s*$/ + next if /^\s*$/ if /^option +nodynamic/ $nodynamic = TRUE - continue + next end $static_ext[$_.split[0]] = TRUE end @@ -339,36 +340,56 @@ if File.file? "./Setup" end for d in Dir["*"] - File.directory?(d) || continue - File.file?(d + "/MANIFEST") || continue + File.directory?(d) || next + File.file?(d + "/MANIFEST") || next d = $1 if d =~ /\/([\/]*)$/ - print "compiling ", d, "\n" - + if $install + print "installing ", d, "\n" + elsif $clean + print "cleaning ", d, "\n" + else + print "compiling ", d, "\n" + end extmake(d) end if $cache_mod f = open("config.cache", "w") for k,v in $lib_cache - printf f, "lib: %s %s\n", k, v + f.printf "lib: %s %s\n", k, v end for k,v in $func_cache - printf f, "func: %s %s\n", k, v + f.printf "func: %s %s\n", k, v end for k,v in $hdr_cache - printf f, "hdr: %s %s\n", k, v + f.printf "hdr: %s %s\n", k, v end f.close end -exit if $install -if $extobjs +exit if $install or $clean +if $extlist.size > 0 + for s,t in $extlist + f = format("%s/%s.o", s, t) + if File.exist?(f) + $extinit += format("\ +\tInit_%s();\n\ +\trb_provide(\"%s.o\");\n\ +", t, t) + $extobjs += "ext/" + $extobjs += f + $extobjs += " " + else + FALSE + end + end + if older("extinit.c", "Setup") f = open("extinit.c", "w") - printf f, "void Init_ext() {\n" - printf f, $extinit - printf f, "}\n" + f.printf "void Init_ext() {\n" + f.printf $extinit + f.printf "}\n" f.close end if older("extinit.o", "extinit.c") @@ -378,16 +399,19 @@ if $extobjs end Dir.chdir ".." - $extobjs = "ext/extinit.o " + $extobjs if older("ruby", "ext/Setup") or older("ruby", "miniruby") `rm -f ruby` end + + $extobjs = "ext/extinit.o " + $extobjs system format('make ruby PROGRAM=ruby EXTOBJS="%s" EXTLIBS="%s"', $extobjs, $extlibs) else Dir.chdir ".." - `rm -f ruby` - `cp miniruby ruby` + if older("ruby", "miniruby") + `rm -f ruby` + `cp miniruby ruby` + end end #Local variables: diff --git a/ext/kconv/MANIFEST b/ext/kconv/MANIFEST new file mode 100644 index 0000000000..8f37a9e166 --- /dev/null +++ b/ext/kconv/MANIFEST @@ -0,0 +1,2 @@ +MANIFEST +kconv.c diff --git a/ext/kconv/kconv.c b/ext/kconv/kconv.c new file mode 100644 index 0000000000..fd6c3bed0a --- /dev/null +++ b/ext/kconv/kconv.c @@ -0,0 +1,1934 @@ +/** Network Kanji Filter. (PDS Version) +************************************************************************ +** Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA) +** Ï¢ÍíÀè¡§ ¡Ê³ô¡ËÉÙ»ÎÄ̸¦µæ½ê¡¡¥½¥Õ¥È£³¸¦¡¡»ÔÀî¡¡»ê +** ¡ÊE-Mail Address: ichikawa@flab.fujitsu.co.jp¡Ë +** Copyright (C) 1996 +** Ï¢ÍíÀè¡§ ΰµåÂç³Ø¾ðÊó¹©³Ø²Ê ²ÏÌî ¿¿¼£ mine/X0208 support +** ¡ÊE-Mail Address: kono@ie.u-ryukyu.ac.jp¡Ë +** Ï¢ÍíÀè¡§ COW for DOS & Win16 & Win32 & OS/2 +** ¡ÊE-Mail Address: GHG00637@niftyserve.or.jp¡Ë +** ±ÄÍø¤òÌÜŪ¤È¤·¤Ê¤¤¸Â¤ê¡¢¤³¤Î¥½¡¼¥¹¤Î¤¤¤«¤Ê¤ë +** Ê£¼Ì¡¤²þÊÑ¡¤½¤Àµ¤âµöÂú¤·¤Þ¤¹¡£¤½¤ÎºÝ¤Ë¤Ï¡¢¤³¤ÎÉôʬ¤ò»Ä¤¹¤³¤È¡£ +** ¤³¤Î¥×¥í¥°¥é¥à¤Ë¤Ä¤¤¤Æ¤ÏÆÃ¤Ë²¿¤ÎÊݾڤ⤷¤Ê¤¤¡¢°¤·¤«¤é¤º¡£ +** Everyone is permitted to do anything on this program +** including copying, modifying, improving +** as long as you don't try to make money off it, +** or pretend that you wrote it. +** i.e., the above copyright notice has to appear in all copies. +** THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE. +***********************************************************************/ + +/*********************************************************************** +** 1996/03/10 modified for Kconv - by Ikuo Nakagawa +***********************************************************************/ +/*********************************************************************** +** 1996/12/18 modified for kconv(ruby) - by matz@ruby.club.or.jp +***********************************************************************/ + +static char *CopyRight = + "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),1996 S. Kono, COW"; +static char *Version = + "1.62"; +static char *Patchlevel = + "5/9612/Shinji Kono, COW matz"; + +/* +** +** +** +** USAGE: nkf [flags] [file] +** +** Flags: +** b Output is bufferred (DEFAULT) +** u Output is unbufferred +** +** t no operation +** +** j Outout code is JIS 7 bit (DEFAULT SELECT) +** s Output code is MS Kanji (DEFAULT SELECT) +** e Output code is AT&T JIS (DEFAULT SELECT) +** l Output code is JIS 7bit and ISO8859-1 Latin-1 +** +** m MIME conversion for ISO-2022-JP +** i_ Output sequence to designate JIS-kanji (DEFAULT_J) +** o_ Output sequence to designate single-byte roman characters (DEFAULT_R) +** +** r {de/en}crypt ROT13/47 +** +** v display Version +** +** T Text mode output (for MS-DOS) +** +** x Do not convert X0201 kana into X0208 +** Z Convert X0208 alphabet to ASCII +** +** f60 fold option +** +** m MIME decode +** B try to fix broken JIS, missing Escape +** B[1-9] broken level +** +** O Output to 'nkf.out' file +** d Delete \r in line feed +** c Add \r in line feed +**/ +/******************************/ +/* ¥Ç¥Õ¥©¥ë¥È¤Î½ÐÎÏ¥³¡¼¥ÉÁªÂò */ +/* Select DEFAULT_CODE */ +#define DEFAULT_CODE_JIS +/* #define DEFAULT_CODE_SJIS */ +/* #define DEFAULT_CODE_EUC */ +/******************************/ +/* ¥×¥í¥È¥¿¥¤¥×¤ÎÁªÂò */ +#define ANSI_C_PROTOTYPE +/******************************/ + +/* for Kconv: _AUTO, _EUC, _SJIS, _JIS */ +#define _AUTO 0 +#define _JIS 1 +#define _EUC 2 +#define _SJIS 3 + +#ifdef __STDC__ +#define ANSI_C_PROTOTYPE +#endif + +#if (defined(__TURBOC__) || defined(LSI_C)) && !defined(MSDOS) +#define MSDOS +#endif + +#include <stdio.h> + +#if defined(MSDOS) || defined(__OS2__) +#include <stdlib.h> +#include <fcntl.h> +#include <io.h> +#endif + +#ifdef MSDOS +#ifdef LSI_C +#define setbinmode(fp) fsetbin(fp) +#else /* Microsoft C, Turbo C */ +#define setbinmode(fp) setmode(fileno(fp), O_BINARY) +#endif +#else /* UNIX,OS/2 */ +#define setbinmode(fp) +#endif + +#ifdef _IOFBF /* SysV and MSDOS */ +#define setvbuffer(fp, buf, size) setvbuf(fp, buf, _IOFBF, size) +#else /* BSD */ +#define setvbuffer(fp, buf, size) setbuffer(fp, buf, size) +#endif + +/*Borland C++ 4.5 EasyWin*/ +#if defined(__TURBOC__) && defined(_Windows) && !defined(__WIN32__) /*Easy Win */ +#define EASYWIN +#include <windows.h> +#endif + +#define FALSE 0 +#define TRUE 1 + +/* state of output_mode and input_mode */ + +#define ASCII 0 +#define X0208 1 +#define X0201 2 +#define NO_X0201 3 +#define JIS_INPUT 4 +#define SJIS_INPUT 5 +#define LATIN1_INPUT 6 +#define FIXED_MIME 7 +#define DOUBLE_SPACE -2 + +#define NL 0x0a +#define ESC 0x1b +#define SP 0x20 +#define AT 0x40 +#define SSP 0xa0 +#define DEL 0x7f +#define SI 0x0f +#define SO 0x0e +#define SSO 0x8e + +#define HOLD_SIZE 32 +#define IOBUF_SIZE 16384 + +#define DEFAULT_J 'B' +#define DEFAULT_R 'B' + +#define SJ0162 0x00e1 /* 01 - 62 ku offset */ +#define SJ6394 0x0161 /* 63 - 94 ku offset */ + + +/* MIME preprocessor */ + +#define _GETC() (*inptr ? (int)(*inptr++) : EOF) +#define _UNGETC(c) (*--inptr = (c)) +#define PUTCHAR(c) (outlen + 1 < outsiz ? \ + ((outptr[outlen++] = (c)), (outptr[outlen] = '\0')) : EOF) +#define GETC() ((!mime_mode)?_GETC():mime_getc()) +#define UNGETC(c) ((!mime_mode)?_UNGETC(c):mime_ungetc(c)) + +#ifdef EASYWIN /*Easy Win */ +extern POINT _BufferSize; +#endif + +/* buffers */ + +static unsigned char hold_buf[HOLD_SIZE*2]; +static int hold_count; +static unsigned char *inptr; +static char *outptr; +static int outsiz; +static int outlen; + +/* MIME preprocessor fifo */ + +#define MIME_BUF_SIZE (1024) /* 2^n ring buffer */ +#define MIME_BUF_MASK (MIME_BUF_SIZE-1) +#define Fifo(n) mime_buf[(n)&MIME_BUF_MASK] +static unsigned char mime_buf[MIME_BUF_SIZE]; +static unsigned int mime_top = 0; +static unsigned int mime_last = 0; /* decoded */ +static unsigned int mime_input = 0; /* undecoded */ + +/* flags */ +static int unbuf_f = FALSE; +static int estab_f = FALSE; +#ifdef notdef +static int nop_f = FALSE; +static int binmode_f = TRUE; /* binary mode */ +#endif +static int rot_f = FALSE; /* rot14/43 mode */ +static int input_f = FALSE; /* non fixed input code */ +static int alpha_f = FALSE; /* convert JIx0208 alphbet to ASCII */ +static int mime_f = FALSE; /* convert MIME B base64 or Q */ +static int mimebuf_f = FALSE; /* MIME buffered input */ +static int broken_f = FALSE; /* convert ESC-less broken JIS */ +static int iso8859_f = FALSE; /* ISO8859 through */ +#if defined(MSDOS) || defined(__OS2__) +static int x0201_f = TRUE; /* Assume JISX0201 kana */ +#else +static int x0201_f = NO_X0201; /* Assume NO JISX0201 */ +#endif + +/* X0208 -> ASCII converter */ + +static int c1_return; + +/* fold parameter */ +static int line = 0; /* chars in line */ +static int prev = 0; +static int fold_f = FALSE; +static int fold_len = 0; + +/* options */ +static char kanji_intro = DEFAULT_J, + ascii_intro = DEFAULT_R; + +/* Folding */ + +static int fold(); +#define FOLD_MARGIN 10 +#define DEFAULT_FOLD 60 + +/* Global states */ +static int output_mode = ASCII, /* output kanji mode */ + input_mode = ASCII, /* input kanji mode */ + shift_mode = FALSE; /* TRUE shift out, or X0201 */ +static int mime_mode = FALSE; /* MIME mode B base64, Q hex */ + +/* X0208 -> ASCII translation table */ + +static unsigned char cv[],dv[],ev[],fv[]; + +#ifdef notdef +static int file_out = FALSE; +static int end_check; +#endif +static int add_cr = FALSE; +static int del_cr = FALSE; + +/* function prototype */ +#ifdef ANSI_C_PROTOTYPE +static void (*iconv) (register int c2,register int c1); /* s_iconv or oconv */ +static void (*oconv) (register int c2,register int c1); /* [ejs]_oconv */ +static int do_kconv(char *i, char *o, int siz, int out_code, int in_code); +static void h_conv(register int c2,register int c1); +static int push_hold_buf(int c2,int c1); +static void s_iconv(register int c2,register int c1); +static void e_oconv(register int c2,register int c1); +static void s_oconv(register int c2,register int c1); +static void j_oconv(register int c2,register int c1); +static int fold(register int c2,register int c1); +static int pre_convert(register int c1,register int c2); +static int mime_begin(); +static int mime_getc(); +static int mime_ungetc(unsigned int c); +static int mime_integrity(unsigned char *p); +static int base64decode(int c); +#else +static void (*iconv) (); /* s_iconv or oconv */ +static void (*oconv) (); /* [ejs]_oconv */ +static int s_iconv (); +static int e_oconv (); +static int j_oconv (); +static int s_oconv (); +static int noconvert (); +static int do_kconv(); +static void h_conv (); +static int push_hold_buf (); +#endif + +#ifdef notdef +main (argc, argv) + int argc; + char **argv; +{ + register FILE *fin; + register char *cp; + +#ifdef EASYWIN /*Easy Win */ + _BufferSize.y = 400;/*Set Scroll Buffer Size*/ +#endif +#ifdef DEFAULT_CODE_JIS + oconv = j_oconv; /* DEFAULT Code is JIS */ +#endif +#ifdef DEFAULT_CODE_SJIS + oconv = s_oconv; /* DEFAULT Code is S-JIS */ +#endif +#ifdef DEFAULT_CODE_EUC + oconv = e_oconv; /* DEFAULT Code is EUC */ +#endif + + for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) { + cp = *argv; + while (*cp) { + switch (*cp++) { + case 'b': /* buffered mode */ + unbuf_f = FALSE; + continue; + case 'u': /* non bufferd mode */ + unbuf_f = TRUE; + continue; + case 't': /* transparent mode */ + nop_f = TRUE; + continue; + case 'j': /* JIS output */ + case 'n': + oconv = j_oconv; + continue; + case 'e': /* AT&T EUC output */ + oconv = e_oconv; + continue; + case 's': /* SJIS output */ + oconv = s_oconv; + continue; + case 'l': /* ISO8859 Latin-1 support, no conversion */ + iso8859_f = TRUE; /* Only compatible with ISO-2022-JP */ + input_f = LATIN1_INPUT; + continue; + case 'i': /* Kanji IN ESC-$-@/B */ + if(*cp=='@'||*cp=='B') + kanji_intro = *cp++; + continue; + case 'o': /* ASCII IN ESC-(-J/B */ + if(*cp=='J'||*cp=='B'||*cp=='H') + ascii_intro = *cp++; + continue; + case 'r': + rot_f = TRUE; + continue; +#if defined(MSDOS) || defined(__OS2__) + case 'T': + binmode_f = FALSE; + continue; +#endif + case 'v': + usage(); + exit(1); + break; + /* Input code assumption */ + case 'J': /* JIS input */ + case 'E': /* AT&T EUC input */ + input_f = JIS_INPUT; + continue; + case 'S': /* MS Kanji input */ + input_f = SJIS_INPUT; + if(x0201_f==NO_X0201) x0201_f=TRUE; + continue; + case 'Z': /* Convert X0208 alphabet to asii */ + /* bit:0 Convert X0208 + bit:1 Convert Kankaku to one space + bit:2 Convert Kankaku to two spaces + */ + if('9'>= *cp && *cp>='0') + alpha_f |= 1<<(*cp++ -'0'); + else + alpha_f |= TRUE; + continue; + case 'x': /* Convert X0201 kana to X0208 or X0201 Conversion */ + x0201_f = FALSE; /* No X0201->X0208 conversion */ + /* accept X0201 + ESC-(-I in JIS, EUC, MS Kanji + SI/SO in JIS, EUC, MS Kanji + SSO in EUC, JIS, not in MS Kanji + MS Kanji (0xa0-0xdf) + output X0201 + ESC-(-I in JIS (0x20-0x5f) + SSO in EUC (0xa0-0xdf) + 0xa0-0xd in MS Kanji (0xa0-0xdf) + */ + continue; + case 'X': /* Assume X0201 kana */ + /* Default value is NO_X0201 for EUC/MS-Kanji mix */ + x0201_f = TRUE; + continue; + case 'f': /* folding -f60 or -f */ + fold_f = TRUE; + fold_len = atoi(cp); + if(!(0<fold_len && fold_len<BUFSIZ)) + fold_len = DEFAULT_FOLD; + while('0'<= *cp && *cp <='9') cp++; + continue; + case 'm': /* MIME support */ + mime_f = TRUE; + if(*cp=='B'||*cp=='Q') { + mime_mode = *cp++; + mimebuf_f = FIXED_MIME; + } + continue; + case 'B': /* Broken JIS support */ + /* bit:0 no ESC JIS + bit:1 allow any x on ESC-(-x or ESC-$-x + bit:2 reset to ascii on NL + */ + if('9'>= *cp && *cp>='0') + broken_f |= 1<<(*cp++ -'0'); + else + broken_f |= TRUE; + continue; + case 'O':/* for Output file */ + file_out = TRUE; + continue; + case 'c':/* add cr code */ + add_cr = TRUE; + continue; + case 'd':/* delete cr code */ + del_cr = TRUE; + continue; + default: + /* bogus option but ignored */ + continue; + } + } + } + + if(iso8859_f && (oconv != j_oconv || !x0201_f )) { + fprintf(stderr,"Mixed ISO8859/JISX0201/SJIS/EUC output is not allowed.\n"); + exit(1); + } + + if(binmode_f == TRUE) +#ifdef __OS2__ + if(freopen("","wb",stdout) == NULL) + return (-1); +#else + setbinmode(stdout); +#endif + + if(unbuf_f) + setbuf (stdout, (char *) NULL); + else + setvbuffer (stdout, stdobuf, IOBUF_SIZE); + + if(argc == 0) { + if(binmode_f == TRUE) +#ifdef __OS2__ + if(freopen("","rb",stdin) == NULL) return (-1); +#else + setbinmode(stdin); +#endif + setvbuffer (stdin, stdibuf, IOBUF_SIZE); + if(nop_f) + noconvert (stdin); + else + convert (stdin); + } else { + while (argc--) { + if((fin = fopen (*argv++, "r")) == NULL) { + perror (*--argv); + return (-1); + } else { +/* reopen file for stdout */ + if(file_out == TRUE){ + if(argc == 1 ) { + if(freopen(*argv++, "w", stdout) == NULL) { + perror (*--argv); + return (-1); + } + argc--; + } else { + if(freopen("nkf.out", "w", stdout) == NULL) { + perror (*--argv); + return (-1); + } + } + if(binmode_f == TRUE) { +#ifdef __OS2__ + if(freopen("","wb",stdout) == NULL) + return (-1); +#else + setbinmode(stdout); +#endif + } + } + if(binmode_f == TRUE) +#ifdef __OS2__ + if(freopen("","rb",fin) == NULL) + return (-1); +#else + setbinmode(fin); +#endif + setvbuffer (fin, stdibuf, IOBUF_SIZE); + if(nop_f) + noconvert (fin); + else + convert (fin); + fclose (fin); + } + } + } +#ifdef EASYWIN /*Easy Win */ + if(file_out == FALSE) + scanf("%d",&end_check); + else + fclose(stdout); +#else /* for Other OS */ + if(file_out == TRUE) + fclose(stdout); +#endif + return (0); +} + +int +noconvert (f) + register FILE *f; +{ + register int c; + + while ((c = getc (f)) != EOF) + putchar (c); + return 1; +} + +#endif /* notdef */ + +static int +do_kconv(i, o, siz, out_code, in_code) + char *i; + char *o; + int siz, out_code, in_code; +{ + register int c1, + c2; + + c2 = 0; + + if (siz <= 0) { + return 0; + } + *o = '\0'; + + inptr = (unsigned char *)i; /* input buffer */ + outptr = o; /* output buffer */ + outsiz = siz; /* output buffer size */ + outlen = 0; /* current length of output string */ + x0201_f = FALSE; /* don't assume JISX0201 kana */ + rot_f = FALSE; /* rot14/43 mode */ + input_f = FALSE; /* non fixed input code */ + alpha_f = FALSE; /* convert JISX0208 alphbet to ASCII */ + mime_f = TRUE; /* convert MIME base64 */ + broken_f = FALSE; /* convert ESC-less broken JIS */ + + switch (out_code) { + case _SJIS: + oconv = s_oconv; + break; + case _EUC: + oconv = e_oconv; + break; + default: + oconv = j_oconv; + break; + } + + switch (in_code) { + case _SJIS: + input_f = SJIS_INPUT; + x0201_f = TRUE; + break; + case _EUC: + case _JIS: + input_f = JIS_INPUT; + break; + default: + input_f = FALSE; + break; + } + + if(input_f == JIS_INPUT || input_f == LATIN1_INPUT) { + estab_f = TRUE; iconv = oconv; + } else if(input_f == SJIS_INPUT) { + estab_f = TRUE; iconv = s_iconv; + } else { + estab_f = FALSE; iconv = oconv; + } + input_mode = ASCII; + output_mode = ASCII; + shift_mode = FALSE; + mime_mode = FALSE; + +#define NEXT continue /* no output, get next */ +#define SEND ; /* output c1 and c2, get next */ +#define LAST break /* end of loop, go closing */ + + while ((c1 = GETC()) != EOF) { + if(!c2 && !input_mode && c1<DEL && !mime_mode && !output_mode + && !shift_mode && !fold_f && !rot_f) { + /* plain ASCII tight loop, no conversion and no fold */ + while(c1!='=' && c1!=SO && c1!=EOF && + c1!=ESC && c1!='$' && c1<DEL && c1!='\r' && c1!='\n') { + PUTCHAR(c1); + c1 = _GETC(); + } + if(c1==EOF) LAST; + } + if(c2) { + /* second byte */ + if(c2 > DEL) { + /* in case of 8th bit is on */ + if(!estab_f) { + /* in case of not established yet */ + if(c1 > SSP) { + /* It is still ambiguious */ + h_conv (c2, c1); + c2 = 0; + NEXT; + } else if(c1 < AT) { + /* ignore bogus code */ + c2 = 0; + NEXT; + } else { + /* established */ + /* it seems to be MS Kanji */ + estab_f = TRUE; + iconv = s_iconv; + SEND; + } + } else + /* in case of already established */ + if(c1 < AT) { + /* ignore bogus code */ + c2 = 0; + NEXT; + } else + SEND; + } else + /* 7 bit code */ + /* it might be kanji shitfted */ + if((c1 == DEL) || (c1 <= SP)) { + /* ignore bogus first code */ + c2 = 0; + NEXT; + } else + SEND; + } else { + /* first byte */ + if(c1 > DEL) { + /* 8 bit code */ + if(!estab_f && !iso8859_f) { + /* not established yet */ + if(c1 < SSP) { + /* it seems to be MS Kanji */ + estab_f = TRUE; + iconv = s_iconv; + } else if(c1 < 0xe0) { + /* it seems to be EUC */ + estab_f = TRUE; + iconv = oconv; + } else { + /* still ambiguious */ + } + c2 = c1; + NEXT; + } else { /* estab_f==TRUE */ + if(iso8859_f) { + SEND; + } else if(SSP<=c1 && c1<0xe0 && iconv == s_iconv) { + /* SJIS X0201 Case... */ + /* This is too arrogant, but ... */ + if(x0201_f==NO_X0201) { + iconv = oconv; + c2 = c1; + NEXT; + } else + if(x0201_f) { + if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) { + /* look ahead for X0201/X0208conversion */ + if((c2 = GETC()) == EOF) { + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + LAST; + } else if(c2==(0xde)) { /* ÂùÅÀ */ + (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]); + c2=0; + NEXT; + } else if(c2==(0xdf)&&ev[(c1-SSP)*2]) { + /* ȾÂùÅÀ */ + (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]); + c2=0; + NEXT; + } + UNGETC(c2); c2 = 0; + } + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + NEXT; + } else + SEND; + } else if(c1==SSO && iconv != s_iconv) { + /* EUC X0201 Case */ + /* This is too arrogant + if(x0201_f == NO_X0201) { + estab_f = FALSE; + c2 = 0; + NEXT; + } */ + c1 = GETC(); /* skip SSO */ + euc_1byte_check: + if(x0201_f && SSP<=c1 && c1<0xe0) { + if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) { + if((c2 = GETC()) == EOF) { + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + LAST; + } + /* forward lookup ÂùÅÀ/ȾÂùÅÀ */ + if(c2 != SSO) { + UNGETC(c2); c2 = 0; + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + NEXT; + } else if((c2 = GETC()) == EOF) { + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + (*oconv)(0,SSO); + LAST; + } else if(c2==(0xde)) { /* ÂùÅÀ */ + (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]); + c2=0; + NEXT; + } else if(c2==(0xdf)&&ev[(c1-SSP)*2]) { + /* ȾÂùÅÀ */ + (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]); + c2=0; + NEXT; + } else { + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + /* we have to check this c2 */ + /* and no way to push back SSO */ + c1 = c2; c2 = 0; + goto euc_1byte_check; + } + } + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + NEXT; + } else + SEND; + } else if(c1 < SSP && iconv != s_iconv) { + /* strange code in EUC */ + iconv = s_iconv; /* try SJIS */ + c2 = c1; + NEXT; + } else { + /* already established */ + c2 = c1; + NEXT; + } + } + } else if((c1 > SP) && (c1 != DEL)) { + /* in case of Roman characters */ + if(shift_mode) { + c1 |= 0x80; + /* output 1 shifted byte */ + if(x0201_f && (!iso8859_f||input_mode==X0201) && + SSP<=c1 && c1<0xe0 ) { + if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) { + if((c2 = GETC()) == EOF) { + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + LAST; + } else if(c2==(0xde&0x7f)) { /* ÂùÅÀ */ + (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]); + c2=0; + NEXT; + } else if(c2==(0xdf&0x7f)&&ev[(c1-SSP)*2]) { + /* ȾÂùÅÀ */ + (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]); + c2=0; + NEXT; + } + UNGETC(c2); c2 = 0; + } + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + NEXT; + } else + SEND; + } else if(c1 == '(' && broken_f && input_mode == X0208 + && !mime_mode ) { + /* Try to recover missing escape */ + if((c1 = GETC()) == EOF) { + (*oconv) (0, '('); + LAST; + } else { + if(c1 == 'B' || c1 == 'J' || c1 == 'H') { + input_mode = ASCII; shift_mode = FALSE; + NEXT; + } else { + (*oconv) (0, '('); + /* do not modify various input_mode */ + /* It can be vt100 sequence */ + SEND; + } + } + } else if(input_mode == X0208) { + /* in case of Kanji shifted */ + c2 = c1; + NEXT; + /* goto next_byte */ + } else if(c1 == '=' && mime_f && !mime_mode ) { + if((c1 = _GETC()) == EOF) { + (*oconv) (0, '='); + LAST; + } else if(c1 == '?') { + /* =? is mime conversion start sequence */ + if(mime_begin() == EOF) /* check in detail */ + LAST; + else + NEXT; + } else { + (*oconv) (0, '='); + _UNGETC(c1); + NEXT; + } + } else if(c1 == '$' && broken_f && !mime_mode) { + /* try to recover missing escape */ + if((c1 = GETC()) == EOF) { + (*oconv) (0, '$'); + LAST; + } else if(c1 == '@'|| c1 == 'B') { + /* in case of Kanji in ESC sequence */ + input_mode = X0208; + shift_mode = FALSE; + NEXT; + } else { + /* sorry */ + (*oconv) (0, '$'); + (*oconv) (0, c1); + NEXT; + } + } else + SEND; + } else if(c1 == SI) { + shift_mode = FALSE; + NEXT; + } else if(c1 == SO) { + shift_mode = TRUE; + NEXT; + } else if(c1 == ESC ) { + if((c1 = GETC()) == EOF) { + (*oconv) (0, ESC); + LAST; + } else if(c1 == '$') { + if((c1 = GETC()) == EOF) { + (*oconv) (0, ESC); + (*oconv) (0, '$'); + LAST; + } else if(c1 == '@'|| c1 == 'B') { + /* This is kanji introduction */ + input_mode = X0208; + shift_mode = FALSE; + NEXT; + } else if(broken_f&0x2) { + input_mode = X0208; + shift_mode = FALSE; + NEXT; + } else { + (*oconv) (0, ESC); + (*oconv) (0, '$'); + (*oconv) (0, c1); + NEXT; + } + } else if(c1 == '(') { + if((c1 = GETC()) == EOF) { + (*oconv) (0, ESC); + (*oconv) (0, '('); + LAST; + } else { + if(c1 == 'I') { + /* This is X0201 kana introduction */ + input_mode = X0201; shift_mode = X0201; + NEXT; + } else if(c1 == 'B' || c1 == 'J' || c1 == 'H') { + /* This is X0208 kanji introduction */ + input_mode = ASCII; shift_mode = FALSE; + NEXT; + } else if(broken_f&0x2) { + input_mode = ASCII; shift_mode = FALSE; + NEXT; + } else { + (*oconv) (0, ESC); + (*oconv) (0, '('); + /* maintain various input_mode here */ + SEND; + } + } + } else { + /* lonely ESC */ + (*oconv) (0, ESC); + SEND; + } + } else if(c1 == NL && broken_f&4) { + input_mode = ASCII; + SEND; + } else + SEND; + } + /* send: */ + if(input_mode == X0208) + (*oconv) (c2, c1); /* this is JIS, not SJIS/EUC case */ + else + (*iconv) (c2, c1); /* can be EUC/SJIS */ + c2 = 0; + continue; + /* goto next_word */ + } + + /* epilogue */ + (*iconv) (EOF, 0); + return outlen; +} + + +static void +h_conv (c2, c1) + register int c1, + c2; +{ + register int wc; + + + /** it must NOT be in the kanji shifte sequence */ + /** it must NOT be written in JIS7 */ + /** and it must be after 2 byte 8bit code */ + + hold_count = 0; + push_hold_buf (c2, c1); + c2 = 0; + + while ((c1 = GETC()) != EOF) { + if(c2) { + /* second byte */ + if(!estab_f) { + /* not established */ + if(c1 > SSP) { + /* it is still ambiguious yet */ + SEND; + } else if(c1 < AT) { + /* ignore bogus first byte */ + c2 = 0; + SEND; + } else { + /* now established */ + /* it seems to be MS Kanji */ + estab_f = TRUE; + iconv = s_iconv; + SEND; + } + } else + SEND; + } else { + /* First byte */ + if(c1 > DEL) { + /* 8th bit is on */ + if(c1 < SSP) { + /* it seems to be MS Kanji */ + estab_f = TRUE; + iconv = s_iconv; + } else if(c1 < 0xe0) { + /* it seems to be EUC */ + estab_f = TRUE; + iconv = oconv; + } else { + /* still ambiguious */ + } + c2 = c1; + NEXT; + } else + /* 7 bit code , then send without any process */ + SEND; + } + /* send: */ + if((push_hold_buf (c2, c1) == EOF) || estab_f) + break; + c2 = 0; + continue; + } + + /** now, + ** 1) EOF is detected, or + ** 2) Code is established, or + ** 3) Buffer is FULL (but last word is pushed) + ** + ** in 1) and 3) cases, we continue to use + ** Kanji codes by oconv and leave estab_f unchanged. + **/ + + for (wc = 0; wc < hold_count; wc += 2) { + c2 = hold_buf[wc]; + c1 = hold_buf[wc+1]; + (*iconv) (c2, c1); + } + return; +} + + + +int +push_hold_buf (c2, c1) + int c2, + c1; +{ + if(hold_count >= HOLD_SIZE*2) + return (EOF); + hold_buf[hold_count++] = c2; + hold_buf[hold_count++] = c1; + return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count); +} + + +static void +s_iconv (c2, c1) + register int c2, + c1; +{ + if((c2 == EOF) || (c2 == 0)) { + /* NOP */ + } else { + c2 = c2 + c2 - ((c2 <= 0x9f) ? SJ0162 : SJ6394); + if(c1 < 0x9f) + c1 = c1 - ((c1 > DEL) ? SP : 0x1f); + else { + c1 = c1 - 0x7e; + c2++; + } + } + (*oconv) (c2, c1); +} + + +static void +e_oconv (c2, c1) + register int c2, + c1; +{ + c2 = pre_convert(c1,c2); c1 = c1_return; + if(fold_f) { + switch(fold(c2,c1)) { + case '\n': + if(add_cr == TRUE) { + PUTCHAR('\r'); + c1 = '\n'; + } + PUTCHAR('\n'); + break; + case 0: return; + case '\r': + c1 = '\n'; c2 = 0; + break; + case '\t': + case ' ': + c1 = ' '; c2 = 0; + break; + } + } + if(c2==DOUBLE_SPACE) { + PUTCHAR(' '); PUTCHAR(' '); + return; + } + if(c2 == EOF) + return; + else if(c2 == 0 && (c1&0x80)) { + PUTCHAR(SSO); PUTCHAR(c1); + } else if(c2 == 0) { + if(c1 == '\n' && add_cr == TRUE) + PUTCHAR('\r'); + if(c1 != '\r') + PUTCHAR(c1); + else if(del_cr == FALSE) + PUTCHAR(c1); + } else { + if((c1<0x20 || 0x7e<c1) || + (c2<0x20 || 0x7e<c2)) { + estab_f = FALSE; + return; /* too late to rescue this char */ + } + PUTCHAR(c2 | 0x080); + PUTCHAR(c1 | 0x080); + } +} + + +static void +s_oconv (c2, c1) + register int c2, + c1; +{ + c2 = pre_convert(c1,c2); c1 = c1_return; + if(fold_f) { + switch(fold(c2,c1)) { + case '\n': + if(add_cr == TRUE) { + PUTCHAR('\r'); + c1 = '\n'; + } + PUTCHAR('\n'); + break; + case '\r': + c1 = '\n'; c2 = 0; + break; + case 0: return; + case '\t': + case ' ': + c1 = ' '; c2 = 0; + break; + } + } + if(c2==DOUBLE_SPACE) { + PUTCHAR(' '); PUTCHAR(' '); + return; + } + if(c2 == EOF) + return; + else if(c2 == 0) { + if(c1 == '\n' && add_cr == TRUE) + PUTCHAR('\r'); + if(c1 != '\r') + PUTCHAR(c1); + else if(del_cr == FALSE) + PUTCHAR(c1); + } else { + if((c1<0x20 || 0x7e<c1) || + (c2<0x20 || 0x7e<c2)) { + estab_f = FALSE; + return; /* too late to rescue this char */ + } + PUTCHAR((((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1))); + PUTCHAR((c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e))); + } +} + +static void +j_oconv (c2, c1) + register int c2, + c1; +{ + c2 = pre_convert(c1,c2); c1 = c1_return; + if(fold_f) { + switch(fold(c2,c1)) { + case '\n': + if(output_mode) { + PUTCHAR(ESC); + PUTCHAR('('); + PUTCHAR(ascii_intro); + } + if(add_cr == TRUE) { + PUTCHAR('\r'); + c1 = '\n'; + } + PUTCHAR('\n'); + output_mode = ASCII; + break; + case '\r': + c1 = '\n'; c2 = 0; + break; + case '\t': + case ' ': + c1 = ' '; c2 = 0; + break; + case 0: return; + } + } + if(c2 == EOF) { + if(output_mode) { + PUTCHAR(ESC); + PUTCHAR('('); + PUTCHAR(ascii_intro); + } + } else if(c2 == 0 && (c1 & 0x80)) { + if(input_mode==X0201 || !iso8859_f) { + if(output_mode!=X0201) { + PUTCHAR(ESC); + PUTCHAR('('); + PUTCHAR('I'); + output_mode = X0201; + } + c1 &= 0x7f; + } else { + /* iso8859 introduction, or 8th bit on */ + /* Can we convert in 7bit form using ESC-'-'-A ? + Is this popular? */ + } + PUTCHAR(c1); + } else if(c2 == 0) { + if(output_mode) { + PUTCHAR(ESC); + PUTCHAR('('); + PUTCHAR(ascii_intro); + output_mode = ASCII; + } + if(c1 == '\n' && add_cr == TRUE) + PUTCHAR('\r'); + if(c1 != '\r') + PUTCHAR(c1); + else if(del_cr == FALSE) + PUTCHAR(c1); + } else if(c2 == DOUBLE_SPACE) { + if(output_mode) { + PUTCHAR(ESC); + PUTCHAR('('); + PUTCHAR(ascii_intro); + output_mode = ASCII; + } + PUTCHAR(' '); + if(c1 == '\n' && add_cr == TRUE) + PUTCHAR('\r'); + if(c1 != '\r') + PUTCHAR(c1); + else if(del_cr == FALSE) + PUTCHAR(c1); + } else { + if(output_mode != X0208) { + PUTCHAR(ESC); + PUTCHAR('$'); + PUTCHAR(kanji_intro); + output_mode = X0208; + } + if(c1<0x20 || 0x7e<c1) + return; + if(c2<0x20 || 0x7e<c2) + return; + PUTCHAR(c2); + if(c1 == '\n' && add_cr == TRUE) + PUTCHAR('\r'); + if(c1 != '\r') + PUTCHAR(c1); + else if(del_cr == FALSE) + PUTCHAR(c1); + } +} + + +#define rot13(c) ( \ + ( c < 'A' ) ? c: \ + (c <= 'M') ? (c + 13): \ + (c <= 'Z') ? (c - 13): \ + (c < 'a') ? (c): \ + (c <= 'm') ? (c + 13): \ + (c <= 'z') ? (c - 13): \ + (c) \ +) + +#define rot47(c) ( \ + ( c < '!' ) ? c: \ + ( c <= 'O' ) ? (c + 47) : \ + ( c <= '~' ) ? (c - 47) : \ + c \ +) + +/* + Return value of fold() + + \n add newline and output char + \r add newline and output nothing + ' ' space + 0 skip + 1 (or else) normal output + + fold state in prev (previous character) + + >0x80 Japanese (X0208/X0201) + <0x80 ASCII + \n new line + ' ' space + + This fold algorthm does not preserve heading space in a line. + This is the main difference from fmt. +*/ + +int +fold(c2,c1) +register int c2,c1; +{ + int prev0; + if(c1=='\r') + return 0; /* ignore cr */ + if(c1== 8) { + if(line>0) line--; + return 1; + } + if(c2==EOF && line != 0) /* close open last line */ + return '\n'; + /* new line */ + if(c1=='\n') { + if(prev == c1) { /* duplicate newline */ + if(line) { + line = 0; + return '\n'; /* output two newline */ + } else { + line = 0; + return 1; + } + } else { + if(prev&0x80) { /* Japanese? */ + prev = c1; + return 0; /* ignore given single newline */ + } else if(prev==' ') { + return 0; + } else { + prev = c1; + if(++line<=fold_len) + return ' '; + else { + line = 0; + return '\r'; /* fold and output nothing */ + } + } + } + } + if(c1=='\f') { + prev = '\n'; + if(line==0) + return 1; + line = 0; + return '\n'; /* output newline and clear */ + } + /* X0208 kankaku or ascii space */ + if( (c2==0&&c1==' ')|| + (c2==0&&c1=='\t')|| + (c2==DOUBLE_SPACE)|| + (c2=='!'&& c1=='!')) { + if(prev == ' ') { + return 0; /* remove duplicate spaces */ + } + prev = ' '; + if(++line<=fold_len) + return ' '; /* output ASCII space only */ + else { + prev = ' '; line = 0; + return '\r'; /* fold and output nothing */ + } + } + prev0 = prev; /* we still need this one... , but almost done */ + prev = c1; + if(c2 || (SSP<=c1 && c1<=0xdf)) + prev |= 0x80; /* this is Japanese */ + line += (c2==0)?1:2; + if(line<=fold_len) { /* normal case */ + return 1; + } + if(line>=fold_len+FOLD_MARGIN) { /* too many kinsou suspension */ + line = (c2==0)?1:2; + return '\n'; /* We can't wait, do fold now */ + } + /* simple kinsoku rules return 1 means no folding */ + if(c2==0) { + if(c1==0xde) return 1; /* ¡«*/ + if(c1==0xdf) return 1; /* ¡¬*/ + if(c1==0xa4) return 1; /* ¡£*/ + if(c1==0xa3) return 1; /* ¡¤*/ + if(c1==0xa1) return 1; /* ¡×*/ + if(c1==0xb0) return 1; /* - */ + if(SSP<=c1 && c1<=0xdf) { /* X0201 */ + line = 1; + return '\n';/* add one new line before this character */ + } + /* fold point in ASCII { [ ( */ + if(( c1!=')'&& + c1!=']'&& + c1!='}'&& + c1!='.'&& + c1!=','&& + c1!='!'&& + c1!='?'&& + c1!='/'&& + c1!=':'&& + c1!=';')&& + ((prev0=='\n')|| (prev0==' ')|| /* ignored new line */ + (prev0&0x80)) /* X0208 - ASCII */ + ) { + line = 1; + return '\n';/* add one new line before this character */ + } + return 1; /* default no fold in ASCII */ + } else { + if(c2=='!') { + if(c1=='"') return 1; /* ¡¢ */ + if(c1=='#') return 1; /* ¡£ */ + if(c1=='$') return 1; /* ¡¤ */ + if(c1=='%') return 1; /* ¡¥ */ + if(c1=='\'') return 1; /* ¡Ü */ + if(c1=='(') return 1; /* ¡¨ */ + if(c1==')') return 1; /* ¡© */ + if(c1=='*') return 1; /* ¡ª */ + if(c1=='+') return 1; /* ¡« */ + if(c1==',') return 1; /* ¡¬ */ + } + line = 2; + return '\n'; /* add one new line before this character */ + } +} + +int +pre_convert(c1,c2) +register int c1,c2; +{ + if(c2) c1 &= 0x7f; + c1_return = c1; + if(c2==EOF) return c2; + c2 &= 0x7f; + if(rot_f) { + if(c2) { + c1 = rot47(c1); + c2 = rot47(c2); + } else { + if(!(c1 & 0x80)) + c1 = rot13(c1); + } + c1_return = c1; + } + /* JISX0208 Alphabet */ + if(alpha_f && c2 == 0x23 ) return 0; + /* JISX0208 Kigou */ + if(alpha_f && c2 == 0x21 ) { + if(0x21==c1) { + if(alpha_f&0x2) { + c1_return = ' '; + return 0; + } else if(alpha_f&0x4) { + c1_return = ' '; + return DOUBLE_SPACE; + } else { + return c2; + } + } else if(0x20<c1 && c1<0x7f && fv[c1-0x20]) { + c1_return = fv[c1-0x20]; + return 0; + } + } + return c2; +} + + +/* X0201 / X0208 conversion tables */ + +/* X0201 kana conversion table */ +/* 90-9F A0-DF */ +unsigned char cv[]= { +0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57, +0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21, +0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29, +0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43, +0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26, +0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d, +0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35, +0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d, +0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46, +0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c, +0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52, +0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e, +0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62, +0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69, +0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d, +0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c, +0x00,0x00}; + + +/* X0201 kana conversion table for daguten */ +/* 90-9F A0-DF */ +unsigned char dv[]= { +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e, +0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36, +0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e, +0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47, +0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53, +0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00}; + +/* X0201 kana conversion table for han-daguten */ +/* 90-9F A0-DF */ +unsigned char ev[]= { +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54, +0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00}; + + +/* X0208 kigou conversion table */ +/* 0x8140 - 0x819e */ +unsigned char fv[] = { + +0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a, +0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00, +0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f, +0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27, +0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d, +0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00, +0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +} ; + + +/* This converts =?ISO-2022-JP?B?HOGE HOGE?= */ + +unsigned char *mime_pattern[] = { + (unsigned char *)"\075?ISO-8859-1?Q?", + (unsigned char *)"\075?ISO-2022-JP?B?", + (unsigned char *)"\075?ISO-2022-JP?Q?", + NULL +}; + +int mime_encode[] = { + 'Q', 'B', 'Q', + 0 +}; + +int iso8859_f_save; + +#define nkf_toupper(c) (('a'<=c && c<='z')?(c-('a'-'A')):c) +/* I don't trust portablity of toupper */ + +int +mime_begin() +{ + int c1; + int i,j,k; + unsigned char *p,*q; + int r[20]; /* recovery buffer, max mime pattern lenght */ + + mime_mode = FALSE; + /* =? has been checked */ + j = 0; + p = mime_pattern[j]; + r[0]='='; r[1]='?'; + + for(i=2;p[i]>' ';i++) { /* start at =? */ + if( ((r[i] = c1 = _GETC())==EOF) || nkf_toupper(c1) != p[i] ) { + /* pattern fails, try next one */ + q = p; + while (p = mime_pattern[++j]) { + for(k=2;k<i;k++) /* assume length(p) > i */ + if(p[k]!=q[k]) break; + if(k==i && nkf_toupper(c1)==p[k]) break; + } + if(p) continue; /* found next one, continue */ + /* all fails, output from recovery buffer */ + _UNGETC(c1); + for(j=0;j<i;j++) { + (*oconv)(0,r[j]); + } + return c1; + } + } + iso8859_f_save = iso8859_f; + if(j==0) { + iso8859_f = TRUE; + } + mime_mode = mime_encode[j]; + if(mime_mode=='B') { + mimebuf_f = unbuf_f; + if(!unbuf_f) { + /* do MIME integrity check */ + return mime_integrity(mime_pattern[j]); + } + } + mimebuf_f = TRUE; + return c1; +} + +#define mime_getc0() (mimebuf_f?_GETC():Fifo(mime_input++)) +#define mime_ungetc0(c) (mimebuf_f?_UNGETC(c):mime_input--) + +int +mime_getc() +{ + int c1, c2, c3, c4, cc; + int t1, t2, t3, t4, mode, exit_mode; + + if(mime_top != mime_last) { /* Something is in FIFO */ + return Fifo(mime_top++); + } + + if(mimebuf_f == FIXED_MIME) + exit_mode = mime_mode; + else + exit_mode = FALSE; + if(mime_mode == 'Q') { + if((c1 = mime_getc0()) == EOF) return (EOF); + if(c1=='_') return ' '; + if(c1!='=' && c1!='?') + return c1; + mime_mode = exit_mode; /* prepare for quit */ + if(c1<=' ') return c1; + if((c2 = mime_getc0()) == EOF) return (EOF); + if(c2<=' ') return c2; + if(c1=='?'&&c2=='=') { + /* end Q encoding */ + input_mode = exit_mode; + iso8859_f = iso8859_f_save; + return _GETC(); + } + if(c1=='?') { + mime_mode = 'Q'; /* still in MIME */ + mime_ungetc0(c2); + return c1; + } + if((c3 = mime_getc0()) == EOF) return (EOF); + if(c2<=' ') return c2; + mime_mode = 'Q'; /* still in MIME */ +#define hex(c) (('0'<=c&&c<='9')?(c-'0'):\ + ('A'<=c&&c<='F')?(c-'A'+10):('a'<=c&&c<='f')?(c-'a'+10):0) + return ((hex(c2)<<4) + hex(c3)); + } + + if(mime_mode != 'B') { + mime_mode = FALSE; + return _GETC(); + } + + + /* Base64 encoding */ + /* + MIME allows line break in the middle of + Base64, but we are very pessimistic in decoding + in unbuf mode because MIME encoded code may broken by + less or editor's control sequence (such as ESC-[-K in unbuffered + mode. ignore incomplete MIME. + */ + mode = mime_mode; + mime_mode = exit_mode; /* prepare for quit */ + + while ((c1 = mime_getc0())<=' ') { + if(c1==EOF) + return (EOF); + } + if((c2 = mime_getc0())<=' ') { + if(c2==EOF) + return (EOF); + if(mimebuf_f!=FIXED_MIME) input_mode = ASCII; + return c2; + } + if((c1 == '?') && (c2 == '=')) { + input_mode = ASCII; + while((c1 = _GETC())==' ' /* || c1=='\n' || c1=='\r' */); + return c1; + } + if((c3 = mime_getc0())<=' ') { + if(c3==EOF) + return (EOF); + if(mimebuf_f!=FIXED_MIME) input_mode = ASCII; + return c3; + } + if((c4 = mime_getc0())<=' ') { + if(c4==EOF) + return (EOF); + if(mimebuf_f!=FIXED_MIME) input_mode = ASCII; + return c4; + } + + mime_mode = mode; /* still in MIME sigh... */ + + /* BASE 64 decoding */ + + t1 = 0x3f & base64decode(c1); + t2 = 0x3f & base64decode(c2); + t3 = 0x3f & base64decode(c3); + t4 = 0x3f & base64decode(c4); + cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03); + if(c2 != '=') { + Fifo(mime_last++) = cc; + cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f); + if(c3 != '=') { + Fifo(mime_last++) = cc; + cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f); + if(c4 != '=') + Fifo(mime_last++) = cc; + } + } else { + return c1; + } + return Fifo(mime_top++); +} + +int +mime_ungetc(c) +unsigned int c; +{ + Fifo(mime_last++) = c; + return c; +} + + +int +mime_integrity(p) +unsigned char *p; +{ + int c,d; + unsigned int q; + /* In buffered mode, read until =? or NL or buffer full + */ + mime_input = mime_top; + mime_last = mime_top; + while(*p) Fifo(mime_input++) = *p++; + d = 0; + q = mime_input; + while((c=_GETC())!=EOF) { + if(((mime_input-mime_top)&MIME_BUF_MASK)==0) break; + if(c=='=' && d=='?') { + /* checked. skip header, start decode */ + Fifo(mime_input++) = c; + mime_input = q; + return 1; + } + if(!( (c=='+'||c=='/'|| c=='=' || c=='?' || + ('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9')))) + break; + /* Should we check length mod 4? */ + Fifo(mime_input++) = c; + d=c; + } + /* In case of Incomplete MIME, no MIME decode */ + Fifo(mime_input++) = c; + mime_last = mime_input; /* point undecoded buffer */ + mime_mode = 1; /* no decode on Fifo last in mime_getc */ + return 1; +} + +int +base64decode(c) + int c; +{ + int i; + if(c > '@') + if(c < '[') + i = c - 'A'; /* A..Z 0-25 */ + else + i = c - 'G' /* - 'a' + 26 */ ; /* a..z 26-51 */ + else if(c > '/') + i = c - '0' + '4' /* - '0' + 52 */ ; /* 0..9 52-61 */ + else if(c == '+') + i = '>' /* 62 */ ; /* + 62 */ + else + i = '?' /* 63 */ ; /* / 63 */ + return (i); +} + +#ifdef notdef +int +usage() +{ + fprintf(stderr,"USAGE: nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n"); + fprintf(stderr,"Flags:\n"); + fprintf(stderr,"b,u Output is bufferred (DEFAULT),Output is unbufferred\n"); +#ifdef DEFAULT_CODE_SJIS + fprintf(stderr,"j,s,e Outout code is JIS 7 bit, Shift JIS (DEFAULT), AT&T JIS (EUC)\n"); +#endif +#ifdef DEFAULT_CODE_JIS + fprintf(stderr,"j,s,e Outout code is JIS 7 bit (DEFAULT), Shift JIS, AT&T JIS (EUC)\n"); +#endif +#ifdef DEFAULT_CODE_EUC + fprintf(stderr,"j,s,e Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC) (DEFAULT)\n"); +#endif + fprintf(stderr,"J,S,E Input assumption is JIS 7 bit , Shift JIS, AT&T JIS (EUC)\n"); + fprintf(stderr,"t no conversion\n"); + fprintf(stderr,"i_ Output sequence to designate JIS-kanji (DEFAULT B)\n"); + fprintf(stderr,"o_ Output sequence to designate ASCII (DEFAULT B)\n"); + fprintf(stderr,"r {de/en}crypt ROT13/47\n"); + fprintf(stderr,"v Show this usage\n"); + fprintf(stderr,"m[BQ] MIME decode [B:base64 stream,Q:quoted stream]\n"); + fprintf(stderr,"l ISO8859-1 (Latin-1) support\n"); + fprintf(stderr,"f Folding: -f60 or -f\n"); + fprintf(stderr,"Z[0-2] Convert X0208 alphabet to ASCII 1: Kankaku to space,2: 2 spaces\n"); + fprintf(stderr,"X,x Assume X0201 kana in MS-Kanji, -x preserves X0201\n"); + fprintf(stderr,"B[0-2] Broken input 0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n"); +#ifdef MSDOS + fprintf(stderr,"T Text mode output\n"); +#endif + fprintf(stderr,"O Output to File (DEFAULT 'nkf.out')\n"); + fprintf(stderr,"d,c Delete \\r in line feed, Add \\r in line feed\n"); + fprintf(stderr,"Network Kanji Filter Version %s (%s) " +#if defined(MSDOS) && !defined(_Windows) + "for DOS" +#endif +#if !defined(__WIN32__) && defined(_Windows) + "for Win16" +#endif +#if defined(__WIN32__) && defined(_Windows) + "for Win32" +#endif +#ifdef __OS2__ + "for OS/2" +#endif + ,Version,Patchlevel); + fprintf(stderr,"\n%s\n",CopyRight); + return 0; +} +#endif /* notdef */ + +#include "ruby.h" + +static VALUE +kconv_kconv(argc, argv) + int argc; + VALUE *argv; +{ + struct RString *src, *dst; + VALUE in, out; + int in_code, out_code; + + rb_scan_args(argc, argv, "12", &src, &out, &in); + Check_Type(src, T_STRING); + + if (NIL_P(out)) { + out_code = _JIS; + } + else { + out_code = NUM2INT(out); + } + if (NIL_P(in)) { + in_code = _AUTO; + } + else { + in_code = NUM2INT(in); + } + + dst = RSTRING(str_new(0, src->len*3+10)); /* large enough? */ + dst->len = do_kconv(src->ptr, dst->ptr, dst->len, out_code, in_code); + + return (VALUE)dst; +} + +static VALUE +kconv_tojis(obj, src) + VALUE obj; + struct RString *src; +{ + struct RString *dst; + + Check_Type(src, T_STRING); + + dst = RSTRING(str_new(0, src->len*3+10)); /* large enough? */ + dst->len = do_kconv(src->ptr, dst->ptr, dst->len, _JIS, _AUTO); + + return (VALUE)dst; +} + +static VALUE +kconv_toeuc(obj, src) + VALUE obj; + struct RString* src; +{ + struct RString *dst; + + Check_Type(src, T_STRING); + + dst = RSTRING(str_new(0, src->len*3+10)); /* large enough? */ + dst->len = do_kconv(src->ptr, dst->ptr, dst->len, _EUC, _AUTO); + + return (VALUE)dst; +} + +static VALUE +kconv_tosjis(obj, src) + VALUE obj; + struct RString* src; +{ + struct RString *dst; + + Check_Type(src, T_STRING); + + dst = RSTRING(str_new(0, src->len*3+10)); /* large enough? */ + dst->len = do_kconv(src->ptr, dst->ptr, dst->len, _SJIS, _AUTO); + + return (VALUE)dst; +} + +void +Init_kconv() +{ + VALUE mKconv = rb_define_module("Kconv"); + + rb_define_module_function(mKconv, "kconv", kconv_kconv, -1); + rb_define_module_function(mKconv, "tojis", kconv_tojis, 1); + rb_define_module_function(mKconv, "toeuc", kconv_toeuc, 1); + rb_define_module_function(mKconv, "tosjis", kconv_tosjis, 1); + + rb_define_const(mKconv, "AUTO", INT2FIX(_AUTO)); + rb_define_const(mKconv, "JIS", INT2FIX(_JIS)); + rb_define_const(mKconv, "EUC", INT2FIX(_EUC)); + rb_define_const(mKconv, "SJIS", INT2FIX(_SJIS)); +} + +/** + ** ¥Ñ¥Ã¥ÁÀ©ºî¼Ô + ** void@merope.pleiades.or.jp (Kusakabe Youichi) + ** NIDE Naoyuki <nide@ics.nara-wu.ac.jp> + ** ohta@src.ricoh.co.jp (Junn Ohta) + ** inouet@strl.nhk.or.jp (Tomoyuki Inoue) + ** kiri@pulser.win.or.jp (Tetsuaki Kiriyama) + ** Kimihiko Sato <sato@sail.t.u-tokyo.ac.jp> + ** a_kuroe@kuroe.aoba.yokohama.jp (Akihiko Kuroe) + ** kono@ie.u-ryukyu.ac.jp (Shinji Kono) + ** GHG00637@nifty-serve.or.jp (COW) + ** j_kuro@pluto.ai.kyutech.ac.jp (Jun Kuroda) + ** + ** ºÇ½ª¹¹¿·Æü + ** 1996.12.18 + **/ + +/* end */ diff --git a/ext/marshal/MANIFEST b/ext/marshal/MANIFEST index 53b0849484..54870ec71f 100644 --- a/ext/marshal/MANIFEST +++ b/ext/marshal/MANIFEST @@ -1,4 +1,5 @@ MANIFEST depend +extconf.rb marshal.c marshal.doc diff --git a/ext/marshal/extconf.rb b/ext/marshal/extconf.rb new file mode 100644 index 0000000000..65923049e5 --- /dev/null +++ b/ext/marshal/extconf.rb @@ -0,0 +1,2 @@ +have_func("tmpnam") +create_makefile("marshal") diff --git a/ext/marshal/marshal.c b/ext/marshal/marshal.c index 0b29ad5ab8..eae8d7fe09 100644 --- a/ext/marshal/marshal.c +++ b/ext/marshal/marshal.c @@ -13,24 +13,52 @@ #include "io.h" #include "st.h" +#define MARSHAL_MAJOR 2 +#define MARSHAL_MINOR 1 + #define TYPE_NIL '0' +#define TYPE_TRUE 'T' +#define TYPE_FALSE 'F' #define TYPE_FIXNUM 'i' #define TYPE_OBJECT 'o' -#define TYPE_LINK '@' +#define TYPE_USERDEF 'u' #define TYPE_FLOAT 'f' #define TYPE_BIGNUM 'l' #define TYPE_STRING '"' +#define TYPE_STRING2 '\'' #define TYPE_REGEXP '/' #define TYPE_ARRAY '[' +#define TYPE_ARRAY2 ']' #define TYPE_HASH '{' +#define TYPE_HASH2 '}' #define TYPE_STRUCT 'S' +#define TYPE_SYMBOL ':' +#define TYPE_SYMLINK ';' + +VALUE cString; +VALUE cArray; +VALUE cHash; + char *rb_class2path(); VALUE rb_path2class(); static ID s_dump, s_load; +#if (defined(linux) && defined(USE_DLN_A_OUT)) || !defined(HAVE_TMPNAM) +#define tmpnam(s) ltmpnam(s) +static char * +tmpnam(s) + char *s; +{ + static int n = 0; + + sprintf(s, "/tmp/rb-mrsr-%x%x", getpid(), n++); + return s; +} +#endif + #define w_byte(c, fp) putc((c), fp) #define w_bytes(s, n, fp) (w_long((n), fp),fwrite(s, 1, n, fp)) @@ -66,70 +94,119 @@ w_float(d, fp) } static void -w_symbol(id, fp) +w_symbol(id, fp, table) ID id; FILE *fp; + st_table *table; { char *sym = rb_id2name(id); + int num; - w_bytes(sym, strlen(sym), fp); + if (st_lookup(table, id, &num)) { + w_byte(TYPE_SYMLINK, fp); + w_long(num, fp); + } + else { + w_byte(TYPE_SYMBOL, fp); + w_bytes(sym, strlen(sym), fp); + st_insert(table, id, table->num_entries); + } +} + +static void +w_unique(s, fp, table) + char *s; + FILE *fp; + st_table *table; +{ + w_symbol(rb_intern(s), fp, table); } static void w_object(); extern VALUE cBignum, cStruct; +struct each_arg { + FILE *fp; + VALUE limit; + st_table *table; +}; + static int -hash_each(key, value, fp) +hash_each(key, value, arg) VALUE key, value; - FILE *fp; + struct each_arg *arg; { - w_object(key, fp); - w_object(value, fp); + w_object(key, arg->fp, arg->limit, arg->table); + w_object(value, arg->fp, arg->limit, arg->table); return ST_CONTINUE; } static int -obj_each(id, value, fp) +obj_each(id, value, arg) ID id; VALUE value; - FILE *fp; + struct each_arg *arg; { - w_symbol(id, fp); - w_object(value, fp); + w_symbol(id, arg->fp, arg->table); + w_object(value, arg->fp, arg->limit, arg->table); return ST_CONTINUE; } -struct st_table *new_idhash(); - static void -w_object(obj, fp, port, table) - VALUE obj, port; +w_object(obj, fp, limit, table) + VALUE obj; FILE *fp; + int limit; st_table *table; { + struct each_arg arg; + int n; + + if (limit == 0) { + Fail("exceed depth limit"); + } + limit--; + + arg.fp = fp; + arg.limit = limit; + arg.table = table; + if (obj == Qnil) { w_byte(TYPE_NIL, fp); } - else if (FIXNUM_P(obj)) { - w_byte(TYPE_FIXNUM, fp); - w_long(FIX2INT(obj), fp); + else if (obj == TRUE) { + w_byte(TYPE_TRUE, fp); + } + else if (obj == FALSE) { + w_byte(TYPE_FALSE, fp); } - else if (st_lookup(table, obj, 0)) { - w_byte(TYPE_LINK, fp); - w_long(obj, fp); + else if (FIXNUM_P(obj)) { + if (sizeof(long) == 4) { + w_byte(TYPE_FIXNUM, fp); + w_long(FIX2INT(obj), fp); + } } else { - st_insert(table, obj, 0); + if (rb_respond_to(obj, s_dump)) { + VALUE v; + + w_byte(TYPE_USERDEF, fp); + w_unique(rb_class2path(CLASS_OF(obj)), fp, table); + v = rb_funcall(obj, s_dump, 1, limit); + if (TYPE(v) != T_STRING) { + TypeError("_dump_to must return String"); + } + w_bytes(RSTRING(v)->ptr, RSTRING(v)->len, fp); + return; + } switch (BUILTIN_TYPE(obj)) { case T_FLOAT: w_byte(TYPE_FLOAT, fp); - w_long(obj, fp); w_float(RFLOAT(obj)->value, fp); - break; + return; case T_BIGNUM: w_byte(TYPE_BIGNUM, fp); - w_long(obj, fp); { char sign = RBIGNUM(obj)->sign?'+':'-'; int len = RBIGNUM(obj)->len; @@ -142,80 +219,92 @@ w_object(obj, fp, port, table) d++; } } - break; + return; + } + switch (BUILTIN_TYPE(obj)) { case T_STRING: - w_byte(TYPE_STRING, fp); - w_long(obj, fp); - w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, fp); - break; + if (CLASS_OF(obj) == cString) { + w_byte(TYPE_STRING, fp); + w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, fp); + } + else { + w_byte(TYPE_STRING2, fp); + w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, fp); + w_unique(rb_class2path(CLASS_OF(obj)), fp, table); + } + return; case T_REGEXP: w_byte(TYPE_REGEXP, fp); - w_long(obj, fp); w_bytes(RREGEXP(obj)->str, RREGEXP(obj)->len, fp); w_byte(FL_TEST(obj, FL_USER1), fp); - break; + return; case T_ARRAY: - w_byte(TYPE_ARRAY, fp); - w_long(obj, fp); + if (CLASS_OF(obj) == cArray) w_byte(TYPE_ARRAY, fp); + else w_byte(TYPE_ARRAY2, fp); { int len = RARRAY(obj)->len; VALUE *ptr = RARRAY(obj)->ptr; w_long(len, fp); while (len--) { - w_object(*ptr, fp, port, table); + w_object(*ptr, fp, limit, table); ptr++; } } + if (CLASS_OF(obj) != cArray) { + w_unique(rb_class2path(CLASS_OF(obj)), fp, table); + } break; case T_HASH: + if (CLASS_OF(obj) == cHash) w_byte(TYPE_HASH, fp); + else w_byte(TYPE_HASH2, fp); w_byte(TYPE_HASH, fp); - w_long(obj, fp); w_long(RHASH(obj)->tbl->num_entries, fp); - st_foreach(RHASH(obj)->tbl, hash_each, fp); + st_foreach(RHASH(obj)->tbl, hash_each, &arg); + if (CLASS_OF(obj) != cHash) { + w_unique(rb_class2path(CLASS_OF(obj)), fp, table); + } break; case T_STRUCT: w_byte(TYPE_STRUCT, fp); - w_long(obj, fp); { int len = RSTRUCT(obj)->len; char *path = rb_class2path(CLASS_OF(obj)); VALUE mem; int i; - w_bytes(path, strlen(path), fp); + w_unique(path, fp, table); w_long(len, fp); mem = rb_ivar_get(CLASS_OF(obj), rb_intern("__member__")); if (mem == Qnil) { - Fail("non-initialized struct"); + Fatal("non-initialized struct"); } for (i=0; i<len; i++) { - w_symbol(FIX2INT(RARRAY(mem)->ptr[i]), fp); - w_object(RSTRUCT(obj)->ptr[i], fp, port, table); + w_symbol(FIX2INT(RARRAY(mem)->ptr[i]), fp, table); + w_object(RSTRUCT(obj)->ptr[i], fp, limit, table); } } break; case T_OBJECT: w_byte(TYPE_OBJECT, fp); - w_long(obj, fp); { VALUE class = CLASS_OF(obj); - char *path = rb_class2path(class); + char *path; - w_bytes(path, strlen(path), fp); - if (rb_responds_to(obj, s_dump)) { - w_long(-1, fp); - rb_funcall(obj, s_dump, 1, port); + if (FL_TEST(class, FL_SINGLETON)) { + TypeError("singleton can't be dumped"); } - else if (ROBJECT(obj)->iv_tbl) { + path = rb_class2path(class); + w_unique(path, fp, table); + if (ROBJECT(obj)->iv_tbl) { w_long(ROBJECT(obj)->iv_tbl->num_entries, fp); - st_foreach(ROBJECT(obj)->iv_tbl, obj_each, fp); + st_foreach(ROBJECT(obj)->iv_tbl, obj_each, &arg); } else { w_long(0, fp); @@ -224,59 +313,108 @@ w_object(obj, fp, port, table) break; default: - Fail("can't dump %s", rb_class2name(CLASS_OF(obj))); + TypeError("can't dump %s", rb_class2name(CLASS_OF(obj))); break; } } } +struct dump_arg { + VALUE obj; + FILE *fp; + int limit; + st_table *table; +}; + static VALUE -marshal_dump(self, obj, port) - VALUE self, obj, port; +dump(arg) + struct dump_arg *arg; +{ + w_object(arg->obj, arg->fp, arg->limit, arg->table); +} + +static VALUE +dump_ensure(arg) + struct dump_arg *arg; +{ + st_free_table(arg->table); +} + +static VALUE +dump_on(obj, port, limit) + VALUE obj, port; + int limit; { extern VALUE cIO; FILE *fp; OpenFile *fptr; - st_table *table; + struct dump_arg arg; if (obj_is_kind_of(port, cIO)) { GetOpenFile(port, fptr); - if (!(fptr->mode & FMODE_WRITABLE)) { - Fail("not opened for writing"); - } + io_writable(fptr); fp = (fptr->f2) ? fptr->f2 : fptr->f; } else { - Fail("instance of IO needed"); + TypeError("instance of IO needed"); } - table = new_idhash(); + w_byte(MARSHAL_MAJOR, fp); + w_byte(MARSHAL_MINOR, fp); - w_object(obj, fp, port, table); + arg.obj = obj; + arg.fp = fp; + arg.limit = limit; + arg.table = st_init_numtable(); + rb_ensure(dump, &arg, dump_ensure, &arg); - st_free_table(table); return Qnil; } static VALUE -marshal_dumps(self, obj) - VALUE self, obj; +marshal_dump(argc, argv) + int argc; + VALUE argv; +{ + VALUE obj, port, lim; + int limit; + + rb_scan_args(argc, argv, "21", &obj, &port, &lim); + if (NIL_P(lim)) limit = 100; + else limit = NUM2INT(lim); + + dump_on(obj, port, limit); +} + +static VALUE +marshal_dumps(argc, argv) + int argc; + VALUE argv; { + VALUE obj, lim; + int limit; VALUE str = str_new(0, 0); VALUE port; - FILE *fp = Qnil; + FILE *fp = 0; char buf[BUFSIZ]; int n; - sprintf(buf, "/tmp/rb-mrsr-%x", getpid()^(int)buf); + rb_scan_args(argc, argv, "11", &obj, &lim); + if (NIL_P(lim)) limit = 100; + else limit = NUM2INT(lim); + + tmpnam(buf); port = file_open(buf, "w"); - if (!port) rb_sys_fail("tmp file"); - fp = fopen(buf, "r"); - if (!fp) rb_sys_fail("tmp file(read)"); + fp = rb_fopen(buf, "r"); +#if !defined(MSDOS) && !defined(__BOW__) unlink(buf); +#endif - marshal_dump(self, obj, port); + dump_on(obj, port, limit); io_close(port); +#if defined(MSDOS) || defined(__BOW__) + unlink(buf); +#endif while (n = fread(buf, 1, BUFSIZ, fp)) { str_cat(str, buf, n); @@ -310,67 +448,96 @@ r_long(fp) /* XXX If your long is > 32 bits, add sign-extension here!!! */ return x; } -#define r_bytes(s, fp) r_bytes0(&s, fp) -static int -r_bytes0(s, fp) - char **s; + +#define r_bytes(s, fp) \ + (s = (char*)r_long(fp), r_bytes0(&s,ALLOCA_N(char,(int)s),(int)s,fp)) + +static char +r_bytes0(sp, s, len, fp) + char **sp, *s; + int len; FILE *fp; { - int len = r_long(fp); - *s = ALLOC_N(char, len+1); + fread(s, 1, len, fp); + (s)[len] = '\0'; + *sp = s; - fread(*s, 1, len, fp); - (*s)[len] = '\0'; return len; } static ID -r_symbol(fp) +r_symbol(fp, table) FILE *fp; + st_table *table; { char *buf; ID id; + char type; + if (r_byte(fp) == TYPE_SYMLINK) { + int num = r_long(fp); + + if (st_lookup(table, num, &id)) { + return id; + } + TypeError("bad symbol"); + } r_bytes(buf, fp); id = rb_intern(buf); - free(buf); + st_insert(table, table->num_entries, id); + return id; } +static char* +r_unique(fp, table) + FILE *fp; + st_table *table; +{ + return rb_id2name(r_symbol(fp, table)); +} + static VALUE -r_object(fp, port, table) +r_string(fp) + FILE *fp; +{ + char *buf; + int len = r_bytes(buf, fp); + VALUE v; + + v = str_new(buf, len); + + return v; +} + +static VALUE +r_object(fp, table) FILE *fp; - VALUE port; st_table *table; { VALUE v; int type = r_byte(fp); - int id; switch (type) { case EOF: - Fail("EOF read where object expected"); + eof_error("EOF read where object expected"); return Qnil; case TYPE_NIL: return Qnil; - case TYPE_LINK: - if (st_lookup(table, r_long(fp), &v)) { - return v; - } - Fail("corrupted marshal file"); - break; + case TYPE_TRUE: + return TRUE; + + case TYPE_FALSE: + return FALSE; case TYPE_FIXNUM: { int i = r_long(fp); return INT2FIX(i); } - } - id = r_long(fp); - switch (type) { case TYPE_FLOAT: { double atof(); @@ -378,9 +545,8 @@ r_object(fp, port, table) r_bytes(buf, fp); v = float_new(atof(buf)); - free(buf); + return v; } - break; case TYPE_BIGNUM: { @@ -395,18 +561,16 @@ r_object(fp, port, table) while (len--) { *digits++ = r_short(fp); } - v = (VALUE)big; + return (VALUE)big; } - break; case TYPE_STRING: - { - char *buf; - int len = r_bytes(buf, fp); - v = str_new(buf, len); - free(buf); - } - break; + return r_string(fp); + + case TYPE_STRING2: + v = r_string(fp); + RBASIC(v)->class = rb_path2class(r_unique(fp, table)); + return v; case TYPE_REGEXP: { @@ -414,19 +578,18 @@ r_object(fp, port, table) int len = r_bytes(buf, fp); int ci = r_byte(fp); v = reg_new(buf, len, ci); - free(buf); + return v; } - break; case TYPE_ARRAY: { int len = r_long(fp); v = ary_new2(len); while (len--) { - ary_push(v, r_object(fp, port, table)); + ary_push(v, r_object(fp, table)); } + return v; } - break; case TYPE_HASH: { @@ -434,120 +597,150 @@ r_object(fp, port, table) v = hash_new(); while (len--) { - VALUE key = r_object(fp, port, table); - VALUE value = r_object(fp, port, table); + VALUE key = r_object(fp, table); + VALUE value = r_object(fp, table); hash_aset(v, key, value); } + return v; } - break; case TYPE_STRUCT: { VALUE class, mem, values; - char *path; int i, len; - r_bytes(path, fp); - class = rb_path2class(path); - free(path); + class = rb_path2class(r_unique(fp, table)); mem = rb_ivar_get(class, rb_intern("__member__")); if (mem == Qnil) { - Fail("non-initialized struct"); + Fatal("non-initialized struct"); } len = r_long(fp); - values = ary_new(); + values = ary_new2(len); i = 0; - while (len--) { - ID slot = r_symbol(fp); - if (RARRAY(mem)->ptr[i++] != INT2FIX(slot)) - Fail("struct not compatible"); - ary_push(values, r_object(fp, port, table)); + for (i=0; i<len; i++) { + ID slot = r_symbol(fp, table); + if (RARRAY(mem)->ptr[i] != INT2FIX(slot)) + TypeError("struct not compatible"); + ary_push(values, r_object(fp, table)); } v = struct_alloc(class, values); } break; + case TYPE_USERDEF: + { + VALUE class; + int len; + + class = rb_path2class(r_unique(fp, table)); + if (rb_respond_to(class, s_load)) { + v = rb_funcall(class, s_load, 1, r_string(fp)); + } + else { + TypeError("class %s needs to have method `_load_from'", + rb_class2name(class)); + } + } + break; case TYPE_OBJECT: { VALUE class; int len; - char *path; - r_bytes(path, fp); - class = rb_path2class(path); - free(path); + class = rb_path2class(r_unique(fp, table)); len = r_long(fp); - if (len == -1) { - if (rb_responds_to(class, s_load)) { - v = rb_funcall(class, s_load, 1, port); - } - else { - Fail("class %s needs to have method `_load_from'", - rb_class2name(class)); - } - } - else { - v = obj_alloc(class); - if (len > 0) { - while (len--) { - ID id = r_symbol(fp); - VALUE val = r_object(fp, port, table); - rb_ivar_set(v, id, val); - } + v = obj_alloc(class); + if (len > 0) { + while (len--) { + ID id = r_symbol(fp, table); + VALUE val = r_object(fp, table); + rb_ivar_set(v, id, val); } } } break; default: - Fail("dump format error(0x%x)", type); + ArgError("dump format error(0x%x)", type); break; } - st_insert(table, id, v); return v; } +struct load_arg { + FILE *fp; + st_table *table; +}; + +static VALUE +load(arg) + struct load_arg *arg; +{ + return r_object(arg->fp, arg->table); +} + +static VALUE +load_ensure(arg) + struct load_arg *arg; +{ + st_free_table(arg->table); +} + static VALUE marshal_load(self, port) VALUE self, port; { extern VALUE cIO; - void *fp; + FILE *fp; + int major; VALUE v; OpenFile *fptr; - st_table *table; + char buf[32]; +#if defined(MSDOS) || defined(__BOW__) + int need_unlink_tmp = 0; +#endif + struct load_arg arg; if (TYPE(port) == T_STRING) { - char buf[32]; - - sprintf(buf, "/tmp/rb-mrsw-%x", getpid()^(int)buf); - fp = fopen(buf, "w"); - if (!fp) rb_sys_fail("tmp file"); + tmpnam(buf); + fp = rb_fopen(buf, "w"); v = file_open(buf, "r"); - if (!v) rb_sys_fail("tmp file(read)"); +#if defined(MSDOS) || defined(__BOW__) + need_unlink_tmp = 0; +#else unlink(buf); +#endif fwrite(RSTRING(port)->ptr, RSTRING(port)->len, 1, fp); fclose(fp); port = v; } + if (obj_is_kind_of(port, cIO)) { GetOpenFile(port, fptr); - if (!(fptr->mode & FMODE_READABLE)) { - Fail("not opened for reading"); - } + io_readable(fptr); fp = fptr->f; } else { - Fail("instance of IO needed"); + TypeError("instance of IO needed"); } - table = new_idhash(); - - v = r_object(fp, port, table); - - st_free_table(table); + major = r_byte(fp); + if (major == MARSHAL_MAJOR) { + if (r_byte(fp) != MARSHAL_MINOR) { + Warning("Old marshal file format (can be read)"); + } + arg.fp = fp; + arg.table = st_init_numtable(); + v = rb_ensure(load, &arg, load_ensure, &arg); + } +#if defined(MSDOS) || defined(__BOW__) + if (need_unlink_tmp) unlink(buf); +#endif + if (major != MARSHAL_MAJOR) { + TypeError("Old marshal file format (can't read)"); + } return v; } @@ -558,8 +751,8 @@ Init_marshal() s_dump = rb_intern("_dump_to"); s_load = rb_intern("_load_from"); - rb_define_module_function(mMarshal, "dump", marshal_dump, 2); - rb_define_module_function(mMarshal, "dumps", marshal_dumps, 1); + rb_define_module_function(mMarshal, "dump", marshal_dump, -1); + rb_define_module_function(mMarshal, "dumps", marshal_dumps, -1); rb_define_module_function(mMarshal, "load", marshal_load, 1); rb_define_module_function(mMarshal, "restore", marshal_load, 1); } diff --git a/ext/marshal/marshal.doc b/ext/marshal/marshal.doc index 8c3b63072e..7529e7942f 100644 --- a/ext/marshal/marshal.doc +++ b/ext/marshal/marshal.doc @@ -10,7 +10,7 @@ ruby¥ª¥Ö¥¸¥§¥¯¥È¤ò¥Õ¥¡¥¤¥ë¤Ë½ñ¤½Ð¤·¤¿¤ê¡¤ÆÉ¤ß¤âÅÙ¤·¤¿¤ê¤¹¤ëµ¡Ç½¤òÄó¶¡ Methods: Single Methods: - dump(obj, port) + dump(obj, port[, limit]) obj¤òºÆµ¢Åª¤Ë¥Õ¥¡¥¤¥ë¤Ë½ñ¤½Ð¤¹¡¥¥Õ¥¡¥¤¥ë¤Ë½ñ¤½Ð¤»¤Ê¤¤¥¯¥é¥¹¤Î¥¤ ¥ó¥¹¥¿¥ó¥¹¤ò¥Õ¥¡¥¤¥ë¤Ë½ñ¤½Ð¤½¤¦¤È¤¹¤ë¤ÈÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥¥Õ¥¡¥¤¥ë @@ -28,6 +28,9 @@ Single Methods: `_dump_to'¤ò»ý¤Ä¥¯¥é¥¹¤Ïɬ¤ºÆ±¤¸¥Õ¥©¡¼¥Þ¥Ã¥È¤òÆÉ¤ßÌ᤹ÆÃ°Û¥á¥½¥Ã¥É `_load_from'¤òÄêµÁ¤¹¤ëɬÍפ¬¤¢¤ë¡¥ + limit¤ò»ØÄꤷ¤¿¾ì¹ç¡¤limitÃʰʾ忼¤¯¥ê¥ó¥¯¤·¤¿¥ª¥Ö¥¸¥§¥¯¥È¤ò¥À¥ó¥× + ¤Ç¤¤Ê¤¤(¥Ç¥Õ¥©¥ë¥È¤Ï100¥ì¥Ù¥ë)¡£Éé¤Îlimit¤ò»ØÄꤹ¤ë¤È¿¼¤µ¥Á¥§¥Ã¥¯ + ¤ò¹Ô¤ï¤Ê¤¤¡£ dumps(obj) diff --git a/ext/md5/MANIFEST b/ext/md5/MANIFEST new file mode 100644 index 0000000000..e4f0004b4a --- /dev/null +++ b/ext/md5/MANIFEST @@ -0,0 +1,6 @@ +MANIFEST +depend +md5.doc +md5.h +md5c.c +md5init.c diff --git a/ext/md5/depend b/ext/md5/depend new file mode 100644 index 0000000000..be56da89b9 --- /dev/null +++ b/ext/md5/depend @@ -0,0 +1,2 @@ +md5c.o: md5c.c md5.h +md5init.o: md5init.c ../../ruby.h ../../config.h ../../defines.h md5.h diff --git a/ext/md5/md5.doc b/ext/md5/md5.doc new file mode 100644 index 0000000000..2203404602 --- /dev/null +++ b/ext/md5/md5.doc @@ -0,0 +1,36 @@ +.\" md5.doc - -*- Indented-Text -*- created at: Fri Aug 2 12:01:27 JST 1996 + +** MD5(¥¯¥é¥¹) + +RFC1321¤Ëµ½Ò¤µ¤ì¤Æ¤¤¤ëRSA Data Security, Inc. ¤Î MD5 Message-Digest +Algorithm¤ò¼ÂÁõ¤¹¤ë¥¯¥é¥¹¡¥ + +SuperClass: Object + +Class Methods: + + new([str]) + md5([str]) + + ¿·¤·¤¤MD5¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤¹¤ë¡¥Ê¸»úÎó°ú¿ô¤¬Í¿¤¨¤é¤ì¤ë¤È¤½¤ì + ¤òÄɲ乤ë(see update)¡¥ + +Methods: + + clone + + MD5¥ª¥Ö¥¸¥§¥¯¥È¤ÎÊ£À½¤òºî¤ë + + digest + + º£¤Þ¤Ç¤ËÄɲä·¤¿Ê¸»úÎó¤ËÂФ¹¤ë¥Ï¥Ã¥·¥åÃͤò16¥Ð¥¤¥ÈŤÎʸ»úÎó¤Ç + ÊÖ¤¹¡¥ + + update(str) + + key¤ò¥¡¼¤È¤¹¤ëÃͤòÊÖ¤¹¡¥ + +------------------------------------------------------- +Local variables: +fill-column: 70 +end: diff --git a/ext/md5/md5.h b/ext/md5/md5.h new file mode 100644 index 0000000000..81a6d7ff36 --- /dev/null +++ b/ext/md5/md5.h @@ -0,0 +1,86 @@ +/* MD5.H - header file for MD5C.C + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +/* ========== include global.h ========== */ +/* GLOBAL.H - RSAREF types and constants + */ + +/* PROTOTYPES should be set to one if and only if the compiler supports + function argument prototyping. +The following makes PROTOTYPES default to 0 if it has not already + been defined with C compiler flags. + */ +#ifdef HAVE_PROTOTYPES +#define PROTOTYPES 1 +#endif +#ifndef PROTOTYPES +#define PROTOTYPES 0 +#endif + +/* POINTER defines a generic pointer type */ +typedef unsigned char *POINTER; + +/* UINT2 defines a two byte word */ +typedef unsigned short int UINT2; + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#else +/* Wild guess */ +#define LONG_MAX 2147483647L +#endif + +/* UINT4 defines a four byte word */ +#if defined(INT_MAX) && INT_MAX == 2147483647 +typedef unsigned int UINT4; +#else +#if defined(LONG_MAX) && LONG_MAX == 2147483647L +typedef unsigned long int UINT4; +#endif +/* Too bad if neither is */ +#endif + +/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. +If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it + returns an empty list. + */ +#if PROTOTYPES +#define PROTO_LIST(list) list +#else +#define PROTO_LIST(list) () +#endif +/* ========== End global.h; continue md5.h ========== */ + +/* MD5 context. */ +typedef struct { + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} MD5_CTX; + +void MD5Init PROTO_LIST ((MD5_CTX *)); +void MD5Update PROTO_LIST + ((MD5_CTX *, unsigned char *, unsigned int)); +void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); diff --git a/ext/md5/md5c.c b/ext/md5/md5c.c new file mode 100644 index 0000000000..d7c7e4fb27 --- /dev/null +++ b/ext/md5/md5c.c @@ -0,0 +1,337 @@ +/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "md5.h" + +/* Constants for MD5Transform routine. + */ + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); +static void Encode PROTO_LIST + ((unsigned char *, UINT4 *, unsigned int)); +static void Decode PROTO_LIST + ((UINT4 *, unsigned char *, unsigned int)); +static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int)); +static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); + +static unsigned char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G, H and I are basic MD5 functions. + */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. + */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +Rotation is separate from addition to prevent recomputation. + */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. + */ +void MD5Init (context) +MD5_CTX *context; /* context */ +{ + context->count[0] = context->count[1] = 0; + /* Load magic initialization constants. +*/ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* MD5 block update operation. Continues an MD5 message-digest + operation, processing another message block, and updating the + context. + */ +void MD5Update (context, input, inputLen) +MD5_CTX *context; /* context */ +unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +{ + unsigned int i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (unsigned int)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((UINT4)inputLen << 3)) + < ((UINT4)inputLen << 3)) + context->count[1]++; + context->count[1] += ((UINT4)inputLen >> 29); + + partLen = 64 - index; + + /* Transform as many times as possible. +*/ + if (inputLen >= partLen) { + MD5_memcpy + ((POINTER)&context->buffer[index], (POINTER)input, partLen); + MD5Transform (context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform (context->state, &input[i]); + + index = 0; + } + else + i = 0; + + /* Buffer remaining input */ + MD5_memcpy + ((POINTER)&context->buffer[index], (POINTER)&input[i], + inputLen-i); +} + +/* MD5 finalization. Ends an MD5 message-digest operation, writing the + the message digest and zeroizing the context. + */ +void MD5Final (digest, context) +unsigned char digest[16]; /* message digest */ +MD5_CTX *context; /* context */ +{ + unsigned char bits[8]; + unsigned int index, padLen; + + /* Save number of bits */ + Encode (bits, context->count, 8); + + /* Pad out to 56 mod 64. +*/ + index = (unsigned int)((context->count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + MD5Update (context, PADDING, padLen); + + /* Append length (before padding) */ + MD5Update (context, bits, 8); + + /* Store state in digest */ + Encode (digest, context->state, 16); + + /* Zeroize sensitive information. +*/ + MD5_memset ((POINTER)context, 0, sizeof (*context)); +} + +/* MD5 basic transformation. Transforms state based on block. + */ +static void MD5Transform (state, block) +UINT4 state[4]; +unsigned char block[64]; +{ + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode (x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. +*/ + MD5_memset ((POINTER)x, 0, sizeof (x)); +} + +/* Encodes input (UINT4) into output (unsigned char). Assumes len is + a multiple of 4. + */ +static void Encode (output, input, len) +unsigned char *output; +UINT4 *input; +unsigned int len; +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + +/* Decodes input (unsigned char) into output (UINT4). Assumes len is + a multiple of 4. + */ +static void Decode (output, input, len) +UINT4 *output; +unsigned char *input; +unsigned int len; +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | + (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); +} + +/* Note: Replace "for loop" with standard memcpy if possible. + */ + +static void MD5_memcpy (output, input, len) +POINTER output; +POINTER input; +unsigned int len; +{ + unsigned int i; + + for (i = 0; i < len; i++) + output[i] = input[i]; +} + +/* Note: Replace "for loop" with standard memset if possible. + */ +static void MD5_memset (output, value, len) +POINTER output; +int value; +unsigned int len; +{ + unsigned int i; + + for (i = 0; i < len; i++) + ((char *)output)[i] = (char)value; +} diff --git a/ext/md5/md5init.c b/ext/md5/md5init.c new file mode 100644 index 0000000000..85f0847e71 --- /dev/null +++ b/ext/md5/md5init.c @@ -0,0 +1,90 @@ +/************************************************ + + md5init.c - + + $Author: matz $ + created at: Fri Aug 2 09:24:12 JST 1996 + + Copyright (C) 1995 Yukihiro Matsumoto + +************************************************/ +/* This module provides an interface to the RSA Data Security, + Inc. MD5 Message-Digest Algorithm, described in RFC 1321. + It requires the files md5c.c and md5.h (which are slightly changed + from the versions in the RFC to avoid the "global.h" file.) */ + +#include "ruby.h" +#include "md5.h" + +static VALUE cMD5; + +static VALUE +md5_update(obj, str) + VALUE obj; + struct RString *str; +{ + MD5_CTX *md5; + + Check_Type(str, T_STRING); + Get_Data_Struct(obj, MD5_CTX, md5); + MD5Update(md5, str->ptr, str->len); + + return Qnil; +} +static VALUE +md5_digest(obj) + VALUE obj; +{ + MD5_CTX *md5, ctx; + unsigned char digest[16]; + + Get_Data_Struct(obj, MD5_CTX, md5); + ctx = *md5; + MD5Final(digest, &ctx); + + return str_new(digest, 16); +} + +static VALUE +md5_clone(obj) + VALUE obj; +{ + VALUE clone; + MD5_CTX *md5, *md5_new; + + Get_Data_Struct(obj, MD5_CTX, md5); + obj = Make_Data_Struct(CLASS_OF(obj), MD5_CTX, 0, 0, md5_new); + *md5_new = *md5; + + return obj; +} + +static VALUE +md5_new(argc, argv, class) +{ + int i; + VALUE arg, obj; + MD5_CTX *md5; + + rb_scan_args(argc, argv, "01", &arg); + if (!NIL_P(arg)) Check_Type(arg, T_STRING); + + obj = Make_Data_Struct(class, MD5_CTX, 0, 0, md5); + MD5Init(md5); + if (!NIL_P(arg)) { + md5_update(obj, arg); + } + + return obj; +} + +Init_md5() +{ + cMD5 = rb_define_class("MD5", cObject); + + rb_define_singleton_method(cMD5, "new", md5_new, -1); + + rb_define_method(cMD5, "update", md5_update, 1); + rb_define_method(cMD5, "digest", md5_digest, 0); + rb_define_method(cMD5, "clone", md5_clone, 0); +} diff --git a/ext/socket/MANIFEST b/ext/socket/MANIFEST index 836caada41..d41d9e0b69 100644 --- a/ext/socket/MANIFEST +++ b/ext/socket/MANIFEST @@ -2,4 +2,3 @@ MANIFEST depend extconf.rb socket.c -socket.doc diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb index 60d6deeb84..f2ec0578d5 100644 --- a/ext/socket/extconf.rb +++ b/ext/socket/extconf.rb @@ -1,6 +1,11 @@ -have_library("inet", "gethostbyname") have_library("socket", "socket") +have_library("inet", "gethostbyname") +have_library("nsl", "gethostbyname") have_header("sys/un.h") if have_func("socket") + have_func("hsterror") + unless have_func("gethostname") + have_func("uname") + end create_makefile("socket") end diff --git a/ext/socket/socket.c b/ext/socket/socket.c index 5671b2762c..6b4f0f5559 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -18,11 +18,11 @@ #include <errno.h> #ifdef HAVE_SYS_UN_H #include <sys/un.h> -#else -#undef AF_UNIX #endif extern VALUE cIO; +extern VALUE cInteger; + VALUE cBasicSocket; VALUE cTCPsocket; VALUE cTCPserver; @@ -32,6 +32,9 @@ VALUE cUNIXserver; #endif VALUE cSocket; +extern VALUE eException; +static VALUE eSocket; + FILE *rb_fdopen(); char *strdup(); @@ -52,8 +55,9 @@ sock_new(class, fd) VALUE class; int fd; { - VALUE sock = obj_alloc(class); OpenFile *fp; + NEWOBJ(sock, struct RFile); + OBJSETUP(sock, class, T_FILE); MakeOpenFile(sock, fp); #ifdef NT @@ -64,7 +68,7 @@ sock_new(class, fd) fp->f2 = rb_fdopen(fd, "w"); fp->mode = FMODE_READWRITE|FMODE_SYNC; - return sock; + return (VALUE)sock; } static VALUE @@ -86,34 +90,53 @@ bsock_shutdown(argc, argv, sock) } GetOpenFile(sock, fptr); if (shutdown(fileno(fptr->f), how) == -1) - rb_sys_fail(Qnil); + rb_sys_fail(0); return INT2FIX(0); } static VALUE -bsock_setopt(sock, lev, optname, val) +bsock_setsockopt(sock, lev, optname, val) VALUE sock, lev, optname; struct RString *val; { int level, option; OpenFile *fptr; + int i; + char *v; + int vlen; level = NUM2INT(lev); option = NUM2INT(optname); - Check_Type(val, T_STRING); + switch (TYPE(val)) { + case T_FIXNUM: + i = FIX2INT(val); + goto numval; + case T_FALSE: + i = 0; + goto numval; + case T_TRUE: + i = 1; + numval: + v = (char*)&i; vlen = sizeof(i); + break; + default: + Check_Type(val, T_STRING); + v = val->ptr; vlen = val->len; + } GetOpenFile(sock, fptr); - if (setsockopt(fileno(fptr->f), level, option, val->ptr, val->len) < 0) + if (setsockopt(fileno(fptr->f), level, option, v, vlen) < 0) rb_sys_fail(fptr->path); return INT2FIX(0); } static VALUE -bsock_getopt(sock, lev, optname) +bsock_getsockopt(sock, lev, optname) VALUE sock, lev, optname; { +#if !defined(__CYGWIN32__) int level, option, len; struct RString *val; OpenFile *fptr; @@ -128,7 +151,11 @@ bsock_getopt(sock, lev, optname) if (getsockopt(fileno(fptr->f), level, option, val->ptr, &len) < 0) rb_sys_fail(fptr->path); val->len = len; + return (VALUE)val; +#else + rb_notimplement(); +#endif } static VALUE @@ -184,8 +211,14 @@ open_inet(class, h, serv, server) if (hostaddr == -1) { if (server && !strlen(host)) hostaddr = INADDR_ANY; - else - rb_sys_fail(host); + else { +#ifdef HAVE_HSTRERROR + extern int h_errno; + Raise(eSocket, (char *)hstrerror(h_errno)); +#else + Raise(eSocket, "host not found"); +#endif + } } _hostent.h_addr_list = (char **)hostaddrPtr; _hostent.h_addr_list[0] = (char *)&hostaddr; @@ -203,27 +236,31 @@ open_inet(class, h, serv, server) Check_Type(serv, T_STRING); servent = getservbyname(RSTRING(serv)->ptr, "tcp"); if (servent == NULL) { - servport = strtoul(RSTRING(serv)->ptr, Qnil, 0); - if (servport == -1) Fail("no such servce %s", RSTRING(serv)->ptr); + servport = strtoul(RSTRING(serv)->ptr, 0, 0); + if (servport == -1) { + Raise(eSocket, "no such servce %s", RSTRING(serv)->ptr); + } setup_servent: - _servent.s_port = servport; - _servent.s_proto = "tcp"; + _servent.s_port = htons(servport); + _servent.s_proto = "tcp"; servent = &_servent; } protoent = getprotobyname(servent->s_proto); - if (protoent == NULL) Fail("no such proto %s", servent->s_proto); + if (protoent == NULL) { + Raise(eSocket, "no such proto %s", servent->s_proto); + } fd = socket(PF_INET, SOCK_STREAM, protoent->p_proto); sockaddr.sin_family = AF_INET; - if (h == Qnil) { - sockaddr.sin_addr.s_addr = INADDR_ANY; - } - else { + if (h) { memcpy((char *)&(sockaddr.sin_addr.s_addr), (char *) hostent->h_addr_list[0], (size_t) hostent->h_length); } + else { + sockaddr.sin_addr.s_addr = INADDR_ANY; + } sockaddr.sin_port = servent->s_port; if (server) { @@ -248,7 +285,7 @@ open_inet(class, h, serv, server) } static VALUE -tcp_s_sock_open(class, host, serv) +tcp_s_open(class, host, serv) VALUE class, host, serv; { Check_Type(host, T_STRING); @@ -266,7 +303,7 @@ tcp_svr_s_open(argc, argv, class) if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) return open_inet(class, arg1, arg2, 1); else - return open_inet(class, Qnil, arg1, 1); + return open_inet(class, 0, arg1, 1); } static VALUE @@ -279,10 +316,15 @@ s_accept(class, fd, sockaddr, len) int fd2; retry: +#ifdef THREAD + thread_wait_fd(fd); +#endif + TRAP_BEG; fd2 = accept(fd, sockaddr, len); + TRAP_END; if (fd2 < 0) { if (errno == EINTR) goto retry; - rb_sys_fail(Qnil); + rb_sys_fail(0); } return sock_new(class, fd2); } @@ -301,7 +343,7 @@ tcp_accept(sock) (struct sockaddr*)&from, &fromlen); } -#ifdef AF_UNIX +#ifdef HAVE_SYS_UN_H static VALUE open_unix(class, path, server) VALUE class; @@ -346,11 +388,63 @@ open_unix(class, path, server) } #endif +static void +setipaddr(name, addr) + char *name; + struct sockaddr_in *addr; +{ + int d1, d2, d3, d4; + char ch; + struct hostent *hp; + long x; + unsigned char *a; + char buf[16]; + + if (name[0] == 0) { + addr->sin_addr.s_addr = INADDR_ANY; + } + else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) { + addr->sin_addr.s_addr = INADDR_BROADCAST; + } + else if (sscanf(name, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 && + 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 && + 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) { + addr->sin_addr.s_addr = htonl( + ((long) d1 << 24) | ((long) d2 << 16) | + ((long) d3 << 8) | ((long) d4 << 0)); + } + else { + hp = gethostbyname(name); + if (!hp) { +#ifdef HAVE_HSTRERROR + extern int h_errno; + Raise(eSocket, (char *)hstrerror(h_errno)); +#else + Raise(eSocket, "host not found"); +#endif + } + memcpy((char *) &addr->sin_addr, hp->h_addr, hp->h_length); + } +} + +static VALUE +mkipaddr(x) + unsigned long x; +{ + char buf[16]; + + x = ntohl(x); + sprintf(buf, "%d.%d.%d.%d", + (int) (x>>24) & 0xff, (int) (x>>16) & 0xff, + (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff); + return str_new2(buf); +} + static VALUE tcpaddr(sockaddr) struct sockaddr_in *sockaddr; { - VALUE family, port, addr; + VALUE family, port, addr1, addr2; VALUE ary; struct hostent *hostent; @@ -358,17 +452,15 @@ tcpaddr(sockaddr) hostent = gethostbyaddr((char*)&sockaddr->sin_addr.s_addr, sizeof(sockaddr->sin_addr), AF_INET); + addr1 = 0; if (hostent) { - addr = str_new2(hostent->h_name); + addr1 = str_new2(hostent->h_name); } - else { - char buf[16]; - char *a = (char*)&sockaddr->sin_addr; - sprintf(buf, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]); - addr = str_new2(buf); - } - port = INT2FIX(sockaddr->sin_port); - ary = ary_new3(3, family, port, addr); + addr2 = mkipaddr(sockaddr->sin_addr.s_addr); + if (!addr1) addr1 = addr2; + + port = INT2FIX(ntohs(sockaddr->sin_port)); + ary = ary_new3(4, family, port, addr1, addr2); return ary; } @@ -399,11 +491,30 @@ tcp_peeraddr(sock) GetOpenFile(sock, fptr); if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) - rb_sys_fail("getsockname(2)"); + rb_sys_fail("getpeername(2)"); return tcpaddr(&addr); } -#ifdef AF_UNIX +static VALUE +tcp_s_getaddress(obj, host) + VALUE obj, host; +{ + struct sockaddr_in addr; + struct hostent *h; + + if (obj_is_kind_of(host, cInteger)) { + int i = NUM2INT(host); + addr.sin_addr.s_addr = htonl(i); + } + else { + Check_Type(host, T_STRING); + setipaddr(RSTRING(host)->ptr, &addr); + } + + return mkipaddr(addr.sin_addr.s_addr); +} + +#ifdef HAVE_SYS_UN_H static VALUE unix_s_sock_open(sock, path) VALUE sock, path; @@ -418,11 +529,11 @@ unix_path(sock) OpenFile *fptr; GetOpenFile(sock, fptr); - if (fptr->path == Qnil) { + if (fptr->path == 0) { struct sockaddr_un addr; int len = sizeof(addr); if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) - rb_sys_fail(Qnil); + rb_sys_fail(0); fptr->path = strdup(addr.sun_path); } return str_new2(fptr->path); @@ -515,7 +626,7 @@ setup_domain_and_type(domain, dv, type, tv) *dv = PF_IPX; #endif else - Fail("Unknown socket domain %s", ptr); + Raise(eSocket, "Unknown socket domain %s", ptr); } else { *dv = NUM2INT(domain); @@ -543,7 +654,7 @@ setup_domain_and_type(domain, dv, type, tv) *tv = SOCK_PACKET; #endif else - Fail("Unknown socket type %s", ptr); + Raise(eSocket, "Unknown socket type %s", ptr); } else { *tv = NUM2INT(type); @@ -559,7 +670,7 @@ sock_s_open(class, domain, type, protocol) setup_domain_and_type(domain, &d, type, &t); fd = socket(d, t, NUM2INT(protocol)); - if (fd < 0) rb_sys_fail("socke(2)"); + if (fd < 0) rb_sys_fail("socket(2)"); return sock_new(class, fd); } @@ -574,6 +685,7 @@ static VALUE sock_s_socketpair(class, domain, type, protocol) VALUE class, domain, type, protocol; { +#if !defined(__CYGWIN32__) int fd; int d, t, sp[2]; @@ -582,6 +694,9 @@ sock_s_socketpair(class, domain, type, protocol) rb_sys_fail("socketpair(2)"); return assoc_new(sock_new(class, sp[0]), sock_new(class, sp[1])); +#else + rb_notimplement(); +#endif } static VALUE @@ -665,6 +780,9 @@ sock_send(argc, argv, sock) GetOpenFile(sock, fptr); f = fptr->f2?fptr->f2:fptr->f; fd = fileno(f); +#ifdef THREAD + thread_fd_writable(fd); +#endif if (to) { Check_Type(to, T_STRING); n = sendto(fd, msg->ptr, msg->len, NUM2INT(flags), @@ -703,8 +821,15 @@ s_recv(sock, argc, argv, from) GetOpenFile(sock, fptr); fd = fileno(fptr->f); - if ((str->len = recvfrom(fd, str->ptr, str->len, flags, - (struct sockaddr*)buf, &alen)) < 0) { +#ifdef THREAD + thread_wait_fd(fd); +#endif + TRAP_BEG; + str->len = recvfrom(fd, str->ptr, str->len, flags, + (struct sockaddr*)buf, &alen); + TRAP_END; + + if (str->len < 0) { rb_sys_fail("recvfrom(2)"); } @@ -732,28 +857,173 @@ sock_recvfrom(argc, argv, sock) return s_recv(sock, argc, argv, 1); } +#ifdef HAVE_GETHOSTNAME +static VALUE +sock_gethostname(obj) + VALUE obj; +{ + char buf[1024]; + + if (gethostname(buf, (int)sizeof buf - 1) < 0) + rb_sys_fail("gethostname"); + + buf[sizeof buf - 1] = '\0'; + return str_new2(buf); +} +#else +#ifdef HAVE_UNAME + +#include <sys/utsname.h> + +static VALUE +sock_gethostname(obj) + VALUE obj; +{ + struct utsname un; + + uname(&un); + return str_new2(un.nodename); +} +#else +static VALUE +sock_gethostname(obj) + VALUE obj; +{ + rb_notimplement(); +} +#endif +#endif + +static VALUE +mkhostent(h) + struct hostent *h; +{ + struct sockaddr_in addr; + char **pch; + VALUE ary, names; + + if (h == NULL) { +#ifdef HAVE_HSTRERROR + extern int h_errno; + Raise(eSocket, (char *)hstrerror(h_errno)); +#else + Raise(eSocket, "host not found"); +#endif + } + ary = ary_new(); + ary_push(ary, str_new2(h->h_name)); + names = ary_new(); + ary_push(ary, names); + for (pch = h->h_aliases; *pch; pch++) { + ary_push(names, str_new2(*pch)); + } + ary_push(ary, INT2FIX(h->h_length)); +#ifdef h_addr + for (pch = h->h_addr_list; *pch; pch++) { + ary_push(ary, str_new(*pch, h->h_length)); + } +#else + ary_push(ary, str_new(h->h_addr, h->h_length)); +#endif + + return ary; +} + +static VALUE +sock_s_gethostbyname(obj, host) + VALUE obj, host; +{ + struct sockaddr_in addr; + struct hostent *h; + + if (obj_is_kind_of(host, cInteger)) { + int i = NUM2INT(host); + addr.sin_addr.s_addr = htonl(i); + } + else { + Check_Type(host, T_STRING); + setipaddr(RSTRING(host)->ptr, &addr); + } + h = gethostbyaddr((char *)&addr.sin_addr, + sizeof(addr.sin_addr), + AF_INET); + + return mkhostent(h); +} + +sock_s_gethostbyaddr(argc, argv) + int argc; + VALUE *argv; +{ + VALUE vaddr, vtype; + int type; + + struct sockaddr_in *addr; + struct hostent *h; + + rb_scan_args(argc, argv, "11", &addr, &type); + Check_Type(addr, T_STRING); + if (!NIL_P(type)) { + type = NUM2INT(vtype); + } + else { + type = AF_INET; + } + + h = gethostbyaddr(RSTRING(addr)->ptr, RSTRING(addr)->len, type); + + return mkhostent(h); +} + +static VALUE +sock_s_getservbyaname(argc, argv) + int argc; + VALUE *argv; +{ + VALUE service, protocol; + char *name, *proto; + struct servent *sp; + int port; + + rb_scan_args(argc, argv, "11", &service, &protocol); + Check_Type(service, T_STRING); + if (NIL_P(protocol)) proto = "tcp"; + else proto = RSTRING(protocol)->ptr; + + sp = getservbyname(RSTRING(service)->ptr, proto); + if (!sp) { + Raise(eSocket, "service/proto not found"); + } + port = ntohs(sp->s_port); + + return INT2FIX(port); +} + Init_socket () { + eSocket = rb_define_class("SocketError", eException); + cBasicSocket = rb_define_class("BasicSocket", cIO); rb_undef_method(cBasicSocket, "new"); rb_define_method(cBasicSocket, "shutdown", bsock_shutdown, -1); - rb_define_method(cBasicSocket, "setopt", bsock_setopt, 3); - rb_define_method(cBasicSocket, "getopt", bsock_getopt, 2); + rb_define_method(cBasicSocket, "setsockopt", bsock_setsockopt, 3); + rb_define_method(cBasicSocket, "getsockopt", bsock_getsockopt, 2); rb_define_method(cBasicSocket, "getsockname", bsock_getsockname, 0); rb_define_method(cBasicSocket, "getpeername", bsock_getpeername, 0); cTCPsocket = rb_define_class("TCPsocket", cBasicSocket); - rb_define_singleton_method(cTCPsocket, "open", tcp_s_sock_open, 2); - rb_define_singleton_method(cTCPsocket, "new", tcp_s_sock_open, 2); + rb_define_singleton_method(cTCPsocket, "open", tcp_s_open, 2); + rb_define_singleton_method(cTCPsocket, "new", tcp_s_open, 2); rb_define_method(cTCPsocket, "addr", tcp_addr, 0); rb_define_method(cTCPsocket, "peeraddr", tcp_peeraddr, 0); + rb_define_singleton_method(cTCPsocket, "getaddress", tcp_s_getaddress, 1); cTCPserver = rb_define_class("TCPserver", cTCPsocket); rb_define_singleton_method(cTCPserver, "open", tcp_svr_s_open, -1); rb_define_singleton_method(cTCPserver, "new", tcp_svr_s_open, -1); rb_define_method(cTCPserver, "accept", tcp_accept, 0); -#ifdef AF_UNIX +#ifdef HAVE_SYS_UN_H cUNIXsocket = rb_define_class("UNIXsocket", cBasicSocket); rb_define_singleton_method(cUNIXsocket, "open", unix_s_sock_open, 1); rb_define_singleton_method(cUNIXsocket, "new", unix_s_sock_open, 1); @@ -782,4 +1052,64 @@ Init_socket () rb_define_method(cSocket, "recvfrom", sock_recv, -1); rb_define_singleton_method(cSocket, "socketpair", sock_s_socketpair, 3); + rb_define_singleton_method(cSocket, "pair", sock_s_socketpair, 3); + rb_define_singleton_method(cSocket, "gethostname", sock_gethostname, 0); + rb_define_singleton_method(cSocket, "gethostbyname", sock_s_gethostbyname, 1); + rb_define_singleton_method(cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1); + rb_define_singleton_method(cSocket, "getservbyname", sock_s_getservbyaname, -1); + + /* constants */ + rb_define_const(cSocket, "AF_INET", INT2FIX(AF_INET)); + rb_define_const(cSocket, "PF_INET", INT2FIX(PF_INET)); +#ifdef AF_UNIX + rb_define_const(cSocket, "AF_UNIX", INT2FIX(AF_UNIX)); + rb_define_const(cSocket, "PF_UNIX", INT2FIX(PF_UNIX)); +#endif +#ifdef AF_IPX + rb_define_const(cSocket, "AF_IPX", INT2FIX(AF_IPX)); + rb_define_const(cSocket, "PF_IPX", INT2FIX(PF_IPX)); +#endif +#ifdef AF_APPLETALK + rb_define_const(cSocket, "AF_APPLETALK", INT2FIX(AF_APPLETALK)); + rb_define_const(cSocket, "PF_APPLETALK", INT2FIX(PF_APPLETALK)); +#endif + + rb_define_const(cSocket, "MSG_OOB", INT2FIX(MSG_OOB)); + rb_define_const(cSocket, "MSG_PEEK", INT2FIX(MSG_PEEK)); + rb_define_const(cSocket, "MSG_DONTROUTE", INT2FIX(MSG_DONTROUTE)); + + rb_define_const(cSocket, "SOCK_STREAM", INT2FIX(SOCK_STREAM)); + rb_define_const(cSocket, "SOCK_DGRAM", INT2FIX(SOCK_DGRAM)); + rb_define_const(cSocket, "SOCK_RAW", INT2FIX(SOCK_RAW)); +#ifdef SOCK_RDM + rb_define_const(cSocket, "SOCK_RDM", INT2FIX(SOCK_RDM)); +#endif +#ifdef SOCK_SEQPACKET + rb_define_const(cSocket, "SOCK_SEQPACKET", INT2FIX(SOCK_SEQPACKET)); +#endif +#ifdef SOCK_PACKET + rb_define_const(cSocket, "SOCK_PACKET", INT2FIX(SOCK_PACKET)); +#endif + + rb_define_const(cSocket, "SOL_SOCKET", INT2FIX(SOL_SOCKET)); +#ifdef SOL_IP + rb_define_const(cSocket, "SOL_IP", INT2FIX(SOL_IP)); +#endif +#ifdef SOL_IPX + rb_define_const(cSocket, "SOL_IPX", INT2FIX(SOL_IPX)); +#endif +#ifdef SOL_ATALK + rb_define_const(cSocket, "SOL_ATALK", INT2FIX(SOL_ATALK)); +#endif +#ifdef SOL_TCP + rb_define_const(cSocket, "SOL_TCP", INT2FIX(SOL_TCP)); +#endif +#ifdef SOL_UDP + rb_define_const(cSocket, "SOL_UDP", INT2FIX(SOL_UDP)); +#endif + + rb_define_const(cSocket, "SO_DEBUG", INT2FIX(SO_DEBUG)); + rb_define_const(cSocket, "SO_REUSEADDR", INT2FIX(SO_REUSEADDR)); + rb_define_const(cSocket, "SO_KEEPALIVE", INT2FIX(SO_KEEPALIVE)); + rb_define_const(cSocket, "SO_LINGER", INT2FIX(SO_LINGER)); } diff --git a/ext/socket/socket.doc b/ext/socket/socket.doc deleted file mode 100644 index aa5bfedbff..0000000000 --- a/ext/socket/socket.doc +++ /dev/null @@ -1,227 +0,0 @@ -.\" socket.doc - -*- Indented-Text -*- created at: Thu Mar 23 20:29:02 JST 1995 - -** Socket(¥¯¥é¥¹) - -SuperClass: BasicSocket - -¥½¥±¥Ã¥È¤½¤Î¤â¤Î¤ËÂФ¹¤ë¥·¥¹¥Æ¥à¥³¡¼¥ë¥ì¥Ù¥ë¤Î¥¢¥¯¥»¥¹¤òÄ󶡤¹¤ë¥¯¥é¥¹¡¥ -Perl¤Î¥½¥±¥Ã¥È¤ËÂФ¹¤ë¥¢¥¯¥»¥¹¤ÈƱ¥ì¥Ù¥ë¤Îµ¡Ç½¤òÄ󶡤·¤Æ¤¤¤ë¡¥¤³¤Î¥¯¥é -¥¹¤Ç¤Ï¥½¥±¥Ã¥È¥¢¥É¥ì¥¹¤Ïpack¤µ¤ì¤¿Ê¸»úÎó¤Ç¡¤»ØÄꤹ¤ë¡¥UDP¥½¥±¥Ã¥È¤Ï¤³ -¤Î¥¯¥é¥¹¤ò»È¤Ã¤ÆÍøÍѤ¹¤ë¡¥ - -Methods: - - accept - - ¿·¤·¤¤Àܳ¤ò¼õ¤±ÉÕ¤±¤Æ¡¤¿·¤·¤¤Àܳ¤ËÂФ¹¤ë¥½¥±¥Ã¥È¤È¥¢¥É¥ì¥¹¤Î - ¥Ú¥¢¤òÊÖ¤¹¡¥accept(2)¤ò»²¾È¡¥ - - bind(addr) - - bind(2)¤ÈƱ¤¸Æ¯¤¤ò¤¹¤ë¡¥addr¤Ïpack¤µ¤ì¤¿¥½¥±¥Ã¥È¥¢¥É¥ì¥¹¹½Â¤ - ÂΤǤ¢¤ë¡¥ - - connect(addr) - - connect(2)¤ÈƱ¤¸Æ¯¤¤ò¤¹¤ë¡¥addr¤Ïpack¤µ¤ì¤¿¥½¥±¥Ã¥È¥¢¥É¥ì¥¹¹½ - ¤ÂΤǤ¢¤ë¡¥ - - listen(backlog) - - listen(2)¤ÈƱ¤¸Æ¯¤¤ò¤¹¤ë¡¥ - - recv(len[, flags]) - - ¥½¥±¥Ã¥È¤«¤é¥Ç¡¼¥¿¤ò¼õ¤±¼è¤ê¡¤Ê¸»úÎó¤È¤·¤ÆÊÖ¤¹¡¥len¤Ï¼õ¤±¼è¤ë - ºÇÂç¤ÎŤµ¤ò»ØÄꤹ¤ë¡¥flags¤Ë¤Ä¤¤¤Æ¤Ïrecv(2)¤ò»²¾È¡¥flags¤Î¥Ç - ¥Õ¥©¥ë¥ÈÃͤÏ0¤Ç¤¢¤ë¡¥ - - recvfrom(len[, flags]) - - recv¤ÈƱÍͤ˥½¥±¥Ã¥È¤«¤é¥Ç¡¼¥¿¤ò¼õ¤±¼è¤ë¤¬¡¤Ìá¤êÃͤÏʸ»úÎó¤ÈÁê - ¼ê¥½¥±¥Ã¥È¤Î¥¢¥É¥ì¥¹¤Î¥Ú¥¢¤Ç¤¢¤ë¡¥°ú¿ô¤Ë¤Ä¤¤¤Æ¤Ïrecv¤ÈƱÍÍ¡¥ - - send(mesg, flags[, to]) - - ¥½¥±¥Ã¥È¤ò²ð¤·¤Æ¥Ç¡¼¥¿¤òÁ÷¤ë¡¥flags¤Ë´Ø¤·¤Æ¤Ïsend(2)¤ò»²¾È¤Î»ö¡¥ - connect¤·¤Æ¤¤¤Ê¤¤¥½¥±¥Ã¥È¤ËÂФ·¤Æ¤ÏÁ÷¤êÀè¤Ç¤¢¤ëto¤ò»ØÄꤹ¤ëɬ - Íפ¬¤¢¤ë¡¥¼ÂºÝ¤ËÁ÷¤Ã¤¿¥Ç¡¼¥¿¤ÎŤµ¤òÊÖ¤¹¡¥ - -Single Methods: - - open(domain, type, protocol) - new(domain, type, protocol) - - ¿·¤·¤¤¥½¥±¥Ã¥È¤òÀ¸À®¤¹¤ë¡¥domain¡¤type¡¤protocol¤Ï¥¤¥ó¥¯¥ë¡¼¥É - ¥Õ¥¡¥¤¥ë¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ëÄê¿ôÃͤǻØÄꤹ¤ë¡¥domain¤Ètype¤Ë´Ø¤·¤Æ - ¤Ï¡¤Ê¸»úÎó¤Ç»ØÄê¤Ç¤¤ë¤¬¡¤¤¹¤Ù¤Æ¤ò¥«¥Ð¡¼¤·¤Æ¤¤¤ëÊݾڤϤʤ¤¡¥ - - socketpair(domain, type, protocol) - - ¥½¥±¥Ã¥È¤Î¥Ú¥¢¤òÊÖ¤¹¡¥°ú¿ô¤Î»ØÄê¤Ï open¤ÈƱ¤¸¤Ç¤¢¤ë¡¥ - -** BasicSocket(¥¯¥é¥¹) - -¥½¥±¥Ã¥È¤òɽ¤¹Ãê¾Ý¥¯¥é¥¹¡¥¶ñÂÎŪ¤Ê¥½¥±¥Ã¥ÈÁàºî¤Ï¥µ¥Ö¥¯¥é¥¹¤ÇÄêµÁ¤µ¤ì¤ë¡¥ -Î㤨¤Ð¥¤¥ó¥¿¡¼¥Í¥Ã¥È¥É¥á¥¤¥ó¤Î¾ì¹ç¤ÏTCPsocket¤òÍѤ¤¤ë¡¥ - -SuperClass: IO - -Methods: - - getopt(level, optname) - - ¥½¥±¥Ã¥È¤Î¥ª¥×¥·¥ç¥ó¤ò¼èÆÀ¤¹¤ë¡¥getsockopt(2)¤ò»²¾È¤Î¤³¤È¡¥¼è - ÆÀ¤·¤¿¥ª¥×¥·¥ç¥ó¤ÎÆâÍÆ¤ò´Þ¤àʸ»úÎó¤òÊÖ¤¹¡¥ - - getpeername - - Àܳ¤ÎÁê¼êÀè¤Î¥½¥±¥Ã¥È¤Î¾ðÊó¤òÆÀ¤ë¡¥¥Ñ¥Ã¥¯¤µ¤ì¤¿sockaddr¹½Â¤ÂÎ - ¤ò¥Ù¥¿¤Ë¥À¥ó¥×¤·¤¿Ê¸»úÎó¤¬ÊÖ¤µ¤ì¤ë¡¥getpeername(2)¤ò»²¾È¤Î¤³¤È¡¥ - - getsockname - - ¥½¥±¥Ã¥È¤Î¾ðÊó¤òÆÀ¤ë¡¥¥Ñ¥Ã¥¯¤µ¤ì¤¿sockaddr¹½Â¤ÂΤò¥Ù¥¿¤Ë¥À¥ó¥× - ¤·¤¿Ê¸»úÎó¤¬ÊÖ¤µ¤ì¤ë¡¥getsockname(2)¤ò»²¾È¤Î¤³¤È¡¥ - - setopt(level, optname, optval) - - ¥½¥±¥Ã¥È¤Î¥ª¥×¥·¥ç¥ó¤òÀßÄꤹ¤ë¡¥setsockopt(2)¤ò»²¾È¤Î¤³¤È¡¥ - - shutdown(how) - - ¥½¥±¥Ã¥È¤Î°Ê¹ß¤ÎÀܳ¤ò½ªÎ»¤µ¤»¤ë¡¥how¤¬0¤Ç¤¢¤ë»þ¡¤°Ê¹ß¤Î¼õ¿®¤¬¡¤ - how¤¬1¤Ç¤¢¤ë»þ¤Ï¡¤°Ê¹ß¤ÎÁ÷¿®¤¬µñÈݤµ¤ì¤ë¡¥how¤¬2¤Î»þ¤Ë¤Ï¡¤¤½¤ì - °Ê¹ß¤ÎÁ÷¿®¡¤¼õ¿®¤È¤â¤ËµñÈݤµ¤ì¤ë¡¥shutdown(2)¤ò»²¾È¡¥ - -** TCPserver(¥¯¥é¥¹) - -TCP/IP¥¹¥È¥ê¡¼¥à·¿Àܳ¤Î¥µ¡¼¥Ð¦¤Î¥½¥±¥Ã¥È¤Î¥¯¥é¥¹¡¥¤³¤Î¥¯¥é¥¹¤Ë¤è¤Ã¤Æ -´Êñ¤Ë¥½¥±¥Ã¥È¤òÍøÍѤ·¤¿¥µ¡¼¥Ð¤Î¥×¥í¥°¥é¥ß¥ó¥°¤¬¤Ç¤¤ë¡¥Î㤨¤Ðecho¥µ¡¼ -¥Ð¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡¥ - - gs = TCPserver.open(4444) - socks = [gs] - - while TRUE - nsock = select(socks); - if nsock == nil; continue end - for s in nsock[0] - if s == gs - socks.push(s.accept) - else - if s.eof - s.close - socks.delete(s) - else - str = s.gets - s.write(str) - end - end - end - end - -SuperClass: TCPsocket - -Methods: - - accept - - ¥¯¥é¥¤¥¢¥ó¥È¤«¤é¤ÎÀܳÍ×µá¤ò¼õ¤±ÉÕ¤±¡¤Àܳ¤·¤¿TCPsocket¤Î¥¤¥ó - ¥¹¥¿¥ó¥¹¤òÊÖ¤¹¡¥ - -Single Methods: - - new([host, ]service) - open([host, ]service) - - service¤Ï/etc/services(¤Þ¤¿¤ÏNIS)¤ËÅÐÏ¿¤µ¤ì¤Æ¤¤¤ë¥µ¡¼¥Ó¥¹Ì¾¤« - ¥Ý¡¼¥ÈÈÖ¹æ¤Ç»ØÄꤹ¤ë¡¥host¤ò»ØÄꤷ¤¿»þ¤Ï»ØÄꤷ¤¿¥Û¥¹¥È¤«¤é¤ÎÀÜ - ³¤À¤±¤ò¼õ¤±ÉÕ¤±¤ë¡¥¾Êά»þ¤ÏÁ´¤Æ¤Î¥Û¥¹¥È¤«¤é¤ÎÀܳÍ×µá¤ò¼õ¤±ÉÕ - ¤±¤ë¡¥ - -** TCPsocket - -¥¤¥ó¥¿¡¼¥Í¥Ã¥È¥É¥á¥¤¥ó¤Î¥¹¥È¥ê¡¼¥à·¿¥½¥±¥Ã¥È¤Î¥¯¥é¥¹¡¥Ä̾ï¤ÎIO¥¯¥é¥¹¤Î -¥µ¥Ö¥¯¥é¥¹¤ÈƱÍÍ¤ÎÆþ½ÐÎϤ¬¤Ç¤¤ë¡¥¤³¤Î¥¯¥é¥¹¤Ë¤è¤Ã¤Æ¥½¥±¥Ã¥È¤òÍѤ¤¤¿¥¯ -¥é¥¤¥¢¥ó¥È¤ò´Êñ¤Ëµ½Ò¤Ç¤¤ë¡¥¥æ¡¼¥¶¤ÎÆþÎϤò¤½¤Î¤Þ¤Þ¥µ¡¼¥Ð¤ËžÁ÷¤¹¤ë¥× -¥í¥°¥é¥à¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë¡¥ - - s = TCPsocket("localhost", 4444) - while gets() - s.write($_) - print(s.read) - end - -SuperClass: BasicSocket - -Methods: - - addr - - ¥½¥±¥Ã¥È¤ÎÀܳ¾ðÊó¤òɽ¤¹ÇÛÎó¤òÊÖ¤¹¡¥¤½¤ÎÇÛÎó¤Î³ÆÍ×ÁǤÏÂè1Í×ÁÇ - ¤¬Ê¸»úÎó "AF_INET"¡¤Âè2Í×ÁǤ¬portÈֹ桤Âè3Í×ÁǤ¬¥Û¥¹¥È¤òɽ¤¹Ê¸ - »úÎó¤Ç¤¢¤ë¡¥ - - peeraddr - - ÀܳÁê¼êÀ襽¥±¥Ã¥È¤Î¾ðÊó¤òɽ¤¹ÇÛÎó¤òÊÖ¤¹¡¥¤½¤ÎÇÛÎó¤Î³ÆÍ×ÁÇ¤Ï - addr¥á¥½¥Ã¥É¤¬ÊÖ¤¹ÇÛÎó¤ÈƱ¤¸¤Ç¤¢¤ë¡¥ - -Single Methods: - - open(host, service) - new(host, service) - - host¤Ç»ØÄꤷ¤¿¥Û¥¹¥È¤Îservice¤Ç»ØÄꤷ¤¿¥Ý¡¼¥È¤ÈÀܳ¤·¤¿¥½¥±¥Ã - ¥È¤òÊÖ¤¹¡¥host¤Ï¥Û¥¹¥È̾¡¤¤Þ¤¿¤Ï¥¤¥ó¥¿¡¼¥Í¥Ã¥È¥¢¥É¥ì¥¹¤ò¼¨¤¹Ê¸ - »úÎó¡¤service¤Ï/etc/services(¤Þ¤¿¤ÏNIS)¤ËÅÐÏ¿¤µ¤ì¤Æ¤¤¤ë¥µ¡¼¥Ó - ¥¹Ì¾¤«¥Ý¡¼¥ÈÈÖ¹æ¤Ç¤¢¤ë¡¥ - -** UNIXserver - -UNIX¥¹¥È¥ê¡¼¥à·¿Àܳ¤Î¥µ¡¼¥Ð¦¤Î¥½¥±¥Ã¥È¤Î¥¯¥é¥¹¡¥ - -SuperClass: UNIXsocket - -Methods: - - accept - - ¥¯¥é¥¤¥¢¥ó¥È¤«¤é¤ÎÀܳÍ×µá¤ò¼õ¤±ÉÕ¤±¡¤Àܳ¤·¤¿UNIXsocket¤Î¥¤¥ó - ¥¹¥¿¥ó¥¹¤òÊÖ¤¹¡¥ - -** UNIXsocket - -UNIX¥É¥á¥¤¥ó¤Î¥¹¥È¥ê¡¼¥à·¿¥½¥±¥Ã¥È¤Î¥¯¥é¥¹¡¥Ä̾ï¤ÎIO¥¯¥é¥¹¤Î¥µ¥Ö¥¯¥é¥¹ -¤ÈƱÍÍ¤ÎÆþ½ÐÎϤ¬¤Ç¤¤ë¡¥ - -SuperClass: BasicSocket - -Methods: - - addr - - ¥½¥±¥Ã¥È¤ÎÀܳ¾ðÊó¤òɽ¤¹ÇÛÎó¤òÊÖ¤¹¡¥¤½¤ÎÇÛÎó¤Î³ÆÍ×ÁǤÏÂè1Í×ÁÇ - ¤¬Ê¸»úÎó "AF_UNIX"¡¤Âè2Í×ÁǤ¬path¤Ç¤¢¤ë¡¥ - - path - - UNIX¥½¥±¥Ã¥È¤Î¥Ñ¥¹¤òÊÖ¤¹¡¥ - - peeraddr - - ÀܳÁê¼êÀ襽¥±¥Ã¥È¤Î¾ðÊó¤òɽ¤¹ÇÛÎó¤òÊÖ¤¹¡¥¤½¤ÎÇÛÎó¤Î³ÆÍ×ÁÇ¤Ï - addr¥á¥½¥Ã¥É¤¬ÊÖ¤¹ÇÛÎó¤ÈƱ¤¸¤Ç¤¢¤ë¡¥ - -Single Methods: - - open(path) - new(path) - - path¤Ç»ØÄꤷ¤¿¥Ñ¥¹Ì¾¤òÍѤ¤¤ÆÀܳ¤·¤¿¥½¥±¥Ã¥È¤òÊÖ¤¹¡¥ - -------------------------------------------------------- -Local variables: -fill-column: 70 -end: diff --git a/ext/tkutil/MANIFEST b/ext/tkutil/MANIFEST index 98df4663b3..870e04b586 100644 --- a/ext/tkutil/MANIFEST +++ b/ext/tkutil/MANIFEST @@ -1,3 +1,3 @@ MANIFEST -extconf.rb tkutil.c +depend diff --git a/ext/tkutil/depend b/ext/tkutil/depend new file mode 100644 index 0000000000..ead83eda57 --- /dev/null +++ b/ext/tkutil/depend @@ -0,0 +1 @@ +tkutil.o: tkutil.c ../../ruby.h ../../config.h ../../defines.h diff --git a/ext/tkutil/extconf.rb b/ext/tkutil/extconf.rb deleted file mode 100644 index b61a7ac01c..0000000000 --- a/ext/tkutil/extconf.rb +++ /dev/null @@ -1,11 +0,0 @@ -for dir in ENV['PATH'].split(':') - if File.exists? "#{dir}/wish" - $CFLAGS = $CFLAGS + " -DWISHPATH=" + "'\"#{dir}/wish\"'" - have_wish = TRUE - break - end -end - -if have_wish and have_func('pipe') - create_makefile("tkutil") -end diff --git a/ext/tkutil/tkutil.c b/ext/tkutil/tkutil.c index 2b74b254c2..51e3412ab5 100644 --- a/ext/tkutil/tkutil.c +++ b/ext/tkutil/tkutil.c @@ -47,7 +47,6 @@ Init_tkutil() VALUE mTK = rb_define_module("TkUtil"); VALUE cTK = rb_define_class("TkKernel", cObject); - rb_define_const(mTK, "WISH_PATH", str_new2(WISHPATH)); rb_define_singleton_method(mTK, "eval_cmd", tk_eval_cmd, -1); rb_define_singleton_method(cTK, "new", tk_s_new, -1); @@ -6,7 +6,7 @@ $Date: 1995/01/10 10:42:36 $ created at: Mon Nov 15 12:24:34 JST 1993 - Copyright (C) 1993-1995 Yukihiro Matsumoto + Copyright (C) 1993-1996 Yukihiro Matsumoto ************************************************/ @@ -26,7 +26,7 @@ #ifdef HAVE_SYS_TIME_H # include <sys/time.h> #else -struct timeval { +stuct timeval { long tv_sec; /* seconds */ long tv_usec; /* and microseconds */ }; @@ -60,28 +60,37 @@ VALUE file_open(fname, mode) char *fname, *mode; { - VALUE port; OpenFile *fptr; - - port = obj_alloc(cFile); - + NEWOBJ(port, struct RFile); + OBJSETUP(port, cFile, T_FILE); MakeOpenFile(port, fptr); - fptr->mode = io_mode_flags(mode); - fptr->f = fopen(fname, mode); - if (fptr->f == NULL) { - if (errno == EMFILE) { - gc(); - fptr->f = fopen(fname, mode); - } - if (fptr->f == NULL) { - rb_sys_fail(fname); - } - } + fptr->mode = io_mode_flags(mode); + fptr->f = rb_fopen(fname, mode); fptr->path = strdup(fname); - return port; + return (VALUE)port; +} + +static VALUE +file_s_open(argc, argv) + int argc; + VALUE *argv; +{ + VALUE fname, vmode; + char *mode; + + rb_scan_args(argc, argv, "11", &fname, &mode); + Check_Type(fname, T_STRING); + if (!NIL_P(mode)) { + Check_Type(mode, T_STRING); + mode = RSTRING(mode)->ptr; + } + else { + mode = "r"; + } + return file_open(RSTRING(fname)->ptr, mode); } static int @@ -113,7 +122,7 @@ file_tell(obj) GetOpenFile(obj, fptr); pos = ftell(fptr->f); - if (ferror(fptr->f) != 0) rb_sys_fail(Qnil); + if (ferror(fptr->f) != 0) rb_sys_fail(0); return int2inum(pos); } @@ -128,7 +137,7 @@ file_seek(obj, offset, ptrname) GetOpenFile(obj, fptr); pos = fseek(fptr->f, NUM2INT(offset), NUM2INT(ptrname)); - if (pos != 0) rb_sys_fail(Qnil); + if (pos != 0) rb_sys_fail(0); clearerr(fptr->f); return obj; @@ -143,7 +152,7 @@ file_set_pos(obj, offset) GetOpenFile(obj, fptr); pos = fseek(fptr->f, NUM2INT(offset), 0); - if (pos != 0) rb_sys_fail(Qnil); + if (pos != 0) rb_sys_fail(0); clearerr(fptr->f); return obj; @@ -156,7 +165,7 @@ file_rewind(obj) OpenFile *fptr; GetOpenFile(obj, fptr); - if (fseek(fptr->f, 0L, 0) != 0) rb_sys_fail(Qnil); + if (fseek(fptr->f, 0L, 0) != 0) rb_sys_fail(0); clearerr(fptr->f); return obj; @@ -191,14 +200,14 @@ file_isatty(obj) } #include <sys/types.h> -#include <sys/stat.h> #include <sys/file.h> +#include <sys/stat.h> static VALUE stat_new(st) struct stat *st; { - if (st == Qnil) Bug("stat_new() called with nil"); + if (!st) Bug("stat_new() called with bad value"); return struct_new(sStat, INT2FIX((int)st->st_dev), INT2FIX((int)st->st_ino), @@ -224,26 +233,7 @@ stat_new(st) #endif time_new(st->st_atime, 0), time_new(st->st_mtime, 0), - time_new(st->st_ctime, 0), - Qnil); -} - -static struct stat laststat; - -int -cache_stat(path, st) - char *path; - struct stat *st; -{ - if (strcmp("&", path) == 0) { - *st = laststat; - return 0; - } - if (stat(path, st) == -1) - return -1; - - laststat = *st; - return 0; + time_new(st->st_ctime, 0)); } static VALUE @@ -254,7 +244,7 @@ file_s_stat(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) == -1) { + if (stat(fname->ptr, &st) == -1) { rb_sys_fail(fname->ptr); } return stat_new(&st); @@ -265,12 +255,13 @@ file_stat(obj) VALUE obj; { OpenFile *fptr; + struct stat st; GetOpenFile(obj, fptr); - if (fstat(fileno(fptr->f), &laststat) == -1) { + if (fstat(fileno(fptr->f), &st) == -1) { rb_sys_fail(fptr->path); } - return stat_new(&laststat); + return stat_new(&st); } static VALUE @@ -278,6 +269,7 @@ file_s_lstat(obj, fname) VALUE obj; struct RString *fname; { +#if !defined(MSDOS) struct stat st; Check_Type(fname, T_STRING); @@ -285,12 +277,16 @@ file_s_lstat(obj, fname) rb_sys_fail(fname->ptr); } return stat_new(&st); +#else + rb_notimplement(); +#endif } static VALUE file_lstat(obj) VALUE obj; { +#if !defined(MSDOS) OpenFile *fptr; struct stat st; @@ -299,6 +295,9 @@ file_lstat(obj) rb_sys_fail(fptr->path); } return stat_new(&st); +#else + rb_notimplement(); +#endif } static int @@ -339,7 +338,7 @@ eaccess(path, mode) struct stat st; static int euid = -1; - if (cache_stat(path, &st) < 0) return (-1); + if (stat(path, &st) < 0) return (-1); if (euid == -1) euid = geteuid (); @@ -378,7 +377,7 @@ test_d(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) return FALSE; + if (stat(fname->ptr, &st) < 0) return FALSE; if (S_ISDIR(st.st_mode)) return TRUE; return FALSE; } @@ -396,7 +395,7 @@ test_p(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) return FALSE; + if (stat(fname->ptr, &st) < 0) return FALSE; if (S_ISFIFO(st.st_mode)) return TRUE; #endif @@ -426,7 +425,7 @@ test_l(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) return FALSE; + if (lstat(fname->ptr, &st) < 0) return FALSE; if (S_ISLNK(st.st_mode)) return TRUE; #endif @@ -456,7 +455,7 @@ test_S(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) return FALSE; + if (stat(fname->ptr, &st) < 0) return FALSE; if (S_ISSOCK(st.st_mode)) return TRUE; #endif @@ -478,7 +477,7 @@ test_b(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) return FALSE; + if (stat(fname->ptr, &st) < 0) return FALSE; if (S_ISBLK(st.st_mode)) return TRUE; #endif @@ -497,7 +496,7 @@ test_c(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) return FALSE; + if (stat(fname->ptr, &st) < 0) return FALSE; if (S_ISBLK(st.st_mode)) return TRUE; return FALSE; @@ -511,7 +510,7 @@ test_e(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) return FALSE; + if (stat(fname->ptr, &st) < 0) return FALSE; return TRUE; } @@ -583,7 +582,7 @@ test_f(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) return FALSE; + if (stat(fname->ptr, &st) < 0) return FALSE; if (S_ISREG(st.st_mode)) return TRUE; return FALSE; } @@ -596,7 +595,7 @@ test_z(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) return FALSE; + if (stat(fname->ptr, &st) < 0) return FALSE; if (st.st_size == 0) return TRUE; return FALSE; } @@ -609,7 +608,7 @@ test_s(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) return FALSE; + if (stat(fname->ptr, &st) < 0) return FALSE; if (st.st_size == 0) return FALSE; return int2inum(st.st_size); } @@ -622,7 +621,7 @@ test_owned(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) return FALSE; + if (stat(fname->ptr, &st) < 0) return FALSE; if (st.st_uid == geteuid()) return TRUE; return FALSE; } @@ -635,7 +634,7 @@ test_rowned(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) return FALSE; + if (stat(fname->ptr, &st) < 0) return FALSE; if (st.st_uid == getuid()) return TRUE; return FALSE; } @@ -649,7 +648,7 @@ test_grpowned(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) return FALSE; + if (stat(fname->ptr, &st) < 0) return FALSE; if (st.st_gid == getegid()) return TRUE; #else Check_Type(fname, T_STRING); @@ -665,7 +664,7 @@ check3rdbyte(file, mode) { struct stat st; - if (cache_stat(file, &st) < 0) return FALSE; + if (stat(file, &st) < 0) return FALSE; if (st.st_mode & mode) return TRUE; return FALSE; } @@ -719,7 +718,7 @@ file_s_type(obj, fname) char *t; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr); + if (stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr); if (S_ISREG(st.st_mode)) { t = "file"; @@ -763,7 +762,7 @@ file_s_atime(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr); + if (stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr); return time_new(st.st_atime, 0); } @@ -789,7 +788,7 @@ file_s_mtime(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr); + if (stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr); return time_new(st.st_mtime, 0); } @@ -815,7 +814,7 @@ file_s_ctime(obj, fname) struct stat st; Check_Type(fname, T_STRING); - if (cache_stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr); + if (stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr); return time_new(st.st_ctime, 0); } @@ -868,8 +867,13 @@ file_chmod(obj, vmode) mode = NUM2INT(vmode); GetOpenFile(obj, fptr); +#if defined(DJGPP) || defined(__CYGWIN32__) + if (chmod(fptr->path, mode) == -1) + rb_sys_fail(fptr->path); +#else if (fchmod(fileno(fptr->f), mode) == -1) rb_sys_fail(fptr->path); +#endif return INT2FIX(0); } @@ -897,13 +901,13 @@ file_s_chown(argc, argv) int n; rb_scan_args(argc, argv, "2*", &o, &g, &rest); - if (o == Qnil) { + if (NIL_P(o)) { arg.owner = -1; } else { arg.owner = NUM2INT(o); } - if (g == Qnil) { + if (NIL_P(g)) { arg.group = -1; } else { @@ -921,13 +925,18 @@ file_chown(obj, owner, group) OpenFile *fptr; GetOpenFile(obj, fptr); +#if defined(DJGPP) || defined(__CYGWIN32__) + if (chown(fptr->path, NUM2INT(owner), NUM2INT(group)) == -1) + rb_sys_fail(fptr->path); +#else if (fchown(fileno(fptr->f), NUM2INT(owner), NUM2INT(group)) == -1) rb_sys_fail(fptr->path); +#endif return INT2FIX(0); } -struct timeval *time_timeval(); +struct timeval time_timeval(); #ifdef HAVE_UTIMES @@ -951,8 +960,8 @@ file_s_utime(argc, argv) rb_scan_args(argc, argv, "2*", &atime, &mtime, &rest); - tvp[0] = *time_timeval(atime); - tvp[1] = *time_timeval(mtime); + tvp[0] = time_timeval(atime); + tvp[1] = time_timeval(mtime); n = apply2files(utime_internal, rest, tvp); return INT2FIX(n); @@ -987,15 +996,15 @@ file_s_utime(argc, argv) { VALUE atime, mtime, rest; int n; - struct timeval *tv; + struct timeval tv; struct utimbuf utbuf; rb_scan_args(argc, argv, "2*", &atime, &mtime, &rest); tv = time_timeval(atime); - utbuf.actime = tv->tv_sec; + utbuf.actime = tv.tv_sec; tv = time_timeval(mtime); - utbuf.modtime = tv->tv_sec; + utbuf.modtime = tv.tv_sec; n = apply2files(utime_internal, rest, &utbuf); return INT2FIX(n); @@ -1021,12 +1030,16 @@ file_s_symlink(obj, from, to) VALUE obj; struct RString *from, *to; { +#if !defined(MSDOS) Check_Type(from, T_STRING); Check_Type(to, T_STRING); if (symlink(from->ptr, to->ptr) < 0) rb_sys_fail(from->ptr); return TRUE; +#else + rb_notimplement(); +#endif } static VALUE @@ -1034,6 +1047,7 @@ file_s_readlink(obj, path) VALUE obj; struct RString *path; { +#if !defined(MSDOS) char buf[MAXPATHLEN]; int cc; @@ -1043,6 +1057,9 @@ file_s_readlink(obj, path) rb_sys_fail(path->ptr); return str_new(buf, cc); +#else + rb_notimplement(); +#endif } static void @@ -1060,7 +1077,7 @@ file_s_unlink(obj, args) { int n; - n = apply2files(unlink_internal, args, Qnil); + n = apply2files(unlink_internal, args, 0); return INT2FIX(n); } @@ -1093,82 +1110,11 @@ file_s_umask(argc, argv) omask = umask(NUM2INT(argv[1])); } else { - Fail("wrong # of argument"); + ArgError("wrong # of argument"); } return INT2FIX(omask); } -#if defined(HAVE_TRUNCATE) || defined(HAVE_CHSIZE) -static VALUE -file_s_truncate(obj, path, len) - VALUE obj, len; - struct RString *path; -{ - Check_Type(path, T_STRING); - -#ifdef HAVE_TRUNCATE - if (truncate(path->ptr, NUM2INT(len)) < 0) - rb_sys_fail(path->ptr); -#else -# ifdef HAVE_CHSIZE - { - int tmpfd; - -#if defined(NT) - if ((tmpfd = open(path->ptr, O_RDWR)) < 0) { - rb_sys_fail(path->ptr); - } -#else - if ((tmpfd = open(path->ptr, 0)) < 0) { - rb_sys_fail(path->ptr); - } -#endif - if (chsize(tmpfd, NUM2INT(len)) < 0) { - close(tmpfd); - rb_sys_fail(path->ptr); - } - close(tmpfd); - } -# endif -#endif - return TRUE; -} - -static VALUE -file_truncate(obj, len) - VALUE obj, len; -{ - OpenFile *fptr; - - GetOpenFile(obj, fptr); - - if (!(fptr->mode & FMODE_WRITABLE)) { - Fail("not opened for writing"); - } -#ifdef HAVE_TRUNCATE - if (ftruncate(fileno(fptr->f), NUM2INT(len)) < 0) - rb_sys_fail(fptr->path); -#else -# ifdef HAVE_CHSIZE - if (chsize(fileno(fptr->f), NUM2INT(len)) < 0) - rb_sys_fail(fptr->path); -# endif -#endif - return TRUE; -} -#endif - -#ifdef HAVE_FCNTL -static VALUE -file_fcntl(obj, req, arg) - VALUE obj, req; - struct RString *arg; -{ - io_ctl(obj, req, arg, 0); - return obj; -} -#endif - static VALUE file_s_expand_path(obj, fname) VALUE obj; @@ -1218,7 +1164,7 @@ file_s_expand_path(obj, fname) #ifdef HAVE_GETCWD getcwd(buf, MAXPATHLEN); #else - getwd(buf)l + getwd(buf); #endif p = &buf[strlen(buf)]; } @@ -1292,17 +1238,17 @@ file_s_basename(argc, argv) rb_scan_args(argc, argv, "11", &fname, &ext); Check_Type(fname, T_STRING); - if (ext) Check_Type(ext, T_STRING); + if (!NIL_P(ext)) Check_Type(ext, T_STRING); p = strrchr(fname->ptr, '/'); - if (p == Qnil) { - if (ext) { + if (!p) { + if (!NIL_P(ext)) { f = rmext(fname->ptr, ext->ptr); if (f) return str_new(fname->ptr, f); } return (VALUE)fname; } p++; /* skip last `/' */ - if (ext) { + if (!NIL_P(ext)) { f = rmext(p, ext->ptr); if (f) return str_new(p, f); } @@ -1315,12 +1261,119 @@ file_s_dirname(obj, fname) struct RString *fname; { char *p; + Check_Type(fname, T_STRING); p = strrchr(fname->ptr, '/'); - if (p == Qnil) return (VALUE)fname; + if (!p) { + return str_new(0,0); + } return str_new(fname->ptr, p - fname->ptr); } +static VALUE separator; + +static VALUE +file_s_split(obj, path) + VALUE obj, path; +{ + return assoc_new(file_s_dirname(Qnil, path), file_s_basename(1,&path)); +} + +static VALUE +file_s_truncate(obj, path, len) + VALUE obj, len; + struct RString *path; +{ + Check_Type(path, T_STRING); + +#ifdef HAVE_TRUNCATE + if (truncate(path->ptr, NUM2INT(len)) < 0) + rb_sys_fail(path->ptr); +#else +# ifdef HAVE_CHSIZE + { + int tmpfd; + +# if defined(NT) + if ((tmpfd = open(path->ptr, O_RDWR)) < 0) { + rb_sys_fail(path->ptr); + } +# else + if ((tmpfd = open(path->ptr, 0)) < 0) { + rb_sys_fail(path->ptr); + } +# endif + if (chsize(tmpfd, NUM2INT(len)) < 0) { + close(tmpfd); + rb_sys_fail(path->ptr); + } + close(tmpfd); + } +# else + rb_notimplement(); +# endif +#endif + return TRUE; +} + +static VALUE +file_truncate(obj, len) + VALUE obj, len; +{ + OpenFile *fptr; + + GetOpenFile(obj, fptr); + + if (!(fptr->mode & FMODE_WRITABLE)) { + Fail("not opened for writing"); + } +#ifdef HAVE_TRUNCATE + if (ftruncate(fileno(fptr->f), NUM2INT(len)) < 0) + rb_sys_fail(fptr->path); +#else +# ifdef HAVE_CHSIZE + if (chsize(fileno(fptr->f), NUM2INT(len)) < 0) + rb_sys_fail(fptr->path); +# else + rb_notimplement(); +# endif +#endif + return TRUE; +} + +static VALUE +file_fcntl(obj, req, arg) + VALUE obj, req; + struct RString *arg; +{ +#ifdef HAVE_FCNTL + io_ctl(obj, req, arg, 0); +#else + rb_notimplement(); +#endif + return obj; +} + +static VALUE +file_flock(obj, operation) + VALUE obj; + VALUE operation; +{ + OpenFile *fptr; + + GetOpenFile(obj, fptr); + + if (flock(fileno(fptr->f), NUM2INT(operation)) < 0) { +#ifdef EWOULDBLOCK + if (errno = EWOULDBLOCK) { + return FALSE; + } +#endif + rb_sys_fail(fptr->path); + } + return obj; +} + static void test_check(n, argc, argv) int n, argc; @@ -1329,7 +1382,7 @@ test_check(n, argc, argv) int i; n+=1; - if (n < argc) Fail("Wrong # of arguments(%d for %d)", argc, n); + if (n < argc) ArgError("Wrong # of arguments(%d for %d)", argc, n); for (i=1; i<n; i++) { Check_Type(argv[i], T_STRING); } @@ -1344,7 +1397,7 @@ f_test(argc, argv) { int cmd; - if (argc == 0) Fail("Wrong # of arguments"); + if (argc == 0) ArgError("Wrong # of arguments"); Need_Fixnum(argv[0]); cmd = FIX2INT(argv[0]); if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) { @@ -1423,7 +1476,7 @@ f_test(argc, argv) struct stat st; CHECK(1); - if (cache_stat(RSTRING(argv[1])->ptr, &st) == -1) { + if (stat(RSTRING(argv[1])->ptr, &st) == -1) { rb_sys_fail(RSTRING(argv[1])->ptr); } @@ -1474,7 +1527,8 @@ Init_File() mFileTest = rb_define_module("FileTest"); rb_define_module_function(mFileTest, "directory?", test_d, 1); - rb_define_module_function(mFileTest, "exists?", test_e, 1); + rb_define_module_function(mFileTest, "exist?", test_e, 1); + rb_define_module_function(mFileTest, "exists?", test_e, 1); /* temporary */ rb_define_module_function(mFileTest, "readable?", test_r, 1); rb_define_module_function(mFileTest, "readable_real?", test_R, 1); rb_define_module_function(mFileTest, "writable?", test_w, 1); @@ -1501,9 +1555,11 @@ Init_File() cFile = rb_define_class("File", cIO); rb_extend_object(cFile, CLASS_OF(mFileTest)); + rb_define_singleton_method(cFile, "open", file_s_open, -1); + rb_define_singleton_method(cFile, "stat", file_s_stat, 1); rb_define_singleton_method(cFile, "lstat", file_s_lstat, 1); - rb_define_singleton_method(cFile, "type", file_s_type, 1); + rb_define_singleton_method(cFile, "ftype", file_s_type, 1); rb_define_singleton_method(cFile, "atime", file_s_atime, 1); rb_define_singleton_method(cFile, "mtime", file_s_mtime, 1); @@ -1521,13 +1577,15 @@ Init_File() rb_define_singleton_method(cFile, "delete", file_s_unlink, -2); rb_define_singleton_method(cFile, "rename", file_s_rename, 2); rb_define_singleton_method(cFile, "umask", file_s_umask, -1); -#if defined(HAVE_TRUNCATE) || defined(HAVE_CHSIZE) rb_define_singleton_method(cFile, "truncate", file_s_truncate, 2); -#endif rb_define_singleton_method(cFile, "expand_path", file_s_expand_path, 1); rb_define_singleton_method(cFile, "basename", file_s_basename, -1); rb_define_singleton_method(cFile, "dirname", file_s_dirname, 1); + separator = INT2FIX('/'); + rb_define_const(cFile, "Separator", separator); + rb_define_singleton_method(cFile, "split", file_s_split, 1); + rb_define_method(cFile, "stat", file_stat, 0); rb_define_method(cFile, "lstat", file_lstat, 0); @@ -1537,9 +1595,7 @@ Init_File() rb_define_method(cFile, "chmod", file_chmod, 1); rb_define_method(cFile, "chown", file_chown, 2); -#if defined(HAVE_TRUNCATE) || defined(HAVE_CHSIZE) rb_define_method(cFile, "truncate", file_truncate, 1); -#endif rb_define_method(cFile, "tell", file_tell, 0); rb_define_method(cFile, "seek", file_seek, 2); @@ -1553,9 +1609,26 @@ Init_File() rb_define_method(cFile, "eof", file_eof, 0); rb_define_method(cFile, "eof?", file_eof, 0); -#ifdef HAVE_FCNTL rb_define_method(cIO, "fcntl", file_fcntl, 2); -#endif + rb_define_method(cFile, "flock", file_flock, 1); + +# ifndef LOCK_SH +# define LOCK_SH 1 +# endif +# ifndef LOCK_EX +# define LOCK_EX 2 +# endif +# ifndef LOCK_NB +# define LOCK_NB 4 +# endif +# ifndef LOCK_UN +# define LOCK_UN 8 +# endif + + rb_define_const(cFile, "LOCK_SH", INT2FIX(LOCK_SH)); + rb_define_const(cFile, "LOCK_EX", INT2FIX(LOCK_EX)); + rb_define_const(cFile, "LOCK_UN", INT2FIX(LOCK_UN)); + rb_define_const(cFile, "LOCK_NB", INT2FIX(LOCK_NB)); rb_define_method(cFile, "path", file_path, 0); @@ -1564,5 +1637,5 @@ Init_File() sStat = struct_define("Stat", "dev", "ino", "mode", "nlink", "uid", "gid", "rdev", "size", "blksize", "blocks", - "atime", "mtime", "ctime", Qnil); + "atime", "mtime", "ctime", 0); } @@ -6,18 +6,23 @@ $Date: 1995/01/12 08:54:47 $ created at: Tue Oct 5 09:44:46 JST 1993 - Copyright (C) 1993-1995 Yukihiro Matsumoto + Copyright (C) 1993-1996 Yukihiro Matsumoto ************************************************/ #include "ruby.h" -#include "env.h" +#include "sig.h" #include "st.h" #include "node.h" +#include "env.h" #include "re.h" #include <stdio.h> #include <setjmp.h> +#ifdef _AIX +#pragma alloca +#endif + void *malloc(); void *calloc(); void *realloc(); @@ -36,10 +41,10 @@ xmalloc(size) if (size == 0) size = 1; mem = malloc(size); - if (mem == Qnil) { + if (!mem) { gc(); mem = malloc(size); - if (mem == Qnil) + if (!mem) Fatal("failed to allocate memory"); } @@ -65,12 +70,12 @@ xrealloc(ptr, size) { void *mem; - if (ptr == Qnil) return xmalloc(size); + if (!ptr) return xmalloc(size); mem = realloc(ptr, size); - if (mem == Qnil) { + if (!mem) { gc(); mem = realloc(ptr, size); - if (mem == Qnil) + if (!mem) Fatal("failed to allocate memory(realloc)"); } @@ -107,12 +112,6 @@ Paradigm Associates Inc Phone: 617-492-6079 Cambridge, MA 02138 */ -#ifdef sparc -#define FLUSH_REGISTER_WINDOWS asm("ta 3") -#else -#define FLUSH_REGISTER_WINDOWS /* empty */ -#endif - static int dont_gc; VALUE @@ -136,10 +135,9 @@ gc_s_disable() VALUE mGC; static struct gc_list { - int n; VALUE *varptr; struct gc_list *next; -} *Global_List = Qnil; +} *Global_List = 0; void rb_global_variable(var) @@ -150,7 +148,6 @@ rb_global_variable(var) tmp = ALLOC(struct gc_list); tmp->next = Global_List; tmp->varptr = var; - tmp->n = 1; Global_List = tmp; } @@ -171,6 +168,7 @@ typedef struct RVALUE { struct RData data; struct RStruct rstruct; struct RBignum bignum; + struct RFile file; struct RNode node; struct RMatch match; struct RVarmap varmap; @@ -236,15 +234,15 @@ newobj() } VALUE -data_new(datap, dmark, dfree) +data_object_alloc(class, datap, dmark, dfree) + VALUE class; void *datap; void (*dfree)(); void (*dmark)(); { - extern VALUE cData; struct RData *data = (struct RData*)newobj(); - OBJSETUP(data, cData, T_DATA); + OBJSETUP(data, class, T_DATA); data->data = datap; data->dfree = dfree; data->dmark = dmark; @@ -253,9 +251,9 @@ data_new(datap, dmark, dfree) } extern st_table *rb_class_tbl; -static VALUE *stack_start_ptr; +VALUE *gc_stack_start; -static long +static int looks_pointerp(p) register RVALUE *p; { @@ -288,8 +286,8 @@ mark_locations_array(x, n) } } -static void -mark_locations(start, end) +void +gc_mark_locations(start, end) VALUE *start, *end; { VALUE *tmp; @@ -351,8 +349,8 @@ gc_mark(obj) register RVALUE *obj; { Top: - if (obj == Qnil) return; /* nil not marked */ if (FIXNUM_P(obj)) return; /* fixnum not marked */ + if (rb_special_const_p(obj)) return; /* special const not marked */ if (obj->as.basic.flags == 0) return; /* free cell */ if (obj->as.basic.flags & FL_MARK) return; /* marked */ @@ -408,7 +406,10 @@ gc_mark(obj) break; case T_STRING: - if (obj->as.string.orig) gc_mark(obj->as.string.orig); + if (obj->as.string.orig) { + obj = (RVALUE*)obj->as.string.orig; + goto Top; + } break; case T_DATA: @@ -419,6 +420,7 @@ gc_mark(obj) if (obj->as.object.iv_tbl) mark_tbl(obj->as.object.iv_tbl); break; + case T_FILE: case T_MATCH: case T_REGEXP: case T_FLOAT: @@ -426,7 +428,9 @@ gc_mark(obj) break; case T_VARMAP: - gc_mark(obj->as.varmap.next); + gc_mark(obj->as.varmap.val); + obj = (RVALUE*)obj->as.varmap.next; + goto Top; break; case T_SCOPE: @@ -435,7 +439,7 @@ gc_mark(obj) VALUE *tbl = obj->as.scope.local_vars; while (n--) { - gc_mark(*tbl); + gc_mark_maybe(*tbl); tbl++; } } @@ -512,12 +516,12 @@ obj_free(obj) break; case T_MODULE: case T_CLASS: - rb_clear_cache(obj); + rb_clear_cache(); st_free_table(obj->as.class.m_tbl); if (obj->as.object.iv_tbl) st_free_table(obj->as.object.iv_tbl); break; case T_STRING: - if (obj->as.string.orig == Qnil) free(obj->as.string.ptr); + if (!obj->as.string.orig) free(obj->as.string.ptr); break; case T_ARRAY: free(obj->as.array.ptr); @@ -538,17 +542,26 @@ obj_free(obj) free(obj->as.match.regs); if (obj->as.match.ptr) free(obj->as.match.ptr); break; + case T_FILE: + io_fptr_finalize(obj->as.file.fptr); + free(obj->as.file.fptr); + break; case T_ICLASS: /* iClass shares table with the module */ + break; + case T_FLOAT: case T_VARMAP: + case T_TRUE: + case T_FALSE: break; + case T_BIGNUM: - free(obj->as.bignum.digits); + if (obj->as.bignum.digits) free(obj->as.bignum.digits); break; case T_NODE: - if (nd_type(obj) == NODE_SCOPE && obj->as.node.nd_tbl) { - free(obj->as.node.nd_tbl); + if (nd_type(obj) == NODE_SCOPE && obj->as.node.u1.tbl) { + free(obj->as.node.u1.tbl); } return; /* no need to free iv_tbl */ @@ -576,7 +589,7 @@ gc_mark_frame(frame) VALUE *tbl = frame->argv; while (n--) { - gc_mark(*tbl); + gc_mark_maybe(*tbl); tbl++; } } @@ -601,18 +614,23 @@ gc() gc_mark_frame(frame); } gc_mark(the_scope); + gc_mark(the_dyna_vars); FLUSH_REGISTER_WINDOWS; /* This assumes that all registers are saved into the jmp_buf */ setjmp(save_regs_gc_mark); - mark_locations((VALUE*)save_regs_gc_mark, - (VALUE*)(((char*)save_regs_gc_mark)+sizeof(save_regs_gc_mark))); - mark_locations(stack_start_ptr, (VALUE*) &stack_end); -#if defined(THINK_C) - mark_locations((VALUE*)((char*)stack_start_ptr + 2), + gc_mark_locations((VALUE*)save_regs_gc_mark, + (VALUE*)(((char*)save_regs_gc_mark)+sizeof(save_regs_gc_mark))); + gc_mark_locations(gc_stack_start, (VALUE*) &stack_end); +#ifdef THINK_C + gc_mark_locations((VALUE*)((char*)gc_stack_start + 2), (VALUE*)((char*)&stack_end + 2)); #endif +#ifdef THREAD + gc_mark_threads(); +#endif + /* mark protected global variables */ for (list = Global_List; list; list = list->next) { gc_mark(*list->varptr); @@ -631,7 +649,7 @@ init_stack() { VALUE start; - stack_start_ptr = &start; + gc_stack_start = &start; } void @@ -641,12 +659,87 @@ init_heap() add_heap(); } +static VALUE +os_live_obj(obj) + VALUE obj; +{ + int i; + int n = 0; + + for (i = 0; i < heaps_used; i++) { + RVALUE *p, *pend; + + p = heaps[i]; pend = p + HEAP_SLOTS; + for (;p < pend; p++) { + if (p->as.basic.flags) { + switch (TYPE(p)) { + case T_ICLASS: + case T_VARMAP: + case T_SCOPE: + case T_NODE: + continue; + case T_CLASS: + if (FL_TEST(p, FL_SINGLETON)) continue; + default: + rb_yield(p); + n++; + } + } + } + } + + return INT2FIX(n); +} + +static VALUE +os_obj_of(obj, of) + VALUE obj, of; +{ + int i; + int n = 0; + + for (i = 0; i < heaps_used; i++) { + RVALUE *p, *pend; + + p = heaps[i]; pend = p + HEAP_SLOTS; + for (;p < pend; p++) { + if (p->as.basic.flags) { + switch (TYPE(p)) { + case T_ICLASS: + case T_VARMAP: + case T_SCOPE: + case T_NODE: + continue; + case T_CLASS: + if (FL_TEST(p, FL_SINGLETON)) continue; + default: + if (obj_is_kind_of(p, of)) { + rb_yield(p); + n++; + } + } + } + } + } + + return INT2FIX(n); +} + +extern VALUE cModule; + void Init_GC() { + VALUE mObSpace; + mGC = rb_define_module("GC"); rb_define_singleton_method(mGC, "start", gc, 0); rb_define_singleton_method(mGC, "enable", gc_s_enable, 0); rb_define_singleton_method(mGC, "disable", gc_s_disable, 0); rb_define_method(mGC, "garbage_collect", gc, 0); + + mObSpace = rb_define_module("ObjectSpace"); + rb_define_module_function(mObSpace, "each_live_object", os_live_obj, 0); + rb_define_module_function(mObSpace, "each_object_of", os_obj_of, 1); + rb_define_module_function(mObSpace, "garbage_collect", gc, 0); } @@ -48,7 +48,7 @@ # endif /* !USG */ #endif /* !HAVE_DIRENT_H */ -#if defined (_POSIX_SOURCE) +#if defined (_POSIX_SOURCE) || defined(DJGPP) /* Posix does not require that the d_ino field be present, and some systems do not provide it. */ # define REAL_DIR_ENTRY(dp) 1 @@ -70,11 +70,15 @@ # define bcopy(s, d, n) (memcpy ((d), (s), (n))) +#ifdef _AIX +#pragma alloca +#else #if defined(HAVE_ALLOCA_H) && !defined(__GNUC__) #include <alloca.h> #else char *alloca (); #endif +#endif #include "fnmatch.h" @@ -376,7 +380,9 @@ char ** glob_filename (pathname) char *pathname; { +#ifndef strrchr char *strrchr(); +#endif char **result; unsigned int result_size; @@ -6,7 +6,7 @@ $Date: 1995/01/10 10:42:26 $ created at: Mon Nov 22 18:51:18 JST 1993 - Copyright (C) 1993-1995 Yukihiro Matsumoto + Copyright (C) 1993-1996 Yukihiro Matsumoto ************************************************/ @@ -27,38 +27,85 @@ static VALUE envtbl; static ID hash; VALUE f_getenv(), f_setenv(); -static VALUE +static int rb_cmp(a, b) VALUE a, b; { - return rb_equal(a, b)?0:1; + if (FIXNUM_P(a)) { + if (FIXNUM_P(b)) return a != b; + } + + if (TYPE(a) == T_STRING) { + if (TYPE(b) == T_STRING) return str_cmp(a, b); + } + + return !rb_eql(a, b); } -static VALUE +static int rb_hash(a, mod) VALUE a; int mod; { - return rb_funcall(a, hash, 0) % mod; + unsigned int hval; + + switch (TYPE(a)) { + case T_FIXNUM: + hval = a; + break; + + case T_STRING: + hval = str_hash(a); + break; + + default: + hval = rb_funcall(a, hash, 0); + hval = FIX2INT(hval); + } + return hval % mod; } -#define ASSOC_KEY(a) RASSOC(a)->car -#define ASSOC_VAL(a) RASSOC(a)->cdr +static struct st_hash_type objhash = { + rb_cmp, + rb_hash, +}; static VALUE -hash_s_new(class) +hash_s_new(argc, argv, class) + int argc; + VALUE *argv; VALUE class; { + VALUE sz; + int size; + NEWOBJ(hash, struct RHash); OBJSETUP(hash, class, T_HASH); - hash->tbl = st_init_table(rb_cmp, rb_hash); + rb_scan_args(argc, argv, "01", &sz); + if (NIL_P(sz)) size = 0; + else size = NUM2INT(sz); + + hash->tbl = st_init_table_with_size(&objhash, size); return (VALUE)hash; } static VALUE hash_clone(); +VALUE +hash_new2(class) + VALUE class; +{ + return hash_s_new(0, 0, class); +} + +VALUE +hash_new() +{ + return hash_new2(cHash); +} + static VALUE hash_s_create(argc, argv, class) int argc; @@ -80,9 +127,9 @@ hash_s_create(argc, argv, class) } if (argc % 2 != 0) { - Fail("odd number args for Hash"); + ArgError("odd number args for Hash"); } - hash = (struct RHash*)hash_s_new(class); + hash = (struct RHash*)hash_new2(class); for (i=0; i<argc; i+=2) { st_insert(hash->tbl, argv[i], argv[i+1]); @@ -91,12 +138,6 @@ hash_s_create(argc, argv, class) return (VALUE)hash; } -VALUE -hash_new() -{ - return hash_s_new(cHash); -} - static VALUE hash_clone(hash) struct RHash *hash; @@ -109,7 +150,7 @@ hash_clone(hash) return (VALUE)hash2; } -static VALUE +VALUE hash_aref(hash, key) struct RHash *hash; VALUE key; @@ -128,29 +169,21 @@ hash_indexes(hash, args) struct RArray *args; { VALUE *p, *pend; - struct RArray *new_hash; + struct RArray *indexes; int i = 0; - if (!args || args->len == 0) { - Fail("wrong # of argment"); - } - else if (args->len == 1) { - if (TYPE(args->ptr[0])) { - args = (struct RArray*)rb_to_a(args->ptr[0]); - } - else { - args = (struct RArray*)args->ptr[0]; - } + if (!args || NIL_P(args)) { + return ary_new2(0); } - new_hash = (struct RArray*)ary_new2(args->len); + indexes = (struct RArray*)ary_new2(args->len); p = args->ptr; pend = p + args->len; while (p < pend) { - new_hash->ptr[i++] = hash_aref(hash, *p++); + indexes->ptr[i++] = hash_aref(hash, *p++); } - new_hash->len = i; - return (VALUE)new_hash; + indexes->len = i; + return (VALUE)indexes; } static VALUE @@ -162,6 +195,7 @@ hash_delete(hash, key) if (st_delete(hash->tbl, &key, &val)) return val; + if (iterator_p()) rb_yield(Qnil); return Qnil; } @@ -209,7 +243,7 @@ static VALUE hash_delete_if(hash) struct RHash *hash; { - st_foreach(hash->tbl, delete_if_i, Qnil); + st_foreach(hash->tbl, delete_if_i, 0); return (VALUE)hash; } @@ -235,7 +269,7 @@ hash_aset(hash, key, val) struct RHash *hash; VALUE key, val; { - if (val == Qnil) { + if (NIL_P(val)) { hash_delete(hash, key); return Qnil; } @@ -253,6 +287,15 @@ hash_length(hash) return INT2FIX(hash->tbl->num_entries); } +VALUE +hash_empty_p(hash) + struct RHash *hash; +{ + if (hash->tbl->num_entries == 0) + return TRUE; + return FALSE; +} + static int each_value_i(key, value) VALUE key, value; @@ -327,15 +370,14 @@ inspect_i(key, value, str) struct RString *str; { VALUE str2; - ID inspect = rb_intern("inspect"); if (str->len > 1) { str_cat(str, ", ", 2); } - str2 = rb_funcall(key, inspect, 0, 0); + str2 = rb_inspect(key); str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len); str_cat(str, "=>", 2); - str2 = rb_funcall(value, inspect, 0, 0); + str2 = rb_inspect(value); str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len); return ST_CONTINUE; @@ -554,7 +596,7 @@ f_getenv(obj, name) Check_Type(name, T_STRING); if (strlen(name->ptr) != name->len) - Fail("Bad environment name"); + ArgError("Bad environment name"); env = getenv(name->ptr); if (env) { @@ -569,7 +611,7 @@ f_setenv(obj, name, value) struct RString *name, *value; { Check_Type(name, T_STRING); - if (value == Qnil) { + if (NIL_P(value)) { env_delete(obj, name); return Qnil; } @@ -577,9 +619,9 @@ f_setenv(obj, name, value) Check_Type(value, T_STRING); if (strlen(name->ptr) != name->len) - Fail("Bad environment name"); + ArgError("Bad environment name"); if (strlen(value->ptr) != value->len) - Fail("Bad environment value"); + ArgError("Bad environment value"); setenv(name->ptr, value->ptr, 1); return TRUE; @@ -588,7 +630,7 @@ f_setenv(obj, name, value) static VALUE env_to_s() { - return str_new2("$ENV"); + return str_new2("ENV"); } void @@ -603,7 +645,7 @@ Init_Hash() rb_include_module(cHash, mEnumerable); - rb_define_singleton_method(cHash, "new", hash_s_new, 0); + rb_define_singleton_method(cHash, "new", hash_s_new, -1); rb_define_singleton_method(cHash, "[]", hash_s_create, -1); rb_define_method(cHash,"clone", hash_clone, 0); @@ -619,6 +661,8 @@ Init_Hash() rb_define_method(cHash,"indexes", hash_indexes, -2); rb_define_method(cHash,"length", hash_length, 0); rb_define_alias(cHash, "size", "length"); + rb_define_method(cHash,"empty?", hash_empty_p, 0); + rb_define_method(cHash,"each", hash_each_pair, 0); rb_define_method(cHash,"each_value", hash_each_value, 0); rb_define_method(cHash,"each_key", hash_each_key, 0); @@ -632,8 +676,11 @@ Init_Hash() rb_define_method(cHash,"delete_if", hash_delete_if, 0); rb_define_method(cHash,"clear", hash_clear, 0); + rb_define_method(cHash,"include?", hash_has_key, 1); rb_define_method(cHash,"has_key?", hash_has_key, 1); rb_define_method(cHash,"has_value?", hash_has_value, 1); + rb_define_method(cHash,"key?", hash_has_key, 1); + rb_define_method(cHash,"value?", hash_has_value, 1); envtbl = obj_alloc(cObject); rb_extend_object(envtbl, mEnumerable); @@ -645,5 +692,5 @@ Init_Hash() rb_define_singleton_method(envtbl,"to_s", env_to_s, 0); rb_define_readonly_variable("$ENV", &envtbl); - rb_define_const(cKernel, "ENV", envtbl); + rb_define_global_const("ENV", envtbl); } @@ -6,7 +6,7 @@ $Date: 1995/01/10 10:42:38 $ created at: Tue Dec 28 16:01:58 JST 1993 - Copyright (C) 1993-1995 Yukihiro Matsumoto + Copyright (C) 1993-1996 Yukihiro Matsumoto ************************************************/ @@ -18,16 +18,20 @@ rb_call_inits() Init_sym(); Init_var_tables(); Init_Object(); +#ifdef THREAD + Init_Thread(); +#endif Init_GC(); Init_eval(); Init_Comparable(); Init_Enumerable(); + Init_String(); + Init_Exception(); Init_Numeric(); Init_Bignum(); Init_Array(); Init_Hash(); Init_Struct(); - Init_String(); Init_Regexp(); Init_pack(); Init_Range(); @@ -6,7 +6,7 @@ $Date: 1995/01/10 10:42:39 $ created at: Fri Oct 15 18:08:59 JST 1993 - Copyright (C) 1993-1995 Yukihiro Matsumoto + Copyright (C) 1993-1996 Yukihiro Matsumoto ************************************************/ @@ -16,8 +16,9 @@ #include <errno.h> #include <sys/types.h> -#include <sys/stat.h> +#ifndef DJGPP #include <sys/ioctl.h> +#endif #ifdef HAVE_SYS_TIME_H # include <sys/time.h> @@ -31,26 +32,94 @@ struct timeval { #include <vfork.h> #endif +#include <sys/stat.h> + +#ifdef DJGPP +#include <fcntl.h> +#endif + VALUE rb_ad_string(); VALUE cIO; extern VALUE cFile; +VALUE eEOFError; +VALUE eIOError; VALUE rb_stdin, rb_stdout, rb_stderr, rb_defout; VALUE FS, OFS; VALUE RS, ORS; +VALUE RS_default; static VALUE argf; ID id_write, id_fd, id_print_on; +VALUE lastline_get(); +void lastline_set(); + extern char *inplace; +struct timeval time_timeval(); + +#ifdef _STDIO_USES_IOSTREAM /* GNU libc */ +# ifdef _IO_fpos_t +# define READ_DATA_PENDING(fp) ((fp)->_IO_read_ptr != (fp)->_IO_read_end) +# else +# define READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr) +# endif +#else +# ifdef FILE_COUNT +# define READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0) +# else +/* requires systems own version of the ReadDataPending() */ +extern int ReadDataPending(); +# define READ_DATA_PENDING(fp) ReadDataPending(fp) +# endif +#endif + +#ifndef THREAD +# define READ_CHECK(fp) 0 +#else +# define READ_CHECK(fp) do {\ + if (!READ_DATA_PENDING(fp)) thread_wait_fd(fileno(fp));\ +} while(0) +#endif + +void +eof_error() +{ + Raise(eEOFError, "End of file reached"); +} + +void +io_writable(fptr) + OpenFile *fptr; +{ + if (!(fptr->mode & FMODE_WRITABLE)) { + Raise(eIOError, "not opened for writing"); + } +} + +void +io_readable(fptr) + OpenFile *fptr; +{ + if (!(fptr->mode & FMODE_READABLE)) { + Raise(eIOError, "not opened for reading"); + } +} + +static void +closed() +{ + Raise(eIOError, "closed stream"); +} + /* writing functions */ VALUE -io_write(obj, str) - VALUE obj; +io_write(io, str) + VALUE io; struct RString *str; { OpenFile *fptr; @@ -58,19 +127,17 @@ io_write(obj, str) VALUE out; int n; - GetOpenFile(obj, fptr); - if (!(fptr->mode & FMODE_WRITABLE)) { - Fail("not opened for writing"); - } + GetOpenFile(io, fptr); + io_writable(fptr); f = (fptr->f2) ? fptr->f2 : fptr->f; - if (f == NULL) Fail("closed stream"); + if (f == NULL) closed(); if (TYPE(str) != T_STRING) str = (struct RString*)obj_as_string(str); if (str->len == 0) return INT2FIX(0); - n = fwrite(str->ptr, sizeof(char), str->len, f); + n = fwrite(str->ptr, 1, str->len, f); if (n == 0 || ferror(f)) { rb_sys_fail(fptr->path); } @@ -82,44 +149,43 @@ io_write(obj, str) } static VALUE -io_puts(obj, str) - VALUE obj, str; +io_puts(io, str) + VALUE io, str; { - io_write(obj, str); - return obj; + io_write(io, str); + return io; } static VALUE -io_flush(obj) - VALUE obj; +io_flush(io) + VALUE io; { OpenFile *fptr; FILE *f; - GetOpenFile(obj, fptr); - if (!(fptr->mode & FMODE_WRITABLE)) { - Fail("not opend for writing"); - } + GetOpenFile(io, fptr); + io_writable(fptr); f = (fptr->f2) ? fptr->f2 : fptr->f; - if (f == NULL) Fail("closed stream"); + if (f == NULL) closed(); - if (fflush(f) == EOF) rb_sys_fail(Qnil); + if (fflush(f) == EOF) rb_sys_fail(0); - return obj; + return io; } static VALUE -io_eof(obj) - VALUE obj; +io_eof(io) + VALUE io; { OpenFile *fptr; int ch; - GetOpenFile(obj, fptr); -#ifdef STDSTDIO /* (the code works without this) */ - if (fptr->f->_cnt > 0) /* cheat a little, since */ - return FALSE; /* this is the most usual case */ -#endif + GetOpenFile(io, fptr); + io_readable(fptr); + if (fptr->f == NULL) closed(); + + if (READ_DATA_PENDING(fptr->f)) return FALSE; + if (feof(fptr->f)) return TRUE; TRAP_BEG; ch = getc(fptr->f); @@ -129,31 +195,27 @@ io_eof(obj) (void)ungetc(ch, fptr->f); return FALSE; } -#ifdef STDSTDIO - if (fptr->f->_cnt < -1) - fptr->f->_cnt = -1; -#endif return TRUE; } static VALUE -io_sync(obj) - VALUE obj; +io_sync(io) + VALUE io; { OpenFile *fptr; - GetOpenFile(obj, fptr); + GetOpenFile(io, fptr); return (fptr->mode & FMODE_SYNC) ? TRUE : FALSE; } static VALUE -io_set_sync(obj, mode) - VALUE obj, mode; |