2000-05-01 05:42:38 -04:00
|
|
|
/**********************************************************************
|
1998-01-16 07:13:05 -05:00
|
|
|
|
|
|
|
util.c -
|
|
|
|
|
|
|
|
$Author$
|
|
|
|
created at: Fri Mar 10 17:22:34 JST 1995
|
|
|
|
|
2008-06-01 19:47:02 -04:00
|
|
|
Copyright (C) 1993-2008 Yukihiro Matsumoto
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2000-05-01 05:42:38 -04:00
|
|
|
**********************************************************************/
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2017-03-03 01:18:36 -05:00
|
|
|
#if defined __MINGW32__ || defined __MINGW64__
|
2019-12-04 03:16:30 -05:00
|
|
|
# define MINGW_HAS_SECURE_API 1
|
2017-03-03 01:18:36 -05:00
|
|
|
#endif
|
|
|
|
|
2020-05-08 05:31:09 -04:00
|
|
|
#include "ruby/internal/config.h"
|
2002-05-14 02:22:31 -04:00
|
|
|
|
2002-05-29 01:20:39 -04:00
|
|
|
#include <ctype.h>
|
2001-11-08 01:43:14 -05:00
|
|
|
#include <errno.h>
|
* sprintf.c (rb_str_format): allow %c to print one character
string (e.g. ?x).
* lib/tempfile.rb (Tempfile::make_tmpname): put dot between
basename and pid. [ruby-talk:196272]
* parse.y (do_block): remove -> style block.
* parse.y (parser_yylex): remove tLAMBDA_ARG.
* eval.c (rb_call0): binding for the return event hook should have
consistent scope. [ruby-core:07928]
* eval.c (proc_invoke): return behavior should depend whether it
is surrounded by a lambda or a mere block.
* eval.c (formal_assign): handles post splat arguments.
* eval.c (rb_call0): ditto.
* st.c (strhash): use FNV-1a hash.
* parse.y (parser_yylex): removed experimental ';;' terminator.
* eval.c (rb_node_arity): should be aware of post splat arguments.
* eval.c (rb_proc_arity): ditto.
* parse.y (f_args): syntax rule enhanced to support arguments
after the splat.
* parse.y (block_param): ditto for block parameters.
* parse.y (f_post_arg): mandatory formal arguments after the splat
argument.
* parse.y (new_args_gen): generate nodes for mandatory formal
arguments after the splat argument.
* eval.c (rb_eval): dispatch mandatory formal arguments after the
splat argument.
* parse.y (args): allow more than one splat in the argument list.
* parse.y (method_call): allow aref [] to accept all kind of
method argument, including assocs, splat, and block argument.
* eval.c (SETUP_ARGS0): prepare block argument as well.
* lib/mathn.rb (Integer): remove Integer#gcd2. [ruby-core:07931]
* eval.c (error_line): print receivers true/false/nil specially.
* eval.c (rb_proc_yield): handles parameters in yield semantics.
* eval.c (nil_yield): gives LocalJumpError to denote no block
error.
* io.c (rb_io_getc): now takes one-character string.
* string.c (rb_str_hash): use FNV-1a hash from Fowler/Noll/Vo
hashing algorithm.
* string.c (rb_str_aref): str[0] now returns 1 character string,
instead of a fixnum. [Ruby2]
* parse.y (parser_yylex): ?c now returns 1 character string,
instead of a fixnum. [Ruby2]
* string.c (rb_str_aset): no longer support fixnum insertion.
* eval.c (umethod_bind): should not update original class.
[ruby-dev:28636]
* eval.c (ev_const_get): should support constant access from
within instance_eval(). [ruby-dev:28327]
* time.c (time_timeval): should round for usec floating
number. [ruby-core:07896]
* time.c (time_add): ditto.
* dir.c (sys_warning): should not call a vararg function
rb_sys_warning() indirectly. [ruby-core:07886]
* numeric.c (flo_divmod): the first element of Float#divmod should
be an integer. [ruby-dev:28589]
* test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
* re.c (rb_reg_initialize): should not allow modifying literal
regexps. frozen check moved from rb_reg_initialize_m as well.
* re.c (rb_reg_initialize): should not modify untainted objects in
safe levels higher than 3.
* re.c (rb_memcmp): type change from char* to const void*.
* dir.c (dir_close): should not close untainted dir stream.
* dir.c (GetDIR): add tainted/frozen check for each dir operation.
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_symbol_arg):
typo fixed. a patch from Florian Gross <florg at florg.net>.
* eval.c (EXEC_EVENT_HOOK): trace_func may remove itself from
event_hooks. no guarantee for arbitrary hook deletion.
[ruby-dev:28632]
* util.c (ruby_strtod): differ addition to minimize error.
[ruby-dev:28619]
* util.c (ruby_strtod): should not raise ERANGE when the input
string does not have any digits. [ruby-dev:28629]
* eval.c (proc_invoke): should restore old ruby_frame->block.
thanks to ts <decoux at moulon.inra.fr>. [ruby-core:07833]
also fix [ruby-dev:28614] as well.
* signal.c (trap): sig should be less then NSIG. Coverity found
this bug. a patch from Kevin Tew <tewk at tewk.com>.
[ruby-core:07823]
* math.c (math_log2): add new method inspired by
[ruby-talk:191237].
* math.c (math_log): add optional base argument to Math::log().
[ruby-talk:191308]
* ext/syck/emitter.c (syck_scan_scalar): avoid accessing
uninitialized array element. a patch from Pat Eyler
<rubypate at gmail.com>. [ruby-core:07809]
* array.c (rb_ary_fill): initialize local variables first. a
patch from Pat Eyler <rubypate at gmail.com>. [ruby-core:07810]
* ext/syck/yaml2byte.c (syck_yaml2byte_handler): need to free
type_tag. a patch from Pat Eyler <rubypate at gmail.com>.
[ruby-core:07808]
* ext/socket/socket.c (make_hostent_internal): accept ai_family
check from Sam Roberts <sroberts at uniserve.com>.
[ruby-core:07691]
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
* array.c (rb_ary_fill): internalize local variable "beg" to
pacify Coverity. [ruby-core:07770]
* pack.c (pack_unpack): now supports CRLF newlines. a patch from
<tommy at tmtm.org>. [ruby-dev:28601]
* applied code clean-up patch from Stefan Huehner
<stefan at huehner.org>. [ruby-core:07764]
* lib/jcode.rb (String::tr_s): should have translated non
squeezing character sequence (i.e. a character) as well. thanks
to Hiroshi Ichikawa <gimite at gimite.ddo.jp> [ruby-list:42090]
* ext/socket/socket.c: document update patch from Sam Roberts
<sroberts at uniserve.com>. [ruby-core:07701]
* lib/mathn.rb (Integer): need not to remove gcd2. a patch from
NARUSE, Yui <naruse at airemix.com>. [ruby-dev:28570]
* parse.y (arg): too much NEW_LIST()
* eval.c (SETUP_ARGS0): remove unnecessary access to nd_alen.
* eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
[ruby-dev:28585]
* parse.y (arg): use NODE_ARGSCAT for placeholder.
* lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
mathew <meta at pobox.com>. [ruby-core:07738]
* variable.c (rb_const_set): raise error when no target klass is
supplied. [ruby-dev:28582]
* prec.c (prec_prec_f): documentation patch from
<gerardo.santana at gmail.com>. [ruby-core:07689]
* bignum.c (rb_big_pow): second operand may be too big even if
it's a Fixnum. [ruby-talk:187984]
* README.EXT: update symbol description. [ruby-talk:188104]
* COPYING: explicitly note GPLv2. [ruby-talk:187922]
* parse.y: remove some obsolete syntax rules (unparenthesized
method calls in argument list).
* eval.c (rb_call0): insecure calling should be checked for non
NODE_SCOPE method invocations too.
* eval.c (rb_alias): should preserve the current safe level as
well as method definition.
* process.c (rb_f_sleep): remove RDoc description about SIGALRM
which is not valid on the current implementation. [ruby-dev:28464]
Thu Mar 23 21:40:47 2006 K.Kosako <sndgk393 AT ybb.ne.jp>
* eval.c (method_missing): should support argument splat in
super. a bug in combination of super, splat and
method_missing. [ruby-talk:185438]
* configure.in: Solaris SunPro compiler -rapth patch from
<kuwa at labs.fujitsu.com>. [ruby-dev:28443]
* configure.in: remove enable_rpath=no for Solaris.
[ruby-dev:28440]
* ext/win32ole/win32ole.c (ole_val2olevariantdata): change behavior
of converting OLE Variant object with VT_ARRAY|VT_UI1 and Ruby
String object.
* ruby.1: a clarification patch from David Lutterkort
<dlutter at redhat.com>. [ruby-core:7508]
* lib/rdoc/ri/ri_paths.rb (RI::Paths): adding paths from rubygems
directories. a patch from Eric Hodel <drbrain at segment7.net>.
[ruby-core:07423]
* eval.c (rb_clear_cache_by_class): clearing wrong cache.
* ext/extmk.rb: use :remove_destination to install extension libraries
to avoid SEGV. [ruby-dev:28417]
* eval.c (rb_thread_fd_writable): should not re-schedule output
from KILLED thread (must be error printing).
* array.c (rb_ary_flatten_bang): allow specifying recursion
level. [ruby-talk:182170]
* array.c (rb_ary_flatten): ditto.
* gc.c (add_heap): a heap_slots may overflow. a patch from Stefan
Weil <weil at mail.berlios.de>.
* eval.c (rb_call): use separate cache for fcall/vcall
invocation.
* eval.c (rb_eval): NODE_FCALL, NODE_VCALL can call local
functions.
* eval.c (rb_mod_local): a new method to specify newly added
visibility "local".
* eval.c (search_method): search for local methods which are
visible only from the current class.
* class.c (rb_class_local_methods): a method to list local methods.
* object.c (Init_Object): add BasicObject class as a top level
BlankSlate class.
* ruby.h (SYM2ID): should not cast to signed long.
[ruby-core:07414]
* class.c (rb_include_module): allow module duplication.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2006-06-09 17:20:17 -04:00
|
|
|
#include <float.h>
|
2019-12-04 03:16:30 -05:00
|
|
|
#include <math.h>
|
|
|
|
#include <stdio.h>
|
1999-01-19 23:59:39 -05:00
|
|
|
|
* configure.in, defines.h, dir.c, dir.h, dln.c, error.c,
eval.c, file.c, hash.c, io.c, main.c, missing.c,
process.c, ruby.c, rubysig.h, signal.c, st.c, util.c, util.h,
bcc/Makefile.sub, win32/Makefile.sub, win32/win32.h,
ext/Win32API/Win32API.c, ext/socket/getaddrinfo.c,
ext/socket/getnameinfo.c, ext/socket/socket.c,
ext/tcltklib/stubs.c
: replace "NT" with "_WIN32", add DOSISH_DRIVE_LETTER
* wince/exe.mak : delete \r at the end of lines.
* wince/mswince-ruby17.def : delete rb_obj_become
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3148 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-12-14 22:18:08 -05:00
|
|
|
#ifdef _WIN32
|
2019-12-04 03:16:30 -05:00
|
|
|
# include "missing/file.h"
|
1999-01-19 23:59:39 -05:00
|
|
|
#endif
|
|
|
|
|
2019-12-04 03:16:30 -05:00
|
|
|
#include "internal.h"
|
|
|
|
#include "internal/sanitizers.h"
|
|
|
|
#include "internal/util.h"
|
2007-06-09 23:06:15 -04:00
|
|
|
#include "ruby/util.h"
|
2021-01-10 03:36:18 -05:00
|
|
|
#include "ruby_atomic.h"
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2015-02-13 02:07:39 -05:00
|
|
|
const char ruby_hexdigits[] = "0123456789abcdef0123456789ABCDEF";
|
|
|
|
#define hexdigit ruby_hexdigits
|
|
|
|
|
1998-01-16 07:13:05 -05:00
|
|
|
unsigned long
|
2009-03-14 05:25:20 -04:00
|
|
|
ruby_scan_oct(const char *start, size_t len, size_t *retlen)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
1999-08-13 01:45:20 -04:00
|
|
|
register const char *s = start;
|
1998-01-16 07:13:05 -05:00
|
|
|
register unsigned long retval = 0;
|
2018-11-08 01:22:57 -05:00
|
|
|
size_t i;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2018-11-08 01:22:57 -05:00
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
if ((s[0] < '0') || ('7' < s[0])) {
|
|
|
|
break;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
retval <<= 3;
|
|
|
|
retval |= *s++ - '0';
|
|
|
|
}
|
2021-07-20 10:21:05 -04:00
|
|
|
*retlen = (size_t)(s - start);
|
1998-01-16 07:13:05 -05:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned long
|
2009-03-14 05:25:20 -04:00
|
|
|
ruby_scan_hex(const char *start, size_t len, size_t *retlen)
|
1998-01-16 07:13:05 -05:00
|
|
|
{
|
1999-08-13 01:45:20 -04:00
|
|
|
register const char *s = start;
|
1998-01-16 07:13:05 -05:00
|
|
|
register unsigned long retval = 0;
|
2021-07-20 06:54:59 -04:00
|
|
|
signed char d;
|
2018-11-12 19:40:52 -05:00
|
|
|
size_t i = 0;
|
1998-01-16 07:13:05 -05:00
|
|
|
|
2018-11-12 19:40:52 -05:00
|
|
|
for (i = 0; i < len; i++) {
|
2021-07-20 06:54:59 -04:00
|
|
|
d = ruby_digit36_to_number_table[(unsigned char)*s];
|
|
|
|
if (d < 0 || 15 < d) {
|
2018-11-12 19:40:52 -05:00
|
|
|
break;
|
|
|
|
}
|
1998-01-16 07:13:05 -05:00
|
|
|
retval <<= 4;
|
2021-07-20 06:54:59 -04:00
|
|
|
retval |= d;
|
1998-01-16 07:13:05 -05:00
|
|
|
s++;
|
|
|
|
}
|
2021-07-20 10:21:05 -04:00
|
|
|
*retlen = (size_t)(s - start);
|
1998-01-16 07:13:05 -05:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2013-07-03 09:32:14 -04:00
|
|
|
const signed char ruby_digit36_to_number_table[] = {
|
|
|
|
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
|
|
|
|
/*0*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
/*1*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
/*2*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
/*3*/ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
|
|
|
|
/*4*/ -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
|
|
|
|
/*5*/ 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
|
|
|
|
/*6*/ -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
|
|
|
|
/*7*/ 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
|
|
|
|
/*8*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
/*9*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
/*a*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
/*b*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
/*c*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
/*d*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
/*e*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
/*f*/ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
|
|
|
};
|
|
|
|
|
2018-11-09 04:44:49 -05:00
|
|
|
NO_SANITIZE("unsigned-integer-overflow", extern unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow));
|
2015-05-29 01:39:03 -04:00
|
|
|
unsigned long
|
|
|
|
ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow)
|
2008-01-02 01:24:27 -05:00
|
|
|
{
|
2021-01-08 01:55:05 -05:00
|
|
|
RBIMPL_ASSERT_OR_ASSUME(base >= 2);
|
|
|
|
RBIMPL_ASSERT_OR_ASSUME(base <= 36);
|
2008-01-02 01:24:27 -05:00
|
|
|
|
|
|
|
const char *start = str;
|
|
|
|
unsigned long ret = 0, x;
|
2008-01-02 23:31:37 -05:00
|
|
|
unsigned long mul_overflow = (~(unsigned long)0) / base;
|
2015-05-29 01:39:03 -04:00
|
|
|
|
2008-01-02 01:24:27 -05:00
|
|
|
*overflow = 0;
|
|
|
|
|
2015-05-29 01:39:03 -04:00
|
|
|
if (!len) {
|
|
|
|
*retlen = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
int d = ruby_digit36_to_number_table[(unsigned char)*str++];
|
2008-01-02 01:24:27 -05:00
|
|
|
if (d == -1 || base <= d) {
|
2015-06-17 03:21:41 -04:00
|
|
|
--str;
|
2015-05-29 01:39:03 -04:00
|
|
|
break;
|
2008-01-02 01:24:27 -05:00
|
|
|
}
|
2008-01-02 23:31:37 -05:00
|
|
|
if (mul_overflow < ret)
|
2008-01-02 01:24:27 -05:00
|
|
|
*overflow = 1;
|
|
|
|
ret *= base;
|
|
|
|
x = ret;
|
2009-02-22 09:23:33 -05:00
|
|
|
ret += d;
|
2008-01-02 01:24:27 -05:00
|
|
|
if (ret < x)
|
|
|
|
*overflow = 1;
|
2015-05-29 01:39:03 -04:00
|
|
|
} while (len < 0 || --len);
|
2015-06-17 03:21:41 -04:00
|
|
|
*retlen = str - start;
|
2008-01-02 01:24:27 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned long
|
|
|
|
ruby_strtoul(const char *str, char **endptr, int base)
|
|
|
|
{
|
|
|
|
int c, b, overflow;
|
|
|
|
int sign = 0;
|
|
|
|
size_t len;
|
|
|
|
unsigned long ret;
|
2008-01-02 09:53:16 -05:00
|
|
|
const char *subject_found = str;
|
2008-01-02 01:24:27 -05:00
|
|
|
|
2021-01-08 01:55:05 -05:00
|
|
|
if (base < 0) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-01-02 01:24:27 -05:00
|
|
|
if (base == 1 || 36 < base) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((c = *str) && ISSPACE(c))
|
|
|
|
str++;
|
|
|
|
|
|
|
|
if (c == '+') {
|
|
|
|
sign = 1;
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
else if (c == '-') {
|
|
|
|
sign = -1;
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (str[0] == '0') {
|
2008-01-02 09:53:16 -05:00
|
|
|
subject_found = str+1;
|
2008-01-02 01:24:27 -05:00
|
|
|
if (base == 0 || base == 16) {
|
|
|
|
if (str[1] == 'x' || str[1] == 'X') {
|
|
|
|
b = 16;
|
|
|
|
str += 2;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
b = base == 0 ? 8 : 16;
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
b = base;
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
b = base == 0 ? 10 : base;
|
|
|
|
}
|
|
|
|
|
2015-05-29 01:39:03 -04:00
|
|
|
ret = ruby_scan_digits(str, -1, b, &len, &overflow);
|
2008-01-02 01:24:27 -05:00
|
|
|
|
2008-01-02 09:53:16 -05:00
|
|
|
if (0 < len)
|
|
|
|
subject_found = str+len;
|
|
|
|
|
2008-01-02 01:24:27 -05:00
|
|
|
if (endptr)
|
2008-01-02 09:53:16 -05:00
|
|
|
*endptr = (char*)subject_found;
|
2008-01-02 01:24:27 -05:00
|
|
|
|
|
|
|
if (overflow) {
|
|
|
|
errno = ERANGE;
|
|
|
|
return ULONG_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sign < 0) {
|
2009-03-10 01:43:14 -04:00
|
|
|
ret = (unsigned long)(-(long)ret);
|
2008-01-02 01:24:27 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
1999-08-13 01:45:20 -04:00
|
|
|
#if defined(HAVE_FCNTL_H)
|
1998-01-16 07:13:05 -05:00
|
|
|
#include <fcntl.h>
|
1999-01-19 23:59:39 -05:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef S_ISDIR
|
2011-01-09 21:24:04 -05:00
|
|
|
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
1999-01-19 23:59:39 -05:00
|
|
|
#endif
|
|
|
|
|
2018-09-09 03:49:04 -04:00
|
|
|
typedef int (cmpfunc_t)(const void*, const void*, void*);
|
|
|
|
|
2018-09-10 00:21:39 -04:00
|
|
|
#if defined HAVE_QSORT_S && defined RUBY_MSVCRT_VERSION
|
|
|
|
/* In contrast to its name, Visual Studio qsort_s is incompatible with
|
|
|
|
* C11 in the order of the comparison function's arguments, and same
|
|
|
|
* as BSD qsort_r rather. */
|
2016-05-11 04:18:56 -04:00
|
|
|
# define qsort_r(base, nel, size, arg, cmp) qsort_s(base, nel, size, cmp, arg)
|
|
|
|
# define cmp_bsd_qsort cmp_ms_qsort
|
|
|
|
# define HAVE_BSD_QSORT_R 1
|
|
|
|
#endif
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2018-09-09 03:49:04 -04:00
|
|
|
#if defined HAVE_BSD_QSORT_R
|
2015-09-14 23:44:34 -04:00
|
|
|
struct bsd_qsort_r_args {
|
|
|
|
cmpfunc_t *cmp;
|
|
|
|
void *arg;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
cmp_bsd_qsort(void *d, const void *a, const void *b)
|
|
|
|
{
|
|
|
|
const struct bsd_qsort_r_args *args = d;
|
|
|
|
return (*args->cmp)(a, b, args->arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void *d)
|
|
|
|
{
|
|
|
|
struct bsd_qsort_r_args args;
|
|
|
|
args.cmp = cmp;
|
|
|
|
args.arg = d;
|
|
|
|
qsort_r(base, nel, size, &args, cmp_bsd_qsort);
|
|
|
|
}
|
2018-09-10 00:21:39 -04:00
|
|
|
#elif defined HAVE_QSORT_S
|
|
|
|
/* C11 qsort_s has the same arguments as GNU's, but uses
|
|
|
|
* runtime-constraints handler. */
|
|
|
|
void
|
|
|
|
ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void *d)
|
|
|
|
{
|
|
|
|
if (!nel || !size) return; /* nothing to sort */
|
|
|
|
|
|
|
|
/* get rid of runtime-constraints handler for MT-safeness */
|
|
|
|
if (!base || !cmp) return;
|
|
|
|
if (nel > RSIZE_MAX || size > RSIZE_MAX) return;
|
|
|
|
|
|
|
|
qsort_s(base, nel, size, cmp, d);
|
|
|
|
}
|
|
|
|
# define HAVE_GNU_QSORT_R 1
|
2015-09-14 23:44:34 -04:00
|
|
|
#elif !defined HAVE_GNU_QSORT_R
|
1999-01-19 23:59:39 -05:00
|
|
|
/* mm.c */
|
|
|
|
|
2011-10-19 22:42:26 -04:00
|
|
|
#define mmtype long
|
|
|
|
#define mmcount (16 / SIZEOF_LONG)
|
|
|
|
#define A ((mmtype*)a)
|
|
|
|
#define B ((mmtype*)b)
|
|
|
|
#define C ((mmtype*)c)
|
|
|
|
#define D ((mmtype*)d)
|
|
|
|
|
|
|
|
#define mmstep (sizeof(mmtype) * mmcount)
|
2001-12-10 02:18:16 -05:00
|
|
|
#define mmprepare(base, size) do {\
|
2011-10-19 22:42:26 -04:00
|
|
|
if (((VALUE)(base) % sizeof(mmtype)) == 0 && ((size) % sizeof(mmtype)) == 0) \
|
|
|
|
if ((size) >= mmstep) mmkind = 1;\
|
2011-01-09 21:24:04 -05:00
|
|
|
else mmkind = 0;\
|
|
|
|
else mmkind = -1;\
|
2011-10-19 22:42:26 -04:00
|
|
|
high = ((size) / mmstep) * mmstep;\
|
|
|
|
low = ((size) % mmstep);\
|
2001-12-10 02:18:16 -05:00
|
|
|
} while (0)\
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2001-12-10 02:18:16 -05:00
|
|
|
#define mmarg mmkind, size, high, low
|
2011-10-19 22:42:26 -04:00
|
|
|
#define mmargdecl int mmkind, size_t size, size_t high, size_t low
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2011-10-19 22:42:26 -04:00
|
|
|
static void mmswap_(register char *a, register char *b, mmargdecl)
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
|
|
|
if (a == b) return;
|
|
|
|
if (mmkind >= 0) {
|
2011-10-19 22:42:26 -04:00
|
|
|
register mmtype s;
|
|
|
|
#if mmcount > 1
|
1999-01-19 23:59:39 -05:00
|
|
|
if (mmkind > 0) {
|
|
|
|
register char *t = a + high;
|
|
|
|
do {
|
|
|
|
s = A[0]; A[0] = B[0]; B[0] = s;
|
|
|
|
s = A[1]; A[1] = B[1]; B[1] = s;
|
2011-10-19 22:42:26 -04:00
|
|
|
#if mmcount > 2
|
1999-01-19 23:59:39 -05:00
|
|
|
s = A[2]; A[2] = B[2]; B[2] = s;
|
2011-10-19 22:42:26 -04:00
|
|
|
#if mmcount > 3
|
|
|
|
s = A[3]; A[3] = B[3]; B[3] = s;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
a += mmstep; b += mmstep;
|
1999-08-13 01:45:20 -04:00
|
|
|
} while (a < t);
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2011-10-19 22:42:26 -04:00
|
|
|
#endif
|
1999-01-19 23:59:39 -05:00
|
|
|
if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = s;
|
2011-10-19 22:42:26 -04:00
|
|
|
#if mmcount > 2
|
|
|
|
if (low >= 2 * sizeof(mmtype)) { s = A[1]; A[1] = B[1]; B[1] = s;
|
|
|
|
#if mmcount > 3
|
|
|
|
if (low >= 3 * sizeof(mmtype)) {s = A[2]; A[2] = B[2]; B[2] = s;}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
|
|
|
else {
|
2011-10-19 22:42:26 -04:00
|
|
|
register char *t = a + size, s;
|
1999-01-19 23:59:39 -05:00
|
|
|
do {s = *a; *a++ = *b; *b++ = s;} while (a < t);
|
|
|
|
}
|
|
|
|
}
|
2001-12-10 02:18:16 -05:00
|
|
|
#define mmswap(a,b) mmswap_((a),(b),mmarg)
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2011-10-19 22:42:26 -04:00
|
|
|
/* a, b, c = b, c, a */
|
|
|
|
static void mmrot3_(register char *a, register char *b, register char *c, mmargdecl)
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
|
|
|
if (mmkind >= 0) {
|
2011-10-19 22:42:26 -04:00
|
|
|
register mmtype s;
|
|
|
|
#if mmcount > 1
|
1999-01-19 23:59:39 -05:00
|
|
|
if (mmkind > 0) {
|
|
|
|
register char *t = a + high;
|
|
|
|
do {
|
|
|
|
s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
|
|
|
|
s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
|
2011-10-19 22:42:26 -04:00
|
|
|
#if mmcount > 2
|
1999-01-19 23:59:39 -05:00
|
|
|
s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;
|
2011-10-19 22:42:26 -04:00
|
|
|
#if mmcount > 3
|
|
|
|
s = A[3]; A[3] = B[3]; B[3] = C[3]; C[3] = s;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
a += mmstep; b += mmstep; c += mmstep;
|
2001-05-02 00:22:21 -04:00
|
|
|
} while (a < t);
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2011-10-19 22:42:26 -04:00
|
|
|
#endif
|
1999-01-19 23:59:39 -05:00
|
|
|
if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
|
2011-10-19 22:42:26 -04:00
|
|
|
#if mmcount > 2
|
|
|
|
if (low >= 2 * sizeof(mmtype)) { s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
|
|
|
|
#if mmcount > 3
|
|
|
|
if (low == 3 * sizeof(mmtype)) {s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
|
|
|
else {
|
2011-10-19 22:42:26 -04:00
|
|
|
register char *t = a + size, s;
|
1999-01-19 23:59:39 -05:00
|
|
|
do {s = *a; *a++ = *b; *b++ = *c; *c++ = s;} while (a < t);
|
|
|
|
}
|
|
|
|
}
|
2001-12-10 02:18:16 -05:00
|
|
|
#define mmrot3(a,b,c) mmrot3_((a),(b),(c),mmarg)
|
1999-01-19 23:59:39 -05:00
|
|
|
|
|
|
|
/* qs6.c */
|
|
|
|
/*****************************************************/
|
|
|
|
/* */
|
|
|
|
/* qs6 (Quick sort function) */
|
|
|
|
/* */
|
|
|
|
/* by Tomoyuki Kawamura 1995.4.21 */
|
|
|
|
/* kawamura@tokuyama.ac.jp */
|
|
|
|
/*****************************************************/
|
|
|
|
|
|
|
|
typedef struct { char *LL, *RR; } stack_node; /* Stack structure for L,l,R,r */
|
2002-04-18 04:46:18 -04:00
|
|
|
#define PUSH(ll,rr) do { top->LL = (ll); top->RR = (rr); ++top; } while (0) /* Push L,l,R,r */
|
2011-01-09 21:24:04 -05:00
|
|
|
#define POP(ll,rr) do { --top; (ll) = top->LL; (rr) = top->RR; } while (0) /* Pop L,l,R,r */
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2011-01-09 21:24:04 -05:00
|
|
|
#define med3(a,b,c) ((*cmp)((a),(b),d)<0 ? \
|
|
|
|
((*cmp)((b),(c),d)<0 ? (b) : ((*cmp)((a),(c),d)<0 ? (c) : (a))) : \
|
|
|
|
((*cmp)((b),(c),d)>0 ? (b) : ((*cmp)((a),(c),d)<0 ? (a) : (c))))
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2005-10-11 08:30:48 -04:00
|
|
|
void
|
2011-10-19 22:42:26 -04:00
|
|
|
ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void *d)
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
2001-05-02 00:22:21 -04:00
|
|
|
register char *l, *r, *m; /* l,r:left,right group m:median point */
|
2009-03-14 00:53:13 -04:00
|
|
|
register int t, eq_l, eq_r; /* eq_l: all items in left group are equal to S */
|
2009-11-03 12:46:28 -05:00
|
|
|
char *L = base; /* left end of current region */
|
2001-12-10 02:18:16 -05:00
|
|
|
char *R = (char*)base + size*(nel-1); /* right end of current region */
|
2009-05-26 00:58:15 -04:00
|
|
|
size_t chklim = 63; /* threshold of ordering element check */
|
2013-12-13 21:45:07 -05:00
|
|
|
enum {size_bits = sizeof(size) * CHAR_BIT};
|
|
|
|
stack_node stack[size_bits]; /* enough for size_t size */
|
|
|
|
stack_node *top = stack;
|
2009-03-14 00:53:13 -04:00
|
|
|
int mmkind;
|
|
|
|
size_t high, low, n;
|
2001-05-02 00:22:21 -04:00
|
|
|
|
|
|
|
if (nel <= 1) return; /* need not to sort */
|
|
|
|
mmprepare(base, size);
|
|
|
|
goto start;
|
|
|
|
|
|
|
|
nxt:
|
|
|
|
if (stack == top) return; /* return if stack is empty */
|
|
|
|
POP(L,R);
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
start:
|
2001-12-10 02:18:16 -05:00
|
|
|
if (L + size == R) { /* 2 elements */
|
2021-05-01 09:26:55 -04:00
|
|
|
if ((*cmp)(L,R,d) > 0) mmswap(L,R);
|
|
|
|
goto nxt;
|
2001-12-10 02:18:16 -05:00
|
|
|
}
|
2001-05-02 00:22:21 -04:00
|
|
|
|
|
|
|
l = L; r = R;
|
2009-03-14 00:53:13 -04:00
|
|
|
n = (r - l + size) / size; /* number of elements */
|
|
|
|
m = l + size * (n >> 1); /* calculate median value */
|
2001-05-02 00:22:21 -04:00
|
|
|
|
2009-03-14 00:53:13 -04:00
|
|
|
if (n >= 60) {
|
2001-05-02 00:22:21 -04:00
|
|
|
register char *m1;
|
|
|
|
register char *m3;
|
2009-03-14 00:53:13 -04:00
|
|
|
if (n >= 200) {
|
|
|
|
n = size*(n>>3); /* number of bytes in splitting 8 */
|
2001-05-02 00:22:21 -04:00
|
|
|
{
|
2009-03-14 00:53:13 -04:00
|
|
|
register char *p1 = l + n;
|
|
|
|
register char *p2 = p1 + n;
|
|
|
|
register char *p3 = p2 + n;
|
2001-05-02 00:22:21 -04:00
|
|
|
m1 = med3(p1, p2, p3);
|
2009-03-14 00:53:13 -04:00
|
|
|
p1 = m + n;
|
|
|
|
p2 = p1 + n;
|
|
|
|
p3 = p2 + n;
|
2001-05-02 00:22:21 -04:00
|
|
|
m3 = med3(p1, p2, p3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2009-03-14 00:53:13 -04:00
|
|
|
n = size*(n>>2); /* number of bytes in splitting 4 */
|
|
|
|
m1 = l + n;
|
|
|
|
m3 = m + n;
|
2001-05-02 00:22:21 -04:00
|
|
|
}
|
|
|
|
m = med3(m1, m, m3);
|
|
|
|
}
|
|
|
|
|
2004-09-20 23:08:33 -04:00
|
|
|
if ((t = (*cmp)(l,m,d)) < 0) { /*3-5-?*/
|
|
|
|
if ((t = (*cmp)(m,r,d)) < 0) { /*3-5-7*/
|
2001-05-02 00:22:21 -04:00
|
|
|
if (chklim && nel >= chklim) { /* check if already ascending order */
|
|
|
|
char *p;
|
|
|
|
chklim = 0;
|
2004-09-20 23:08:33 -04:00
|
|
|
for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) > 0) goto fail;
|
2001-05-02 00:22:21 -04:00
|
|
|
goto nxt;
|
|
|
|
}
|
|
|
|
fail: goto loopA; /*3-5-7*/
|
|
|
|
}
|
|
|
|
if (t > 0) {
|
2004-09-20 23:08:33 -04:00
|
|
|
if ((*cmp)(l,r,d) <= 0) {mmswap(m,r); goto loopA;} /*3-5-4*/
|
2001-05-02 00:22:21 -04:00
|
|
|
mmrot3(r,m,l); goto loopA; /*3-5-2*/
|
|
|
|
}
|
|
|
|
goto loopB; /*3-5-5*/
|
|
|
|
}
|
|
|
|
|
|
|
|
if (t > 0) { /*7-5-?*/
|
2004-09-20 23:08:33 -04:00
|
|
|
if ((t = (*cmp)(m,r,d)) > 0) { /*7-5-3*/
|
2001-05-02 00:22:21 -04:00
|
|
|
if (chklim && nel >= chklim) { /* check if already ascending order */
|
|
|
|
char *p;
|
|
|
|
chklim = 0;
|
2004-09-20 23:08:33 -04:00
|
|
|
for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) < 0) goto fail2;
|
2001-05-02 00:22:21 -04:00
|
|
|
while (l<r) {mmswap(l,r); l+=size; r-=size;} /* reverse region */
|
|
|
|
goto nxt;
|
|
|
|
}
|
|
|
|
fail2: mmswap(l,r); goto loopA; /*7-5-3*/
|
|
|
|
}
|
|
|
|
if (t < 0) {
|
2004-09-20 23:08:33 -04:00
|
|
|
if ((*cmp)(l,r,d) <= 0) {mmswap(l,m); goto loopB;} /*7-5-8*/
|
2001-05-02 00:22:21 -04:00
|
|
|
mmrot3(l,m,r); goto loopA; /*7-5-6*/
|
|
|
|
}
|
|
|
|
mmswap(l,r); goto loopA; /*7-5-5*/
|
|
|
|
}
|
|
|
|
|
2004-09-20 23:08:33 -04:00
|
|
|
if ((t = (*cmp)(m,r,d)) < 0) {goto loopA;} /*5-5-7*/
|
2001-05-02 00:22:21 -04:00
|
|
|
if (t > 0) {mmswap(l,r); goto loopB;} /*5-5-3*/
|
|
|
|
|
2001-12-10 02:18:16 -05:00
|
|
|
/* determining splitting type in case 5-5-5 */ /*5-5-5*/
|
2001-05-02 00:22:21 -04:00
|
|
|
for (;;) {
|
|
|
|
if ((l += size) == r) goto nxt; /*5-5-5*/
|
|
|
|
if (l == m) continue;
|
2004-09-20 23:08:33 -04:00
|
|
|
if ((t = (*cmp)(l,m,d)) > 0) {mmswap(l,r); l = L; goto loopA;}/*575-5*/
|
2001-05-02 00:22:21 -04:00
|
|
|
if (t < 0) {mmswap(L,l); l = L; goto loopB;} /*535-5*/
|
|
|
|
}
|
|
|
|
|
|
|
|
loopA: eq_l = 1; eq_r = 1; /* splitting type A */ /* left <= median < right */
|
|
|
|
for (;;) {
|
|
|
|
for (;;) {
|
|
|
|
if ((l += size) == r)
|
|
|
|
{l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;}
|
|
|
|
if (l == m) continue;
|
2004-09-20 23:08:33 -04:00
|
|
|
if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;}
|
2001-05-02 00:22:21 -04:00
|
|
|
if (t < 0) eq_l = 0;
|
|
|
|
}
|
|
|
|
for (;;) {
|
|
|
|
if (l == (r -= size))
|
|
|
|
{l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;}
|
|
|
|
if (r == m) {m = l; break;}
|
2004-09-20 23:08:33 -04:00
|
|
|
if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;}
|
2001-05-02 00:22:21 -04:00
|
|
|
if (t == 0) break;
|
|
|
|
}
|
|
|
|
mmswap(l,r); /* swap left and right */
|
|
|
|
}
|
|
|
|
|
|
|
|
loopB: eq_l = 1; eq_r = 1; /* splitting type B */ /* left < median <= right */
|
|
|
|
for (;;) {
|
|
|
|
for (;;) {
|
|
|
|
if (l == (r -= size))
|
|
|
|
{r += size; if (r != m) mmswap(r,m); r += size; goto fin;}
|
|
|
|
if (r == m) continue;
|
2004-09-20 23:08:33 -04:00
|
|
|
if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;}
|
2001-05-02 00:22:21 -04:00
|
|
|
if (t > 0) eq_r = 0;
|
|
|
|
}
|
|
|
|
for (;;) {
|
|
|
|
if ((l += size) == r)
|
|
|
|
{r += size; if (r != m) mmswap(r,m); r += size; goto fin;}
|
|
|
|
if (l == m) {m = r; break;}
|
2004-09-20 23:08:33 -04:00
|
|
|
if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;}
|
2001-05-02 00:22:21 -04:00
|
|
|
if (t == 0) break;
|
|
|
|
}
|
|
|
|
mmswap(l,r); /* swap left and right */
|
|
|
|
}
|
|
|
|
|
|
|
|
fin:
|
|
|
|
if (eq_l == 0) /* need to sort left side */
|
|
|
|
if (eq_r == 0) /* need to sort right side */
|
|
|
|
if (l-L < R-r) {PUSH(r,R); R = l;} /* sort left side first */
|
|
|
|
else {PUSH(L,l); L = r;} /* sort right side first */
|
|
|
|
else R = l; /* need to sort left side only */
|
|
|
|
else if (eq_r == 0) L = r; /* need to sort right side only */
|
|
|
|
else goto nxt; /* need not to sort both sides */
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
2014-02-08 07:50:28 -05:00
|
|
|
#endif /* HAVE_GNU_QSORT_R */
|
1999-08-13 01:45:20 -04:00
|
|
|
|
2000-07-27 05:49:34 -04:00
|
|
|
char *
|
2005-10-22 01:26:44 -04:00
|
|
|
ruby_strdup(const char *str)
|
2000-07-27 05:49:34 -04:00
|
|
|
{
|
|
|
|
char *tmp;
|
2009-03-14 01:16:03 -04:00
|
|
|
size_t len = strlen(str) + 1;
|
2000-07-27 05:49:34 -04:00
|
|
|
|
|
|
|
tmp = xmalloc(len);
|
|
|
|
memcpy(tmp, str, len);
|
|
|
|
|
|
|
|
return tmp;
|
|
|
|
}
|
2001-11-08 01:43:14 -05:00
|
|
|
|
2012-05-16 22:48:59 -04:00
|
|
|
char *
|
|
|
|
ruby_getcwd(void)
|
|
|
|
{
|
2017-10-23 01:56:25 -04:00
|
|
|
#if defined HAVE_GETCWD
|
2017-05-18 07:29:42 -04:00
|
|
|
# undef RUBY_UNTYPED_DATA_WARNING
|
|
|
|
# define RUBY_UNTYPED_DATA_WARNING 0
|
2014-04-16 04:46:29 -04:00
|
|
|
# if defined NO_GETCWD_MALLOC
|
2017-05-18 07:29:42 -04:00
|
|
|
VALUE guard = Data_Wrap_Struct((VALUE)0, NULL, RUBY_DEFAULT_FREE, NULL);
|
2001-11-08 01:43:14 -05:00
|
|
|
int size = 200;
|
|
|
|
char *buf = xmalloc(size);
|
|
|
|
|
|
|
|
while (!getcwd(buf, size)) {
|
2015-12-23 03:57:48 -05:00
|
|
|
int e = errno;
|
|
|
|
if (e != ERANGE) {
|
* array.c, bignum.c, cont.c, dir.c, dln.c, encoding.c, enumerator.c,
enumerator.c (enumerator_allocate), eval_jump.c, file.c, hash.c,
io.c, load.c, pack.c, proc.c, random.c, re.c, ruby.c, st.c,
string.c, thread.c, thread_pthread.c, time.c, util.c, variable.c,
vm.c, gc.c:
allocated memory objects by xmalloc (ruby_xmalloc) should be
freed by xfree (ruby_xfree).
* ext/curses/curses.c, ext/dbm/dbm.c, ext/digest/digest.c,
ext/gdbm/gdbm.c, ext/json/ext/parser/parser.c,
ext/json/ext/parser/unicode.c, ext/openssl/ossl_cipher.c,
ext/openssl/ossl_hmac.c, ext/openssl/ossl_pkey_ec.c,
ext/sdbm/init.c, ext/strscan/strscan.c, ext/zlib/zlib.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17017 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-06-08 06:01:40 -04:00
|
|
|
xfree(buf);
|
2017-05-18 07:29:42 -04:00
|
|
|
DATA_PTR(guard) = NULL;
|
2015-12-23 03:57:48 -05:00
|
|
|
rb_syserr_fail(e, "getcwd");
|
2004-09-12 10:55:22 -04:00
|
|
|
}
|
2001-11-08 01:43:14 -05:00
|
|
|
size *= 2;
|
2017-05-18 07:29:42 -04:00
|
|
|
DATA_PTR(guard) = buf;
|
2001-11-08 01:43:14 -05:00
|
|
|
buf = xrealloc(buf, size);
|
|
|
|
}
|
2014-04-16 04:46:29 -04:00
|
|
|
# else
|
2017-05-18 07:29:42 -04:00
|
|
|
VALUE guard = Data_Wrap_Struct((VALUE)0, NULL, free, NULL);
|
2014-04-16 04:46:29 -04:00
|
|
|
char *buf, *cwd = getcwd(NULL, 0);
|
2017-05-18 07:29:42 -04:00
|
|
|
DATA_PTR(guard) = cwd;
|
2014-04-16 04:46:29 -04:00
|
|
|
if (!cwd) rb_sys_fail("getcwd");
|
|
|
|
buf = ruby_strdup(cwd); /* allocate by xmalloc */
|
|
|
|
free(cwd);
|
|
|
|
# endif
|
2017-05-18 07:29:42 -04:00
|
|
|
DATA_PTR(RB_GC_GUARD(guard)) = NULL;
|
* gc.c (Init_stack): stack region is far smaller than usual if
pthread is used.
* marshal.c (w_extended): singleton methods should not be checked
when dumping via marshal_dump() or _dump(). [ruby-talk:85909]
* file.c (getcwdofdrv): avoid using getcwd() directly, use
my_getcwd() instead.
* merged NeXT, OpenStep, Rhapsody ports patch from Eric Sunshine
<sunshine@sunshineco.com>. [ruby-core:01596]
* marshal.c (w_object): LINK check earlier than anything else,
i.e. do not dump TYPE_IVAR for already dumped objects.
(ruby-bugs PR#1220)
* eval.c (rb_eval): call "inherited" only when a new class is
generated; not on reopening.
* eval.c (eval): prepend error position in evaluating string to
* configure.in: revived NextStep, OpenStep, and Rhapsody ports which
had become unbuildable; enhanced --enable-fat-binary option so that
it accepts a list of desired architectures (rather than assuming a
fixed list), or defaults to a platform-appropriate list if user does
not provide an explicit list; made the default list of architectures
for MAB (fat binary) more comprehensive; now uses -fno-common even
when building the interpreter (in addition to using it for
extensions), thus allowing the interpreter to be embedded into a
plugin module of an external project (in addition to allowing
embedding directly into an application); added checks for
<netinet/in_systm.h> (needed by `socket' extension) and getcwd(); now
ensures that -I/usr/local/include is employed when extensions'
extconf.rb scripts invoke have_header() since extension checks on
NextStep and OpenStep will fail without it if the desired resource
resides in the /usr/local tree; fixed formatting of --help message.
* Makefile.in: $(LIBRUBY_A) rule now deletes the archive before
invoking $(AR) since `ar' on Apple/NeXT can not "update" MAB archives
(see configure's --enable-fat-binary option); added rule for new
missing/getcwd.c.
* defines.h: fixed endian handling during MAB build (see configure's
--enable-fat-binary option) to ensure that all portions of the
project see the correct WORDS_BIGENDIAN value (some extension modules
were getting the wrong endian setting); added missing constants
GETPGRP_VOID, WNOHANG, WUNTRACED, X_OK, and type pid_t for NextStep
and OpenStep; removed unnecessary and problematic HAVE_SYS_WAIT_H
define in NeXT section.
* dir.c: do not allow NAMLEN() macro to trust dirent::d_namlen on
NextStep since, on some installations, this value always resolves
uselessly to zero.
* dln.c: added error reporting to NextStep extension loader since the
previous behavior of failing silently was not useful; now ensures
that NSLINKMODULE_OPTION_BINDNOW compatibility constant is defined
for OpenStep and Rhapsody; no longer includes <mach-o/dyld.h> twice
on Rhapsody since this header lacks multiple-include protection,
which resulted in "redefinition" compilation errors.
* main.c: also create hard reference to objc_msgSend() on NeXT
platforms (in addition to Apple platforms).
* lib/mkmf.rb: now exports XCFLAGS from configure script to extension
makefiles so that extensions can be built MAB (see configure's
--enable-fat-binary option); also utilize XCFLAGS in cc_command()
(but not cpp_command() because MAB flags are incompatible with
direct invocation of `cpp').
* ext/curses/extconf.rb: now additionally checks for presence of these
curses functions which are not present on NextStep or Openstep:
bkgd(), bkgdset(), color(), curs(), getbkgd(), init(), scrl(), set(),
setscrreg(), wattroff(), wattron(), wattrset(), wbkgd(), wbkgdset(),
wscrl(), wsetscrreg()
* ext/curses/curses.c: added appropriate #ifdef's for additional set of
curses functions now checked by extconf.rb; fixed curses_bkgd() and
window_bkgd() to correctly return boolean result rather than numeric
result; fixed window_getbkgd() to correctly signal an error by
returning nil rather than -1.
* ext/etc/etc.c: setup_passwd() and setup_group() now check for null
pointers before invoking rb_tainted_str_new2() upon fields extracted
from `struct passwd' and `struct group' since null pointers in some
fields are common on NextStep/OpenStep (especially so for the
`pw_comment' field) and rb_tainted_str_new2() throws an exception
when it receives a null pointer.
* ext/pty/pty.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup().
* ext/socket/getaddrinfo.c: cast first argument of getservbyname(),
gethostbyaddr(), and gethostbyname() from (const char*) to non-const
(char*) for older platforms such as NextStep and OpenStep.
* ext/socket/socket.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup(); include
<netinet/in_systm.h> if present for NextStep and OpenStep; cast first
argument of gethostbyaddr() and getservbyname() from (const char*) to
non-const (char*) for older platforms.
* ext/syslog/syslog.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5002 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-11-21 23:00:03 -05:00
|
|
|
#else
|
|
|
|
# ifndef PATH_MAX
|
|
|
|
# define PATH_MAX 8192
|
|
|
|
# endif
|
|
|
|
char *buf = xmalloc(PATH_MAX+1);
|
|
|
|
|
|
|
|
if (!getwd(buf)) {
|
2015-12-23 03:57:48 -05:00
|
|
|
int e = errno;
|
* array.c, bignum.c, cont.c, dir.c, dln.c, encoding.c, enumerator.c,
enumerator.c (enumerator_allocate), eval_jump.c, file.c, hash.c,
io.c, load.c, pack.c, proc.c, random.c, re.c, ruby.c, st.c,
string.c, thread.c, thread_pthread.c, time.c, util.c, variable.c,
vm.c, gc.c:
allocated memory objects by xmalloc (ruby_xmalloc) should be
freed by xfree (ruby_xfree).
* ext/curses/curses.c, ext/dbm/dbm.c, ext/digest/digest.c,
ext/gdbm/gdbm.c, ext/json/ext/parser/parser.c,
ext/json/ext/parser/unicode.c, ext/openssl/ossl_cipher.c,
ext/openssl/ossl_hmac.c, ext/openssl/ossl_pkey_ec.c,
ext/sdbm/init.c, ext/strscan/strscan.c, ext/zlib/zlib.c:
ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17017 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-06-08 06:01:40 -04:00
|
|
|
xfree(buf);
|
2015-12-23 03:57:48 -05:00
|
|
|
rb_syserr_fail(e, "getwd");
|
* gc.c (Init_stack): stack region is far smaller than usual if
pthread is used.
* marshal.c (w_extended): singleton methods should not be checked
when dumping via marshal_dump() or _dump(). [ruby-talk:85909]
* file.c (getcwdofdrv): avoid using getcwd() directly, use
my_getcwd() instead.
* merged NeXT, OpenStep, Rhapsody ports patch from Eric Sunshine
<sunshine@sunshineco.com>. [ruby-core:01596]
* marshal.c (w_object): LINK check earlier than anything else,
i.e. do not dump TYPE_IVAR for already dumped objects.
(ruby-bugs PR#1220)
* eval.c (rb_eval): call "inherited" only when a new class is
generated; not on reopening.
* eval.c (eval): prepend error position in evaluating string to
* configure.in: revived NextStep, OpenStep, and Rhapsody ports which
had become unbuildable; enhanced --enable-fat-binary option so that
it accepts a list of desired architectures (rather than assuming a
fixed list), or defaults to a platform-appropriate list if user does
not provide an explicit list; made the default list of architectures
for MAB (fat binary) more comprehensive; now uses -fno-common even
when building the interpreter (in addition to using it for
extensions), thus allowing the interpreter to be embedded into a
plugin module of an external project (in addition to allowing
embedding directly into an application); added checks for
<netinet/in_systm.h> (needed by `socket' extension) and getcwd(); now
ensures that -I/usr/local/include is employed when extensions'
extconf.rb scripts invoke have_header() since extension checks on
NextStep and OpenStep will fail without it if the desired resource
resides in the /usr/local tree; fixed formatting of --help message.
* Makefile.in: $(LIBRUBY_A) rule now deletes the archive before
invoking $(AR) since `ar' on Apple/NeXT can not "update" MAB archives
(see configure's --enable-fat-binary option); added rule for new
missing/getcwd.c.
* defines.h: fixed endian handling during MAB build (see configure's
--enable-fat-binary option) to ensure that all portions of the
project see the correct WORDS_BIGENDIAN value (some extension modules
were getting the wrong endian setting); added missing constants
GETPGRP_VOID, WNOHANG, WUNTRACED, X_OK, and type pid_t for NextStep
and OpenStep; removed unnecessary and problematic HAVE_SYS_WAIT_H
define in NeXT section.
* dir.c: do not allow NAMLEN() macro to trust dirent::d_namlen on
NextStep since, on some installations, this value always resolves
uselessly to zero.
* dln.c: added error reporting to NextStep extension loader since the
previous behavior of failing silently was not useful; now ensures
that NSLINKMODULE_OPTION_BINDNOW compatibility constant is defined
for OpenStep and Rhapsody; no longer includes <mach-o/dyld.h> twice
on Rhapsody since this header lacks multiple-include protection,
which resulted in "redefinition" compilation errors.
* main.c: also create hard reference to objc_msgSend() on NeXT
platforms (in addition to Apple platforms).
* lib/mkmf.rb: now exports XCFLAGS from configure script to extension
makefiles so that extensions can be built MAB (see configure's
--enable-fat-binary option); also utilize XCFLAGS in cc_command()
(but not cpp_command() because MAB flags are incompatible with
direct invocation of `cpp').
* ext/curses/extconf.rb: now additionally checks for presence of these
curses functions which are not present on NextStep or Openstep:
bkgd(), bkgdset(), color(), curs(), getbkgd(), init(), scrl(), set(),
setscrreg(), wattroff(), wattron(), wattrset(), wbkgd(), wbkgdset(),
wscrl(), wsetscrreg()
* ext/curses/curses.c: added appropriate #ifdef's for additional set of
curses functions now checked by extconf.rb; fixed curses_bkgd() and
window_bkgd() to correctly return boolean result rather than numeric
result; fixed window_getbkgd() to correctly signal an error by
returning nil rather than -1.
* ext/etc/etc.c: setup_passwd() and setup_group() now check for null
pointers before invoking rb_tainted_str_new2() upon fields extracted
from `struct passwd' and `struct group' since null pointers in some
fields are common on NextStep/OpenStep (especially so for the
`pw_comment' field) and rb_tainted_str_new2() throws an exception
when it receives a null pointer.
* ext/pty/pty.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup().
* ext/socket/getaddrinfo.c: cast first argument of getservbyname(),
gethostbyaddr(), and gethostbyname() from (const char*) to non-const
(char*) for older platforms such as NextStep and OpenStep.
* ext/socket/socket.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup(); include
<netinet/in_systm.h> if present for NextStep and OpenStep; cast first
argument of gethostbyaddr() and getservbyname() from (const char*) to
non-const (char*) for older platforms.
* ext/syslog/syslog.c: include "util.h" for strdup()/ruby_strdup() for
platforms such as NextStep and OpenStep which lack strdup().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5002 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-11-21 23:00:03 -05:00
|
|
|
}
|
|
|
|
#endif
|
2001-11-08 01:43:14 -05:00
|
|
|
return buf;
|
|
|
|
}
|
2002-05-14 02:22:31 -04:00
|
|
|
|
2008-02-23 16:13:05 -05:00
|
|
|
void
|
|
|
|
ruby_each_words(const char *str, void (*func)(const char*, int, void*), void *arg)
|
|
|
|
{
|
|
|
|
const char *end;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if (!str) return;
|
|
|
|
for (; *str; str = end) {
|
|
|
|
while (ISSPACE(*str) || *str == ',') str++;
|
|
|
|
if (!*str) break;
|
|
|
|
end = str;
|
|
|
|
while (*end && !ISSPACE(*end) && *end != ',') end++;
|
2009-03-14 04:54:21 -04:00
|
|
|
len = (int)(end - str); /* assume no string exceeds INT_MAX */
|
2008-02-23 16:13:05 -05:00
|
|
|
(*func)(str, len, arg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-07 03:53:11 -05:00
|
|
|
#undef strtod
|
|
|
|
#define strtod ruby_strtod
|
|
|
|
#undef dtoa
|
|
|
|
#define dtoa ruby_dtoa
|
|
|
|
#undef hdtoa
|
|
|
|
#define hdtoa ruby_hdtoa
|
|
|
|
#include "missing/dtoa.c"
|