diff options
| author | Yukihiro Matsumoto <matz@ruby-lang.org> | 1995-03-15 14:59:18 +0900 |
|---|---|---|
| committer | Takashi Kokubun <takashikkbn@gmail.com> | 2019-08-17 22:09:31 +0900 |
| commit | d349889e770a2078c247d9d28070e86a54b856f4 (patch) | |
| tree | 8bdbf87f3ff78ef237c4ff8efa061fbb8dc5a226 | |
| parent | 881c5a9c320c637ee0f6526b40cf70c1379ab656 (diff) | |
version 0.69v0_69
https://cache.ruby-lang.org/pub/ruby/1.0/ruby-0.69.tar.gz
Wed Mar 15 14:59:18 1995 Yukihiro Matsumoto (matz@ix-02)
* version 0.69
* eval.c(method_missing): unknownから名称変更.
* eval.c(single_method_added): 特異メソッドが定義された時に呼ばれ
るメソッド.hookとして使える.実際に定義される直前に呼ばれる.
Tue Mar 14 14:46:44 1995 Yukihiro Matsumoto (matz@ix-02)
* ruby.c(proc_options): 引数の解析を自分でやることにより引数指定の
方法がperlに近付いた.getopt_longはもう使わない.
* dir.c(glob): `{}'のネストを許すようにした.
Mon Mar 13 17:56:25 1995 Yukihiro Matsumoto (matz@ix-02)
* glob.c: Glob(ワイルドカードオブジェクト)はなくなった.ワイルドカー
ドの展開はDir.glob(文字列)を使う.ワイルドカードのマッチは正規表
現で代用.
Fri Mar 10 18:35:46 1995 Yukihiro Matsumoto (matz@ix-02)
* eval.c: Mathのようなモジュールは自分自身でextendする.
* eval.c: クラスやモジュールを定義した既に同名のものがあれば追加定
義となるように.ただし.superクラスの違いなどはチェックする.
* regex.c: debug.
* math.c: 定数PIとEを定義.
Thu Mar 9 21:35:12 1995 Yukihiro Matsumoto (matz@ix-02)
* regex.c: EUC,SJISモードでは0x80以上の8進,16進リテラルを禁止.
* regex.c: クラス内でも数値リテラル・文字クラスが使えるようした.
Wed Mar 8 17:39:05 1995 Yukihiro Matsumoto (matz@ix-02)
* regex.c: \200など括弧の数以上の表現は8進リテラルと解釈する.ただ
し,\1から\9までは例外.
* regex.c: \9以上のリファレンスも有効にした.
Tue Mar 7 14:26:01 1995 Yukihiro Matsumoto (matz@ix-02)
* eval.c(public/private): スコープ制御メソッドの名称変更.静的なア
クセスも出来るようにしてみたが,不採用.
Mon Mar 6 19:34:32 1995 Yukihiro Matsumoto (matz@ix-02)
* eval.c(inlcude): メソッド化.動的にモジュールをインクルードでき
るように.さらに任意のオブジェクトにもモジュールをインクルードで
きるメソッド `extend'も用意した.
* parse.y: 文法からincludeを削除.メソッド化.
Tue Feb 28 15:35:10 1995 Yukihiro Matsumoto (matz@ix-02)
* parse.y: 配列,連想配列の最後に`,'をおけるように.
| -rw-r--r-- | ChangeLog | 63 | ||||
| -rw-r--r-- | MANIFEST | 6 | ||||
| -rw-r--r-- | Makefile.in | 24 | ||||
| -rw-r--r-- | class.c | 6 | ||||
| -rw-r--r-- | dict.c | 3 | ||||
| -rw-r--r-- | dir.c | 105 | ||||
| -rw-r--r-- | env.h | 3 | ||||
| -rw-r--r-- | error.c | 9 | ||||
| -rw-r--r-- | etc.c | 15 | ||||
| -rw-r--r-- | eval.c | 167 | ||||
| -rw-r--r-- | file.c | 56 | ||||
| -rw-r--r-- | getopt.c | 660 | ||||
| -rw-r--r-- | getopt.h | 128 | ||||
| -rw-r--r-- | getopt1.c | 162 | ||||
| -rw-r--r-- | glob.c | 678 | ||||
| -rw-r--r-- | gnuglob.c | 580 | ||||
| -rw-r--r-- | ident.h | 11 | ||||
| -rw-r--r-- | inits.c | 1 | ||||
| -rw-r--r-- | io.c | 3 | ||||
| -rw-r--r-- | math.c | 24 | ||||
| -rw-r--r-- | node.h | 9 | ||||
| -rw-r--r-- | object.c | 26 | ||||
| -rw-r--r-- | parse.y | 290 | ||||
| -rw-r--r-- | process.c | 29 | ||||
| -rw-r--r-- | re.c | 163 | ||||
| -rw-r--r-- | re.h | 17 | ||||
| -rw-r--r-- | regex.c | 1329 | ||||
| -rw-r--r-- | regex.h | 52 | ||||
| -rw-r--r-- | ruby.1 | 49 | ||||
| -rw-r--r-- | ruby.c | 195 | ||||
| -rw-r--r-- | ruby.h | 2 | ||||
| -rw-r--r-- | sample/Artistic | 0 | ||||
| -rw-r--r-- | sample/evaldef.rb | 4 | ||||
| -rw-r--r-- | sample/export.rb | 32 | ||||
| -rw-r--r-- | sample/exyacc.rb | 2 | ||||
| -rw-r--r-- | sample/from.rb | 4 | ||||
| -rw-r--r-- | sample/opt_x.rb | 0 | ||||
| -rw-r--r-- | sample/ruby-mode.el | 120 | ||||
| -rwxr-xr-x | sample/uumerge.rb | 20 | ||||
| -rw-r--r-- | spec | 118 | ||||
| -rw-r--r-- | string.c | 25 | ||||
| -rw-r--r-- | util.c | 53 | ||||
| -rw-r--r-- | util.h | 16 | ||||
| -rw-r--r-- | variable.c | 11 | ||||
| -rw-r--r-- | version.h | 4 |
45 files changed, 2081 insertions, 3193 deletions
@@ -1,3 +1,66 @@ +Wed Mar 15 14:59:18 1995 Yukihiro Matsumoto (matz@ix-02) + + * version 0.69 + + * eval.c(method_missing): unknown̾ѹ + + * eval.c(single_method_added): ðۥåɤ줿˸ƤФ + åɡhookȤƻȤ롥ºݤľ˸ƤФ롥 + +Tue Mar 14 14:46:44 1995 Yukihiro Matsumoto (matz@ix-02) + + * ruby.c(proc_options): βϤʬǤ뤳Ȥˤ + ˡperl˶դgetopt_longϤ⤦Ȥʤ + + * dir.c(glob): `{}'ΥͥȤ褦ˤ + +Mon Mar 13 17:56:25 1995 Yukihiro Matsumoto (matz@ix-02) + + * glob.c: Glob(磻ɥɥ֥)Ϥʤʤä磻ɥ + ɤŸDir.glob(ʸ)Ȥ磻ɥɤΥޥåɽ + ѡ + +Fri Mar 10 18:35:46 1995 Yukihiro Matsumoto (matz@ix-02) + + * eval.c: MathΤ褦ʥ⥸塼ϼʬȤextend롥 + + * eval.c: 饹⥸塼Ʊ̾ΤΤɲ + Ȥʤ褦ˡsuper饹ΰ㤤ʤɤϥå롥 + + * regex.c: debug. + + * math.c: PIE + +Thu Mar 9 21:35:12 1995 Yukihiro Matsumoto (matz@ix-02) + + * regex.c: EUC,SJIS⡼ɤǤ0x80ʾ8ʡ16ʥƥػߡ + + * regex.c: 饹Ǥͥƥ롦ʸ饹Ȥ褦 + +Wed Mar 8 17:39:05 1995 Yukihiro Matsumoto (matz@ix-02) + + * regex.c: \200ʤɳ̤οʾɽ8ʥƥȲ᤹롥 + \1\9ޤǤ㳰 + + * regex.c: \9ʾΥեͭˤ + +Tue Mar 7 14:26:01 1995 Yukihiro Matsumoto (matz@ix-02) + + * eval.c(public/private): åɤ̾ѹŪʥ + 褦ˤƤߤԺѡ + +Mon Mar 6 19:34:32 1995 Yukihiro Matsumoto (matz@ix-02) + + * eval.c(inlcude): åɲưŪ˥⥸塼롼ɤǤ + 褦ˡǤդΥ֥Ȥˤ⥸塼롼ɤ + å `extend'Ѱդ + + * parse.y: ʸˡincludeåɲ + +Tue Feb 28 15:35:10 1995 Yukihiro Matsumoto (matz@ix-02) + + * parse.y: ϢκǸ`,'褦ˡ + Fri Feb 24 13:15:43 1995 Yukihiro Matsumoto (matz@ix-02) * version 0.68 @@ -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 @@ -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 @@ -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); @@ -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); } @@ -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 */ @@ -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"); } @@ -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); } @@ -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() @@ -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 */ @@ -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. */ @@ -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 @@ -28,7 +28,6 @@ rb_call_inits() Init_Struct(); Init_String(); Init_Regexp(); - Init_Glob(); Init_pack(); Init_Cons(); Init_Range(); @@ -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); @@ -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); } @@ -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) @@ -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 |