mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* eval.c (rb_f_require): searches ".rb" and ".so" at the same
time. previous behavior (search ".rb", then ".so") has a security risk (ruby-bugs#PR140). * array.c (rb_ary_to_ary): new function to replace internal rb_Array(), which never calls to_a, but to_ary (rb_Array() might call both). [new] * regex.c (PUSH_FAILURE_POINT): push option status again. * regex.c (re_compile_pattern): avoid pushing unnecessary option_set. * eval.c (rb_load): tainted string is OK if wrapped *and* $SAFE >= 4. * eval.c (rb_thread_start_0): should not nail down higher blocks before preserving original context (i.e. should not alter original context). * eval.c (proc_yield): new method equivalent to Proc#call but no check for number of arguments. [new] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1526 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
6aa71d4c80
commit
9d51cf8a6a
10 changed files with 253 additions and 108 deletions
33
ChangeLog
33
ChangeLog
|
@ -1,9 +1,42 @@
|
|||
Mon Jun 18 17:38:50 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* eval.c (rb_f_require): searches ".rb" and ".so" at the same
|
||||
time. previous behavior (search ".rb", then ".so") has a
|
||||
security risk (ruby-bugs#PR140).
|
||||
|
||||
* array.c (rb_ary_to_ary): new function to replace internal
|
||||
rb_Array(), which never calls to_a, but to_ary (rb_Array() might
|
||||
call both). [new]
|
||||
|
||||
Mon Jun 18 00:43:20 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* regex.c (PUSH_FAILURE_POINT): push option status again.
|
||||
|
||||
* regex.c (re_compile_pattern): avoid pushing unnecessary
|
||||
option_set.
|
||||
|
||||
Sat Jun 16 10:58:48 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* eval.c (rb_load): tainted string is OK if wrapped *and*
|
||||
$SAFE >= 4.
|
||||
|
||||
Thu Jun 14 16:27:07 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* eval.c (rb_thread_start_0): should not nail down higher blocks
|
||||
before preserving original context (i.e. should not alter
|
||||
original context).
|
||||
|
||||
Wed Jun 13 19:34:59 2001 Akinori MUSHA <knu@iDaemons.org>
|
||||
|
||||
* dir.c (Init_Dir): add a new method File::fnmatch? along with
|
||||
File::Constants::FNM_*. While I am here, FNM_NOCASE is renamed
|
||||
to FNM_CASEFOLD which is commonly used by *BSD and GNU libc.
|
||||
|
||||
Wed Jun 13 09:33:45 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* eval.c (proc_yield): new method equivalent to Proc#call but no
|
||||
check for number of arguments. [new]
|
||||
|
||||
Tue Jun 12 14:21:28 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
|
||||
|
||||
* lib/mkmf.rb: target_prefix is only for installation, not for
|
||||
|
|
1
ToDo
1
ToDo
|
@ -83,6 +83,7 @@ Standard Libraries
|
|||
* hash etc. should handle self referenceing array/hash
|
||||
* move NameError under StandardError.
|
||||
* library to load per-user profile seeking .ruby_profile or ruby.ini file.
|
||||
* warning framework
|
||||
|
||||
Extension Libraries
|
||||
|
||||
|
|
17
array.c
17
array.c
|
@ -17,6 +17,7 @@
|
|||
#include "st.h"
|
||||
|
||||
VALUE rb_cArray;
|
||||
static ID cmp;
|
||||
|
||||
#define ARY_DEFAULT_SIZE 16
|
||||
|
||||
|
@ -729,6 +730,20 @@ to_ary(ary)
|
|||
return rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_ary_to_ary(obj)
|
||||
VALUE obj;
|
||||
{
|
||||
if (NIL_P(obj)) return rb_ary_new2(0);
|
||||
if (TYPE(obj) == T_ARRAY) {
|
||||
return obj;
|
||||
}
|
||||
if (rb_respond_to(obj, rb_intern("to_ary"))) {
|
||||
return rb_convert_type(obj, T_ARRAY, "Array", "to_ary");
|
||||
}
|
||||
return rb_ary_new3(1, obj);
|
||||
}
|
||||
|
||||
extern VALUE rb_output_fs;
|
||||
|
||||
static VALUE
|
||||
|
@ -958,8 +973,6 @@ rb_ary_reverse_m(ary)
|
|||
return rb_ary_reverse(rb_obj_dup(ary));
|
||||
}
|
||||
|
||||
static ID cmp;
|
||||
|
||||
static int
|
||||
sort_1(a, b)
|
||||
VALUE *a, *b;
|
||||
|
|
111
eval.c
111
eval.c
|
@ -1676,7 +1676,7 @@ copy_node_scope(node, rval)
|
|||
char *file = ruby_sourcefile;\
|
||||
int line = ruby_sourceline;\
|
||||
if (TYPE(args) != T_ARRAY)\
|
||||
args = rb_Array(args);\
|
||||
args = rb_ary_to_ary(args);\
|
||||
argc = RARRAY(args)->len;\
|
||||
argv = ALLOCA_N(VALUE, argc);\
|
||||
MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);\
|
||||
|
@ -2129,7 +2129,7 @@ rb_eval(self, n)
|
|||
VALUE v = rb_eval(self, tag->nd_head->nd_head);
|
||||
int i;
|
||||
|
||||
if (TYPE(v) != T_ARRAY) v = rb_Array(v);
|
||||
if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v);
|
||||
for (i=0; i<RARRAY(v)->len; i++) {
|
||||
if (RTEST(RARRAY(v)->ptr[i])) {
|
||||
node = node->nd_body;
|
||||
|
@ -2174,7 +2174,7 @@ rb_eval(self, n)
|
|||
VALUE v = rb_eval(self, tag->nd_head->nd_head);
|
||||
int i;
|
||||
|
||||
if (TYPE(v) != T_ARRAY) v = rb_Array(v);
|
||||
if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v);
|
||||
for (i=0; i<RARRAY(v)->len; i++) {
|
||||
if (RTEST(rb_funcall2(RARRAY(v)->ptr[i], eqq, 1, &val))){
|
||||
node = node->nd_body;
|
||||
|
@ -2347,14 +2347,14 @@ rb_eval(self, n)
|
|||
case NODE_RESTARY:
|
||||
result = rb_eval(self, node->nd_head);
|
||||
if (TYPE(result) != T_ARRAY) {
|
||||
result = rb_Array(result);
|
||||
result = rb_ary_to_ary(result);
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_REXPAND:
|
||||
result = rb_eval(self, node->nd_head);
|
||||
if (TYPE(result) != T_ARRAY) {
|
||||
result = rb_Array(result);
|
||||
result = rb_ary_to_ary(result);
|
||||
}
|
||||
if (RARRAY(result)->len == 0) {
|
||||
result = Qnil;
|
||||
|
@ -2520,7 +2520,7 @@ rb_eval(self, n)
|
|||
|
||||
case NODE_ARGSCAT:
|
||||
result = rb_ary_concat(rb_eval(self, node->nd_head),
|
||||
rb_Array(rb_eval(self, node->nd_body)));
|
||||
rb_ary_to_ary(rb_eval(self, node->nd_body)));
|
||||
break;
|
||||
|
||||
case NODE_ARGSPUSH:
|
||||
|
@ -3546,16 +3546,20 @@ rb_f_block_given_p()
|
|||
return Qfalse;
|
||||
}
|
||||
|
||||
#define PC_NONE 0x0
|
||||
#define PC_ACHECK 0x1
|
||||
#define PC_PCALL 0x2
|
||||
|
||||
static VALUE
|
||||
rb_yield_0(val, self, klass, acheck)
|
||||
rb_yield_0(val, self, klass, pcall)
|
||||
VALUE val, self, klass; /* OK */
|
||||
int acheck;
|
||||
int pcall;
|
||||
{
|
||||
NODE *node;
|
||||
volatile VALUE result = Qnil;
|
||||
volatile VALUE old_cref;
|
||||
struct BLOCK *block;
|
||||
struct SCOPE *old_scope;
|
||||
struct BLOCK * volatile block;
|
||||
struct SCOPE * volatile old_scope;
|
||||
struct FRAME frame;
|
||||
int state;
|
||||
static unsigned serial = 1;
|
||||
|
@ -3591,7 +3595,7 @@ rb_yield_0(val, self, klass, acheck)
|
|||
PUSH_TAG(PROT_NONE);
|
||||
if ((state = EXEC_TAG()) == 0) {
|
||||
if (block->var == (NODE*)1) {
|
||||
if (acheck && val != Qundef &&
|
||||
if ((pcall&PC_ACHECK) && val != Qundef &&
|
||||
TYPE(val) == T_ARRAY && RARRAY(val)->len != 0) {
|
||||
rb_raise(rb_eArgError, "wrong # of arguments (%d for 0)",
|
||||
RARRAY(val)->len);
|
||||
|
@ -3605,14 +3609,14 @@ rb_yield_0(val, self, klass, acheck)
|
|||
}
|
||||
else {
|
||||
if (nd_type(block->var) == NODE_MASGN)
|
||||
massign(self, block->var, val, acheck);
|
||||
massign(self, block->var, val, (pcall&PC_ACHECK));
|
||||
else {
|
||||
/* argument adjust for proc_call etc. */
|
||||
if (acheck && val != Qundef &&
|
||||
if (pcall && val != Qundef &&
|
||||
TYPE(val) == T_ARRAY && RARRAY(val)->len == 1) {
|
||||
val = RARRAY(val)->ptr[0];
|
||||
}
|
||||
assign(self, block->var, val, acheck);
|
||||
assign(self, block->var, val, (pcall&PC_ACHECK));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3621,7 +3625,7 @@ rb_yield_0(val, self, klass, acheck)
|
|||
}
|
||||
else {
|
||||
/* argument adjust for proc_call etc. */
|
||||
if (acheck && val != Qundef &&
|
||||
if (pcall && val != Qundef &&
|
||||
TYPE(val) == T_ARRAY && RARRAY(val)->len == 1) {
|
||||
val = RARRAY(val)->ptr[0];
|
||||
}
|
||||
|
@ -5171,7 +5175,12 @@ rb_load(fname, wrap)
|
|||
NODE *saved_cref = ruby_cref;
|
||||
TMP_PROTECT;
|
||||
|
||||
SafeStringValue(fname);
|
||||
if (wrap && ruby_safe_level >= 4) {
|
||||
StringValue(fname);
|
||||
}
|
||||
else {
|
||||
SafeStringValue(fname);
|
||||
}
|
||||
file = rb_find_file(RSTRING(fname)->ptr);
|
||||
if (!file) {
|
||||
rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING(fname)->ptr);
|
||||
|
@ -5402,28 +5411,20 @@ rb_f_require(obj, fname)
|
|||
}
|
||||
buf = ALLOCA_N(char, strlen(RSTRING(fname)->ptr) + 5);
|
||||
strcpy(buf, RSTRING(fname)->ptr);
|
||||
strcat(buf, ".rb");
|
||||
if (rb_find_file(buf)) {
|
||||
switch (rb_find_file_noext(buf)) {
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 1:
|
||||
fname = rb_str_new2(buf);
|
||||
feature = buf;
|
||||
file = feature = buf;
|
||||
goto load_rb;
|
||||
}
|
||||
strcpy(buf, RSTRING(fname)->ptr);
|
||||
strcat(buf, DLEXT);
|
||||
file = rb_find_file(buf);
|
||||
if (file) {
|
||||
|
||||
default:
|
||||
feature = buf;
|
||||
file = rb_find_file(buf);
|
||||
goto load_dyna;
|
||||
}
|
||||
#ifdef DLEXT2
|
||||
strcpy(buf, RSTRING(fname)->ptr);
|
||||
strcat(buf, DLEXT2);
|
||||
file = rb_find_file(buf);
|
||||
if (file) {
|
||||
feature = buf;
|
||||
goto load_dyna;
|
||||
}
|
||||
#endif
|
||||
rb_raise(rb_eLoadError, "No such file to load -- %s",
|
||||
RSTRING(fname)->ptr);
|
||||
|
||||
|
@ -6330,8 +6331,9 @@ callargs(args)
|
|||
}
|
||||
|
||||
static VALUE
|
||||
proc_call(proc, args)
|
||||
proc_invoke(proc, args, pcall)
|
||||
VALUE proc, args; /* OK */
|
||||
int pcall;
|
||||
{
|
||||
struct BLOCK * volatile old_block;
|
||||
struct BLOCK _block;
|
||||
|
@ -6341,6 +6343,13 @@ proc_call(proc, args)
|
|||
volatile int orphan;
|
||||
volatile int safe = ruby_safe_level;
|
||||
|
||||
if (pcall) {
|
||||
pcall = PC_ACHECK|PC_PCALL;
|
||||
}
|
||||
else {
|
||||
pcall = PC_PCALL;
|
||||
}
|
||||
|
||||
if (rb_block_given_p() && ruby_frame->last_func) {
|
||||
rb_warning("block for %s#%s is useless",
|
||||
rb_class2name(CLASS_OF(proc)),
|
||||
|
@ -6367,7 +6376,7 @@ proc_call(proc, args)
|
|||
state = EXEC_TAG();
|
||||
if (state == 0) {
|
||||
proc_set_safe_level(proc);
|
||||
result = rb_yield_0(args, 0, 0, Qtrue);
|
||||
result = rb_yield_0(args, 0, 0, pcall);
|
||||
}
|
||||
POP_TAG();
|
||||
|
||||
|
@ -6398,6 +6407,20 @@ proc_call(proc, args)
|
|||
return result;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
proc_call(proc, args)
|
||||
VALUE proc, args; /* OK */
|
||||
{
|
||||
return proc_invoke(proc, args, Qtrue);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
proc_yield(proc, args)
|
||||
VALUE proc, args; /* OK */
|
||||
{
|
||||
return proc_invoke(proc, args, Qfalse);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
proc_arity(proc)
|
||||
VALUE proc;
|
||||
|
@ -6899,6 +6922,7 @@ Init_Proc()
|
|||
rb_define_singleton_method(rb_cProc, "new", proc_s_new, -1);
|
||||
|
||||
rb_define_method(rb_cProc, "call", proc_call, -2);
|
||||
rb_define_method(rb_cProc, "yield", proc_yield, -2);
|
||||
rb_define_method(rb_cProc, "arity", proc_arity, 0);
|
||||
rb_define_method(rb_cProc, "[]", proc_call, -2);
|
||||
rb_define_method(rb_cProc, "==", proc_eq, 1);
|
||||
|
@ -8210,7 +8234,11 @@ rb_thread_start_0(fn, arg, th_arg)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (ruby_block) { /* should nail down higher scopes */
|
||||
if (THREAD_SAVE_CONTEXT(curr_thread)) {
|
||||
return thread;
|
||||
}
|
||||
|
||||
if (ruby_block) { /* should nail down higher blocks */
|
||||
struct BLOCK dummy;
|
||||
|
||||
dummy.prev = ruby_block;
|
||||
|
@ -8219,9 +8247,6 @@ rb_thread_start_0(fn, arg, th_arg)
|
|||
}
|
||||
scope_dup(ruby_scope);
|
||||
FL_SET(ruby_scope, SCOPE_SHARED);
|
||||
if (THREAD_SAVE_CONTEXT(curr_thread)) {
|
||||
return thread;
|
||||
}
|
||||
|
||||
if (!th->next) {
|
||||
/* merge in thread list */
|
||||
|
@ -8243,17 +8268,21 @@ rb_thread_start_0(fn, arg, th_arg)
|
|||
POP_TAG();
|
||||
status = th->status;
|
||||
|
||||
if (th == main_thread) ruby_stop(state);
|
||||
rb_thread_remove(th);
|
||||
|
||||
while (saved_block) {
|
||||
struct BLOCK *tmp = saved_block;
|
||||
|
||||
if (curr_thread == main_thread) {
|
||||
printf("free(%p)\n", saved_block);
|
||||
}
|
||||
if (tmp->frame.argc > 0)
|
||||
free(tmp->frame.argv);
|
||||
saved_block = tmp->prev;
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
if (th == main_thread) ruby_stop(state);
|
||||
rb_thread_remove(th);
|
||||
if (state && status != THREAD_TO_KILL && !NIL_P(ruby_errinfo)) {
|
||||
th->flags |= THREAD_RAISED;
|
||||
if (state == TAG_FATAL) {
|
||||
|
|
110
file.c
110
file.c
|
@ -2202,41 +2202,76 @@ is_macos_native_path(path)
|
|||
}
|
||||
#endif
|
||||
|
||||
static char*
|
||||
file_load_ok(file)
|
||||
char *file;
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
f = fopen(file, "r");
|
||||
if (f == NULL) return 0;
|
||||
fclose(f);
|
||||
return file;
|
||||
}
|
||||
|
||||
extern VALUE rb_load_path;
|
||||
|
||||
int
|
||||
rb_find_file_noext(file)
|
||||
char *file;
|
||||
{
|
||||
char *path, *e, *found;
|
||||
char *fend = file + strlen(file);
|
||||
VALUE fname;
|
||||
int i, j;
|
||||
|
||||
static char *ext[] = {
|
||||
".rb", DLEXT,
|
||||
#ifdef DLEXT2
|
||||
DLEXT2,
|
||||
#endif
|
||||
0
|
||||
};
|
||||
|
||||
if (file[0] == '~') {
|
||||
fname = rb_str_new2(file);
|
||||
fname = rb_file_s_expand_path(1, &fname);
|
||||
file = StringValuePtr(fname);
|
||||
}
|
||||
|
||||
if (is_absolute_path(file)) {
|
||||
for (i=0; ext[i]; i++) {
|
||||
strcpy(fend, ext[i]);
|
||||
if (file_load_ok(file)) return i+1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!rb_load_path) return 0;
|
||||
|
||||
Check_Type(rb_load_path, T_ARRAY);
|
||||
for (i=0;i<RARRAY(rb_load_path)->len;i++) {
|
||||
VALUE str = RARRAY(rb_load_path)->ptr[i];
|
||||
|
||||
SafeStringValue(str);
|
||||
path = RSTRING(str)->ptr;
|
||||
for (j=0; ext[j]; j++) {
|
||||
strcpy(fend, ext[j]);
|
||||
found = dln_find_file(file, path);
|
||||
if (found && file_load_ok(found)) return j+1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char*
|
||||
rb_find_file(file)
|
||||
char *file;
|
||||
{
|
||||
extern VALUE rb_load_path;
|
||||
VALUE vpath, fname;
|
||||
char *path;
|
||||
struct stat st;
|
||||
|
||||
#if defined(__MACOS__) || defined(riscos)
|
||||
if (is_macos_native_path(file)) {
|
||||
FILE *f;
|
||||
|
||||
if (rb_safe_level() >= 2 && !rb_path_check(file)) {
|
||||
rb_raise(rb_eSecurityError, "loading from unsafe file %s", file);
|
||||
}
|
||||
f= fopen(file, "r");
|
||||
if (f == NULL) return 0;
|
||||
fclose(f);
|
||||
return file;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (is_absolute_path(file)) {
|
||||
FILE *f;
|
||||
|
||||
if (rb_safe_level() >= 2 && !rb_path_check(file)) {
|
||||
rb_raise(rb_eSecurityError, "loading from unsafe file %s", file);
|
||||
}
|
||||
f = fopen(file, "r");
|
||||
if (f == NULL) return 0;
|
||||
fclose(f);
|
||||
return file;
|
||||
}
|
||||
|
||||
if (file[0] == '~') {
|
||||
fname = rb_str_new2(file);
|
||||
fname = rb_file_s_expand_path(1, &fname);
|
||||
|
@ -2246,6 +2281,22 @@ rb_find_file(file)
|
|||
file = StringValuePtr(fname);
|
||||
}
|
||||
|
||||
#if defined(__MACOS__) || defined(riscos)
|
||||
if (is_macos_native_path(file)) {
|
||||
if (rb_safe_level() >= 2 && !rb_path_check(file)) {
|
||||
rb_raise(rb_eSecurityError, "loading from unsafe file %s", file);
|
||||
}
|
||||
return file_load_ok(file);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (is_absolute_path(file)) {
|
||||
if (rb_safe_level() >= 2 && !rb_path_check(file)) {
|
||||
rb_raise(rb_eSecurityError, "loading from unsafe file %s", file);
|
||||
}
|
||||
return file_load_ok(file);
|
||||
}
|
||||
|
||||
if (rb_load_path) {
|
||||
int i;
|
||||
|
||||
|
@ -2269,10 +2320,7 @@ rb_find_file(file)
|
|||
}
|
||||
|
||||
path = dln_find_file(file, path);
|
||||
if (path && stat(path, &st) == 0) {
|
||||
return path;
|
||||
}
|
||||
return 0;
|
||||
return file_load_ok(path);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
2
intern.h
2
intern.h
|
@ -27,6 +27,7 @@ VALUE rb_ary_new4 _((long, VALUE *));
|
|||
VALUE rb_ary_freeze _((VALUE));
|
||||
VALUE rb_ary_aref _((int, VALUE*, VALUE));
|
||||
void rb_ary_store _((VALUE, long, VALUE));
|
||||
VALUE rb_ary_to_ary _((VALUE));
|
||||
VALUE rb_ary_to_s _((VALUE));
|
||||
VALUE rb_ary_push _((VALUE, VALUE));
|
||||
VALUE rb_ary_pop _((VALUE));
|
||||
|
@ -179,6 +180,7 @@ void rb_thread_atfork _((void));
|
|||
int eaccess _((const char*, int));
|
||||
VALUE rb_file_s_expand_path _((int, VALUE *));
|
||||
void rb_file_const _((const char*, VALUE));
|
||||
int rb_find_file_noext _((char*));
|
||||
char *rb_find_file _((char*));
|
||||
/* gc.c */
|
||||
void rb_gc_mark_locations _((VALUE*, VALUE*));
|
||||
|
|
6
io.c
6
io.c
|
@ -3462,10 +3462,8 @@ opt_i_set(val)
|
|||
VALUE val;
|
||||
{
|
||||
if (ruby_inplace_mode) free(ruby_inplace_mode);
|
||||
if (!RTEST(val)) {
|
||||
ruby_inplace_mode = 0;
|
||||
return;
|
||||
}
|
||||
ruby_inplace_mode = 0;
|
||||
if (!RTEST(val)) return;
|
||||
StringValue(val);
|
||||
ruby_inplace_mode = strdup(RSTRING(val)->ptr);
|
||||
}
|
||||
|
|
|
@ -854,7 +854,7 @@ class Resolv
|
|||
raise DecodeError.new("limit exceed") if @limit < @index + len
|
||||
arr = @data.unpack("@#{@index}#{template}")
|
||||
@index += len
|
||||
return *arr
|
||||
return arr
|
||||
end
|
||||
|
||||
def get_string
|
||||
|
|
|
@ -660,21 +660,24 @@ An end of a defun is found by moving forward from the beginning of one."
|
|||
|
||||
(cond
|
||||
((featurep 'font-lock)
|
||||
(or (boundp 'font-lock-variable-name-face)
|
||||
(setq font-lock-variable-name-face font-lock-type-face))
|
||||
|
||||
(setq ruby-font-lock-syntactic-keywords
|
||||
'(("\\$\\([#\"'`$\\]\\)" 1 (1 . nil))
|
||||
("\\(#\\)[{$@]" 1 (1 . nil))
|
||||
("\\(/\\)\\([^/\n]\\|\\/\\)*\\(/\\)"
|
||||
(1 (7 . ?'))
|
||||
(3 (7 . ?')))
|
||||
("^\\(=\\)begin\\(\\s \\|$\\)" 1 (7 . nil))
|
||||
("^\\(=\\)end\\(\\s \\|$\\)" 1 (7 . nil))))
|
||||
(put major-mode 'font-lock-defaults
|
||||
'((ruby-font-lock-keywords)
|
||||
nil nil nil
|
||||
beginning-of-line
|
||||
(font-lock-syntactic-keywords
|
||||
. ruby-font-lock-syntactic-keywords)))
|
||||
|
||||
(add-hook 'ruby-mode-hook
|
||||
'(lambda ()
|
||||
(make-local-variable 'font-lock-syntactic-keywords)
|
||||
(setq font-lock-syntactic-keywords
|
||||
'(("\\$\\([#\"'`$\\]\\)" 1 (1 . nil))
|
||||
("\\(#\\)[{$@]" 1 (1 . nil))
|
||||
("\\(/\\)\\([^/\n]\\|\\/\\)*\\(/\\)"
|
||||
(1 (7 . ?'))
|
||||
(3 (7 . ?')))
|
||||
("^\\(=\\)begin\\(\\s \\|$\\)" 1 (7 . nil))
|
||||
("^\\(=\\)end\\(\\s \\|$\\)" 1 (7 . nil))))
|
||||
(make-local-variable 'font-lock-defaults)
|
||||
(setq font-lock-defaults '((ruby-font-lock-keywords) nil nil))
|
||||
(setq font-lock-keywords ruby-font-lock-keywords)))
|
||||
|
||||
(defun ruby-font-lock-docs (limit)
|
||||
(if (re-search-forward "^=begin\\(\\s \\|$\\)" limit t)
|
||||
|
@ -687,6 +690,21 @@ An end of a defun is found by moving forward from the beginning of one."
|
|||
(set-match-data (list beg (point)))
|
||||
t)))))
|
||||
|
||||
(defun ruby-font-lock-maybe-docs (limit)
|
||||
(let (beg)
|
||||
(save-excursion
|
||||
(if (and (re-search-backward "^=\\(begin\\|end\\)\\(\\s \\|$\\)" nil t)
|
||||
(string= (match-string-no-properties 1) "begin"))
|
||||
(progn
|
||||
(beginning-of-line)
|
||||
(setq beg (point)))))
|
||||
(if (and beg (and (re-search-forward "^=\\(begin\\|end\\)\\(\\s \\|$\\)" nil t)
|
||||
(string= (match-string-no-properties 1) "end")))
|
||||
(progn
|
||||
(set-match-data (list beg (point)))
|
||||
t)
|
||||
nil)))
|
||||
|
||||
(defvar ruby-font-lock-keywords
|
||||
(list
|
||||
(cons (concat
|
||||
|
@ -741,6 +759,8 @@ An end of a defun is found by moving forward from the beginning of one."
|
|||
;; embedded document
|
||||
'(ruby-font-lock-docs
|
||||
0 font-lock-comment-face t)
|
||||
'(ruby-font-lock-maybe-docs
|
||||
0 font-lock-comment-face t)
|
||||
;; constants
|
||||
'("\\(^\\|[^_]\\)\\b\\([A-Z]+\\(\\w\\|_\\)*\\)"
|
||||
2 font-lock-type-face)
|
||||
|
|
31
regex.c
31
regex.c
|
@ -1874,8 +1874,10 @@ re_compile_pattern(pattern, size, bufp)
|
|||
if ((options ^ stackp[-1]) & RE_OPTION_IGNORECASE) {
|
||||
BUFPUSH((options&RE_OPTION_IGNORECASE)?casefold_off:casefold_on);
|
||||
}
|
||||
BUFPUSH(option_set);
|
||||
BUFPUSH(stackp[-1]);
|
||||
if ((options ^ stackp[-1]) != RE_OPTION_IGNORECASE) {
|
||||
BUFPUSH(option_set);
|
||||
BUFPUSH(stackp[-1]);
|
||||
}
|
||||
}
|
||||
p0 = b;
|
||||
options = *--stackp;
|
||||
|
@ -3262,7 +3264,8 @@ re_search(bufp, string, size, startpos, range, regs)
|
|||
}
|
||||
|
||||
if (startpos > size) return -1;
|
||||
if (anchor && size > 0 && startpos == size) return -1;
|
||||
if ((anchor || !bufp->can_be_null) && size > 0 && startpos == size)
|
||||
return -1;
|
||||
val = re_match(bufp, string, size, startpos, regs);
|
||||
if (val >= 0) return startpos;
|
||||
if (val == -2) return -2;
|
||||
|
@ -3362,7 +3365,7 @@ re_search(bufp, string, size, startpos, range, regs)
|
|||
#define NUM_COUNT_ITEMS 2
|
||||
|
||||
/* Individual items aside from the registers. */
|
||||
#define NUM_NONREG_ITEMS 3
|
||||
#define NUM_NONREG_ITEMS 4
|
||||
|
||||
/* We push at most this many things on the stack whenever we
|
||||
fail. The `+ 2' refers to PATTERN_PLACE and STRING_PLACE, which are
|
||||
|
@ -3412,6 +3415,7 @@ re_search(bufp, string, size, startpos, range, regs)
|
|||
\
|
||||
*stackp++ = pattern_place; \
|
||||
*stackp++ = string_place; \
|
||||
*stackp++ = (unsigned char*)options; /* current option status */ \
|
||||
*stackp++ = (unsigned char*)0; /* non-greedy flag */ \
|
||||
} while(0)
|
||||
|
||||
|
@ -3735,15 +3739,11 @@ re_match(bufp, string_arg, size, pos, regs)
|
|||
int regno = *p++; /* Get which register to match against */
|
||||
register unsigned char *d2, *dend2;
|
||||
|
||||
#if 0
|
||||
/* Check if corresponding group is still open */
|
||||
if (IS_ACTIVE(reg_info[regno])) goto fail;
|
||||
|
||||
/* Where in input to try to start matching. */
|
||||
d2 = regstart[regno];
|
||||
#else
|
||||
d2 = IS_ACTIVE(reg_info[regno])?old_regstart[regno]:regstart[regno];
|
||||
#endif
|
||||
if (REG_UNSET(d2)) goto fail;
|
||||
|
||||
/* Where to stop matching; if both the place to start and
|
||||
|
@ -3791,7 +3791,7 @@ re_match(bufp, string_arg, size, pos, regs)
|
|||
case stop_nowidth:
|
||||
EXTRACT_NUMBER_AND_INCR(mcnt, p);
|
||||
stackp = stackb + mcnt;
|
||||
d = stackp[-2];
|
||||
d = stackp[-3];
|
||||
POP_FAILURE_POINT();
|
||||
continue;
|
||||
|
||||
|
@ -4015,8 +4015,8 @@ re_match(bufp, string_arg, size, pos, regs)
|
|||
because didn't fail. Also remove the register information
|
||||
put on by the on_failure_jump. */
|
||||
case finalize_jump:
|
||||
if (stackp > stackb && stackp[-2] == d) {
|
||||
p = stackp[-3];
|
||||
if (stackp > stackb && stackp[-3] == d) {
|
||||
p = stackp[-4];
|
||||
POP_FAILURE_POINT();
|
||||
continue;
|
||||
}
|
||||
|
@ -4032,7 +4032,7 @@ re_match(bufp, string_arg, size, pos, regs)
|
|||
case jump:
|
||||
nofinalize:
|
||||
EXTRACT_NUMBER_AND_INCR(mcnt, p);
|
||||
if (mcnt < 0 && stackp > stackb && stackp[-2] == d) /* avoid infinite loop */
|
||||
if (mcnt < 0 && stackp > stackb && stackp[-3] == d) /* avoid infinite loop */
|
||||
goto fail;
|
||||
p += mcnt;
|
||||
continue;
|
||||
|
@ -4123,7 +4123,7 @@ re_match(bufp, string_arg, size, pos, regs)
|
|||
case finalize_push:
|
||||
POP_FAILURE_POINT();
|
||||
EXTRACT_NUMBER_AND_INCR(mcnt, p);
|
||||
if (mcnt < 0 && stackp > stackb && stackp[-2] == d) /* avoid infinite loop */
|
||||
if (mcnt < 0 && stackp > stackb && stackp[-3] == d) /* avoid infinite loop */
|
||||
goto fail;
|
||||
PUSH_FAILURE_POINT(p + mcnt, d);
|
||||
stackp[-1] = NON_GREEDY;
|
||||
|
@ -4288,11 +4288,12 @@ re_match(bufp, string_arg, size, pos, regs)
|
|||
|
||||
/* If this failure point is from a dummy_failure_point, just
|
||||
skip it. */
|
||||
if (stackp[-3] == 0 || (best_regs_set && stackp[-1] == NON_GREEDY)) {
|
||||
if (stackp[-4] == 0 || (best_regs_set && stackp[-1] == NON_GREEDY)) {
|
||||
POP_FAILURE_POINT();
|
||||
goto fail;
|
||||
}
|
||||
stackp--; /* discard flag */
|
||||
stackp--; /* discard greedy flag */
|
||||
options = (int)*--stackp;
|
||||
d = *--stackp;
|
||||
p = *--stackp;
|
||||
/* Restore register info. */
|
||||
|
|
Loading…
Reference in a new issue