* eval.c (rb_eval): too many line trace call. (ruby-bugs PR#1320)

* numeric.c (flo_to_s): tweak output string based to preserve
  decimal point and to remove trailing zeros.  [ruby-talk:97891]

* string.c (rb_str_index_m): use unsigned comparison for T_FIXNUM
  search.  [ruby-talk:97342]

* hash.c (rb_hash_equal): returns true if two hashes have same set
  of key-value set.  [ruby-talk:97559]

* hash.c (rb_hash_eql): returns true if two hashes are equal and
  have same default values.

* string.c (rb_str_equal): always returns true or false, never
  returns nil. [ruby-dev:23404]

* io.c (rb_io_reopen): should use rb_io_check_io().


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@6263 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2004-05-07 08:48:30 +00:00
parent 4d372569d8
commit 2b5a14bf7c
17 changed files with 147 additions and 77 deletions

View file

@ -62,6 +62,10 @@ Fri Apr 30 20:08:41 2004 WATANABE Hirofumi <eban@ruby-lang.org>
* time.c (SIZEOF_TIME_T): support SIZEOF_TIME_T == SIZEOF_INT. * time.c (SIZEOF_TIME_T): support SIZEOF_TIME_T == SIZEOF_INT.
Tue Apr 27 13:12:42 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
* eval.c (rb_eval): too many line trace call. (ruby-bugs PR#1320)
Tue Apr 27 08:41:28 2004 why the lucky stiff <why@ruby-lang.org> Tue Apr 27 08:41:28 2004 why the lucky stiff <why@ruby-lang.org>
* lib/yaml/rubytypes.rb: passing Range tests. * lib/yaml/rubytypes.rb: passing Range tests.
@ -129,6 +133,14 @@ Thu Apr 22 04:15:36 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
* parse.y (aref_args): should pass expanded list. [ruby-core:02793] * parse.y (aref_args): should pass expanded list. [ruby-core:02793]
Thu Apr 22 01:12:57 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
* numeric.c (flo_to_s): tweak output string based to preserve
decimal point and to remove trailing zeros. [ruby-talk:97891]
* string.c (rb_str_index_m): use unsigned comparison for T_FIXNUM
search. [ruby-talk:97342]
Wed Apr 21 22:57:27 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp> Wed Apr 21 22:57:27 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
* lib/rinda/rinda.rb, test/rinda/test_rinda.rb: check Hash tuple size. * lib/rinda/rinda.rb, test/rinda/test_rinda.rb: check Hash tuple size.
@ -138,6 +150,14 @@ Wed Apr 21 20:05:00 2004 Tanaka Akira <akr@m17n.org>
* lib/open-uri.rb (URI::HTTP#proxy_open): set Host: field explicitly. * lib/open-uri.rb (URI::HTTP#proxy_open): set Host: field explicitly.
[ruby-list:39542] [ruby-list:39542]
Mon Apr 19 18:11:15 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
* hash.c (rb_hash_equal): returns true if two hashes have same set
of key-value set. [ruby-talk:97559]
* hash.c (rb_hash_eql): returns true if two hashes are equal and
have same default values.
Mon Apr 19 08:19:58 2004 Doug Kearns <djkea2@mugca.its.monash.edu.au> Mon Apr 19 08:19:58 2004 Doug Kearns <djkea2@mugca.its.monash.edu.au>
* dln.c, io.c, lib/benchmark.rb, lib/cgi.rb, lib/csv.rb, lib/date.rb, * dln.c, io.c, lib/benchmark.rb, lib/cgi.rb, lib/csv.rb, lib/date.rb,
@ -158,6 +178,11 @@ Fri Apr 16 22:33:00 2004 Gavin Sinclair <gsinclair@soyabean.com.au>
* ext/iconv/iconv.c: nearly finished RDoc comments. * ext/iconv/iconv.c: nearly finished RDoc comments.
Fri Apr 16 17:04:07 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
* string.c (rb_str_equal): always returns true or false, never
returns nil. [ruby-dev:23404]
Fri Apr 16 08:27:02 2004 Nobuyoshi Nakada <nobu@ruby-lang.org> Fri Apr 16 08:27:02 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/extmk.rb: skip linking when libraries to be preloaded not * ext/extmk.rb: skip linking when libraries to be preloaded not
@ -263,6 +288,10 @@ Wed Apr 7 00:19:50 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
* test/rinda/test_rinda.rb * test/rinda/test_rinda.rb
Tue Apr 6 18:24:18 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
* io.c (rb_io_reopen): should use rb_io_check_io().
Tue Apr 6 16:46:09 2004 Tanaka Akira <akr@m17n.org> Tue Apr 6 16:46:09 2004 Tanaka Akira <akr@m17n.org>
* configure.in: check the size of time_t. * configure.in: check the size of time_t.

View file

@ -463,6 +463,9 @@ rb_cstr_to_inum(str, base, badcheck)
} }
continue; continue;
} }
else if (!ISASCII(c)) {
break;
}
else if (isdigit(c)) { else if (isdigit(c)) {
c -= '0'; c -= '0';
} }

5
eval.c
View file

@ -2697,11 +2697,6 @@ rb_eval(self, n)
if (!node) RETURN(Qnil); if (!node) RETURN(Qnil);
ruby_current_node = node; ruby_current_node = node;
if (trace_func && FL_TEST(node, NODE_NEWLINE)) {
call_trace_func("line", node, self,
ruby_frame->last_func,
ruby_frame->last_class);
}
switch (nd_type(node)) { switch (nd_type(node)) {
case NODE_BLOCK: case NODE_BLOCK:
if (contnode) { if (contnode) {

63
hash.c
View file

@ -1392,6 +1392,35 @@ equal_i(key, val1, data)
return ST_CONTINUE; return ST_CONTINUE;
} }
static VALUE
hash_equal(hash1, hash2, eql)
VALUE hash1, hash2;
int eql; /* compare default value if true */
{
struct equal_data data;
if (hash1 == hash2) return Qtrue;
if (TYPE(hash2) != T_HASH) {
if (!rb_respond_to(hash2, rb_intern("to_hash"))) {
return Qfalse;
}
return rb_equal(hash2, hash1);
}
if (RHASH(hash1)->tbl->num_entries != RHASH(hash2)->tbl->num_entries)
return Qfalse;
if (eql) {
if (!(rb_equal(RHASH(hash1)->ifnone, RHASH(hash2)->ifnone) &&
FL_TEST(hash1, HASH_PROC_DEFAULT) == FL_TEST(hash2, HASH_PROC_DEFAULT)))
return Qfalse;
}
data.tbl = RHASH(hash2)->tbl;
data.result = Qtrue;
st_foreach(RHASH(hash1)->tbl, equal_i, (st_data_t)&data);
return data.result;
}
/* /*
* call-seq: * call-seq:
* hsh == other_hash => true or false * hsh == other_hash => true or false
@ -1415,26 +1444,23 @@ static VALUE
rb_hash_equal(hash1, hash2) rb_hash_equal(hash1, hash2)
VALUE hash1, hash2; VALUE hash1, hash2;
{ {
struct equal_data data; return hash_equal(hash1, hash2, Qfalse);
}
if (hash1 == hash2) return Qtrue; /*
if (TYPE(hash2) != T_HASH) { * call-seq:
if (!rb_respond_to(hash2, rb_intern("to_hash"))) { * hsh.eql?(other_hash) => true or false
return Qfalse; *
} * Returns true if two hashes are equal, i.e they have same key-value set,
return rb_equal(hash2, hash1); * and same default values.
} *
if (RHASH(hash1)->tbl->num_entries != RHASH(hash2)->tbl->num_entries) */
return Qfalse;
if (!(rb_equal(RHASH(hash1)->ifnone, RHASH(hash2)->ifnone) &&
FL_TEST(hash1, HASH_PROC_DEFAULT) == FL_TEST(hash2, HASH_PROC_DEFAULT)))
return Qfalse;
data.tbl = RHASH(hash2)->tbl; static VALUE
data.result = Qtrue; rb_hash_eql(hash1, hash2)
st_foreach(RHASH(hash1)->tbl, equal_i, (st_data_t)&data); VALUE hash1, hash2;
{
return data.result; return hash_equal(hash1, hash2, Qtrue);
} }
static int static int
@ -2368,6 +2394,7 @@ Init_Hash()
rb_define_method(rb_cHash,"inspect", rb_hash_inspect, 0); rb_define_method(rb_cHash,"inspect", rb_hash_inspect, 0);
rb_define_method(rb_cHash,"==", rb_hash_equal, 1); rb_define_method(rb_cHash,"==", rb_hash_equal, 1);
rb_define_method(rb_cHash,"eql?", rb_hash_eql, 1);
rb_define_method(rb_cHash,"[]", rb_hash_aref, 1); rb_define_method(rb_cHash,"[]", rb_hash_aref, 1);
rb_define_method(rb_cHash,"fetch", rb_hash_fetch, -1); rb_define_method(rb_cHash,"fetch", rb_hash_fetch, -1);
rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2); rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2);

25
io.c
View file

@ -2368,15 +2368,28 @@ rb_fdopen(fd, mode)
{ {
FILE *file; FILE *file;
#if defined(sun)
errno = 0;
#endif
file = fdopen(fd, mode); file = fdopen(fd, mode);
if (!file) { if (!file) {
#if defined(sun)
if (errno == 0 || errno == EMFILE || errno == ENFILE) {
#else
if (errno == EMFILE || errno == ENFILE) { if (errno == EMFILE || errno == ENFILE) {
#endif
rb_gc(); rb_gc();
#if defined(sun)
errno = 0;
#endif
file = fdopen(fd, mode); file = fdopen(fd, mode);
} }
if (!file) { if (!file) {
#ifdef _WIN32 #ifdef _WIN32
if (errno == 0) errno = EINVAL; if (errno == 0) errno = EINVAL;
#endif
#if defined(sun)
if (errno == 0) errno = EMFILE;
#endif #endif
rb_sys_fail(0); rb_sys_fail(0);
} }
@ -2993,6 +3006,13 @@ rb_io_get_io(io)
return rb_convert_type(io, T_FILE, "IO", "to_io"); return rb_convert_type(io, T_FILE, "IO", "to_io");
} }
static VALUE
rb_io_check_io(io)
VALUE io;
{
return rb_check_convert_type(io, T_FILE, "IO", "to_io");
}
static char* static char*
rb_io_mode_string(fptr) rb_io_mode_string(fptr)
OpenFile *fptr; OpenFile *fptr;
@ -3122,8 +3142,9 @@ rb_io_reopen(argc, argv, file)
rb_secure(4); rb_secure(4);
if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 1) { if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 1) {
if (TYPE(fname) != T_STRING) { /* fname must be IO */ VALUE tmp = rb_io_check_io(fname);
return io_reopen(file, fname); if (!NIL_P(tmp)) {
return io_reopen(file, tmp);
} }
} }

View file

@ -30,7 +30,7 @@
# See http://www.w3.org/CGI/ for more information on the CGI # See http://www.w3.org/CGI/ for more information on the CGI
# protocol. # protocol.
raise "Please, use ruby1.5.4 or later." if RUBY_VERSION < "1.5.4" raise "Please, use ruby 1.5.4 or later." if RUBY_VERSION < "1.5.4"
require 'English' require 'English'

View file

@ -557,7 +557,7 @@ class CSV
private private
def initialize(dev) def initialize(dev)
raise RuntimeError.new('do not instanciate this class directly') raise RuntimeError.new('do not instantiate this class directly')
end end
def get_row(row) def get_row(row)
@ -709,7 +709,7 @@ class CSV
private private
def initialize(dev) def initialize(dev)
raise RuntimeError.new('do not instanciate this class directly') raise RuntimeError.new('do not instantiate this class directly')
end end
def terminate def terminate
@ -801,7 +801,7 @@ class CSV
# end # end
# end # end
# #
class StreamBuf # pure virtual. (do not instanciate it directly) class StreamBuf # pure virtual. (do not instantiate it directly)
# get a char or a partial string from the stream. # get a char or a partial string from the stream.
# idx: index of a string to specify a start point of a string to get. # idx: index of a string to specify a start point of a string to get.
@ -893,7 +893,7 @@ class CSV
return idx_is_eos?(0) return idx_is_eos?(0)
end end
# WARN: Do not instanciate this class directly. Define your own class # WARN: Do not instantiate this class directly. Define your own class
# which derives this class and define 'read' instance method. # which derives this class and define 'read' instance method.
def initialize def initialize
@buf_list = [] @buf_list = []

View file

@ -125,7 +125,7 @@ class Generator
# Returns the element at the current position and moves forward. # Returns the element at the current position and moves forward.
def next() def next()
if end? if end?
raise EOFError, "no more element is supplied" raise EOFError, "no more elements available"
end end
if @cont_next = callcc { |c| c } if @cont_next = callcc { |c| c }
@ -140,7 +140,7 @@ class Generator
# Returns the element at the current position. # Returns the element at the current position.
def current() def current()
if @queue.empty? if @queue.empty?
raise EOFError, "no more element is supplied" raise EOFError, "no more elements available"
end end
@queue.first @queue.first

View file

@ -539,6 +539,7 @@ private
def create_logfile(filename) def create_logfile(filename)
logdev = open(filename, (File::WRONLY | File::APPEND | File::CREAT)) logdev = open(filename, (File::WRONLY | File::APPEND | File::CREAT))
logdev.sync = true
add_log_header(logdev) add_log_header(logdev)
logdev logdev
end end

View file

@ -57,7 +57,7 @@ class OpenStruct
len = args.length len = args.length
if mname =~ /=$/ if mname =~ /=$/
if len != 1 if len != 1
raise ArgumentError, "wrong # of arguments (#{len} for 1)", caller(1) raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)
end end
if self.frozen? if self.frozen?
raise TypeError, "can't modify frozen #{self.class}", caller(1) raise TypeError, "can't modify frozen #{self.class}", caller(1)

View file

@ -48,7 +48,7 @@ class Rational < Numeric
@RCS_ID='-$Id: rational.rb,v 1.7 1999/08/24 12:49:28 keiju Exp keiju $-' @RCS_ID='-$Id: rational.rb,v 1.7 1999/08/24 12:49:28 keiju Exp keiju $-'
def Rational.reduce(num, den = 1) def Rational.reduce(num, den = 1)
raise ZeroDivisionError, "denominator is 0" if den == 0 raise ZeroDivisionError, "denominator is zero" if den == 0
if den < 0 if den < 0
num = -num num = -num
@ -135,7 +135,7 @@ class Rational < Numeric
den = @denominator * a.numerator den = @denominator * a.numerator
Rational(num, den) Rational(num, den)
elsif a.kind_of?(Integer) elsif a.kind_of?(Integer)
raise ZeroDivisionError, "divided by 0" if a == 0 raise ZeroDivisionError, "division by zero" if a == 0
self / Rational.new!(a, 1) self / Rational.new!(a, 1)
elsif a.kind_of?(Float) elsif a.kind_of?(Float)
Float(self) / a Float(self) / a

View file

@ -13,7 +13,7 @@
# a == b # => true # a == b # => true
# a.new # NoMethodError - new is private ... # a.new # NoMethodError - new is private ...
# #
# * ``The instance'' is created at instanciation time, in other # * ``The instance'' is created at instantiation time, in other
# words the first call of Klass.instance(), thus # words the first call of Klass.instance(), thus
# #
# class OtherKlass # class OtherKlass
@ -44,11 +44,11 @@
# #
# * Klass._load(str) - calling Klass.instance() # * Klass._load(str) - calling Klass.instance()
# #
# * Klass._instanciate?() - returning ``the instance'' or # * Klass._instantiate?() - returning ``the instance'' or
# nil. This hook method puts a second (or nth) thread calling # nil. This hook method puts a second (or nth) thread calling
# Klass.instance() on a waiting loop. The return value # Klass.instance() on a waiting loop. The return value
# signifies the successful completion or premature termination # signifies the successful completion or premature termination
# of the first, or more generally, current "instanciation thread". # of the first, or more generally, current "instantiation thread".
# #
# #
# The instance method of Singleton are # The instance method of Singleton are
@ -103,7 +103,7 @@ class << Singleton
@__instance__ = nil # failed instance creation @__instance__ = nil # failed instance creation
end end
end end
elsif _instanciate?() elsif _instantiate?()
Thread.critical = false Thread.critical = false
else else
@__instance__ = false @__instance__ = false
@ -144,7 +144,7 @@ class << Singleton
end end
# waiting-loop hook # waiting-loop hook
def _instanciate?() def _instantiate?()
while false.equal?(@__instance__) while false.equal?(@__instance__)
Thread.critical = false Thread.critical = false
sleep(0.08) # timeout sleep(0.08) # timeout
@ -209,7 +209,7 @@ end
puts "\nThreaded example with exception and customized #_instanciate?() hook"; p puts "\nThreaded example with exception and customized #_instantiate?() hook"; p
Thread.abort_on_exception = false Thread.abort_on_exception = false
class Ups < SomeSingletonClass class Ups < SomeSingletonClass
@ -220,7 +220,7 @@ class Ups < SomeSingletonClass
end end
class << Ups class << Ups
def _instanciate? def _instantiate?
@enter.push Thread.current[:i] @enter.push Thread.current[:i]
while false.equal?(@__instance__) while false.equal?(@__instance__)
Thread.critical = false Thread.critical = false
@ -247,7 +247,7 @@ class << Ups
end end
end end
def instanciate_all def instantiate_all
@enter = [] @enter = []
@leave = [] @leave = []
1.upto(9) {|i| 1.upto(9) {|i|
@ -270,7 +270,7 @@ class << Ups
end end
Ups.instanciate_all Ups.instantiate_all
# results in message like # results in message like
# Before there were 0 Ups instance(s) # Before there were 0 Ups instance(s)
# boom - thread #6 failed to create instance # boom - thread #6 failed to create instance
@ -293,7 +293,7 @@ def Yup.new
end end
end end
end end
Yup.instanciate_all Yup.instantiate_all
puts "\n\n","Customized marshalling" puts "\n\n","Customized marshalling"

View file

@ -9,7 +9,7 @@ require 'tmpdir'
# A class for managing temporary files. This library is written to be # A class for managing temporary files. This library is written to be
# thread safe. # thread safe.
class Tempfile < SimpleDelegator class Tempfile < DelegateClass(File)
MAX_TRY = 10 MAX_TRY = 10
@@cleanlist = [] @@cleanlist = []

View file

@ -31,7 +31,9 @@ module Test
# Creates a new instance of the fixture for running the # Creates a new instance of the fixture for running the
# test represented by test_method_name. # test represented by test_method_name.
def initialize(test_method_name) def initialize(test_method_name)
unless(respond_to?(test_method_name) && method(test_method_name).arity == 0) unless(respond_to?(test_method_name) and
(method(test_method_name).arity == 0 ||
method(test_method_name).arity == -1))
throw :invalid_test throw :invalid_test
end end
@method_name = test_method_name @method_name = test_method_name

View file

@ -325,7 +325,7 @@ The variable ruby-indent-level controls the amount of indentation.
(looking-at ruby-block-op-re) (looking-at ruby-block-op-re)
(looking-at ruby-block-mid-re)) (looking-at ruby-block-mid-re))
(goto-char (match-end 0)) (goto-char (match-end 0))
(looking-at "\\>")) (not (looking-at "\\s_")))
((eq option 'expr-qstr) ((eq option 'expr-qstr)
(looking-at "[a-zA-Z][a-zA-z0-9_]* +%[^ \t]")) (looking-at "[a-zA-Z][a-zA-z0-9_]* +%[^ \t]"))
((eq option 'expr-re) ((eq option 'expr-re)

View file

@ -489,9 +489,10 @@ flo_to_s(flt)
VALUE flt; VALUE flt;
{ {
char buf[32]; char buf[32];
char *fmt = "%.15g"; char *fmt = "%.15f";
double value = RFLOAT(flt)->value; double value = RFLOAT(flt)->value;
double avalue, d1, d2; double avalue, d1, d2;
char *p, *e;
if (isinf(value)) if (isinf(value))
return rb_str_new2(value < 0 ? "-Infinity" : "Infinity"); return rb_str_new2(value < 0 ? "-Infinity" : "Infinity");
@ -499,27 +500,18 @@ flo_to_s(flt)
return rb_str_new2("NaN"); return rb_str_new2("NaN");
avalue = fabs(value); avalue = fabs(value);
if (avalue == 0.0) { if (avalue < 1.0e-7 || avalue >= 1.0e15) {
fmt = "%.1f"; fmt = "%.16e";
}
else if (avalue < 1.0e-3) {
d1 = avalue;
while (d1 < 1.0) d1 *= 10.0;
d1 = modf(d1, &d2);
if (d1 == 0) fmt = "%.1e";
}
else if (avalue >= 1.0e15) {
d1 = avalue;
while (d1 > 10.0) d1 /= 10.0;
d1 = modf(d1, &d2);
if (d1 == 0) fmt = "%.1e";
else fmt = "%.16e";
}
else if ((d1 = modf(value, &d2)) == 0) {
fmt = "%.1f";
} }
sprintf(buf, fmt, value); sprintf(buf, fmt, value);
if (!(e = strchr(buf, 'e'))) {
e = buf + strlen(buf);
}
p = e;
while (*--p=='0')
;
if (*p == '.') *p++;
memmove(p+1, e, strlen(e)+1);
return rb_str_new2(buf); return rb_str_new2(buf);
} }

View file

@ -889,7 +889,7 @@ rb_str_equal(str1, str2)
if (str1 == str2) return Qtrue; if (str1 == str2) return Qtrue;
if (TYPE(str2) != T_STRING) { if (TYPE(str2) != T_STRING) {
if (!rb_respond_to(str2, rb_intern("to_str"))) { if (!rb_respond_to(str2, rb_intern("to_str"))) {
return Qnil; return Qfalse;
} }
return rb_equal(str2, str1); return rb_equal(str2, str1);
} }
@ -954,7 +954,7 @@ rb_str_cmp_m(str1, str2)
if (TYPE(str2) != T_STRING) { if (TYPE(str2) != T_STRING) {
if (!rb_respond_to(str2, rb_intern("to_str"))) { if (!rb_respond_to(str2, rb_intern("to_str"))) {
return Qnil; return Qfalse;
} }
else if (!rb_respond_to(str2, rb_intern("<=>"))) { else if (!rb_respond_to(str2, rb_intern("<=>"))) {
return Qnil; return Qnil;
@ -1081,7 +1081,7 @@ rb_str_index_m(argc, argv, str)
{ {
int c = FIX2INT(sub); int c = FIX2INT(sub);
long len = RSTRING(str)->len; long len = RSTRING(str)->len;
char *p = RSTRING(str)->ptr; unsigned char *p = RSTRING(str)->ptr;
for (;pos<len;pos++) { for (;pos<len;pos++) {
if (p[pos] == c) return LONG2NUM(pos); if (p[pos] == c) return LONG2NUM(pos);
@ -1203,15 +1203,15 @@ rb_str_rindex_m(argc, argv, str)
case T_FIXNUM: case T_FIXNUM:
{ {
int c = FIX2INT(sub); int c = FIX2INT(sub);
char *p = RSTRING(str)->ptr + pos; unsigned char *p = RSTRING(str)->ptr + pos;
char *pbeg = RSTRING(str)->ptr; unsigned char *pbeg = RSTRING(str)->ptr;
if (pos == RSTRING(str)->len) { if (pos == RSTRING(str)->len) {
if (pos == 0) return Qnil; if (pos == 0) return Qnil;
--p; --p;
} }
while (pbeg <= p) { while (pbeg <= p) {
if (*p == c) return LONG2NUM(p - RSTRING(str)->ptr); if (*p == c) return LONG2NUM((char*)p - RSTRING(str)->ptr);
p--; p--;
} }
return Qnil; return Qnil;