require_relative '../../spec_helper' require_relative 'fixtures/classes' describe 'TracePoint#self' do it 'return the trace object from event' do trace = nil TracePoint.new(:line) { |tp| next unless TracePointSpec.target_thread? trace = tp.self }.enable do trace.equal?(self).should be_true end end it 'return the class object from a class event' do trace = nil TracePoint.new(:class) { |tp| next unless TracePointSpec.target_thread? trace = tp.self }.enable do class TracePointSpec::C end end trace.should equal TracePointSpec::C end end ='this.form.submit();'> The Ruby Programming Language
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYukihiro Matsumoto <matz@ruby-lang.org>1995-03-15 14:59:18 +0900
committerTakashi Kokubun <takashikkbn@gmail.com>2019-08-17 22:09:31 +0900
commitd349889e770a2078c247d9d28070e86a54b856f4 (patch)
tree8bdbf87f3ff78ef237c4ff8efa061fbb8dc5a226
parent881c5a9c320c637ee0f6526b40cf70c1379ab656 (diff)
version 0.69v0_69
https://cache.ruby-lang.org/pub/ruby/1.0/ruby-0.69.tar.gz Wed Mar 15 14:59:18 1995 Yukihiro Matsumoto (matz@ix-02) * version 0.69 * eval.c(method_missing): unknownから名称変更. * eval.c(single_method_added): 特異メソッドが定義された時に呼ばれ るメソッド.hookとして使える.実際に定義される直前に呼ばれる. Tue Mar 14 14:46:44 1995 Yukihiro Matsumoto (matz@ix-02) * ruby.c(proc_options): 引数の解析を自分でやることにより引数指定の 方法がperlに近付いた.getopt_longはもう使わない. * dir.c(glob): `{}'のネストを許すようにした. Mon Mar 13 17:56:25 1995 Yukihiro Matsumoto (matz@ix-02) * glob.c: Glob(ワイルドカードオブジェクト)はなくなった.ワイルドカー ドの展開はDir.glob(文字列)を使う.ワイルドカードのマッチは正規表 現で代用. Fri Mar 10 18:35:46 1995 Yukihiro Matsumoto (matz@ix-02) * eval.c: Mathのようなモジュールは自分自身でextendする. * eval.c: クラスやモジュールを定義した既に同名のものがあれば追加定 義となるように.ただし.superクラスの違いなどはチェックする. * regex.c: debug. * math.c: 定数PIとEを定義. Thu Mar 9 21:35:12 1995 Yukihiro Matsumoto (matz@ix-02) * regex.c: EUC,SJISモードでは0x80以上の8進,16進リテラルを禁止. * regex.c: クラス内でも数値リテラル・文字クラスが使えるようした. Wed Mar 8 17:39:05 1995 Yukihiro Matsumoto (matz@ix-02) * regex.c: \200など括弧の数以上の表現は8進リテラルと解釈する.ただ し,\1から\9までは例外. * regex.c: \9以上のリファレンスも有効にした. Tue Mar 7 14:26:01 1995 Yukihiro Matsumoto (matz@ix-02) * eval.c(public/private): スコープ制御メソッドの名称変更.静的なア クセスも出来るようにしてみたが,不採用. Mon Mar 6 19:34:32 1995 Yukihiro Matsumoto (matz@ix-02) * eval.c(inlcude): メソッド化.動的にモジュールをインクルードでき るように.さらに任意のオブジェクトにもモジュールをインクルードで きるメソッド `extend'も用意した. * parse.y: 文法からincludeを削除.メソッド化. Tue Feb 28 15:35:10 1995 Yukihiro Matsumoto (matz@ix-02) * parse.y: 配列,連想配列の最後に`,'をおけるように.
Diffstat
-rw-r--r--ChangeLog63
-rw-r--r--MANIFEST6
-rw-r--r--Makefile.in24
-rw-r--r--class.c6
-rw-r--r--dict.c3
-rw-r--r--dir.c105
-rw-r--r--env.h3
-rw-r--r--error.c9
-rw-r--r--etc.c15
-rw-r--r--eval.c167
-rw-r--r--file.c56
-rw-r--r--getopt.c660
-rw-r--r--getopt.h128
-rw-r--r--getopt1.c162
-rw-r--r--glob.c678
-rw-r--r--gnuglob.c580
-rw-r--r--ident.h11
-rw-r--r--inits.c1
-rw-r--r--io.c3
-rw-r--r--math.c24
-rw-r--r--node.h9
-rw-r--r--object.c26
-rw-r--r--parse.y290
-rw-r--r--process.c29
-rw-r--r--re.c163
-rw-r--r--re.h17
-rw-r--r--regex.c1329
-rw-r--r--regex.h52
-rw-r--r--ruby.149
-rw-r--r--ruby.c195
-rw-r--r--ruby.h2
-rw-r--r--sample/Artistic0
-rw-r--r--sample/evaldef.rb4
-rw-r--r--sample/export.rb32
-rw-r--r--sample/exyacc.rb2
-rw-r--r--sample/from.rb4
-rw-r--r--sample/opt_x.rb0
-rw-r--r--sample/ruby-mode.el120
-rwxr-xr-xsample/uumerge.rb20
-rw-r--r--spec118
-rw-r--r--string.c25
-rw-r--r--util.c53
-rw-r--r--util.h16
-rw-r--r--variable.c11
-rw-r--r--version.h4
45 files changed, 2081 insertions, 3193 deletions
diff --git a/ChangeLog b/ChangeLog
index 78d6488e6d..eac8efba2a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,66 @@
+Wed Mar 15 14:59:18 1995 Yukihiro Matsumoto (matz@ix-02)
+
+ * version 0.69
+
+ * eval.c(method_missing): unknown̾ѹ
+
+ * eval.c(single_method_added): ðۥ᥽åɤ줿˸ƤФ
+ ᥽åɡhookȤƻȤ롥ºݤľ˸ƤФ롥
+
+Tue Mar 14 14:46:44 1995 Yukihiro Matsumoto (matz@ix-02)
+
+ * ruby.c(proc_options): βϤʬǤ뤳Ȥˤ
+ ˡperl˶դgetopt_longϤ⤦Ȥʤ
+
+ * dir.c(glob): `{}'ΥͥȤ褦ˤ
+
+Mon Mar 13 17:56:25 1995 Yukihiro Matsumoto (matz@ix-02)
+
+ * glob.c: Glob(磻ɥɥ֥)Ϥʤʤä磻ɥ
+ ɤŸDir.glob(ʸ)Ȥ磻ɥɤΥޥåɽ
+ ѡ
+
+Fri Mar 10 18:35:46 1995 Yukihiro Matsumoto (matz@ix-02)
+
+ * eval.c: MathΤ褦ʥ⥸塼ϼʬȤextend롥
+
+ * eval.c: 饹⥸塼Ʊ̾ΤΤɲ
+ Ȥʤ褦ˡsuper饹ΰ㤤ʤɤϥå롥
+
+ * regex.c: debug.
+
+ * math.c: PIE
+
+Thu Mar 9 21:35:12 1995 Yukihiro Matsumoto (matz@ix-02)
+
+ * regex.c: EUC,SJIS⡼ɤǤ0x80ʾ8ʡ16ʥƥػߡ
+
+ * regex.c: 饹Ǥͥƥ롦ʸ饹Ȥ褦
+
+Wed Mar 8 17:39:05 1995 Yukihiro Matsumoto (matz@ix-02)
+
+ * regex.c: \200ʤɳ̤οʾɽ8ʥƥȲ᤹롥
+ \1\9ޤǤ㳰
+
+ * regex.c: \9ʾΥե󥹤ͭˤ
+
+Tue Mar 7 14:26:01 1995 Yukihiro Matsumoto (matz@ix-02)
+
+ * eval.c(public/private): ᥽åɤ̾ѹŪʥ
+ 褦ˤƤߤԺѡ
+
+Mon Mar 6 19:34:32 1995 Yukihiro Matsumoto (matz@ix-02)
+
+ * eval.c(inlcude): ᥽åɲưŪ˥⥸塼򥤥󥯥롼ɤǤ
+ 褦ˡǤդΥ֥Ȥˤ⥸塼򥤥󥯥롼ɤ
+ ᥽å `extend'Ѱդ
+
+ * parse.y: ʸˡinclude᥽åɲ
+
+Tue Feb 28 15:35:10 1995 Yukihiro Matsumoto (matz@ix-02)
+
+ * parse.y: ϢκǸ`,'򤪤褦ˡ
+
Fri Feb 24 13:15:43 1995 Yukihiro Matsumoto (matz@ix-02)
* version 0.68
diff --git a/MANIFEST b/MANIFEST
index 429e921074..06b4a8ccb2 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -27,11 +27,7 @@ file.c
fnmatch.c
fnmatch.h
gc.c
-getopt.c
-getopt.h
-getopt1.c
glob.c
-gnuglob.c
ident.h
inits.c
io.c
@@ -62,6 +58,8 @@ st.h
string.c
struct.c
time.c
+util.h
+util.c
variable.c
version.c
version.h
diff --git a/Makefile.in b/Makefile.in
index b0c6eb5ea9..8f818473ad 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -28,7 +28,6 @@ bindir = $(exec_prefix)/bin
HDRS = defines.h \
dln.h \
- getopt.h \
ident.h \
io.h \
node.h \
@@ -54,10 +53,7 @@ OBJS = array.o \
file.o \
fnmatch.o \
gc.o \
- getopt.o \
- getopt1.o \
glob.o \
- gnuglob.o \
inits.o \
io.o \
main.o \
@@ -79,6 +75,7 @@ OBJS = array.o \
string.o \
struct.o \
time.o \
+ util.o \
variable.o \
version.o \
$(MISSING)
@@ -142,19 +139,19 @@ array.o: array.c ruby.h config.h defines.h
bignum.o: bignum.c ruby.h config.h defines.h
class.o: class.c ruby.h config.h defines.h env.h node.h st.h
compar.o: compar.c ruby.h config.h defines.h
+cons.o: cons.c ruby.h config.h defines.h
dbm.o: dbm.c ruby.h config.h defines.h
dict.o: dict.c ruby.h config.h defines.h st.h
dir.o: dir.c ruby.h config.h defines.h
-dln.o: dln.c defines.h dln.h
+dln.o: dln.c config.h defines.h dln.h st.h
enum.o: enum.c ruby.h config.h defines.h
error.o: error.c ruby.h config.h defines.h env.h
etc.o: etc.c ruby.h config.h defines.h
eval.o: eval.c ruby.h config.h defines.h ident.h env.h node.h st.h
file.o: file.c ruby.h config.h defines.h io.h
-fnmatch.o: fnmatch.c fnmatch.h
-gc.o: gc.c ruby.h config.h defines.h env.h st.h
-glob.o: glob.c ruby.h config.h defines.h fnmatch.h
-gnuglob.o: gnuglob.c fnmatch.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
+glob.o: glob.c config.h fnmatch.h
inits.o: inits.c ruby.h config.h defines.h
io.o: io.c ruby.h config.h defines.h io.h
main.o: main.c
@@ -166,13 +163,16 @@ process.o: process.c ruby.h config.h defines.h st.h
random.o: random.c ruby.h config.h defines.h
range.o: range.c ruby.h config.h defines.h
re.o: re.c ruby.h config.h defines.h re.h regex.h
-regex.o: regex.c defines.h regex.h
-ruby.o: ruby.c ruby.h config.h defines.h re.h regex.h getopt.h
+regex.o: regex.c config.h defines.h regex.h util.h
+ruby.o: ruby.c ruby.h config.h defines.h re.h regex.h
+signal.o: signal.c ruby.h config.h defines.h
socket.o: socket.c ruby.h config.h defines.h io.h
sprintf.o: sprintf.c ruby.h config.h defines.h
-st.o: st.c st.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
+tclglob.o: tclglob.c
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 ident.h st.h
version.o: version.c ruby.h config.h defines.h version.h
diff --git a/class.c b/class.c
index a7fbf7a2f5..00b6b8805f 100644
--- a/class.c
+++ b/class.c
@@ -230,7 +230,7 @@ rb_define_method(class, name, func, argc)
VALUE (*func)();
int argc;
{
- rb_add_method(class, rb_intern(name), NEW_CFUNC(func, argc), 0);
+ rb_add_method(class, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PUBLIC);
}
void
@@ -238,7 +238,7 @@ rb_undef_method(class, name)
struct RClass *class;
char *name;
{
- rb_add_method(class, rb_intern(name), Qnil, 0);
+ rb_add_method(class, rb_intern(name), Qnil, NOEX_PUBLIC);
}
void
@@ -248,7 +248,7 @@ rb_define_private_method(class, name, func, argc)
VALUE (*func)();
int argc;
{
- rb_add_method(class, rb_intern(name), NEW_CFUNC(func, argc), 1);
+ rb_add_method(class, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PRIVATE);
}
VALUE
diff --git a/dict.c b/dict.c
index 364a1ac99f..c7bc6d454d 100644
--- a/dict.c
+++ b/dict.c
@@ -615,12 +615,13 @@ Init_Dict()
rb_define_method(C_Dict,"has_value", Fdic_has_value, 1);
envtbl = obj_alloc(C_Object);
+ rb_extend_object(envtbl, M_Enumerable);
+
rb_define_single_method(envtbl,"[]", Fgetenv, 1);
rb_define_single_method(envtbl,"[]=", Fsetenv, 2);
rb_define_single_method(envtbl,"each", Fenv_each, 0);
rb_define_single_method(envtbl,"delete", Fenv_delete, 1);
rb_define_single_method(envtbl,"to_s", Fenv_to_s, 0);
- rb_include_module(CLASS_OF(envtbl), M_Enumerable);
rb_define_variable("$ENV", &envtbl, Qnil, rb_readonly_hook, 0);
rb_define_const(C_Kernel, "ENV", envtbl);
diff --git a/dir.c b/dir.c
index f20e555a2f..f50c760e2f 100644
--- a/dir.c
+++ b/dir.c
@@ -237,6 +237,108 @@ Sdir_rmdir(obj, dir)
return TRUE;
}
+#define isdelim(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\0')
+
+char **glob_filename();
+
+static void
+push_globs(ary, s)
+ VALUE ary;
+ char *s;
+{
+ char **fnames, **ff;
+
+ fnames = glob_filename(s);
+ if (fnames == (char**)-1) rb_sys_fail(s);
+ ff = fnames;
+ while (*ff) {
+ ary_push(ary, str_new2(*ff));
+ free(*ff);
+ ff++;
+ }
+ free(fnames);
+}
+
+static int
+push_braces(ary, s)
+ VALUE ary;
+ char *s;
+{
+ char buf[MAXPATHLEN];
+ char *p, *t, *b;
+ char *lbrace, *rbrace;
+
+ p = s;
+ lbrace = rbrace = Qnil;
+ while (*p) {
+ if (*p == '{' && !lbrace) lbrace = p;
+ if (*p == '}' && lbrace) rbrace = p;
+ *p++;
+ }
+
+ if (lbrace) {
+ memcpy(buf, s, lbrace-s);
+ b = buf + (lbrace-s);
+ p = lbrace;
+ while (*p != '}') {
+ t = p + 1;
+ for (p = t; *p!='}' && *p!=','; p++) {
+ /* skip inner braces */
+ if (*p == '{') while (*p!='}') p++;
+ }
+ memcpy(b, t, p-t);
+ strcpy(b+(p-t), rbrace+1);
+ push_braces(ary, buf);
+ }
+ }
+ else {
+ push_globs(ary, s);
+ }
+}
+
+static VALUE
+Sdir_glob(dir, str)
+ VALUE dir;
+ struct RString *str;
+{
+ char *p, *pend;
+ char buf[MAXPATHLEN];
+ char *t, *t0;
+ int nest;
+ VALUE ary;
+
+ Check_Type(str, T_STRING);
+
+ ary = ary_new();
+
+ p = str->ptr;
+ pend = p + str->len;
+
+ while (p < pend) {
+ t = buf;
+ while (p < pend && isdelim(*p)) p++;
+ while (p < pend && !isdelim(*p)) {
+ *t++ = *p++;
+ }
+ *t = '\0';
+ t0 = buf;
+ nest = 0;
+ while (t0 < t) {
+ if (*t0 == '{') nest+=2;
+ if (*t0 == '}') nest+=3;
+ t0++;
+ }
+ if (nest == 0) {
+ push_globs(ary, buf);
+ }
+ else if (nest % 5 == 0) {
+ push_braces(ary, buf);
+ }
+ /* else unmatched braces */
+ }
+ return ary;
+}
+
Init_Dir()
{
extern VALUE M_Enumerable;
@@ -261,4 +363,7 @@ Init_Dir()
rb_define_single_method(C_Dir,"rmdir", Sdir_rmdir, 1);
rb_define_single_method(C_Dir,"delete", Sdir_rmdir, 1);
rb_define_single_method(C_Dir,"unlink", Sdir_rmdir, 1);
+
+ rb_define_single_method(C_Dir,"glob", Sdir_glob, 1);
+ rb_define_single_method(C_Dir,"[]", Sdir_glob, 1);
}
diff --git a/env.h b/env.h
index 2076c25608..f9786d1ae4 100644
--- a/env.h
+++ b/env.h
@@ -32,4 +32,7 @@ extern int rb_in_eval;
extern struct RClass *the_class;
+#define NOEX_PUBLIC 0
+#define NOEX_PRIVATE 1
+
#endif /* ENV_H */
diff --git a/error.c b/error.c
index d9dcbe0516..1e0363e736 100644
--- a/error.c
+++ b/error.c
@@ -25,8 +25,13 @@ err_sprintf(buf, fmt, args)
char *buf, *fmt;
va_list args;
{
- sprintf(buf, "%s:%d: ", sourcefile, sourceline);
- vsprintf((char*)buf+strlen(buf), fmt, args);
+ if (!sourcefile) {
+ vsprintf(buf, fmt, args);
+ }
+ else {
+ sprintf(buf, "%s:%d: ", sourcefile, sourceline);
+ vsprintf((char*)buf+strlen(buf), fmt, args);
+ }
if (buf[strlen(buf)-1] != '\n')
strcat(buf, "\n");
}
diff --git a/etc.c b/etc.c
index 141d979fad..130592ec78 100644
--- a/etc.c
+++ b/etc.c
@@ -179,14 +179,15 @@ VALUE M_Etc;
Init_Etc()
{
M_Etc = rb_define_module("Etc");
+ rb_extend_object(M_Etc, M_Etc);
- rb_define_module_function(M_Etc, "getlogin", Fetc_getlogin, 0);
+ rb_define_method(M_Etc, "getlogin", Fetc_getlogin, 0);
- rb_define_module_function(M_Etc, "getpwuid", Fetc_getpwuid, -1);
- rb_define_module_function(M_Etc, "getpwnam", Fetc_getpwnam, 1);
- rb_define_module_function(M_Etc, "passwd", Fetc_passwd, 0);
+ rb_define_method(M_Etc, "getpwuid", Fetc_getpwuid, -1);
+ rb_define_method(M_Etc, "getpwnam", Fetc_getpwnam, 1);
+ rb_define_method(M_Etc, "passwd", Fetc_passwd, 0);
- rb_define_module_function(M_Etc, "getgrgid", Fetc_getgrgid, 1);
- rb_define_module_function(M_Etc, "getgrnam", Fetc_getgrnam, 1);
- rb_define_module_function(M_Etc, "group", Fetc_group, 0);
+ rb_define_method(M_Etc, "getgrgid", Fetc_getgrgid, 1);
+ rb_define_method(M_Etc, "getgrnam", Fetc_getgrnam, 1);
+ rb_define_method(M_Etc, "group", Fetc_group, 0);
}
diff --git a/eval.c b/eval.c
index b0d8022074..58a8354864 100644
--- a/eval.c
+++ b/eval.c
@@ -448,6 +448,10 @@ ruby_init(argc, argv, envp)
POP_SCOPE();
the_scope = top_scope;
+ if (state == TAG_EXIT) {
+ rb_trap_exit();
+ exit(FIX2UINT(last_val));
+ }
if (state) {
PUSH_TAG();
error_print();
@@ -926,11 +930,21 @@ rb_eval(node)
int argc; VALUE *argv; /* used in SETUP_ARGS */
PUSH_ITER(ITER_NOT);
- recv = node->nd_recv?rb_eval(node->nd_recv):Qself;
+ recv = rb_eval(node->nd_recv);
SETUP_ARGS;
POP_ITER();
- return rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,
- node->nd_recv?0:1);
+ return rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0);
+ }
+ break;
+
+ case NODE_FCALL:
+ {
+ int argc; VALUE *argv; /* used in SETUP_ARGS */
+
+ PUSH_ITER(ITER_NOT);
+ SETUP_ARGS;
+ POP_ITER();
+ return rb_call(CLASS_OF(Qself),Qself,node->nd_mid,argc,argv,1);
}
break;
@@ -1093,6 +1107,9 @@ rb_eval(node)
case NODE_CONST:
return node->nd_cval;
+ case NODE_NTH_REF:
+ return re_nth_match(node->nd_nth);
+
case NODE_HASH:
{
NODE *list;
@@ -1139,7 +1156,6 @@ rb_eval(node)
case NODE_STR2:
case NODE_XSTR2:
case NODE_DREGX:
- case NODE_DGLOB:
{
VALUE str, str2;
NODE *list = node->nd_next;
@@ -1166,9 +1182,6 @@ rb_eval(node)
if (nd_type(node) == NODE_XSTR2) {
return rb_xstring(str);
}
- if (nd_type(node) == NODE_DGLOB) {
- return glob_new(str);
- }
return str;
}
@@ -1210,12 +1223,15 @@ rb_eval(node)
Fail("Can't define method \"%s\" for nil",
rb_id2name(node->nd_mid));
}
- rb_add_method(rb_single_class(recv),node->nd_mid,node->nd_defn,0);
+ rb_funcall(recv, rb_intern("single_method_added"),
+ 1, INT2FIX(node->nd_mid));
+ rb_add_method(rb_single_class(recv),node->nd_mid,node->nd_defn,
+ NOEX_PUBLIC);
}
return Qnil;
case NODE_UNDEF:
- rb_add_method(the_class, node->nd_mid, Qnil, 0);
+ rb_add_method(the_class, node->nd_mid, Qnil, NOEX_PUBLIC);
return Qnil;
case NODE_ALIAS:
@@ -1225,23 +1241,42 @@ rb_eval(node)
case NODE_CLASS:
{
VALUE super, class;
+ struct RClass *tmp;
if (node->nd_super) {
- super = rb_id2class(node->nd_super);
+ super = rb_const_get(the_class, node->nd_super);
if (super == Qnil) {
Fail("undefined superclass %s",
rb_id2name(node->nd_super));
}
}
else {
- super = C_Object;
- }
- if (verbose && rb_id2class(node->nd_cname)) {
- Warning("redefine class %s", rb_id2name(node->nd_cname));
+ super = Qnil;
}
- class = rb_define_class_id(node->nd_cname, super);
- rb_const_set(the_class, node->nd_cname, class);
+ if (rb_const_bound(the_class, node->nd_cname)) {
+ class = rb_const_get(the_class, 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)) {
+ tmp = RCLASS(tmp)->super;
+ }
+ while (TYPE(tmp) == T_ICLASS) {
+ tmp = RCLASS(tmp)->super;
+ }
+ if (tmp != super)
+ Fail("%s's superclass differs",
+ rb_id2name(node->nd_cname));
+ }
+ Warning("extending class %s", rb_id2name(node->nd_cname));
+ }
+ else {
+ if (super == Qnil) super = C_Object;
+ class = rb_define_class_id(node->nd_cname, super);
+ rb_const_set(the_class, node->nd_cname, class);
+ }
module_setup(class, node->nd_body);
return class;
@@ -1251,29 +1286,21 @@ rb_eval(node)
{
VALUE module;
- if (verbose && rb_id2class(node->nd_cname)) {
- Warning("redefine module %s", rb_id2name(node->nd_cname));
+ if (rb_const_bound(the_class, 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));
+ Warning("extending module %s", rb_id2name(node->nd_cname));
+ }
+ else {
+ module = rb_define_module_id(node->nd_cname);
+ rb_const_set(the_class, node->nd_cname, module);
}
-
- module = rb_define_module_id(node->nd_cname);
- rb_const_set(the_class, node->nd_cname, module);
module_setup(module, node->nd_body);
return module;
}
- case NODE_INC:
- {
- struct RClass *module;
-
- module = (struct RClass*)rb_const_get(CLASS_OF(Qself), node->nd_modl);
- if (module == Qnil) {
- Fail("undefined module %s", rb_id2name(node->nd_modl));
- }
- rb_include_module(the_class, module);
- }
- return Qnil;
-
default:
Bug("unknown node type %d", nd_type(node));
}
@@ -1706,7 +1733,7 @@ rb_ensure(b_proc, data1, e_proc, data2)
static int last_noex;
static VALUE
-Funknown(argc, argv, obj)
+Fmissing(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
@@ -1731,7 +1758,7 @@ Funknown(argc, argv, obj)
/* fake environment */
PUSH_ENV();
env = the_env->prev;
- MEMCPY(the_env, the_env->prev->prev, struct ENVIRON, 1);
+ MEMCPY(the_env, env->prev, struct ENVIRON, 1);
the_env->prev = env;
Fail(format,
@@ -1758,23 +1785,24 @@ rb_undefined(obj, id, argc, argv, noex)
last_noex = noex;
- return rb_funcall2(obj, rb_intern("unknown"), argc+1, nargv);
+ return rb_funcall2(obj, rb_intern("method_missing"), argc+1, nargv);
}
static VALUE
-rb_call(class, recv, mid, argc, argv, func)
+rb_call(class, recv, mid, argc, argv, scope)
struct RClass *class;
VALUE recv;
ID mid;
int argc;
VALUE *argv;
- int func;
+ int scope;
{
NODE *body;
int noex;
VALUE result;
struct cache_entry *ent;
int itr;
+ enum node_type type;
/* is it in the method cache? */
ent = cache + EXPR1(class, mid);
@@ -1793,8 +1821,13 @@ rb_call(class, recv, mid, argc, argv, func)
mid = id;
}
- if (!func && noex) {
- return rb_undefined(recv, mid, argc, argv, 1);
+ switch (noex) {
+ case NOEX_PUBLIC:
+ break;
+ case NOEX_PRIVATE:
+ if (scope == 0) /* receiver specified */
+ return rb_undefined(recv, mid, argc, argv, 1);
+ break;
}
switch (iter->iter) {
@@ -1806,6 +1839,13 @@ rb_call(class, recv, mid, argc, argv, func)
itr = ITER_NOT;
break;
}
+
+ type = nd_type(body);
+ if (type == NODE_ZSUPER) {
+ /* for re-scoped method */
+ return rb_call(class->super, recv, mid, argc, argv, scope?scope:1);
+ }
+
PUSH_ITER(itr);
PUSH_SELF(recv);
PUSH_ENV();
@@ -1814,7 +1854,7 @@ rb_call(class, recv, mid, argc, argv, func)
the_env->argc = argc;
the_env->argv = argv;
- switch (nd_type(body)) {
+ switch (type) {
case NODE_CFUNC:
{
int len = body->nd_argc;
@@ -1831,7 +1871,7 @@ rb_call(class, recv, mid, argc, argv, func)
result = (*body->nd_cfnc)(argc, argv, recv);
break;
case 0:
- result = (*body->nd_cfnc)(recv);
+ result = (*body->nd_cfnc)(recv);
break;
case 1:
result = (*body->nd_cfnc)(recv, argv[0]);
@@ -1930,8 +1970,6 @@ rb_call(class, recv, mid, argc, argv, func)
/* for attr get/set */
case NODE_ATTRSET:
case NODE_IVAR:
- /* for exported method */
- case NODE_ZSUPER:
return rb_eval(body);
default:
@@ -2281,8 +2319,41 @@ addpath(path)
}
}
-extern VALUE C_Kernel;
+static VALUE
+Fmod_include(argc, argv, module)
+ int argc;
+ VALUE *argv;
+ struct RClass *module;
+{
+ int i;
+ for (i=0; i<argc; i++) {
+ rb_include_module(module, argv[i]);
+ }
+ return (VALUE)module;
+}
+
+static VALUE
+Ftop_include(argc, argv)
+{
+ return Fmod_include(argc, argv, C_Object);
+}
+
+static VALUE
+Fobj_extend(argc, argv, obj)
+{
+ return Fmod_include(argc, argv, rb_single_class(obj));
+}
+
+void
+rb_extend_object(obj, module)
+ VALUE obj, module;
+{
+ rb_include_module(rb_single_class(obj), module);
+}
+
+extern VALUE C_Kernel;
+extern VALUE C_Module;
Init_eval()
{
@@ -2298,7 +2369,11 @@ Init_eval()
rb_define_private_method(C_Kernel, "eval", Feval, 1);
rb_define_private_method(C_Kernel, "iterator_p", Fiterator_p, 0);
rb_define_method(C_Kernel, "apply", Fapply, -1);
- rb_define_method(C_Kernel, "unknown", Funknown, -1);
+ rb_define_method(C_Kernel, "method_missing", Fmissing, -1);
+
+ rb_define_method(C_Module, "include", Fmod_include, -1);
+ rb_define_method(CLASS_OF(TopSelf), "include", Ftop_include, -1);
+ rb_define_method(C_Object, "extend", Fobj_extend, -1);
}
Init_load()
diff --git a/file.c b/file.c
index a1729dee55..3c861dafbc 100644
--- a/file.c
+++ b/file.c
@@ -1,4 +1,3 @@
-
/************************************************
file.c -
@@ -56,60 +55,24 @@ file_open(fname, mode)
}
static int
-apply2files0(func, args, arg, gl)
- void (*func)();
+apply2files(func, args, arg)
+ int (*func)();
struct RArray *args;
void *arg;
- int gl;
{
- int i, n;
+ int i;
VALUE path;
- for (i=n=0; i<args->len; i++) {
+ for (i=0; i<args->len; i++) {
path = args->ptr[i];
- if (TYPE(path) == T_STRING) {
- if (gl) {
- char buf[MAXPATHLEN];
- char *p, *s;
-
- s = buf;
- p = RSTRING(path)->ptr;
- while (*p) {
- switch (*s = *p++) {
- case '*': case '?':
- case '[': case '{':
- path = glob_new(path);
- goto glob;
- case '\\':
- if (*p == '\0') break;
- *s = *p++;
- }
- s++;
- }
- *s = '\0';
- (*func)(buf, arg);
- }
- else {
- (*func)(RSTRING(path)->ptr, arg);
- }
- n++;
- }
- else {
- extern VALUE C_Glob;
-
- if (!obj_is_kind_of(path, C_Glob)) {
- WrongType(path, T_STRING);
- }
- glob:
- n += apply2files0(func, rb_to_a(path), arg, 0);
- }
+ Check_Type(path, T_STRING);
+ if ((*func)(RSTRING(path)->ptr, arg) < 0)
+ rb_sys_fail(RSTRING(path)->ptr);
}
- return n;
+ return args->len;
}
-#define apply2files(func,args,arg) apply2files0(func,args,arg,1)
-
static VALUE
Ffile_tell(obj)
VALUE obj;
@@ -1131,6 +1094,7 @@ Init_File()
rb_define_method(M_FileTest, "k", Ftest_sticky, 1);
C_File = rb_define_class("File", C_IO);
+ rb_extend_object(C_File, M_FileTest);
rb_define_single_method(C_File, "stat", Sfile_stat, 1);
rb_define_single_method(C_File, "lstat", Sfile_lstat, 1);
@@ -1154,8 +1118,6 @@ Init_File()
rb_define_single_method(C_File, "umask", Sfile_umask, -1);
rb_define_single_method(C_File, "truncate", Sfile_truncate, 2);
- rb_include_module(CLASS_OF(C_File), M_FileTest);
-
rb_define_method(C_File, "stat", Ffile_stat, 0);
rb_define_method(C_File, "lstat", Ffile_lstat, 0);
diff --git a/getopt.c b/getopt.c
deleted file mode 100644
index bfc4013b29..0000000000
--- a/getopt.c
+++ /dev/null
@@ -1,660 +0,0 @@
-/* Getopt for GNU.
- NOTE: getopt is now part of the C library, so if you don't know what
- "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
- before changing it!
-
- Copyright (C) 1987, 88, 89, 90, 91, 1992 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU Library General Public License as published
- by the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include "config.h"
-
-#include <stdio.h>
-
-/* This needs to come after some library #include
- to get __GNU_LIBRARY__ defined. */
-#ifdef __GNU_LIBRARY__
-#include <stdlib.h>
-#include <string.h>
-#endif /* GNU C library. */
-
-
-#ifndef __STDC__
-#define const
-#endif
-
-/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
- long-named option. Because this is not POSIX.2 compliant, it is
- being phased out. */
-#define GETOPT_COMPAT
-
-/* This version of `getopt' appears to the caller like standard Unix `getopt'
- but it behaves differently for the user, since it allows the user
- to intersperse the options with the other arguments.
-
- As `getopt' works, it permutes the elements of ARGV so that,
- when it is done, all the options precede everything else. Thus
- all application programs are extended to handle flexible argument order.
-
- Setting the environment variable POSIXLY_CORRECT disables permutation.
- Then the behavior is completely standard.
-
- GNU application programs can use a third alternative mode in which
- they can distinguish the relative order of options and other arguments. */
-
-#include "getopt.h"
-
-/* For communication from `getopt' to the caller.
- When `getopt' finds an option that takes an argument,
- the argument value is returned here.
- Also, when `ordering' is RETURN_IN_ORDER,
- each non-option ARGV-element is returned here. */
-
-char *optarg = 0;
-
-/* Index in ARGV of the next element to be scanned.
- This is used for communication to and from the caller
- and for communication between successive calls to `getopt'.
-
- On entry to `getopt', zero means this is the first call; initialize.
-
- When `getopt' returns EOF, this is the index of the first of the
- non-option elements that the caller should itself scan.
-
- Otherwise, `optind' communicates from one call to the next
- how much of ARGV has been scanned so far. */
-
-int optind = 0;
-
-/* The next char to be scanned in the option-element
- in which the last option character we returned was found.
- This allows us to pick up the scan where we left off.
-
- If this is zero, or a null string, it means resume the scan
- by advancing to the next ARGV-element. */
-
-static char *nextchar;
-
-/* Callers store zero here to inhibit the error message
- for unrecognized options. */
-
-int opterr = 1;
-
-/* Describe how to deal with options that follow non-option ARGV-elements.
-
- If the caller did not specify anything,
- the default is REQUIRE_ORDER if the environment variable
- POSIXLY_CORRECT is defined, PERMUTE otherwise.
-
- REQUIRE_ORDER means don't recognize them as options;
- stop option processing when the first non-option is seen.
- This is what Unix does.
- This mode of operation is selected by either setting the environment
- variable POSIXLY_CORRECT, or using `+' as the first character
- of the list of option characters.
-
- PERMUTE is the default. We permute the contents of ARGV as we scan,
- so that eventually all the non-options are at the end. This allows options
- to be given in any order, even with programs that were not written to
- expect this.
-
- RETURN_IN_ORDER is an option available to programs that were written
- to expect options and other ARGV-elements in any order and that care about
- the ordering of the two. We describe each non-option ARGV-element
- as if it were the argument of an option with character code 1.
- Using `-' as the first character of the list of option characters
- selects this mode of operation.
-
- The special argument `--' forces an end of option-scanning regardless
- of the value of `ordering'. In the case of RETURN_IN_ORDER, only
- `--' can cause `getopt' to return EOF with `optind' != ARGC. */
-
-static enum
-{
- REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
-} ordering;
-
-#ifdef __GNU_LIBRARY__
-#include <string.h>
-#define my_index strchr
-#define my_bcopy(src, dst, n) memcpy ((dst), (src), (n))
-#else
-
-/* Avoid depending on library functions or files
- whose names are inconsistent. */
-
-char *getenv ();
-
-static char *
-my_index (string, chr)
- char *string;
- int chr;
-{
- while (*string)
- {
- if (*string == chr)
- return string;
- string++;
- }
- return 0;
-}
-
-static void
-my_bcopy (from, to, size)
- char *from, *to;
- int size;
-{
- int i;
- for (i = 0; i < size; i++)
- to[i] = from[i];
-}
-#endif /* GNU C library. */
-
-/* Handle permutation of arguments. */
-
-/* Describe the part of ARGV that contains non-options that have
- been skipped. `first_nonopt' is the index in ARGV of the first of them;
- `last_nonopt' is the index after the last of them. */
-
-static int first_nonopt;
-static int last_nonopt;
-
-/* Exchange two adjacent subsequences of ARGV.
- One subsequence is elements [first_nonopt,last_nonopt)
- which contains all the non-options that have been skipped so far.
- The other is elements [last_nonopt,optind), which contains all
- the options processed since those non-options were skipped.
-
- `first_nonopt' and `last_nonopt' are relocated so that they describe
- the new indices of the non-options in ARGV after they are moved. */
-
-static void
-exchange (argv)
- char **argv;
-{
- int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *);
- char **temp = (char **) malloc (nonopts_size);
-
- /* Interchange the two blocks of data in ARGV. */
-
- my_bcopy (&argv[first_nonopt], temp, nonopts_size);
- my_bcopy (&argv[last_nonopt], &argv[first_nonopt],
- (optind - last_nonopt) * sizeof (char *));
- my_bcopy (temp, &argv[first_nonopt + optind - last_nonopt], nonopts_size);
-
- free(temp);
-
- /* Update records for the slots the non-options now occupy. */
-
- first_nonopt += (optind - last_nonopt);
- last_nonopt = optind;
-}
-
-/* Scan elements of ARGV (whose length is ARGC) for option characters
- given in OPTSTRING.
-
- If an element of ARGV starts with '-', and is not exactly "-" or "--",
- then it is an option element. The characters of this element
- (aside from the initial '-') are option characters. If `getopt'
- is called repeatedly, it returns successively each of the option characters
- from each of the option elements.
-
- If `getopt' finds another option character, it returns that character,
- updating `optind' and `nextchar' so that the next call to `getopt' can
- resume the scan with the following option character or ARGV-element.
-
- If there are no more option characters, `getopt' returns `EOF'.
- Then `optind' is the index in ARGV of the first ARGV-element
- that is not an option. (The ARGV-elements have been permuted
- so that those that are not options now come last.)
-
- OPTSTRING is a string containing the legitimate option characters.
- If an option character is seen that is not listed in OPTSTRING,
- return '?' after printing an error message. If you set `opterr' to
- zero, the error message is suppressed but we still return '?'.
-
- If a char in OPTSTRING is followed by a colon, that means it wants an arg,
- so the following text in the same ARGV-element, or the text of the following
- ARGV-element, is returned in `optarg'. Two colons mean an option that
- wants an optional arg; if there is text in the current ARGV-element,
- it is returned in `optarg', otherwise `optarg' is set to zero.
-
- If OPTSTRING starts with `-' or `+', it requests different methods of
- handling the non-option ARGV-elements.
- See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
-
- Long-named options begin with `--' instead of `-'.
- Their names may be abbreviated as long as the abbreviation is unique
- or is an exact match for some defined option. If they have an
- argument, it follows the option name in the same ARGV-element, separated
- from the option name by a `=', or else the in next ARGV-element.
- When `getopt' finds a long-named option, it returns 0 if that option's
- `flag' field is nonzero, the value of the option's `val' field
- if the `flag' field is zero.
-
- The elements of ARGV aren't really const, because we permute them.
- But we pretend they're const in the prototype to be compatible
- with other systems.
-
- LONGOPTS is a vector of `struct option' terminated by an
- element containing a name which is zero.
-
- LONGIND returns the index in LONGOPT of the long-named option found.
- It is only valid when a long-named option has been found by the most
- recent call.
-
- If LONG_ONLY is nonzero, '-' as well as '--' can introduce
- long-named options. */
-
-int
-_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
- int argc;
- char *const *argv;
- const char *optstring;
- const struct option *longopts;
- int *longind;
- int long_only;
-{
- int option_index;
-
- optarg = 0;
-
- /* Initialize the internal data when the first call is made.
- Start processing options with ARGV-element 1 (since ARGV-element 0
- is the program name); the sequence of previously skipped
- non-option ARGV-elements is empty. */
-
- if (optind == 0)
- {
- first_nonopt = last_nonopt = optind = 1;
-
- nextchar = NULL;
-
- /* Determine how to handle the ordering of options and nonoptions. */
-
- if (optstring[0] == '-')
- {
- ordering = RETURN_IN_ORDER;
- ++optstring;
- }
- else if (optstring[0] == '+')
- {
- ordering = REQUIRE_ORDER;
- ++optstring;
- }
- else if (getenv ("POSIXLY_CORRECT") != NULL)
- ordering = REQUIRE_ORDER;
- else
- ordering = PERMUTE;
- }
-
- if (nextchar == NULL || *nextchar == '\0')
- {
- if (ordering == PERMUTE)
- {
- /* If we have just processed some options following some non-options,
- exchange them so that the options come first. */
-
- if (first_nonopt != last_nonopt && last_nonopt != optind)
- exchange ((char **) argv);
- else if (last_nonopt != optind)
- first_nonopt = optind;
-
- /* Now skip any additional non-options
- and extend the range of non-options previously skipped. */
-
- while (optind < argc
- && (argv[optind][0] != '-' || argv[optind][1] == '\0')
-#ifdef GETOPT_COMPAT
- && (longopts == NULL
- || argv[optind][0] != '+' || argv[optind][1] == '\0')
-#endif /* GETOPT_COMPAT */
- )
- optind++;
- last_nonopt = optind;
- }
-
- /* Special ARGV-element `--' means premature end of options.
- Skip it like a null option,
- then exchange with previous non-options as if it were an option,
- then skip everything else like a non-option. */
-
- if (optind != argc && !strcmp (argv[optind], "--"))
- {
- optind++;
-
- if (first_nonopt != last_nonopt && last_nonopt != optind)
- exchange ((char **) argv);
- else if (first_nonopt == last_nonopt)
- first_nonopt = optind;
- last_nonopt = argc;
-
- optind = argc;
- }
-
- /* If we have done all the ARGV-elements, stop the scan
- and back over any non-options that we skipped and permuted. */
-
- if (optind == argc)
- {
- /* Set the next-arg-index to point at the non-options
- that we previously skipped, so the caller will digest them. */
- if (first_nonopt != last_nonopt)
- optind = first_nonopt;
- return EOF;
- }
-
- /* If we have come to a non-option and did not permute it,
- either stop the scan or describe it to the caller and pass it by. */
-
- if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
-#ifdef GETOPT_COMPAT
- && (longopts == NULL
- || argv[optind][0] != '+' || argv[optind][1] == '\0')
-#endif /* GETOPT_COMPAT */
- )
- {
- if (ordering == REQUIRE_ORDER)
- return EOF;
- optarg = argv[optind++];
- return 1;
- }
-
- /* We have found another option-ARGV-element.
- Start decoding its characters. */
-
- nextchar = (argv[optind] + 1
- + (longopts != NULL && argv[optind][1] == '-'));
- }
-
- if (longopts != NULL
- && ((argv[optind][0] == '-'
- && (argv[optind][1] == '-' || long_only))
-#ifdef GETOPT_COMPAT
- || argv[optind][0] == '+'
-#endif /* GETOPT_COMPAT */
- ))
- {
- const struct option *p;
- char *s = nextchar;
- int exact = 0;
- int ambig = 0;
- const struct option *pfound = NULL;
- int indfound = 0;
- extern int strncmp();
-
- while (*s && *s != '=')
- s++;
-
- /* Test all options for either exact match or abbreviated matches. */
- for (p = longopts, option_index = 0; p->name;
- p++, option_index++)
- if (!strncmp (p->name, nextchar, s - nextchar))
- {
- if (s - nextchar == strlen (p->name))
- {
- /* Exact match found. */
- pfound = p;
- indfound = option_index;
- exact = 1;
- break;
- }
- else if (pfound == NULL)
- {
- /* First nonexact match found. */
- pfound = p;
- indfound = option_index;
- }
- else
- /* Second nonexact match found. */
- ambig = 1;
- }
-
- if (ambig && !exact)
- {
- if (opterr)
- fprintf (stderr, "%s: option `%s' is ambiguous\n",
- argv[0], argv[optind]);
- nextchar += strlen (nextchar);
- optind++;
- return '?';
- }
-
- if (pfound != NULL)
- {
- option_index = indfound;
- optind++;
- if (*s)
- {
- /* Don't test has_arg with >, because some C compilers don't
- allow it to be used on enums. */
- if (pfound->has_arg)
- optarg = s + 1;
- else
- {
- if (opterr)
- {
- if (argv[optind - 1][1] == '-')
- /* --option */
- fprintf (stderr,
- "%s: option `--%s' doesn't allow an argument\n",
- argv[0], pfound->name);
- else
- /* +option or -option */
- fprintf (stderr,
- "%s: option `%c%s' doesn't allow an argument\n",
- argv[0], argv[optind - 1][0], pfound->name);
- }
- nextchar += strlen (nextchar);
- return '?';
- }
- }
- else if (pfound->has_arg == 1)
- {
- if (optind < argc)
- optarg = argv[optind++];
- else
- {
- if (opterr)
- fprintf (stderr, "%s: option `%s' requires an argument\n",
- argv[0], argv[optind - 1]);
- nextchar += strlen (nextchar);
- return '?';
- }
- }
- nextchar += strlen (nextchar);
- if (longind != NULL)
- *longind = option_index;
- if (pfound->flag)
- {
- *(pfound->flag) = pfound->val;
- return 0;
- }
- return pfound->val;
- }
- /* Can't find it as a long option. If this is not getopt_long_only,
- or the option starts with '--' or is not a valid short
- option, then it's an error.
- Otherwise interpret it as a short option. */
- if (!long_only || argv[optind][1] == '-'
-#ifdef GETOPT_COMPAT
- || argv[optind][0] == '+'
-#endif /* GETOPT_COMPAT */
- || my_index (optstring, *nextchar) == NULL)
- {
- if (opterr)
- {
- if (argv[optind][1] == '-')
- /* --option */
- fprintf (stderr, "%s: unrecognized option `--%s'\n",
- argv[0], nextchar);
- else
- /* +option or -option */
- fprintf (stderr, "%s: unrecognized option `%c%s'\n",
- argv[0], argv[optind][0], nextchar);
- }
- nextchar = (char *) "";
- optind++;
- return '?';
- }
- }
-
- /* Look at and handle the next option-character. */
-
- {
- char c = *nextchar++;
- char *temp = my_index (optstring, c);
-
- /* Increment `optind' when we start to process its last character. */
- if (*nextchar == '\0')
- ++optind;
-
- if (temp == NULL || c == ':')
- {
- if (opterr)
- {
- if (c < 040 || c >= 0177)
- fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
- argv[0], c);
- else
- fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
- }
- return '?';
- }
- if (temp[1] == ':')
- {
- if (temp[2] == ':')
- {
- /* This is an option that accepts an argument optionally. */
- if (*nextchar != '\0')
- {
- optarg = nextchar;
- optind++;
- }
- else
- optarg = 0;
- nextchar = NULL;
- }
- else
- {
- /* This is an option that requires an argument. */
- if (*nextchar != '\0')
- {
- optarg = nextchar;
- /* If we end this ARGV-element by taking the rest as an arg,
- we must advance to the next element now. */
- optind++;
- }
- else if (optind == argc)
- {
- if (opterr)
- fprintf (stderr, "%s: option `-%c' requires an argument\n",
- argv[0], c);
- c = '?';
- }
- else
- /* We already incremented `optind' once;
- increment it again when taking next ARGV-elt as argument. */
- optarg = argv[optind++];
- nextchar = NULL;
- }
- }
- return c;
- }
-}
-
-int
-getopt (argc, argv, optstring)
- int argc;
- char *const *argv;
- const char *optstring;
-{
- return _getopt_internal (argc, argv, optstring,
- (const struct option *) 0,
- (int *) 0,
- 0);
-}
-
-#ifdef TEST
-
-/* Compile with -DTEST to make an executable for use in testing
- the above definition of `getopt'. */
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- int c;
- int digit_optind = 0;
-
- while (1)
- {
- int this_option_optind = optind ? optind : 1;
-
- c = getopt (argc, argv, "abc:d:0123456789");
- if (c == EOF)
- break;
-
- switch (c)
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (digit_optind != 0 && digit_optind != this_option_optind)
- printf ("digits occur in two different argv-elements.\n");
- digit_optind = this_option_optind;
- printf ("option %c\n", c);
- break;
-
- case 'a':
- printf ("option a\n");
- break;
-
- case 'b':
- printf ("option b\n");
- break;
-
- case 'c':
- printf ("option c with value `%s'\n", optarg);
- break;
-
- case '?':
- break;
-
- default:
- printf ("?? getopt returned character code 0%o ??\n", c);
- }
- }
-
- if (optind < argc)
- {
- printf ("non-option ARGV-elements: ");
- while (optind < argc)
- printf ("%s ", argv[optind++]);
- printf ("\n");
- }
-
- exit (0);
-}
-
-#endif /* TEST */
diff --git a/getopt.h b/getopt.h
deleted file mode 100644
index de027434f7..0000000000
--- a/getopt.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* Declarations for getopt.
- Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU Library General Public License as published
- by the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#ifndef _GETOPT_H
-#define _GETOPT_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* For communication from `getopt' to the caller.
- When `getopt' finds an option that takes an argument,
- the argument value is returned here.
- Also, when `ordering' is RETURN_IN_ORDER,
- each non-option ARGV-element is returned here. */
-
-extern char *optarg;
-
-/* Index in ARGV of the next element to be scanned.
- This is used for communication to and from the caller
- and for communication between successive calls to `getopt'.
-
- On entry to `getopt', zero means this is the first call; initialize.
-
- When `getopt' returns EOF, this is the index of the first of the
- non-option elements that the caller should itself scan.
-
- Otherwise, `optind' communicates from one call to the next
- how much of ARGV has been scanned so far. */
-
-extern int optind;
-
-/* Callers store zero here to inhibit the error message `getopt' prints
- for unrecognized options. */
-
-extern int opterr;
-
-/* Describe the long-named options requested by the application.
- The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
- of `struct option' terminated by an element containing a name which is
- zero.
-
- The field `has_arg' is:
- no_argument (or 0) if the option does not take an argument,
- required_argument (or 1) if the option requires an argument,
- optional_argument (or 2) if the option takes an optional argument.
-
- If the field `flag' is not NULL, it points to a variable that is set
- to the value given in the field `val' when the option is found, but
- left unchanged if the option is not found.
-
- To have a long-named option do something other than set an `int' to
- a compiled-in constant, such as set a value from `optarg', set the
- option's `flag' field to zero and its `val' field to a nonzero
- value (the equivalent single-letter option character, if there is
- one). For long options that have a zero `flag' field, `getopt'
- returns the contents of the `val' field. */
-
-struct option
-{
-#if __STDC__
- const char *name;
-#else
- char *name;
-#endif
- /* has_arg can't be an enum because some compilers complain about
- type mismatches in all the code that assumes it is an int. */
- int has_arg;
- int *flag;
- int val;
-};
-
-/* Names for the values of the `has_arg' field of `struct option'. */
-
-enum _argtype
-{
- no_argument,
- required_argument,
- optional_argument
-};
-
-#if __STDC__
-#if defined(__GNU_LIBRARY__)
-/* Many other libraries have conflicting prototypes for getopt, with
- differences in the consts, in stdlib.h. To avoid compilation
- errors, only prototype getopt for the GNU C library. */
-extern int getopt (int argc, char *const *argv, const char *shortopts);
-#else /* not __GNU_LIBRARY__ */
-extern int getopt ();
-#endif /* not __GNU_LIBRARY__ */
-extern int getopt_long (int argc, char *const *argv, const char *shortopts,
- const struct option *longopts, int *longind);
-extern int getopt_long_only (int argc, char *const *argv,
- const char *shortopts,
- const struct option *longopts, int *longind);
-
-/* Internal only. Users should not call this directly. */
-extern int _getopt_internal (int argc, char *const *argv,
- const char *shortopts,
- const struct option *longopts, int *longind,
- int long_only);
-#else /* not __STDC__ */
-extern int getopt ();
-extern int getopt_long ();
-extern int getopt_long_only ();
-
-extern int _getopt_internal ();
-#endif /* not __STDC__ */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _GETOPT_H */
diff --git a/getopt1.c b/getopt1.c
deleted file mode 100644
index 7a2bbae344..0000000000
--- a/getopt1.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/* Getopt for GNU.
- Copyright (C) 1987, 88, 89, 90, 91, 1992 Free Software Foundation, Inc.
-
-This file is part of the libiberty library.
-Libiberty is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public
-License as published by the Free Software Foundation; either
-version 2 of the License, or (at your option) any later version.
-
-Libiberty is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with libiberty; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA. */
-
-#include "config.h"
-
-#ifdef LIBC
-/* For when compiled as part of the GNU C library. */
-#include <ansidecl.h>
-#endif
-
-#include "getopt.h"
-
-#ifndef __STDC__
-#define const
-#endif
-
-#if defined(STDC_HEADERS) || defined(__GNU_LIBRARY__) || defined (LIBC)
-#include <stdlib.h>
-#else /* STDC_HEADERS or __GNU_LIBRARY__ */
-char *getenv ();
-#endif /* STDC_HEADERS or __GNU_LIBRARY__ */
-
-#if !defined (NULL)
-#define NULL 0
-#endif
-
-int
-getopt_long (argc, argv, options, long_options, opt_index)
- int argc;
- char *const *argv;
- const char *options;
- const struct option *long_options;
- int *opt_index;
-{
- return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
-}
-
-/* Like getopt_long, but '-' as well as '--' can indicate a long option.
- If an option that starts with '-' (not '--') doesn't match a long option,
- but does match a short option, it is parsed as a short option
- instead. */
-
-int
-getopt_long_only (argc, argv, options, long_options, opt_index)
- int argc;
- char *const *argv;
- const char *options;
- const struct option *long_options;
- int *opt_index;
-{
- return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
-}
-
-#ifdef TEST
-
-#include <stdio.h>
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- int c;
- int digit_optind = 0;
-
- while (1)
- {
- int this_option_optind = optind ? optind : 1;
- int option_index = 0;
- static struct option long_options[] =
- {
- {"add", 1, 0, 0},
- {"append", 0, 0, 0},
- {"delete", 1, 0, 0},
- {"verbose", 0, 0, 0},
- {"create", 0, 0, 0},
- {"file", 1, 0, 0},
- {0, 0, 0, 0}
- };
-
- c = getopt_long (argc, argv, "abc:d:0123456789",
- long_options, &option_index);
- if (c == EOF)
- break;
-
- switch (c)
- {
- case 0:
- printf ("option %s", long_options[option_index].name);
- if (optarg)
- printf (" with arg %s", optarg);
- printf ("\n");
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (digit_optind != 0 && digit_optind != this_option_optind)
- printf ("digits occur in two different argv-elements.\n");
- digit_optind = this_option_optind;
- printf ("option %c\n", c);
- break;
-
- case 'a':
- printf ("option a\n");
- break;
-
- case 'b':
- printf ("option b\n");
- break;
-
- case 'c':
- printf ("option c with value `%s'\n", optarg);
- break;
-
- case 'd':
- printf ("option d with value `%s'\n", optarg);
- break;
-
- case '?':
- break;
-
- default:
- printf ("?? getopt returned character code 0%o ??\n", c);
- }
- }
-
- if (optind < argc)
- {
- printf ("non-option ARGV-elements: ");
- while (optind < argc)
- printf ("%s ", argv[optind++]);
- printf ("\n");
- }
-
- exit (0);
-}
-
-#endif /* TEST */
diff --git a/glob.c b/glob.c
index 74dfe52fdd..69af7b1618 100644
--- a/glob.c
+++ b/glob.c
@@ -1,184 +1,580 @@
-/************************************************
+/* File-name wildcard pattern matching for GNU.
+ Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
- glob.c -
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
- $Author: matz $
- $Date: 1994/12/09 09:47:52 $
- created at: Mon Sep 12 18:56:43 JST 1994
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-************************************************/
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* To whomever it may concern: I have never seen the code which most
+ Unix programs use to perform this function. I wrote this from scratch
+ based on specifications for the pattern matching. --RMS. */
+
+#include "config.h"
+
+#if defined (SHELL)
+# if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+# else
+# include "ansi_stdlib.h"
+# endif /* HAVE_STDLIB_H */
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if !defined (SHELL) && (defined (_POSIX_VERSION) || defined (USGr3))
+# if !defined (HAVE_DIRENT_H)
+# define HAVE_DIRENT_H
+# endif /* !HAVE_DIRENT_H */
+#endif /* !SHELL && (_POSIX_VERSION || USGr3) */
+
+#if defined (HAVE_DIRENT_H)
+# include <dirent.h>
+# if !defined (direct)
+# define direct dirent
+# endif /* !direct */
+# define D_NAMLEN(d) strlen ((d)->d_name)
+#else /* !HAVE_DIRENT_H */
+# define D_NAMLEN(d) ((d)->d_namlen)
+# if defined (USG)
+# if defined (Xenix)
+# include <sys/ndir.h>
+# else /* !Xenix (but USG...) */
+# include "ndir.h"
+# endif /* !Xenix */
+# else /* !USG */
+# include <sys/dir.h>
+# endif /* !USG */
+#endif /* !HAVE_DIRENT_H */
+
+#if defined (_POSIX_SOURCE)
+/* Posix does not require that the d_ino field be present, and some
+ systems do not provide it. */
+# define REAL_DIR_ENTRY(dp) 1
+#else
+# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+#endif /* _POSIX_SOURCE */
+
+#if defined (USG) || defined (NeXT)
+# if !defined (HAVE_STRING_H)
+# define HAVE_STRING_H
+# endif /* !HAVE_STRING_H */
+#endif /* USG || NeXT */
+
+#if defined (HAVE_STRING_H)
+# include <string.h>
+#else /* !HAVE_STRING_H */
+# include <strings.h>
+#endif /* !HAVE_STRING_H */
+
+#if defined (USG)
+# if !defined (isc386)
+# include <memory.h>
+# endif /* !isc386 */
+# if defined (RISC6000)
+extern void bcopy ();
+# else /* !RISC6000 */
+# define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
+# endif /* !RISC6000 */
+#endif /* USG */
+
+#if defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
+#include <alloca.h>
+#else
+char *alloca ();
+#endif
-#include <sys/param.h>
-#include "ruby.h"
#include "fnmatch.h"
-char *strdup();
+/* If the opendir () on your system lets you open non-directory files,
+ then we consider that not robust. Define OPENDIR_NOT_ROBUST in the
+ SYSDEP_CFLAGS for your machines entry in machines.h. */
+#if defined (OPENDIR_NOT_ROBUST)
+# if defined (SHELL)
+# include "posixstat.h"
+# else /* !SHELL */
+# include <sys/stat.h>
+# endif /* !SHELL */
+#endif /* OPENDIR_NOT_ROBUST */
+
+extern void *xmalloc (), *xrealloc ();
+#if !defined (HAVE_STDLIB_H)
+extern void free ();
+#endif /* !HAVE_STDLIB_H */
+
+#if !defined (NULL)
+# if defined (__STDC__)
+# define NULL ((void *) 0)
+# else
+# define NULL 0x0
+# endif /* __STDC__ */
+#endif /* !NULL */
-VALUE C_Glob;
+#if defined (SHELL)
+extern int interrupt_state;
+#endif /* SHELL */
-struct glob_data {
- char **globs;
-};
+/* Global variable which controls whether or not * matches .*.
+ Non-zero means don't match .*. */
+int noglob_dot_filenames = 1;
-static ID id_data;
+/* Global variable to return to signify an error in globbing. */
+char *glob_error_return;
+
+/* Return nonzero if PATTERN has any special globbing chars in it. */
+int
+glob_pattern_p (pattern)
+ char *pattern;
+{
+ register char *p = pattern;
+ register char c;
+ int open = 0;
+
+ while ((c = *p++) != '\0')
+ switch (c)
+ {
+ case '?':
+ case '*':
+ return (1);
+
+ case '[': /* Only accept an open brace if there is a close */
+ open++; /* brace to match it. Bracket expressions must be */
+ continue; /* complete, according to Posix.2 */
+ case ']':
+ if (open)
+ return (1);
+ continue;
+
+ case '\\':
+ if (*p++ == '\0')
+ return (0);
+ }
+
+ return (0);
+}
+
+/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
static void
-glob_free(data)
- struct glob_data *data;
+dequote_pathname (pathname)
+ char *pathname;
{
- char **globs = data->globs;
- while (*globs) {
- free(*globs);
- globs++;
+ register int i, j;
+
+ for (i = j = 0; pathname && pathname[i]; )
+ {
+ if (pathname[i] == '\\')
+ i++;
+
+ pathname[j++] = pathname[i++];
+
+ if (!pathname[i - 1])
+ break;
}
- free(data->globs);
+ pathname[j] = '\0';
}
-#define isdelim(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\0')
+
+/* Return a vector of names of files in directory DIR
+ whose names match glob pattern PAT.
+ The names are not in any particular order.
+ Wildcards at the beginning of PAT do not match an initial period.
+
+ The vector is terminated by an element that is a null pointer.
-char *strchr();
-char *strdup();
+ To free the space allocated, first free the vector's elements,
+ then free the vector.
-static int
-expand_brace(s, data, len)
- char *s;
- struct glob_data *data;
- int len;
+ Return 0 if cannot get enough memory to hold the pointer
+ and the names.
+
+ Return -1 if cannot access directory DIR.
+ Look in errno for more information. */
+
+char **
+glob_vector (pat, dir)
+ char *pat;
+ char *dir;
{
- char org[MAXPATHLEN], path[MAXPATHLEN];
- char *pre, *post, *head, *p, *t;
-
- strcpy(org, s);
- pre = strchr(org, '{');
- if (pre) post = strchr(pre, '}');
- if (!pre || !post) {
- data->globs[len++] = strdup(s);
- REALLOC_N(data->globs, char*, len+1);
- return len;
+ struct globval
+ {
+ struct globval *next;
+ char *name;
+ };
+
+ DIR *d;
+ register struct direct *dp;
+ struct globval *lastlink;
+ register struct globval *nextlink;
+ register char *nextname;
+ unsigned int count;
+ int lose, skip;
+ register char **name_vector;
+ register unsigned int i;
+#if defined (OPENDIR_NOT_ROBUST)
+ struct stat finfo;
+
+ if (stat (dir, &finfo) < 0)
+ return ((char **) &glob_error_return);
+
+ if (!S_ISDIR (finfo.st_mode))
+ return ((char **) &glob_error_return);
+#endif /* OPENDIR_NOT_ROBUST */
+
+ d = opendir (dir);
+ if (d == NULL)
+ return ((char **) &glob_error_return);
+
+ lastlink = 0;
+ count = 0;
+ lose = 0;
+ skip = 0;
+
+ /* If PAT is empty, skip the loop, but return one (empty) filename. */
+ if (!pat || !*pat)
+ {
+ nextlink = (struct globval *)alloca (sizeof (struct globval));
+ nextlink->next = lastlink;
+ nextname = (char *) xmalloc (1);
+ if (!nextname)
+ lose = 1;
+ else
+ {
+ lastlink = nextlink;
+ nextlink->name = nextname;
+ nextname[0] = '\0';
+ count++;
+ }
+ skip = 1;
}
- memcpy(path, org, pre - org);
- p = org + (pre - org) + 1;
- head = path + (pre - org);
+ /* Scan the directory, finding all names that match.
+ For each name that matches, allocate a struct globval
+ on the stack and store the name in it.
+ Chain those structs together; lastlink is the front of the chain. */
+ while (!skip)
+ {
+ int flags; /* Flags passed to fnmatch (). */
+#if defined (SHELL)
+ /* Make globbing interruptible in the bash shell. */
+ if (interrupt_state)
+ {
+ closedir (d);
+ lose = 1;
+ goto lost;
+ }
+#endif /* SHELL */
+
+ dp = readdir (d);
+ if (dp == NULL)
+ break;
+
+ /* If this directory entry is not to be used, try again. */
+ if (!REAL_DIR_ENTRY (dp))
+ continue;
- while (p < post) {
- t = p;
- while (t < post) {
- if (*t == ',') break;
- t++;
+ /* If a dot must be explicity matched, check to see if they do. */
+ if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.')
+ continue;
+
+ flags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
+
+ if (fnmatch (pat, dp->d_name, flags) != FNM_NOMATCH)
+ {
+ nextlink = (struct globval *) alloca (sizeof (struct globval));
+ nextlink->next = lastlink;
+ nextname = (char *) xmalloc (D_NAMLEN (dp) + 1);
+ if (nextname == NULL)
+ {
+ lose = 1;
+ break;
+ }
+ lastlink = nextlink;
+ nextlink->name = nextname;
+ bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1);
+ ++count;
}
- memcpy(head, p, t-p);
- strcpy(head+(t-p), post+1);
- len = expand_brace(path, data, len);
- p = t + 1;
}
- return len;
-}
+ (void) closedir (d);
-static VALUE
-glob_new0(class, str)
- VALUE class;
- struct RString *str;
-{
- VALUE new;
- struct glob_data *data;
- char *p1, *p2, *pend, *s;
- int len = 0;
-
- new = obj_alloc(class);
- Make_Data_Struct(new, id_data, struct glob_data, Qnil, glob_free, data);
- data->globs = ALLOC_N(char*, 1);
-
- p1 = p2 = str->ptr;
- pend = p1 + str->len;
- while (p1 < pend) {
- char s[MAXPATHLEN];
- int d;
-
- while (isdelim(*p1)) p1++;
- p2 = p1;
- while (!isdelim(*p2)) p2++;
- d = p2 - p1;
- memcpy(s, p1, d);
- s[d] = '\0';
- len = expand_brace(s, data, len);
- p1 = p2;
+ if (!lose)
+ {
+ name_vector = (char **) xmalloc ((count + 1) * sizeof (char *));
+ lose |= name_vector == NULL;
}
- data->globs[len] = Qnil;
- return new;
-}
+ /* Have we run out of memory? */
+ lost:
+ if (lose)
+ {
+ /* Here free the strings we have got. */
+ while (lastlink)
+ {
+ free (lastlink->name);
+ lastlink = lastlink->next;
+ }
+#if defined (SHELL)
+ if (interrupt_state)
+ throw_to_top_level ();
+#endif /* SHELL */
+ return (NULL);
+ }
-VALUE
-glob_new(str)
- struct RString *str;
-{
- return glob_new0(C_Glob, str);
+ /* Copy the name pointers from the linked list into the vector. */
+ for (i = 0; i < count; ++i)
+ {
+ name_vector[i] = lastlink->name;
+ lastlink = lastlink->next;
+ }
+
+ name_vector[count] = NULL;
+ return (name_vector);
}
+
+/* Return a new array which is the concatenation of each string in ARRAY
+ to DIR. This function expects you to pass in an allocated ARRAY, and
+ it takes care of free()ing that array. Thus, you might think of this
+ function as side-effecting ARRAY. */
+static char **
+glob_dir_to_array (dir, array)
+ char *dir, **array;
+{
+ register unsigned int i, l;
+ int add_slash;
+ char **result;
+
+ l = strlen (dir);
+ if (l == 0)
+ return (array);
+
+ add_slash = dir[l - 1] != '/';
-char **glob_filename();
+ i = 0;
+ while (array[i] != NULL)
+ ++i;
+
+ result = (char **) xmalloc ((i + 1) * sizeof (char *));
+ if (result == NULL)
+ return (NULL);
+
+ for (i = 0; array[i] != NULL; i++)
+ {
+ result[i] = (char *) xmalloc (l + (add_slash ? 1 : 0)
+ + strlen (array[i]) + 1);
+ if (result[i] == NULL)
+ return (NULL);
+ sprintf (result[i], "%s%s%s", dir, add_slash ? "/" : "", array[i]);
+ }
+ result[i] = NULL;
-static VALUE
-Fglob_each(glob)
- VALUE glob;
+ /* Free the input array. */
+ for (i = 0; array[i] != NULL; i++)
+ free (array[i]);
+ free ((char *) array);
+
+ return (result);
+}
+
+/* Do globbing on PATHNAME. Return an array of pathnames that match,
+ marking the end of the array with a null-pointer as an element.
+ If no pathnames match, then the array is empty (first element is null).
+ If there isn't enough memory, then return NULL.
+ If a file system error occurs, return -1; `errno' has the error code. */
+char **
+glob_filename (pathname)
+ char *pathname;
{
- struct glob_data *data;
- char **patv, **fnames, **ff;
-
- Get_Data_Struct(glob, id_data, struct glob_data, data);
- for (patv = data->globs; *patv; patv++) {
- if (!glob_pattern_p(*patv)) {
- rb_yield(str_new2(*patv));
- continue;
- }
- fnames = glob_filename(*patv);
- if (fnames == (char**)-1) rb_sys_fail(*patv);
- if (fnames[0] == Qnil) {
- rb_yield(str_new2(*patv));
+ char *strrchr();
+
+ char **result;
+ unsigned int result_size;
+ char *directory_name, *filename;
+ unsigned int directory_len;
+
+ result = (char **) xmalloc (sizeof (char *));
+ result_size = 1;
+ if (result == NULL)
+ return (NULL);
+
+ result[0] = NULL;
+
+ /* Find the filename. */
+ filename = strrchr (pathname, '/');
+ if (filename == NULL)
+ {
+ filename = pathname;
+ directory_name = "";
+ directory_len = 0;
+ }
+ else
+ {
+ directory_len = (filename - pathname) + 1;
+ directory_name = (char *) alloca (directory_len + 1);
+
+ bcopy (pathname, directory_name, directory_len);
+ directory_name[directory_len] = '\0';
+ ++filename;
+ }
+
+ /* If directory_name contains globbing characters, then we
+ have to expand the previous levels. Just recurse. */
+ if (glob_pattern_p (directory_name))
+ {
+ char **directories;
+ register unsigned int i;
+
+ if (directory_name[directory_len - 1] == '/')
+ directory_name[directory_len - 1] = '\0';
+
+ directories = glob_filename (directory_name);
+
+ if (directories == NULL)
+ goto memory_error;
+ else if (directories == (char **)&glob_error_return)
+ return ((char **) &glob_error_return);
+ else if (*directories == NULL)
+ {
+ free ((char *) directories);
+ return ((char **) &glob_error_return);
}
- else {
- ff = fnames;
- while (*ff) {
- rb_yield(str_new2(*ff));
- free(*ff);
- ff++;
+
+ /* We have successfully globbed the preceding directory name.
+ For each name in DIRECTORIES, call glob_vector on it and
+ FILENAME. Concatenate the results together. */
+ for (i = 0; directories[i] != NULL; ++i)
+ {
+ char **temp_results;
+
+ /* Scan directory even on a NULL pathname. That way, `*h/'
+ returns only directories ending in `h', instead of all
+ files ending in `h' with a `/' appended. */
+ temp_results = glob_vector (filename, directories[i]);
+
+ /* Handle error cases. */
+ if (temp_results == NULL)
+ goto memory_error;
+ else if (temp_results == (char **)&glob_error_return)
+ /* This filename is probably not a directory. Ignore it. */
+ ;
+ else
+ {
+ char **array;
+ register unsigned int l;
+
+ array = glob_dir_to_array (directories[i], temp_results);
+ l = 0;
+ while (array[l] != NULL)
+ ++l;
+
+ result =
+ (char **)xrealloc(result, (result_size + l) * sizeof (char *));
+
+ if (result == NULL)
+ goto memory_error;
+
+ for (l = 0; array[l] != NULL; ++l)
+ result[result_size++ - 1] = array[l];
+
+ result[result_size - 1] = NULL;
+
+ /* Note that the elements of ARRAY are not freed. */
+ free ((char *) array);
}
}
- free(fnames);
+ /* Free the directories. */
+ for (i = 0; directories[i]; i++)
+ free (directories[i]);
+
+ free ((char *) directories);
+
+ return (result);
}
- return Qnil;
-}
-VALUE
-Fglob_match(glob, str)
- VALUE glob;
- struct RString *str;
-{
- struct glob_data *data;
- char **patv;
-
- Check_Type(str, T_STRING);
- Get_Data_Struct(glob, id_data, struct glob_data, data);
- patv = data->globs;
- while (*patv) {
- if (fnmatch(*patv, str->ptr, 0) != FNM_NOMATCH)
- return TRUE;
- patv++;
+ /* If there is only a directory name, return it. */
+ if (*filename == '\0')
+ {
+ result = (char **) xrealloc ((char *) result, 2 * sizeof (char *));
+ if (result == NULL)
+ return (NULL);
+ result[0] = (char *) xmalloc (directory_len + 1);
+ if (result[0] == NULL)
+ goto memory_error;
+ bcopy (directory_name, result[0], directory_len + 1);
+ result[1] = NULL;
+ return (result);
}
- return FALSE;
-}
+ else
+ {
+ char **temp_results;
-extern VALUE M_Enumerable;
+ /* There are no unquoted globbing characters in DIRECTORY_NAME.
+ Dequote it before we try to open the directory since there may
+ be quoted globbing characters which should be treated verbatim. */
+ if (directory_len > 0)
+ dequote_pathname (directory_name);
-Init_Glob()
-{
- C_Glob = rb_define_class("Glob", C_Object);
- rb_include_module(C_Glob, M_Enumerable);
+ /* We allocated a small array called RESULT, which we won't be using.
+ Free that memory now. */
+ free (result);
+
+ /* Just return what glob_vector () returns appended to the
+ directory name. */
+ temp_results =
+ glob_vector (filename, (directory_len == 0 ? "." : directory_name));
- rb_define_single_method(C_Glob, "new", glob_new0, 1);
+ if (temp_results == NULL || temp_results == (char **)&glob_error_return)
+ return (temp_results);
- rb_define_method(C_Glob, "each", Fglob_each, 0);
- rb_define_method(C_Glob, "=~", Fglob_match, 1);
+ return (glob_dir_to_array (directory_name, temp_results));
+ }
+
+ /* We get to memory_error if the program has run out of memory, or
+ if this is the shell, and we have been interrupted. */
+ memory_error:
+ if (result != NULL)
+ {
+ register unsigned int i;
+ for (i = 0; result[i] != NULL; ++i)
+ free (result[i]);
+ free ((char *) result);
+ }
+#if defined (SHELL)
+ if (interrupt_state)
+ throw_to_top_level ();
+#endif /* SHELL */
+ return (NULL);
+}
+
+#if defined (TEST)
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ unsigned int i;
+
+ for (i = 1; i < argc; ++i)
+ {
+ char **value = glob_filename (argv[i]);
+ if (value == NULL)
+ puts ("Out of memory.");
+ else if (value == &glob_error_return)
+ perror (argv[i]);
+ else
+ for (i = 0; value[i] != NULL; i++)
+ puts (value[i]);
+ }
- id_data = rb_intern("data");
+ exit (0);
}
+#endif /* TEST. */
diff --git a/gnuglob.c b/gnuglob.c
deleted file mode 100644
index 69af7b1618..0000000000
--- a/gnuglob.c
+++ /dev/null
@@ -1,580 +0,0 @@
-/* File-name wildcard pattern matching for GNU.
- Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* To whomever it may concern: I have never seen the code which most
- Unix programs use to perform this function. I wrote this from scratch
- based on specifications for the pattern matching. --RMS. */
-
-#include "config.h"
-
-#if defined (SHELL)
-# if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-# else
-# include "ansi_stdlib.h"
-# endif /* HAVE_STDLIB_H */
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-
-#if !defined (SHELL) && (defined (_POSIX_VERSION) || defined (USGr3))
-# if !defined (HAVE_DIRENT_H)
-# define HAVE_DIRENT_H
-# endif /* !HAVE_DIRENT_H */
-#endif /* !SHELL && (_POSIX_VERSION || USGr3) */
-
-#if defined (HAVE_DIRENT_H)
-# include <dirent.h>
-# if !defined (direct)
-# define direct dirent
-# endif /* !direct */
-# define D_NAMLEN(d) strlen ((d)->d_name)
-#else /* !HAVE_DIRENT_H */
-# define D_NAMLEN(d) ((d)->d_namlen)
-# if defined (USG)
-# if defined (Xenix)
-# include <sys/ndir.h>
-# else /* !Xenix (but USG...) */
-# include "ndir.h"
-# endif /* !Xenix */
-# else /* !USG */
-# include <sys/dir.h>
-# endif /* !USG */
-#endif /* !HAVE_DIRENT_H */
-
-#if defined (_POSIX_SOURCE)
-/* Posix does not require that the d_ino field be present, and some
- systems do not provide it. */
-# define REAL_DIR_ENTRY(dp) 1
-#else
-# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
-#endif /* _POSIX_SOURCE */
-
-#if defined (USG) || defined (NeXT)
-# if !defined (HAVE_STRING_H)
-# define HAVE_STRING_H
-# endif /* !HAVE_STRING_H */
-#endif /* USG || NeXT */
-
-#if defined (HAVE_STRING_H)
-# include <string.h>
-#else /* !HAVE_STRING_H */
-# include <strings.h>
-#endif /* !HAVE_STRING_H */
-
-#if defined (USG)
-# if !defined (isc386)
-# include <memory.h>
-# endif /* !isc386 */
-# if defined (RISC6000)
-extern void bcopy ();
-# else /* !RISC6000 */
-# define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
-# endif /* !RISC6000 */
-#endif /* USG */
-
-#if defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
-#include <alloca.h>
-#else
-char *alloca ();
-#endif
-
-#include "fnmatch.h"
-
-/* If the opendir () on your system lets you open non-directory files,
- then we consider that not robust. Define OPENDIR_NOT_ROBUST in the
- SYSDEP_CFLAGS for your machines entry in machines.h. */
-#if defined (OPENDIR_NOT_ROBUST)
-# if defined (SHELL)
-# include "posixstat.h"
-# else /* !SHELL */
-# include <sys/stat.h>
-# endif /* !SHELL */
-#endif /* OPENDIR_NOT_ROBUST */
-
-extern void *xmalloc (), *xrealloc ();
-#if !defined (HAVE_STDLIB_H)
-extern void free ();
-#endif /* !HAVE_STDLIB_H */
-
-#if !defined (NULL)
-# if defined (__STDC__)
-# define NULL ((void *) 0)
-# else
-# define NULL 0x0
-# endif /* __STDC__ */
-#endif /* !NULL */
-
-#if defined (SHELL)
-extern int interrupt_state;
-#endif /* SHELL */
-
-/* Global variable which controls whether or not * matches .*.
- Non-zero means don't match .*. */
-int noglob_dot_filenames = 1;
-
-/* Global variable to return to signify an error in globbing. */
-char *glob_error_return;
-
-
-/* Return nonzero if PATTERN has any special globbing chars in it. */
-int
-glob_pattern_p (pattern)
- char *pattern;
-{
- register char *p = pattern;
- register char c;
- int open = 0;
-
- while ((c = *p++) != '\0')
- switch (c)
- {
- case '?':
- case '*':
- return (1);
-
- case '[': /* Only accept an open brace if there is a close */
- open++; /* brace to match it. Bracket expressions must be */
- continue; /* complete, according to Posix.2 */
- case ']':
- if (open)
- return (1);
- continue;
-
- case '\\':
- if (*p++ == '\0')
- return (0);
- }
-
- return (0);
-}
-
-/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
-static void
-dequote_pathname (pathname)
- char *pathname;
-{
- register int i, j;
-
- for (i = j = 0; pathname && pathname[i]; )
- {
- if (pathname[i] == '\\')
- i++;
-
- pathname[j++] = pathname[i++];
-
- if (!pathname[i - 1])
- break;
- }
- pathname[j] = '\0';
-}
-
-
-/* Return a vector of names of files in directory DIR
- whose names match glob pattern PAT.
- The names are not in any particular order.
- Wildcards at the beginning of PAT do not match an initial period.
-
- The vector is terminated by an element that is a null pointer.
-
- To free the space allocated, first free the vector's elements,
- then free the vector.
-
- Return 0 if cannot get enough memory to hold the pointer
- and the names.
-
- Return -1 if cannot access directory DIR.
- Look in errno for more information. */
-
-char **
-glob_vector (pat, dir)
- char *pat;
- char *dir;
-{
- struct globval
- {
- struct globval *next;
- char *name;
- };
-
- DIR *d;
- register struct direct *dp;
- struct globval *lastlink;
- register struct globval *nextlink;
- register char *nextname;
- unsigned int count;
- int lose, skip;
- register char **name_vector;
- register unsigned int i;
-#if defined (OPENDIR_NOT_ROBUST)
- struct stat finfo;
-
- if (stat (dir, &finfo) < 0)
- return ((char **) &glob_error_return);
-
- if (!S_ISDIR (finfo.st_mode))
- return ((char **) &glob_error_return);
-#endif /* OPENDIR_NOT_ROBUST */
-
- d = opendir (dir);
- if (d == NULL)
- return ((char **) &glob_error_return);
-
- lastlink = 0;
- count = 0;
- lose = 0;
- skip = 0;
-
- /* If PAT is empty, skip the loop, but return one (empty) filename. */
- if (!pat || !*pat)
- {
- nextlink = (struct globval *)alloca (sizeof (struct globval));
- nextlink->next = lastlink;
- nextname = (char *) xmalloc (1);
- if (!nextname)
- lose = 1;
- else
- {
- lastlink = nextlink;
- nextlink->name = nextname;
- nextname[0] = '\0';
- count++;
- }
- skip = 1;
- }
-
- /* Scan the directory, finding all names that match.
- For each name that matches, allocate a struct globval
- on the stack and store the name in it.
- Chain those structs together; lastlink is the front of the chain. */
- while (!skip)
- {
- int flags; /* Flags passed to fnmatch (). */
-#if defined (SHELL)
- /* Make globbing interruptible in the bash shell. */
- if (interrupt_state)
- {
- closedir (d);
- lose = 1;
- goto lost;
- }
-#endif /* SHELL */
-
- dp = readdir (d);
- if (dp == NULL)
- break;
-
- /* If this directory entry is not to be used, try again. */
- if (!REAL_DIR_ENTRY (dp))
- continue;
-
- /* If a dot must be explicity matched, check to see if they do. */
- if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.')
- continue;
-
- flags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
-
- if (fnmatch (pat, dp->d_name, flags) != FNM_NOMATCH)
- {
- nextlink = (struct globval *) alloca (sizeof (struct globval));
- nextlink->next = lastlink;
- nextname = (char *) xmalloc (D_NAMLEN (dp) + 1);
- if (nextname == NULL)
- {
- lose = 1;
- break;
- }
- lastlink = nextlink;
- nextlink->name = nextname;
- bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1);
- ++count;
- }
- }
- (void) closedir (d);
-
- if (!lose)
- {
- name_vector = (char **) xmalloc ((count + 1) * sizeof (char *));
- lose |= name_vector == NULL;
- }
-
- /* Have we run out of memory? */
- lost:
- if (lose)
- {
- /* Here free the strings we have got. */
- while (lastlink)
- {
- free (lastlink->name);
- lastlink = lastlink->next;
- }
-#if defined (SHELL)
- if (interrupt_state)
- throw_to_top_level ();
-#endif /* SHELL */
- return (NULL);
- }
-
- /* Copy the name pointers from the linked list into the vector. */
- for (i = 0; i < count; ++i)
- {
- name_vector[i] = lastlink->name;
- lastlink = lastlink->next;
- }
-
- name_vector[count] = NULL;
- return (name_vector);
-}
-
-/* Return a new array which is the concatenation of each string in ARRAY
- to DIR. This function expects you to pass in an allocated ARRAY, and
- it takes care of free()ing that array. Thus, you might think of this
- function as side-effecting ARRAY. */
-static char **
-glob_dir_to_array (dir, array)
- char *dir, **array;
-{
- register unsigned int i, l;
- int add_slash;
- char **result;
-
- l = strlen (dir);
- if (l == 0)
- return (array);
-
- add_slash = dir[l - 1] != '/';
-
- i = 0;
- while (array[i] != NULL)
- ++i;
-
- result = (char **) xmalloc ((i + 1) * sizeof (char *));
- if (result == NULL)
- return (NULL);
-
- for (i = 0; array[i] != NULL; i++)
- {
- result[i] = (char *) xmalloc (l + (add_slash ? 1 : 0)
- + strlen (array[i]) + 1);
- if (result[i] == NULL)
- return (NULL);
- sprintf (result[i], "%s%s%s", dir, add_slash ? "/" : "", array[i]);
- }
- result[i] = NULL;
-
- /* Free the input array. */
- for (i = 0; array[i] != NULL; i++)
- free (array[i]);
- free ((char *) array);
-
- return (result);
-}
-
-/* Do globbing on PATHNAME. Return an array of pathnames that match,
- marking the end of the array with a null-pointer as an element.
- If no pathnames match, then the array is empty (first element is null).
- If there isn't enough memory, then return NULL.
- If a file system error occurs, return -1; `errno' has the error code. */
-char **
-glob_filename (pathname)
- char *pathname;
-{
- char *strrchr();
-
- char **result;
- unsigned int result_size;
- char *directory_name, *filename;
- unsigned int directory_len;
-
- result = (char **) xmalloc (sizeof (char *));
- result_size = 1;
- if (result == NULL)
- return (NULL);
-
- result[0] = NULL;
-
- /* Find the filename. */
- filename = strrchr (pathname, '/');
- if (filename == NULL)
- {
- filename = pathname;
- directory_name = "";
- directory_len = 0;
- }
- else
- {
- directory_len = (filename - pathname) + 1;
- directory_name = (char *) alloca (directory_len + 1);
-
- bcopy (pathname, directory_name, directory_len);
- directory_name[directory_len] = '\0';
- ++filename;
- }
-
- /* If directory_name contains globbing characters, then we
- have to expand the previous levels. Just recurse. */
- if (glob_pattern_p (directory_name))
- {
- char **directories;
- register unsigned int i;
-
- if (directory_name[directory_len - 1] == '/')
- directory_name[directory_len - 1] = '\0';
-
- directories = glob_filename (directory_name);
-
- if (directories == NULL)
- goto memory_error;
- else if (directories == (char **)&glob_error_return)
- return ((char **) &glob_error_return);
- else if (*directories == NULL)
- {
- free ((char *) directories);
- return ((char **) &glob_error_return);
- }
-
- /* We have successfully globbed the preceding directory name.
- For each name in DIRECTORIES, call glob_vector on it and
- FILENAME. Concatenate the results together. */
- for (i = 0; directories[i] != NULL; ++i)
- {
- char **temp_results;
-
- /* Scan directory even on a NULL pathname. That way, `*h/'
- returns only directories ending in `h', instead of all
- files ending in `h' with a `/' appended. */
- temp_results = glob_vector (filename, directories[i]);
-
- /* Handle error cases. */
- if (temp_results == NULL)
- goto memory_error;
- else if (temp_results == (char **)&glob_error_return)
- /* This filename is probably not a directory. Ignore it. */
- ;
- else
- {
- char **array;
- register unsigned int l;
-
- array = glob_dir_to_array (directories[i], temp_results);
- l = 0;
- while (array[l] != NULL)
- ++l;
-
- result =
- (char **)xrealloc(result, (result_size + l) * sizeof (char *));
-
- if (result == NULL)
- goto memory_error;
-
- for (l = 0; array[l] != NULL; ++l)
- result[result_size++ - 1] = array[l];
-
- result[result_size - 1] = NULL;
-
- /* Note that the elements of ARRAY are not freed. */
- free ((char *) array);
- }
- }
- /* Free the directories. */
- for (i = 0; directories[i]; i++)
- free (directories[i]);
-
- free ((char *) directories);
-
- return (result);
- }
-
- /* If there is only a directory name, return it. */
- if (*filename == '\0')
- {
- result = (char **) xrealloc ((char *) result, 2 * sizeof (char *));
- if (result == NULL)
- return (NULL);
- result[0] = (char *) xmalloc (directory_len + 1);
- if (result[0] == NULL)
- goto memory_error;
- bcopy (directory_name, result[0], directory_len + 1);
- result[1] = NULL;
- return (result);
- }
- else
- {
- char **temp_results;
-
- /* There are no unquoted globbing characters in DIRECTORY_NAME.
- Dequote it before we try to open the directory since there may
- be quoted globbing characters which should be treated verbatim. */
- if (directory_len > 0)
- dequote_pathname (directory_name);
-
- /* We allocated a small array called RESULT, which we won't be using.
- Free that memory now. */
- free (result);
-
- /* Just return what glob_vector () returns appended to the
- directory name. */
- temp_results =
- glob_vector (filename, (directory_len == 0 ? "." : directory_name));
-
- if (temp_results == NULL || temp_results == (char **)&glob_error_return)
- return (temp_results);
-
- return (glob_dir_to_array (directory_name, temp_results));
- }
-
- /* We get to memory_error if the program has run out of memory, or
- if this is the shell, and we have been interrupted. */
- memory_error:
- if (result != NULL)
- {
- register unsigned int i;
- for (i = 0; result[i] != NULL; ++i)
- free (result[i]);
- free ((char *) result);
- }
-#if defined (SHELL)
- if (interrupt_state)
- throw_to_top_level ();
-#endif /* SHELL */
- return (NULL);
-}
-
-#if defined (TEST)
-
-main (argc, argv)
- int argc;
- char **argv;
-{
- unsigned int i;
-
- for (i = 1; i < argc; ++i)
- {
- char **value = glob_filename (argv[i]);
- if (value == NULL)
- puts ("Out of memory.");
- else if (value == &glob_error_return)
- perror (argv[i]);
- else
- for (i = 0; value[i] != NULL; i++)
- puts (value[i]);
- }
-
- exit (0);
-}
-#endif /* TEST. */
diff --git a/ident.h b/ident.h
index acf738ba9b..1fa1a14cd2 100644
--- a/ident.h
+++ b/ident.h
@@ -14,12 +14,13 @@
#ifndef IDENT_H
#define IDENT_H
+#define ID_SCOPE_SHIFT 3
#define ID_SCOPE_MASK 0x07
#define ID_LOCAL 0x00
-#define ID_ATTRSET 0x04
-#define ID_INSTANCE 0x02
-#define ID_GLOBAL 0x03
-#define ID_CONST 0x06
-#define ID_VARMASK 0x02
+#define ID_INSTANCE 0x01
+#define ID_GLOBAL 0x02
+#define ID_ATTRSET 0x03
+#define ID_CONST 0x04
+#define ID_NTHREF 0x05
#endif
diff --git a/inits.c b/inits.c
index 271fa7de44..ce93514a47 100644
--- a/inits.c
+++ b/inits.c
@@ -28,7 +28,6 @@ rb_call_inits()
Init_Struct();
Init_String();
Init_Regexp();
- Init_Glob();
Init_pack();
Init_Cons();
Init_Range();
diff --git a/io.c b/io.c
index ac94f9ee9c..583353c609 100644
--- a/io.c
+++ b/io.c
@@ -1395,6 +1395,8 @@ Init_IO()
rb_define_const(C_Object, "STDERR", rb_stderr);
argf = obj_alloc(C_Object);
+ rb_extend_object(argf, M_Enumerable);
+
rb_define_variable("$<", &argf, Qnil, rb_readonly_hook, 0);
rb_define_variable("$ARGF", &argf, Qnil, rb_readonly_hook, 0);
@@ -1411,7 +1413,6 @@ Init_IO()
rb_define_single_method(argf, "to_s", Farg_filename, 0);
rb_define_single_method(argf, "filename", Farg_filename, 0);
rb_define_single_method(argf, "file", Farg_file, 0);
- rb_include_module(CLASS_OF(argf), M_Enumerable);
filename = str_new2("-");
rb_define_variable("$FILENAME", &filename, Qnil, rb_readonly_hook, 0);
diff --git a/math.c b/math.c
index 78a6615e7f..4356a346b0 100644
--- a/math.c
+++ b/math.c
@@ -108,14 +108,18 @@ Fmath_sqrt(obj, x)
Init_Math()
{
M_Math = rb_define_module("Math");
-
- rb_define_module_function(M_Math, "atan2", Fmath_atan2, 2);
- rb_define_module_function(M_Math, "cos", Fmath_cos, 1);
- rb_define_module_function(M_Math, "sin", Fmath_sin, 1);
- rb_define_module_function(M_Math, "tan", Fmath_tan, 1);
-
- rb_define_module_function(M_Math, "exp", Fmath_exp, 1);
- rb_define_module_function(M_Math, "log", Fmath_log, 1);
- rb_define_module_function(M_Math, "log10", Fmath_log10, 1);
- rb_define_module_function(M_Math, "sqrt", Fmath_sqrt, 1);
+ rb_extend_object(M_Math, M_Math);
+
+ rb_define_const(M_Math, "PI", float_new(M_PI));
+ rb_define_const(M_Math, "E", float_new(M_E));
+
+ rb_define_method(M_Math, "atan2", Fmath_atan2, 2);
+ rb_define_method(M_Math, "cos", Fmath_cos, 1);
+ rb_define_method(M_Math, "sin", Fmath_sin, 1);
+ rb_define_method(M_Math, "tan", Fmath_tan, 1);
+
+ rb_define_method(M_Math, "exp", Fmath_exp, 1);
+ rb_define_method(M_Math, "log", Fmath_log, 1);
+ rb_define_method(M_Math, "log10", Fmath_log10, 1);
+ rb_define_method(M_Math, "sqrt", Fmath_sqrt, 1);
}
diff --git a/node.h b/node.h
index 7db04c5c95..113467abea 100644
--- a/node.h
+++ b/node.h
@@ -38,6 +38,7 @@ enum node_type {
NODE_OP_ASGN1,
NODE_OP_ASGN2,
NODE_CALL,
+ NODE_FCALL,
NODE_SUPER,
NODE_ZSUPER,
NODE_ARRAY,
@@ -56,13 +57,13 @@ enum node_type {
NODE_IVAR,
NODE_CVAR,
NODE_CONST,
+ NODE_NTH_REF,
NODE_LIT,
NODE_STR,
NODE_STR2,
NODE_XSTR,
NODE_XSTR2,
NODE_DREGX,
- NODE_DGLOB,
NODE_ARGS,
NODE_DEFN,
NODE_DEFS,
@@ -71,7 +72,6 @@ enum node_type {
NODE_CLASS,
NODE_MODULE,
NODE_CREF,
- NODE_INC,
NODE_DOT3,
NODE_ATTRSET,
NODE_SELF,
@@ -173,6 +173,8 @@ typedef struct RNode {
#define nd_state u3.state
#define nd_rval u3.node
+#define nd_nth u2.argc
+
#define NEW_METHOD(n,x) newnode(NODE_METHOD,x,n,0)
#define NEW_FBODY(n,i,o) newnode(NODE_FBODY,n,i,o)
#define NEW_DEFN(i,a,d,p) newnode(NODE_DEFN,p,i,NEW_RFUNC(a,d))
@@ -216,12 +218,14 @@ typedef struct RNode {
#define NEW_LVAR2(v) newnode(NODE_LVAR2,v,0,0)
#define NEW_IVAR(v) newnode(NODE_IVAR,v,0,0)
#define NEW_CVAR(v) newnode(NODE_CVAR,v,0,cref_list)
+#define NEW_NTH_REF(n) newnode(NODE_NTH_REF,0,n,0)
#define NEW_LIT(l) newnode(NODE_LIT,l,0,0)
#define NEW_STR(s) newnode(NODE_STR,s,0,0)
#define NEW_STR2(s) newnode(NODE_STR2,s,0,0)
#define NEW_XSTR(s) newnode(NODE_XSTR,s,0,0)
#define NEW_XSTR2(s) newnode(NODE_XSTR2,s,0,0)
#define NEW_CALL(r,m,a) newnode(NODE_CALL,r,m,a)
+#define NEW_FCALL(m,a) newnode(NODE_FCALL,0,m,a)
#define NEW_SUPER(a) newnode(NODE_SUPER,0,0,a)
#define NEW_ZSUPER() newnode(NODE_ZSUPER,0,0,0)
#define NEW_ARGS(f,r) newnode(NODE_ARGS,0,r,f)
@@ -232,7 +236,6 @@ typedef struct RNode {
#define NEW_CREF0() (cref_list=newnode(NODE_CREF,the_class,0,0))
#define NEW_CREF(b) (cref_list=newnode(NODE_CREF,0,0,cref_list))
#define NEW_CBODY(b) (cref_list->nd_body=NEW_SCOPE(b),cref_list)
-#define NEW_INC(m) newnode(NODE_INC,m,0,0)
#define NEW_DOT3(b,e) newnode(NODE_DOT3,b,e,0)
#define NEW_ATTRSET(a) newnode(NODE_ATTRSET,a,0,0)
#define NEW_SELF() newnode(NODE_SELF,0,0,0)
diff --git a/object.c b/object.c
index 7aa16483e1..7fb582302d 100644
--- a/object.c
+++ b/object.c
@@ -208,6 +208,13 @@ Fobj_init_object(obj)
}
static VALUE
+Fobj_s_added(obj, id)
+ VALUE obj, id;
+{
+ return Qnil;
+}
+
+static VALUE
Fnil_to_s(obj)
VALUE obj;
{
@@ -296,8 +303,8 @@ Fcls_attr(argc, argv, class)
return Qnil;
}
-static VALUE
-Fcls_export_internal(argc, argv, ex)
+void
+method_visibility(argc, argv, ex)
int argc;
VALUE *argv;
int ex;
@@ -316,24 +323,23 @@ Fcls_export_internal(argc, argv, ex)
}
rb_export_method(self, id, ex);
}
- return Qnil;
}
static VALUE
-Fcls_export(argc, argv)
+Fcls_public(argc, argv)
int argc;
VALUE *argv;
{
- Fcls_export_internal(argc, argv, 0);
+ method_visibility(argc, argv, NOEX_PUBLIC);
return Qnil;
}
static VALUE
-Fcls_unexport(argc, argv)
+Fcls_private(argc, argv)
int argc;
VALUE *argv;
{
- Fcls_export_internal(argc, argv, 1);
+ method_visibility(argc, argv, NOEX_PRIVATE);
return Qnil;
}
@@ -429,6 +435,7 @@ Init_Object()
rb_define_alias(C_Kernel, "format", "sprintf");
rb_define_private_method(C_Object, "init_object", Fobj_init_object, -1);
+ rb_define_private_method(C_Object, "single_method_added", Fobj_s_added, 1);
rb_define_method(C_Object, "clone", Fobj_clone, 0);
@@ -440,8 +447,9 @@ Init_Object()
rb_define_method(C_Module, "to_s", Fcls_to_s, 0);
rb_define_method(C_Module, "clone", Fcant_clone, 0);
rb_define_private_method(C_Module, "attr", Fcls_attr, -1);
- rb_define_method(C_Module, "export", Fcls_export, -1);
- rb_define_method(C_Module, "unexport", Fcls_unexport, -1);
+
+ rb_define_method(C_Module, "public", Fcls_public, -1);
+ rb_define_method(C_Module, "private", Fcls_private, -1);
rb_define_method(C_Class, "new", Fcls_new, -1);
diff --git a/parse.y b/parse.y