summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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: 定数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: 配列,連想配列の最後に`,'をおけるように.
+
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
index 74b500b024..12e6672ca1 100644
--- a/parse.y
+++ b/parse.y
@@ -24,9 +24,9 @@
#define is_local_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
#define is_global_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
#define is_instance_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
-#define is_variable_id(id) (is_id_nonop(id)&&((id)&ID_VARMASK))
#define is_attrset_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
#define is_const_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
+#define is_nthref_id(id) (((id)&ID_SCOPE_MASK)==ID_NTHREF)
struct op_tbl {
ID token;
@@ -94,7 +94,6 @@ static void top_local_setup();
MODULE
DEF
UNDEF
- INCLUDE
BEGIN
RESQUE
ENSURE
@@ -126,16 +125,16 @@ static void top_local_setup();
WHILE_MOD
ALIAS
-%token <id> IDENTIFIER GVAR IVAR CONSTANT
-%token <val> INTEGER FLOAT STRING XSTRING REGEXP GLOB
-%token <node> STRING2 XSTRING2 DREGEXP DGLOB
+%token <id> IDENTIFIER GVAR IVAR CONSTANT NTH_REF
+%token <val> INTEGER FLOAT STRING XSTRING REGEXP
+%token <node> STRING2 XSTRING2 DREGEXP
-%type <node> singleton inc_list
+%type <node> singleton
%type <val> literal numeric
%type <node> compexpr exprs expr arg primary var_ref
%type <node> if_tail opt_else case_body cases resque ensure
%type <node> call_args call_args0 args args2 opt_args
-%type <node> f_arglist f_args assoc_list assocs assoc
+%type <node> f_arglist f_args array assoc_list assocs assoc
%type <node> mlhs mlhs_head mlhs_tail lhs iter_var opt_iter_var
%type <id> superclass variable symbol
%type <id> fname op rest_arg
@@ -245,7 +244,7 @@ expr : mlhs '=' args2
}
| IDENTIFIER call_args0
{
- $$ = NEW_CALL(Qnil, $1, $2);
+ $$ = NEW_FCALL($1, $2);
}
| primary '.' IDENTIFIER call_args0
{
@@ -266,12 +265,6 @@ expr : mlhs '=' args2
{
$$ = NEW_ALIAS($2, $4);
}
- | INCLUDE inc_list
- {
- if (cur_mid || in_single)
- Error("include appeared in method definition");
- $$ = $2;
- }
| expr IF_MOD expr
{
$$ = NEW_IF(cond($3), $1, Qnil);
@@ -322,7 +315,7 @@ lhs : variable
{
$$ = asignable($1, Qnil);
}
- | primary '[' opt_args rbracket
+ | primary '[' opt_args opt_nl rbracket
{
$$ = aryset($1, $3, Qnil);
}
@@ -331,25 +324,6 @@ lhs : variable
$$ = attrset($1, $3, Qnil);
}
-inc_list : CONSTANT
- {
- $$ = NEW_INC($1);
- }
- | inc_list comma CONSTANT
- {
- $$ = block_append($1, NEW_INC($3));
- }
- | error
- {
- lex_state = EXPR_BEG;
- $$ = Qnil;
- }
- | inc_list comma error
- {
- lex_state = EXPR_BEG;
- $$ = $1;
- }
-
fname : IDENTIFIER
| CONSTANT
| op
@@ -389,9 +363,9 @@ arg : variable '=' arg
value_expr($3);
$$ = asignable($1, $3);
}
- | primary '[' opt_args rbracket '=' arg
+ | primary '[' opt_args opt_nl rbracket '=' arg
{
- $$ = aryset($1, $3, $6);
+ $$ = aryset($1, $3, $7);
}
| primary '.' IDENTIFIER '=' arg
{
@@ -416,12 +390,12 @@ arg : variable '=' arg
}
$$ = asignable($1, call_op(val, $2, 1, $3));
}
- | primary '[' opt_args rbracket OP_ASGN arg
+ | primary '[' opt_args opt_nl rbracket OP_ASGN arg
{
- NODE *args = NEW_LIST($6);
+ NODE *args = NEW_LIST($7);
if ($3) list_concat(args, $3);
- $$ = NEW_OP_ASGN1($1, $5, args);
+ $$ = NEW_OP_ASGN1($1, $6, args);
}
| primary '.' IDENTIFIER OP_ASGN arg
{
@@ -577,8 +551,8 @@ call_args : /* none */
{
$$ = Qnil;
}
- | call_args0
- | '*' arg
+ | call_args0 opt_nl
+ | '*' arg opt_nl
{
$$ = $2;
}
@@ -624,6 +598,12 @@ args2 : args
}
}
+array : /* none */
+ {
+ $$ = Qnil;
+ }
+ | args trailer
+
primary : literal
{
$$ = NEW_LIT($1);
@@ -639,7 +619,6 @@ primary : literal
}
| XSTRING2
| DREGEXP
- | DGLOB
| var_ref
| SUPER '(' call_args rparen
{
@@ -653,12 +632,12 @@ primary : literal
Error("super called outside of method");
$$ = NEW_ZSUPER();
}
- | primary '[' opt_args rbracket
+ | primary '[' opt_args opt_nl rbracket
{
value_expr($1);
$$ = NEW_CALL($1, AREF, $3);
}
- | LBRACK opt_args rbracket
+ | LBRACK array rbracket
{
if ($2 == Qnil)
$$ = NEW_ZARRAY(); /* zero length array*/
@@ -726,13 +705,13 @@ primary : literal
if (nd_type($1) == NODE_LVAR
|| nd_type($1) == NODE_LVAR2
|| nd_type($1) == NODE_CVAR) {
- $1 = NEW_CALL(Qnil, $1->nd_vid, Qnil);
+ $1 = NEW_FCALL($1->nd_vid, Qnil);
}
$$ = NEW_ITER($3, $1, $5);
}
| IDENTIFIER '(' call_args rparen
{
- $$ = NEW_CALL(Qnil, $1, $3);
+ $$ = NEW_FCALL($1, $3);
}
| primary '.' IDENTIFIER '(' call_args rparen
{
@@ -832,7 +811,7 @@ primary : literal
compexpr
END
{
- $$ = NEW_DEFN($2, $4, $5, class_nest?1:0);
+ $$ = NEW_DEFN($2, $4, $5, class_nest?0:1);
local_pop();
cur_mid = Qnil;
}
@@ -918,7 +897,6 @@ literal : numeric
$$ = INT2FIX($2);
}
| REGEXP
- | GLOB
symbol : fname
| IVAR
@@ -931,6 +909,7 @@ variable : IDENTIFIER
| IVAR
| GVAR
| CONSTANT
+ | NTH_REF
| NIL
{
$$ = NIL;
@@ -1037,7 +1016,6 @@ singleton : var_ref
case NODE_XSTR:
case NODE_XSTR2:
case NODE_DREGX:
- case NODE_DGLOB:
case NODE_LIT:
case NODE_ARRAY:
case NODE_ZARRAY:
@@ -1052,8 +1030,8 @@ assoc_list : /* none */
{
$$ = Qnil;
}
- | assocs
- | args
+ | assocs trailer
+ | args trailer
{
if ($1->nd_alen%2 != 0) {
Error("odd number list for Dict");
@@ -1078,6 +1056,10 @@ opt_term : /* none */
opt_nl : /* none */
| nl
+trailer : /* none */
+ | nl
+ | comma
+
term : sc
| nl
@@ -1091,10 +1073,12 @@ rparen : ')' { yyerrok; }
rbracket : ']' { yyerrok; }
rbrace : '}' { yyerrok; }
comma : ',' { yyerrok; }
+
%%
#include <ctype.h>
#include <sys/types.h>
#include "regex.h"
+#include "util.h"
#define is_identchar(c) ((c)!=-1&&(isalnum(c) || (c) == '_' || ismbchar(c)))
@@ -1107,12 +1091,11 @@ VALUE newfloat();
VALUE newinteger();
char *strdup();
-#define EXPAND_B 1
-#define LEAVE_BS 2
-
static NODE *var_extend();
static void read_escape();
+#define LEAVE_BS 1
+
static char *lex_p;
static int lex_len;
@@ -1132,6 +1115,22 @@ lex_setsrc(src, ptr, len)
#define nextc() ((--lex_len>=0)?(*lex_p++):-1)
#define pushback() (lex_len++, lex_p--)
+#define SCAN_HEX(i) \
+do { \
+ int numlen; \
+ i=scan_hex(lex_p, 2, &numlen); \
+ lex_p += numlen; \
+ lex_len -= numlen; \
+} while (0)
+
+#define SCAN_OCT(i) \
+do { \
+ int numlen; \
+ i=scan_oct(lex_p, 3, &numlen); \
+ lex_p += numlen; \
+ lex_len -= numlen; \
+} while (0)
+
#define tokfix() (tokenbuf[tokidx]='\0')
#define tok() tokenbuf
#define toklen() tokidx
@@ -1187,18 +1186,37 @@ parse_regx()
continue;
case '\\':
- if ((c = nextc()) == -1) {
+ switch (c = nextc()) {
+ case -1:
sourceline = re_start;
Error("unterminated regexp meets end of file");
return 0;
- }
- else if (c == '\n') {
+
+ case '\n':
sourceline++;
- }
- else if (in_brack && c == 'b') {
- tokadd('\b');
- }
- else {
+ break;
+
+ case '\\':
+ tokadd('\\');
+ tokadd('\\');
+ break;
+
+ case '1': case '2': case '3':
+ case '4': case '5': case '6':
+ case '7': case '8': case '9':
+ case '0': case 'x':
+ tokadd('\\');
+ tokadd(c);
+ break;
+
+ case 'b':
+ if (!in_brack) {
+ tokadd('\\');
+ tokadd('b');
+ break;
+ }
+ /* fall through */
+ default:
pushback();
read_escape(LEAVE_BS);
}
@@ -1285,11 +1303,11 @@ parse_string(term)
tokadd(c);
}
else {
- int flags = EXPAND_B;
- if (term != '"') flags |= LEAVE_BS;
- pushback();
- read_escape(flags);
- }
+ int flags = 0;
+ if (term != '"') flags = LEAVE_BS;
+ pushback();
+ read_escape(flags);
+ }
continue;
}
tokadd(c);
@@ -1342,7 +1360,6 @@ static struct kwtable {
"for", FOR, EXPR_BEG,
"if", IF, EXPR_BEG,
"in", IN, EXPR_BEG,
- "include", INCLUDE, EXPR_BEG,
"module", MODULE, EXPR_BEG,
"nil", NIL, EXPR_END,
"or", OR, EXPR_BEG,
@@ -1438,14 +1455,6 @@ retry:
return '=';
case '<':
- if (lex_state == EXPR_BEG) {
- if (parse_string('>') == STRING) {
- yylval.val = glob_new(yylval.val);
- return GLOB;
- }
- nd_set_type(yylval.node, NODE_DGLOB);
- return DGLOB;
- }
lex_state = EXPR_BEG;
if ((c = nextc()) == '=') {
if ((c = nextc()) == '>') {
@@ -1533,7 +1542,7 @@ retry:
case '?':
if ((c = nextc()) == '\\') {
newtok();
- read_escape(EXPAND_B);
+ read_escape(0);
c = tok()[0];
}
c &= 0xff;
@@ -1830,8 +1839,8 @@ retry:
return c;
case '$':
+ lex_state = EXPR_END;
newtok();
- tokadd(c);
c = nextc();
switch (c) {
case '*': /* $*: argv */
@@ -1854,17 +1863,42 @@ retry:
case '<': /* $<: reading filename */
case '>': /* $>: default output handle */
case '"': /* $": already loaded files */
+ tokadd('$');
tokadd(c);
tokfix();
yylval.id = rb_intern(tok());
- lex_state = EXPR_END;
return GVAR;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ while (isdigit(c)) {
+ tokadd(c);
+ c = nextc();
+ }
+ pushback();
+ tokfix();
+ {
+ ID id = atoi(tok());
+ id <<= ID_SCOPE_SHIFT;
+ id |= ID_NTHREF;
+ yylval.id = id;
+ return NTH_REF;
+ }
+
+ case '0':
default:
if (!is_identchar(c)) {
pushback();
return '$';
}
+ tokadd('$');
}
break;
@@ -2082,87 +2116,36 @@ read_escape(flag)
tokadd(033);
break;
- case 'M':
- if ((c = nextc()) != '-') {
- Error("Invalid escape character syntax");
- tokadd('\0');
- return;
- }
- if ((c = nextc()) == '\\') {
- read_escape(flag);
- tokenbuf[tokidx-1] |= 0200; /* kludge */
- }
+ case 'c':
+ if (c == '?')
+ tokadd(0177);
else {
- tokadd((c & 0xff) | 0200);
+ if (islower(c))
+ c = toupper(c);
+ tokadd(c ^ 64);
}
break;
- case 'C':
- if ((c = nextc()) != '-') {
- Error("Invalid escape character syntax");
- tokadd('\0');
- return;
- }
- case '^':
- if ((c = nextc())== '\\') {
- read_escape (flag);
- tokenbuf[tokidx-1] &= 0237; /* kludge */
- }
- else if (c == '?')
- tokadd(0177);
- else
- tokadd(c & 0237);
- break;
-
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
{ /* octal constant */
- register int i = c - '0';
- register int count = 0;
-
- while (++count < 3) {
- if ((c = nextc()) >= '0' && c <= '7') {
- i *= 8;
- i += c - '0';
- }
- else {
- pushback();
- break;
- }
- }
- tokadd(i&0xff);
+ pushback();
+ SCAN_OCT(c);
+ tokadd(c);
}
break;
case 'x': /* hex constant */
{
- register int i = 0;
- register int count = 0;
-
- while (++count < 3) {
- if ((c = nextc()) >= '0' && c <= '9') {
- i *= 16;
- i += c - '0';
- }
- else if ((int)strchr("abcdefABCDEF", (c = nextc()))) {
- i *= 16;
- i += toupper(c) - 'A' + 10;
- }
- else {
- pushback();
- break;
- }
- }
- tokadd(i&0xff);
+ SCAN_HEX(c);
+ tokadd(c);
}
break;
case 'b': /* backspace */
- if (flag & EXPAND_B) {
- tokadd('\b');
- return;
- }
- /* go turough */
+ tokadd('\b');
+ return;
+
default:
if (flag & LEAVE_BS) {
tokadd('\\');
@@ -2398,6 +2381,9 @@ gettable(id)
else if (is_const_id(id)) {
return NEW_CVAR(id);
}
+ else if (is_nthref_id(id)) {
+ return NEW_NTH_REF(id>>ID_SCOPE_SHIFT);
+ }
}
static NODE*
@@ -2405,14 +2391,12 @@ asignable(id, val)
ID id;
NODE *val;
{
- NODE *lhs;
+ NODE *lhs = Qnil;
if (id == SELF) {
- lhs = Qnil;
Error("Can't change the value of self");
}
else if (id == NIL) {
- lhs = Qnil;
Error("Can't asign to nil");
}
else if (id == _LINE_ || id == _FILE_) {
@@ -2432,6 +2416,9 @@ asignable(id, val)
Error("class constant asigned in method body");
lhs = NEW_CASGN(id, val);
}
+ else if (is_nthref_id(id)) {
+ Error("Can't set variable $%d", id>>ID_SCOPE_SHIFT);
+ }
else {
Bug("bad id for variable");
}
@@ -2476,7 +2463,6 @@ value_expr(node)
case NODE_FAIL:
case NODE_WHILE:
case NODE_WHILE2:
- case NODE_INC:
case NODE_CLASS:
case NODE_MODULE:
case NODE_DEFN:
@@ -2699,8 +2685,8 @@ void
yyappend_print()
{
eval_tree =
- block_append(eval_tree, NEW_CALL(Qnil, rb_intern("print"),
- NEW_ARRAY(NEW_GVAR(rb_intern("$_")))));
+ block_append(eval_tree, NEW_FCALL(rb_intern("print"),
+ NEW_ARRAY(NEW_GVAR(rb_intern("$_")))));
}
void
@@ -2719,7 +2705,7 @@ yywhole_loop(chop, split)
block_append(NEW_CALL(NEW_GVAR(rb_intern("$_")),
rb_intern("chop"), Qnil), eval_tree);
}
- eval_tree = NEW_WHILE(NEW_CALL(0,rb_intern("gets"),0),eval_tree);
+ eval_tree = NEW_WHILE(NEW_FCALL(rb_intern("gets"),0),eval_tree);
}
static struct op_tbl rb_op_tbl[] = {
@@ -2790,7 +2776,7 @@ rb_intern(name)
return id;
id = ++last_id;
- id <<= 3;
+ id <<= ID_SCOPE_SHIFT;
switch (name[0]) {
case '$':
id |= ID_GLOBAL;
diff --git a/process.c b/process.c
index e7e22614a5..ed8a428648 100644
--- a/process.c
+++ b/process.c
@@ -492,6 +492,7 @@ Init_process()
rb_define_private_method(C_Kernel, "sleep", Fsleep, -1);
M_Process = rb_define_module("Process");
+ rb_extend_object(M_Process, M_Process);
rb_define_single_method(M_Process, "fork", Ffork, 0);
rb_define_single_method(M_Process, "_exit", Ffork, 1);
@@ -499,25 +500,25 @@ Init_process()
rb_define_single_method(M_Process, "waitpid", Fwaitpid, 2);
rb_define_single_method(M_Process, "kill", Fkill, -1);
- rb_define_module_function(M_Process, "pid", get_pid, 0);
- rb_define_module_function(M_Process, "ppid", get_ppid, 0);
+ rb_define_method(M_Process, "pid", get_pid, 0);
+ rb_define_method(M_Process, "ppid", get_ppid, 0);
- rb_define_module_function(M_Process, "getpgrp", Fproc_getpgrp, -1);
- rb_define_module_function(M_Process, "setpgrp", Fproc_setpgrp, 2);
+ rb_define_method(M_Process, "getpgrp", Fproc_getpgrp, -1);
+ rb_define_method(M_Process, "setpgrp", Fproc_setpgrp, 2);
- rb_define_module_function(M_Process, "getpriority", Fproc_getpriority, 2);
- rb_define_module_function(M_Process, "setpriority", Fproc_setpriority, 3);
+ rb_define_method(M_Process, "getpriority", Fproc_getpriority, 2);
+ rb_define_method(M_Process, "setpriority", Fproc_setpriority, 3);
rb_define_const(M_Process, "PRIO_PROCESS", INT2FIX(PRIO_PROCESS));
rb_define_const(M_Process, "PRIO_PGRP", INT2FIX(PRIO_PGRP));
rb_define_const(M_Process, "PRIO_USER", INT2FIX(PRIO_USER));
- rb_define_module_function(M_Process, "uid", Fproc_getuid, 0);
- rb_define_module_function(M_Process, "uid=", Fproc_setuid, 1);
- rb_define_module_function(M_Process, "gid", Fproc_getgid, 0);
- rb_define_module_function(M_Process, "gid=", Fproc_setgid, 1);
- rb_define_module_function(M_Process, "euid", Fproc_geteuid, 0);
- rb_define_module_function(M_Process, "euid=", Fproc_seteuid, 1);
- rb_define_module_function(M_Process, "egid", Fproc_getegid, 0);
- rb_define_module_function(M_Process, "egid=", Fproc_setegid, 1);
+ rb_define_method(M_Process, "uid", Fproc_getuid, 0);
+ rb_define_method(M_Process, "uid=", Fproc_setuid, 1);
+ rb_define_method(M_Process, "gid", Fproc_getgid, 0);
+ rb_define_method(M_Process, "gid=", Fproc_setgid, 1);
+ rb_define_method(M_Process, "euid", Fproc_geteuid, 0);
+ rb_define_method(M_Process, "euid=", Fproc_seteuid, 1);
+ rb_define_method(M_Process, "egid", Fproc_getegid, 0);
+ rb_define_method(M_Process, "egid=", Fproc_setegid, 1);
}
diff --git a/re.c b/re.c
index bc83ec71db..0814f287a4 100644
--- a/re.c
+++ b/re.c
@@ -13,7 +13,6 @@
#include "ruby.h"
#include "re.h"
-/* Generate compiled regular expressions */
#if 'a' == 97 /* it's ascii */
static char casetable[] = {
'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
@@ -102,22 +101,16 @@ int len;
rp = ALLOC(Regexp);
MEMZERO((char *)rp, Regexp, 1);
- rp->pat.buffer = ALLOC_N(char, 16);
- rp->pat.allocated = 16;
- rp->pat.fastmap = ALLOC_N(char, 256);
+ rp->buffer = ALLOC_N(char, 16);
+ rp->allocated = 16;
+ rp->fastmap = ALLOC_N(char, 256);
- if ((err = re_compile_pattern(s, (size_t)len, &(rp->pat))) != NULL)
+ if ((err = re_compile_pattern(s, (size_t)len, rp)) != NULL)
Fail("%s: /%s/", err, s);
return rp;
}
-struct match {
- UINT len;
- char *ptr;
- struct re_registers regs;
-};
-
struct match last_match;
VALUE ignorecase;
@@ -134,14 +127,20 @@ research(reg, str, start)
if (FL_TEST(reg, FL_USER1)) {
casefold = TRUE;
}
- if (casefold)
- reg->ptr->pat.translate = casetable;
- else
- reg->ptr->pat.translate = NULL;
+ if (casefold) {
+ if (reg->ptr->translate != casetable) {
+ reg->ptr->translate = casetable;
+ reg->ptr->fastmap_accurate = 0;
+ }
+ }
+ else if (reg->ptr->translate) {
+ reg->ptr->translate = NULL;
+ reg->ptr->fastmap_accurate = 0;
+ }
if (start > str->len) return -1;
- result = re_search(&(reg->ptr->pat), str->ptr, str->len,
- start, str->len - start, &(reg->ptr->regs));
+ result = re_search(reg->ptr, str->ptr, str->len,
+ start, str->len - start, &last_match.regs);
if (result >= 0) {
last_match.len = str->len;
@@ -153,24 +152,23 @@ research(reg, str, start)
}
memcpy(last_match.ptr, str->ptr, last_match.len);
last_match.ptr[last_match.len] = '\0';
- last_match.regs = reg->ptr->regs;
}
return result;
}
-static VALUE
-nth_match(nth)
+VALUE
+re_nth_match(nth)
int nth;
{
int start, end, len;
- if (nth >= RE_NREGS) {
- Fail("match out of range %d, %d", nth, RE_NREGS);
+ if (nth >= last_match.regs.num_regs) {
+ return Qnil;
}
- start = last_match.regs.start[nth];
+ start = BEG(nth);
if (start == -1) return Qnil;
- end = last_match.regs.end[nth];
+ end = END(nth);
len = end - start;
return str_new(last_match.ptr + start, len);
}
@@ -179,7 +177,7 @@ VALUE
re_last_match(id)
ID id;
{
- return nth_match(0);
+ return re_nth_match(0);
}
static VALUE
@@ -187,8 +185,8 @@ re_match_pre()
{
struct match *match;
- if (last_match.regs.start[0] == -1) return Qnil;
- return str_new(last_match.ptr, last_match.regs.start[0]);
+ if (BEG(0) == -1) return Qnil;
+ return str_new(last_match.ptr, BEG(0));
}
static VALUE
@@ -196,24 +194,22 @@ re_match_post()
{
struct match *match;
- if (last_match.regs.start[0] == -1) return Qnil;
- return str_new(last_match.ptr+last_match.regs.end[0],
- last_match.len-last_match.regs.end[0]);
+ if (BEG(0) == -1) return Qnil;
+ return str_new(last_match.ptr+END(0),
+ last_match.len-END(0));
}
static VALUE
re_match_last()
{
- struct match *match;
- int i;
+ int i, len;
- if (last_match.regs.start[0] == -1) return Qnil;
+ if (BEG(0) == -1) return Qnil;
- for (i=0; i<RE_NREGS; i++) {
- if (last_match.regs.start[i] == -1) break;
+ for (i=last_match.regs.num_regs-1; BEG(i) == -1 && i > 0; i--) {
}
- if (i == RE_NREGS) return Qnil;
- return nth_match(i-1);
+ if (i == 0) return Qnil;
+ return re_nth_match(i);
}
static VALUE
@@ -221,7 +217,7 @@ get_match_data(id, nth)
ID id;
int nth;
{
- return nth_match(nth);
+ return re_nth_match(nth);
}
static void
@@ -229,6 +225,10 @@ free_match(data)
struct match *data;
{
free(data->ptr);
+ if (data->regs.allocated > 0) {
+ free(data->regs.beg);
+ free(data->regs.end);
+ }
}
static VALUE
@@ -242,7 +242,8 @@ get_match()
data->len = last_match.len;
data->ptr = ALLOC_N(char, last_match.len+1);
memcpy(data->ptr, last_match.ptr, data->len+1);
- data->regs = last_match.regs;
+ data->regs.allocated = 0;
+ re_copy_registers(&data->regs, &last_match.regs);
return data_new(data, free_match, Qnil);
}
@@ -280,8 +281,8 @@ void
reg_free(rp)
Regexp *rp;
{
- free(rp->pat.buffer);
- free(rp->pat.fastmap);
+ free(rp->buffer);
+ free(rp->fastmap);
free(rp);
}
@@ -472,10 +473,6 @@ re_regsub(str)
if (c == '\\' && (*s == '\\' || *s == '&'))
p = ++s;
} else {
-
-#define BEG(no) last_match.regs.start[no]
-#define END(no) last_match.regs.end[no]
-
if (BEG(no) == -1) continue;
str_cat(val, last_match.ptr+BEG(no), END(no)-BEG(no));
}
@@ -491,6 +488,19 @@ re_regsub(str)
return val;
}
+static VALUE
+kcode()
+{
+ switch (re_syntax_options & RE_MBCTYPE_MASK) {
+ case RE_MBCTYPE_SJIS:
+ return str_new2("SJIS");
+ case RE_MBCTYPE_EUC:
+ return str_new2("EUC");
+ default:
+ return str_new2("NONE");
+ }
+}
+
void
rb_set_kanjicode(code)
char *code;
@@ -500,59 +510,46 @@ rb_set_kanjicode(code)
switch (code[0]) {
case 'E':
case 'e':
- obscure_syntax &= ~RE_MBCTYPE_MASK;
- obscure_syntax |= RE_MBCTYPE_EUC;
+ re_syntax_options &= ~RE_MBCTYPE_MASK;
+ re_syntax_options |= RE_MBCTYPE_EUC;
break;
case 'S':
case 's':
- obscure_syntax &= ~RE_MBCTYPE_MASK;
- obscure_syntax |= RE_MBCTYPE_SJIS;
+ re_syntax_options &= ~RE_MBCTYPE_MASK;
+ re_syntax_options |= RE_MBCTYPE_SJIS;
break;
default:
case 'N':
case 'n':
set_no_conversion:
- obscure_syntax &= ~RE_MBCTYPE_MASK;
+ re_syntax_options &= ~RE_MBCTYPE_MASK;
break;
}
- re_set_syntax(obscure_syntax);
+ re_set_syntax(re_syntax_options);
}
-static VALUE
-kanji_var_get()
+void
+rb_setup_kcode()
{
- switch (obscure_syntax & RE_MBCTYPE_MASK) {
- case RE_MBCTYPE_SJIS:
- return str_new2("SJIS");
- case RE_MBCTYPE_EUC:
- return str_new2("EUC");
- default:
- return Qnil;
- }
+ rb_define_const(C_Object, "KCODE", kcode());
}
-static void
-kanji_var_set(val)
- struct RString *val;
-{
- if (val == Qnil) rb_set_kanjicode(Qnil);
- Check_Type(val, T_STRING);
- rb_set_kanjicode(val->ptr);
-}
+VALUE rb_readonly_hook();
void
Init_Regexp()
{
int i;
- obscure_syntax = RE_NO_BK_PARENS | RE_NO_BK_VBAR
- | RE_CONTEXT_INDEP_OPS | RE_INTERVALS
- | RE_NO_BK_CURLY_BRACES
- | RE_MBCTYPE_EUC;
-
- for (i=0; i<RE_NREGS; i++) {
- last_match.regs.start[i] = last_match.regs.end[i] = -1;
- }
+ re_set_syntax(RE_NO_BK_PARENS | RE_NO_BK_VBAR
+ | RE_AWK_CLASS_HACK
+ | RE_INTERVALS
+ | RE_NO_BK_BRACES
+ | RE_BACKSLASH_ESCAPE_IN_LISTS
+#ifdef DEFAULT_MBCTYPE
+ | DEFAULT_MBCTYPE
+#endif
+);
rb_define_variable("$~", Qnil, get_match, set_match, 0);
@@ -561,18 +558,6 @@ Init_Regexp()
rb_define_variable("$'", Qnil, re_match_post, Qnil, 0);
rb_define_variable("$+", Qnil, re_match_last, Qnil, 0);
- rb_define_variable("$1", Qnil, get_match_data, Qnil, 1);
- rb_define_variable("$2", Qnil, get_match_data, Qnil, 2);
- rb_define_variable("$3", Qnil, get_match_data, Qnil, 3);
- rb_define_variable("$4", Qnil, get_match_data, Qnil, 4);
- rb_define_variable("$5", Qnil, get_match_data, Qnil, 5);
- rb_define_variable("$6", Qnil, get_match_data, Qnil, 6);
- rb_define_variable("$7", Qnil, get_match_data, Qnil, 7);
- rb_define_variable("$8", Qnil, get_match_data, Qnil, 8);
- rb_define_variable("$9", Qnil, get_match_data, Qnil, 9);
-
- rb_define_variable("$KANJI", Qnil, kanji_var_get, kanji_var_set, 0);
-
rb_define_variable("$=", &ignorecase, Qnil, Qnil, 0);
C_Regexp = rb_define_class("Regexp", C_Object);
diff --git a/re.h b/re.h
index e26d325e1f..aa38fbf95a 100644
--- a/re.h
+++ b/re.h
@@ -18,10 +18,19 @@
#include <stdio.h>
#include "regex.h"
-typedef struct Regexp {
- struct re_pattern_buffer pat;
- struct re_registers regs;
-} Regexp;
+
+typedef struct re_pattern_buffer Regexp;
+
+struct match {
+ UINT len;
+ char *ptr;
+ struct re_registers regs;
+};
+
+extern struct match last_match;
+
+#define BEG(no) last_match.regs.beg[no]
+#define END(no) last_match.regs.end[no]
VALUE re_regcomp();
VALUE re_regsub();
diff --git a/regex.c b/regex.c
index bfd604f99c..1a6d9fa97f 100644
--- a/regex.c
+++ b/regex.c
@@ -25,27 +25,15 @@
On the other hand, if you compile with both -Dtest and -Dcanned you
can run some tests we've already thought of. */
-#include "config.h"
-
/* We write fatal error messages on standard error. */
#include <stdio.h>
/* isalpha(3) etc. are used for the character classes. */
#include <ctype.h>
+#include <sys/types.h>
-#ifdef emacs
-
-/* The `emacs' switch turns on certain special matching commands
- that make sense only in emacs. */
-
-#include "lisp.h"
-#include "buffer.h"
-#include "syntax.h"
-
-#else /* not emacs */
-
+#include "config.h"
#include "defines.h"
-#include <sys/types.h>
#ifdef __STDC__
#define P(s) s
@@ -74,6 +62,9 @@ char *alloca ();
#endif
#endif /* __GNUC__ */
+#define RE_ALLOCATE alloca
+#define FREE_VARIABLES() alloca (0)
+
#define FREE_AND_RETURN_VOID(stackb) return
#define FREE_AND_RETURN(stackb,val) return(val)
#define DOUBLE_STACK(stackx,stackb,len) \
@@ -82,12 +73,38 @@ char *alloca ();
/* Only copy what is in use. */ \
(unsigned char **) memcpy (stackx, stackb, len * sizeof (char *)))
#else /* NO_ALLOCA defined */
+
+#define RE_ALLOCATE malloc
+
+#define FREE_VAR(var) if (var) free (var); var = NULL
+#define FREE_VARIABLES() \
+ do { \
+ FREE_VAR (regstart); \
+ FREE_VAR (regend); \
+ FREE_VAR (best_regstart); \
+ FREE_VAR (best_regend); \
+ FREE_VAR (reg_info); \
+ } while (0)
+
#define FREE_AND_RETURN_VOID(stackb) free(stackb);return
#define FREE_AND_RETURN(stackb,val) free(stackb);return(val)
#define DOUBLE_STACK(stackx,stackb,len) \
(unsigned char **)xrealloc (stackb, 2 * len * sizeof (unsigned char *))
#endif /* NO_ALLOCA */
+#define RE_TALLOC(n,t) ((t*)RE_ALLOCATE((n)*sizeof(t)))
+#define TMALLOC(n,t) ((t*)xmalloc((n)*sizeof(t)))
+#define TREALLOC(s,n,t) (s=((t*)xrealloc(s,(n)*sizeof(t))))
+
+/* Get the interface, including the syntax bits. */
+#include "regex.h"
+
+static int re_search_2 P((struct re_pattern_buffer *, char *, int,
+ char *, int, int, int,
+ struct re_registers *));
+static int re_match_2 P((struct re_pattern_buffer *, char *, int,
+ char *, int, int, struct re_registers *));
+
static void store_jump P((char *, int, char *));
static void insert_jump P((int, char *, char *, char *));
static void store_jump_n P((char *, int, char *, unsigned));
@@ -95,7 +112,6 @@ static void insert_jump_n P((int, char *, char *, char *, unsigned));
static void insert_op_2 P((int, char *, char *, int, int ));
static int memcmp_translate P((unsigned char *, unsigned char *,
int, unsigned char *));
-long re_set_syntax P((long));
/* Define the syntax stuff, so we can do the \<, \>, etc. */
@@ -107,16 +123,12 @@ long re_set_syntax P((long));
#define SYNTAX(c) re_syntax_table[c]
-
-#ifdef SYNTAX_TABLE
-
-char *re_syntax_table;
-
-#else /* not SYNTAX_TABLE */
-
static char re_syntax_table[256];
static void init_syntax_once P((void));
+#undef P
+
+#include "util.h"
static void
init_syntax_once ()
@@ -147,20 +159,11 @@ init_syntax_once ()
done = 1;
}
-#endif /* SYNTAX_TABLE */
-#undef P
-#endif /* emacs */
-
-
/* Sequents are missing isgraph. */
#ifndef isgraph
#define isgraph(c) (isprint((c)) && !isspace((c)))
#endif
-/* Get the interface, including the syntax bits. */
-#include "regex.h"
-
-
/* These are the command codes that appear in compiled regular
expressions, one per byte. Some command codes are followed by
argument bytes. A command code can specify any interpretation
@@ -226,22 +229,10 @@ enum regexpcode
duplicate, /* Match a duplicate of something remembered.
Followed by one byte containing the index of the memory
register. */
- before_dot, /* Succeeds if before point. */
- at_dot, /* Succeeds if at point. */
- after_dot, /* Succeeds if after point. */
- begbuf, /* Succeeds if at beginning of buffer. */
- endbuf, /* Succeeds if at end of buffer. */
wordchar, /* Matches any word-constituent character. */
notwordchar, /* Matches any char that is not a word-constituent. */
- wordbeg, /* Succeeds if at word beginning. */
- wordend, /* Succeeds if at word end. */
wordbound, /* Succeeds if at a word boundary. */
notwordbound,/* Succeeds if not at a word boundary. */
- syntaxspec, /* Matches any character whose syntax is specified.
- followed by a byte which contains a syntax code,
- e.g., Sword. */
- notsyntaxspec /* Matches any character whose syntax differs from
- that specified. */
};
@@ -301,39 +292,20 @@ re_set_syntax (syntax)
{
long ret;
- ret = obscure_syntax;
- obscure_syntax = syntax;
+ ret = re_syntax_options;
+ re_syntax_options = syntax;
return ret;
}
/* Set by re_set_syntax to the current regexp syntax to recognize. */
-#ifdef EUC
-#define DEFAULT_MBCTYPE RE_MBCTYPE_EUC
-#else
-#ifdef SJIS
-#define DEFAULT_MBCTYPE RE_MBCTYPE_SJIS
-#else
-#define DEFAULT_MBCTYPE 0
-#endif
-#endif
-long obscure_syntax = DEFAULT_MBCTYPE;
+long re_syntax_options = DEFAULT_MBCTYPE;
/* Macros for re_compile_pattern, which is found below these definitions. */
#define CHAR_CLASS_MAX_LENGTH 6
-
-/* Fetch the next character in the uncompiled pattern, translating it if
- necessary. */
+/* Fetch the next character in the uncompiled pattern. */
#define PATFETCH(c) \
- {if (p == pend) goto end_of_pattern; \
- c = * (unsigned char *) p++; \
- if (translate && !ismbchar (c)) \
- c = (unsigned char) translate[(unsigned char) c]; }
-
-/* Fetch the next character in the uncompiled pattern, with no
- translation. */
-#define PATFETCH_RAW(c) \
{if (p == pend) goto end_of_pattern; \
c = * (unsigned char *) p++; }
@@ -436,20 +408,13 @@ long obscure_syntax = DEFAULT_MBCTYPE;
}; */
static void
-#ifdef __STDC__
-set_list_bits (unsigned short c1, unsigned short c2,
- unsigned char *b, const unsigned char *translate)
-#else
-set_list_bits (c1, c2, b, translate)
- unsigned short c1, c2;
- unsigned char *b;
- const unsigned char *translate;
-#endif
+set_list_bits (c1, c2, b)
+ unsigned short c1, c2;
+ unsigned char *b;
{
- enum regexpcode op = (enum regexpcode) b[-2];
unsigned char sbc_size = b[-1];
unsigned short mbc_size = EXTRACT_UNSIGNED (&b[sbc_size]);
- unsigned short c, beg, end, upb;
+ unsigned short beg, end, upb;
if (c1 > c2)
return;
@@ -464,15 +429,9 @@ set_list_bits (c1, c2, b, translate)
memset (&b[sbc_size], 0, (1 << BYTEWIDTH) / BYTEWIDTH - sbc_size);
b[-1] = sbc_size = (1 << BYTEWIDTH) / BYTEWIDTH;
}
- if (!translate) {
- for (; c1 <= upb; c1++)
- if (!ismbchar (c1))
- SET_LIST_BIT (c1);
- }
- else
- for (; c1 <= upb; c1++)
+ for (; c1 <= upb; c1++)
if (!ismbchar (c1))
- SET_LIST_BIT (translate[c1]);
+ SET_LIST_BIT (c1);
if (c2 < 1 << BYTEWIDTH)
return;
c1 = 0x8000; /* The first wide char */
@@ -513,41 +472,37 @@ set_list_bits (c1, c2, b, translate)
}
static int
-#ifdef __STDC__
-is_in_list (unsigned short c, const unsigned char *b)
-#else
is_in_list (c, b)
- unsigned short c;
- const unsigned char *b;
-#endif
+ unsigned short c;
+ const unsigned char *b;
{
- unsigned short size;
- int in = (enum regexpcode) b[-1] == charset_not;
+ unsigned short size;
- size = *b++;
- if (c < 1 << BYTEWIDTH) {
- if (c / BYTEWIDTH < size && b[c / BYTEWIDTH] & 1 << c % BYTEWIDTH)
- in = !in;
- }
- else {
- unsigned short i, j;
+ size = *b++;
+ if (c < 1 << BYTEWIDTH) {
+ if (c / BYTEWIDTH < size && b[c / BYTEWIDTH] & 1 << c % BYTEWIDTH) {
+ return 1;
+ }
+ }
+ else {
+ unsigned short i, j;
- b += size + 2;
- size = EXTRACT_UNSIGNED (&b[-2]);
+ b += size + 2;
+ size = EXTRACT_UNSIGNED (&b[-2]);
- for (i = 0, j = size; i < j; ) {
- unsigned short k = (i + j) >> 1;
+ for (i = 0, j = size; i < j; ) {
+ unsigned short k = (i + j) >> 1;
- if (c > EXTRACT_MBC (&b[k*4 + 2]))
- i = k + 1;
- else
- j = k;
+ if (c > EXTRACT_MBC (&b[k*4 + 2]))
+ i = k + 1;
+ else
+ j = k;
+ }
+ if (i < size && EXTRACT_MBC (&b[i*4]) <= c
+ && ((unsigned char) c != '\n' && (unsigned char) c != '\0'))
+ return 1;
}
- if (i < size && EXTRACT_MBC (&b[i*4]) <= c
- && ((unsigned char) c != '\n' && (unsigned char) c != '\0'))
- in = !in;
- }
- return in;
+ return 0;
}
/* re_compile_pattern takes a regular-expression string
@@ -571,88 +526,85 @@ re_compile_pattern (pattern, size, bufp)
size_t size;
struct re_pattern_buffer *bufp;
{
- register char *b = bufp->buffer;
- register char *p = pattern;
- char *pend = pattern + size;
- register unsigned c, c1;
- char *p0;
- unsigned char *translate = (unsigned char *) bufp->translate;
-
- /* Address of the count-byte of the most recently inserted `exactn'
- command. This makes it possible to tell whether a new exact-match
- character can be added to that command or requires a new `exactn'
- command. */
-
- char *pending_exact = 0;
-
- /* Address of the place where a forward-jump should go to the end of
- the containing expression. Each alternative of an `or', except the
- last, ends with a forward-jump of this sort. */
-
- char *fixup_jump = 0;
-
- /* Address of start of the most recently finished expression.
- This tells postfix * where to find the start of its operand. */
-
- char *laststart = 0;
-
- /* In processing a repeat, 1 means zero matches is allowed. */
-
- char zero_times_ok;
-
- /* In processing a repeat, 1 means many matches is allowed. */
-
- char many_times_ok;
-
- /* Address of beginning of regexp, or inside of last \(. */
-
- char *begalt = b;
-
- /* In processing an interval, at least this many matches must be made. */
- int lower_bound;
-
- /* In processing an interval, at most this many matches can be made. */
- int upper_bound;
-
- /* Place in pattern (i.e., the {) to which to go back if the interval
- is invalid. */
- char *beg_interval = 0;
-
- /* Stack of information saved by \( and restored by \).
- Four stack elements are pushed by each \(:
+ register char *b = bufp->buffer;
+ register char *p = pattern;
+ char *pend = pattern + size;
+ register unsigned c, c1;
+ char *p0;
+ int numlen;
+
+ /* Address of the count-byte of the most recently inserted `exactn'
+ command. This makes it possible to tell whether a new exact-match
+ character can be added to that command or requires a new `exactn'
+ command. */
+
+ char *pending_exact = 0;
+
+ /* Address of the place where a forward-jump should go to the end of
+ the containing expression. Each alternative of an `or', except the
+ last, ends with a forward-jump of this sort. */
+
+ char *fixup_jump = 0;
+
+ /* Address of start of the most recently finished expression.
+ This tells postfix * where to find the start of its operand. */
+
+ char *laststart = 0;
+
+ /* In processing a repeat, 1 means zero matches is allowed. */
+
+ char zero_times_ok;
+
+ /* In processing a repeat, 1 means many matches is allowed. */
+
+ char many_times_ok;
+
+ /* Address of beginning of regexp, or inside of last \(. */
+
+ char *begalt = b;
+
+ /* In processing an interval, at least this many matches must be made. */
+ int lower_bound;
+
+ /* In processing an interval, at most this many matches can be made. */
+ int upper_bound;
+
+ /* Place in pattern (i.e., the {) to which to go back if the interval
+ is invalid. */
+ char *beg_interval = 0;
+
+ /* Stack of information saved by \( and restored by \).
+ Four stack elements are pushed by each \(:
First, the value of b.
Second, the value of fixup_jump.
Third, the value of regnum.
Fourth, the value of begalt. */
+
+ int stackb[40];
+ int *stackp = stackb;
+ int *stacke = stackb + 40;
+ int *stackt;
+
+ /* Counts \('s as they are encountered. Remembered for the matching \),
+ where it becomes the register number to put in the stop_memory
+ command. */
+
+ int regnum = 1;
+ int range = 0;
- int stackb[40];
- int *stackp = stackb;
- int *stacke = stackb + 40;
- int *stackt;
-
- /* Counts \('s as they are encountered. Remembered for the matching \),
- where it becomes the register number to put in the stop_memory
- command. */
-
- int regnum = 1;
-
- bufp->fastmap_accurate = 0;
-
-#ifndef emacs
-#ifndef SYNTAX_TABLE
- /* Initialize the syntax table. */
- init_syntax_once();
-#endif
-#endif
-
- if (bufp->allocated == 0)
- {
- bufp->allocated = INIT_BUF_SIZE;
- if (bufp->buffer)
- /* EXTEND_BUFFER loses when bufp->allocated is 0. */
- bufp->buffer = (char *) xrealloc (bufp->buffer, INIT_BUF_SIZE);
- else
- /* Caller did not allocate a buffer. Do it for them. */
+ bufp->fastmap_accurate = 0;
+
+ /* Initialize the syntax table. */
+ init_syntax_once();
+
+ if (bufp->allocated == 0)
+ {
+ bufp->allocated = INIT_BUF_SIZE;
+ if (bufp->buffer)
+ /* EXTEND_BUFFER loses when bufp->allocated is 0. */
+ bufp->buffer = (char *) xrealloc (bufp->buffer, INIT_BUF_SIZE);
+ else
+ /* Caller did not allocate a buffer. Do it for them. */
bufp->buffer = (char *) xmalloc (INIT_BUF_SIZE);
if (!bufp->buffer) goto memory_exhausted;
begalt = b = bufp->buffer;
@@ -669,23 +621,18 @@ re_compile_pattern (pattern, size, bufp)
char *p1 = p;
/* When testing what follows the $,
look past the \-constructs that don't consume anything. */
- if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+ if (! (re_syntax_options & RE_CONTEXT_INDEP_OPS))
while (p1 != pend)
{
if (*p1 == '\\' && p1 + 1 != pend
- && (p1[1] == '<' || p1[1] == '>'
- || p1[1] == '`' || p1[1] == '\''
-#ifdef emacs
- || p1[1] == '='
-#endif
- || p1[1] == 'b' || p1[1] == 'B'))
+ && (p1[1] == 'b' || p1[1] == 'B'))
p1 += 2;
else
break;
}
- if (obscure_syntax & RE_TIGHT_VBAR)
+ if (re_syntax_options & RE_TIGHT_VBAR)
{
- if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS) && p1 != pend)
+ if (! (re_syntax_options & RE_CONTEXT_INDEP_OPS) && p1 != pend)
goto normal_char;
/* Make operand of last vbar end before this `$'. */
if (fixup_jump)
@@ -697,14 +644,14 @@ re_compile_pattern (pattern, size, bufp)
/* $ means succeed if at end of line, but only in special contexts.
If validly in the middle of a pattern, it is a normal character. */
- if ((obscure_syntax & RE_CONTEXTUAL_INVALID_OPS) && p1 != pend)
+ if ((re_syntax_options & RE_CONTEXTUAL_INVALID_OPS) && p1 != pend)
goto invalid_pattern;
if (p1 == pend || *p1 == '\n'
- || (obscure_syntax & RE_CONTEXT_INDEP_OPS)
- || (obscure_syntax & RE_NO_BK_PARENS
+ || (re_syntax_options & RE_CONTEXT_INDEP_OPS)
+ || (re_syntax_options & RE_NO_BK_PARENS
? *p1 == ')'
: *p1 == '\\' && p1[1] == ')')
- || (obscure_syntax & RE_NO_BK_VBAR
+ || (re_syntax_options & RE_NO_BK_VBAR
? *p1 == '|'
: *p1 == '\\' && p1[1] == '|'))
{
@@ -717,15 +664,15 @@ re_compile_pattern (pattern, size, bufp)
/* ^ means succeed if at beg of line, but only if no preceding
pattern. */
- if ((obscure_syntax & RE_CONTEXTUAL_INVALID_OPS) && laststart)
+ if ((re_syntax_options & RE_CONTEXTUAL_INVALID_OPS) && laststart)
goto invalid_pattern;
if (laststart && p - 2 >= pattern && p[-2] != '\n'
- && !(obscure_syntax & RE_CONTEXT_INDEP_OPS))
+ && !(re_syntax_options & RE_CONTEXT_INDEP_OPS))
goto normal_char;
- if (obscure_syntax & RE_TIGHT_VBAR)
+ if (re_syntax_options & RE_TIGHT_VBAR)
{
if (p != pattern + 1
- && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+ && ! (re_syntax_options & RE_CONTEXT_INDEP_OPS))
goto normal_char;
BUFPUSH (begline);
begalt = b;
@@ -736,17 +683,17 @@ re_compile_pattern (pattern, size, bufp)
case '+':
case '?':
- if ((obscure_syntax & RE_BK_PLUS_QM)
- || (obscure_syntax & RE_LIMITED_OPS))
+ if ((re_syntax_options & RE_BK_PLUS_QM)
+ || (re_syntax_options & RE_LIMITED_OPS))
goto normal_char;
handle_plus:
case '*':
/* If there is no previous pattern, char not special. */
if (!laststart)
{
- if (obscure_syntax & RE_CONTEXTUAL_INVALID_OPS)
+ if (re_syntax_options & RE_CONTEXTUAL_INVALID_OPS)
goto invalid_pattern;
- else if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+ else if (! (re_syntax_options & RE_CONTEXT_INDEP_OPS))
goto normal_char;
}
/* If there is a sequence of repetition chars,
@@ -762,10 +709,10 @@ re_compile_pattern (pattern, size, bufp)
PATFETCH (c);
if (c == '*')
;
- else if (!(obscure_syntax & RE_BK_PLUS_QM)
+ else if (!(re_syntax_options & RE_BK_PLUS_QM)
&& (c == '+' || c == '?'))
;
- else if ((obscure_syntax & RE_BK_PLUS_QM)
+ else if ((re_syntax_options & RE_BK_PLUS_QM)
&& c == '\\')
{
/* int c1; */
@@ -846,7 +793,7 @@ re_compile_pattern (pattern, size, bufp)
/* Clear the whole map */
memset (b, 0, (1 << BYTEWIDTH) / BYTEWIDTH + 2);
- if ((obscure_syntax & RE_HAT_NOT_NEWLINE) && b[-2] == charset_not)
+ if ((re_syntax_options & RE_HAT_NOT_NEWLINE) && b[-2] == charset_not)
SET_LIST_BIT ('\n');
@@ -854,6 +801,7 @@ re_compile_pattern (pattern, size, bufp)
while (1)
{
int size;
+ unsigned last = -1;
if ((size = EXTRACT_UNSIGNED (&b[(1 << BYTEWIDTH) / BYTEWIDTH]))) {
/* Ensure the space is enough to hold another interval
@@ -862,150 +810,131 @@ re_compile_pattern (pattern, size, bufp)
while (b + size + 1 > bufp->buffer + bufp->allocated)
EXTEND_BUFFER;
}
- /* Don't translate while fetching, in case it's a range bound.
- When we set the bit for the character, we translate it. */
- PATFETCH_RAW (c);
-
- /* If set, \ escapes characters when inside [...]. */
- if ((obscure_syntax & RE_AWK_CLASS_HACK) && c == '\\')
- {
- PATFETCH(c1);
- if (ismbchar (c1)) {
- unsigned char c2;
+ range_retry:
+ PATFETCH (c);
- PATFETCH_RAW (c2);
- c1 = c1 << 8 | c2;
- set_list_bits (c1, c1, (unsigned char *) b, translate);
- continue;
- }
- SET_LIST_BIT (c1);
- continue;
- }
- if (c == ']')
- {
- if (p == p0 + 1)
- {
+ if (c == ']') {
+ if (p == p0 + 1) {
/* If this is an empty bracket expression. */
- if ((obscure_syntax & RE_NO_EMPTY_BRACKETS)
+ if ((re_syntax_options & RE_NO_EMPTY_BRACKETS)
&& p == pend)
- goto invalid_pattern;
- }
+ goto invalid_pattern;
+ }
else
/* Stop if this isn't merely a ] inside a bracket
expression, but rather the end of a bracket
expression. */
- break;
- }
+ break;
+ }
if (ismbchar (c)) {
- unsigned char c2;
-
- PATFETCH_RAW (c2);
- c = c << 8 | c2;
+ PATFETCH (c1);
+ c = c << 8 | c1;
}
- /* Get a range. */
- if (p[0] == '-' && p[1] != ']')
- {
- PATFETCH_RAW (c1);
- /* Don't translate the range bounds while fetching them. */
- PATFETCH_RAW (c1);
- if (ismbchar (c)) {
- unsigned char c2;
- PATFETCH_RAW (c2);
- c1 = c1 << 8 | c2;
+ /* \ escapes characters when inside [...]. */
+ if (c == '\\') {
+ PATFETCH(c);
+ switch (c) {
+ case 'w':
+ for (c = 0; c < 256; c++)
+ if (isalnum(c))
+ SET_LIST_BIT (c);
+ last = -1;
+ continue;
+
+ case 'W':
+ if (re_syntax_options & RE_MBCTYPE_MASK)
+ goto invalid_char;
+ for (c = 0; c < 256; c++)
+ if (!isalnum(c))
+ SET_LIST_BIT (c);
+ last = -1;
+ continue;
+
+ case 's':
+ for (c = 0; c < 256; c++)
+ if (isspace(c))
+ SET_LIST_BIT (c);
+ last = -1;
+ continue;
+
+ case 'S':
+ if (re_syntax_options & RE_MBCTYPE_MASK)
+ goto invalid_char;
+ for (c = 0; c < 256; c++)
+ if (!isspace(c))
+ SET_LIST_BIT (c);
+ last = -1;
+ continue;
+
+ case 'd':
+ for (c = '0'; c <= '9'; c++)
+ SET_LIST_BIT (c);
+ last = -1;
+ continue;
+
+ case 'D':
+ if (re_syntax_options & RE_MBCTYPE_MASK)
+ goto invalid_char;
+ for (c = 0; c < '0'; c++)
+ SET_LIST_BIT (c);
+ for (c = '9' + 1; c < 256; c++)
+ SET_LIST_BIT (c);
+ last = -1;
+ continue;
+
+ case 'x':
+ c = scan_hex(p, 2, &numlen);
+ if ((re_syntax_options & RE_MBCTYPE_MASK) && (c > 0x7f))
+ goto invalid_char;
+ p += numlen;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ PATUNFETCH;
+ c = scan_oct(p, 3, &numlen);
+ if ((re_syntax_options & RE_MBCTYPE_MASK) && (c > 0x7f))
+ goto invalid_char;
+ p += numlen;
+ break;
+
+ default:
+ if (ismbchar (c)) {
+ PATFETCH(c1);
+ c = c << 8 | c1;
+ }
+ break;
}
-
- if ((obscure_syntax & RE_NO_EMPTY_RANGES) && c > c1)
- goto invalid_pattern;
-
- if ((obscure_syntax & RE_NO_HYPHEN_RANGE_END)
- && c1 == '-' && *p != ']')
+ }
+
+ /* Get a range. */
+ if (range) {
+ if (last > c)
goto invalid_pattern;
-
- set_list_bits (c, c1, (unsigned char *) b, translate);
- }
- else if ((obscure_syntax & RE_CHAR_CLASSES)
- && c == '[' && p[0] == ':')
- {
- /* Longest valid character class word has six characters. */
- char str[CHAR_CLASS_MAX_LENGTH];
- PATFETCH_RAW (c);
- c1 = 0;
- /* If no ] at end. */
- if (p == pend)
+
+ if ((re_syntax_options & RE_NO_HYPHEN_RANGE_END)
+ && c == '-' && *p != ']')
goto invalid_pattern;
- while (1)
- {
- /* Don't translate the ``character class'' characters. */
- PATFETCH_RAW (c);
- if (c == ':' || c == ']' || p == pend
- || c1 == CHAR_CLASS_MAX_LENGTH)
- break;
- str[c1++] = c;
- }
- str[c1] = '\0';
- if (p == pend
- || c == ']' /* End of the bracket expression. */
- || p[0] != ']'
- || p + 1 == pend
- || (strcmp (str, "alpha") != 0
- && strcmp (str, "upper") != 0
- && strcmp (str, "lower") != 0
- && strcmp (str, "digit") != 0
- && strcmp (str, "alnum") != 0
- && strcmp (str, "xdigit") != 0
- && strcmp (str, "space") != 0
- && strcmp (str, "print") != 0
- && strcmp (str, "punct") != 0
- && strcmp (str, "graph") != 0
- && strcmp (str, "cntrl") != 0))
- {
- /* Undo the ending character, the letters, and leave
- the leading : and [ (but set bits for them). */
- c1++;
- while (c1--)
- PATUNFETCH;
-#if 1 /* The original was: */
- SET_LIST_BIT ('[');
- SET_LIST_BIT (':');
-#else /* I think this is the right way. */
- if (translate) {
- SET_LIST_BIT (translate['[']);
- SET_LIST_BIT (trasnlate[':']);
- }
- else {
- SET_LIST_BIT ('[');
- SET_LIST_BIT (':');
- }
-#endif
- }
- else
- {
- /* The ] at the end of the character class. */
- PATFETCH (c);
- if (c != ']')
- goto invalid_pattern;
- for (c = 0; c < (1 << BYTEWIDTH); c++)
- {
- if ((strcmp (str, "alpha") == 0 && isalpha (c))
- || (strcmp (str, "upper") == 0 && isupper (c))
- || (strcmp (str, "lower") == 0 && islower (c))
- || (strcmp (str, "digit") == 0 && isdigit (c))
- || (strcmp (str, "alnum") == 0 && isalnum (c))
- || (strcmp (str, "xdigit") == 0 && isxdigit (c))
- || (strcmp (str, "space") == 0 && isspace (c))
- || (strcmp (str, "print") == 0 && isprint (c))
- || (strcmp (str, "punct") == 0 && ispunct (c))
- || (strcmp (str, "graph") == 0 && isgraph (c))
- || (strcmp (str, "cntrl") == 0 && iscntrl (c)))
- SET_LIST_BIT (c);
- }
- }
- }
- else if (translate && c < 1 << BYTEWIDTH)
- SET_LIST_BIT (translate[c]);
+
+ range = 0;
+ if (last < 1 << BYTEWIDTH && c < 1 << BYTEWIDTH) {
+ for (;last<=c;last++)
+ SET_LIST_BIT (last);
+ }
+ else
+ set_list_bits (last, c, (unsigned char*)b);
+ }
+ else if (p[0] == '-' && p[1] != ']') {
+ last = c;
+ PATFETCH(c1);
+ range = 1;
+ goto range_retry;
+ }
+ else if (c < 1 << BYTEWIDTH)
+ SET_LIST_BIT (c);
else
- set_list_bits (c, c, (unsigned char *) b, translate);
+ set_list_bits (c, c, (unsigned char*)b);
}
/* Discard any character set/class bitmap bytes that are all
@@ -1019,46 +948,46 @@ re_compile_pattern (pattern, size, bufp)
break;
case '(':
- if (! (obscure_syntax & RE_NO_BK_PARENS))
+ if (! (re_syntax_options & RE_NO_BK_PARENS))
goto normal_char;
else
goto handle_open;
case ')':
- if (! (obscure_syntax & RE_NO_BK_PARENS))
+ if (! (re_syntax_options & RE_NO_BK_PARENS))
goto normal_char;
else
goto handle_close;
case '\n':
- if (! (obscure_syntax & RE_NEWLINE_OR))
+ if (! (re_syntax_options & RE_NEWLINE_OR))
goto normal_char;
else
goto handle_bar;
case '|':
- if ((obscure_syntax & RE_CONTEXTUAL_INVALID_OPS)
+ if ((re_syntax_options & RE_CONTEXTUAL_INVALID_OPS)
&& (! laststart || p == pend))
goto invalid_pattern;
- else if (! (obscure_syntax & RE_NO_BK_VBAR))
+ else if (! (re_syntax_options & RE_NO_BK_VBAR))
goto normal_char;
else
goto handle_bar;
case '{':
- if (! ((obscure_syntax & RE_NO_BK_CURLY_BRACES)
- && (obscure_syntax & RE_INTERVALS)))
+ if (! ((re_syntax_options & RE_NO_BK_CURLY_BRACES)
+ && (re_syntax_options & RE_INTERVALS)))
goto normal_char;
else
goto handle_interval;
case '\\':
if (p == pend) goto invalid_pattern;
- PATFETCH_RAW (c);
+ PATFETCH(c);
switch (c)
{
case '(':
- if (obscure_syntax & RE_NO_BK_PARENS)
+ if (re_syntax_options & RE_NO_BK_PARENS)
goto normal_backsl;
handle_open:
if (stackp == stacke) goto nesting_too_deep;
@@ -1066,11 +995,8 @@ re_compile_pattern (pattern, size, bufp)
/* Laststart should point to the start_memory that we are about
to push (unless the pattern has RE_NREGS or more ('s). */
*stackp++ = b - bufp->buffer;
- if (regnum < RE_NREGS)
- {
- BUFPUSH (start_memory);
- BUFPUSH (regnum);
- }
+ BUFPUSH (start_memory);
+ BUFPUSH (regnum);
*stackp++ = fixup_jump ? fixup_jump - bufp->buffer + 1 : 0;
*stackp++ = regnum++;
*stackp++ = begalt - bufp->buffer;
@@ -1080,29 +1006,26 @@ re_compile_pattern (pattern, size, bufp)
break;
case ')':
- if (obscure_syntax & RE_NO_BK_PARENS)
+ if (re_syntax_options & RE_NO_BK_PARENS)
goto normal_backsl;
handle_close:
if (stackp == stackb) goto unmatched_close;
begalt = *--stackp + bufp->buffer;
if (fixup_jump)
store_jump (fixup_jump, jump, b);
- if (stackp[-1] < RE_NREGS)
- {
- BUFPUSH (stop_memory);
- BUFPUSH (stackp[-1]);
- }
+ BUFPUSH (stop_memory);
+ BUFPUSH (stackp[-1]);
stackp -= 2;
fixup_jump = *stackp ? *stackp + bufp->buffer - 1 : 0;
laststart = *--stackp + bufp->buffer;
break;
case '|':
- if ((obscure_syntax & RE_LIMITED_OPS)
- || (obscure_syntax & RE_NO_BK_VBAR))
+ if ((re_syntax_options & RE_LIMITED_OPS)
+ || (re_syntax_options & RE_NO_BK_VBAR))
goto normal_backsl;
handle_bar:
- if (obscure_syntax & RE_LIMITED_OPS)
+ if (re_syntax_options & RE_LIMITED_OPS)
goto normal_char;
/* Insert before the previous alternative a jump which
jumps to this alternative if the former fails. */
@@ -1130,10 +1053,10 @@ re_compile_pattern (pattern, size, bufp)
break;
case '{':
- if (! (obscure_syntax & RE_INTERVALS)
+ if (! (re_syntax_options & RE_INTERVALS)
/* Let \{ be a literal. */
- || ((obscure_syntax & RE_INTERVALS)
- && (obscure_syntax & RE_NO_BK_CURLY_BRACES))
+ || ((re_syntax_options & RE_INTERVALS)
+ && (re_syntax_options & RE_NO_BK_CURLY_BRACES))
/* If it's the string "\{". */
|| (p - 2 == pattern && p == pend))
goto normal_backsl;
@@ -1142,7 +1065,7 @@ re_compile_pattern (pattern, size, bufp)
/* If there is no previous pattern, this isn't an interval. */
if (!laststart)
{
- if (obscure_syntax & RE_CONTEXTUAL_INVALID_OPS)
+ if (re_syntax_options & RE_CONTEXTUAL_INVALID_OPS)
goto invalid_pattern;
else
goto normal_backsl;
@@ -1156,15 +1079,15 @@ re_compile_pattern (pattern, size, bufp)
|| *laststart == charset_not
|| *laststart == start_memory
|| (*laststart == exactn && laststart[1] == 1)
- || (! (obscure_syntax & RE_NO_BK_REFS)
+ || (! (re_syntax_options & RE_NO_BK_REFS)
&& *laststart == duplicate)))
{
- if (obscure_syntax & RE_NO_BK_CURLY_BRACES)
+ if (re_syntax_options & RE_NO_BK_CURLY_BRACES)
goto normal_char;
/* Posix extended syntax is handled in previous
statement; this is for Posix basic syntax. */
- if (obscure_syntax & RE_INTERVALS)
+ if (re_syntax_options & RE_INTERVALS)
goto invalid_pattern;
goto normal_backsl;
@@ -1180,7 +1103,7 @@ re_compile_pattern (pattern, size, bufp)
}
if (upper_bound < 0)
upper_bound = lower_bound;
- if (! (obscure_syntax & RE_NO_BK_CURLY_BRACES))
+ if (! (re_syntax_options & RE_NO_BK_CURLY_BRACES))
{
if (c != '\\')
goto invalid_pattern;
@@ -1188,10 +1111,10 @@ re_compile_pattern (pattern, size, bufp)
}
if (c != '}' || lower_bound < 0 || upper_bound > RE_DUP_MAX
|| lower_bound > upper_bound
- || ((obscure_syntax & RE_NO_BK_CURLY_BRACES)
+ || ((re_syntax_options & RE_NO_BK_CURLY_BRACES)
&& p != pend && *p == '{'))
{
- if (obscure_syntax & RE_NO_BK_CURLY_BRACES)
+ if (re_syntax_options & RE_NO_BK_CURLY_BRACES)
goto unfetch_interval;
else
goto invalid_pattern;
@@ -1273,27 +1196,6 @@ re_compile_pattern (pattern, size, bufp)
goto normal_char;
break;
-#ifdef emacs
- case '=':
- BUFPUSH (at_dot);
- break;
-
- case 's':
- laststart = b;
- BUFPUSH (syntaxspec);
- PATFETCH (c);
- BUFPUSH (syntax_spec_code[c]);
- break;
-
- case 'S':
- laststart = b;
- BUFPUSH (notsyntaxspec);
- PATFETCH (c);
- BUFPUSH (syntax_spec_code[c]);
- break;
-#endif /* emacs */
-
-#ifdef RUBY
case 's':
case 'S':
case 'd':
@@ -1334,7 +1236,6 @@ re_compile_pattern (pattern, size, bufp)
2 + EXTRACT_UNSIGNED (&b[(1 << BYTEWIDTH) / BYTEWIDTH])*4);
b += b[-1] + 2 + EXTRACT_UNSIGNED (&b[b[-1]])*4;
break;
-#endif /* RUBY */
case 'w':
laststart = b;
@@ -1345,15 +1246,7 @@ re_compile_pattern (pattern, size, bufp)
laststart = b;
BUFPUSH (notwordchar);
break;
-#ifndef RUBY
- case '<':
- BUFPUSH (wordbeg);
- break;
- case '>':
- BUFPUSH (wordend);
- break;
-#endif /* RUBY */
case 'b':
BUFPUSH (wordbound);
break;
@@ -1362,33 +1255,50 @@ re_compile_pattern (pattern, size, bufp)
BUFPUSH (notwordbound);
break;
- case '`':
- BUFPUSH (begbuf);
- break;
+ /* hex */
+ case 'x':
+ c1 = 0;
+ c = scan_hex(p, 2, &numlen);
+ if ((re_syntax_options & RE_MBCTYPE_MASK) && (c > 0x7f))
+ goto invalid_char;
+ p += numlen;
+ goto numeric_char;
+
+ /* octal */
+ case '0':
+ c1 = 0;
+ c = scan_oct(p, 3, &numlen);
+ p += numlen;
+ goto numeric_char;
+
+ /* back-ref or octal */
+ case '1': case '2': case '3':
+ case '4': case '5': case '6':
+ case '7': case '8': case '9':
+ {
+ char *p_save;
- case '\'':
- BUFPUSH (endbuf);
- break;
+ PATUNFETCH;
+ p_save = p;
+
+ c1 = 0;
+ GET_UNSIGNED_NUMBER(c1);
+
+ if (c1 >= regnum) {
+ if (c1 < RE_NREGS)
+ goto invalid_pattern;
+
+ /* need to get octal */
+ p = p_save;
+ c = scan_oct(p_save, 3, &numlen);
+ if ((re_syntax_options & RE_MBCTYPE_MASK) && (c > 0x7f))
+ goto invalid_char;
+ p = p_save + numlen;
+ c1 = 0;
+ goto numeric_char;
+ }
+ }
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (obscure_syntax & RE_NO_BK_REFS)
- goto normal_char;
- c1 = c - '0';
- if (c1 >= regnum)
- {
- if (obscure_syntax & RE_NO_EMPTY_BK_REF)
- goto invalid_pattern;
- else
- goto normal_char;
- }
/* Can't back reference to a subexpression if inside of it. */
for (stackt = stackp - 2; stackt > stackb; stackt -= 4)
if (*stackt == c1)
@@ -1400,7 +1310,7 @@ re_compile_pattern (pattern, size, bufp)
case '+':
case '?':
- if (obscure_syntax & RE_BK_PLUS_QM)
+ if (re_syntax_options & RE_BK_PLUS_QM)
goto handle_plus;
else
goto normal_backsl;
@@ -1408,10 +1318,6 @@ re_compile_pattern (pattern, size, bufp)
default:
normal_backsl:
- /* You might think it would be useful for \ to mean
- not to translate; but if we don't translate it
- it will never match anything. */
- if (translate && !ismbchar (c)) c = (unsigned char) translate[c];
goto normal_char;
}
break;
@@ -1421,16 +1327,17 @@ re_compile_pattern (pattern, size, bufp)
c1 = 0;
if (ismbchar (c)) {
c1 = c;
- PATFETCH_RAW (c);
+ PATFETCH(c);
}
+ numeric_char:
if (!pending_exact || pending_exact + *pending_exact + 1 != b
|| *pending_exact >= (c1 ? 0176 : 0177)
|| *p == '*' || *p == '^'
- || ((obscure_syntax & RE_BK_PLUS_QM)
+ || ((re_syntax_options & RE_BK_PLUS_QM)
? *p == '\\' && (p[1] == '+' || p[1] == '?')
: (*p == '+' || *p == '?'))
- || ((obscure_syntax & RE_INTERVALS)
- && ((obscure_syntax & RE_NO_BK_CURLY_BRACES)
+ || ((re_syntax_options & RE_INTERVALS)
+ && ((re_syntax_options & RE_NO_BK_CURLY_BRACES)
? *p == '{'
: (p[0] == '\\' && p[1] == '{'))))
{
@@ -1454,16 +1361,20 @@ re_compile_pattern (pattern, size, bufp)
if (stackp != stackb) goto unmatched_open;
bufp->used = b - bufp->buffer;
+ bufp->re_nsub = regnum;
return 0;
+ invalid_char:
+ return "Invalid character in regular expression";
+
invalid_pattern:
return "Invalid regular expression";
unmatched_open:
- return "Unmatched \\(";
+ return "Unmatched (";
unmatched_close:
- return "Unmatched \\)";
+ return "Unmatched )";
end_of_pattern:
return "Premature end of regular expression";
@@ -1600,20 +1511,14 @@ re_compile_fastmap (bufp)
register unsigned char *p = pattern;
register unsigned char *pend = pattern + size;
register int j, k;
- unsigned char *translate = (unsigned char *) bufp->translate;
+ unsigned char *translate = (unsigned char *)bufp->translate;
unsigned is_a_succeed_n;
-#ifndef NO_ALLOCA
- unsigned char *stackb[NFAILURES];
- unsigned char **stackp = stackb;
-
-#else
unsigned char **stackb;
unsigned char **stackp;
- stackb = (unsigned char **) xmalloc (NFAILURES * sizeof (unsigned char *));
+ stackb = RE_TALLOC(NFAILURES, unsigned char*);
stackp = stackb;
-#endif /* NO_ALLOCA */
memset (fastmap, 0, (1 << BYTEWIDTH));
bufp->fastmap_accurate = 1;
bufp->can_be_null = 0;
@@ -1633,26 +1538,15 @@ re_compile_fastmap (bufp)
#endif
{
case exactn:
-#if 1 /* The original was: */
if (translate)
fastmap[translate[p[1]]] = 1;
else
fastmap[p[1]] = 1;
-#else /* The compiled pattern has already been translated. (not true for ruby) */
- fastmap[p[1]] = 1;
-#endif
break;
case begline:
- case before_dot:
- case at_dot:
- case after_dot:
- case begbuf:
- case endbuf:
case wordbound:
case notwordbound:
- case wordbeg:
- case wordend:
continue;
case endline:
@@ -1748,41 +1642,16 @@ re_compile_fastmap (bufp)
fastmap[j] = 1;
break;
-#ifdef emacs
- case syntaxspec:
- k = *p++;
- for (j = 0; j < (1 << BYTEWIDTH); j++)
- if (SYNTAX (j) == (enum syntaxcode) k)
- fastmap[j] = 1;
- break;
-
- case notsyntaxspec:
- k = *p++;
- for (j = 0; j < (1 << BYTEWIDTH); j++)
- if (SYNTAX (j) != (enum syntaxcode) k)
- fastmap[j] = 1;
- break;
-
-#else /* not emacs */
- case syntaxspec:
- case notsyntaxspec:
- break;
-#endif /* not emacs */
-
case charset:
/* NOTE: Charset for single-byte chars never contain
multi-byte char. See set_list_bits(). */
for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
{
-#if 1 /* The original was: */
if (translate)
fastmap[translate[j]] = 1;
else
fastmap[j] = 1;
-#else /* The compiled pattern has already been translated. */
- fastmap[j] = 1;
-#endif
}
{
unsigned short size;
@@ -1830,7 +1699,7 @@ re_compile_fastmap (bufp)
p += p[-1] + 2;
size = EXTRACT_UNSIGNED (&p[-2]);
- c = 0x8000;
+ c = 0x80;
for (j = 0; j < size; j++) {
for (beg = (unsigned char) p[j*4 + 0]; c < beg; c++)
if (ismbchar (c))
@@ -1868,8 +1737,7 @@ re_search (pbufp, string, size, startpos, range, regs)
int size, startpos, range;
struct re_registers *regs;
{
- return re_search_2 (pbufp, (char *) 0, 0, string, size, startpos, range,
- regs, size);
+ return re_search_2 (pbufp, (char*)0, 0, string, size, startpos, range, regs);
}
@@ -1881,23 +1749,20 @@ re_search (pbufp, string, size, startpos, range, regs)
- 1, etc. STRING1 and STRING2 are of SIZE1 and SIZE2, respectively.
In REGS, return the indices of the virtual concatenation of STRING1
and STRING2 that matched the entire PBUFP->buffer and its contained
- subexpressions. Do not consider matching one past the index MSTOP in
- the virtual concatenation of STRING1 and STRING2.
+ subexpressions.
The value returned is the position in the strings at which the match
was found, or -1 if no match was found, or -2 if error (such as
failure stack overflow). */
-int
-re_search_2 (pbufp, string1, size1, string2, size2, startpos, range,
- regs, mstop)
+static int
+re_search_2 (pbufp, string1, size1, string2, size2, startpos, range, regs)
struct re_pattern_buffer *pbufp;
char *string1, *string2;
int size1, size2;
int startpos;
register int range;
struct re_registers *regs;
- int mstop;
{
register char *fastmap = pbufp->fastmap;
register unsigned char *translate = (unsigned char *) pbufp->translate;
@@ -1917,19 +1782,9 @@ re_search_2 (pbufp, string1, size1, string2, size2, startpos, range,
range = total_size - startpos;
/* Update the fastmap now if not correct already. */
- if (fastmap && !pbufp->fastmap_accurate)
- re_compile_fastmap (pbufp);
-
- /* If the search isn't to be a backwards one, don't waste time in a
- long search for a pattern that says it is anchored. */
- if (pbufp->used > 0 && (enum regexpcode) pbufp->buffer[0] == begbuf
- && range > 0)
- {
- if (startpos > 0)
- return -1;
- else
- range = 1;
- }
+ if (fastmap && !pbufp->fastmap_accurate) {
+ re_compile_fastmap (pbufp);
+ }
while (1)
{
@@ -1987,7 +1842,7 @@ re_search_2 (pbufp, string1, size1, string2, size2, startpos, range,
return -1;
val = re_match_2 (pbufp, string1, size1, string2, size2, startpos,
- regs, mstop);
+ regs);
if (val >= 0)
return startpos;
if (val == -2)
@@ -2039,7 +1894,6 @@ re_search_2 (pbufp, string1, size1, string2, size2, startpos, range,
-#ifndef emacs /* emacs never uses this. */
int
re_match (pbufp, string, size, pos, regs)
struct re_pattern_buffer *pbufp;
@@ -2049,7 +1903,6 @@ re_match (pbufp, string, size, pos, regs)
{
return re_match_2 (pbufp, (char *) 0, 0, string, size, pos, regs, size);
}
-#endif /* not emacs */
/* The following are used for re_match_2, defined below: */
@@ -2086,7 +1939,7 @@ struct register_info
fail. The `+ 2' refers to PATTERN_PLACE and STRING_PLACE, which are
arguments to the PUSH_FAILURE_POINT macro. */
-#define MAX_NUM_FAILURE_ITEMS (RE_NREGS * NUM_REG_ITEMS + 2)
+#define MAX_NUM_FAILURE_ITEMS (num_regs * NUM_REG_ITEMS + 2)
/* We push this many things on the stack whenever we fail. */
@@ -2102,8 +1955,8 @@ struct register_info
long last_used_reg, this_reg; \
\
/* Find out how many registers are active or have been matched. \
- (Aside from register zero, which is only set at the end.) */ \
- for (last_used_reg = RE_NREGS - 1; last_used_reg > 0; last_used_reg--)\
+ (Aside from register zero, which is only set at the end.) */ \
+ for (last_used_reg = num_regs - 1; last_used_reg > 0; last_used_reg--)\
if (regstart[last_used_reg] != (unsigned char *)(-1L)) \
break; \
\
@@ -2113,6 +1966,7 @@ struct register_info
unsigned int len = stacke - stackb; \
if (len > re_max_failures * MAX_NUM_FAILURE_ITEMS) \
{ \
+ FREE_VARIABLES(); \
FREE_AND_RETURN(stackb,(-2)); \
} \
\
@@ -2179,8 +2033,8 @@ struct register_info
registers corresponding to the subexpressions of which we currently
are inside. */
#define SET_REGS_MATCHED \
- { unsigned this_reg; \
- for (this_reg = 0; this_reg < RE_NREGS; this_reg++) \
+ { unsigned this_reg; \
+ for (this_reg = 0; this_reg < num_regs; this_reg++) \
{ \
if (IS_ACTIVE(reg_info[this_reg])) \
MATCHED_SOMETHING(reg_info[this_reg]) = 1; \
@@ -2209,15 +2063,37 @@ struct register_info
(SYNTAX ((d) == end1 ? *string2 : (d) == string2 - 1 ? *(end1 - 1) : *(d))\
== Sword)
+static void
+init_regs(regs, num_regs)
+ struct re_registers *regs;
+ unsigned num_regs;
+{
+ int i;
+
+ regs->num_regs = num_regs;
+ if (num_regs < RE_NREGS)
+ num_regs = RE_NREGS;
+
+ if (regs->allocated == 0) {
+ regs->beg = TMALLOC(num_regs, int);
+ regs->end = TMALLOC(num_regs, int);
+ regs->allocated = num_regs;
+ }
+ else if (regs->allocated < num_regs) {
+ TREALLOC(regs->beg, num_regs, int);
+ TREALLOC(regs->end, num_regs, int);
+ }
+ for (i=0; i<num_regs; i++) {
+ regs->beg[i] = regs->end[i] = -1;
+ }
+}
/* Match the pattern described by PBUFP against the virtual
concatenation of STRING1 and STRING2, which are of SIZE1 and SIZE2,
respectively. Start the match at index POS in the virtual
concatenation of STRING1 and STRING2. In REGS, return the indices of
the virtual concatenation of STRING1 and STRING2 that matched the
- entire PBUFP->buffer and its contained subexpressions. Do not
- consider matching one past the index MSTOP in the virtual
- concatenation of STRING1 and STRING2.
+ entire PBUFP->buffer and its contained subexpressions.
If pbufp->fastmap is nonzero, then it had better be up to date.
@@ -2229,20 +2105,21 @@ struct register_info
error (such as match stack overflow). Otherwise the value is the
length of the substring which was matched. */
-int
-re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
+static int
+re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs)
struct re_pattern_buffer *pbufp;
char *string1_arg, *string2_arg;
int size1, size2;
int pos;
struct re_registers *regs;
- int mstop;
{
register unsigned char *p = (unsigned char *) pbufp->buffer;
/* Pointer to beyond end of buffer. */
register unsigned char *pend = p + pbufp->used;
+ unsigned num_regs = pbufp->re_nsub + 1;
+
unsigned char *string1 = (unsigned char *) string1_arg;
unsigned char *string2 = (unsigned char *) string2_arg;
unsigned char *end1; /* Just past end of first string. */
@@ -2267,9 +2144,6 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
``dummy''; if a failure happens and the failure point is a dummy, it
gets discarded and the next next one is tried. */
-#ifndef NO_ALLOCA
- unsigned char *initial_stack[MAX_NUM_FAILURE_ITEMS * NFAILURES];
-#endif
unsigned char **stackb;
unsigned char **stackp;
unsigned char **stacke;
@@ -2283,8 +2157,8 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
stopped matching the regnum-th subexpression. (The zeroth register
keeps track of what the whole pattern matches.) */
- unsigned char *regstart[RE_NREGS];
- unsigned char *regend[RE_NREGS];
+ unsigned char **regstart = RE_TALLOC(num_regs, unsigned char*);
+ unsigned char **regend = RE_TALLOC(num_regs, unsigned char*);
/* The is_active field of reg_info helps us keep track of which (possibly
nested) subexpressions we are currently in. The matched_something
@@ -2293,8 +2167,7 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
subexpression. These two fields get reset each time through any
loop their register is in. */
- struct register_info reg_info[RE_NREGS];
-
+ struct register_info *reg_info = RE_TALLOC(num_regs, struct register_info);
/* The following record the register info as found in the above
variables when we find a match better than any we've seen before.
@@ -2302,15 +2175,16 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
turn happens only if we have not yet matched the entire string. */
unsigned best_regs_set = 0;
- unsigned char *best_regstart[RE_NREGS];
- unsigned char *best_regend[RE_NREGS];
+ unsigned char **best_regstart = RE_TALLOC(num_regs, unsigned char*);
+ unsigned char **best_regend = RE_TALLOC(num_regs, unsigned char*);
+
+ if (regs) {
+ init_regs(regs, num_regs);
+ }
+
/* Initialize the stack. */
-#ifdef NO_ALLOCA
- stackb = (unsigned char **) xmalloc (MAX_NUM_FAILURE_ITEMS * NFAILURES * sizeof (char *));
-#else
- stackb = initial_stack;
-#endif
+ stackb = RE_TALLOC(MAX_NUM_FAILURE_ITEMS * NFAILURES, unsigned char*);
stackp = stackb;
stacke = &stackb[MAX_NUM_FAILURE_ITEMS * NFAILURES];
@@ -2321,41 +2195,27 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
/* Initialize subexpression text positions to -1 to mark ones that no
\( or ( and \) or ) has been seen for. Also set all registers to
inactive and mark them as not having matched anything or ever
- failed. */
- for (mcnt = 0; mcnt < RE_NREGS; mcnt++)
- {
+ failed. */
+ for (mcnt = 0; mcnt < num_regs; mcnt++) {
regstart[mcnt] = regend[mcnt] = (unsigned char *) (-1L);
IS_ACTIVE (reg_info[mcnt]) = 0;
MATCHED_SOMETHING (reg_info[mcnt]) = 0;
- }
+ }
- if (regs)
- for (mcnt = 0; mcnt < RE_NREGS; mcnt++)
- regs->start[mcnt] = regs->end[mcnt] = -1;
-
/* Set up pointers to ends of strings.
Don't allow the second string to be empty unless both are empty. */
- if (size2 == 0)
- {
+ if (size2 == 0) {
string2 = string1;
size2 = size1;
string1 = 0;
size1 = 0;
- }
+ }
end1 = string1 + size1;
end2 = string2 + size2;
/* Compute where to stop matching, within the two strings. */
- if (mstop <= size1)
- {
- end_match_1 = string1 + mstop;
- end_match_2 = string2;
- }
- else
- {
- end_match_1 = end1;
- end_match_2 = string2 + mstop - size1;
- }
+ end_match_1 = end1;
+ end_match_2 = string2 + size2 - size1;
/* `p' scans through the pattern as `d' scans through the data. `dend'
is the end of the input string that `d' points within. `d' is
@@ -2405,7 +2265,7 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
best_regs_set = 1;
best_regend[0] = d; /* Never use regstart[0]. */
- for (mcnt = 1; mcnt < RE_NREGS; mcnt++)
+ for (mcnt = 1; mcnt < num_regs; mcnt++)
{
best_regstart[mcnt] = regstart[mcnt];
best_regend[mcnt] = regend[mcnt];
@@ -2420,7 +2280,7 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
/* Restore best match. */
d = best_regend[0];
- for (mcnt = 0; mcnt < RE_NREGS; mcnt++)
+ for (mcnt = 0; mcnt < num_regs; mcnt++)
{
regstart[mcnt] = best_regstart[mcnt];
regend[mcnt] = best_regend[mcnt];
@@ -2432,23 +2292,23 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
to indices. */
if (regs)
{
- regs->start[0] = pos;
+ regs->beg[0] = pos;
if (MATCHING_IN_FIRST_STRING)
regs->end[0] = d - string1;
else
regs->end[0] = d - string2 + size1;
- for (mcnt = 1; mcnt < RE_NREGS; mcnt++)
+ for (mcnt = 1; mcnt < num_regs; mcnt++)
{
if (regend[mcnt] == (unsigned char *)(-1L))
{
- regs->start[mcnt] = -1;
+ regs->beg[mcnt] = -1;
regs->end[mcnt] = -1;
continue;
}
if (IS_IN_FIRST_STRING (regstart[mcnt]))
- regs->start[mcnt] = regstart[mcnt] - string1;
+ regs->beg[mcnt] = regstart[mcnt] - string1;
else
- regs->start[mcnt] = regstart[mcnt] - string2 + size1;
+ regs->beg[mcnt] = regstart[mcnt] - string2 + size1;
if (IS_IN_FIRST_STRING (regend[mcnt]))
regs->end[mcnt] = regend[mcnt] - string1;
@@ -2456,6 +2316,7 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
regs->end[mcnt] = regend[mcnt] - string2 + size1;
}
}
+ FREE_VARIABLES();
FREE_AND_RETURN(stackb,
(d - pos - (MATCHING_IN_FIRST_STRING ?
string1 :
@@ -2586,7 +2447,7 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
break;
}
if ((translate ? translate[*d] : *d) == '\n'
- || ((obscure_syntax & RE_DOT_NOT_NULL)
+ || ((re_syntax_options & RE_DOT_NOT_NULL)
&& (translate ? translate[*d] : *d) == '\000'))
goto fail;
SET_REGS_MATCHED;
@@ -2597,9 +2458,7 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
case charset_not:
{
int not; /* Nonzero for charset_not. */
- register int c;
- if (*(p - 1) == (unsigned char) charset_not)
- not = 1;
+ int c;
PREFETCH; /* Fetch a data character. */
@@ -2613,14 +2472,17 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
c = (unsigned char) translate[c];
not = is_in_list (c, p);
+ if (*(p - 1) == (unsigned char) charset_not)
+ not = !not;
p += 1 + *p + 2 + EXTRACT_UNSIGNED (&p[1 + *p])*4;
if (!not) goto fail;
SET_REGS_MATCHED;
+
d++;
if (d != dend && c >= 1 << BYTEWIDTH)
- d++;
+ d++;
break;
}
@@ -2686,14 +2548,17 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
if (p1[3] == (unsigned char) exactn && p1[5] != c)
p[-3] = (unsigned char) finalize_jump;
else if (p1[3] == (unsigned char) charset
- || p1[3] == (unsigned char) charset_not)
- {
+ || p1[3] == (unsigned char) charset_not) {
+ int not;
if (ismbchar (c))
c = c << 8 | p2[3];
/* `is_in_list()' is TRUE if c would match */
/* That means it is not safe to finalize. */
- if (!is_in_list (c, p1 + 4))
- p[-3] = (unsigned char) finalize_jump;
+ not = is_in_list (c, p1 + 4);
+ if (p1[3] == (unsigned char) charset_not)
+ not = !not;
+ if (!not)
+ p[-3] = (unsigned char) finalize_jump;
}
}
}
@@ -2798,60 +2663,6 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
goto fail;
break;
- case wordbeg:
- if (IS_A_LETTER (d) && (AT_STRINGS_BEG || !IS_A_LETTER (d - 1)))
- break;
- goto fail;
-
- case wordend:
- /* Have to check if AT_STRINGS_BEG before looking at d - 1. */
- if (!AT_STRINGS_BEG && IS_A_LETTER (d - 1)
- && (!IS_A_LETTER (d) || AT_STRINGS_END))
- break;
- goto fail;
-
-#ifdef emacs
- case before_dot:
- if (PTR_CHAR_POS (d) >= point)
- goto fail;
- break;
-
- case at_dot:
- if (PTR_CHAR_POS (d) != point)
- goto fail;
- break;
-
- case after_dot:
- if (PTR_CHAR_POS (d) <= point)
- goto fail;
- break;
-
- case wordchar:
- mcnt = (int) Sword;
- goto matchsyntax;
-
- case syntaxspec:
- mcnt = *p++;
- matchsyntax:
- PREFETCH;
- if (SYNTAX (*d++) != (enum syntaxcode) mcnt) goto fail;
- SET_REGS_MATCHED;
- break;
-
- case notwordchar:
- mcnt = (int) Sword;
- goto matchnotsyntax;
-
- case notsyntaxspec:
- mcnt = *p++;
- matchnotsyntax:
- PREFETCH;
- if (SYNTAX (*d++) == (enum syntaxcode) mcnt) goto fail;
- SET_REGS_MATCHED;
- break;
-
-#else /* not emacs */
-
case wordchar:
PREFETCH;
if (!IS_A_LETTER (d))
@@ -2868,25 +2679,6 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
SET_REGS_MATCHED;
break;
- case before_dot:
- case at_dot:
- case after_dot:
- case syntaxspec:
- case notsyntaxspec:
- break;
-
-#endif /* not emacs */
-
- case begbuf:
- if (AT_STRINGS_BEG)
- break;
- goto fail;
-
- case endbuf:
- if (AT_STRINGS_END)
- break;
- goto fail;
-
case exactn:
/* Match the next few pattern characters exactly.
mcnt is how many characters to match. */
@@ -2922,27 +2714,8 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
{
do
{
-#if 0
- /* this code suppose that multi-byte chars are not splited
- in string1 and string2. If you want to check this with
- speed cost, change `#if 0' here and next to `#if 1'. */
- unsigned char c;
-
-#endif
PREFETCH;
-#if 0
- c = *d++;
- if (ismbchar (c)) {
- if (c != (unsigned char) *p++
- || !--mcnt
- || d == dend)
- goto fail;
- c = *d++;
- }
- if (c != (unsigned char) *p++) goto fail;
-#else
if (*d++ != *p++) goto fail;
-#endif
}
while (--mcnt);
}
@@ -2973,8 +2746,8 @@ re_match_2 (pbufp, string1_arg, size1, string2_arg, size2, pos, regs, mstop)
/* Restore register info. */
last_used_reg = (long) *--stackp;
- /* Make the ones that weren't saved -1 or 0 again. */
- for (this_reg = RE_NREGS - 1; this_reg > last_used_reg; this_reg--)
+ /* Make the ones that weren't saved -1 or 0 again. */
+ for (this_reg = num_regs - 1; this_reg > last_used_reg; this_reg--)
{
regend[this_reg] = (unsigned char *) (-1L);
regstart[this_reg] = (unsigned char *) (-1L);
@@ -3023,218 +2796,22 @@ memcmp_translate (s1, s2, len, translate)
return 0;
}
-
-
-/* Entry points compatible with 4.2 BSD regex library. */
-
-#if !defined(emacs) && !defined(GAWK) && !defined(RUBY)
-
-static struct re_pattern_buffer re_comp_buf;
-
-char *
-re_comp (s)
- char *s;
-{
- if (!s)
- {
- if (!re_comp_buf.buffer)
- return "No previous regular expression";
- return 0;
- }
-
- if (!re_comp_buf.buffer)
- {
- if (!(re_comp_buf.buffer = (char *) xmalloc (200)))
- return "Memory exhausted";
- re_comp_buf.allocated = 200;
- if (!(re_comp_buf.fastmap = (char *) xmalloc (1 << BYTEWIDTH)))
- return "Memory exhausted";
- }
- return re_compile_pattern (s, strlen (s), &re_comp_buf);
-}
-
-int
-re_exec (s)
- char *s;
-{
- int len = strlen (s);
- return 0 <= re_search (&re_comp_buf, s, len, 0, len,
- (struct re_registers *) 0);
-}
-#endif /* not emacs && not GAWK && not RUBY */
-
-
-
-#ifdef test
-
-#ifdef atarist
-long _stksize = 2L; /* reserve memory for stack */
-#endif
-#include <stdio.h>
-
-/* Indexed by a character, gives the upper case equivalent of the
- character. */
-
-char upcase[0400] =
- { 000, 001, 002, 003, 004, 005, 006, 007,
- 010, 011, 012, 013, 014, 015, 016, 017,
- 020, 021, 022, 023, 024, 025, 026, 027,
- 030, 031, 032, 033, 034, 035, 036, 037,
- 040, 041, 042, 043, 044, 045, 046, 047,
- 050, 051, 052, 053, 054, 055, 056, 057,
- 060, 061, 062, 063, 064, 065, 066, 067,
- 070, 071, 072, 073, 074, 075, 076, 077,
- 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
- 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
- 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
- 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
- 0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
- 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
- 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
- 0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
- 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
- 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
- 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
- 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
- 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
- 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
- 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
- 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
- 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
- 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
- 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
- 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
- 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
- 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
- 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
- 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
- };
-
-#ifdef canned
-
-#include "tests.h"
-
-typedef enum { extended_test, basic_test } test_type;
-
-/* Use this to run the tests we've thought of. */
-
void
-main ()
+re_copy_registers(regs1, regs2)
+ struct re_registers *regs1, *regs2;
{
- test_type t = extended_test;
+ int i;
- if (t == basic_test)
- {
- printf ("Running basic tests:\n\n");
- test_posix_basic ();
- }
- else if (t == extended_test)
- {
- printf ("Running extended tests:\n\n");
- test_posix_extended ();
+ if (regs1->allocated == 0) {
+ regs1->beg = TMALLOC(regs2->num_regs, int);
+ regs1->end = TMALLOC(regs2->num_regs, int);
}
-}
-
-#else /* not canned */
-
-/* Use this to run interactive tests. */
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- char pat[80];
- struct re_pattern_buffer buf;
- int i;
- char c;
- char fastmap[(1 << BYTEWIDTH)];
-
- /* Allow a command argument to specify the style of syntax. */
- if (argc > 1)
- obscure_syntax = atol (argv[1]);
-
- buf.allocated = 40;
- buf.buffer = (char *) xmalloc (buf.allocated);
- buf.fastmap = fastmap;
- buf.translate = upcase;
-
- while (1)
- {
- gets (pat);
-
- if (*pat)
- {
- re_compile_pattern (pat, strlen(pat), &buf);
-
- for (i = 0; i < buf.used; i++)
- printchar (buf.buffer[i]);
-
- putchar ('\n');
-
- printf ("%d allocated, %d used.\n", buf.allocated, buf.used);
-
- re_compile_fastmap (&buf);
- printf ("Allowed by fastmap: ");
- for (i = 0; i < (1 << BYTEWIDTH); i++)
- if (fastmap[i]) printchar (i);
- putchar ('\n');
- }
-
- gets (pat); /* Now read the string to match against */
-
- i = re_match (&buf, pat, strlen (pat), 0, 0);
- printf ("Match value %d.\n", i);
+ else if (regs1->allocated < regs2->num_regs) {
+ TREALLOC(regs1->beg, regs2->num_regs, int);
+ TREALLOC(regs1->end, regs2->num_regs, int);
}
-}
-
-#endif
-
-
-#ifdef NOTDEF
-print_buf (bufp)
- struct re_pattern_buffer *bufp;
-{
- int i;
-
- printf ("buf is :\n----------------\n");
- for (i = 0; i < bufp->used; i++)
- printchar (bufp->buffer[i]);
-
- printf ("\n%d allocated, %d used.\n", bufp->allocated, bufp->used);
-
- printf ("Allowed by fastmap: ");
- for (i = 0; i < (1 << BYTEWIDTH); i++)
- if (bufp->fastmap[i])
- printchar (i);
- printf ("\nAllowed by translate: ");
- if (bufp->translate)
- for (i = 0; i < (1 << BYTEWIDTH); i++)
- if (bufp->translate[i])
- printchar (i);
- printf ("\nfastmap is%s accurate\n", bufp->fastmap_accurate ? "" : "n't");
- printf ("can %s be null\n----------", bufp->can_be_null ? "" : "not");
-}
-#endif /* NOTDEF */
-
-printchar (c)
- char c;
-{
- if (c < 040 || c >= 0177)
- {
- putchar ('\\');
- putchar (((c >> 6) & 3) + '0');
- putchar (((c >> 3) & 7) + '0');
- putchar ((c & 7) + '0');
+ for (i=0; i<regs2->num_regs; i++) {
+ regs1->beg[i] = regs2->beg[i];
+ regs1->end[i] = regs2->end[i];
}
- else
- putchar (c);
-}
-
-error (string)
- char *string;
-{
- puts (string);
- exit (1);
}
-#endif /* test */
diff --git a/regex.h b/regex.h
index 8481bc84b3..8162d79119 100644
--- a/regex.h
+++ b/regex.h
@@ -38,10 +38,10 @@
/* This defines the various regexp syntaxes. */
-extern long obscure_syntax;
+extern long re_syntax_options;
-/* The following bits are used in the obscure_syntax variable to choose among
+/* The following bits are used in the re_syntax_options variable to choose among
alternative regexp syntaxes. */
/* If this bit is set, plain parentheses serve as grouping, and backslash
@@ -93,6 +93,7 @@ extern long obscure_syntax;
If set, then { and } serve as interval operators and \{ and \} are
literals. */
#define RE_NO_BK_CURLY_BRACES (1L << 8)
+#define RE_NO_BK_BRACES RE_NO_BK_CURLY_BRACES
/* If this bit is set, then character classes are supported; they are:
[:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
@@ -142,6 +143,9 @@ extern long obscure_syntax;
If it isn't, then it can. */
#define RE_NO_HYPHEN_RANGE_END (1L << 18)
+/* If this bit is not set, then \ inside a bracket expression is literal.
+ If set, then such a \ quotes the following character. */
+#define RE_BACKSLASH_ESCAPE_IN_LISTS (1L << 19)
/* Define combinations of bits for the standard possibilities. */
#define RE_SYNTAX_POSIX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR \
@@ -165,15 +169,25 @@ extern long obscure_syntax;
| RE_NO_HYPHEN_RANGE_END)
/* For multi-byte char support */
-#define RE_MBCTYPE_EUC (1L << 19)
-#define RE_MBCTYPE_SJIS (1L << 20)
+#define RE_MBCTYPE_EUC (1L << 20)
+#define RE_MBCTYPE_SJIS (1L << 21)
#define RE_MBCTYPE_MASK (RE_MBCTYPE_EUC | RE_MBCTYPE_SJIS)
+#ifdef EUC
+#define DEFAULT_MBCTYPE RE_MBCTYPE_EUC
+#else
+#ifdef SJIS
+#define DEFAULT_MBCTYPE RE_MBCTYPE_SJIS
+#else
+#define DEFAULT_MBCTYPE 0
+#endif
+#endif
+
#undef ismbchar
#define ismbchar(c) \
- (obscure_syntax & RE_MBCTYPE_EUC \
+ (re_syntax_options & RE_MBCTYPE_EUC \
? ((unsigned char) (c) >= 0x80) \
- : (obscure_syntax & RE_MBCTYPE_SJIS \
+ : (re_syntax_options & RE_MBCTYPE_SJIS \
? (( 0x80 <= (unsigned char) (c) \
&& (unsigned char) (c) <= 0x9f) \
|| (0xe0 <= (unsigned char) (c))) \
@@ -193,6 +207,9 @@ struct re_pattern_buffer
comparing, or zero for no translation.
The translation is applied to a pattern when it is
compiled and to data when it is matched. */
+
+
+ long re_nsub; /* Number of subexpressions found by the compiler. */
char fastmap_accurate;
/* Set to zero when a new pattern is stored,
set to one when the fastmap is updated from it. */
@@ -223,8 +240,10 @@ struct re_pattern_buffer
struct re_registers
{
- int start[RE_NREGS];
- int end[RE_NREGS];
+ unsigned allocated;
+ unsigned num_regs;
+ int *beg;
+ int *end;
};
@@ -236,14 +255,10 @@ extern char *re_compile_pattern (char *, size_t, struct re_pattern_buffer *);
extern void re_compile_fastmap (struct re_pattern_buffer *);
extern int re_search (struct re_pattern_buffer *, char*, int, int, int,
struct re_registers *);
-extern int re_search_2 (struct re_pattern_buffer *, char *, int,
- char *, int, int, int,
- struct re_registers *, int);
extern int re_match (struct re_pattern_buffer *, char *, int, int,
struct re_registers *);
-extern int re_match_2 (struct re_pattern_buffer *, char *, int,
- char *, int, int, struct re_registers *, int);
extern long re_set_syntax (long syntax);
+extern void re_copy_registers (struct re_registers*, struct re_registers*);
#ifndef RUBY
/* 4.2 bsd compatibility. */
@@ -256,15 +271,10 @@ extern int re_exec (char *);
extern char *re_compile_pattern ();
/* Is this really advertised? */
extern void re_compile_fastmap ();
-extern int re_search (), re_search_2 ();
-extern int re_match (), re_match_2 ();
+extern int re_search ();
+extern int re_match ();
extern long re_set_syntax();
-
-#ifndef RUBY
-/* 4.2 bsd compatibility. */
-extern char *re_comp ();
-extern int re_exec ();
-#endif
+extern void re_copy_registers ();
#endif /* __STDC__ */
diff --git a/ruby.1 b/ruby.1
index f3bb919183..b8c6162554 100644
--- a/ruby.1
+++ b/ruby.1
@@ -39,6 +39,15 @@ ruby \- オブジェクト指向スクリプト言語
.B ruby
インタプリタは以下の引数を受け付ける.
.TP 5
+.B \-0数字
+入力レコードセパレータ(`$/')の8進数で指定する.
+
+数字を指定しない場合はヌルキャラクタがセパレータになる。数の
+後に他のスイッチがあってもよい。
+
+\-00で, パラグラフモード, \-0777で(そのコードを持つ文字は存
+在しないので)全ファイルを一度に読み込むモードに設定できる.
+.TP 5
.B \-a
`\-n'や`\-p'とともに用いて, オートスプリットモードをONにする.
オートスプリットモードでは各ループの先頭で,
@@ -55,21 +64,20 @@ ruby \- オブジェクト指向スクリプト言語
スクリプトの内部形式へのコンパイルのみを行い, 実行しない. コ
ンパイル終了後, 文法エラーが無ければ, "Syntax OK"と出力する.
.TP 5
-.B \-C " code"
+.B \-K " c"
.B ruby
の処理する漢字コードを指定する.
.B ruby
-は指定した文字列が `E'または`e'から始まる場合は文字列やアク
-セスするファイルがEUCで記述されていると仮定する. 同様に`S'ま
-たは`s'の場合はSJISとして処理する. `N'は漢字を処理しない. デ
-フォルトはEUC.
+は指定した文字列 `E'または`e'の場合は文字列やアクセスするファ
+イルがEUCで記述されていると仮定する. 同様に`S'または`s'の場
+合はSJISとして処理する. `N'は漢字を処理しない. デフォルトは
+EUC.
.nf
.ne 2
- ruby -C EUC -e 'print "テスト"'
- ruby -Ceuc -e 'print "テスト"'
- ruby -C 'Shift JIS' -e 'print "テスト"'
- ruby -CN 'print "テスト"'
+ ruby -CE -e 'print "テスト"'
+ ruby -Cs -e 'print "テスト"'
+ ruby -Cn -e 'print "テスト"'
.fi
このオプションは将来文字コードの自動判別機能が追加された場合
@@ -83,11 +91,11 @@ ruby \- オブジェクト指向スクリプト言語
コマンドラインからスクリプトを指定する. \-eオプションを付け
た時には引数からスクリプトファイル名を取らない.
.TP 5
-.B \-F " 文字列"
+.B \-F" 文字列"
入力フィールドセパレータ(`$;')の値を文字列にセットする. awk
の同名のオプションと同じ働きをする.
.TP 5
-.B \-i " extension"
+.B \-i" extension"
引数で指定されたファイルの内容を置き換える(in-place edit)こ
とを指定する. 元のファイルは拡張子をつけた形で保存される.
.nf
@@ -105,7 +113,7 @@ ruby \- オブジェクト指向スクリプト言語
.fi
.TP 5
-.B \-I " directory"
+.B \-I" directory"
ファイルをロードするパスを指定(追加)する. 指定されたディレク
トリは
.B ruby
@@ -139,15 +147,6 @@ ruby \- オブジェクト指向スクリプト言語
.fi
.TP 5
-.B \-R 文字列(または8進数)
-入力レコードセパレータ(`$/')の値を文字列にセットする. 文字列
-がすべて数字(0-7まで)から構成されている時には, その8進数で指
-定されたコードをもつ文字をセパレータとする.
-
-この場合, \-R0で, パラグラフモード, \-R777で(そのコードを持
-つ文字は存在しないので)全ファイルを一度に読み込むモードに設
-定できる.
-.TP 5
.B \-s
スクリプト名に続く, \-で始まる引数を解釈して, 同名の大域変数
に値を設定する. `\-\-'なる引数以降は解釈を行なわない. 該当す
@@ -207,14 +206,14 @@ $VERBOSEをセットする. この変数がセットされている時, いくつか
.fi
.TP 5
-.B \-x
+.B \-x"directory"
メッセージ中のスクリプトを取り出して実行する. #!で始まり,
"ruby"という文字列を含む行までを読み飛ばす. スクリプトの終り
はEOF(ファイルの終り), ^D(コントロールD), ^Z(コントロールZ)
または予約語``__END__''で指定する.
-.TP 5
-.B \-X " directory"
-スクリプト実行前に指定されたディレクトリに移る.
+
+ディレクトリ名を指定すると,スクリプト実行前に指定されたディ
+レクトリに移る.
.TP 5
.B \-y, \-\-yydebug
コンパイラデバッグモード. コンパイル時の構文解析の過程を表示
diff --git a/ruby.c b/ruby.c
index 87bb14ba24..7b029cd84c 100644
--- a/ruby.c
+++ b/ruby.c
@@ -18,20 +18,8 @@
#include <sys/stat.h>
#include <signal.h>
-#include "getopt.h"
-
static int version, copyright;
-static struct option long_options[] =
-{
- {"debug", 0, 0, 'd'},
- {"yydebug", 0, 0, 'y'},
- {"verbose", 0, 0, 'v'},
- {"version", 0, &version, 1},
- {"copyright", 0, &copyright, 1},
- {0, 0, 0, 0}
-};
-
int debug = 0;
int verbose = 0;
static int sflag = FALSE;
@@ -67,12 +55,11 @@ proc_options(argcp, argvp)
{
int argc = *argcp;
char **argv = *argvp;
+ int script_given, do_search;
+ char *s;
+
extern VALUE rb_load_path;
- extern char *optarg;
- extern int optind;
- int c, i, j, script_given, do_search, opt_index;
extern VALUE RS, ORS, FS;
- char *src;
if (argc == 0) return;
@@ -80,114 +67,155 @@ proc_options(argcp, argvp)
script_given = FALSE;
do_search = FALSE;
- optind = 0;
- while ((c = getopt_long(argc, argv, "+acC:de:F:i:I:lnpR:svxX:yS",
- long_options, &opt_index)) != EOF) {
- switch (c) {
+ for (argc--,argv++; argc > 0; argc--,argv++) {
+ if (argv[0][0] != '-' || !argv[0][1]) break;
+
+ s = argv[0]+1;
+ reswitch:
+ switch (*s) {
+ case 'a':
+ do_split = TRUE;
+ s++;
+ goto reswitch;
+
case 'p':
do_print = TRUE;
/* through */
case 'n':
do_loop = TRUE;
- break;
+ s++;
+ goto reswitch;
case 'd':
debug = TRUE;
- break;
+ s++;
+ goto reswitch;
case 'y':
yydebug = 1;
- break;
+ s++;
+ goto reswitch;
case 'v':
verbose = TRUE;
show_version();
- break;
+ s++;
+ goto reswitch;
+
+ case 'c':
+ do_check = TRUE;
+ s++;
+ goto reswitch;
+
+ case 's':
+ sflag = TRUE;
+ s++;
+ goto reswitch;
+
+ case 'l':
+ do_line = TRUE;
+ ORS = RS;
+ s++;
+ goto reswitch;
+
+ case 'S':
+ do_search = TRUE;
+ s++;
+ goto reswitch;
case 'e':
script_given++;
if (script == 0) script = "-e";
- lex_setsrc("-e", optarg, strlen(optarg));
+ if (argv[1]) {
+ lex_setsrc("-e", argv[1], strlen(argv[1]));
+ argc--,argv++;
+ }
+ else {
+ lex_setsrc("-e", "", 0);
+ }
yyparse();
break;
case 'i':
- inplace = strdup(optarg);
- break;
-
- case 'c':
- do_check = TRUE;
+ inplace = strdup(s+1);
break;
case 'x':
xflag = TRUE;
+ s++;
+ if (*s && chdir(s) < 0) {
+ Fatal("Can't chdir to %s", s);
+ }
break;
- case 'X':
- if (chdir(optarg) < 0)
- Fatal("Can't chdir to %s", optarg);
+ case 'F':
+ FS = str_new2(s+1);
break;
- case 's':
- sflag = TRUE;
- break;
+ case 'K':
+ s++;
+ rb_set_kanjicode(s);
+ s++;
+ goto reswitch;
- case 'l':
- do_line = TRUE;
- ORS = RS;
+ case 'I':
+ ary_unshift(rb_load_path, str_new2(s+1));
break;
- case 'R':
+ case '0':
{
- char *p = optarg;
-
- while (*p) {
- if (*p < '0' || '7' < *p) {
- break;
- }
- p++;
- }
- if (*p) {
- RS = str_new2(optarg);
+ int numlen;
+ int v;
+ char c;
+
+ v = scan_oct(s, 4, &numlen);
+ s += numlen;
+ if (v > 0377) RS = Qnil;
+ else if (v == 0 && numlen >= 2) {
+ RS = str_new2("\n\n");
}
else {
- int i = strtoul(optarg, Qnil, 8);
-
- if (i == 0) RS = str_new(0, 0);
- else if (i > 0xff) RS = Qnil;
- else {
- char c = i;
- RS = str_new(&c, 1);
- }
+ c = v & 0xff;
+ RS = str_new(&c, 1);
}
}
- break;
+ goto reswitch;
- case 'F':
- FS = str_new2(optarg);
- break;
+ case 'u':
+ case 'U':
- case 'a':
- do_split = TRUE;
- break;
-
- case 'C':
- rb_set_kanjicode(optarg);
- break;
-
- case 'S':
- do_search = TRUE;
- break;
-
- case 'I':
- ary_unshift(rb_load_path, str_new2(optarg));
+ case '-':
+ if (!s[1]) {
+ argc--,argv++;
+ goto switch_end;
+ }
+ s++;
+ if (strcmp("copyright", s) == 0)
+ copyright = 1;
+ else if (strcmp("debug", s) == 0)
+ debug = 1;
+ else if (strcmp("version", s) == 0)
+ version = 1;
+ else if (strcmp("verbose", s) == 0)
+ verbose = 1;
+ else if (strcmp("yydebug", s) == 0)
+ yydebug = 1;
+ else {
+ Fatal("Unrecognized long option: --%s",s);
+ }
break;
default:
+ Fatal("Unrecognized switch: -%s",s);
+
+ case 0:
break;
}
}
+ switch_end:
+ if (*argvp[0] == Qnil) return;
+
if (version) {
show_version();
exit(0);
@@ -196,28 +224,28 @@ proc_options(argcp, argvp)
show_copyright();
}
- if (argv[0] == Qnil) return;
+ rb_setup_kcode();
if (script_given == 0) {
- if (argc == optind) { /* no more args */
+ if (argc == 0) { /* no more args */
if (verbose) exit(0);
script = "-";
load_stdin();
}
else {
- script = argv[optind];
+ script = argv[0];
if (do_search) {
script = dln_find_file(script, getenv("PATH"));
- if (!script) script = argv[optind];
+ if (!script) script = argv[0];
}
load_file(script, 1);
- optind++;
+ argc--,argv++;
}
}
xflag = FALSE;
- *argvp += optind;
- *argcp -= optind;
+ *argvp = argv;
+ *argcp = argc;
if (sflag) {
char *s;
@@ -239,6 +267,7 @@ proc_options(argcp, argvp)
}
*argcp = argc; *argvp = argv;
}
+
}
static void
diff --git a/ruby.h b/ruby.h
index 5786574502..a08a6082a2 100644
--- a/ruby.h
+++ b/ruby.h
@@ -161,7 +161,7 @@ struct RArray {
struct RRegexp {
struct RBasic basic;
- struct Regexp *ptr;
+ struct re_pattern_buffer *ptr;
UINT len;
char *str;
};
diff --git a/sample/Artistic b/sample/Artistic
deleted file mode 100644
index e69de29bb2..0000000000
--- a/sample/Artistic
+++ /dev/null
diff --git a/sample/evaldef.rb b/sample/evaldef.rb
index a705300a94..2cedd54999 100644
--- a/sample/evaldef.rb
+++ b/sample/evaldef.rb
@@ -18,8 +18,8 @@ class Bar : Foo
end
end
-f = foo.new
-b = bar.new
+f = Foo.new
+b = Bar.new
b.foo
b.bar
diff --git a/sample/export.rb b/sample/export.rb
index a6dfa8e40e..2d05d8afd7 100644
--- a/sample/export.rb
+++ b/sample/export.rb
@@ -1,18 +1,38 @@
# method access permission
# output:
# foobar
-# foo
+# Foo
class Foo
- export :printf
+ public :printf
+ def baz
+ print "baz\n"
+ end
+ private :baz
+
+ def quux
+ print "in QUUX "
+ baz()
+ end
end
def foobar
print "foobar\n"
end
-f = foo.new
-#foo.unexport :printf
-foo.export :foobar
+f = Foo.new
+#Foo.private :printf
+Foo.public :foobar
f.foobar
-f.printf "%s\n", foo
+f.printf "%s\n", Foo
+
+f.quux
+
+class Bar : Foo
+ def quux
+ super
+ baz()
+ end
+end
+
+Bar.new.quux
diff --git a/sample/exyacc.rb b/sample/exyacc.rb
index ad6191c03d..cd1170feb4 100644
--- a/sample/exyacc.rb
+++ b/sample/exyacc.rb
@@ -1,4 +1,4 @@
-#! /usr/local/bin/ruby -Cn
+#! /usr/local/bin/ruby -Kn
# usage: exyacc.rb [yaccfiles]
# this is coverted from exyacc.pl in the camel book
diff --git a/sample/from.rb b/sample/from.rb
index f6602943af..a8baf4f375 100644
--- a/sample/from.rb
+++ b/sample/from.rb
@@ -17,8 +17,8 @@ module ParseDate
if date.sub(/\s+(\d+:\d+(:\d+)?)/, ' ')
time = $1
end
- if date =~ /19\d\d/
- year = $&
+ if date =~ /19(\d\d)/
+ year = $1
end
if date.sub(/\s*(\d+)\s+(#{MONTHPAT})\S*\s+/, ' ')
dayofmonth = $1
diff --git a/sample/opt_x.rb b/sample/opt_x.rb
deleted file mode 100644
index e69de29bb2..0000000000
--- a/sample/opt_x.rb
+++ /dev/null
diff --git a/sample/ruby-mode.el b/sample/ruby-mode.el
index aa91be330d..fd44dc661b 100644
--- a/sample/ruby-mode.el
+++ b/sample/ruby-mode.el
@@ -18,7 +18,7 @@
(defconst ruby-block-end-re "end")
(defconst ruby-delimiter
- (concat "[$/<(){}#\"'`]\\|\\[\\|\\]\\|\\b\\("
+ (concat "[$/(){}#\"'`]\\|\\[\\|\\]\\|\\b\\("
ruby-block-beg-re "\\|" ruby-block-end-re "\\)\\b")
)
@@ -178,9 +178,7 @@ The variable ruby-indent-level controls the amount of indentation.
(t
(goto-char indent-point)
(setq in-string t))))
- ((or (string= "/" w)
- (string= "<" w))
- (if (string= "<" w) (setq w ">"))
+ ((string= "/" w)
(let (c)
(save-excursion
(goto-char pnt)
@@ -263,6 +261,120 @@ The variable ruby-indent-level controls the amount of indentation.
(error (format "bad string %s" w)))))))
(list in-string in-paren (car nest) depth)))
+(defun ruby-parse-region (start end)
+ (let ((indent-point end)
+ (indent 0)
+ (in-string nil)
+ (in-paren nil)
+ (depth 0)
+ (nest nil))
+ (save-excursion
+ (if start
+ (goto-char start)
+ (ruby-beginning-of-defun))
+ (while (and (> indent-point (point))
+ (re-search-forward ruby-delimiter indent-point t))
+ (let ((w (buffer-substring (match-beginning 0) (match-end 0)))
+ (pnt (match-beginning 0)))
+ (cond
+ ((or (string= "\"" w) ;skip string
+ (string= "'" w)
+ (string= "`" w))
+ (cond
+ ((string= w (char-to-string (char-after (point))))
+ (forward-char 1))
+ ((re-search-forward (format "[^\\]%s" w) indent-point t)
+ nil)
+ (t
+ (goto-char indent-point)
+ (setq in-string t))))
+ ((or (string= "/" w)
+ (string= "<" w))
+ (if (string= "<" w) (setq w ">"))
+ (let (c)
+ (save-excursion
+ (goto-char pnt)
+ (skip-chars-backward " \t")
+ (setq c (char-after (1- (point))))
+ (if c (setq c (char-syntax c))))
+ (if (or (eq c ?.)
+ (and (eq c ?w)
+ (save-excursion
+ (forward-word -1)
+ (or
+ (looking-at ruby-block-beg-re)
+ (looking-at ruby-block-mid-re)))))
+ (cond
+ ((string= w (char-to-string (char-after (point))))
+ (forward-char 1))
+ ((re-search-forward (format "[^\\]%s" w) indent-point t)
+ nil)
+ (t
+ (goto-char indent-point)
+ (setq in-string t))))))
+ ((string= "$" w) ;skip $char
+ (forward-char 1))
+ ((string= "#" w) ;skip comment
+ (forward-line 1))
+ ((string= "(" w) ;skip to matching paren
+ (let ((orig depth))
+ (setq nest (cons (point) nest))
+ (setq depth (1+ depth))
+ (while (and (/= depth orig)
+ (re-search-forward "[()]" indent-point t))
+ (cond
+ ((= (char-after (match-beginning 0)) ?\( )
+ (setq nest (cons (point) nest))
+ (setq depth (1+ depth)))
+ (t
+ (setq nest (cdr nest))
+ (setq depth (1- depth)))))
+ (if (> depth orig) (setq in-paren ?\())))
+ ((string= "[" w) ;skip to matching paren
+ (let ((orig depth))
+ (setq nest (cons (point) nest))
+ (setq depth (1+ depth))
+ (while (and (/= depth orig)
+ (re-search-forward "\\[\\|\\]" indent-point t))
+ (cond
+ ((= (char-after (match-beginning 0)) ?\[ )
+ (setq nest (cons (point) nest))
+ (setq depth (1+ depth)))
+ (t
+ (setq nest (cdr nest))
+ (setq depth (1- depth)))))
+ (if (> depth orig) (setq in-paren ?\[))))
+ ((string= "{" w) ;skip to matching paren
+ (let ((orig depth))
+ (setq nest (cons (point) nest))
+ (setq depth (1+ depth))
+ (while (and (/= depth orig)
+ (re-search-forward "[{}]" indent-point t))
+ (cond
+ ((= (char-after (match-beginning 0)) ?{ )
+ (setq nest (cons (point) nest))
+ (setq depth (1+ depth)))
+ (t
+ (setq nest (cdr nest))
+ (setq depth (1- depth)))))
+ (if (> depth orig) (setq in-paren ?{))))
+ ((string-match ruby-block-end-re w)
+ (setq nest (cdr nest))
+ (setq depth (1- depth)))
+ ((string-match ruby-block-beg-re w)
+ (let (c)
+ (save-excursion
+ (goto-char pnt)
+ (skip-chars-backward " \t")
+ (setq c (char-after (1- (point)))))
+ (if (or (null c) (= c ?\n) (= c ?\;))
+ (progn
+ (setq nest (cons (point) nest))
+ (setq depth (1+ depth))))))
+ (t
+ (error (format "bad string %s" w)))))))
+ (list in-string in-paren (car nest) depth)))
+
(defun ruby-calculate-indent (&optional parse-start)
(save-excursion
(beginning-of-line)
diff --git a/sample/uumerge.rb b/sample/uumerge.rb
index d0bd016036..ac6e1c6849 100755
--- a/sample/uumerge.rb
+++ b/sample/uumerge.rb
@@ -1,5 +1,10 @@
#!/usr/local/bin/ruby
+if $ARGV[0] == "-c"
+ out_stdout = 1;
+ $ARGV.shift
+end
+
while gets()
if /^begin\s*(\d*)\s*(\S*)/
$mode, $file = $1, $2
@@ -8,8 +13,13 @@ while gets()
end
end
-fail "missing begin" if !$sawbegin;
-OUT = open($file, "w") if $file != "";
+fail "missing begin" if ! $sawbegin;
+
+if out_stdout
+ out = STDOUT
+else
+ out = open($file, "w") if $file != "";
+end
while gets()
if /^end/
@@ -19,9 +29,9 @@ while gets()
sub(/[a-z]+$/, ""); # handle stupid trailing lowercase letters
continue if /[a-z]/
continue if !(((($_[0] - 32) & 077) + 2) / 3 == $_.length / 4)
- OUT << $_.unpack("u");
+ out << $_.unpack("u");
end
-fail "missing end" if ! $sawend;
-File.chmod $mode.oct, $file;
+fail "missing end" if !$sawend;
+File.chmod $mode.oct, $file if ! out_stdout
exit 0;
diff --git a/spec b/spec
index cf7e3807c9..a067075b67 100644
--- a/spec
+++ b/spec
@@ -68,13 +68,13 @@ tab), CR(carriage return),改頁(form feed)である.改行(newline)は明ら
予約語は以下の通りである
- alias def if resque when
- and else in retry while
- begin elsif include return yield
- break end module self __END__
- case ensure nil super __FILE__
- class fail or then __LINE__
- continue for redo undef
+ alias def if retry while
+ and else in return yield
+ begin elsif module self __END__
+ break end nil super __FILE__
+ case ensure or then __LINE__
+ class fail redo undef
+ continue for resque when
予約語はクラス名,メソッド名,変数名などに用いることはできない.
@@ -120,9 +120,7 @@ Rubyではnilが偽,それ以外が真と評価される.CやPerlなどとは異なり,0や
\# 文字`#'そのもの
\nnn 8進数表記(nは0-7)
\xnn 16進数表記(nは0-9,a-f)
- \^c コントロール文字(cはASCII文字)
- \C-c コントロール文字(同上)
- \M-c メタ文字(c|0x80)
+ \cx コントロール文字(xはASCII文字)
\x 文字xそのもの
また,`#'による変数展開も行われる.一方,シングルクォート(`'')で括られ
@@ -166,17 +164,6 @@ Rubyではshのようにコマンドの実行結果を文字列リテラルのように使うことが
その他に文字列と同じバックスラッシュ記法や変数展開も有効である.
-** ワイルドカード式
-
- <...>
-
- * 任意の文字列(空文字列を含む)と一致
- ? 任意の1文字と一致
- [ ] []内のいずれか1文字と一致
- {..} {}内の(コンマで区切られた)いずれかの文字列と一致
-
-その他に文字列と同じバックスラッシュ記法や変数展開も有効である.
-
** 変数展開
ダブルクォート(`"')で囲まれた文字列式,コマンド文字列,正規表現,およ
@@ -363,9 +350,10 @@ Rubyの変数はスコープ(有効範囲)と寿命(有効期限)によって4種類に分類され,
でも小文字でも構わない.変数名とは識別子の名前空間が違うので重複しても
構わない.
-クラス定義文の外で指定されたメソッドとクラスModuleのunexportメソッドで
-指定されたメソッドは関数的メソッドと呼ばれ,関数形式でしか呼び出すこと
-ができない(DEF参照).
+クラスModuleで定義されているメソッド(public,protected,private)でメソッ
+ドの呼び出し方を制御することが出来る.protectedまたは privateで指定さ
+れた制限されたメソッドは関数形式でしか呼び出すことが出来ず,さらに
+privateメソッドは同じクラスで定義されたメソッドからしか呼び出せない.
** SUPER
@@ -805,17 +793,18 @@ begin式のresque節で使い,begin式を始めから実行する.例外処理を行なって
で指定する.仮引数並びの最後に`*'がある場合,仮引数より多く与えられた
実引数は,最後の引数に配列として与えられる(足りない時にはエラー).
-メソッドには関数的メソッドと通常メソッドがある.関数的メソッドは関数形
-式でしか呼び出すことができず,よって該当するクラスとそのサブクラスのメ
-ソッドからしか呼び出すことができない.
-新規にメソッドを定義する場合,クラス定義式の外にあるdef式は関数的メソッ
-ドを定義し,クラス定義式の中にあるdef式は通常のメソッドを定義する.スー
-パークラスのメソッドを再定義する場合には定義されるメソッドの可視性はスー
-パークラスのメソッドのものを受け継ぐ.
+メソッドには呼び出し制限を加えることが出来,制限を加えられたメソッドは,
+関数形式でしか呼び出せない(protected),あるいは関数形式でしかも同じク
+ラスのメソッドからしか呼べない(private).
+
+新規にメソッドを定義する場合,クラス定義式の外にあるdef式はデフォルト
+ではprotectedメソッドを定義し,クラス定義式の中にあるdef式はpublicメソッ
+ドを定義する.スーパークラスのメソッドを再定義する場合には定義されるメ
+ソッドの可視性はスーパークラスのメソッドのものを受け継ぐ.
-メソッドの可視性を変更する場合にはModuleクラスのexport/unexportメソッ
-ドを用いる.
+メソッドの可視性を変更する場合にはModuleクラスで定義されているpublic,
+protected, privateの各メソッドを用いる.
** 特異メソッド定義
@@ -835,19 +824,6 @@ begin式のresque節で使い,begin式を始めから実行する.例外処理を行なって
サブクラスにも継承される.言い替えればクラスの特異メソッドは他のオブジェ
クト指向システムにおけるクラスメソッドの働きをする.
-** INCLUDE
-
-モジュールをインクルードすることによって,クラスまたはモジュールに機能
-を追加できる.現在の定義中のクラスまたはモジュール(トップレベルでは
-Objectクラス)に指定したモジュールをインクルードする構式は以下の通りで
-ある.
-
- include モジュール名 [`,' モジュール名..]
-
-モジュールをインクルードすると,そのモジュール(およびそのモジュールが
-更にインクルードしているモジュール)の全てのメソッドを受け継ぐ.別のい
-い方をすればインクルードは限定された多重継承(Mixin)といえる.
-
** ALIAS
以下の形式でメソッドに別名をつけることができる.
@@ -1204,6 +1180,9 @@ Rubyには厳密な意味では関数はないがKernelクラスの関数メソッドは(全ての
ると対応する環境変数の値が得られる.環境変数が存在しな
い場合はnilが返る.
+ KCODE 対応している漢字コードを表す文字列."EUC","SJIS"または
+ "NONE".
+
VERSION rubyのバージョンを示す文字列
* 組み込みクラスとモジュール
@@ -1797,6 +1776,18 @@ Methods:
Single Methods:
+ self[pat]
+ glob(pat)
+
+ 文字列patをsh形式のワイルドカードとして展開した結果を文字列の
+ 配列として返す.書式は以下の通りである.
+
+ * 任意の文字列(空文字列を含む)と一致
+ ? 任意の1文字と一致
+ [ ] []内のいずれか1文字と一致
+ {..} {}内の(コンマで区切られた)いずれかの文字列と
+ 一致
+
chdir(path)
カレントディレクトリをpathに変更する.
@@ -2664,20 +2655,32 @@ Private Methods:
Methods:
- export(name[, name..])
+ include(module[, module..])
- nameで指定されたメソッドを通常形式で呼び出し可能にする.すでに
- 通常メソッドである場合には何もしない.
+ 引数で指定したモジュールをインクルードして,メソッド,定数を追
+ 加する.クラス,モジュールに別のモジュールをインクルードするこ
+ とによって,限定された多重継承(Mixin)を実現できる.
to_s
モジュールの文字列表現を返す.モジュールの場合の文字列表現はモ
ジュール名である.
- unexport(name[, name..])
+ private(name[, name..])
+
+ nameで指定されたメソッドを同じクラスで定義されたメソッドからだ
+ け,関数形式でだけ呼び出し可能にする.すでにprivateメソッドで
+ ある場合には何もしない.
+
+ protected(name[, name..])
nameで指定されたメソッドを関数形式でだけ呼び出し可能にする.す
- でに関数メソッドである場合には何もしない.
+ でにprotectedメソッドである場合には何もしない.
+
+ public(name[, name..])
+
+ nameで指定されたメソッドを通常形式で呼び出し可能にする.すでに
+ publicメソッドである場合には何もしない.
** Nil(クラス)
@@ -2741,8 +2744,15 @@ SuperClass: Builtin
Methods:
+ extened(module[, module..])
+
+ 引数で指定したモジュールをselfにインクルードする.モジュールで
+ 定義されているメソッドが特異メソッドとして追加される.
+
init_object
+ オブジェクトの生成時に呼び出される.デフォルトの定義は何もしな
+ い.サブクラスで必要に応じて再定義されることが期待されている.
is_member_of(class)
@@ -2955,7 +2965,6 @@ Single Methods:
ソケットのペアを返す.引数の指定は openと同じである.
-
** Regexp(クラス)
正規表現のクラス.正規表現のリテラルは/.../という形式で表すが,動的に
@@ -3733,9 +3742,8 @@ PRIMARY : `(' EXPR `)'
| super `(' [CALL_ARGS] `)'
| super
| PRIMARY `[' [ARGS] `]'
- | `[' [ARGS] `]'
- | `{' ARGS `}'
- | `{' ASSOCS `}'
+ | `[' [ARGS [`,']] `]'
+ | `{' [ (ARGS|ASSOCS) [`,'] ] `}'
| redo
| break
| continue
diff --git a/string.c b/string.c
index a107a7f8b7..73c1678974 100644
--- a/string.c
+++ b/string.c
@@ -360,8 +360,6 @@ Fstr_cmp(str1, str2)
VALUE Freg_match();
-extern VALUE C_Glob;
-
static VALUE
Fstr_match(x, y)
struct RString *x, *y;
@@ -382,9 +380,6 @@ Fstr_match(x, y)
return INT2FIX(start);
default:
- if (obj_is_kind_of(y, C_Glob)) {
- return Fglob_match(y, x);
- }
Fail("type mismatch");
break;
}
@@ -684,8 +679,8 @@ str_sub(str, pat, val, once)
for (offset=0, n=0;
(beg=research(pat, str, offset)) >= 0;
- offset=RREGEXP(pat)->ptr->regs.start[0]+STRLEN(val)) {
- end = RREGEXP(pat)->ptr->regs.end[0]-1;
+ offset=BEG(0)+STRLEN(val)) {
+ end = END(0)-1;
sub = re_regsub(val);
str_replace2(str, beg, end, sub);
n++;
@@ -1339,11 +1334,8 @@ Fstr_split(argc, argv, str)
int last_null = 0;
int idx;
-#define LMATCH spat->ptr->regs.start
-#define RMATCH spat->ptr->regs.end
-
while ((end = research(spat, str, start)) >= 0) {
- if (start == end && LMATCH[0] == RMATCH[0]) {
+ if (start == end && BEG(0) == END(0)) {
if (last_null == 1) {
if (ismbchar(str->ptr[beg]))
ary_push(result, str_substr(str, beg, 2));
@@ -1360,17 +1352,17 @@ Fstr_split(argc, argv, str)
}
else {
ary_push(result, str_substr(str, beg, end-beg));
- beg = start = RMATCH[0];
+ beg = start = END(0);
if (limit && lim <= ++i) break;
}
last_null = 0;
for (idx=1; idx < 10; idx++) {
- if (LMATCH[idx] == -1) break;
- if (LMATCH[idx] == RMATCH[idx])
+ if (BEG(idx) == -1) break;
+ if (BEG(idx) == END(idx))
tmp = str_new(0, 0);
else
- tmp = str_subseq(str, LMATCH[idx], RMATCH[idx]-1);
+ tmp = str_subseq(str, BEG(idx), END(idx)-1);
ary_push(result, tmp);
if (limit && lim <= ++i) break;
}
@@ -1380,9 +1372,6 @@ Fstr_split(argc, argv, str)
if (str->len > beg) {
ary_push(result, str_subseq(str, beg, -1));
}
- else if (str->len == beg) {
- ary_push(result, str_new(0, 0));
- }
return result;
}
diff --git a/util.c b/util.c
new file mode 100644
index 0000000000..62e34f5753
--- /dev/null
+++ b/util.c
@@ -0,0 +1,53 @@
+/************************************************
+
+ util.c -
+
+ $Author$
+ $Revision$
+ $Date$
+ created at: Fri Mar 10 17:22:34 JST 1995
+
+************************************************/
+
+#include "defines.h"
+#include "config.h"
+#include "util.h"
+
+unsigned long
+scan_oct(start, len, retlen)
+char *start;
+int len;
+int *retlen;
+{
+ register char *s = start;
+ register unsigned long retval = 0;
+
+ while (len-- && *s >= '0' && *s <= '7') {
+ retval <<= 3;
+ retval |= *s++ - '0';
+ }
+ *retlen = s - start;
+ return retval;
+}
+
+extern char *strchr();
+
+unsigned long
+scan_hex(start, len, retlen)
+char *start;
+int len;
+int *retlen;
+{
+ static char hexdigit[] = "0123456789abcdef0123456789ABCDEFx";
+ register char *s = start;
+ register unsigned long retval = 0;
+ char *tmp;
+
+ while (len-- && *s && (tmp = strchr(hexdigit, *s))) {
+ retval <<= 4;
+ retval |= (tmp - hexdigit) & 15;
+ s++;
+ }
+ *retlen = s - start;
+ return retval;
+}
diff --git a/util.h b/util.h
new file mode 100644
index 0000000000..e2ada4176b
--- /dev/null
+++ b/util.h
@@ -0,0 +1,16 @@
+/************************************************
+
+ util.h -
+
+ $Author$
+ $Date$
+ created at: Thu Mar 9 11:55:53 JST 1995
+
+************************************************/
+#ifndef UTIL_H
+#define UTIL_H
+
+unsigned long scan_hex();
+unsigned long scan_oct();
+
+#endif /* UTIL_H */
diff --git a/variable.c b/variable.c
index b65a1fc05e..34bd8f4de5 100644
--- a/variable.c
+++ b/variable.c
@@ -203,17 +203,6 @@ rb_readonly_hook(val, id)
}
VALUE
-rb_id2class(id)
- ID id;
-{
- VALUE class;
-
- if (st_lookup(class_tbl, id, &class))
- return class;
- return Qnil;
-}
-
-VALUE
rb_gvar_get(entry)
struct global_entry *entry;
{
diff --git a/version.h b/version.h
index 4ef6289513..231f54afb1 100644
--- a/version.h
+++ b/version.h
@@ -1,2 +1,2 @@
-#define RUBY_VERSION "0.68"
-#define VERSION_DATE "95/02/23"
+#define RUBY_VERSION "0.69"
+#define VERSION_DATE "95/03/15"