2000-05-09 08:53:16 +04:00
|
|
|
/**********************************************************************
|
1998-01-16 15:13:05 +03:00
|
|
|
|
|
|
|
ruby.c -
|
|
|
|
|
|
|
|
$Author$
|
|
|
|
created at: Tue Aug 10 12:47:31 JST 1993
|
|
|
|
|
* encoding.c: provide basic features for M17N.
* parse.y: encoding aware parsing.
* parse.y (pragma_encoding): encoding specification pragma.
* parse.y (rb_intern3): encoding specified symbols.
* string.c (rb_str_length): length based on characters.
for older behavior, bytesize method added.
* string.c (rb_str_index_m): index based on characters. rindex as
well.
* string.c (succ_char): encoding aware succeeding string.
* string.c (rb_str_reverse): reverse based on characters.
* string.c (rb_str_inspect): encoding aware string description.
* string.c (rb_str_upcase_bang): encoding aware case conversion.
downcase, capitalize, swapcase as well.
* string.c (rb_str_tr_bang): tr based on characters. delete,
squeeze, tr_s, count as well.
* string.c (rb_str_split_m): split based on characters.
* string.c (rb_str_each_line): encoding aware each_line.
* string.c (rb_str_each_char): added. iteration based on
characters.
* string.c (rb_str_strip_bang): encoding aware whitespace
stripping. lstrip, rstrip as well.
* string.c (rb_str_justify): encoding aware justifying (ljust,
rjust, center).
* string.c (str_encoding): get encoding attribute from a string.
* re.c (rb_reg_initialize): encoding aware regular expression
* sprintf.c (rb_str_format): formatting (i.e. length count) based
on characters.
* io.c (rb_io_getc): getc to return one-character string.
for older behavior, getbyte method added.
* ext/stringio/stringio.c (strio_getc): ditto.
* io.c (rb_io_ungetc): allow pushing arbitrary string at the
current reading point.
* ext/stringio/stringio.c (strio_ungetc): ditto.
* ext/strscan/strscan.c: encoding support.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13261 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-08-25 07:29:39 +04:00
|
|
|
Copyright (C) 1993-2007 Yukihiro Matsumoto
|
2000-05-01 13:42:38 +04:00
|
|
|
Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
|
2000-05-09 08:53:16 +04:00
|
|
|
Copyright (C) 2000 Information-technology Promotion Agency, Japan
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2000-05-09 08:53:16 +04:00
|
|
|
**********************************************************************/
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2020-05-08 12:31:09 +03:00
|
|
|
#include "ruby/internal/config.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
|
|
|
|
#include <ctype.h>
|
1998-01-16 15:13:05 +03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/types.h>
|
2019-12-04 11:16:30 +03:00
|
|
|
|
|
|
|
#ifdef __CYGWIN__
|
|
|
|
# include <windows.h>
|
|
|
|
# include <sys/cygwin.h>
|
|
|
|
#endif
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2023-12-04 04:32:21 +03:00
|
|
|
#if defined(LOAD_RELATIVE) && defined(HAVE_DLADDR)
|
2019-12-04 11:16:30 +03:00
|
|
|
# include <dlfcn.h>
|
2009-03-09 18:06:22 +03:00
|
|
|
#endif
|
1998-01-16 15:13:05 +03:00
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
#ifdef HAVE_UNISTD_H
|
2019-12-04 11:16:30 +03:00
|
|
|
# include <unistd.h>
|
1998-01-16 15:19:22 +03:00
|
|
|
#endif
|
2019-12-04 11:16:30 +03:00
|
|
|
|
2007-09-29 00:29:32 +04:00
|
|
|
#if defined(HAVE_FCNTL_H)
|
2019-12-04 11:16:30 +03:00
|
|
|
# include <fcntl.h>
|
2007-09-29 00:29:32 +04:00
|
|
|
#elif defined(HAVE_SYS_FCNTL_H)
|
2019-12-04 11:16:30 +03:00
|
|
|
# include <sys/fcntl.h>
|
2007-09-29 00:29:32 +04:00
|
|
|
#endif
|
2019-12-04 11:16:30 +03:00
|
|
|
|
2004-03-12 14:19:22 +03:00
|
|
|
#ifdef HAVE_SYS_PARAM_H
|
|
|
|
# include <sys/param.h>
|
|
|
|
#endif
|
2019-12-04 11:16:30 +03:00
|
|
|
|
|
|
|
#include "dln.h"
|
|
|
|
#include "eval_intern.h"
|
|
|
|
#include "internal.h"
|
2022-01-10 17:38:16 +03:00
|
|
|
#include "internal/cmdlineopt.h"
|
2022-10-17 19:27:59 +03:00
|
|
|
#include "internal/cont.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
#include "internal/error.h"
|
|
|
|
#include "internal/file.h"
|
|
|
|
#include "internal/inits.h"
|
|
|
|
#include "internal/io.h"
|
|
|
|
#include "internal/load.h"
|
|
|
|
#include "internal/loadpath.h"
|
|
|
|
#include "internal/missing.h"
|
|
|
|
#include "internal/object.h"
|
2023-04-10 04:53:13 +03:00
|
|
|
#include "internal/thread.h"
|
2023-05-28 14:00:20 +03:00
|
|
|
#include "internal/ruby_parser.h"
|
2020-01-09 17:52:01 +03:00
|
|
|
#include "internal/variable.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
#include "ruby/encoding.h"
|
|
|
|
#include "ruby/thread.h"
|
|
|
|
#include "ruby/util.h"
|
|
|
|
#include "ruby/version.h"
|
Some global variables can be accessed from ractors
Some global variables should be used from non-main Ractors.
[Bug #17268]
```ruby
# ractor-local (derived from created ractor): debug
'$DEBUG' => $DEBUG,
'$-d' => $-d,
# ractor-local (derived from created ractor): verbose
'$VERBOSE' => $VERBOSE,
'$-w' => $-w,
'$-W' => $-W,
'$-v' => $-v,
# process-local (readonly): other commandline parameters
'$-p' => $-p,
'$-l' => $-l,
'$-a' => $-a,
# process-local (readonly): getpid
'$$' => $$,
# thread local: process result
'$?' => $?,
# scope local: match
'$~' => $~.inspect,
'$&' => $&,
'$`' => $`,
'$\'' => $',
'$+' => $+,
'$1' => $1,
# scope local: last line
'$_' => $_,
# scope local: last backtrace
'$@' => $@,
'$!' => $!,
# ractor local: stdin, out, err
'$stdin' => $stdin.inspect,
'$stdout' => $stdout.inspect,
'$stderr' => $stderr.inspect,
```
2020-10-20 04:46:43 +03:00
|
|
|
#include "ruby/internal/error.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
|
2022-10-19 12:45:26 +03:00
|
|
|
#define singlebit_only_p(x) !((x) & ((x)-1))
|
|
|
|
STATIC_ASSERT(Qnil_1bit_from_Qfalse, singlebit_only_p(Qnil^Qfalse));
|
2022-10-20 04:57:40 +03:00
|
|
|
STATIC_ASSERT(Qundef_1bit_from_Qnil, singlebit_only_p(Qundef^Qnil));
|
2022-10-19 12:45:26 +03:00
|
|
|
|
2004-03-12 14:19:22 +03:00
|
|
|
#ifndef MAXPATHLEN
|
|
|
|
# define MAXPATHLEN 1024
|
|
|
|
#endif
|
2015-10-17 07:03:23 +03:00
|
|
|
#ifndef O_ACCMODE
|
|
|
|
# define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
|
|
|
|
#endif
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2022-10-24 19:20:44 +03:00
|
|
|
void Init_ruby_description(ruby_cmdline_options_t *opt);
|
2018-08-10 08:02:35 +03:00
|
|
|
|
1999-01-20 07:59:39 +03:00
|
|
|
#ifndef HAVE_STDLIB_H
|
1998-01-16 15:13:05 +03:00
|
|
|
char *getenv();
|
1999-01-20 07:59:39 +03:00
|
|
|
#endif
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2013-10-14 07:22:24 +04:00
|
|
|
#ifndef DISABLE_RUBYGEMS
|
|
|
|
# define DISABLE_RUBYGEMS 0
|
|
|
|
#endif
|
|
|
|
#if DISABLE_RUBYGEMS
|
2012-11-23 12:31:52 +04:00
|
|
|
#define DEFAULT_RUBYGEMS_ENABLED "disabled"
|
|
|
|
#else
|
|
|
|
#define DEFAULT_RUBYGEMS_ENABLED "enabled"
|
|
|
|
#endif
|
|
|
|
|
2019-12-20 17:05:22 +03:00
|
|
|
void rb_warning_category_update(unsigned int mask, unsigned int bits);
|
|
|
|
|
2016-03-08 18:21:22 +03:00
|
|
|
#define COMMA ,
|
2015-09-23 17:43:45 +03:00
|
|
|
#define FEATURE_BIT(bit) (1U << feature_##bit)
|
2016-03-08 18:21:22 +03:00
|
|
|
#define EACH_FEATURES(X, SEP) \
|
2016-02-07 13:21:27 +03:00
|
|
|
X(gems) \
|
2016-03-08 18:21:22 +03:00
|
|
|
SEP \
|
2021-06-28 07:27:35 +03:00
|
|
|
X(error_highlight) \
|
2021-06-18 11:11:39 +03:00
|
|
|
SEP \
|
2016-02-07 13:21:27 +03:00
|
|
|
X(did_you_mean) \
|
2016-03-08 18:21:22 +03:00
|
|
|
SEP \
|
2022-07-26 23:16:21 +03:00
|
|
|
X(syntax_suggest) \
|
|
|
|
SEP \
|
2016-02-07 13:21:27 +03:00
|
|
|
X(rubyopt) \
|
2016-03-08 18:21:22 +03:00
|
|
|
SEP \
|
2016-02-07 13:21:27 +03:00
|
|
|
X(frozen_string_literal) \
|
2018-07-18 15:45:54 +03:00
|
|
|
SEP \
|
2023-03-07 10:17:25 +03:00
|
|
|
X(rjit) \
|
2020-09-28 14:03:28 +03:00
|
|
|
SEP \
|
2022-01-12 11:53:52 +03:00
|
|
|
X(yjit) \
|
2016-02-07 13:21:27 +03:00
|
|
|
/* END OF FEATURES */
|
2016-03-08 18:21:22 +03:00
|
|
|
#define EACH_DEBUG_FEATURES(X, SEP) \
|
2016-02-09 10:36:27 +03:00
|
|
|
X(frozen_string_literal) \
|
|
|
|
/* END OF DEBUG FEATURES */
|
2016-02-08 04:30:22 +03:00
|
|
|
#define AMBIGUOUS_FEATURE_NAMES 0 /* no ambiguous feature names now */
|
2016-03-08 18:21:22 +03:00
|
|
|
#define DEFINE_FEATURE(bit) feature_##bit
|
|
|
|
#define DEFINE_DEBUG_FEATURE(bit) feature_debug_##bit
|
2015-09-23 17:43:45 +03:00
|
|
|
enum feature_flag_bits {
|
2016-03-08 18:21:22 +03:00
|
|
|
EACH_FEATURES(DEFINE_FEATURE, COMMA),
|
2016-02-09 10:42:21 +03:00
|
|
|
feature_debug_flag_first,
|
2023-03-07 10:15:30 +03:00
|
|
|
#if defined(RJIT_FORCE_ENABLE) || !USE_YJIT
|
2023-03-07 10:17:25 +03:00
|
|
|
DEFINE_FEATURE(jit) = feature_rjit,
|
2022-01-12 11:53:52 +03:00
|
|
|
#else
|
|
|
|
DEFINE_FEATURE(jit) = feature_yjit,
|
|
|
|
#endif
|
2023-03-07 10:17:25 +03:00
|
|
|
feature_jit_mask = FEATURE_BIT(rjit) | FEATURE_BIT(yjit),
|
2022-06-29 19:09:51 +03:00
|
|
|
|
2016-02-09 10:42:21 +03:00
|
|
|
feature_debug_flag_begin = feature_debug_flag_first - 1,
|
2016-03-08 18:21:22 +03:00
|
|
|
EACH_DEBUG_FEATURES(DEFINE_DEBUG_FEATURE, COMMA),
|
2015-09-23 17:43:45 +03:00
|
|
|
feature_flag_count
|
2008-02-24 00:13:05 +03:00
|
|
|
};
|
|
|
|
|
2022-06-29 19:09:51 +03:00
|
|
|
#define MULTI_BITS_P(bits) ((bits) & ((bits) - 1))
|
|
|
|
|
2015-11-25 11:02:29 +03:00
|
|
|
#define DEBUG_BIT(bit) (1U << feature_debug_##bit)
|
|
|
|
|
2008-05-20 07:13:52 +04:00
|
|
|
#define DUMP_BIT(bit) (1U << dump_##bit)
|
2016-03-08 18:21:22 +03:00
|
|
|
#define DEFINE_DUMP(bit) dump_##bit
|
|
|
|
#define EACH_DUMPS(X, SEP) \
|
2016-02-09 11:24:37 +03:00
|
|
|
X(version) \
|
2016-03-08 18:21:22 +03:00
|
|
|
SEP \
|
2016-02-09 11:24:37 +03:00
|
|
|
X(copyright) \
|
2016-03-08 18:21:22 +03:00
|
|
|
SEP \
|
2016-02-09 11:24:37 +03:00
|
|
|
X(usage) \
|
2016-03-08 18:21:22 +03:00
|
|
|
SEP \
|
2016-02-09 11:24:37 +03:00
|
|
|
X(help) \
|
2016-03-08 18:21:22 +03:00
|
|
|
SEP \
|
2016-02-09 11:24:37 +03:00
|
|
|
X(yydebug) \
|
2016-03-08 18:21:22 +03:00
|
|
|
SEP \
|
2016-02-09 11:24:37 +03:00
|
|
|
X(syntax) \
|
2016-03-08 18:21:22 +03:00
|
|
|
SEP \
|
2016-02-09 11:24:37 +03:00
|
|
|
X(parsetree) \
|
2016-03-08 18:21:22 +03:00
|
|
|
SEP \
|
2016-02-09 11:24:37 +03:00
|
|
|
X(parsetree_with_comment) \
|
2016-03-08 18:21:22 +03:00
|
|
|
SEP \
|
2016-02-09 11:24:37 +03:00
|
|
|
X(insns) \
|
2021-08-27 10:19:56 +03:00
|
|
|
SEP \
|
|
|
|
X(insns_without_opt) \
|
2016-02-09 11:24:37 +03:00
|
|
|
/* END OF DUMPS */
|
2008-05-20 07:13:52 +04:00
|
|
|
enum dump_flag_bits {
|
2012-08-09 13:33:49 +04:00
|
|
|
dump_version_v,
|
2022-09-25 15:23:17 +03:00
|
|
|
dump_error_tolerant,
|
2016-03-08 18:21:22 +03:00
|
|
|
EACH_DUMPS(DEFINE_DUMP, COMMA),
|
2022-10-09 10:08:09 +03:00
|
|
|
dump_error_tolerant_bits = (DUMP_BIT(yydebug) |
|
|
|
|
DUMP_BIT(parsetree) |
|
|
|
|
DUMP_BIT(parsetree_with_comment)),
|
2016-12-07 17:39:24 +03:00
|
|
|
dump_exit_bits = (DUMP_BIT(yydebug) | DUMP_BIT(syntax) |
|
|
|
|
DUMP_BIT(parsetree) | DUMP_BIT(parsetree_with_comment) |
|
2024-02-16 06:22:58 +03:00
|
|
|
DUMP_BIT(insns) | DUMP_BIT(insns_without_opt))
|
2008-05-20 07:13:52 +04:00
|
|
|
};
|
|
|
|
|
2019-03-30 17:31:35 +03:00
|
|
|
static inline void
|
|
|
|
rb_feature_set_to(ruby_features_t *feat, unsigned int bit_mask, unsigned int bit_set)
|
|
|
|
{
|
|
|
|
feat->mask |= bit_mask;
|
|
|
|
feat->set = (feat->set & ~bit_mask) | bit_set;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define FEATURE_SET_TO(feat, bit_mask, bit_set) \
|
|
|
|
rb_feature_set_to(&(feat), bit_mask, bit_set)
|
|
|
|
#define FEATURE_SET(feat, bits) FEATURE_SET_TO(feat, bits, bits)
|
2019-12-20 16:50:46 +03:00
|
|
|
#define FEATURE_SET_RESTORE(feat, save) FEATURE_SET_TO(feat, (save).mask, (save).set & (save).mask)
|
2022-06-30 10:04:23 +03:00
|
|
|
#define FEATURE_SET_P(feat, bits) ((feat).set & FEATURE_BIT(bits))
|
2022-06-29 19:09:51 +03:00
|
|
|
#define FEATURE_USED_P(feat, bits) ((feat).mask & FEATURE_BIT(bits))
|
|
|
|
#define FEATURE_SET_BITS(feat) ((feat).set & (feat).mask)
|
2019-03-30 17:31:35 +03:00
|
|
|
|
2016-08-19 13:44:53 +03:00
|
|
|
static void init_ids(ruby_cmdline_options_t *);
|
2008-06-09 08:20:07 +04:00
|
|
|
|
|
|
|
#define src_encoding_index GET_VM()->src_encoding_index
|
|
|
|
|
2015-11-19 08:58:31 +03:00
|
|
|
enum {
|
|
|
|
COMPILATION_FEATURES = (
|
|
|
|
0
|
|
|
|
| FEATURE_BIT(frozen_string_literal)
|
2015-11-25 11:02:29 +03:00
|
|
|
| FEATURE_BIT(debug_frozen_string_literal)
|
2015-11-19 08:58:31 +03:00
|
|
|
),
|
|
|
|
DEFAULT_FEATURES = (
|
2016-02-09 10:42:21 +03:00
|
|
|
(FEATURE_BIT(debug_flag_first)-1)
|
2015-11-19 08:58:31 +03:00
|
|
|
#if DISABLE_RUBYGEMS
|
|
|
|
& ~FEATURE_BIT(gems)
|
|
|
|
#endif
|
|
|
|
& ~FEATURE_BIT(frozen_string_literal)
|
2022-06-29 19:09:51 +03:00
|
|
|
& ~feature_jit_mask
|
2015-11-19 08:58:31 +03:00
|
|
|
)
|
|
|
|
};
|
|
|
|
|
2023-08-10 18:29:32 +03:00
|
|
|
#define BACKTRACE_LENGTH_LIMIT_VALID_P(n) ((n) >= -1)
|
|
|
|
#define OPT_BACKTRACE_LENGTH_LIMIT_VALID_P(opt) \
|
|
|
|
BACKTRACE_LENGTH_LIMIT_VALID_P((opt)->backtrace_length_limit)
|
|
|
|
|
2016-08-19 13:44:53 +03:00
|
|
|
static ruby_cmdline_options_t *
|
|
|
|
cmdline_options_init(ruby_cmdline_options_t *opt)
|
2008-06-09 08:20:07 +04:00
|
|
|
{
|
|
|
|
MEMZERO(opt, *opt, 1);
|
|
|
|
init_ids(opt);
|
|
|
|
opt->src.enc.index = src_encoding_index;
|
2009-05-17 04:47:49 +04:00
|
|
|
opt->ext.enc.index = -1;
|
|
|
|
opt->intern.enc.index = -1;
|
2019-03-30 17:31:35 +03:00
|
|
|
opt->features.set = DEFAULT_FEATURES;
|
2023-03-07 10:15:30 +03:00
|
|
|
#ifdef RJIT_FORCE_ENABLE /* to use with: ./configure cppflags="-DRJIT_FORCE_ENABLE" */
|
2023-03-07 10:17:25 +03:00
|
|
|
opt->features.set |= FEATURE_BIT(rjit);
|
2021-10-01 15:45:02 +03:00
|
|
|
#elif defined(YJIT_FORCE_ENABLE)
|
2021-03-07 02:46:56 +03:00
|
|
|
opt->features.set |= FEATURE_BIT(yjit);
|
2021-09-08 19:47:00 +03:00
|
|
|
#endif
|
2023-08-10 18:29:32 +03:00
|
|
|
opt->backtrace_length_limit = LONG_MIN;
|
2021-10-01 15:45:02 +03:00
|
|
|
|
2008-06-09 08:20:07 +04:00
|
|
|
return opt;
|
|
|
|
}
|
|
|
|
|
2017-10-29 18:51:23 +03:00
|
|
|
static rb_ast_t *load_file(VALUE parser, VALUE fname, VALUE f, int script,
|
2017-05-28 12:49:30 +03:00
|
|
|
ruby_cmdline_options_t *opt);
|
|
|
|
static VALUE open_load_file(VALUE fname_v, int *xflag);
|
2017-01-31 15:54:59 +03:00
|
|
|
static void forbid_setid(const char *, const ruby_cmdline_options_t *);
|
2010-12-28 01:37:59 +03:00
|
|
|
#define forbid_setid(s) forbid_setid((s), opt)
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2007-09-29 01:50:01 +04:00
|
|
|
static struct {
|
2007-09-29 01:47:31 +04:00
|
|
|
int argc;
|
|
|
|
char **argv;
|
|
|
|
} origarg;
|
1998-01-16 15:19:22 +03:00
|
|
|
|
2020-03-27 17:18:42 +03:00
|
|
|
static const char esc_standout[] = "\n\033[1;7m";
|
|
|
|
static const char esc_bold[] = "\033[1m";
|
|
|
|
static const char esc_reset[] = "\033[0m";
|
|
|
|
static const char esc_none[] = "";
|
2023-10-04 16:55:24 +03:00
|
|
|
#define USAGE_INDENT " " /* macro for concatenation */
|
2020-03-27 17:18:42 +03:00
|
|
|
|
2015-05-24 05:20:10 +03:00
|
|
|
static void
|
2023-10-04 16:57:56 +03:00
|
|
|
show_usage_part(const char *str, const unsigned int namelen,
|
|
|
|
const char *str2, const unsigned int secondlen,
|
|
|
|
const char *desc,
|
2023-06-04 17:03:10 +03:00
|
|
|
int help, int highlight, unsigned int w, int columns)
|
2015-05-24 05:20:10 +03:00
|
|
|
{
|
2023-10-04 16:55:24 +03:00
|
|
|
static const int indent_width = (int)rb_strlen_lit(USAGE_INDENT);
|
2020-03-27 17:18:42 +03:00
|
|
|
const char *sb = highlight ? esc_bold : esc_none;
|
|
|
|
const char *se = highlight ? esc_reset : esc_none;
|
2023-06-05 04:09:23 +03:00
|
|
|
unsigned int desclen = (unsigned int)strcspn(desc, "\n");
|
2024-03-13 06:00:38 +03:00
|
|
|
if (!help && desclen > 0 && strchr(".;:", desc[desclen-1])) --desclen;
|
2023-10-04 16:55:24 +03:00
|
|
|
if (help && (namelen + 1 > w) && /* a padding space */
|
|
|
|
(int)(namelen + secondlen + indent_width) >= columns) {
|
|
|
|
printf(USAGE_INDENT "%s" "%.*s" "%s\n", sb, namelen, str, se);
|
|
|
|
if (secondlen > 0) {
|
|
|
|
const int second_end = secondlen;
|
|
|
|
int n = 0;
|
|
|
|
if (str2[n] == ',') n++;
|
|
|
|
if (str2[n] == ' ') n++;
|
|
|
|
printf(USAGE_INDENT "%s" "%.*s" "%s\n", sb, second_end-n, str2+n, se);
|
2023-06-04 17:03:10 +03:00
|
|
|
}
|
2023-10-04 16:55:24 +03:00
|
|
|
printf("%-*s%.*s\n", w + indent_width, USAGE_INDENT, desclen, desc);
|
2023-06-05 04:09:23 +03:00
|
|
|
}
|
|
|
|
else {
|
2023-10-04 16:55:24 +03:00
|
|
|
const int wrap = help && namelen + secondlen >= w;
|
|
|
|
printf(USAGE_INDENT "%s%.*s%-*.*s%s%-*s%.*s\n", sb, namelen, str,
|
|
|
|
(wrap ? 0 : w - namelen),
|
|
|
|
(help ? secondlen : 0), str2, se,
|
|
|
|
(wrap ? (int)(w + rb_strlen_lit("\n" USAGE_INDENT)) : 0),
|
|
|
|
(wrap ? "\n" USAGE_INDENT : ""),
|
2023-06-05 04:09:23 +03:00
|
|
|
desclen, desc);
|
|
|
|
}
|
|
|
|
if (help) {
|
|
|
|
while (desc[desclen]) {
|
2023-10-04 16:55:24 +03:00
|
|
|
desc += desclen + rb_strlen_lit("\n");
|
2023-06-05 04:09:23 +03:00
|
|
|
desclen = (unsigned int)strcspn(desc, "\n");
|
2023-10-04 16:55:24 +03:00
|
|
|
printf("%-*s%.*s\n", w + indent_width, USAGE_INDENT, desclen, desc);
|
2023-06-05 04:09:23 +03:00
|
|
|
}
|
2023-06-04 17:03:10 +03:00
|
|
|
}
|
2015-05-24 05:20:10 +03:00
|
|
|
}
|
|
|
|
|
2023-10-04 16:57:56 +03:00
|
|
|
static void
|
|
|
|
show_usage_line(const struct ruby_opt_message *m,
|
|
|
|
int help, int highlight, unsigned int w, int columns)
|
|
|
|
{
|
|
|
|
const char *str = m->str;
|
|
|
|
const unsigned int namelen = m->namelen, secondlen = m->secondlen;
|
|
|
|
const char *desc = str + namelen + secondlen;
|
|
|
|
show_usage_part(str, namelen - 1, str + namelen, secondlen - 1, desc,
|
|
|
|
help, highlight, w, columns);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ruby_show_usage_line(const char *name, const char *secondary, const char *description,
|
2023-10-04 19:40:08 +03:00
|
|
|
int help, int highlight, unsigned int width, int columns)
|
2023-10-04 16:57:56 +03:00
|
|
|
{
|
|
|
|
unsigned int namelen = (unsigned int)strlen(name);
|
|
|
|
unsigned int secondlen = (secondary ? (unsigned int)strlen(secondary) : 0);
|
|
|
|
show_usage_part(name, namelen, secondary, secondlen,
|
2023-10-04 19:40:08 +03:00
|
|
|
description, help, highlight, width, columns);
|
2023-10-04 16:57:56 +03:00
|
|
|
}
|
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
static void
|
2020-04-12 07:00:27 +03:00
|
|
|
usage(const char *name, int help, int highlight, int columns)
|
1999-08-13 09:45:20 +04:00
|
|
|
{
|
2022-01-10 17:38:16 +03:00
|
|
|
#define M(shortopt, longopt, desc) RUBY_OPT_MESSAGE(shortopt, longopt, desc)
|
|
|
|
|
2022-08-15 20:05:12 +03:00
|
|
|
#if USE_YJIT
|
2021-12-14 03:08:01 +03:00
|
|
|
# define PLATFORM_JIT_OPTION "--yjit"
|
|
|
|
#else
|
2023-03-07 10:17:25 +03:00
|
|
|
# define PLATFORM_JIT_OPTION "--rjit (experimental)"
|
2021-12-14 03:08:01 +03:00
|
|
|
#endif
|
2023-05-31 09:15:59 +03:00
|
|
|
|
|
|
|
/* This message really ought to be max 23 lines.
|
|
|
|
* Removed -h because the user already knows that option. Others? */
|
2022-01-10 17:38:16 +03:00
|
|
|
static const struct ruby_opt_message usage_msg[] = {
|
2024-03-12 22:14:56 +03:00
|
|
|
M("-0[octal]", "", "Set input record separator ($/):\n"
|
|
|
|
"-0 for \\0; -00 for paragraph mode; -0777 for slurp mode."),
|
|
|
|
M("-a", "", "Split each input line ($_) into fields ($F)."),
|
|
|
|
M("-c", "", "Check syntax (no execution)."),
|
|
|
|
M("-Cdirpath", "", "Execute program in specified directory."),
|
|
|
|
M("-d", ", --debug", "Set debugging flag ($DEBUG) to true."),
|
|
|
|
M("-e 'code'", "", "Execute given Ruby code; multiple -e allowed."),
|
|
|
|
M("-Eex[:in]", ", --encoding=ex[:in]", "Set default external and internal encodings."),
|
|
|
|
M("-Fpattern", "", "Set input field separator ($;); used with -a."),
|
|
|
|
M("-i[extension]", "", "Set ARGF in-place mode;\n"
|
|
|
|
"create backup files with given extension."),
|
|
|
|
M("-Idirpath", "", "Add specified directory to load paths ($LOAD_PATH);\n"
|
|
|
|
"multiple -I allowed."),
|
|
|
|
M("-l", "", "Set output record separator ($\\) to $/;\n"
|
|
|
|
"used for line-oriented output."),
|
|
|
|
M("-n", "", "Run program in gets loop."),
|
|
|
|
M("-p", "", "Like -n, with printing added."),
|
|
|
|
M("-rlibrary", "", "Require the given library."),
|
|
|
|
M("-s", "", "Define global variables using switches following program path."),
|
|
|
|
M("-S", "", "Search directories found in the PATH environment variable."),
|
|
|
|
M("-v", "", "Print version; set $VERBOSE to true."),
|
|
|
|
M("-w", "", "Synonym for -W1."),
|
2024-03-13 06:00:38 +03:00
|
|
|
M("-W[level=2|:category]", "", "Set warning flag ($-W):\n"
|
2024-03-12 22:14:56 +03:00
|
|
|
"0 for silent; 1 for moderate; 2 for verbose."),
|
|
|
|
M("-x[dirpath]", "", "Execute Ruby code starting from a #!ruby line."),
|
2024-03-12 23:44:47 +03:00
|
|
|
M("--jit", "", "Enable JIT for the platform; same as " PLATFORM_JIT_OPTION "."),
|
2022-08-15 20:05:12 +03:00
|
|
|
#if USE_YJIT
|
2024-03-12 23:44:47 +03:00
|
|
|
M("--yjit", "", "Enable in-process JIT compiler."),
|
2023-03-08 10:30:49 +03:00
|
|
|
#endif
|
|
|
|
#if USE_RJIT
|
2024-03-12 22:14:56 +03:00
|
|
|
M("--rjit", "", "Enable pure-Ruby JIT compiler (experimental)."),
|
2022-01-12 11:18:01 +03:00
|
|
|
#endif
|
2024-03-12 22:14:56 +03:00
|
|
|
M("-h", "", "Print this help message; use --help for longer message."),
|
2012-11-23 12:31:52 +04:00
|
|
|
};
|
2023-05-31 09:15:59 +03:00
|
|
|
STATIC_ASSERT(usage_msg_size, numberof(usage_msg) < 25);
|
|
|
|
|
2022-01-10 17:38:16 +03:00
|
|
|
static const struct ruby_opt_message help_msg[] = {
|
2024-03-12 22:14:56 +03:00
|
|
|
M("--backtrace-limit=num", "", "Set backtrace limit."),
|
|
|
|
M("--copyright", "", "Print Ruby copyright."),
|
|
|
|
M("--crash-report=template", "", "Set template for crash report file."),
|
|
|
|
M("--disable=features", "", "Disable features; see list below."),
|
|
|
|
M("--dump=items", "", "Dump items; see list below."),
|
|
|
|
M("--enable=features", "", "Enable features; see list below."),
|
|
|
|
M("--external-encoding=encoding", "", "Set default external encoding."),
|
2024-03-13 06:00:38 +03:00
|
|
|
M("--help", "", "Print long help message; use -h for short message."),
|
2024-03-12 22:14:56 +03:00
|
|
|
M("--internal-encoding=encoding", "", "Set default internal encoding."),
|
|
|
|
M("--parser=parser", "", "Set Ruby parser: parse.y or prism."),
|
|
|
|
M("--verbose", "", "Set $VERBOSE to true; ignore input from $stdin."),
|
|
|
|
M("--version", "", "Print Ruby version."),
|
|
|
|
M("-y", ", --yydebug", "Print parser log; backward compatibility not guaranteed."),
|
2017-09-20 08:01:09 +03:00
|
|
|
};
|
2022-01-10 17:38:16 +03:00
|
|
|
static const struct ruby_opt_message dumps[] = {
|
2024-03-12 22:14:56 +03:00
|
|
|
M("insns", "", "Instruction sequences."),
|
|
|
|
M("insns_without_opt", "", "Instruction sequences compiled with no optimization."),
|
|
|
|
M("yydebug(+error-tolerant)", "", "yydebug of yacc parser generator."),
|
|
|
|
M("parsetree(+error-tolerant)", "", "Abstract syntax tree (AST)."),
|
|
|
|
M("parsetree_with_comment(+error-tolerant)", "", "AST with comments."),
|
2012-11-23 12:31:52 +04:00
|
|
|
};
|
2022-01-10 17:38:16 +03:00
|
|
|
static const struct ruby_opt_message features[] = {
|
2024-03-12 22:14:56 +03:00
|
|
|
M("gems", "", "Rubygems (only for debugging, default: "DEFAULT_RUBYGEMS_ENABLED")."),
|
|
|
|
M("error_highlight", "", "error_highlight (default: "DEFAULT_RUBYGEMS_ENABLED")."),
|
|
|
|
M("did_you_mean", "", "did_you_mean (default: "DEFAULT_RUBYGEMS_ENABLED")."),
|
2024-03-12 23:44:47 +03:00
|
|
|
M("syntax_suggest", "", "syntax_suggest (default: "DEFAULT_RUBYGEMS_ENABLED")."),
|
|
|
|
M("rubyopt", "", "RUBYOPT environment variable (default: enabled)."),
|
2024-03-12 22:14:56 +03:00
|
|
|
M("frozen-string-literal", "", "Freeze all string literals (default: disabled)."),
|
2022-08-15 20:05:12 +03:00
|
|
|
#if USE_YJIT
|
2024-03-12 22:14:56 +03:00
|
|
|
M("yjit", "", "In-process JIT compiler (default: disabled)."),
|
2023-03-08 08:16:05 +03:00
|
|
|
#endif
|
|
|
|
#if USE_RJIT
|
2024-03-12 22:14:56 +03:00
|
|
|
M("rjit", "", "Pure-Ruby JIT compiler (experimental, default: disabled)."),
|
2022-01-12 11:18:01 +03:00
|
|
|
#endif
|
2012-11-23 12:31:52 +04:00
|
|
|
};
|
2022-01-10 17:38:16 +03:00
|
|
|
static const struct ruby_opt_message warn_categories[] = {
|
2024-03-12 22:14:56 +03:00
|
|
|
M("deprecated", "", "Deprecated features."),
|
|
|
|
M("experimental", "", "Experimental features."),
|
|
|
|
M("performance", "", "Performance issues."),
|
2019-12-20 17:05:22 +03:00
|
|
|
};
|
2023-03-08 08:16:05 +03:00
|
|
|
#if USE_RJIT
|
2023-03-09 10:14:33 +03:00
|
|
|
extern const struct ruby_opt_message rb_rjit_option_messages[];
|
2022-01-12 11:18:01 +03:00
|
|
|
#endif
|
2015-05-24 05:20:10 +03:00
|
|
|
int i;
|
2020-03-27 17:18:42 +03:00
|
|
|
const char *sb = highlight ? esc_standout+1 : esc_none;
|
|
|
|
const char *se = highlight ? esc_reset : esc_none;
|
2015-05-24 05:20:10 +03:00
|
|
|
const int num = numberof(usage_msg) - (help ? 1 : 0);
|
2020-04-12 07:00:27 +03:00
|
|
|
unsigned int w = (columns > 80 ? (columns - 79) / 2 : 0) + 16;
|
2023-06-04 17:03:10 +03:00
|
|
|
#define SHOW(m) show_usage_line(&(m), help, highlight, w, columns)
|
1999-08-13 09:45:20 +04:00
|
|
|
|
2024-03-12 22:14:56 +03:00
|
|
|
printf("%sUsage:%s %s [options] [--] [filepath] [arguments]\n", sb, se, name);
|
2012-11-23 12:31:52 +04:00
|
|
|
for (i = 0; i < num; ++i)
|
|
|
|
SHOW(usage_msg[i]);
|
|
|
|
|
|
|
|
if (!help) return;
|
|
|
|
|
2020-03-27 17:18:42 +03:00
|
|
|
if (highlight) sb = esc_standout;
|
|
|
|
|
2012-11-23 12:31:52 +04:00
|
|
|
for (i = 0; i < numberof(help_msg); ++i)
|
|
|
|
SHOW(help_msg[i]);
|
2020-03-27 17:18:42 +03:00
|
|
|
printf("%s""Dump List:%s\n", sb, se);
|
2017-09-20 08:01:09 +03:00
|
|
|
for (i = 0; i < numberof(dumps); ++i)
|
|
|
|
SHOW(dumps[i]);
|
2020-03-27 17:18:42 +03:00
|
|
|
printf("%s""Features:%s\n", sb, se);
|
2012-11-23 12:31:52 +04:00
|
|
|
for (i = 0; i < numberof(features); ++i)
|
|
|
|
SHOW(features[i]);
|
2020-03-27 17:18:42 +03:00
|
|
|
printf("%s""Warning categories:%s\n", sb, se);
|
2019-12-20 17:05:22 +03:00
|
|
|
for (i = 0; i < numberof(warn_categories); ++i)
|
|
|
|
SHOW(warn_categories[i]);
|
2022-08-15 20:05:12 +03:00
|
|
|
#if USE_YJIT
|
2022-12-12 23:13:46 +03:00
|
|
|
printf("%s""YJIT options:%s\n", sb, se);
|
2023-10-04 19:34:06 +03:00
|
|
|
rb_yjit_show_usage(help, highlight, w, columns);
|
2022-01-12 11:18:01 +03:00
|
|
|
#endif
|
2023-03-08 08:16:05 +03:00
|
|
|
#if USE_RJIT
|
|
|
|
printf("%s""RJIT options (experimental):%s\n", sb, se);
|
2023-03-09 10:14:33 +03:00
|
|
|
for (i = 0; rb_rjit_option_messages[i].str; ++i)
|
|
|
|
SHOW(rb_rjit_option_messages[i]);
|
2023-03-08 08:16:05 +03:00
|
|
|
#endif
|
1999-08-13 09:45:20 +04:00
|
|
|
}
|
|
|
|
|
2014-04-16 12:46:31 +04:00
|
|
|
#define rubylib_path_new rb_str_new
|
1999-08-13 09:45:20 +04:00
|
|
|
|
2007-07-26 08:38:07 +04:00
|
|
|
static void
|
|
|
|
push_include(const char *path, VALUE (*filter)(VALUE))
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
1999-08-13 09:45:20 +04:00
|
|
|
const char sep = PATH_SEP_CHAR;
|
2007-07-26 08:38:07 +04:00
|
|
|
const char *p, *s;
|
2008-04-30 13:03:03 +04:00
|
|
|
VALUE load_path = GET_VM()->load_path;
|
1999-01-20 07:59:39 +03:00
|
|
|
|
2007-07-26 08:38:07 +04:00
|
|
|
p = path;
|
|
|
|
while (*p) {
|
|
|
|
while (*p == sep)
|
|
|
|
p++;
|
|
|
|
if (!*p) break;
|
|
|
|
for (s = p; *s && *s != sep; s = CharNext(s));
|
2014-04-16 12:46:31 +04:00
|
|
|
rb_ary_push(load_path, (*filter)(rubylib_path_new(p, s - p)));
|
2007-07-26 08:38:07 +04:00
|
|
|
p = s;
|
1999-01-20 07:59:39 +03:00
|
|
|
}
|
2007-07-26 08:38:07 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef __CYGWIN__
|
|
|
|
static void
|
|
|
|
push_include_cygwin(const char *path, VALUE (*filter)(VALUE))
|
|
|
|
{
|
|
|
|
const char *p, *s;
|
|
|
|
char rubylib[FILENAME_MAX];
|
|
|
|
VALUE buf = 0;
|
|
|
|
|
|
|
|
p = path;
|
|
|
|
while (*p) {
|
|
|
|
unsigned int len;
|
|
|
|
while (*p == ';')
|
|
|
|
p++;
|
|
|
|
if (!*p) break;
|
|
|
|
for (s = p; *s && *s != ';'; s = CharNext(s));
|
|
|
|
len = s - p;
|
|
|
|
if (*s) {
|
|
|
|
if (!buf) {
|
|
|
|
buf = rb_str_new(p, len);
|
|
|
|
p = RSTRING_PTR(buf);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
else {
|
2007-07-26 08:38:07 +04:00
|
|
|
rb_str_resize(buf, len);
|
|
|
|
p = strncpy(RSTRING_PTR(buf), p, len);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
2010-11-11 15:24:41 +03:00
|
|
|
#ifdef HAVE_CYGWIN_CONV_PATH
|
|
|
|
#define CONV_TO_POSIX_PATH(p, lib) \
|
2010-12-28 01:37:59 +03:00
|
|
|
cygwin_conv_path(CCP_WIN_A_TO_POSIX|CCP_RELATIVE, (p), (lib), sizeof(lib))
|
2010-11-11 15:24:41 +03:00
|
|
|
#else
|
2014-04-17 12:24:15 +04:00
|
|
|
# error no cygwin_conv_path
|
2010-11-11 15:24:41 +03:00
|
|
|
#endif
|
|
|
|
if (CONV_TO_POSIX_PATH(p, rubylib) == 0)
|
2007-07-26 08:38:07 +04:00
|
|
|
p = rubylib;
|
|
|
|
push_include(p, filter);
|
|
|
|
if (!*s) break;
|
|
|
|
p = s + 1;
|
2000-08-01 13:25:37 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-26 08:38:07 +04:00
|
|
|
#define push_include push_include_cygwin
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void
|
|
|
|
ruby_push_include(const char *path, VALUE (*filter)(VALUE))
|
|
|
|
{
|
|
|
|
if (path == 0)
|
|
|
|
return;
|
|
|
|
push_include(path, filter);
|
|
|
|
}
|
|
|
|
|
2005-04-21 01:44:20 +04:00
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
identical_path(VALUE path)
|
2005-04-21 01:44:20 +04:00
|
|
|
{
|
|
|
|
return path;
|
|
|
|
}
|
2008-12-15 05:32:21 +03:00
|
|
|
static VALUE
|
|
|
|
locale_path(VALUE path)
|
|
|
|
{
|
|
|
|
rb_enc_associate(path, rb_locale_encoding());
|
|
|
|
return path;
|
|
|
|
}
|
2005-04-21 01:44:20 +04:00
|
|
|
|
2007-07-26 08:38:07 +04:00
|
|
|
void
|
2005-04-21 01:44:20 +04:00
|
|
|
ruby_incpush(const char *path)
|
|
|
|
{
|
2008-12-15 05:32:21 +03:00
|
|
|
ruby_push_include(path, locale_path);
|
2005-04-21 01:44:20 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
expand_include_path(VALUE path)
|
2005-04-21 01:44:20 +04:00
|
|
|
{
|
2006-08-31 14:47:44 +04:00
|
|
|
char *p = RSTRING_PTR(path);
|
2006-12-31 18:02:22 +03:00
|
|
|
if (!p)
|
|
|
|
return path;
|
|
|
|
if (*p == '.' && p[1] == '/')
|
|
|
|
return path;
|
2005-04-21 01:44:20 +04:00
|
|
|
return rb_file_expand_path(path, Qnil);
|
|
|
|
}
|
|
|
|
|
2009-01-21 07:59:20 +03:00
|
|
|
void
|
2005-04-21 01:44:20 +04:00
|
|
|
ruby_incpush_expand(const char *path)
|
|
|
|
{
|
|
|
|
ruby_push_include(path, expand_include_path);
|
|
|
|
}
|
|
|
|
|
2014-11-29 10:53:17 +03:00
|
|
|
#undef UTF8_PATH
|
2007-05-18 06:11:42 +04:00
|
|
|
#if defined _WIN32 || defined __CYGWIN__
|
|
|
|
static HMODULE libruby;
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved)
|
|
|
|
{
|
|
|
|
if (reason == DLL_PROCESS_ATTACH)
|
|
|
|
libruby = dll;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2009-03-02 05:01:48 +03:00
|
|
|
|
|
|
|
HANDLE
|
|
|
|
rb_libruby_handle(void)
|
|
|
|
{
|
|
|
|
return libruby;
|
|
|
|
}
|
2014-11-29 10:53:17 +03:00
|
|
|
|
2014-11-29 18:02:25 +03:00
|
|
|
static inline void
|
|
|
|
translit_char_bin(char *p, int from, int to)
|
|
|
|
{
|
|
|
|
while (*p) {
|
|
|
|
if ((unsigned char)*p == from)
|
|
|
|
*p = to;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
2016-04-23 03:03:37 +03:00
|
|
|
#endif
|
2014-11-29 18:02:25 +03:00
|
|
|
|
2016-04-23 03:03:37 +03:00
|
|
|
#ifdef _WIN32
|
2014-11-29 10:53:17 +03:00
|
|
|
# define UTF8_PATH 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef UTF8_PATH
|
|
|
|
# define UTF8_PATH 0
|
2007-05-18 06:11:42 +04:00
|
|
|
#endif
|
2016-06-02 11:05:21 +03:00
|
|
|
#if UTF8_PATH
|
|
|
|
# define IF_UTF8_PATH(t, f) t
|
|
|
|
#else
|
|
|
|
# define IF_UTF8_PATH(t, f) f
|
|
|
|
#endif
|
2007-05-18 06:11:42 +04:00
|
|
|
|
2014-11-29 18:02:58 +03:00
|
|
|
#if UTF8_PATH
|
|
|
|
static VALUE
|
|
|
|
str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
|
|
|
|
{
|
|
|
|
return rb_str_conv_enc_opts(str, from, to,
|
|
|
|
ECONV_UNDEF_REPLACE|ECONV_INVALID_REPLACE,
|
|
|
|
Qnil);
|
|
|
|
}
|
2017-05-17 07:47:05 +03:00
|
|
|
#else
|
|
|
|
# define str_conv_enc(str, from, to) (str)
|
2014-11-29 18:02:58 +03:00
|
|
|
#endif
|
|
|
|
|
2019-09-21 05:06:22 +03:00
|
|
|
void ruby_init_loadpath(void);
|
2008-10-31 02:16:16 +03:00
|
|
|
|
2023-12-04 04:32:21 +03:00
|
|
|
#if defined(LOAD_RELATIVE)
|
2015-01-24 15:24:27 +03:00
|
|
|
static VALUE
|
2018-05-21 15:24:47 +03:00
|
|
|
runtime_libruby_path(void)
|
2015-01-24 15:24:27 +03:00
|
|
|
{
|
2018-05-21 15:24:47 +03:00
|
|
|
#if defined _WIN32 || defined __CYGWIN__
|
2023-04-05 00:30:06 +03:00
|
|
|
DWORD ret;
|
|
|
|
DWORD len = 32;
|
2018-05-21 15:24:47 +03:00
|
|
|
VALUE path;
|
|
|
|
VALUE wsopath = rb_str_new(0, len*sizeof(WCHAR));
|
|
|
|
WCHAR *wlibpath;
|
|
|
|
char *libpath;
|
|
|
|
|
|
|
|
while (wlibpath = (WCHAR *)RSTRING_PTR(wsopath),
|
|
|
|
ret = GetModuleFileNameW(libruby, wlibpath, len),
|
|
|
|
(ret == len))
|
|
|
|
{
|
|
|
|
rb_str_modify_expand(wsopath, len*sizeof(WCHAR));
|
|
|
|
rb_str_set_len(wsopath, (len += len)*sizeof(WCHAR));
|
|
|
|
}
|
|
|
|
if (!ret || ret > len) rb_fatal("failed to get module file name");
|
|
|
|
#if defined __CYGWIN__
|
|
|
|
{
|
|
|
|
const int win_to_posix = CCP_WIN_W_TO_POSIX | CCP_RELATIVE;
|
|
|
|
size_t newsize = cygwin_conv_path(win_to_posix, wlibpath, 0, 0);
|
|
|
|
if (!newsize) rb_fatal("failed to convert module path to cygwin");
|
|
|
|
path = rb_str_new(0, newsize);
|
|
|
|
libpath = RSTRING_PTR(path);
|
|
|
|
if (cygwin_conv_path(win_to_posix, wlibpath, libpath, newsize)) {
|
|
|
|
rb_str_resize(path, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
{
|
|
|
|
DWORD i;
|
|
|
|
for (len = ret, i = 0; i < len; ++i) {
|
|
|
|
if (wlibpath[i] == L'\\') {
|
|
|
|
wlibpath[i] = L'/';
|
|
|
|
ret = i+1; /* chop after the last separator */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
len = WideCharToMultiByte(CP_UTF8, 0, wlibpath, ret, NULL, 0, NULL, NULL);
|
|
|
|
path = rb_utf8_str_new(0, len);
|
|
|
|
libpath = RSTRING_PTR(path);
|
|
|
|
WideCharToMultiByte(CP_UTF8, 0, wlibpath, ret, libpath, len, NULL, NULL);
|
|
|
|
#endif
|
|
|
|
rb_str_resize(wsopath, 0);
|
|
|
|
return path;
|
|
|
|
#elif defined(HAVE_DLADDR)
|
2015-01-24 15:24:27 +03:00
|
|
|
Dl_info dli;
|
|
|
|
VALUE fname, path;
|
2018-05-21 15:24:47 +03:00
|
|
|
const void* addr = (void *)(VALUE)expand_include_path;
|
2015-01-24 15:24:27 +03:00
|
|
|
|
2018-07-26 12:34:30 +03:00
|
|
|
if (!dladdr((void *)addr, &dli)) {
|
2015-01-24 15:24:27 +03:00
|
|
|
return rb_str_new(0, 0);
|
|
|
|
}
|
|
|
|
#ifdef __linux__
|
2017-08-09 14:03:55 +03:00
|
|
|
else if (origarg.argc > 0 && origarg.argv && dli.dli_fname == origarg.argv[0]) {
|
2015-01-24 15:24:27 +03:00
|
|
|
fname = rb_str_new_cstr("/proc/self/exe");
|
2015-09-05 17:00:15 +03:00
|
|
|
path = rb_readlink(fname, NULL);
|
2015-01-24 15:24:27 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
else {
|
|
|
|
fname = rb_str_new_cstr(dli.dli_fname);
|
|
|
|
path = rb_realpath_internal(Qnil, fname, 1);
|
|
|
|
}
|
|
|
|
rb_str_resize(fname, 0);
|
|
|
|
return path;
|
2018-05-21 15:24:47 +03:00
|
|
|
#else
|
|
|
|
# error relative load path is not supported on this platform.
|
|
|
|
#endif
|
2015-01-24 15:24:27 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-07-02 08:12:04 +03:00
|
|
|
#define INITIAL_LOAD_PATH_MARK rb_intern_const("@gem_prelude_index")
|
|
|
|
|
2018-04-27 05:02:29 +03:00
|
|
|
VALUE ruby_archlibdir_path, ruby_prefix_path;
|
|
|
|
|
2008-10-31 02:16:16 +03:00
|
|
|
void
|
2019-09-21 05:06:22 +03:00
|
|
|
ruby_init_loadpath(void)
|
2000-08-01 13:25:37 +04:00
|
|
|
{
|
2018-04-27 08:20:40 +03:00
|
|
|
VALUE load_path, archlibdir = 0;
|
|
|
|
ID id_initial_load_path_mark;
|
|
|
|
const char *paths = ruby_initial_load_paths;
|
2022-07-30 14:26:57 +03:00
|
|
|
|
2018-04-27 08:20:40 +03:00
|
|
|
#if defined LOAD_RELATIVE
|
2018-04-27 07:36:34 +03:00
|
|
|
#if !defined ENABLE_MULTIARCH
|
|
|
|
# define RUBY_ARCH_PATH ""
|
|
|
|
#elif defined RUBY_ARCH
|
|
|
|
# define RUBY_ARCH_PATH "/"RUBY_ARCH
|
|
|
|
#else
|
|
|
|
# define RUBY_ARCH_PATH "/"RUBY_PLATFORM
|
|
|
|
#endif
|
2009-05-17 04:02:58 +04:00
|
|
|
char *libpath;
|
|
|
|
VALUE sopath;
|
2009-10-18 13:32:02 +04:00
|
|
|
size_t baselen;
|
2018-04-26 15:36:26 +03:00
|
|
|
const char *p;
|
2007-05-18 06:11:42 +04:00
|
|
|
|
2023-12-04 04:32:21 +03:00
|
|
|
sopath = runtime_libruby_path();
|
2009-08-27 08:55:55 +04:00
|
|
|
libpath = RSTRING_PTR(sopath);
|
2001-02-09 17:11:23 +03:00
|
|
|
|
|
|
|
p = strrchr(libpath, '/');
|
2000-08-03 13:50:41 +04:00
|
|
|
if (p) {
|
2018-05-21 15:25:45 +03:00
|
|
|
static const char libdir[] = "/"
|
|
|
|
#ifdef LIBDIR_BASENAME
|
|
|
|
LIBDIR_BASENAME
|
|
|
|
#else
|
|
|
|
"lib"
|
|
|
|
#endif
|
|
|
|
RUBY_ARCH_PATH;
|
|
|
|
const ptrdiff_t libdir_len = (ptrdiff_t)sizeof(libdir)
|
|
|
|
- rb_strlen_lit(RUBY_ARCH_PATH) - 1;
|
2012-08-29 09:59:05 +04:00
|
|
|
static const char bindir[] = "/bin";
|
|
|
|
const ptrdiff_t bindir_len = (ptrdiff_t)sizeof(bindir) - 1;
|
2013-02-21 07:45:07 +04:00
|
|
|
|
2018-04-26 15:36:26 +03:00
|
|
|
const char *p2 = NULL;
|
2013-02-21 07:45:07 +04:00
|
|
|
|
2018-04-27 05:02:29 +03:00
|
|
|
#ifdef ENABLE_MULTIARCH
|
2013-02-21 07:45:07 +04:00
|
|
|
multiarch:
|
|
|
|
#endif
|
|
|
|
if (p - libpath >= bindir_len && !STRNCASECMP(p - bindir_len, bindir, bindir_len)) {
|
2012-08-29 09:59:05 +04:00
|
|
|
p -= bindir_len;
|
2018-04-27 05:02:29 +03:00
|
|
|
archlibdir = rb_str_subseq(sopath, 0, p - libpath);
|
|
|
|
rb_str_cat_cstr(archlibdir, libdir);
|
|
|
|
OBJ_FREEZE_RAW(archlibdir);
|
2012-08-29 09:59:05 +04:00
|
|
|
}
|
2013-02-21 07:45:07 +04:00
|
|
|
else if (p - libpath >= libdir_len && !strncmp(p - libdir_len, libdir, libdir_len)) {
|
2018-04-27 05:02:29 +03:00
|
|
|
archlibdir = rb_str_subseq(sopath, 0, (p2 ? p2 : p) - libpath);
|
|
|
|
OBJ_FREEZE_RAW(archlibdir);
|
2012-08-29 09:59:05 +04:00
|
|
|
p -= libdir_len;
|
2000-08-03 13:50:41 +04:00
|
|
|
}
|
2013-02-21 07:45:07 +04:00
|
|
|
#ifdef ENABLE_MULTIARCH
|
|
|
|
else if (p2) {
|
|
|
|
p = p2;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
p2 = p;
|
|
|
|
p = rb_enc_path_last_separator(libpath, p, rb_ascii8bit_encoding());
|
|
|
|
if (p) goto multiarch;
|
|
|
|
p = p2;
|
|
|
|
}
|
|
|
|
#endif
|
2021-03-05 18:45:56 +03:00
|
|
|
baselen = p - libpath;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
baselen = 0;
|
2000-08-03 13:50:41 +04:00
|
|
|
}
|
2010-08-05 09:12:50 +04:00
|
|
|
rb_str_resize(sopath, baselen);
|
2010-08-02 16:51:18 +04:00
|
|
|
libpath = RSTRING_PTR(sopath);
|
2010-03-12 01:15:11 +03:00
|
|
|
#define PREFIX_PATH() sopath
|
2009-10-18 13:32:02 +04:00
|
|
|
#define BASEPATH() rb_str_buf_cat(rb_str_buf_new(baselen+len), libpath, baselen)
|
2010-12-28 01:37:59 +03:00
|
|
|
#define RUBY_RELATIVE(path, len) rb_str_buf_cat(BASEPATH(), (path), (len))
|
2000-08-03 13:50:41 +04:00
|
|
|
#else
|
2013-02-18 05:11:58 +04:00
|
|
|
const size_t exec_prefix_len = strlen(ruby_exec_prefix);
|
2014-04-16 12:46:31 +04:00
|
|
|
#define RUBY_RELATIVE(path, len) rubylib_path_new((path), (len))
|
2013-02-18 05:11:58 +04:00
|
|
|
#define PREFIX_PATH() RUBY_RELATIVE(ruby_exec_prefix, exec_prefix_len)
|
2000-08-03 13:50:41 +04:00
|
|
|
#endif
|
2018-04-27 05:02:29 +03:00
|
|
|
rb_gc_register_address(&ruby_prefix_path);
|
|
|
|
ruby_prefix_path = PREFIX_PATH();
|
|
|
|
OBJ_FREEZE_RAW(ruby_prefix_path);
|
|
|
|
if (!archlibdir) archlibdir = ruby_prefix_path;
|
|
|
|
rb_gc_register_address(&ruby_archlibdir_path);
|
|
|
|
ruby_archlibdir_path = archlibdir;
|
|
|
|
|
2008-04-30 13:03:03 +04:00
|
|
|
load_path = GET_VM()->load_path;
|
2000-08-03 13:50:41 +04:00
|
|
|
|
2019-09-21 05:06:22 +03:00
|
|
|
ruby_push_include(getenv("RUBYLIB"), identical_path);
|
2000-08-01 13:25:37 +04:00
|
|
|
|
2015-07-02 08:12:04 +03:00
|
|
|
id_initial_load_path_mark = INITIAL_LOAD_PATH_MARK;
|
2009-02-05 05:21:37 +03:00
|
|
|
while (*paths) {
|
2009-05-17 04:02:58 +04:00
|
|
|
size_t len = strlen(paths);
|
2010-03-12 18:11:10 +03:00
|
|
|
VALUE path = RUBY_RELATIVE(paths, len);
|
|
|
|
rb_ivar_set(path, id_initial_load_path_mark, path);
|
|
|
|
rb_ary_push(load_path, path);
|
2009-03-09 22:56:46 +03:00
|
|
|
paths += len + 1;
|
2009-02-05 05:21:37 +03:00
|
|
|
}
|
2010-03-12 01:15:11 +03:00
|
|
|
|
2018-04-27 05:02:29 +03:00
|
|
|
rb_const_set(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"), ruby_prefix_path);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2009-05-17 04:47:49 +04:00
|
|
|
add_modules(VALUE *req_list, const char *mod)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2009-05-17 04:47:49 +04:00
|
|
|
VALUE list = *req_list;
|
2012-08-23 11:46:12 +04:00
|
|
|
VALUE feature;
|
2008-06-09 08:20:07 +04:00
|
|
|
|
|
|
|
if (!list) {
|
2022-07-25 17:40:45 +03:00
|
|
|
*req_list = list = rb_ary_hidden_new(0);
|
2008-06-09 08:20:07 +04:00
|
|
|
}
|
2018-06-12 02:33:35 +03:00
|
|
|
feature = rb_str_cat_cstr(rb_str_tmp_new(0), mod);
|
2012-08-23 11:46:12 +04:00
|
|
|
rb_ary_push(list, feature);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
* intern.h: add prototypes.
rb_gc_enable(), rb_gc_disable(), rb_gc_start(), rb_str_new5()
rb_str_buf_append(), rb_str_buf_cat(), rb_str_buf_cat2(),
rb_str_dup_frozen()
* ruby.h: added declaration.
rb_defout, rb_stdin, rb_stdout, rb_stderr, ruby_errinfo
* rubyio.h: changed double include guard macro to RUBYIO_H.
* array.c (inspect_call): make static.
* eval.c (dvar_asgn): ditto.
* io.c (rb_io_close_read): ditto.
* lex.c (rb_reserved_word): ditto.
* ruby.c: (req_list_head, req_list_last): ditto.
* ruby.c (require_libraries): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1915 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2001-12-17 10:52:35 +03:00
|
|
|
static void
|
2009-05-17 04:47:49 +04:00
|
|
|
require_libraries(VALUE *req_list)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2009-05-17 04:47:49 +04:00
|
|
|
VALUE list = *req_list;
|
2011-02-11 06:06:50 +03:00
|
|
|
VALUE self = rb_vm_top_self();
|
2011-03-23 02:05:53 +03:00
|
|
|
ID require;
|
2012-08-23 11:46:12 +04:00
|
|
|
rb_encoding *extenc = rb_default_external_encoding();
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2008-06-09 13:25:32 +04:00
|
|
|
CONST_ID(require, "require");
|
2008-06-09 10:40:02 +04:00
|
|
|
while (list && RARRAY_LEN(list) > 0) {
|
2008-06-09 08:20:07 +04:00
|
|
|
VALUE feature = rb_ary_shift(list);
|
2012-08-23 11:46:12 +04:00
|
|
|
rb_enc_associate(feature, extenc);
|
* include/ruby/ruby.h: constify RBasic::klass and add
RBASIC_CLASS(obj) macro which returns a class of `obj'.
This change is a part of RGENGC branch [ruby-trunk - Feature #8339].
* object.c: add new function rb_obj_reveal().
This function reveal interal (hidden) object by rb_obj_hide().
Note that do not change class before and after hiding.
Only permitted example is:
klass = RBASIC_CLASS(obj);
rb_obj_hide(obj);
....
rb_obj_reveal(obj, klass);
TODO: API design. rb_obj_reveal() should be replaced with others.
TODO: modify constified variables using cast may be harmful for
compiler's analysis and optimizaton.
Any idea to prohibt inserting RBasic::klass directly?
If rename RBasic::klass and force to use RBASIC_CLASS(obj),
then all codes such as `RBASIC(obj)->klass' will be
compilation error. Is it acceptable? (We have similar
experience at Ruby 1.9,
for example "RARRAY(ary)->ptr" to "RARRAY_PTR(ary)".
* internal.h: add some macros.
* RBASIC_CLEAR_CLASS(obj) clear RBasic::klass to make it internal
object.
* RBASIC_SET_CLASS(obj, cls) set RBasic::klass.
* RBASIC_SET_CLASS_RAW(obj, cls) same as RBASIC_SET_CLASS
without write barrier (planned).
* RCLASS_SET_SUPER(a, b) set super class of a.
* array.c, class.c, compile.c, encoding.c, enum.c, error.c, eval.c,
file.c, gc.c, hash.c, io.c, iseq.c, marshal.c, object.c,
parse.y, proc.c, process.c, random.c, ruby.c, sprintf.c,
string.c, thread.c, transcode.c, vm.c, vm_eval.c, win32/file.c:
Use above macros and functions to access RBasic::klass.
* ext/coverage/coverage.c, ext/readline/readline.c,
ext/socket/ancdata.c, ext/socket/init.c,
* ext/zlib/zlib.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-05-13 14:49:11 +04:00
|
|
|
RBASIC_SET_CLASS_RAW(feature, rb_cString);
|
2012-08-23 11:46:12 +04:00
|
|
|
OBJ_FREEZE(feature);
|
2016-07-29 14:57:14 +03:00
|
|
|
rb_funcallv(self, require, 1, &feature);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2009-05-17 04:47:49 +04:00
|
|
|
*req_list = 0;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2016-07-28 14:02:30 +03:00
|
|
|
static const struct rb_block*
|
2016-03-29 00:39:24 +03:00
|
|
|
toplevel_context(rb_binding_t *bind)
|
2012-06-14 06:22:08 +04:00
|
|
|
{
|
2016-07-28 14:02:30 +03:00
|
|
|
return &bind->block;
|
2012-06-14 06:22:08 +04:00
|
|
|
}
|
|
|
|
|
2023-07-13 10:58:48 +03:00
|
|
|
static int
|
|
|
|
process_sflag(int sflag)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2023-07-13 10:58:48 +03:00
|
|
|
if (sflag > 0) {
|
2002-08-21 19:47:54 +04:00
|
|
|
long n;
|
2013-11-08 06:37:47 +04:00
|
|
|
const VALUE *args;
|
2008-03-01 11:59:04 +03:00
|
|
|
VALUE argv = rb_argv;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2008-03-01 11:59:04 +03:00
|
|
|
n = RARRAY_LEN(argv);
|
2013-11-08 06:37:47 +04:00
|
|
|
args = RARRAY_CONST_PTR(argv);
|
1999-12-02 09:58:52 +03:00
|
|
|
while (n > 0) {
|
2001-05-02 08:22:21 +04:00
|
|
|
VALUE v = *args++;
|
|
|
|
char *s = StringValuePtr(v);
|
1999-10-15 12:52:18 +04:00
|
|
|
char *p;
|
2009-09-13 15:18:51 +04:00
|
|
|
int hyphen = FALSE;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
if (s[0] != '-')
|
|
|
|
break;
|
1999-12-02 09:58:52 +03:00
|
|
|
n--;
|
2006-12-31 18:02:22 +03:00
|
|
|
if (s[1] == '-' && s[2] == '\0')
|
|
|
|
break;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2005-05-01 04:13:48 +04:00
|
|
|
v = Qtrue;
|
|
|
|
/* check if valid name before replacing - with _ */
|
|
|
|
for (p = s + 1; *p; p++) {
|
|
|
|
if (*p == '=') {
|
|
|
|
*p++ = '\0';
|
|
|
|
v = rb_str_new2(p);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (*p == '-') {
|
2009-09-13 15:18:51 +04:00
|
|
|
hyphen = TRUE;
|
2005-05-01 04:13:48 +04:00
|
|
|
}
|
|
|
|
else if (*p != '_' && !ISALNUM(*p)) {
|
|
|
|
VALUE name_error[2];
|
2006-12-31 18:02:22 +03:00
|
|
|
name_error[0] =
|
|
|
|
rb_str_new2("invalid name for global variable - ");
|
2005-05-01 04:13:48 +04:00
|
|
|
if (!(p = strchr(p, '='))) {
|
|
|
|
rb_str_cat2(name_error[0], s);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
rb_str_cat(name_error[0], s, p - s);
|
|
|
|
}
|
|
|
|
name_error[1] = args[-1];
|
2007-09-29 01:47:31 +04:00
|
|
|
rb_exc_raise(rb_class_new_instance(2, name_error, rb_eNameError));
|
2005-05-01 04:13:48 +04:00
|
|
|
}
|
1999-10-15 12:52:18 +04:00
|
|
|
}
|
2005-05-01 04:13:48 +04:00
|
|
|
s[0] = '$';
|
|
|
|
if (hyphen) {
|
|
|
|
for (p = s + 1; *p; ++p) {
|
2006-12-31 18:02:22 +03:00
|
|
|
if (*p == '-')
|
|
|
|
*p = '_';
|
2005-05-01 04:13:48 +04:00
|
|
|
}
|
1999-10-15 12:52:18 +04:00
|
|
|
}
|
2005-05-01 04:13:48 +04:00
|
|
|
rb_gv_set(s, v);
|
1999-10-15 12:52:18 +04:00
|
|
|
}
|
2008-03-01 11:59:04 +03:00
|
|
|
n = RARRAY_LEN(argv) - n;
|
1999-10-15 12:52:18 +04:00
|
|
|
while (n--) {
|
2008-03-01 11:59:04 +03:00
|
|
|
rb_ary_shift(argv);
|
1999-10-15 12:52:18 +04:00
|
|
|
}
|
2023-07-13 10:58:48 +03:00
|
|
|
return -1;
|
1999-10-15 12:52:18 +04:00
|
|
|
}
|
2023-07-13 10:58:48 +03:00
|
|
|
return sflag;
|
1999-10-15 12:52:18 +04:00
|
|
|
}
|
|
|
|
|
2016-08-19 13:44:53 +03:00
|
|
|
static long proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt);
|
1999-10-21 11:52:15 +04:00
|
|
|
|
2008-10-30 04:34:23 +03:00
|
|
|
static void
|
2016-08-19 13:44:53 +03:00
|
|
|
moreswitches(const char *s, ruby_cmdline_options_t *opt, int envopt)
|
1999-10-21 11:52:15 +04:00
|
|
|
{
|
2009-05-17 04:47:49 +04:00
|
|
|
long argc, i, len;
|
2008-10-30 04:34:23 +03:00
|
|
|
char **argv, *p;
|
|
|
|
const char *ap = 0;
|
|
|
|
VALUE argstr, argary;
|
2018-05-10 05:54:04 +03:00
|
|
|
void *ptr;
|
2008-10-30 04:34:23 +03:00
|
|
|
|
2023-07-13 11:08:55 +03:00
|
|
|
VALUE src_enc_name = opt->src.enc.name;
|
|
|
|
VALUE ext_enc_name = opt->ext.enc.name;
|
|
|
|
VALUE int_enc_name = opt->intern.enc.name;
|
|
|
|
ruby_features_t feat = opt->features;
|
|
|
|
ruby_features_t warn = opt->warn;
|
2023-08-12 19:00:16 +03:00
|
|
|
long backtrace_length_limit = opt->backtrace_length_limit;
|
2023-09-13 09:02:10 +03:00
|
|
|
const char *crash_report = opt->crash_report;
|
2023-07-13 11:08:55 +03:00
|
|
|
|
2008-10-30 04:34:23 +03:00
|
|
|
while (ISSPACE(*s)) s++;
|
|
|
|
if (!*s) return;
|
2023-08-02 18:08:19 +03:00
|
|
|
|
|
|
|
opt->src.enc.name = opt->ext.enc.name = opt->intern.enc.name = 0;
|
|
|
|
|
2023-09-18 04:14:46 +03:00
|
|
|
const int hyphen = *s != '-';
|
|
|
|
argstr = rb_str_tmp_new((len = strlen(s)) + hyphen);
|
2008-10-30 04:34:23 +03:00
|
|
|
argary = rb_str_tmp_new(0);
|
|
|
|
|
|
|
|
p = RSTRING_PTR(argstr);
|
2023-09-18 04:14:46 +03:00
|
|
|
if (hyphen) *p = '-';
|
|
|
|
memcpy(p + hyphen, s, len + 1);
|
2008-10-30 04:34:23 +03:00
|
|
|
ap = 0;
|
|
|
|
rb_str_cat(argary, (char *)&ap, sizeof(ap));
|
|
|
|
while (*p) {
|
|
|
|
ap = p;
|
|
|
|
rb_str_cat(argary, (char *)&ap, sizeof(ap));
|
|
|
|
while (*p && !ISSPACE(*p)) ++p;
|
|
|
|
if (!*p) break;
|
|
|
|
*p++ = '\0';
|
2009-01-21 07:59:20 +03:00
|
|
|
while (ISSPACE(*p)) ++p;
|
2008-10-30 04:34:23 +03:00
|
|
|
}
|
|
|
|
argc = RSTRING_LEN(argary) / sizeof(ap);
|
|
|
|
ap = 0;
|
|
|
|
rb_str_cat(argary, (char *)&ap, sizeof(ap));
|
2018-05-10 05:54:04 +03:00
|
|
|
argv = ptr = ALLOC_N(char *, argc);
|
|
|
|
MEMMOVE(argv, RSTRING_PTR(argary), char *, argc);
|
2008-10-30 04:34:23 +03:00
|
|
|
|
2017-08-10 08:54:56 +03:00
|
|
|
while ((i = proc_options(argc, argv, opt, envopt)) > 1 && envopt && (argc -= i) > 0) {
|
2008-10-30 04:34:23 +03:00
|
|
|
argv += i;
|
|
|
|
if (**argv != '-') {
|
|
|
|
*--*argv = '-';
|
|
|
|
}
|
|
|
|
if ((*argv)[1]) {
|
|
|
|
++argc;
|
|
|
|
--argv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-13 11:08:55 +03:00
|
|
|
if (src_enc_name) {
|
|
|
|
opt->src.enc.name = src_enc_name;
|
|
|
|
}
|
|
|
|
if (ext_enc_name) {
|
|
|
|
opt->ext.enc.name = ext_enc_name;
|
|
|
|
}
|
|
|
|
if (int_enc_name) {
|
|
|
|
opt->intern.enc.name = int_enc_name;
|
|
|
|
}
|
|
|
|
FEATURE_SET_RESTORE(opt->features, feat);
|
|
|
|
FEATURE_SET_RESTORE(opt->warn, warn);
|
2023-08-12 19:00:16 +03:00
|
|
|
if (BACKTRACE_LENGTH_LIMIT_VALID_P(backtrace_length_limit)) {
|
|
|
|
opt->backtrace_length_limit = backtrace_length_limit;
|
|
|
|
}
|
2023-09-13 09:02:10 +03:00
|
|
|
if (crash_report) {
|
|
|
|
opt->crash_report = crash_report;
|
2023-08-21 11:29:44 +03:00
|
|
|
}
|
2023-07-13 11:08:55 +03:00
|
|
|
|
2018-05-10 05:54:04 +03:00
|
|
|
ruby_xfree(ptr);
|
2008-10-30 04:34:23 +03:00
|
|
|
/* get rid of GC */
|
|
|
|
rb_str_resize(argary, 0);
|
|
|
|
rb_str_resize(argstr, 0);
|
1999-10-21 11:52:15 +04:00
|
|
|
}
|
|
|
|
|
2015-09-27 08:47:24 +03:00
|
|
|
static int
|
|
|
|
name_match_p(const char *name, const char *str, size_t len)
|
|
|
|
{
|
|
|
|
if (len == 0) return 0;
|
2019-07-14 15:56:39 +03:00
|
|
|
while (1) {
|
2015-09-27 08:47:24 +03:00
|
|
|
while (TOLOWER(*str) == *name) {
|
2022-10-09 10:08:09 +03:00
|
|
|
if (!--len) return 1;
|
2015-09-27 08:47:24 +03:00
|
|
|
++name;
|
2022-10-09 10:08:09 +03:00
|
|
|
++str;
|
2015-09-27 08:47:24 +03:00
|
|
|
}
|
|
|
|
if (*str != '-' && *str != '_') return 0;
|
|
|
|
while (ISALNUM(*name)) name++;
|
|
|
|
if (*name != '-' && *name != '_') return 0;
|
|
|
|
++name;
|
|
|
|
++str;
|
2022-10-09 10:08:09 +03:00
|
|
|
if (--len == 0) return 1;
|
2019-07-14 15:56:39 +03:00
|
|
|
}
|
2015-09-27 08:47:24 +03:00
|
|
|
}
|
|
|
|
|
2008-02-24 00:49:15 +03:00
|
|
|
#define NAME_MATCH_P(name, str, len) \
|
2015-09-27 08:47:24 +03:00
|
|
|
((len) < (int)sizeof(name) && name_match_p((name), (str), (len)))
|
2008-02-24 00:49:15 +03:00
|
|
|
|
|
|
|
#define UNSET_WHEN(name, bit, str, len) \
|
2010-12-28 01:37:59 +03:00
|
|
|
if (NAME_MATCH_P((name), (str), (len))) { \
|
2008-02-24 00:49:15 +03:00
|
|
|
*(unsigned int *)arg &= ~(bit); \
|
|
|
|
return; \
|
2008-02-24 00:13:05 +03:00
|
|
|
}
|
|
|
|
|
2008-02-24 00:49:15 +03:00
|
|
|
#define SET_WHEN(name, bit, str, len) \
|
2010-12-28 01:37:59 +03:00
|
|
|
if (NAME_MATCH_P((name), (str), (len))) { \
|
2008-02-24 00:49:15 +03:00
|
|
|
*(unsigned int *)arg |= (bit); \
|
|
|
|
return; \
|
2008-02-24 00:13:05 +03:00
|
|
|
}
|
|
|
|
|
2016-03-08 18:21:22 +03:00
|
|
|
#define LITERAL_NAME_ELEMENT(name) #name
|
2016-02-09 11:32:20 +03:00
|
|
|
|
2008-02-24 00:13:05 +03:00
|
|
|
static void
|
2015-11-19 11:56:12 +03:00
|
|
|
feature_option(const char *str, int len, void *arg, const unsigned int enable)
|
2008-02-24 00:13:05 +03:00
|
|
|
{
|
2016-03-08 18:21:22 +03:00
|
|
|
static const char list[] = EACH_FEATURES(LITERAL_NAME_ELEMENT, ", ");
|
2019-03-30 17:31:35 +03:00
|
|
|
ruby_features_t *argp = arg;
|
2015-11-19 11:56:12 +03:00
|
|
|
unsigned int mask = ~0U;
|
2016-02-08 04:30:22 +03:00
|
|
|
unsigned int set = 0U;
|
2019-03-30 17:31:35 +03:00
|
|
|
#if AMBIGUOUS_FEATURE_NAMES
|
2016-02-08 04:30:22 +03:00
|
|
|
int matched = 0;
|
2019-03-30 17:31:35 +03:00
|
|
|
# define FEATURE_FOUND ++matched
|
2016-02-08 04:30:22 +03:00
|
|
|
#else
|
2019-03-30 17:31:35 +03:00
|
|
|
# define FEATURE_FOUND goto found
|
2016-02-08 04:30:22 +03:00
|
|
|
#endif
|
2019-03-30 17:31:35 +03:00
|
|
|
#define SET_FEATURE(bit) \
|
|
|
|
if (NAME_MATCH_P(#bit, str, len)) {set |= mask = FEATURE_BIT(bit); FEATURE_FOUND;}
|
2016-03-08 18:21:22 +03:00
|
|
|
EACH_FEATURES(SET_FEATURE, ;);
|
2021-12-14 03:08:01 +03:00
|
|
|
if (NAME_MATCH_P("jit", str, len)) { // This allows you to cancel --jit
|
2022-01-12 11:53:52 +03:00
|
|
|
set |= mask = FEATURE_BIT(jit);
|
2021-12-14 03:08:01 +03:00
|
|
|
goto found;
|
|
|
|
}
|
2008-02-24 00:49:15 +03:00
|
|
|
if (NAME_MATCH_P("all", str, len)) {
|
2023-03-07 10:15:30 +03:00
|
|
|
// YJIT and RJIT cannot be enabled at the same time. We enable only one for --enable=all.
|
2022-06-29 19:09:51 +03:00
|
|
|
mask &= ~feature_jit_mask | FEATURE_BIT(jit);
|
2020-06-16 09:32:39 +03:00
|
|
|
goto found;
|
2008-02-24 00:49:15 +03:00
|
|
|
}
|
2016-02-08 04:30:22 +03:00
|
|
|
#if AMBIGUOUS_FEATURE_NAMES
|
|
|
|
if (matched == 1) goto found;
|
|
|
|
if (matched > 1) {
|
2024-01-19 10:03:38 +03:00
|
|
|
VALUE mesg = rb_sprintf("ambiguous feature: '%.*s' (", len, str);
|
2016-02-09 08:47:12 +03:00
|
|
|
#define ADD_FEATURE_NAME(bit) \
|
2016-02-08 04:30:22 +03:00
|
|
|
if (FEATURE_BIT(bit) & set) { \
|
|
|
|
rb_str_cat_cstr(mesg, #bit); \
|
|
|
|
if (--matched) rb_str_cat_cstr(mesg, ", "); \
|
|
|
|
}
|
2016-03-08 18:21:22 +03:00
|
|
|
EACH_FEATURES(ADD_FEATURE_NAME, ;);
|
2016-02-08 04:30:22 +03:00
|
|
|
rb_str_cat_cstr(mesg, ")");
|
|
|
|
rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, mesg));
|
2016-02-09 08:47:12 +03:00
|
|
|
#undef ADD_FEATURE_NAME
|
2016-02-08 04:30:22 +03:00
|
|
|
}
|
2021-07-05 18:09:05 +03:00
|
|
|
#else
|
|
|
|
(void)set;
|
2016-02-08 04:30:22 +03:00
|
|
|
#endif
|
2024-01-19 10:03:38 +03:00
|
|
|
rb_warn("unknown argument for --%s: '%.*s'",
|
2015-11-19 11:56:12 +03:00
|
|
|
enable ? "enable" : "disable", len, str);
|
2016-03-08 18:21:22 +03:00
|
|
|
rb_warn("features are [%.*s].", (int)strlen(list), list);
|
2020-06-16 09:32:39 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
found:
|
|
|
|
FEATURE_SET_TO(*argp, mask, (mask & enable));
|
|
|
|
return;
|
2015-11-19 11:56:12 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
enable_option(const char *str, int len, void *arg)
|
|
|
|
{
|
|
|
|
feature_option(str, len, arg, ~0U);
|
2008-02-24 00:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
disable_option(const char *str, int len, void *arg)
|
|
|
|
{
|
2015-11-19 11:56:12 +03:00
|
|
|
feature_option(str, len, arg, 0U);
|
2008-02-24 00:13:05 +03:00
|
|
|
}
|
|
|
|
|
2017-06-21 05:44:23 +03:00
|
|
|
RUBY_EXTERN const int ruby_patchlevel;
|
|
|
|
int ruby_env_debug_option(const char *str, int len, void *arg);
|
|
|
|
|
2015-11-21 12:57:31 +03:00
|
|
|
static void
|
|
|
|
debug_option(const char *str, int len, void *arg)
|
|
|
|
{
|
2016-03-08 18:21:22 +03:00
|
|
|
static const char list[] = EACH_DEBUG_FEATURES(LITERAL_NAME_ELEMENT, ", ");
|
2019-03-30 17:31:35 +03:00
|
|
|
ruby_features_t *argp = arg;
|
|
|
|
#define SET_WHEN_DEBUG(bit) \
|
|
|
|
if (NAME_MATCH_P(#bit, str, len)) { \
|
|
|
|
FEATURE_SET(*argp, DEBUG_BIT(bit)); \
|
|
|
|
return; \
|
|
|
|
}
|
2016-03-08 18:21:22 +03:00
|
|
|
EACH_DEBUG_FEATURES(SET_WHEN_DEBUG, ;);
|
2017-06-21 07:34:25 +03:00
|
|
|
#ifdef RUBY_DEVEL
|
2017-06-21 05:44:23 +03:00
|
|
|
if (ruby_patchlevel < 0 && ruby_env_debug_option(str, len, 0)) return;
|
2017-06-21 07:34:25 +03:00
|
|
|
#endif
|
2024-01-19 10:03:38 +03:00
|
|
|
rb_warn("unknown argument for --debug: '%.*s'", len, str);
|
2016-03-08 18:21:22 +03:00
|
|
|
rb_warn("debug features are [%.*s].", (int)strlen(list), list);
|
2015-11-21 12:57:31 +03:00
|
|
|
}
|
|
|
|
|
2022-10-09 10:08:09 +03:00
|
|
|
static int
|
|
|
|
memtermspn(const char *str, char term, int len)
|
|
|
|
{
|
|
|
|
RUBY_ASSERT(len >= 0);
|
|
|
|
if (len <= 0) return 0;
|
|
|
|
const char *next = memchr(str, term, len);
|
|
|
|
return next ? (int)(next - str) : len;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char additional_opt_sep = '+';
|
|
|
|
|
|
|
|
static unsigned int
|
|
|
|
dump_additional_option(const char *str, int len, unsigned int bits, const char *name)
|
|
|
|
{
|
|
|
|
int w;
|
|
|
|
for (; len-- > 0 && *str++ == additional_opt_sep; len -= w, str += w) {
|
|
|
|
w = memtermspn(str, additional_opt_sep, len);
|
|
|
|
#define SET_ADDITIONAL(bit) if (NAME_MATCH_P(#bit, str, w)) { \
|
|
|
|
if (bits & DUMP_BIT(bit)) \
|
2024-01-19 10:03:38 +03:00
|
|
|
rb_warn("duplicate option to dump %s: '%.*s'", name, w, str); \
|
2022-10-09 10:08:09 +03:00
|
|
|
bits |= DUMP_BIT(bit); \
|
|
|
|
continue; \
|
|
|
|
}
|
|
|
|
if (dump_error_tolerant_bits & bits) {
|
|
|
|
SET_ADDITIONAL(error_tolerant);
|
|
|
|
}
|
2024-01-19 10:03:38 +03:00
|
|
|
rb_warn("don't know how to dump %s with '%.*s'", name, w, str);
|
2022-10-09 10:08:09 +03:00
|
|
|
}
|
|
|
|
return bits;
|
|
|
|
}
|
|
|
|
|
2008-05-20 07:13:52 +04:00
|
|
|
static void
|
|
|
|
dump_option(const char *str, int len, void *arg)
|
|
|
|
{
|
2016-03-08 18:21:22 +03:00
|
|
|
static const char list[] = EACH_DUMPS(LITERAL_NAME_ELEMENT, ", ");
|
2022-10-09 10:08:09 +03:00
|
|
|
int w = memtermspn(str, additional_opt_sep, len);
|
|
|
|
|
|
|
|
#define SET_WHEN_DUMP(bit) \
|
|
|
|
if (NAME_MATCH_P(#bit, (str), (w))) { \
|
|
|
|
*(unsigned int *)arg |= \
|
|
|
|
dump_additional_option(str + w, len - w, DUMP_BIT(bit), #bit); \
|
|
|
|
return; \
|
2022-09-25 15:23:17 +03:00
|
|
|
}
|
2016-03-08 18:21:22 +03:00
|
|
|
EACH_DUMPS(SET_WHEN_DUMP, ;);
|
2024-01-19 10:03:38 +03:00
|
|
|
rb_warn("don't know how to dump '%.*s',", len, str);
|
2016-03-08 18:21:22 +03:00
|
|
|
rb_warn("but only [%.*s].", (int)strlen(list), list);
|
2008-05-20 07:13:52 +04:00
|
|
|
}
|
|
|
|
|
2008-10-14 04:41:09 +04:00
|
|
|
static void
|
2009-05-17 04:47:49 +04:00
|
|
|
set_option_encoding_once(const char *type, VALUE *name, const char *e, long elen)
|
2008-10-14 04:41:09 +04:00
|
|
|
{
|
|
|
|
VALUE ename;
|
|
|
|
|
|
|
|
if (!elen) elen = strlen(e);
|
|
|
|
ename = rb_str_new(e, elen);
|
|
|
|
|
2008-12-08 04:32:36 +03:00
|
|
|
if (*name &&
|
|
|
|
rb_funcall(ename, rb_intern("casecmp"), 1, *name) != INT2FIX(0)) {
|
2008-10-14 04:41:09 +04:00
|
|
|
rb_raise(rb_eRuntimeError,
|
2013-06-24 15:31:21 +04:00
|
|
|
"%s already set to %"PRIsVALUE, type, *name);
|
2008-10-14 04:41:09 +04:00
|
|
|
}
|
2008-12-08 04:32:36 +03:00
|
|
|
*name = ename;
|
2008-10-14 04:41:09 +04:00
|
|
|
}
|
|
|
|
|
2008-12-08 04:32:36 +03:00
|
|
|
#define set_internal_encoding_once(opt, e, elen) \
|
2010-12-28 01:37:59 +03:00
|
|
|
set_option_encoding_once("default_internal", &(opt)->intern.enc.name, (e), (elen))
|
2008-12-08 04:32:36 +03:00
|
|
|
#define set_external_encoding_once(opt, e, elen) \
|
2010-12-28 01:37:59 +03:00
|
|
|
set_option_encoding_once("default_external", &(opt)->ext.enc.name, (e), (elen))
|
2008-12-08 04:32:36 +03:00
|
|
|
#define set_source_encoding_once(opt, e, elen) \
|
2010-12-28 01:37:59 +03:00
|
|
|
set_option_encoding_once("source", &(opt)->src.enc.name, (e), (elen))
|
2008-10-14 04:41:09 +04:00
|
|
|
|
2021-10-15 23:51:57 +03:00
|
|
|
#define yjit_opt_match_noarg(s, l, name) \
|
|
|
|
opt_match(s, l, name) && (*(s) ? (rb_warn("argument to --yjit-" name " is ignored"), 1) : 1)
|
|
|
|
#define yjit_opt_match_arg(s, l, name) \
|
|
|
|
opt_match(s, l, name) && (*(s) && *(s+1) ? 1 : (rb_raise(rb_eRuntimeError, "--yjit-" name " needs an argument"), 0))
|
|
|
|
|
2022-08-15 20:05:12 +03:00
|
|
|
#if USE_YJIT
|
Rust YJIT
In December 2021, we opened an [issue] to solicit feedback regarding the
porting of the YJIT codebase from C99 to Rust. There were some
reservations, but this project was given the go ahead by Ruby core
developers and Matz. Since then, we have successfully completed the port
of YJIT to Rust.
The new Rust version of YJIT has reached parity with the C version, in
that it passes all the CRuby tests, is able to run all of the YJIT
benchmarks, and performs similarly to the C version (because it works
the same way and largely generates the same machine code). We've even
incorporated some design improvements, such as a more fine-grained
constant invalidation mechanism which we expect will make a big
difference in Ruby on Rails applications.
Because we want to be careful, YJIT is guarded behind a configure
option:
```shell
./configure --enable-yjit # Build YJIT in release mode
./configure --enable-yjit=dev # Build YJIT in dev/debug mode
```
By default, YJIT does not get compiled and cargo/rustc is not required.
If YJIT is built in dev mode, then `cargo` is used to fetch development
dependencies, but when building in release, `cargo` is not required,
only `rustc`. At the moment YJIT requires Rust 1.60.0 or newer.
The YJIT command-line options remain mostly unchanged, and more details
about the build process are documented in `doc/yjit/yjit.md`.
The CI tests have been updated and do not take any more resources than
before.
The development history of the Rust port is available at the following
commit for interested parties:
https://github.com/Shopify/ruby/commit/1fd9573d8b4b65219f1c2407f30a0a60e537f8be
Our hope is that Rust YJIT will be compiled and included as a part of
system packages and compiled binaries of the Ruby 3.2 release. We do not
anticipate any major problems as Rust is well supported on every
platform which YJIT supports, but to make sure that this process works
smoothly, we would like to reach out to those who take care of building
systems packages before the 3.2 release is shipped and resolve any
issues that may come up.
[issue]: https://bugs.ruby-lang.org/issues/18481
Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
Co-authored-by: Noah Gibbs <the.codefolio.guy@gmail.com>
Co-authored-by: Kevin Newton <kddnewton@gmail.com>
2022-04-19 21:40:21 +03:00
|
|
|
static bool
|
|
|
|
setup_yjit_options(const char *s)
|
2021-01-26 23:21:47 +03:00
|
|
|
{
|
Rust YJIT
In December 2021, we opened an [issue] to solicit feedback regarding the
porting of the YJIT codebase from C99 to Rust. There were some
reservations, but this project was given the go ahead by Ruby core
developers and Matz. Since then, we have successfully completed the port
of YJIT to Rust.
The new Rust version of YJIT has reached parity with the C version, in
that it passes all the CRuby tests, is able to run all of the YJIT
benchmarks, and performs similarly to the C version (because it works
the same way and largely generates the same machine code). We've even
incorporated some design improvements, such as a more fine-grained
constant invalidation mechanism which we expect will make a big
difference in Ruby on Rails applications.
Because we want to be careful, YJIT is guarded behind a configure
option:
```shell
./configure --enable-yjit # Build YJIT in release mode
./configure --enable-yjit=dev # Build YJIT in dev/debug mode
```
By default, YJIT does not get compiled and cargo/rustc is not required.
If YJIT is built in dev mode, then `cargo` is used to fetch development
dependencies, but when building in release, `cargo` is not required,
only `rustc`. At the moment YJIT requires Rust 1.60.0 or newer.
The YJIT command-line options remain mostly unchanged, and more details
about the build process are documented in `doc/yjit/yjit.md`.
The CI tests have been updated and do not take any more resources than
before.
The development history of the Rust port is available at the following
commit for interested parties:
https://github.com/Shopify/ruby/commit/1fd9573d8b4b65219f1c2407f30a0a60e537f8be
Our hope is that Rust YJIT will be compiled and included as a part of
system packages and compiled binaries of the Ruby 3.2 release. We do not
anticipate any major problems as Rust is well supported on every
platform which YJIT supports, but to make sure that this process works
smoothly, we would like to reach out to those who take care of building
systems packages before the 3.2 release is shipped and resolve any
issues that may come up.
[issue]: https://bugs.ruby-lang.org/issues/18481
Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
Co-authored-by: Noah Gibbs <the.codefolio.guy@gmail.com>
Co-authored-by: Kevin Newton <kddnewton@gmail.com>
2022-04-19 21:40:21 +03:00
|
|
|
// The option parsing is done in yjit/src/options.rs
|
|
|
|
bool rb_yjit_parse_option(const char* s);
|
|
|
|
bool success = rb_yjit_parse_option(s);
|
|
|
|
|
|
|
|
if (success) {
|
|
|
|
return true;
|
2021-01-27 00:19:29 +03:00
|
|
|
}
|
Rust YJIT
In December 2021, we opened an [issue] to solicit feedback regarding the
porting of the YJIT codebase from C99 to Rust. There were some
reservations, but this project was given the go ahead by Ruby core
developers and Matz. Since then, we have successfully completed the port
of YJIT to Rust.
The new Rust version of YJIT has reached parity with the C version, in
that it passes all the CRuby tests, is able to run all of the YJIT
benchmarks, and performs similarly to the C version (because it works
the same way and largely generates the same machine code). We've even
incorporated some design improvements, such as a more fine-grained
constant invalidation mechanism which we expect will make a big
difference in Ruby on Rails applications.
Because we want to be careful, YJIT is guarded behind a configure
option:
```shell
./configure --enable-yjit # Build YJIT in release mode
./configure --enable-yjit=dev # Build YJIT in dev/debug mode
```
By default, YJIT does not get compiled and cargo/rustc is not required.
If YJIT is built in dev mode, then `cargo` is used to fetch development
dependencies, but when building in release, `cargo` is not required,
only `rustc`. At the moment YJIT requires Rust 1.60.0 or newer.
The YJIT command-line options remain mostly unchanged, and more details
about the build process are documented in `doc/yjit/yjit.md`.
The CI tests have been updated and do not take any more resources than
before.
The development history of the Rust port is available at the following
commit for interested parties:
https://github.com/Shopify/ruby/commit/1fd9573d8b4b65219f1c2407f30a0a60e537f8be
Our hope is that Rust YJIT will be compiled and included as a part of
system packages and compiled binaries of the Ruby 3.2 release. We do not
anticipate any major problems as Rust is well supported on every
platform which YJIT supports, but to make sure that this process works
smoothly, we would like to reach out to those who take care of building
systems packages before the 3.2 release is shipped and resolve any
issues that may come up.
[issue]: https://bugs.ruby-lang.org/issues/18481
Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
Co-authored-by: Noah Gibbs <the.codefolio.guy@gmail.com>
Co-authored-by: Kevin Newton <kddnewton@gmail.com>
2022-04-19 21:40:21 +03:00
|
|
|
|
|
|
|
rb_raise(
|
|
|
|
rb_eRuntimeError,
|
2024-01-19 10:03:38 +03:00
|
|
|
"invalid YJIT option '%s' (--help will show valid yjit options)",
|
Rust YJIT
In December 2021, we opened an [issue] to solicit feedback regarding the
porting of the YJIT codebase from C99 to Rust. There were some
reservations, but this project was given the go ahead by Ruby core
developers and Matz. Since then, we have successfully completed the port
of YJIT to Rust.
The new Rust version of YJIT has reached parity with the C version, in
that it passes all the CRuby tests, is able to run all of the YJIT
benchmarks, and performs similarly to the C version (because it works
the same way and largely generates the same machine code). We've even
incorporated some design improvements, such as a more fine-grained
constant invalidation mechanism which we expect will make a big
difference in Ruby on Rails applications.
Because we want to be careful, YJIT is guarded behind a configure
option:
```shell
./configure --enable-yjit # Build YJIT in release mode
./configure --enable-yjit=dev # Build YJIT in dev/debug mode
```
By default, YJIT does not get compiled and cargo/rustc is not required.
If YJIT is built in dev mode, then `cargo` is used to fetch development
dependencies, but when building in release, `cargo` is not required,
only `rustc`. At the moment YJIT requires Rust 1.60.0 or newer.
The YJIT command-line options remain mostly unchanged, and more details
about the build process are documented in `doc/yjit/yjit.md`.
The CI tests have been updated and do not take any more resources than
before.
The development history of the Rust port is available at the following
commit for interested parties:
https://github.com/Shopify/ruby/commit/1fd9573d8b4b65219f1c2407f30a0a60e537f8be
Our hope is that Rust YJIT will be compiled and included as a part of
system packages and compiled binaries of the Ruby 3.2 release. We do not
anticipate any major problems as Rust is well supported on every
platform which YJIT supports, but to make sure that this process works
smoothly, we would like to reach out to those who take care of building
systems packages before the 3.2 release is shipped and resolve any
issues that may come up.
[issue]: https://bugs.ruby-lang.org/issues/18481
Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
Co-authored-by: Noah Gibbs <the.codefolio.guy@gmail.com>
Co-authored-by: Kevin Newton <kddnewton@gmail.com>
2022-04-19 21:40:21 +03:00
|
|
|
s
|
|
|
|
);
|
2021-01-26 23:21:47 +03:00
|
|
|
}
|
2022-01-11 11:26:21 +03:00
|
|
|
#endif
|
2021-01-26 23:21:47 +03:00
|
|
|
|
2023-06-08 04:18:55 +03:00
|
|
|
/*
|
|
|
|
* Following proc_*_option functions are tree kinds:
|
|
|
|
*
|
|
|
|
* - with a required argument, takes also `argc` and `argv`, and
|
|
|
|
* returns the number of consumed argv including the option itself.
|
|
|
|
*
|
|
|
|
* - with a mandatory argument just after the option.
|
|
|
|
*
|
|
|
|
* - no required argument, this returns the address of
|
|
|
|
* the next character after the last consumed character.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* optional */
|
|
|
|
static const char *
|
|
|
|
proc_W_option(ruby_cmdline_options_t *opt, const char *s, int *warning)
|
|
|
|
{
|
|
|
|
if (s[1] == ':') {
|
|
|
|
unsigned int bits = 0;
|
|
|
|
static const char no_prefix[] = "no-";
|
|
|
|
int enable = strncmp(s += 2, no_prefix, sizeof(no_prefix)-1) != 0;
|
|
|
|
if (!enable) s += sizeof(no_prefix)-1;
|
|
|
|
size_t len = strlen(s);
|
|
|
|
if (NAME_MATCH_P("deprecated", s, len)) {
|
|
|
|
bits = 1U << RB_WARN_CATEGORY_DEPRECATED;
|
|
|
|
}
|
|
|
|
else if (NAME_MATCH_P("experimental", s, len)) {
|
|
|
|
bits = 1U << RB_WARN_CATEGORY_EXPERIMENTAL;
|
|
|
|
}
|
|
|
|
else if (NAME_MATCH_P("performance", s, len)) {
|
|
|
|
bits = 1U << RB_WARN_CATEGORY_PERFORMANCE;
|
|
|
|
}
|
|
|
|
else {
|
2024-01-19 10:03:38 +03:00
|
|
|
rb_warn("unknown warning category: '%s'", s);
|
2023-06-08 04:18:55 +03:00
|
|
|
}
|
|
|
|
if (bits) FEATURE_SET_TO(opt->warn, bits, enable ? bits : 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
size_t numlen;
|
|
|
|
int v = 2; /* -W as -W2 */
|
|
|
|
|
|
|
|
if (*++s) {
|
|
|
|
v = scan_oct(s, 1, &numlen);
|
|
|
|
if (numlen == 0)
|
|
|
|
v = 2;
|
|
|
|
s += numlen;
|
|
|
|
}
|
|
|
|
if (!opt->warning) {
|
|
|
|
switch (v) {
|
|
|
|
case 0:
|
|
|
|
ruby_verbose = Qnil;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
ruby_verbose = Qfalse;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ruby_verbose = Qtrue;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*warning = 1;
|
|
|
|
switch (v) {
|
|
|
|
case 0:
|
|
|
|
FEATURE_SET_TO(opt->warn, RB_WARN_CATEGORY_DEFAULT_BITS, 0);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
FEATURE_SET_TO(opt->warn, 1U << RB_WARN_CATEGORY_DEPRECATED, 0);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
FEATURE_SET(opt->warn, RB_WARN_CATEGORY_DEFAULT_BITS);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* required */
|
|
|
|
static long
|
|
|
|
proc_e_option(ruby_cmdline_options_t *opt, const char *s, long argc, char **argv)
|
|
|
|
{
|
|
|
|
long n = 1;
|
|
|
|
forbid_setid("-e");
|
|
|
|
if (!*++s) {
|
|
|
|
if (!--argc)
|
|
|
|
rb_raise(rb_eRuntimeError, "no code specified for -e");
|
|
|
|
s = *++argv;
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
if (!opt->e_script) {
|
|
|
|
opt->e_script = rb_str_new(0, 0);
|
|
|
|
if (opt->script == 0)
|
|
|
|
opt->script = "-e";
|
|
|
|
}
|
|
|
|
rb_str_cat2(opt->e_script, s);
|
|
|
|
rb_str_cat2(opt->e_script, "\n");
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* optional */
|
|
|
|
static const char *
|
|
|
|
proc_K_option(ruby_cmdline_options_t *opt, const char *s)
|
|
|
|
{
|
|
|
|
if (*++s) {
|
|
|
|
const char *enc_name = 0;
|
|
|
|
switch (*s) {
|
|
|
|
case 'E': case 'e':
|
|
|
|
enc_name = "EUC-JP";
|
|
|
|
break;
|
|
|
|
case 'S': case 's':
|
|
|
|
enc_name = "Windows-31J";
|
|
|
|
break;
|
|
|
|
case 'U': case 'u':
|
|
|
|
enc_name = "UTF-8";
|
|
|
|
break;
|
|
|
|
case 'N': case 'n': case 'A': case 'a':
|
|
|
|
enc_name = "ASCII-8BIT";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (enc_name) {
|
|
|
|
opt->src.enc.name = rb_str_new2(enc_name);
|
|
|
|
if (!opt->ext.enc.name)
|
|
|
|
opt->ext.enc.name = opt->src.enc.name;
|
|
|
|
}
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* optional */
|
|
|
|
static const char *
|
|
|
|
proc_0_option(ruby_cmdline_options_t *opt, const char *s)
|
|
|
|
{
|
|
|
|
size_t numlen;
|
|
|
|
int v;
|
|
|
|
char c;
|
|
|
|
|
|
|
|
v = scan_oct(s, 4, &numlen);
|
|
|
|
s += numlen;
|
|
|
|
if (v > 0377)
|
|
|
|
rb_rs = Qnil;
|
|
|
|
else if (v == 0 && numlen >= 2) {
|
|
|
|
rb_rs = rb_str_new2("");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
c = v & 0xff;
|
|
|
|
rb_rs = rb_str_new(&c, 1);
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* mandatory */
|
|
|
|
static void
|
|
|
|
proc_encoding_option(ruby_cmdline_options_t *opt, const char *s, const char *opt_name)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
# define set_encoding_part(type) \
|
|
|
|
if (!(p = strchr(s, ':'))) { \
|
|
|
|
set_##type##_encoding_once(opt, s, 0); \
|
|
|
|
return; \
|
|
|
|
} \
|
|
|
|
else if (p > s) { \
|
|
|
|
set_##type##_encoding_once(opt, s, p-s); \
|
|
|
|
}
|
|
|
|
set_encoding_part(external);
|
|
|
|
if (!*(s = ++p)) return;
|
|
|
|
set_encoding_part(internal);
|
|
|
|
if (!*(s = ++p)) return;
|
|
|
|
#if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
|
|
|
|
set_encoding_part(source);
|
|
|
|
if (!*(s = ++p)) return;
|
|
|
|
#endif
|
|
|
|
rb_raise(rb_eRuntimeError, "extra argument for %s: %s", opt_name, s);
|
|
|
|
# undef set_encoding_part
|
|
|
|
UNREACHABLE;
|
|
|
|
}
|
|
|
|
|
2023-06-08 05:07:50 +03:00
|
|
|
static long
|
|
|
|
proc_long_options(ruby_cmdline_options_t *opt, const char *s, long argc, char **argv, int envopt)
|
|
|
|
{
|
|
|
|
size_t n;
|
|
|
|
long argc0 = argc;
|
|
|
|
# define is_option_end(c, allow_hyphen) \
|
|
|
|
(!(c) || ((allow_hyphen) && (c) == '-') || (c) == '=')
|
|
|
|
# define check_envopt(name, allow_envopt) \
|
|
|
|
(((allow_envopt) || !envopt) ? (void)0 : \
|
|
|
|
rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --" name))
|
|
|
|
# define need_argument(name, s, needs_arg, next_arg) \
|
2024-01-17 05:26:12 +03:00
|
|
|
((*(s) ? !*++(s) : (next_arg) && (argc <= 1 || !((s) = argv[1]) || (--argc, ++argv, 0))) && (needs_arg) ? \
|
2023-06-08 05:07:50 +03:00
|
|
|
rb_raise(rb_eRuntimeError, "missing argument for --" name) \
|
|
|
|
: (void)0)
|
|
|
|
# define is_option_with_arg(name, allow_hyphen, allow_envopt) \
|
|
|
|
is_option_with_optarg(name, allow_hyphen, allow_envopt, Qtrue, Qtrue)
|
|
|
|
# define is_option_with_optarg(name, allow_hyphen, allow_envopt, needs_arg, next_arg) \
|
|
|
|
(strncmp((name), s, n = sizeof(name) - 1) == 0 && is_option_end(s[n], (allow_hyphen)) && \
|
2024-01-17 05:26:12 +03:00
|
|
|
(s[n] != '-' || (s[n] && s[n+1])) ? \
|
2023-06-08 05:07:50 +03:00
|
|
|
(check_envopt(name, (allow_envopt)), s += n, \
|
|
|
|
need_argument(name, s, needs_arg, next_arg), 1) : 0)
|
|
|
|
|
|
|
|
if (strcmp("copyright", s) == 0) {
|
|
|
|
if (envopt) goto noenvopt_long;
|
|
|
|
opt->dump |= DUMP_BIT(copyright);
|
|
|
|
}
|
|
|
|
else if (is_option_with_optarg("debug", Qtrue, Qtrue, Qfalse, Qfalse)) {
|
|
|
|
if (s && *s) {
|
|
|
|
ruby_each_words(s, debug_option, &opt->features);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ruby_debug = Qtrue;
|
|
|
|
ruby_verbose = Qtrue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (is_option_with_arg("enable", Qtrue, Qtrue)) {
|
|
|
|
ruby_each_words(s, enable_option, &opt->features);
|
|
|
|
}
|
|
|
|
else if (is_option_with_arg("disable", Qtrue, Qtrue)) {
|
|
|
|
ruby_each_words(s, disable_option, &opt->features);
|
|
|
|
}
|
|
|
|
else if (is_option_with_arg("encoding", Qfalse, Qtrue)) {
|
|
|
|
proc_encoding_option(opt, s, "--encoding");
|
|
|
|
}
|
|
|
|
else if (is_option_with_arg("internal-encoding", Qfalse, Qtrue)) {
|
|
|
|
set_internal_encoding_once(opt, s, 0);
|
|
|
|
}
|
|
|
|
else if (is_option_with_arg("external-encoding", Qfalse, Qtrue)) {
|
|
|
|
set_external_encoding_once(opt, s, 0);
|
|
|
|
}
|
2023-12-08 02:47:36 +03:00
|
|
|
else if (is_option_with_arg("parser", Qfalse, Qtrue)) {
|
|
|
|
if (strcmp("prism", s) == 0) {
|
|
|
|
(*rb_ruby_prism_ptr()) = true;
|
|
|
|
}
|
|
|
|
else if (strcmp("parse.y", s) == 0) {
|
|
|
|
// default behavior
|
2023-12-16 18:21:00 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
rb_raise(rb_eRuntimeError, "unknown parser %s", s);
|
2023-12-08 02:47:36 +03:00
|
|
|
}
|
|
|
|
}
|
2023-06-08 05:07:50 +03:00
|
|
|
#if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
|
|
|
|
else if (is_option_with_arg("source-encoding", Qfalse, Qtrue)) {
|
|
|
|
set_source_encoding_once(opt, s, 0);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
else if (strcmp("version", s) == 0) {
|
|
|
|
if (envopt) goto noenvopt_long;
|
|
|
|
opt->dump |= DUMP_BIT(version);
|
|
|
|
}
|
|
|
|
else if (strcmp("verbose", s) == 0) {
|
|
|
|
opt->verbose = 1;
|
|
|
|
ruby_verbose = Qtrue;
|
|
|
|
}
|
|
|
|
else if (strcmp("jit", s) == 0) {
|
2023-12-13 11:05:11 +03:00
|
|
|
#if USE_YJIT || USE_RJIT
|
2023-06-08 05:07:50 +03:00
|
|
|
FEATURE_SET(opt->features, FEATURE_BIT(jit));
|
2023-12-13 11:05:11 +03:00
|
|
|
#else
|
|
|
|
rb_warn("Ruby was built without JIT support");
|
2023-06-08 05:07:50 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (is_option_with_optarg("rjit", '-', true, false, false)) {
|
|
|
|
#if USE_RJIT
|
|
|
|
extern void rb_rjit_setup_options(const char *s, struct rb_rjit_options *rjit_opt);
|
|
|
|
FEATURE_SET(opt->features, FEATURE_BIT(rjit));
|
|
|
|
rb_rjit_setup_options(s, &opt->rjit);
|
|
|
|
#else
|
|
|
|
rb_warn("RJIT support is disabled.");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (is_option_with_optarg("yjit", '-', true, false, false)) {
|
|
|
|
#if USE_YJIT
|
|
|
|
FEATURE_SET(opt->features, FEATURE_BIT(yjit));
|
|
|
|
setup_yjit_options(s);
|
|
|
|
#else
|
|
|
|
rb_warn("Ruby was built without YJIT support."
|
|
|
|
" You may need to install rustc to build Ruby with YJIT.");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (strcmp("yydebug", s) == 0) {
|
|
|
|
if (envopt) goto noenvopt_long;
|
|
|
|
opt->dump |= DUMP_BIT(yydebug);
|
|
|
|
}
|
|
|
|
else if (is_option_with_arg("dump", Qfalse, Qfalse)) {
|
|
|
|
ruby_each_words(s, dump_option, &opt->dump);
|
|
|
|
}
|
|
|
|
else if (strcmp("help", s) == 0) {
|
|
|
|
if (envopt) goto noenvopt_long;
|
|
|
|
opt->dump |= DUMP_BIT(help);
|
|
|
|
return 0;
|
|
|
|
}
|
2023-07-01 17:15:09 +03:00
|
|
|
else if (is_option_with_arg("backtrace-limit", Qfalse, Qtrue)) {
|
2023-06-08 05:07:50 +03:00
|
|
|
char *e;
|
|
|
|
long n = strtol(s, &e, 10);
|
2023-08-10 18:29:32 +03:00
|
|
|
if (errno == ERANGE || !BACKTRACE_LENGTH_LIMIT_VALID_P(n) || *e) {
|
|
|
|
rb_raise(rb_eRuntimeError, "wrong limit for backtrace length");
|
|
|
|
}
|
2023-08-12 19:00:16 +03:00
|
|
|
else {
|
2023-08-10 18:29:32 +03:00
|
|
|
opt->backtrace_length_limit = n;
|
|
|
|
}
|
2023-06-08 05:07:50 +03:00
|
|
|
}
|
2023-09-13 09:02:10 +03:00
|
|
|
else if (is_option_with_arg("crash-report", true, true)) {
|
|
|
|
opt->crash_report = s;
|
2023-08-04 10:56:55 +03:00
|
|
|
}
|
2023-06-08 05:07:50 +03:00
|
|
|
else {
|
|
|
|
rb_raise(rb_eRuntimeError,
|
|
|
|
"invalid option --%s (-h will show valid options)", s);
|
|
|
|
}
|
|
|
|
return argc0 - argc + 1;
|
|
|
|
|
|
|
|
noenvopt_long:
|
|
|
|
rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --%s", s);
|
|
|
|
# undef is_option_end
|
|
|
|
# undef check_envopt
|
|
|
|
# undef need_argument
|
|
|
|
# undef is_option_with_arg
|
|
|
|
# undef is_option_with_optarg
|
|
|
|
UNREACHABLE_RETURN(0);
|
|
|
|
}
|
|
|
|
|
2009-05-17 04:47:49 +04:00
|
|
|
static long
|
2016-08-19 13:44:53 +03:00
|
|
|
proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt)
|
1999-10-15 12:52:18 +04:00
|
|
|
{
|
2009-05-17 04:47:49 +04:00
|
|
|
long n, argc0 = argc;
|
2006-07-21 18:58:18 +04:00
|
|
|
const char *s;
|
2015-12-29 15:23:04 +03:00
|
|
|
int warning = opt->warning;
|
1999-10-16 14:33:06 +04:00
|
|
|
|
2017-08-09 14:03:55 +03:00
|
|
|
if (argc <= 0 || !argv)
|
* include/ruby/{intern,ruby}.h, compile.[ch], error.c, eval.c,
eval_load.c, gc.c, iseq.c, main.c, parse.y, re.c, ruby.c,
yarvcore.[ch] (ruby_eval_tree, ruby_sourcefile, ruby_sourceline,
ruby_nerrs): purge global variables.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12700 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-07-05 12:12:18 +04:00
|
|
|
return 0;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
for (argc--, argv++; argc > 0; argc--, argv++) {
|
2008-12-08 04:32:36 +03:00
|
|
|
const char *const arg = argv[0];
|
2012-11-23 19:00:55 +04:00
|
|
|
if (!arg || arg[0] != '-' || !arg[1])
|
2006-12-31 18:02:22 +03:00
|
|
|
break;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2008-12-08 04:32:36 +03:00
|
|
|
s = arg + 1;
|
1998-01-16 15:13:05 +03:00
|
|
|
reswitch:
|
|
|
|
switch (*s) {
|
|
|
|
case 'a':
|
2008-10-30 04:34:23 +03:00
|
|
|
if (envopt) goto noenvopt;
|
2009-09-13 15:18:51 +04:00
|
|
|
opt->do_split = TRUE;
|
1998-01-16 15:13:05 +03:00
|
|
|
s++;
|
|
|
|
goto reswitch;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'p':
|
2008-10-30 04:34:23 +03:00
|
|
|
if (envopt) goto noenvopt;
|
2009-09-13 15:18:51 +04:00
|
|
|
opt->do_print = TRUE;
|
1998-01-16 15:13:05 +03:00
|
|
|
/* through */
|
|
|
|
case 'n':
|
2008-10-30 04:34:23 +03:00
|
|
|
if (envopt) goto noenvopt;
|
2009-09-13 15:18:51 +04:00
|
|
|
opt->do_loop = TRUE;
|
1998-01-16 15:13:05 +03:00
|
|
|
s++;
|
|
|
|
goto reswitch;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'd':
|
1999-08-13 09:45:20 +04:00
|
|
|
ruby_debug = Qtrue;
|
1999-10-16 14:33:06 +04:00
|
|
|
ruby_verbose = Qtrue;
|
1998-01-16 15:13:05 +03:00
|
|
|
s++;
|
|
|
|
goto reswitch;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'y':
|
2008-10-30 04:34:23 +03:00
|
|
|
if (envopt) goto noenvopt;
|
2008-12-08 05:28:17 +03:00
|
|
|
opt->dump |= DUMP_BIT(yydebug);
|
1998-01-16 15:13:05 +03:00
|
|
|
s++;
|
|
|
|
goto reswitch;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'v':
|
2007-09-29 01:47:31 +04:00
|
|
|
if (opt->verbose) {
|
2001-02-27 10:52:11 +03:00
|
|
|
s++;
|
|
|
|
goto reswitch;
|
|
|
|
}
|
2012-08-09 13:33:49 +04:00
|
|
|
opt->dump |= DUMP_BIT(version_v);
|
2007-09-29 01:47:31 +04:00
|
|
|
opt->verbose = 1;
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'w':
|
2015-12-29 13:12:48 +03:00
|
|
|
if (!opt->warning) {
|
2015-12-29 15:23:04 +03:00
|
|
|
warning = 1;
|
2015-12-29 13:12:48 +03:00
|
|
|
ruby_verbose = Qtrue;
|
|
|
|
}
|
2023-04-13 17:48:59 +03:00
|
|
|
FEATURE_SET(opt->warn, RB_WARN_CATEGORY_DEFAULT_BITS);
|
1998-01-16 15:13:05 +03:00
|
|
|
s++;
|
|
|
|
goto reswitch;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2003-07-29 22:26:55 +04:00
|
|
|
case 'W':
|
2023-06-08 04:18:55 +03:00
|
|
|
if (!(s = proc_W_option(opt, s, &warning))) break;
|
2003-07-29 22:26:55 +04:00
|
|
|
goto reswitch;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'c':
|
2008-10-30 04:34:23 +03:00
|
|
|
if (envopt) goto noenvopt;
|
2008-12-08 05:28:17 +03:00
|
|
|
opt->dump |= DUMP_BIT(syntax);
|
1998-01-16 15:13:05 +03:00
|
|
|
s++;
|
|
|
|
goto reswitch;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case 's':
|
2008-10-30 04:34:23 +03:00
|
|
|
if (envopt) goto noenvopt;
|
1998-01-16 15:13:05 +03:00
|
|
|
forbid_setid("-s");
|
2009-05-17 04:47:49 +04:00
|
|
|
if (!opt->sflag) opt->sflag = 1;
|
1998-01-16 15:13:05 +03:00
|
|
|
s++;
|
|
|
|
goto reswitch;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1999-08-13 09:45:20 +04:00
|
|
|
case 'h':
|
2008-10-30 04:34:23 +03:00
|
|
|
if (envopt) goto noenvopt;
|
2008-12-08 05:28:17 +03:00
|
|
|
opt->dump |= DUMP_BIT(usage);
|
|
|
|
goto switch_end;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'l':
|
2008-10-30 04:34:23 +03:00
|
|
|
if (envopt) goto noenvopt;
|
2009-09-13 15:18:51 +04:00
|
|
|
opt->do_line = TRUE;
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_output_rs = rb_rs;
|
1998-01-16 15:13:05 +03:00
|
|
|
s++;
|
|
|
|
goto reswitch;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'S':
|
2008-10-30 04:34:23 +03:00
|
|
|
if (envopt) goto noenvopt;
|
1998-01-16 15:13:05 +03:00
|
|
|
forbid_setid("-S");
|
2009-09-13 15:18:51 +04:00
|
|
|
opt->do_search = TRUE;
|
1998-01-16 15:13:05 +03:00
|
|
|
s++;
|
|
|
|
goto reswitch;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'e':
|
2008-10-30 04:34:23 +03:00
|
|
|
if (envopt) goto noenvopt;
|
2023-06-08 04:18:55 +03:00
|
|
|
if (!(n = proc_e_option(opt, s, argc, argv))) break;
|
|
|
|
--n;
|
|
|
|
argc -= n;
|
|
|
|
argv += n;
|
1998-01-16 15:13:05 +03:00
|
|
|
break;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'r':
|
|
|
|
forbid_setid("-r");
|
|
|
|
if (*++s) {
|
2009-05-17 04:47:49 +04:00
|
|
|
add_modules(&opt->req_list, s);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2014-02-07 20:20:55 +04:00
|
|
|
else if (argc > 1) {
|
2009-05-17 04:47:49 +04:00
|
|
|
add_modules(&opt->req_list, argv[1]);
|
2006-12-31 18:02:22 +03:00
|
|
|
argc--, argv++;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
break;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'i':
|
2008-10-30 04:34:23 +03:00
|
|
|
if (envopt) goto noenvopt;
|
1998-01-16 15:13:05 +03:00
|
|
|
forbid_setid("-i");
|
2008-03-01 11:59:04 +03:00
|
|
|
ruby_set_inplace_mode(s + 1);
|
1998-01-16 15:13:05 +03:00
|
|
|
break;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'x':
|
2008-10-30 04:34:23 +03:00
|
|
|
if (envopt) goto noenvopt;
|
2017-01-31 15:54:59 +03:00
|
|
|
forbid_setid("-x");
|
2009-09-13 15:18:51 +04:00
|
|
|
opt->xflag = TRUE;
|
1998-01-16 15:13:05 +03:00
|
|
|
s++;
|
|
|
|
if (*s && chdir(s) < 0) {
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_fatal("Can't chdir to %s", s);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
break;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2000-01-05 07:41:21 +03:00
|
|
|
case 'C':
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'X':
|
2008-10-30 04:34:23 +03:00
|
|
|
if (envopt) goto noenvopt;
|
2014-02-07 20:20:55 +04:00
|
|
|
if (!*++s && (!--argc || !(s = *++argv) || !*s)) {
|
2000-01-05 07:41:21 +03:00
|
|
|
rb_fatal("Can't chdir");
|
|
|
|
}
|
|
|
|
if (chdir(s) < 0) {
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_fatal("Can't chdir to %s", s);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
break;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'F':
|
2008-10-30 04:34:23 +03:00
|
|
|
if (envopt) goto noenvopt;
|
1999-12-06 12:04:03 +03:00
|
|
|
if (*++s) {
|
2008-01-05 07:04:26 +03:00
|
|
|
rb_fs = rb_reg_new(s, strlen(s), 0);
|
1999-12-06 12:04:03 +03:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
break;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2007-10-17 00:07:20 +04:00
|
|
|
case 'E':
|
2008-10-30 04:34:23 +03:00
|
|
|
if (!*++s && (!--argc || !(s = *++argv))) {
|
|
|
|
rb_raise(rb_eRuntimeError, "missing argument for -E");
|
|
|
|
}
|
2023-06-08 04:18:55 +03:00
|
|
|
proc_encoding_option(opt, s, "-E");
|
|
|
|
break;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2008-10-13 03:03:17 +04:00
|
|
|
case 'U':
|
2008-10-14 04:41:09 +04:00
|
|
|
set_internal_encoding_once(opt, "UTF-8", 0);
|
2008-10-14 09:11:20 +04:00
|
|
|
++s;
|
|
|
|
goto reswitch;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'K':
|
2023-06-08 04:18:55 +03:00
|
|
|
if (!(s = proc_K_option(opt, s))) break;
|
1998-01-16 15:13:05 +03:00
|
|
|
goto reswitch;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case 'I':
|
|
|
|
forbid_setid("-I");
|
|
|
|
if (*++s)
|
2005-04-21 01:44:20 +04:00
|
|
|
ruby_incpush_expand(s);
|
2014-02-07 20:20:55 +04:00
|
|
|
else if (argc > 1) {
|
2005-04-21 01:44:20 +04:00
|
|
|
ruby_incpush_expand(argv[1]);
|
2006-12-31 18:02:22 +03:00
|
|
|
argc--, argv++;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2002-05-23 11:41:53 +04:00
|
|
|
break;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case '0':
|
2008-10-30 04:34:23 +03:00
|
|
|
if (envopt) goto noenvopt;
|
2023-06-08 04:18:55 +03:00
|
|
|
if (!(s = proc_0_option(opt, s))) break;
|
1998-01-16 15:13:05 +03:00
|
|
|
goto reswitch;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case '-':
|
2003-01-16 10:38:40 +03:00
|
|
|
if (!s[1] || (s[1] == '\r' && !s[2])) {
|
2006-12-31 18:02:22 +03:00
|
|
|
argc--, argv++;
|
1998-01-16 15:13:05 +03:00
|
|
|
goto switch_end;
|
|
|
|
}
|
|
|
|
s++;
|
2008-10-30 04:34:23 +03:00
|
|
|
|
2023-06-08 05:07:50 +03:00
|
|
|
if (!(n = proc_long_options(opt, s, argc, argv, envopt))) goto switch_end;
|
|
|
|
--n;
|
|
|
|
argc -= n;
|
|
|
|
argv += n;
|
2022-07-21 19:23:58 +03:00
|
|
|
break;
|
|
|
|
|
2005-01-15 08:58:02 +03:00
|
|
|
case '\r':
|
2006-12-31 18:02:22 +03:00
|
|
|
if (!s[1])
|
2022-07-21 19:23:58 +03:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2023-06-08 04:18:55 +03:00
|
|
|
rb_raise(rb_eRuntimeError,
|
|
|
|
"invalid option -%c (-h will show valid options)",
|
|
|
|
(int)(unsigned char)*s);
|
2007-09-29 01:47:31 +04:00
|
|
|
goto switch_end;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2008-10-30 04:34:23 +03:00
|
|
|
noenvopt:
|
|
|
|
/* "EIdvwWrKU" only */
|
|
|
|
rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: -%c", *s);
|
|
|
|
break;
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_end:
|
2015-12-29 15:23:04 +03:00
|
|
|
if (warning) opt->warning = warning;
|
2007-09-29 01:47:31 +04:00
|
|
|
return argc0 - argc;
|
|
|
|
}
|
|
|
|
|
2019-12-10 10:19:13 +03:00
|
|
|
void Init_builtin_features(void);
|
|
|
|
|
2007-11-10 12:22:59 +03:00
|
|
|
static void
|
2011-01-15 03:48:16 +03:00
|
|
|
ruby_init_prelude(void)
|
2007-11-10 12:22:59 +03:00
|
|
|
{
|
2019-12-10 10:19:13 +03:00
|
|
|
Init_builtin_features();
|
2010-03-12 01:15:11 +03:00
|
|
|
rb_const_remove(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"));
|
2007-11-10 12:22:59 +03:00
|
|
|
}
|
|
|
|
|
2020-05-16 11:37:28 +03:00
|
|
|
void rb_call_builtin_inits(void);
|
|
|
|
|
2021-12-06 05:25:44 +03:00
|
|
|
// Initialize extra optional exts linked statically.
|
|
|
|
// This empty definition will be replaced with the actual strong symbol by linker.
|
|
|
|
#if RBIMPL_HAS_ATTRIBUTE(weak)
|
|
|
|
__attribute__((weak))
|
|
|
|
#endif
|
2022-08-06 04:13:20 +03:00
|
|
|
void
|
|
|
|
Init_extra_exts(void)
|
2021-12-06 05:25:44 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-05-16 11:37:28 +03:00
|
|
|
static void
|
|
|
|
ruby_opt_init(ruby_cmdline_options_t *opt)
|
|
|
|
{
|
2024-02-20 17:03:13 +03:00
|
|
|
rb_warning_category_update(opt->warn.mask, opt->warn.set);
|
|
|
|
|
2020-05-16 11:37:28 +03:00
|
|
|
if (opt->dump & dump_exit_bits) return;
|
|
|
|
|
2022-06-30 10:04:23 +03:00
|
|
|
if (FEATURE_SET_P(opt->features, gems)) {
|
2020-05-16 11:37:28 +03:00
|
|
|
rb_define_module("Gem");
|
2021-06-28 07:27:35 +03:00
|
|
|
if (opt->features.set & FEATURE_BIT(error_highlight)) {
|
|
|
|
rb_define_module("ErrorHighlight");
|
2021-06-18 11:11:39 +03:00
|
|
|
}
|
2020-05-16 11:37:28 +03:00
|
|
|
if (opt->features.set & FEATURE_BIT(did_you_mean)) {
|
|
|
|
rb_define_module("DidYouMean");
|
|
|
|
}
|
2022-07-26 23:16:21 +03:00
|
|
|
if (opt->features.set & FEATURE_BIT(syntax_suggest)) {
|
|
|
|
rb_define_module("SyntaxSuggest");
|
|
|
|
}
|
2020-05-16 11:37:28 +03:00
|
|
|
}
|
|
|
|
|
2023-08-24 21:23:19 +03:00
|
|
|
/* [Feature #19785] Warning for removed GC environment variable.
|
|
|
|
* Remove this in Ruby 3.4. */
|
|
|
|
if (getenv("RUBY_GC_HEAP_INIT_SLOTS")) {
|
|
|
|
rb_warn_deprecated("The environment variable RUBY_GC_HEAP_INIT_SLOTS",
|
2023-08-30 23:49:32 +03:00
|
|
|
"environment variables RUBY_GC_HEAP_%d_INIT_SLOTS");
|
2023-08-24 21:23:19 +03:00
|
|
|
}
|
|
|
|
|
2023-12-20 08:12:18 +03:00
|
|
|
if (getenv("RUBY_FREE_AT_EXIT")) {
|
|
|
|
rb_warn("Free at exit is experimental and may be unstable");
|
|
|
|
rb_free_at_exit = true;
|
2023-10-12 21:15:53 +03:00
|
|
|
}
|
|
|
|
|
2023-03-07 10:15:30 +03:00
|
|
|
#if USE_RJIT
|
|
|
|
// rb_call_builtin_inits depends on RubyVM::RJIT.enabled?
|
2023-03-07 10:17:25 +03:00
|
|
|
if (opt->rjit.on)
|
2023-03-09 10:14:33 +03:00
|
|
|
rb_rjit_enabled = true;
|
2023-03-07 10:17:25 +03:00
|
|
|
if (opt->rjit.stats)
|
2023-03-09 10:14:33 +03:00
|
|
|
rb_rjit_stats_enabled = true;
|
2023-03-12 23:55:39 +03:00
|
|
|
if (opt->rjit.trace_exits)
|
|
|
|
rb_rjit_trace_exits_enabled = true;
|
2022-09-05 07:53:46 +03:00
|
|
|
#endif
|
|
|
|
|
2020-05-16 11:37:28 +03:00
|
|
|
Init_ext(); /* load statically linked extensions before rubygems */
|
2021-12-06 05:25:44 +03:00
|
|
|
Init_extra_exts();
|
2023-10-18 11:47:48 +03:00
|
|
|
|
|
|
|
GET_VM()->running = 0;
|
2020-05-16 11:37:28 +03:00
|
|
|
rb_call_builtin_inits();
|
2023-10-18 11:47:48 +03:00
|
|
|
GET_VM()->running = 1;
|
|
|
|
memset(ruby_vm_redefined_flag, 0, sizeof(ruby_vm_redefined_flag));
|
|
|
|
|
2020-05-16 11:37:28 +03:00
|
|
|
ruby_init_prelude();
|
|
|
|
|
2022-10-24 19:20:44 +03:00
|
|
|
// Initialize JITs after prelude because JITing prelude is typically not optimal.
|
2023-03-07 10:15:30 +03:00
|
|
|
#if USE_RJIT
|
2023-03-09 10:14:33 +03:00
|
|
|
// Also, rb_rjit_init is safe only after rb_call_builtin_inits() defines RubyVM::RJIT::Compiler.
|
2023-03-07 10:17:25 +03:00
|
|
|
if (opt->rjit.on)
|
2023-03-09 10:14:33 +03:00
|
|
|
rb_rjit_init(&opt->rjit);
|
2022-09-05 07:53:46 +03:00
|
|
|
#endif
|
2022-10-24 19:20:44 +03:00
|
|
|
#if USE_YJIT
|
2023-11-02 19:15:48 +03:00
|
|
|
rb_yjit_init(opt->yjit);
|
2022-10-24 19:20:44 +03:00
|
|
|
#endif
|
2022-09-05 07:53:46 +03:00
|
|
|
|
2020-05-16 11:37:28 +03:00
|
|
|
ruby_set_script_name(opt->script_name);
|
|
|
|
require_libraries(&opt->req_list);
|
|
|
|
}
|
|
|
|
|
2008-01-09 09:54:26 +03:00
|
|
|
static int
|
|
|
|
opt_enc_index(VALUE enc_name)
|
|
|
|
{
|
|
|
|
const char *s = RSTRING_PTR(enc_name);
|
|
|
|
int i = rb_enc_find_index(s);
|
|
|
|
|
|
|
|
if (i < 0) {
|
|
|
|
rb_raise(rb_eRuntimeError, "unknown encoding name - %s", s);
|
|
|
|
}
|
|
|
|
else if (rb_enc_dummy_p(rb_enc_from_index(i))) {
|
|
|
|
rb_raise(rb_eRuntimeError, "dummy encoding is not acceptable - %s ", s);
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2013-08-07 18:12:08 +04:00
|
|
|
#define rb_progname (GET_VM()->progname)
|
|
|
|
#define rb_orig_progname (GET_VM()->orig_progname)
|
2008-06-10 06:25:18 +04:00
|
|
|
VALUE rb_argv0;
|
2018-11-10 14:43:02 +03:00
|
|
|
VALUE rb_e_script;
|
2008-01-25 10:11:18 +03:00
|
|
|
|
2008-12-08 05:28:17 +03:00
|
|
|
static VALUE
|
2019-08-27 05:16:52 +03:00
|
|
|
false_value(ID _x, VALUE *_y)
|
2008-12-08 05:28:17 +03:00
|
|
|
{
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2019-08-27 05:16:52 +03:00
|
|
|
true_value(ID _x, VALUE *_y)
|
2008-12-08 05:28:17 +03:00
|
|
|
{
|
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define rb_define_readonly_boolean(name, val) \
|
|
|
|
rb_define_virtual_variable((name), (val) ? true_value : false_value, 0)
|
|
|
|
|
2008-12-15 17:46:50 +03:00
|
|
|
static VALUE
|
* cont.c (rb_fiber_current), dln.c (dln_print_undef, dln_undefined),
eval.c (rb_iterator_p, rb_need_block), load.c: (Init_load), ruby.c
(uscore_get, rb_f_chop), st.c (stat_col), signal.c
(rb_signal_buff_size, ruby_sig_finalize), thread.c
(rb_thread_sleep_forever, rb_thread_sleep_deadly, rb_thread_alone):
protoized.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21929 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-02-01 15:51:44 +03:00
|
|
|
uscore_get(void)
|
2008-12-15 17:46:50 +03:00
|
|
|
{
|
|
|
|
VALUE line;
|
|
|
|
|
|
|
|
line = rb_lastline_get();
|
2011-09-29 15:07:45 +04:00
|
|
|
if (!RB_TYPE_P(line, T_STRING)) {
|
2008-12-15 17:46:50 +03:00
|
|
|
rb_raise(rb_eTypeError, "$_ value need to be String (%s given)",
|
|
|
|
NIL_P(line) ? "nil" : rb_obj_classname(line));
|
|
|
|
}
|
|
|
|
return line;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:07:33 +04:00
|
|
|
* sub(pattern, replacement) -> $_
|
2013-04-24 08:47:31 +04:00
|
|
|
* sub(pattern) {|...| block } -> $_
|
2009-01-21 07:59:20 +03:00
|
|
|
*
|
2008-12-15 17:46:50 +03:00
|
|
|
* Equivalent to <code>$_.sub(<i>args</i>)</code>, except that
|
|
|
|
* <code>$_</code> will be updated if substitution occurs.
|
|
|
|
* Available only when -p/-n command line option specified.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
2019-08-28 12:19:11 +03:00
|
|
|
rb_f_sub(int argc, VALUE *argv, VALUE _)
|
2008-12-15 17:46:50 +03:00
|
|
|
{
|
2012-10-14 07:30:50 +04:00
|
|
|
VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("sub"), argc, argv);
|
2008-12-15 17:46:50 +03:00
|
|
|
rb_lastline_set(str);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2013-04-24 08:47:31 +04:00
|
|
|
* gsub(pattern, replacement) -> $_
|
|
|
|
* gsub(pattern) {|...| block } -> $_
|
2009-01-21 07:59:20 +03:00
|
|
|
*
|
2008-12-15 17:46:50 +03:00
|
|
|
* Equivalent to <code>$_.gsub...</code>, except that <code>$_</code>
|
2013-04-24 08:47:31 +04:00
|
|
|
* will be updated if substitution occurs.
|
2008-12-15 17:46:50 +03:00
|
|
|
* Available only when -p/-n command line option specified.
|
2009-01-21 07:59:20 +03:00
|
|
|
*
|
2008-12-15 17:46:50 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
2019-08-28 12:19:11 +03:00
|
|
|
rb_f_gsub(int argc, VALUE *argv, VALUE _)
|
2008-12-15 17:46:50 +03:00
|
|
|
{
|
2012-10-14 07:30:50 +04:00
|
|
|
VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("gsub"), argc, argv);
|
2008-12-15 17:46:50 +03:00
|
|
|
rb_lastline_set(str);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2013-04-24 08:47:31 +04:00
|
|
|
* chop -> $_
|
2009-01-21 07:59:20 +03:00
|
|
|
*
|
2008-12-15 17:46:50 +03:00
|
|
|
* Equivalent to <code>($_.dup).chop!</code>, except <code>nil</code>
|
2019-03-28 06:33:35 +03:00
|
|
|
* is never returned. See String#chop!.
|
2008-12-15 17:46:50 +03:00
|
|
|
* Available only when -p/-n command line option specified.
|
2009-01-21 07:59:20 +03:00
|
|
|
*
|
2008-12-15 17:46:50 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
2019-08-28 12:19:11 +03:00
|
|
|
rb_f_chop(VALUE _)
|
2008-12-15 17:46:50 +03:00
|
|
|
{
|
2012-10-14 07:30:50 +04:00
|
|
|
VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("chop"), 0, 0);
|
2008-12-15 17:46:50 +03:00
|
|
|
rb_lastline_set(str);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-18 01:07:33 +04:00
|
|
|
* chomp -> $_
|
|
|
|
* chomp(string) -> $_
|
2009-01-21 07:59:20 +03:00
|
|
|
*
|
2008-12-15 17:46:50 +03:00
|
|
|
* Equivalent to <code>$_ = $_.chomp(<em>string</em>)</code>. See
|
2019-03-28 06:33:35 +03:00
|
|
|
* String#chomp.
|
2008-12-15 17:46:50 +03:00
|
|
|
* Available only when -p/-n command line option specified.
|
2009-01-21 07:59:20 +03:00
|
|
|
*
|
2008-12-15 17:46:50 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
2019-08-28 12:19:11 +03:00
|
|
|
rb_f_chomp(int argc, VALUE *argv, VALUE _)
|
2008-12-15 17:46:50 +03:00
|
|
|
{
|
2012-10-14 07:30:50 +04:00
|
|
|
VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("chomp"), argc, argv);
|
2008-12-15 17:46:50 +03:00
|
|
|
rb_lastline_set(str);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2020-04-12 06:56:17 +03:00
|
|
|
static void
|
|
|
|
setup_pager_env(void)
|
|
|
|
{
|
2023-06-05 12:43:33 +03:00
|
|
|
if (!getenv("LESS")) {
|
|
|
|
// Output "raw" control characters, and move per sections.
|
|
|
|
ruby_setenv("LESS", "-R +/^[A-Z].*");
|
|
|
|
}
|
2020-04-12 06:56:17 +03:00
|
|
|
}
|
|
|
|
|
2020-12-21 12:09:45 +03:00
|
|
|
#ifdef _WIN32
|
|
|
|
static int
|
|
|
|
tty_enabled(void)
|
|
|
|
{
|
|
|
|
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
DWORD m;
|
|
|
|
if (!GetConsoleMode(h, &m)) return 0;
|
|
|
|
# ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
2021-02-19 18:48:46 +03:00
|
|
|
# define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4
|
2020-12-21 12:09:45 +03:00
|
|
|
# endif
|
|
|
|
if (!(m & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#elif !defined(HAVE_WORKING_FORK)
|
|
|
|
# define tty_enabled() 0
|
|
|
|
#endif
|
|
|
|
|
2021-09-28 17:24:40 +03:00
|
|
|
static VALUE
|
|
|
|
copy_str(VALUE str, rb_encoding *enc, bool intern)
|
|
|
|
{
|
2021-09-29 13:59:31 +03:00
|
|
|
if (!intern) {
|
|
|
|
if (rb_enc_str_coderange_scan(str, enc) == ENC_CODERANGE_BROKEN)
|
|
|
|
return 0;
|
|
|
|
return rb_enc_associate(rb_str_dup(str), enc);
|
|
|
|
}
|
2021-09-28 17:24:40 +03:00
|
|
|
return rb_enc_interned_str(RSTRING_PTR(str), RSTRING_LEN(str), enc);
|
|
|
|
}
|
|
|
|
|
2023-02-01 16:45:45 +03:00
|
|
|
#if USE_YJIT
|
2023-01-31 20:18:41 +03:00
|
|
|
// Check that an environment variable is set to a truthy value
|
|
|
|
static bool
|
|
|
|
env_var_truthy(const char *name)
|
|
|
|
{
|
|
|
|
const char *value = getenv(name);
|
|
|
|
|
|
|
|
if (!value)
|
|
|
|
return false;
|
|
|
|
if (strcmp(value, "1") == 0)
|
|
|
|
return true;
|
|
|
|
if (strcmp(value, "true") == 0)
|
|
|
|
return true;
|
|
|
|
if (strcmp(value, "yes") == 0)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2023-02-01 16:42:12 +03:00
|
|
|
#endif
|
2023-01-31 20:18:41 +03:00
|
|
|
|
2023-05-21 10:47:14 +03:00
|
|
|
rb_pid_t rb_fork_ruby(int *status);
|
|
|
|
|
2024-02-15 17:30:29 +03:00
|
|
|
static void
|
|
|
|
show_help(const char *progname, int help)
|
|
|
|
{
|
|
|
|
int tty = isatty(1);
|
|
|
|
int columns = 0;
|
|
|
|
if (help && tty) {
|
|
|
|
const char *pager_env = getenv("RUBY_PAGER");
|
|
|
|
if (!pager_env) pager_env = getenv("PAGER");
|
|
|
|
if (pager_env && *pager_env && isatty(0)) {
|
|
|
|
const char *columns_env = getenv("COLUMNS");
|
|
|
|
if (columns_env) columns = atoi(columns_env);
|
|
|
|
VALUE pager = rb_str_new_cstr(pager_env);
|
|
|
|
#ifdef HAVE_WORKING_FORK
|
|
|
|
int fds[2];
|
|
|
|
if (rb_pipe(fds) == 0) {
|
|
|
|
rb_pid_t pid = rb_fork_ruby(NULL);
|
|
|
|
if (pid > 0) {
|
|
|
|
/* exec PAGER with reading from child */
|
|
|
|
dup2(fds[0], 0);
|
|
|
|
}
|
|
|
|
else if (pid == 0) {
|
|
|
|
/* send the help message to the parent PAGER */
|
|
|
|
dup2(fds[1], 1);
|
|
|
|
dup2(fds[1], 2);
|
|
|
|
}
|
|
|
|
close(fds[0]);
|
|
|
|
close(fds[1]);
|
|
|
|
if (pid > 0) {
|
|
|
|
setup_pager_env();
|
|
|
|
rb_f_exec(1, &pager);
|
|
|
|
kill(SIGTERM, pid);
|
|
|
|
rb_waitpid(pid, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
setup_pager_env();
|
|
|
|
VALUE port = rb_io_popen(pager, rb_str_new_lit("w"), Qnil, Qnil);
|
|
|
|
if (!NIL_P(port)) {
|
|
|
|
int oldout = dup(1);
|
|
|
|
int olderr = dup(2);
|
|
|
|
int fd = RFILE(port)->fptr->fd;
|
|
|
|
tty = tty_enabled();
|
|
|
|
dup2(fd, 1);
|
|
|
|
dup2(fd, 2);
|
|
|
|
usage(progname, 1, tty, columns);
|
|
|
|
fflush(stdout);
|
|
|
|
dup2(oldout, 1);
|
|
|
|
dup2(olderr, 2);
|
|
|
|
rb_io_close(port);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
usage(progname, help, tty, columns);
|
|
|
|
}
|
|
|
|
|
2024-02-16 06:22:58 +03:00
|
|
|
static rb_ast_t *
|
|
|
|
process_script(ruby_cmdline_options_t *opt)
|
|
|
|
{
|
|
|
|
rb_ast_t *ast;
|
|
|
|
VALUE parser = rb_parser_new();
|
|
|
|
|
|
|
|
if (opt->dump & DUMP_BIT(yydebug)) {
|
|
|
|
rb_parser_set_yydebug(parser, Qtrue);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opt->dump & DUMP_BIT(error_tolerant)) {
|
|
|
|
rb_parser_error_tolerant(parser);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opt->e_script) {
|
|
|
|
VALUE progname = rb_progname;
|
|
|
|
rb_parser_set_context(parser, 0, TRUE);
|
|
|
|
|
|
|
|
ruby_opt_init(opt);
|
|
|
|
ruby_set_script_name(progname);
|
|
|
|
rb_parser_set_options(parser, opt->do_print, opt->do_loop,
|
|
|
|
opt->do_line, opt->do_split);
|
|
|
|
ast = rb_parser_compile_string(parser, opt->script, opt->e_script, 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
VALUE f;
|
|
|
|
int xflag = opt->xflag;
|
|
|
|
f = open_load_file(opt->script_name, &xflag);
|
|
|
|
opt->xflag = xflag != 0;
|
|
|
|
rb_parser_set_context(parser, 0, f == rb_stdin);
|
|
|
|
ast = load_file(parser, opt->script_name, f, 1, opt);
|
|
|
|
}
|
|
|
|
if (!ast->body.root) {
|
|
|
|
rb_ast_dispose(ast);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return ast;
|
|
|
|
}
|
|
|
|
|
2024-02-28 20:12:45 +03:00
|
|
|
/**
|
|
|
|
* Call ruby_opt_init to set up the global state based on the command line
|
|
|
|
* options, and then warn if prism is enabled and the experimental warning
|
|
|
|
* category is enabled.
|
|
|
|
*/
|
2024-02-16 06:22:58 +03:00
|
|
|
static void
|
2024-02-28 20:12:45 +03:00
|
|
|
prism_opt_init(ruby_cmdline_options_t *opt)
|
2024-02-16 06:22:58 +03:00
|
|
|
{
|
|
|
|
ruby_opt_init(opt);
|
|
|
|
|
2024-02-14 18:32:09 +03:00
|
|
|
if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL)) {
|
|
|
|
rb_category_warn(
|
|
|
|
RB_WARN_CATEGORY_EXPERIMENTAL,
|
|
|
|
"The compiler based on the Prism parser is currently experimental "
|
|
|
|
"and compatibility with the compiler based on parse.y is not yet "
|
|
|
|
"complete. Please report any issues you find on the `ruby/prism` "
|
|
|
|
"issue tracker."
|
|
|
|
);
|
|
|
|
}
|
2024-02-28 20:12:45 +03:00
|
|
|
}
|
2024-02-14 18:32:09 +03:00
|
|
|
|
2024-02-28 20:12:45 +03:00
|
|
|
/**
|
|
|
|
* Process the command line options and parse the script into the given result.
|
|
|
|
* Raise an error if the script cannot be parsed.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result)
|
|
|
|
{
|
|
|
|
memset(result, 0, sizeof(pm_parse_result_t));
|
|
|
|
|
2024-02-29 19:01:07 +03:00
|
|
|
pm_options_t *options = &result->options;
|
2024-02-28 18:38:48 +03:00
|
|
|
pm_options_line_set(options, 1);
|
2024-02-29 19:01:07 +03:00
|
|
|
|
2024-03-18 17:58:54 +03:00
|
|
|
if (opt->ext.enc.name != 0) {
|
|
|
|
pm_options_encoding_set(options, StringValueCStr(opt->ext.enc.name));
|
|
|
|
}
|
|
|
|
|
2024-02-29 19:01:07 +03:00
|
|
|
uint8_t command_line = 0;
|
|
|
|
if (opt->do_split) command_line |= PM_OPTIONS_COMMAND_LINE_A;
|
|
|
|
if (opt->do_line) command_line |= PM_OPTIONS_COMMAND_LINE_L;
|
|
|
|
if (opt->do_loop) command_line |= PM_OPTIONS_COMMAND_LINE_N;
|
|
|
|
if (opt->do_print) command_line |= PM_OPTIONS_COMMAND_LINE_P;
|
|
|
|
if (opt->xflag) command_line |= PM_OPTIONS_COMMAND_LINE_X;
|
2024-02-16 06:22:58 +03:00
|
|
|
|
|
|
|
VALUE error;
|
|
|
|
if (strcmp(opt->script, "-") == 0) {
|
2024-03-11 18:05:31 +03:00
|
|
|
pm_options_command_line_set(options, command_line);
|
|
|
|
pm_options_filepath_set(options, "-");
|
|
|
|
|
|
|
|
prism_opt_init(opt);
|
|
|
|
error = pm_parse_stdin(result);
|
2024-02-16 06:22:58 +03:00
|
|
|
}
|
|
|
|
else if (opt->e_script) {
|
2024-02-29 19:01:07 +03:00
|
|
|
command_line |= PM_OPTIONS_COMMAND_LINE_E;
|
|
|
|
pm_options_command_line_set(options, command_line);
|
|
|
|
|
2024-02-28 20:12:45 +03:00
|
|
|
prism_opt_init(opt);
|
2024-02-16 06:22:58 +03:00
|
|
|
error = pm_parse_string(result, opt->e_script, rb_str_new2("-e"));
|
|
|
|
}
|
|
|
|
else {
|
2024-02-29 19:01:07 +03:00
|
|
|
pm_options_command_line_set(options, command_line);
|
2024-02-28 20:12:45 +03:00
|
|
|
error = pm_load_file(result, opt->script_name);
|
|
|
|
|
|
|
|
// If reading the file did not error, at that point we load the command
|
|
|
|
// line options. We do it in this order so that if the main script fails
|
|
|
|
// to load, it doesn't require files required by -r.
|
|
|
|
if (NIL_P(error)) {
|
|
|
|
prism_opt_init(opt);
|
|
|
|
error = pm_parse_file(result, opt->script_name);
|
|
|
|
}
|
2024-02-16 06:22:58 +03:00
|
|
|
|
2024-02-28 20:12:45 +03:00
|
|
|
// If we found an __END__ marker, then we're going to define a global
|
|
|
|
// DATA constant that is a file object that can be read to read the
|
|
|
|
// contents after the marker.
|
2024-02-16 06:22:58 +03:00
|
|
|
if (NIL_P(error) && result->parser.data_loc.start != NULL) {
|
|
|
|
int xflag = opt->xflag;
|
|
|
|
VALUE file = open_load_file(opt->script_name, &xflag);
|
|
|
|
|
2024-02-28 20:12:45 +03:00
|
|
|
const pm_parser_t *parser = &result->parser;
|
|
|
|
size_t offset = parser->data_loc.start - parser->start + 7;
|
|
|
|
|
|
|
|
if ((parser->start + offset < parser->end) && parser->start[offset] == '\r') offset++;
|
|
|
|
if ((parser->start + offset < parser->end) && parser->start[offset] == '\n') offset++;
|
2024-02-16 06:22:58 +03:00
|
|
|
|
2024-02-16 07:12:26 +03:00
|
|
|
rb_funcall(file, rb_intern_const("seek"), 2, SIZET2NUM(offset), INT2FIX(SEEK_SET));
|
2024-02-16 06:22:58 +03:00
|
|
|
rb_define_global_const("DATA", file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!NIL_P(error)) {
|
|
|
|
pm_parse_result_free(result);
|
|
|
|
rb_exc_raise(error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
prism_dump_tree(pm_parse_result_t *result)
|
|
|
|
{
|
|
|
|
pm_buffer_t output_buffer = { 0 };
|
|
|
|
|
|
|
|
pm_prettyprint(&output_buffer, &result->parser, result->node.ast_node);
|
|
|
|
VALUE tree = rb_str_new(output_buffer.value, output_buffer.length);
|
|
|
|
pm_buffer_free(&output_buffer);
|
|
|
|
return tree;
|
|
|
|
}
|
|
|
|
|
2024-02-16 06:25:48 +03:00
|
|
|
static void
|
|
|
|
process_options_global_setup(const ruby_cmdline_options_t *opt, const rb_iseq_t *iseq)
|
|
|
|
{
|
|
|
|
if (OPT_BACKTRACE_LENGTH_LIMIT_VALID_P(opt)) {
|
|
|
|
rb_backtrace_length_limit = opt->backtrace_length_limit;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opt->do_loop) {
|
|
|
|
rb_define_global_function("sub", rb_f_sub, -1);
|
|
|
|
rb_define_global_function("gsub", rb_f_gsub, -1);
|
|
|
|
rb_define_global_function("chop", rb_f_chop, 0);
|
|
|
|
rb_define_global_function("chomp", rb_f_chomp, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
rb_define_readonly_boolean("$-p", opt->do_print);
|
|
|
|
rb_define_readonly_boolean("$-l", opt->do_line);
|
|
|
|
rb_define_readonly_boolean("$-a", opt->do_split);
|
|
|
|
|
|
|
|
rb_gvar_ractor_local("$-p");
|
|
|
|
rb_gvar_ractor_local("$-l");
|
|
|
|
rb_gvar_ractor_local("$-a");
|
|
|
|
|
|
|
|
if ((rb_e_script = opt->e_script) != 0) {
|
|
|
|
rb_str_freeze(rb_e_script);
|
2024-03-03 12:46:46 +03:00
|
|
|
rb_vm_register_global_object(opt->e_script);
|
2024-02-16 06:25:48 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
rb_execution_context_t *ec = GET_EC();
|
|
|
|
VALUE script = (opt->e_script ? opt->e_script : Qnil);
|
|
|
|
rb_exec_event_hook_script_compiled(ec, iseq, script);
|
|
|
|
}
|
|
|
|
|
2007-10-03 05:06:57 +04:00
|
|
|
static VALUE
|
2016-08-19 13:44:53 +03:00
|
|
|
process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
|
2007-09-29 01:47:31 +04:00
|
|
|
{
|
2024-02-16 06:22:58 +03:00
|
|
|
struct {
|
|
|
|
rb_ast_t *ast;
|
|
|
|
pm_parse_result_t prism;
|
|
|
|
} result = {0};
|
|
|
|
#define dispose_result() \
|
|
|
|
(result.ast ? rb_ast_dispose(result.ast) : pm_parse_result_free(&result.prism))
|
|
|
|
|
2023-12-06 03:57:29 +03:00
|
|
|
const rb_iseq_t *iseq;
|
2016-04-24 06:42:25 +03:00
|
|
|
rb_encoding *enc, *lenc;
|
2016-04-26 17:35:24 +03:00
|
|
|
#if UTF8_PATH
|
2020-11-23 03:16:16 +03:00
|
|
|
rb_encoding *ienc = 0;
|
|
|
|
rb_encoding *const uenc = rb_utf8_encoding();
|
2016-04-26 17:35:24 +03:00
|
|
|
#endif
|
2007-09-29 01:47:31 +04:00
|
|
|
const char *s;
|
2008-05-08 01:43:54 +04:00
|
|
|
char fbuf[MAXPATHLEN];
|
2009-06-22 09:35:51 +04:00
|
|
|
int i = (int)proc_options(argc, argv, opt, 0);
|
2016-12-07 17:39:24 +03:00
|
|
|
unsigned int dump = opt->dump & dump_exit_bits;
|
2021-09-27 19:32:50 +03:00
|
|
|
rb_vm_t *vm = GET_VM();
|
|
|
|
const long loaded_before_enc = RARRAY_LEN(vm->loaded_features);
|
2007-09-29 01:47:31 +04:00
|
|
|
|
2012-11-23 12:31:52 +04:00
|
|
|
if (opt->dump & (DUMP_BIT(usage)|DUMP_BIT(help))) {
|
2017-08-09 14:03:55 +03:00
|
|
|
const char *const progname =
|
|
|
|
(argc > 0 && argv && argv[0] ? argv[0] :
|
|
|
|
origarg.argc > 0 && origarg.argv && origarg.argv[0] ? origarg.argv[0] :
|
|
|
|
ruby_engine);
|
2024-02-15 17:30:29 +03:00
|
|
|
show_help(progname, (opt->dump & DUMP_BIT(help)));
|
2008-12-08 05:28:17 +03:00
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
|
2017-08-09 14:03:55 +03:00
|
|
|
argc -= i;
|
|
|
|
argv += i;
|
|
|
|
|
2022-07-01 03:37:00 +03:00
|
|
|
if (FEATURE_SET_P(opt->features, rubyopt) && (s = getenv("RUBYOPT"))) {
|
2008-10-30 04:34:23 +03:00
|
|
|
moreswitches(s, opt, 1);
|
1999-10-21 11:52:15 +04:00
|
|
|
}
|
|
|
|
|
2012-07-04 20:01:01 +04:00
|
|
|
if (opt->src.enc.name)
|
2020-09-28 20:10:31 +03:00
|
|
|
/* cannot set deprecated category, as enabling deprecation warnings based on flags
|
|
|
|
* has not happened yet.
|
|
|
|
*/
|
|
|
|
rb_warning("-K is specified; it is for 1.8 compatibility and may cause odd behavior");
|
2012-07-04 20:01:01 +04:00
|
|
|
|
2022-06-29 19:09:51 +03:00
|
|
|
if (!(FEATURE_SET_BITS(opt->features) & feature_jit_mask)) {
|
2022-08-15 20:05:12 +03:00
|
|
|
#if USE_YJIT
|
2023-01-31 20:18:41 +03:00
|
|
|
if (!FEATURE_USED_P(opt->features, yjit) && env_var_truthy("RUBY_YJIT_ENABLE")) {
|
2022-06-29 19:09:51 +03:00
|
|
|
FEATURE_SET(opt->features, FEATURE_BIT(yjit));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2022-07-08 13:04:57 +03:00
|
|
|
if (MULTI_BITS_P(FEATURE_SET_BITS(opt->features) & feature_jit_mask)) {
|
2023-03-07 10:15:30 +03:00
|
|
|
rb_warn("RJIT and YJIT cannot both be enabled at the same time. Exiting");
|
2022-07-08 13:04:57 +03:00
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2023-03-07 10:15:30 +03:00
|
|
|
#if USE_RJIT
|
2023-03-07 10:17:25 +03:00
|
|
|
if (FEATURE_SET_P(opt->features, rjit)) {
|
2023-03-09 10:14:33 +03:00
|
|
|
opt->rjit.on = true; // set opt->rjit.on for Init_ruby_description() and calling rb_rjit_init()
|
2018-07-18 15:45:54 +03:00
|
|
|
}
|
2021-09-08 20:21:03 +03:00
|
|
|
#endif
|
2022-08-15 20:05:12 +03:00
|
|
|
#if USE_YJIT
|
2022-06-29 19:09:51 +03:00
|
|
|
if (FEATURE_SET_P(opt->features, yjit)) {
|
2022-10-24 19:20:44 +03:00
|
|
|
opt->yjit = true; // set opt->yjit for Init_ruby_description() and calling rb_yjit_init()
|
2021-09-07 22:57:33 +03:00
|
|
|
}
|
2022-06-29 19:09:51 +03:00
|
|
|
#endif
|
2023-10-17 03:51:53 +03:00
|
|
|
|
|
|
|
ruby_mn_threads_params();
|
2022-10-24 19:20:44 +03:00
|
|
|
Init_ruby_description(opt);
|
2023-10-17 03:51:53 +03:00
|
|
|
|
2022-06-14 18:08:36 +03:00
|
|
|
if (opt->dump & (DUMP_BIT(version) | DUMP_BIT(version_v))) {
|
1999-01-20 07:59:39 +03:00
|
|
|
ruby_show_version();
|
2012-08-09 13:33:49 +04:00
|
|
|
if (opt->dump & DUMP_BIT(version)) return Qtrue;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2008-12-08 05:28:17 +03:00
|
|
|
if (opt->dump & DUMP_BIT(copyright)) {
|
1999-01-20 07:59:39 +03:00
|
|
|
ruby_show_copyright();
|
2016-01-07 05:34:33 +03:00
|
|
|
return Qtrue;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2007-09-29 01:47:31 +04:00
|
|
|
if (!opt->e_script) {
|
2017-08-09 14:03:55 +03:00
|
|
|
if (argc <= 0) { /* no more args */
|
2007-09-29 01:47:31 +04:00
|
|
|
if (opt->verbose)
|
2007-10-03 05:06:57 +04:00
|
|
|
return Qtrue;
|
2007-09-29 01:47:31 +04:00
|
|
|
opt->script = "-";
|
2001-09-03 09:37:42 +04:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
else {
|
2007-09-29 01:47:31 +04:00
|
|
|
opt->script = argv[0];
|
2012-11-23 19:00:55 +04:00
|
|
|
if (!opt->script || opt->script[0] == '\0') {
|
2007-09-29 01:47:31 +04:00
|
|
|
opt->script = "-";
|
2003-02-13 06:02:19 +03:00
|
|
|
}
|
2007-09-29 01:47:31 +04:00
|
|
|
else if (opt->do_search) {
|
2021-03-12 10:46:40 +03:00
|
|
|
const char *path = getenv("RUBYPATH");
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2007-09-29 01:47:31 +04:00
|
|
|
opt->script = 0;
|
1999-10-15 12:52:18 +04:00
|
|
|
if (path) {
|
2008-05-08 01:43:54 +04:00
|
|
|
opt->script = dln_find_file_r(argv[0], path, fbuf, sizeof(fbuf));
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2007-09-29 01:47:31 +04:00
|
|
|
if (!opt->script) {
|
2008-05-08 01:43:54 +04:00
|
|
|
opt->script = dln_find_file_r(argv[0], getenv(PATH_ENV), fbuf, sizeof(fbuf));
|
1999-10-15 12:52:18 +04:00
|
|
|
}
|
2007-09-29 01:47:31 +04:00
|
|
|
if (!opt->script)
|
|
|
|
opt->script = argv[0];
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2006-12-31 18:02:22 +03:00
|
|
|
argc--;
|
|
|
|
argv++;
|
2003-02-13 03:59:00 +03:00
|
|
|
}
|
2017-01-31 15:54:59 +03:00
|
|
|
if (opt->script[0] == '-' && !opt->script[1]) {
|
|
|
|
forbid_setid("program input from stdin");
|
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2008-12-15 05:32:21 +03:00
|
|
|
opt->script_name = rb_str_new_cstr(opt->script);
|
|
|
|
opt->script = RSTRING_PTR(opt->script_name);
|
2014-11-29 18:02:25 +03:00
|
|
|
|
2021-04-29 15:31:05 +03:00
|
|
|
#ifdef _WIN32
|
2014-11-29 18:02:25 +03:00
|
|
|
translit_char_bin(RSTRING_PTR(opt->script_name), '\\', '/');
|
|
|
|
#elif defined DOSISH
|
2009-02-19 09:11:41 +03:00
|
|
|
translit_char(RSTRING_PTR(opt->script_name), '\\', '/');
|
2008-04-15 21:26:29 +04:00
|
|
|
#endif
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2019-09-21 05:06:22 +03:00
|
|
|
ruby_gc_set_params();
|
|
|
|
ruby_init_loadpath();
|
2018-02-05 19:51:12 +03:00
|
|
|
|
2012-05-16 09:39:06 +04:00
|
|
|
Init_enc();
|
2008-05-07 15:25:23 +04:00
|
|
|
lenc = rb_locale_encoding();
|
2008-09-14 11:07:31 +04:00
|
|
|
rb_enc_associate(rb_progname, lenc);
|
2011-07-07 10:44:46 +04:00
|
|
|
rb_obj_freeze(rb_progname);
|
2008-01-25 07:18:14 +03:00
|
|
|
if (opt->ext.enc.name != 0) {
|
|
|
|
opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
|
2007-12-31 17:57:46 +03:00
|
|
|
}
|
2008-10-07 21:39:44 +04:00
|
|
|
if (opt->intern.enc.name != 0) {
|
|
|
|
opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
|
|
|
|
}
|
2008-01-25 07:18:14 +03:00
|
|
|
if (opt->src.enc.name != 0) {
|
|
|
|
opt->src.enc.index = opt_enc_index(opt->src.enc.name);
|
2008-01-25 10:11:18 +03:00
|
|
|
src_encoding_index = opt->src.enc.index;
|
2008-01-25 07:18:14 +03:00
|
|
|
}
|
2009-02-06 06:12:09 +03:00
|
|
|
if (opt->ext.enc.index >= 0) {
|
|
|
|
enc = rb_enc_from_index(opt->ext.enc.index);
|
|
|
|
}
|
|
|
|
else {
|
2020-12-07 19:48:37 +03:00
|
|
|
enc = IF_UTF8_PATH(uenc, lenc);
|
2009-02-06 06:12:09 +03:00
|
|
|
}
|
|
|
|
rb_enc_set_default_external(rb_enc_from_encoding(enc));
|
2008-10-07 21:39:44 +04:00
|
|
|
if (opt->intern.enc.index >= 0) {
|
|
|
|
enc = rb_enc_from_index(opt->intern.enc.index);
|
|
|
|
rb_enc_set_default_internal(rb_enc_from_encoding(enc));
|
|
|
|
opt->intern.enc.index = -1;
|
2016-04-26 17:35:24 +03:00
|
|
|
#if UTF8_PATH
|
|
|
|
ienc = enc;
|
|
|
|
#endif
|
2008-10-07 21:39:44 +04:00
|
|
|
}
|
2020-11-23 03:16:16 +03:00
|
|
|
rb_enc_associate(opt->script_name, IF_UTF8_PATH(uenc, lenc));
|
2017-06-08 05:07:42 +03:00
|
|
|
#if UTF8_PATH
|
|
|
|
if (uenc != lenc) {
|
2017-05-17 07:47:05 +03:00
|
|
|
opt->script_name = str_conv_enc(opt->script_name, uenc, lenc);
|
|
|
|
opt->script = RSTRING_PTR(opt->script_name);
|
|
|
|
}
|
2017-06-08 05:07:42 +03:00
|
|
|
#endif
|
2011-07-07 10:44:46 +04:00
|
|
|
rb_obj_freeze(opt->script_name);
|
2017-05-17 07:47:05 +03:00
|
|
|
if (IF_UTF8_PATH(uenc != lenc, 1)) {
|
2008-12-15 05:32:21 +03:00
|
|
|
long i;
|
2019-05-20 12:10:35 +03:00
|
|
|
VALUE load_path = vm->load_path;
|
2015-07-02 08:12:04 +03:00
|
|
|
const ID id_initial_load_path_mark = INITIAL_LOAD_PATH_MARK;
|
2019-05-20 12:10:35 +03:00
|
|
|
int modifiable = FALSE;
|
|
|
|
|
|
|
|
rb_get_expanded_load_path();
|
2008-12-15 05:32:21 +03:00
|
|
|
for (i = 0; i < RARRAY_LEN(load_path); ++i) {
|
2014-08-23 06:52:23 +04:00
|
|
|
VALUE path = RARRAY_AREF(load_path, i);
|
2015-07-02 08:12:04 +03:00
|
|
|
int mark = rb_attr_get(path, id_initial_load_path_mark) == path;
|
2016-06-02 11:05:21 +03:00
|
|
|
#if UTF8_PATH
|
2016-06-03 15:27:24 +03:00
|
|
|
VALUE newpath = rb_str_conv_enc(path, uenc, lenc);
|
|
|
|
if (newpath == path) continue;
|
|
|
|
path = newpath;
|
2016-06-02 11:05:21 +03:00
|
|
|
#else
|
2021-09-29 13:59:31 +03:00
|
|
|
if (!(path = copy_str(path, lenc, !mark))) continue;
|
2016-06-02 11:05:21 +03:00
|
|
|
#endif
|
2015-07-02 08:12:04 +03:00
|
|
|
if (mark) rb_ivar_set(path, id_initial_load_path_mark, path);
|
2019-05-20 12:10:35 +03:00
|
|
|
if (!modifiable) {
|
|
|
|
rb_ary_modify(load_path);
|
|
|
|
modifiable = TRUE;
|
|
|
|
}
|
2014-08-23 06:52:23 +04:00
|
|
|
RARRAY_ASET(load_path, i, path);
|
2008-12-15 05:32:21 +03:00
|
|
|
}
|
2019-05-20 12:10:35 +03:00
|
|
|
if (modifiable) {
|
|
|
|
rb_ary_replace(vm->load_path_snapshot, load_path);
|
|
|
|
}
|
2008-12-15 05:32:21 +03:00
|
|
|
}
|
2021-09-27 19:32:50 +03:00
|
|
|
{
|
|
|
|
VALUE loaded_features = vm->loaded_features;
|
2021-09-28 17:25:51 +03:00
|
|
|
bool modified = false;
|
2021-09-27 19:32:50 +03:00
|
|
|
for (long i = loaded_before_enc; i < RARRAY_LEN(loaded_features); ++i) {
|
|
|
|
VALUE path = RARRAY_AREF(loaded_features, i);
|
2021-09-29 13:59:31 +03:00
|
|
|
if (!(path = copy_str(path, IF_UTF8_PATH(uenc, lenc), true))) continue;
|
2022-01-04 21:54:21 +03:00
|
|
|
if (!modified) {
|
|
|
|
rb_ary_modify(loaded_features);
|
|
|
|
modified = true;
|
|
|
|
}
|
2021-09-27 19:32:50 +03:00
|
|
|
RARRAY_ASET(loaded_features, i, path);
|
|
|
|
}
|
2021-09-28 17:25:51 +03:00
|
|
|
if (modified) {
|
|
|
|
rb_ary_replace(vm->loaded_features_snapshot, loaded_features);
|
|
|
|
}
|
2021-09-27 19:32:50 +03:00
|
|
|
}
|
2020-05-16 11:37:28 +03:00
|
|
|
|
2019-03-30 17:31:35 +03:00
|
|
|
if (opt->features.mask & COMPILATION_FEATURES) {
|
2015-10-23 22:02:55 +03:00
|
|
|
VALUE option = rb_hash_new();
|
2015-11-19 08:58:31 +03:00
|
|
|
#define SET_COMPILE_OPTION(h, o, name) \
|
2022-06-30 10:04:23 +03:00
|
|
|
rb_hash_aset((h), ID2SYM(rb_intern_const(#name)), \
|
|
|
|
RBOOL(FEATURE_SET_P(o->features, name)))
|
2015-11-19 08:58:31 +03:00
|
|
|
SET_COMPILE_OPTION(option, opt, frozen_string_literal);
|
2015-11-25 11:02:29 +03:00
|
|
|
SET_COMPILE_OPTION(option, opt, debug_frozen_string_literal);
|
2015-10-23 22:02:55 +03:00
|
|
|
rb_funcallv(rb_cISeq, rb_intern_const("compile_option="), 1, &option);
|
2015-11-19 08:58:31 +03:00
|
|
|
#undef SET_COMPILE_OPTION
|
2015-10-23 22:02:55 +03:00
|
|
|
}
|
2008-10-18 14:36:20 +04:00
|
|
|
ruby_set_argv(argc, argv);
|
2023-07-13 10:58:48 +03:00
|
|
|
opt->sflag = process_sflag(opt->sflag);
|
2008-02-16 02:03:22 +03:00
|
|
|
|
2024-02-16 06:22:58 +03:00
|
|
|
if (opt->e_script) {
|
|
|
|
rb_encoding *eenc;
|
|
|
|
if (opt->src.enc.index >= 0) {
|
|
|
|
eenc = rb_enc_from_index(opt->src.enc.index);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
eenc = lenc;
|
2023-12-06 03:57:29 +03:00
|
|
|
#if UTF8_PATH
|
2024-02-16 06:22:58 +03:00
|
|
|
if (ienc) eenc = ienc;
|
2023-12-06 03:57:29 +03:00
|
|
|
#endif
|
2023-12-08 02:47:36 +03:00
|
|
|
}
|
2024-02-16 06:22:58 +03:00
|
|
|
#if UTF8_PATH
|
|
|
|
if (eenc != uenc) {
|
|
|
|
opt->e_script = str_conv_enc(opt->e_script, uenc, eenc);
|
2023-12-08 02:47:36 +03:00
|
|
|
}
|
2024-02-16 06:22:58 +03:00
|
|
|
#endif
|
|
|
|
rb_enc_associate(opt->e_script, eenc);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(*rb_ruby_prism_ptr())) {
|
|
|
|
if (!(result.ast = process_script(opt))) return Qfalse;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
prism_script(opt, &result.prism);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2012-06-14 06:22:08 +04:00
|
|
|
ruby_set_script_name(opt->script_name);
|
2024-02-16 06:22:58 +03:00
|
|
|
if ((dump & DUMP_BIT(yydebug)) && !(dump &= ~DUMP_BIT(yydebug))) {
|
|
|
|
dispose_result();
|
|
|
|
return Qtrue;
|
2016-12-07 17:39:24 +03:00
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2009-02-06 06:05:27 +03:00
|
|
|
if (opt->ext.enc.index >= 0) {
|
|
|
|
enc = rb_enc_from_index(opt->ext.enc.index);
|
|
|
|
}
|
|
|
|
else {
|
2020-12-07 19:48:37 +03:00
|
|
|
enc = IF_UTF8_PATH(uenc, lenc);
|
2009-02-06 06:05:27 +03:00
|
|
|
}
|
|
|
|
rb_enc_set_default_external(rb_enc_from_encoding(enc));
|
2008-10-07 21:39:44 +04:00
|
|
|
if (opt->intern.enc.index >= 0) {
|
|
|
|
/* Set in the shebang line */
|
|
|
|
enc = rb_enc_from_index(opt->intern.enc.index);
|
|
|
|
rb_enc_set_default_internal(rb_enc_from_encoding(enc));
|
|
|
|
}
|
2008-12-13 09:58:58 +03:00
|
|
|
else if (!rb_default_internal_encoding())
|
2008-10-07 21:39:44 +04:00
|
|
|
/* Freeze default_internal */
|
|
|
|
rb_enc_set_default_internal(Qnil);
|
2009-07-31 11:37:02 +04:00
|
|
|
rb_stdio_set_default_encoding();
|
2008-10-07 21:39:44 +04:00
|
|
|
|
2023-07-13 10:58:48 +03:00
|
|
|
opt->sflag = process_sflag(opt->sflag);
|
2007-09-29 01:47:31 +04:00
|
|
|
opt->xflag = 0;
|
2001-05-30 13:12:34 +04:00
|
|
|
|
2016-12-07 17:39:24 +03:00
|
|
|
if (dump & DUMP_BIT(syntax)) {
|
2007-12-04 08:34:37 +03:00
|
|
|
printf("Syntax OK\n");
|
2016-12-07 17:39:24 +03:00
|
|
|
dump &= ~DUMP_BIT(syntax);
|
|
|
|
if (!dump) return Qtrue;
|
2007-12-04 08:34:37 +03:00
|
|
|
}
|
|
|
|
|
2024-02-16 06:22:58 +03:00
|
|
|
if (dump & (DUMP_BIT(parsetree)|DUMP_BIT(parsetree_with_comment))) {
|
|
|
|
VALUE tree;
|
|
|
|
if (result.ast) {
|
|
|
|
int comment = dump & DUMP_BIT(parsetree_with_comment);
|
|
|
|
tree = rb_parser_dump_tree(result.ast->body.root, comment);
|
2024-01-31 22:25:27 +03:00
|
|
|
}
|
|
|
|
else {
|
2024-02-16 06:22:58 +03:00
|
|
|
tree = prism_dump_tree(&result.prism);
|
2024-01-31 22:25:27 +03:00
|
|
|
}
|
2024-02-16 06:22:58 +03:00
|
|
|
rb_io_write(rb_stdout, tree);
|
2009-12-09 17:05:59 +03:00
|
|
|
rb_io_flush(rb_stdout);
|
2016-12-07 17:39:24 +03:00
|
|
|
dump &= ~DUMP_BIT(parsetree)&~DUMP_BIT(parsetree_with_comment);
|
2017-10-27 19:44:57 +03:00
|
|
|
if (!dump) {
|
2024-02-16 06:22:58 +03:00
|
|
|
dispose_result();
|
2017-10-27 19:44:57 +03:00
|
|
|
return Qtrue;
|
|
|
|
}
|
2009-12-09 17:05:59 +03:00
|
|
|
}
|
|
|
|
|
2016-03-29 00:39:24 +03:00
|
|
|
{
|
2010-03-16 20:40:00 +03:00
|
|
|
VALUE path = Qnil;
|
2012-12-21 14:39:59 +04:00
|
|
|
if (!opt->e_script && strcmp(opt->script, "-")) {
|
2024-02-16 06:22:58 +03:00
|
|
|
path = rb_realpath_internal(Qnil, opt->script_name, 1);
|
2017-10-21 18:43:05 +03:00
|
|
|
#if UTF8_PATH
|
|
|
|
if (uenc != lenc) {
|
|
|
|
path = str_conv_enc(path, uenc, lenc);
|
|
|
|
}
|
|
|
|
#endif
|
2017-12-16 16:25:11 +03:00
|
|
|
if (!ENCODING_GET(path)) { /* ASCII-8BIT */
|
|
|
|
rb_enc_copy(path, opt->script_name);
|
|
|
|
}
|
2012-12-21 14:39:59 +04:00
|
|
|
}
|
2019-10-03 19:29:21 +03:00
|
|
|
|
2024-01-31 20:17:31 +03:00
|
|
|
rb_binding_t *toplevel_binding;
|
|
|
|
GetBindingPtr(rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING")), toplevel_binding);
|
|
|
|
const struct rb_block *base_block = toplevel_context(toplevel_binding);
|
2024-02-16 06:22:58 +03:00
|
|
|
const rb_iseq_t *parent = vm_block_iseq(base_block);
|
|
|
|
bool optimize = !(dump & DUMP_BIT(insns_without_opt));
|
2023-12-02 00:25:41 +03:00
|
|
|
|
2024-02-16 06:22:58 +03:00
|
|
|
if (!result.ast) {
|
|
|
|
pm_parse_result_t *pm = &result.prism;
|
|
|
|
iseq = pm_iseq_new_main(&pm->node, opt->script_name, path, parent, optimize);
|
|
|
|
pm_parse_result_free(pm);
|
2023-12-16 18:21:00 +03:00
|
|
|
}
|
|
|
|
else {
|
2024-02-16 06:22:58 +03:00
|
|
|
rb_ast_t *ast = result.ast;
|
|
|
|
iseq = rb_iseq_new_main(&ast->body, opt->script_name, path, parent, optimize);
|
2023-12-08 02:47:36 +03:00
|
|
|
rb_ast_dispose(ast);
|
|
|
|
}
|
2016-03-29 00:39:24 +03:00
|
|
|
}
|
2008-05-20 08:19:27 +04:00
|
|
|
|
2021-08-27 10:19:56 +03:00
|
|
|
if (dump & (DUMP_BIT(insns) | DUMP_BIT(insns_without_opt))) {
|
2015-07-22 01:52:59 +03:00
|
|
|
rb_io_write(rb_stdout, rb_iseq_disasm((const rb_iseq_t *)iseq));
|
2008-05-20 07:13:52 +04:00
|
|
|
rb_io_flush(rb_stdout);
|
2016-12-07 17:39:24 +03:00
|
|
|
dump &= ~DUMP_BIT(insns);
|
|
|
|
if (!dump) return Qtrue;
|
2008-05-20 07:13:52 +04:00
|
|
|
}
|
2016-12-07 17:39:24 +03:00
|
|
|
if (opt->dump & dump_exit_bits) return Qtrue;
|
2008-05-20 07:13:52 +04:00
|
|
|
|
2024-02-16 06:25:48 +03:00
|
|
|
process_options_global_setup(opt, iseq);
|
2015-07-22 01:52:59 +03:00
|
|
|
return (VALUE)iseq;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2016-03-07 18:44:34 +03:00
|
|
|
#ifndef DOSISH
|
2016-03-04 16:27:36 +03:00
|
|
|
static void
|
|
|
|
warn_cr_in_shebang(const char *str, long len)
|
|
|
|
{
|
2024-01-13 14:33:33 +03:00
|
|
|
if (len > 1 && str[len-1] == '\n' && str[len-2] == '\r') {
|
2017-06-01 07:38:03 +03:00
|
|
|
rb_warn("shebang line ending with \\r may cause problems");
|
2016-03-04 16:27:36 +03:00
|
|
|
}
|
|
|
|
}
|
2016-03-07 22:39:32 +03:00
|
|
|
#else
|
|
|
|
#define warn_cr_in_shebang(str, len) (void)0
|
2016-03-07 18:44:34 +03:00
|
|
|
#endif
|
2016-03-04 16:27:36 +03:00
|
|
|
|
2022-07-02 14:58:59 +03:00
|
|
|
void rb_reset_argf_lineno(long n);
|
|
|
|
|
2008-10-27 09:58:28 +03:00
|
|
|
struct load_file_arg {
|
|
|
|
VALUE parser;
|
2011-10-31 22:05:03 +04:00
|
|
|
VALUE fname;
|
2008-10-27 09:58:28 +03:00
|
|
|
int script;
|
2016-08-19 13:44:53 +03:00
|
|
|
ruby_cmdline_options_t *opt;
|
2014-06-03 18:33:51 +04:00
|
|
|
VALUE f;
|
2008-10-27 09:58:28 +03:00
|
|
|
};
|
|
|
|
|
2024-03-29 10:18:14 +03:00
|
|
|
VALUE rb_script_lines_for(VALUE path);
|
2023-08-25 10:53:29 +03:00
|
|
|
|
2008-10-27 09:58:28 +03:00
|
|
|
static VALUE
|
2015-10-17 07:19:12 +03:00
|
|
|
load_file_internal(VALUE argp_v)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2014-06-03 18:33:51 +04:00
|
|
|
struct load_file_arg *argp = (struct load_file_arg *)argp_v;
|
2008-10-27 09:58:28 +03:00
|
|
|
VALUE parser = argp->parser;
|
2013-08-09 17:20:58 +04:00
|
|
|
VALUE orig_fname = argp->fname;
|
2008-10-27 09:58:28 +03:00
|
|
|
int script = argp->script;
|
2016-08-19 13:44:53 +03:00
|
|
|
ruby_cmdline_options_t *opt = argp->opt;
|
2014-06-03 18:33:51 +04:00
|
|
|
VALUE f = argp->f;
|
1998-01-16 15:13:05 +03:00
|
|
|
int line_start = 1;
|
2017-10-29 18:51:23 +03:00
|
|
|
rb_ast_t *ast = 0;
|
2008-01-19 02:35:38 +03:00
|
|
|
rb_encoding *enc;
|
2008-10-29 03:23:04 +03:00
|
|
|
ID set_encoding;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2008-10-29 03:23:04 +03:00
|
|
|
CONST_ID(set_encoding, "set_encoding");
|
1998-01-16 15:13:05 +03:00
|
|
|
if (script) {
|
2001-07-14 19:17:19 +04:00
|
|
|
VALUE c = 1; /* something not nil */
|
1998-01-16 15:13:05 +03:00
|
|
|
VALUE line;
|
2016-03-04 08:19:12 +03:00
|
|
|
char *p, *str;
|
|
|
|
long len;
|
2008-01-25 07:18:14 +03:00
|
|
|
int no_src_enc = !opt->src.enc.name;
|
|
|
|
int no_ext_enc = !opt->ext.enc.name;
|
2008-10-07 21:39:44 +04:00
|
|
|
int no_int_enc = !opt->intern.enc.name;
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2008-10-29 03:30:09 +03:00
|
|
|
enc = rb_ascii8bit_encoding();
|
2008-10-29 03:23:04 +03:00
|
|
|
rb_funcall(f, set_encoding, 1, rb_enc_from_encoding(enc));
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2017-05-28 12:49:30 +03:00
|
|
|
if (opt->xflag) {
|
2010-12-05 05:27:13 +03:00
|
|
|
line_start--;
|
2009-08-05 14:19:18 +04:00
|
|
|
search_shebang:
|
1999-01-20 07:59:39 +03:00
|
|
|
while (!NIL_P(line = rb_io_gets(f))) {
|
1998-01-16 15:13:05 +03:00
|
|
|
line_start++;
|
2016-03-04 08:19:12 +03:00
|
|
|
RSTRING_GETMEM(line, str, len);
|
|
|
|
if (len > 2 && str[0] == '#' && str[1] == '!') {
|
2016-03-04 16:27:36 +03:00
|
|
|
if (line_start == 1) warn_cr_in_shebang(str, len);
|
2016-03-04 08:19:12 +03:00
|
|
|
if ((p = strstr(str+2, ruby_engine)) != 0) {
|
1998-01-16 15:13:05 +03:00
|
|
|
goto start_read;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-07 03:38:33 +04:00
|
|
|
rb_loaderror("no Ruby script found in input");
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2022-07-21 19:23:58 +03:00
|
|
|
|
* encoding.c: provide basic features for M17N.
* parse.y: encoding aware parsing.
* parse.y (pragma_encoding): encoding specification pragma.
* parse.y (rb_intern3): encoding specified symbols.
* string.c (rb_str_length): length based on characters.
for older behavior, bytesize method added.
* string.c (rb_str_index_m): index based on characters. rindex as
well.
* string.c (succ_char): encoding aware succeeding string.
* string.c (rb_str_reverse): reverse based on characters.
* string.c (rb_str_inspect): encoding aware string description.
* string.c (rb_str_upcase_bang): encoding aware case conversion.
downcase, capitalize, swapcase as well.
* string.c (rb_str_tr_bang): tr based on characters. delete,
squeeze, tr_s, count as well.
* string.c (rb_str_split_m): split based on characters.
* string.c (rb_str_each_line): encoding aware each_line.
* string.c (rb_str_each_char): added. iteration based on
characters.
* string.c (rb_str_strip_bang): encoding aware whitespace
stripping. lstrip, rstrip as well.
* string.c (rb_str_justify): encoding aware justifying (ljust,
rjust, center).
* string.c (str_encoding): get encoding attribute from a string.
* re.c (rb_reg_initialize): encoding aware regular expression
* sprintf.c (rb_str_format): formatting (i.e. length count) based
on characters.
* io.c (rb_io_getc): getc to return one-character string.
for older behavior, getbyte method added.
* ext/stringio/stringio.c (strio_getc): ditto.
* io.c (rb_io_ungetc): allow pushing arbitrary string at the
current reading point.
* ext/stringio/stringio.c (strio_ungetc): ditto.
* ext/strscan/strscan.c: encoding support.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13261 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-08-25 07:29:39 +04:00
|
|
|
c = rb_io_getbyte(f);
|
1998-01-16 15:13:05 +03:00
|
|
|
if (c == INT2FIX('#')) {
|
* encoding.c: provide basic features for M17N.
* parse.y: encoding aware parsing.
* parse.y (pragma_encoding): encoding specification pragma.
* parse.y (rb_intern3): encoding specified symbols.
* string.c (rb_str_length): length based on characters.
for older behavior, bytesize method added.
* string.c (rb_str_index_m): index based on characters. rindex as
well.
* string.c (succ_char): encoding aware succeeding string.
* string.c (rb_str_reverse): reverse based on characters.
* string.c (rb_str_inspect): encoding aware string description.
* string.c (rb_str_upcase_bang): encoding aware case conversion.
downcase, capitalize, swapcase as well.
* string.c (rb_str_tr_bang): tr based on characters. delete,
squeeze, tr_s, count as well.
* string.c (rb_str_split_m): split based on characters.
* string.c (rb_str_each_line): encoding aware each_line.
* string.c (rb_str_each_char): added. iteration based on
characters.
* string.c (rb_str_strip_bang): encoding aware whitespace
stripping. lstrip, rstrip as well.
* string.c (rb_str_justify): encoding aware justifying (ljust,
rjust, center).
* string.c (str_encoding): get encoding attribute from a string.
* re.c (rb_reg_initialize): encoding aware regular expression
* sprintf.c (rb_str_format): formatting (i.e. length count) based
on characters.
* io.c (rb_io_getc): getc to return one-character string.
for older behavior, getbyte method added.
* ext/stringio/stringio.c (strio_getc): ditto.
* io.c (rb_io_ungetc): allow pushing arbitrary string at the
current reading point.
* ext/stringio/stringio.c (strio_ungetc): ditto.
* ext/strscan/strscan.c: encoding support.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13261 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-08-25 07:29:39 +04:00
|
|
|
c = rb_io_getbyte(f);
|
2018-10-02 21:51:21 +03:00
|
|
|
if (c == INT2FIX('!') && !NIL_P(line = rb_io_gets(f))) {
|
2016-03-04 08:19:12 +03:00
|
|
|
RSTRING_GETMEM(line, str, len);
|
2016-03-04 16:27:36 +03:00
|
|
|
warn_cr_in_shebang(str, len);
|
2016-03-04 08:19:12 +03:00
|
|
|
if ((p = strstr(str, ruby_engine)) == 0) {
|
2009-08-05 14:19:18 +04:00
|
|
|
/* not ruby script, assume -x flag */
|
|
|
|
goto search_shebang;
|
1998-01-16 15:19:22 +03:00
|
|
|
}
|
2022-07-21 19:23:58 +03:00
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
start_read:
|
2016-03-04 08:19:12 +03:00
|
|
|
str += len - 1;
|
|
|
|
if (*str == '\n') *str-- = '\0';
|
|
|
|
if (*str == '\r') *str-- = '\0';
|
2016-03-04 06:53:43 +03:00
|
|
|
/* ruby_engine should not contain a space */
|
2005-05-01 04:13:48 +04:00
|
|
|
if ((p = strstr(p, " -")) != 0) {
|
2015-12-29 13:12:48 +03:00
|
|
|
opt->warning = 0;
|
2008-10-30 04:34:23 +03:00
|
|
|
moreswitches(p + 1, opt, 0);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2005-05-14 06:48:07 +04:00
|
|
|
/* push back shebang for pragma may exist in next line */
|
2008-08-25 12:36:46 +04:00
|
|
|
rb_io_ungetbyte(f, rb_str_new2("!\n"));
|
2005-05-14 06:48:07 +04:00
|
|
|
}
|
|
|
|
else if (!NIL_P(c)) {
|
2008-08-25 12:36:46 +04:00
|
|
|
rb_io_ungetbyte(f, c);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2008-08-25 12:36:46 +04:00
|
|
|
rb_io_ungetbyte(f, INT2FIX('#'));
|
2008-01-25 07:18:14 +03:00
|
|
|
if (no_src_enc && opt->src.enc.name) {
|
|
|
|
opt->src.enc.index = opt_enc_index(opt->src.enc.name);
|
2008-01-25 10:11:18 +03:00
|
|
|
src_encoding_index = opt->src.enc.index;
|
2008-01-25 07:18:14 +03:00
|
|
|
}
|
|
|
|
if (no_ext_enc && opt->ext.enc.name) {
|
|
|
|
opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
|
2008-01-09 09:54:26 +03:00
|
|
|
}
|
2008-10-07 21:39:44 +04:00
|
|
|
if (no_int_enc && opt->intern.enc.name) {
|
|
|
|
opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
|
|
|
|
}
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2000-06-28 12:31:35 +04:00
|
|
|
else if (!NIL_P(c)) {
|
2008-08-25 12:36:46 +04:00
|
|
|
rb_io_ungetbyte(f, c);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2019-06-04 03:36:32 +03:00
|
|
|
if (NIL_P(c)) {
|
2017-01-31 15:55:00 +03:00
|
|
|
argp->f = f = Qnil;
|
2010-06-27 18:31:19 +04:00
|
|
|
}
|
2022-07-02 14:58:59 +03:00
|
|
|
rb_reset_argf_lineno(0);
|
2020-05-16 11:37:28 +03:00
|
|
|
ruby_opt_init(opt);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2008-01-25 07:18:14 +03:00
|
|
|
if (opt->src.enc.index >= 0) {
|
|
|
|
enc = rb_enc_from_index(opt->src.enc.index);
|
2008-01-13 07:50:48 +03:00
|
|
|
}
|
|
|
|
else if (f == rb_stdin) {
|
2008-01-25 21:49:28 +03:00
|
|
|
enc = rb_locale_encoding();
|
2008-01-19 02:35:38 +03:00
|
|
|
}
|
|
|
|
else {
|
2012-11-06 04:49:57 +04:00
|
|
|
enc = rb_utf8_encoding();
|
2008-01-13 07:50:48 +03:00
|
|
|
}
|
2017-10-24 14:09:41 +03:00
|
|
|
rb_parser_set_options(parser, opt->do_print, opt->do_loop,
|
|
|
|
opt->do_line, opt->do_split);
|
2023-08-25 10:53:29 +03:00
|
|
|
|
2024-03-29 10:18:14 +03:00
|
|
|
VALUE lines = rb_script_lines_for(orig_fname);
|
2023-08-25 10:53:29 +03:00
|
|
|
if (!NIL_P(lines)) {
|
|
|
|
rb_parser_set_script_lines(parser, lines);
|
|
|
|
}
|
|
|
|
|
2010-06-27 18:31:19 +04:00
|
|
|
if (NIL_P(f)) {
|
|
|
|
f = rb_str_new(0, 0);
|
|
|
|
rb_enc_associate(f, enc);
|
2013-08-09 17:20:58 +04:00
|
|
|
return (VALUE)rb_parser_compile_string_path(parser, orig_fname, f, line_start);
|
2010-06-27 18:31:19 +04:00
|
|
|
}
|
2008-10-30 12:17:49 +03:00
|
|
|
rb_funcall(f, set_encoding, 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-"));
|
2017-10-27 19:44:57 +03:00
|
|
|
ast = rb_parser_compile_file_path(parser, orig_fname, f, line_start);
|
2008-10-29 03:23:04 +03:00
|
|
|
rb_funcall(f, set_encoding, 1, rb_parser_encoding(parser));
|
2017-01-31 15:55:00 +03:00
|
|
|
if (script && rb_parser_end_seen_p(parser)) {
|
|
|
|
/*
|
|
|
|
* DATA is a File that contains the data section of the executed file.
|
|
|
|
* To create a data section use <tt>__END__</tt>:
|
|
|
|
*
|
|
|
|
* $ cat t.rb
|
|
|
|
* puts DATA.gets
|
|
|
|
* __END__
|
|
|
|
* hello world!
|
|
|
|
*
|
|
|
|
* $ ruby t.rb
|
|
|
|
* hello world!
|
|
|
|
*/
|
|
|
|
rb_define_global_const("DATA", f);
|
|
|
|
argp->f = Qnil;
|
|
|
|
}
|
2017-10-27 19:44:57 +03:00
|
|
|
return (VALUE)ast;
|
2014-06-03 18:33:51 +04:00
|
|
|
}
|
|
|
|
|
2020-12-15 17:17:23 +03:00
|
|
|
/* disabling O_NONBLOCK, and returns 0 on success, otherwise errno */
|
|
|
|
static inline int
|
|
|
|
disable_nonblock(int fd)
|
|
|
|
{
|
|
|
|
#if defined(HAVE_FCNTL) && defined(F_SETFL)
|
|
|
|
if (fcntl(fd, F_SETFL, 0) < 0) {
|
|
|
|
const int e = errno;
|
|
|
|
ASSUME(e != 0);
|
|
|
|
# if defined ENOTSUP
|
|
|
|
if (e == ENOTSUP) return 0;
|
|
|
|
# endif
|
|
|
|
# if defined B_UNSUPPORTED
|
|
|
|
if (e == B_UNSUPPORTED) return 0;
|
|
|
|
# endif
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-06-03 18:33:51 +04:00
|
|
|
static VALUE
|
2015-10-17 07:19:12 +03:00
|
|
|
open_load_file(VALUE fname_v, int *xflag)
|
2014-06-03 18:33:51 +04:00
|
|
|
{
|
2017-05-28 12:49:30 +03:00
|
|
|
const char *fname = (fname_v = rb_str_encode_ospath(fname_v),
|
|
|
|
StringValueCStr(fname_v));
|
2016-10-10 06:40:56 +03:00
|
|
|
long flen = RSTRING_LEN(fname_v);
|
2014-06-03 18:33:51 +04:00
|
|
|
VALUE f;
|
2015-10-18 00:09:10 +03:00
|
|
|
int e;
|
2014-06-03 18:33:51 +04:00
|
|
|
|
2016-10-10 06:40:56 +03:00
|
|
|
if (flen == 1 && fname[0] == '-') {
|
2014-06-03 18:33:51 +04:00
|
|
|
f = rb_stdin;
|
|
|
|
}
|
|
|
|
else {
|
2015-10-18 00:09:10 +03:00
|
|
|
int fd;
|
|
|
|
/* open(2) may block if fname is point to FIFO and it's empty. Let's
|
|
|
|
use O_NONBLOCK. */
|
2022-01-16 17:47:10 +03:00
|
|
|
const int MODE_TO_LOAD = O_RDONLY | (
|
|
|
|
#if defined O_NONBLOCK && HAVE_FCNTL
|
2015-10-17 07:03:23 +03:00
|
|
|
/* TODO: fix conflicting O_NONBLOCK in ruby/win32.h */
|
2022-01-16 17:47:10 +03:00
|
|
|
!(O_NONBLOCK & O_ACCMODE) ? O_NONBLOCK :
|
|
|
|
#endif
|
|
|
|
#if defined O_NDELAY && HAVE_FCNTL
|
|
|
|
!(O_NDELAY & O_ACCMODE) ? O_NDELAY :
|
2015-10-16 09:54:38 +03:00
|
|
|
#endif
|
2022-01-16 17:47:10 +03:00
|
|
|
0);
|
2016-10-12 15:07:16 +03:00
|
|
|
int mode = MODE_TO_LOAD;
|
2014-06-03 18:33:51 +04:00
|
|
|
#if defined DOSISH || defined __CYGWIN__
|
2016-10-12 11:24:36 +03:00
|
|
|
# define isdirsep(x) ((x) == '/' || (x) == '\\')
|
2014-06-03 18:33:51 +04:00
|
|
|
{
|
2016-10-12 11:24:36 +03:00
|
|
|
static const char exeext[] = ".exe";
|
2016-10-10 06:40:56 +03:00
|
|
|
enum {extlen = sizeof(exeext)-1};
|
|
|
|
if (flen > extlen && !isdirsep(fname[flen-extlen-1]) &&
|
|
|
|
STRNCASECMP(fname+flen-extlen, exeext, extlen) == 0) {
|
2016-10-12 15:07:16 +03:00
|
|
|
mode |= O_BINARY;
|
2015-10-17 07:19:12 +03:00
|
|
|
*xflag = 1;
|
2014-06-03 18:33:51 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2014-06-03 18:33:51 +04:00
|
|
|
if ((fd = rb_cloexec_open(fname, mode, 0)) < 0) {
|
2018-01-24 23:50:29 +03:00
|
|
|
e = errno;
|
2016-10-21 10:06:27 +03:00
|
|
|
if (!rb_gc_for_fd(e)) {
|
|
|
|
rb_load_fail(fname_v, strerror(e));
|
|
|
|
}
|
|
|
|
if ((fd = rb_cloexec_open(fname, mode, 0)) < 0) {
|
|
|
|
rb_load_fail(fname_v, strerror(errno));
|
|
|
|
}
|
2014-06-03 18:33:51 +04:00
|
|
|
}
|
2015-10-18 00:09:10 +03:00
|
|
|
rb_update_max_fd(fd);
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2020-12-15 17:17:23 +03:00
|
|
|
if (MODE_TO_LOAD != O_RDONLY && (e = disable_nonblock(fd)) != 0) {
|
2015-10-18 02:38:18 +03:00
|
|
|
(void)close(fd);
|
2015-10-18 00:09:10 +03:00
|
|
|
rb_load_fail(fname_v, strerror(e));
|
|
|
|
}
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2016-03-14 10:03:01 +03:00
|
|
|
e = ruby_is_fd_loadable(fd);
|
2016-10-10 09:22:30 +03:00
|
|
|
if (!e) {
|
|
|
|
e = errno;
|
|
|
|
(void)close(fd);
|
|
|
|
rb_load_fail(fname_v, strerror(e));
|
2014-06-03 18:33:51 +04:00
|
|
|
}
|
2022-07-21 19:23:58 +03:00
|
|
|
|
2014-06-03 18:33:51 +04:00
|
|
|
f = rb_io_fdopen(fd, mode, fname);
|
2016-10-10 09:22:30 +03:00
|
|
|
if (e < 0) {
|
|
|
|
/*
|
|
|
|
We need to wait if FIFO is empty. It's FIFO's semantics.
|
|
|
|
rb_thread_wait_fd() release GVL. So, it's safe.
|
|
|
|
*/
|
2021-06-19 04:47:16 +03:00
|
|
|
rb_io_wait(f, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
|
2016-10-10 09:22:30 +03:00
|
|
|
}
|
2014-06-03 18:33:51 +04:00
|
|
|
}
|
2015-10-17 07:19:12 +03:00
|
|
|
return f;
|
|
|
|
}
|
2014-06-03 18:33:51 +04:00
|
|
|
|
2015-10-17 07:19:12 +03:00
|
|
|
static VALUE
|
|
|
|
restore_load_file(VALUE arg)
|
|
|
|
{
|
|
|
|
struct load_file_arg *argp = (struct load_file_arg *)arg;
|
|
|
|
VALUE f = argp->f;
|
2014-06-03 18:33:51 +04:00
|
|
|
|
2017-01-31 15:55:00 +03:00
|
|
|
if (!NIL_P(f) && f != rb_stdin) {
|
1999-01-20 07:59:39 +03:00
|
|
|
rb_io_close(f);
|
|
|
|
}
|
2016-02-24 11:21:04 +03:00
|
|
|
return Qnil;
|
2008-10-27 09:58:28 +03:00
|
|
|
}
|
|
|
|
|
2017-10-29 18:51:23 +03:00
|
|
|
static rb_ast_t *
|
2017-05-28 12:49:30 +03:00
|
|
|
load_file(VALUE parser, VALUE fname, VALUE f, int script, ruby_cmdline_options_t *opt)
|
2008-10-27 09:58:28 +03:00
|
|
|
{
|
|
|
|
struct load_file_arg arg;
|
|
|
|
arg.parser = parser;
|
|
|
|
arg.fname = fname;
|
|
|
|
arg.script = script;
|
|
|
|
arg.opt = opt;
|
2017-05-28 12:49:30 +03:00
|
|
|
arg.f = f;
|
2017-10-29 18:51:23 +03:00
|
|
|
return (rb_ast_t *)rb_ensure(load_file_internal, (VALUE)&arg,
|
2017-10-27 19:44:57 +03:00
|
|
|
restore_load_file, (VALUE)&arg);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2006-12-31 18:02:22 +03:00
|
|
|
void *
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
rb_load_file(const char *fname)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2011-10-31 22:05:03 +04:00
|
|
|
VALUE fname_v = rb_str_new_cstr(fname);
|
2013-07-26 08:04:23 +04:00
|
|
|
return rb_load_file_str(fname_v);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
rb_load_file_str(VALUE fname_v)
|
|
|
|
{
|
2017-05-28 12:49:30 +03:00
|
|
|
return rb_parser_load_file(rb_parser_new(), fname_v);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2016-03-19 08:46:20 +03:00
|
|
|
void *
|
|
|
|
rb_parser_load_file(VALUE parser, VALUE fname_v)
|
|
|
|
{
|
2016-08-19 13:44:53 +03:00
|
|
|
ruby_cmdline_options_t opt;
|
2023-07-13 10:58:48 +03:00
|
|
|
int xflag = 0;
|
|
|
|
VALUE f = open_load_file(fname_v, &xflag);
|
|
|
|
cmdline_options_init(&opt)->xflag = xflag != 0;
|
2017-05-28 12:49:30 +03:00
|
|
|
return load_file(parser, fname_v, f, 0, &opt);
|
2016-03-19 08:46:20 +03:00
|
|
|
}
|
|
|
|
|
2013-08-07 18:12:04 +04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* Process.argv0 -> frozen_string
|
|
|
|
*
|
|
|
|
* Returns the name of the script being executed. The value is not
|
|
|
|
* affected by assigning a new value to $0.
|
2013-09-02 09:42:02 +04:00
|
|
|
*
|
|
|
|
* This method first appeared in Ruby 2.1 to serve as a global
|
|
|
|
* variable free means to get the script name.
|
2013-08-07 18:12:04 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
proc_argv0(VALUE process)
|
|
|
|
{
|
|
|
|
return rb_orig_progname;
|
|
|
|
}
|
|
|
|
|
2017-10-19 14:24:03 +03:00
|
|
|
static VALUE ruby_setproctitle(VALUE title);
|
|
|
|
|
2013-08-07 18:12:04 +04:00
|
|
|
/*
|
|
|
|
* call-seq:
|
|
|
|
* Process.setproctitle(string) -> string
|
|
|
|
*
|
2013-09-02 09:42:02 +04:00
|
|
|
* Sets the process title that appears on the ps(1) command. Not
|
|
|
|
* necessarily effective on all platforms. No exception will be
|
|
|
|
* raised regardless of the result, nor will NotImplementedError be
|
|
|
|
* raised even if the platform does not support the feature.
|
2013-08-07 18:12:04 +04:00
|
|
|
*
|
|
|
|
* Calling this method does not affect the value of $0.
|
|
|
|
*
|
|
|
|
* Process.setproctitle('myapp: worker #%d' % worker_id)
|
2013-09-02 09:42:02 +04:00
|
|
|
*
|
|
|
|
* This method first appeared in Ruby 2.1 to serve as a global
|
|
|
|
* variable free means to change the process title.
|
2013-08-07 18:12:04 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
proc_setproctitle(VALUE process, VALUE title)
|
|
|
|
{
|
2017-10-19 14:24:03 +03:00
|
|
|
return ruby_setproctitle(title);
|
|
|
|
}
|
2013-08-07 18:12:04 +04:00
|
|
|
|
2017-10-19 14:24:03 +03:00
|
|
|
static VALUE
|
|
|
|
ruby_setproctitle(VALUE title)
|
|
|
|
{
|
|
|
|
const char *ptr = StringValueCStr(title);
|
|
|
|
setproctitle("%.*s", RSTRING_LENINT(title), ptr);
|
2013-08-07 18:12:04 +04:00
|
|
|
return title;
|
|
|
|
}
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static void
|
2019-08-27 05:16:52 +03:00
|
|
|
set_arg0(VALUE val, ID id, VALUE *_)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2007-09-29 01:47:31 +04:00
|
|
|
if (origarg.argv == 0)
|
2006-12-31 18:02:22 +03:00
|
|
|
rb_raise(rb_eRuntimeError, "$0 not initialized");
|
2008-06-01 22:23:10 +04:00
|
|
|
|
2017-10-19 14:24:03 +03:00
|
|
|
rb_progname = rb_str_new_frozen(ruby_setproctitle(val));
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2014-11-29 10:53:17 +03:00
|
|
|
static inline VALUE
|
|
|
|
external_str_new_cstr(const char *p)
|
|
|
|
{
|
|
|
|
#if UTF8_PATH
|
|
|
|
VALUE str = rb_utf8_str_new_cstr(p);
|
2018-07-27 08:42:56 +03:00
|
|
|
str = str_conv_enc(str, NULL, rb_default_external_encoding());
|
|
|
|
return str;
|
2014-11-29 10:53:17 +03:00
|
|
|
#else
|
|
|
|
return rb_external_str_new_cstr(p);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2023-04-13 15:45:56 +03:00
|
|
|
static void
|
|
|
|
set_progname(VALUE name)
|
|
|
|
{
|
|
|
|
rb_orig_progname = rb_progname = name;
|
|
|
|
rb_vm_set_progname(rb_progname);
|
|
|
|
}
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
void
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
ruby_script(const char *name)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
if (name) {
|
2023-04-13 15:45:56 +03:00
|
|
|
set_progname(rb_str_freeze(external_str_new_cstr(name)));
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-14 06:22:08 +04:00
|
|
|
/*! Sets the current script name to this value.
|
|
|
|
*
|
|
|
|
* Same as ruby_script() but accepts a VALUE.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ruby_set_script_name(VALUE name)
|
|
|
|
{
|
2023-04-13 15:45:56 +03:00
|
|
|
set_progname(rb_str_new_frozen(name));
|
2012-06-14 06:22:08 +04:00
|
|
|
}
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
static void
|
2016-08-19 13:44:53 +03:00
|
|
|
init_ids(ruby_cmdline_options_t *opt)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2008-06-09 08:20:07 +04:00
|
|
|
rb_uid_t uid = getuid();
|
|
|
|
rb_uid_t euid = geteuid();
|
|
|
|
rb_gid_t gid = getgid();
|
|
|
|
rb_gid_t egid = getegid();
|
|
|
|
|
|
|
|
if (uid != euid) opt->setids |= 1;
|
|
|
|
if (egid != gid) opt->setids |= 2;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
2008-06-09 08:20:07 +04:00
|
|
|
#undef forbid_setid
|
1998-01-16 15:13:05 +03:00
|
|
|
static void
|
2017-01-31 15:54:59 +03:00
|
|
|
forbid_setid(const char *s, const ruby_cmdline_options_t *opt)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2008-06-09 08:20:07 +04:00
|
|
|
if (opt->setids & 1)
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 09:47:45 +03:00
|
|
|
rb_raise(rb_eSecurityError, "no %s allowed while running setuid", s);
|
2008-06-09 08:20:07 +04:00
|
|
|
if (opt->setids & 2)
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 09:47:45 +03:00
|
|
|
rb_raise(rb_eSecurityError, "no %s allowed while running setgid", s);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
Some global variables can be accessed from ractors
Some global variables should be used from non-main Ractors.
[Bug #17268]
```ruby
# ractor-local (derived from created ractor): debug
'$DEBUG' => $DEBUG,
'$-d' => $-d,
# ractor-local (derived from created ractor): verbose
'$VERBOSE' => $VERBOSE,
'$-w' => $-w,
'$-W' => $-W,
'$-v' => $-v,
# process-local (readonly): other commandline parameters
'$-p' => $-p,
'$-l' => $-l,
'$-a' => $-a,
# process-local (readonly): getpid
'$$' => $$,
# thread local: process result
'$?' => $?,
# scope local: match
'$~' => $~.inspect,
'$&' => $&,
'$`' => $`,
'$\'' => $',
'$+' => $+,
'$1' => $1,
# scope local: last line
'$_' => $_,
# scope local: last backtrace
'$@' => $@,
'$!' => $!,
# ractor local: stdin, out, err
'$stdin' => $stdin.inspect,
'$stdout' => $stdout.inspect,
'$stderr' => $stderr.inspect,
```
2020-10-20 04:46:43 +03:00
|
|
|
static VALUE
|
|
|
|
verbose_getter(ID id, VALUE *ptr)
|
|
|
|
{
|
|
|
|
return *rb_ruby_verbose_ptr();
|
|
|
|
}
|
|
|
|
|
2003-07-29 22:26:55 +04:00
|
|
|
static void
|
2019-08-27 05:16:52 +03:00
|
|
|
verbose_setter(VALUE val, ID id, VALUE *variable)
|
2003-07-29 22:26:55 +04:00
|
|
|
{
|
Some global variables can be accessed from ractors
Some global variables should be used from non-main Ractors.
[Bug #17268]
```ruby
# ractor-local (derived from created ractor): debug
'$DEBUG' => $DEBUG,
'$-d' => $-d,
# ractor-local (derived from created ractor): verbose
'$VERBOSE' => $VERBOSE,
'$-w' => $-w,
'$-W' => $-W,
'$-v' => $-v,
# process-local (readonly): other commandline parameters
'$-p' => $-p,
'$-l' => $-l,
'$-a' => $-a,
# process-local (readonly): getpid
'$$' => $$,
# thread local: process result
'$?' => $?,
# scope local: match
'$~' => $~.inspect,
'$&' => $&,
'$`' => $`,
'$\'' => $',
'$+' => $+,
'$1' => $1,
# scope local: last line
'$_' => $_,
# scope local: last backtrace
'$@' => $@,
'$!' => $!,
# ractor local: stdin, out, err
'$stdin' => $stdin.inspect,
'$stdout' => $stdout.inspect,
'$stderr' => $stderr.inspect,
```
2020-10-20 04:46:43 +03:00
|
|
|
*rb_ruby_verbose_ptr() = RTEST(val) ? Qtrue : val;
|
2003-07-29 22:26:55 +04:00
|
|
|
}
|
|
|
|
|
2004-03-03 07:55:35 +03:00
|
|
|
static VALUE
|
Some global variables can be accessed from ractors
Some global variables should be used from non-main Ractors.
[Bug #17268]
```ruby
# ractor-local (derived from created ractor): debug
'$DEBUG' => $DEBUG,
'$-d' => $-d,
# ractor-local (derived from created ractor): verbose
'$VERBOSE' => $VERBOSE,
'$-w' => $-w,
'$-W' => $-W,
'$-v' => $-v,
# process-local (readonly): other commandline parameters
'$-p' => $-p,
'$-l' => $-l,
'$-a' => $-a,
# process-local (readonly): getpid
'$$' => $$,
# thread local: process result
'$?' => $?,
# scope local: match
'$~' => $~.inspect,
'$&' => $&,
'$`' => $`,
'$\'' => $',
'$+' => $+,
'$1' => $1,
# scope local: last line
'$_' => $_,
# scope local: last backtrace
'$@' => $@,
'$!' => $!,
# ractor local: stdin, out, err
'$stdin' => $stdin.inspect,
'$stdout' => $stdout.inspect,
'$stderr' => $stderr.inspect,
```
2020-10-20 04:46:43 +03:00
|
|
|
opt_W_getter(ID id, VALUE *dmy)
|
2004-03-03 07:55:35 +03:00
|
|
|
{
|
Some global variables can be accessed from ractors
Some global variables should be used from non-main Ractors.
[Bug #17268]
```ruby
# ractor-local (derived from created ractor): debug
'$DEBUG' => $DEBUG,
'$-d' => $-d,
# ractor-local (derived from created ractor): verbose
'$VERBOSE' => $VERBOSE,
'$-w' => $-w,
'$-W' => $-W,
'$-v' => $-v,
# process-local (readonly): other commandline parameters
'$-p' => $-p,
'$-l' => $-l,
'$-a' => $-a,
# process-local (readonly): getpid
'$$' => $$,
# thread local: process result
'$?' => $?,
# scope local: match
'$~' => $~.inspect,
'$&' => $&,
'$`' => $`,
'$\'' => $',
'$+' => $+,
'$1' => $1,
# scope local: last line
'$_' => $_,
# scope local: last backtrace
'$@' => $@,
'$!' => $!,
# ractor local: stdin, out, err
'$stdin' => $stdin.inspect,
'$stdout' => $stdout.inspect,
'$stderr' => $stderr.inspect,
```
2020-10-20 04:46:43 +03:00
|
|
|
VALUE v = *rb_ruby_verbose_ptr();
|
|
|
|
|
|
|
|
switch (v) {
|
2008-06-17 18:02:20 +04:00
|
|
|
case Qnil:
|
2006-12-31 18:02:22 +03:00
|
|
|
return INT2FIX(0);
|
2008-06-17 18:02:20 +04:00
|
|
|
case Qfalse:
|
2006-12-31 18:02:22 +03:00
|
|
|
return INT2FIX(1);
|
2008-06-17 18:02:20 +04:00
|
|
|
case Qtrue:
|
2006-12-31 18:02:22 +03:00
|
|
|
return INT2FIX(2);
|
2012-04-15 04:06:13 +04:00
|
|
|
default:
|
|
|
|
return Qnil;
|
2008-06-17 18:02:20 +04:00
|
|
|
}
|
2004-03-03 07:55:35 +03:00
|
|
|
}
|
|
|
|
|
Some global variables can be accessed from ractors
Some global variables should be used from non-main Ractors.
[Bug #17268]
```ruby
# ractor-local (derived from created ractor): debug
'$DEBUG' => $DEBUG,
'$-d' => $-d,
# ractor-local (derived from created ractor): verbose
'$VERBOSE' => $VERBOSE,
'$-w' => $-w,
'$-W' => $-W,
'$-v' => $-v,
# process-local (readonly): other commandline parameters
'$-p' => $-p,
'$-l' => $-l,
'$-a' => $-a,
# process-local (readonly): getpid
'$$' => $$,
# thread local: process result
'$?' => $?,
# scope local: match
'$~' => $~.inspect,
'$&' => $&,
'$`' => $`,
'$\'' => $',
'$+' => $+,
'$1' => $1,
# scope local: last line
'$_' => $_,
# scope local: last backtrace
'$@' => $@,
'$!' => $!,
# ractor local: stdin, out, err
'$stdin' => $stdin.inspect,
'$stdout' => $stdout.inspect,
'$stderr' => $stderr.inspect,
```
2020-10-20 04:46:43 +03:00
|
|
|
static VALUE
|
|
|
|
debug_getter(ID id, VALUE *dmy)
|
|
|
|
{
|
|
|
|
return *rb_ruby_debug_ptr();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
debug_setter(VALUE val, ID id, VALUE *dmy)
|
|
|
|
{
|
|
|
|
*rb_ruby_debug_ptr() = val;
|
|
|
|
}
|
|
|
|
|
1998-01-16 15:13:05 +03:00
|
|
|
void
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
ruby_prog_init(void)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
Some global variables can be accessed from ractors
Some global variables should be used from non-main Ractors.
[Bug #17268]
```ruby
# ractor-local (derived from created ractor): debug
'$DEBUG' => $DEBUG,
'$-d' => $-d,
# ractor-local (derived from created ractor): verbose
'$VERBOSE' => $VERBOSE,
'$-w' => $-w,
'$-W' => $-W,
'$-v' => $-v,
# process-local (readonly): other commandline parameters
'$-p' => $-p,
'$-l' => $-l,
'$-a' => $-a,
# process-local (readonly): getpid
'$$' => $$,
# thread local: process result
'$?' => $?,
# scope local: match
'$~' => $~.inspect,
'$&' => $&,
'$`' => $`,
'$\'' => $',
'$+' => $+,
'$1' => $1,
# scope local: last line
'$_' => $_,
# scope local: last backtrace
'$@' => $@,
'$!' => $!,
# ractor local: stdin, out, err
'$stdin' => $stdin.inspect,
'$stdout' => $stdout.inspect,
'$stderr' => $stderr.inspect,
```
2020-10-20 04:46:43 +03:00
|
|
|
rb_define_virtual_variable("$VERBOSE", verbose_getter, verbose_setter);
|
|
|
|
rb_define_virtual_variable("$-v", verbose_getter, verbose_setter);
|
|
|
|
rb_define_virtual_variable("$-w", verbose_getter, verbose_setter);
|
|
|
|
rb_define_virtual_variable("$-W", opt_W_getter, rb_gvar_readonly_setter);
|
|
|
|
rb_define_virtual_variable("$DEBUG", debug_getter, debug_setter);
|
|
|
|
rb_define_virtual_variable("$-d", debug_getter, debug_setter);
|
|
|
|
|
|
|
|
rb_gvar_ractor_local("$VERBOSE");
|
|
|
|
rb_gvar_ractor_local("$-v");
|
|
|
|
rb_gvar_ractor_local("$-w");
|
|
|
|
rb_gvar_ractor_local("$-W");
|
|
|
|
rb_gvar_ractor_local("$DEBUG");
|
|
|
|
rb_gvar_ractor_local("$-d");
|
1998-01-16 15:13:05 +03:00
|
|
|
|
1998-01-16 15:19:22 +03:00
|
|
|
rb_define_hooked_variable("$0", &rb_progname, 0, set_arg0);
|
2004-04-02 06:36:48 +04:00
|
|
|
rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0);
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2013-08-07 18:12:08 +04:00
|
|
|
rb_define_module_function(rb_mProcess, "argv0", proc_argv0, 0);
|
2013-08-07 18:12:04 +04:00
|
|
|
rb_define_module_function(rb_mProcess, "setproctitle", proc_setproctitle, 1);
|
|
|
|
|
2011-06-29 07:09:34 +04:00
|
|
|
/*
|
2015-11-19 13:45:04 +03:00
|
|
|
* ARGV contains the command line arguments used to run ruby.
|
2011-06-29 07:09:34 +04:00
|
|
|
*
|
|
|
|
* A library like OptionParser can be used to process command-line
|
|
|
|
* arguments.
|
|
|
|
*/
|
1998-01-16 15:19:22 +03:00
|
|
|
rb_define_global_const("ARGV", rb_argv);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
ruby_set_argv(int argc, char **argv)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
|
|
|
int i;
|
2008-03-01 11:59:04 +03:00
|
|
|
VALUE av = rb_argv;
|
1998-01-16 15:13:05 +03:00
|
|
|
|
2008-03-01 11:59:04 +03:00
|
|
|
rb_ary_clear(av);
|
2006-12-31 18:02:22 +03:00
|
|
|
for (i = 0; i < argc; i++) {
|
2014-11-29 10:53:17 +03:00
|
|
|
VALUE arg = external_str_new_cstr(argv[i]);
|
2003-03-25 11:26:08 +03:00
|
|
|
|
|
|
|
OBJ_FREEZE(arg);
|
2008-03-01 11:59:04 +03:00
|
|
|
rb_ary_push(av, arg);
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
* include/ruby/{intern,ruby}.h, compile.[ch], error.c, eval.c,
eval_load.c, gc.c, iseq.c, main.c, parse.y, re.c, ruby.c,
yarvcore.[ch] (ruby_eval_tree, ruby_sourcefile, ruby_sourceline,
ruby_nerrs): purge global variables.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12700 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-07-05 12:12:18 +04:00
|
|
|
void *
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 14:44:21 +04:00
|
|
|
ruby_process_options(int argc, char **argv)
|
1998-01-16 15:13:05 +03:00
|
|
|
{
|
2016-08-19 13:44:53 +03:00
|
|
|
ruby_cmdline_options_t opt;
|
2009-02-22 07:04:31 +03:00
|
|
|
VALUE iseq;
|
2015-11-29 05:25:12 +03:00
|
|
|
const char *script_name = (argc > 0 && argv[0]) ? argv[0] : ruby_engine;
|
* include/ruby/{intern,ruby}.h, compile.[ch], error.c, eval.c,
eval_load.c, gc.c, iseq.c, main.c, parse.y, re.c, ruby.c,
yarvcore.[ch] (ruby_eval_tree, ruby_sourcefile, ruby_sourceline,
ruby_nerrs): purge global variables.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12700 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-07-05 12:12:18 +04:00
|
|
|
|
2023-12-08 02:47:36 +03:00
|
|
|
(*rb_ruby_prism_ptr()) = false;
|
|
|
|
|
2017-08-09 14:03:55 +03:00
|
|
|
if (!origarg.argv || origarg.argc <= 0) {
|
|
|
|
origarg.argc = argc;
|
|
|
|
origarg.argv = argv;
|
|
|
|
}
|
2023-04-13 15:45:56 +03:00
|
|
|
set_progname(external_str_new_cstr(script_name)); /* for the time being */
|
2008-06-10 06:25:18 +04:00
|
|
|
rb_argv0 = rb_str_new4(rb_progname);
|
2024-03-03 12:46:46 +03:00
|
|
|
rb_vm_register_global_object(rb_argv0);
|
2011-05-14 14:49:47 +04:00
|
|
|
|
|
|
|
#ifndef HAVE_SETPROCTITLE
|
2014-11-19 18:57:31 +03:00
|
|
|
ruby_init_setproctitle(argc, argv);
|
2011-05-14 14:49:47 +04:00
|
|
|
#endif
|
|
|
|
|
2023-08-23 01:14:37 +03:00
|
|
|
iseq = process_options(argc, argv, cmdline_options_init(&opt));
|
|
|
|
|
2023-09-13 09:02:10 +03:00
|
|
|
if (opt.crash_report && *opt.crash_report) {
|
|
|
|
void ruby_set_crash_report(const char *template);
|
|
|
|
ruby_set_crash_report(opt.crash_report);
|
2023-08-04 10:56:55 +03:00
|
|
|
}
|
2009-02-22 07:04:31 +03:00
|
|
|
return (void*)(struct RData*)iseq;
|
1998-01-16 15:13:05 +03:00
|
|
|
}
|
2007-09-29 12:45:24 +04:00
|
|
|
|
2011-10-30 13:46:56 +04:00
|
|
|
static void
|
|
|
|
fill_standard_fds(void)
|
|
|
|
{
|
|
|
|
int f0, f1, f2, fds[2];
|
2011-10-30 17:34:04 +04:00
|
|
|
struct stat buf;
|
|
|
|
f0 = fstat(0, &buf) == -1 && errno == EBADF;
|
|
|
|
f1 = fstat(1, &buf) == -1 && errno == EBADF;
|
|
|
|
f2 = fstat(2, &buf) == -1 && errno == EBADF;
|
2011-10-30 13:46:56 +04:00
|
|
|
if (f0) {
|
|
|
|
if (pipe(fds) == 0) {
|
|
|
|
close(fds[1]);
|
|
|
|
if (fds[0] != 0) {
|
|
|
|
dup2(fds[0], 0);
|
|
|
|
close(fds[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (f1 || f2) {
|
|
|
|
if (pipe(fds) == 0) {
|
|
|
|
close(fds[0]);
|
|
|
|
if (f1 && fds[1] != 1)
|
|
|
|
dup2(fds[1], 1);
|
|
|
|
if (f2 && fds[1] != 2)
|
|
|
|
dup2(fds[1], 2);
|
|
|
|
if (fds[1] != 1 && fds[1] != 2)
|
|
|
|
close(fds[1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-29 12:45:24 +04:00
|
|
|
void
|
|
|
|
ruby_sysinit(int *argc, char ***argv)
|
|
|
|
{
|
2009-05-17 03:55:46 +04:00
|
|
|
#if defined(_WIN32)
|
2007-09-29 12:45:24 +04:00
|
|
|
rb_w32_sysinit(argc, argv);
|
|
|
|
#endif
|
2017-08-09 14:03:55 +03:00
|
|
|
if (*argc >= 0 && *argv) {
|
|
|
|
origarg.argc = *argc;
|
|
|
|
origarg.argv = *argv;
|
|
|
|
}
|
2011-10-30 13:46:56 +04:00
|
|
|
fill_standard_fds();
|
2007-09-29 12:45:24 +04:00
|
|
|
}
|