1 /**********************************************************************
6 created at: Tue Aug 10 12:47:31 JST 1993
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
12 **********************************************************************/
14 #include "ruby/internal/config.h"
18 #include <sys/types.h>
22 # include <sys/cygwin.h>
26 # include <sys/pstat.h>
29 #if defined(LOAD_RELATIVE) && defined(HAVE_DLADDR)
37 #if defined(HAVE_FCNTL_H)
39 #elif defined(HAVE_SYS_FCNTL_H)
40 # include <sys/fcntl.h>
43 #ifdef HAVE_SYS_PARAM_H
44 # include <sys/param.h>
48 #include "eval_intern.h"
50 #include "internal/error.h"
51 #include "internal/file.h"
52 #include "internal/inits.h"
53 #include "internal/io.h"
54 #include "internal/load.h"
55 #include "internal/loadpath.h"
56 #include "internal/missing.h"
57 #include "internal/object.h"
58 #include "internal/parse.h"
59 #include "internal/process.h"
60 #include "internal/variable.h"
63 #include "ruby/encoding.h"
64 #include "ruby/thread.h"
65 #include "ruby/util.h"
66 #include "ruby/version.h"
67 #include "ruby/internal/error.h"
70 # define MAXPATHLEN 1024
73 # define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
76 void Init_ruby_description(void);
82 #ifndef DISABLE_RUBYGEMS
83 # define DISABLE_RUBYGEMS 0
86 #define DEFAULT_RUBYGEMS_ENABLED "disabled"
88 #define DEFAULT_RUBYGEMS_ENABLED "enabled"
91 void rb_warning_category_update(unsigned int mask
, unsigned int bits
);
94 #define FEATURE_BIT(bit) (1U << feature_##bit)
95 #define EACH_FEATURES(X, SEP) \
104 X(frozen_string_literal) \
109 /* END OF FEATURES */
110 #define EACH_DEBUG_FEATURES(X, SEP) \
111 X(frozen_string_literal) \
112 /* END OF DEBUG FEATURES */
113 #define AMBIGUOUS_FEATURE_NAMES 0 /* no ambiguous feature names now */
114 #define DEFINE_FEATURE(bit) feature_##bit
115 #define DEFINE_DEBUG_FEATURE(bit) feature_debug_##bit
116 enum feature_flag_bits
{
117 EACH_FEATURES(DEFINE_FEATURE
, COMMA
),
118 feature_debug_flag_first
,
119 feature_debug_flag_begin
= feature_debug_flag_first
- 1,
120 EACH_DEBUG_FEATURES(DEFINE_DEBUG_FEATURE
, COMMA
),
124 #define DEBUG_BIT(bit) (1U << feature_debug_##bit)
126 #define DUMP_BIT(bit) (1U << dump_##bit)
127 #define DEFINE_DUMP(bit) dump_##bit
128 #define EACH_DUMPS(X, SEP) \
143 X(parsetree_with_comment) \
147 X(insns_without_opt) \
149 enum dump_flag_bits
{
151 EACH_DUMPS(DEFINE_DUMP
, COMMA
),
152 dump_exit_bits
= (DUMP_BIT(yydebug
) | DUMP_BIT(syntax
) |
153 DUMP_BIT(parsetree
) | DUMP_BIT(parsetree_with_comment
) |
154 DUMP_BIT(insns
) | DUMP_BIT(insns_without_opt
))
157 typedef struct ruby_cmdline_options ruby_cmdline_options_t
;
165 rb_feature_set_to(ruby_features_t
*feat
, unsigned int bit_mask
, unsigned int bit_set
)
167 feat
->mask
|= bit_mask
;
168 feat
->set
= (feat
->set
& ~bit_mask
) | bit_set
;
171 #define FEATURE_SET_TO(feat, bit_mask, bit_set) \
172 rb_feature_set_to(&(feat), bit_mask, bit_set)
173 #define FEATURE_SET(feat, bits) FEATURE_SET_TO(feat, bits, bits)
174 #define FEATURE_SET_RESTORE(feat, save) FEATURE_SET_TO(feat, (save).mask, (save).set & (save).mask)
175 #define FEATURE_SET_P(feat, bits) ((feat).set & (bits))
177 struct ruby_cmdline_options
{
188 ruby_features_t features
;
189 ruby_features_t warn
;
192 struct mjit_options mjit
;
194 struct rb_yjit_options yjit
;
197 unsigned int warning
: 1;
198 unsigned int verbose
: 1;
199 unsigned int do_loop
: 1;
200 unsigned int do_print
: 1;
201 unsigned int do_line
: 1;
202 unsigned int do_split
: 1;
203 unsigned int do_search
: 1;
204 unsigned int setids
: 2;
207 static void init_ids(ruby_cmdline_options_t
*);
209 #define src_encoding_index GET_VM()->src_encoding_index
212 COMPILATION_FEATURES
= (
214 | FEATURE_BIT(frozen_string_literal
)
215 | FEATURE_BIT(debug_frozen_string_literal
)
218 (FEATURE_BIT(debug_flag_first
)-1)
222 & ~FEATURE_BIT(frozen_string_literal
)
228 static ruby_cmdline_options_t
*
229 cmdline_options_init(ruby_cmdline_options_t
*opt
)
231 MEMZERO(opt
, *opt
, 1);
233 opt
->src
.enc
.index
= src_encoding_index
;
234 opt
->ext
.enc
.index
= -1;
235 opt
->intern
.enc
.index
= -1;
236 opt
->features
.set
= DEFAULT_FEATURES
;
237 #ifdef MJIT_FORCE_ENABLE /* to use with: ./configure cppflags="-DMJIT_FORCE_ENABLE" */
238 opt
->features
.set
|= FEATURE_BIT(mjit
);
239 #elif defined(YJIT_FORCE_ENABLE)
240 opt
->features
.set
|= FEATURE_BIT(yjit
);
243 if (getenv("RUBY_YJIT_ENABLE")) {
244 opt
->features
.set
|= FEATURE_BIT(yjit
);
250 static rb_ast_t
*load_file(VALUE parser
, VALUE fname
, VALUE f
, int script
,
251 ruby_cmdline_options_t
*opt
);
252 static VALUE
open_load_file(VALUE fname_v
, int *xflag
);
253 static void forbid_setid(const char *, const ruby_cmdline_options_t
*);
254 #define forbid_setid(s) forbid_setid((s), opt)
261 static const char esc_standout
[] = "\n\033[1;7m";
262 static const char esc_bold
[] = "\033[1m";
263 static const char esc_reset
[] = "\033[0m";
264 static const char esc_none
[] = "";
267 show_usage_line(const char *str
, unsigned int namelen
, unsigned int secondlen
, int help
, int highlight
, unsigned int w
)
269 const char *sb
= highlight
? esc_bold
: esc_none
;
270 const char *se
= highlight
? esc_reset
: esc_none
;
271 const int wrap
= help
&& namelen
+ secondlen
- 1 > w
;
272 printf(" %s%.*s%-*.*s%s%-*s%s\n", sb
, namelen
-1, str
,
273 (wrap
? 0 : w
- namelen
+ 1),
274 (help
? secondlen
-1 : 0), str
+ namelen
, se
,
275 (wrap
? w
+ 3 : 0), (wrap
? "\n" : ""),
276 str
+ namelen
+ secondlen
);
280 usage(const char *name
, int help
, int highlight
, int columns
)
282 /* This message really ought to be max 23 lines.
283 * Removed -h because the user already knows that option. Others? */
287 unsigned short namelen
, secondlen
;
289 #define M(shortopt, longopt, desc) { \
290 shortopt " " longopt " " desc, \
291 (unsigned short)sizeof(shortopt), \
292 (unsigned short)sizeof(longopt), \
295 # define PLATFORM_JIT_OPTION "--yjit"
297 # define PLATFORM_JIT_OPTION "--mjit"
299 static const struct message usage_msg
[] = {
300 M("-0[octal]", "", "specify record separator (\\0, if no argument)"),
301 M("-a", "", "autosplit mode with -n or -p (splits $_ into $F)"),
302 M("-c", "", "check syntax only"),
303 M("-Cdirectory", "", "cd to directory before executing your script"),
304 M("-d", ", --debug", "set debugging flags (set $DEBUG to true)"),
305 M("-e 'command'", "", "one line of script. Several -e's allowed. Omit [programfile]"),
306 M("-Eex[:in]", ", --encoding=ex[:in]", "specify the default external and internal character encodings"),
307 M("-Fpattern", "", "split() pattern for autosplit (-a)"),
308 M("-i[extension]", "", "edit ARGV files in place (make backup if extension supplied)"),
309 M("-Idirectory", "", "specify $LOAD_PATH directory (may be used more than once)"),
310 M("-l", "", "enable line ending processing"),
311 M("-n", "", "assume 'while gets(); ... end' loop around your script"),
312 M("-p", "", "assume loop like -n but print line also like sed"),
313 M("-rlibrary", "", "require the library before executing your script"),
314 M("-s", "", "enable some switch parsing for switches after script name"),
315 M("-S", "", "look for the script using PATH environment variable"),
316 M("-v", "", "print the version number, then turn on verbose mode"),
317 M("-w", "", "turn warnings on for your script"),
318 M("-W[level=2|:category]", "", "set warning level; 0=silence, 1=medium, 2=verbose"),
319 M("-x[directory]", "", "strip off text before #!ruby line and perhaps cd to directory"),
320 M("--jit", "", "enable JIT for the platform, same as " PLATFORM_JIT_OPTION
" (experimental)"),
321 M("--mjit", "", "enable C compiler-based JIT compiler (experimental)"),
322 M("--yjit", "", "enable in-process JIT compiler (experimental)"),
323 M("-h", "", "show this message, --help for more info"),
325 static const struct message help_msg
[] = {
326 M("--copyright", "", "print the copyright"),
327 M("--dump={insns|parsetree|...}[,...]", "",
328 "dump debug information. see below for available dump list"),
329 M("--enable={mjit|rubyopt|...}[,...]", ", --disable={mjit|rubyopt|...}[,...]",
330 "enable or disable features. see below for available features"),
331 M("--external-encoding=encoding", ", --internal-encoding=encoding",
332 "specify the default external or internal character encoding"),
333 M("--backtrace-limit=num", "", "limit the maximum length of backtrace"),
334 M("--verbose", "", "turn on verbose mode and disable script from stdin"),
335 M("--version", "", "print the version number, then exit"),
336 M("--help", "", "show this message, -h for short message"),
338 static const struct message dumps
[] = {
339 M("insns", "", "instruction sequences"),
340 M("insns_without_opt", "", "instruction sequences compiled with no optimization"),
341 M("yydebug", "", "yydebug of yacc parser generator"),
342 M("parsetree", "", "AST"),
343 M("parsetree_with_comment", "", "AST with comments"),
345 static const struct message features
[] = {
346 M("gems", "", "rubygems (only for debugging, default: "DEFAULT_RUBYGEMS_ENABLED
")"),
347 M("error_highlight", "", "error_highlight (default: "DEFAULT_RUBYGEMS_ENABLED
")"),
348 M("did_you_mean", "", "did_you_mean (default: "DEFAULT_RUBYGEMS_ENABLED
")"),
349 M("rubyopt", "", "RUBYOPT environment variable (default: enabled)"),
350 M("frozen-string-literal", "", "freeze all string literals (default: disabled)"),
351 M("mjit", "", "C compiler-based JIT compiler (default: disabled)"),
352 M("yjit", "", "in-process JIT compiler (default: disabled)"),
354 static const struct message warn_categories
[] = {
355 M("deprecated", "", "deprecated features"),
356 M("experimental", "", "experimental features"),
358 static const struct message mjit_options
[] = {
359 M("--mjit-warnings", "", "Enable printing JIT warnings"),
360 M("--mjit-debug", "", "Enable JIT debugging (very slow), or add cflags if specified"),
361 M("--mjit-wait", "", "Wait until JIT compilation finishes every time (for testing)"),
362 M("--mjit-save-temps", "", "Save JIT temporary files in $TMP or /tmp (for testing)"),
363 M("--mjit-verbose=num", "", "Print JIT logs of level num or less to stderr (default: 0)"),
364 M("--mjit-max-cache=num", "", "Max number of methods to be JIT-ed in a cache (default: 100)"),
365 M("--mjit-min-calls=num", "", "Number of calls to trigger JIT (for testing, default: 10000)"),
367 static const struct message yjit_options
[] = {
369 M("--yjit-stats", "", "Enable collecting YJIT statistics"),
371 M("--yjit-exec-mem-size=num", "", "Size of executable memory block in MiB (default: 256)"),
372 M("--yjit-call-threshold", "", "Number of calls to trigger JIT (default: 10)"),
373 M("--yjit-max-versions", "", "Maximum number of versions per basic block (default: 4)"),
374 M("--yjit-greedy-versioning", "", "Greedy versioning mode (default: disabled)"),
377 const char *sb
= highlight
? esc_standout
+1 : esc_none
;
378 const char *se
= highlight
? esc_reset
: esc_none
;
379 const int num
= numberof(usage_msg
) - (help
? 1 : 0);
380 unsigned int w
= (columns
> 80 ? (columns
- 79) / 2 : 0) + 16;
381 #define SHOW(m) show_usage_line((m).str, (m).namelen, (m).secondlen, help, highlight, w)
383 printf("%sUsage:%s %s [switches] [--] [programfile] [arguments]\n", sb
, se
, name
);
384 for (i
= 0; i
< num
; ++i
)
389 if (highlight
) sb
= esc_standout
;
391 for (i
= 0; i
< numberof(help_msg
); ++i
)
393 printf("%s""Dump List:%s\n", sb
, se
);
394 for (i
= 0; i
< numberof(dumps
); ++i
)
396 printf("%s""Features:%s\n", sb
, se
);
397 for (i
= 0; i
< numberof(features
); ++i
)
399 printf("%s""Warning categories:%s\n", sb
, se
);
400 for (i
= 0; i
< numberof(warn_categories
); ++i
)
401 SHOW(warn_categories
[i
]);
402 printf("%s""MJIT options (experimental):%s\n", sb
, se
);
403 for (i
= 0; i
< numberof(mjit_options
); ++i
)
404 SHOW(mjit_options
[i
]);
405 printf("%s""YJIT options (experimental):%s\n", sb
, se
);
406 for (i
= 0; i
< numberof(yjit_options
); ++i
)
407 SHOW(yjit_options
[i
]);
410 #define rubylib_path_new rb_str_new
413 push_include(const char *path
, VALUE (*filter
)(VALUE
))
415 const char sep
= PATH_SEP_CHAR
;
417 VALUE load_path
= GET_VM()->load_path
;
424 for (s
= p
; *s
&& *s
!= sep
; s
= CharNext(s
));
425 rb_ary_push(load_path
, (*filter
)(rubylib_path_new(p
, s
- p
)));
432 push_include_cygwin(const char *path
, VALUE (*filter
)(VALUE
))
435 char rubylib
[FILENAME_MAX
];
444 for (s
= p
; *s
&& *s
!= ';'; s
= CharNext(s
));
448 buf
= rb_str_new(p
, len
);
449 p
= RSTRING_PTR(buf
);
452 rb_str_resize(buf
, len
);
453 p
= strncpy(RSTRING_PTR(buf
), p
, len
);
456 #ifdef HAVE_CYGWIN_CONV_PATH
457 #define CONV_TO_POSIX_PATH(p, lib) \
458 cygwin_conv_path(CCP_WIN_A_TO_POSIX|CCP_RELATIVE, (p), (lib), sizeof(lib))
460 # error no cygwin_conv_path
462 if (CONV_TO_POSIX_PATH(p
, rubylib
) == 0)
464 push_include(p
, filter
);
470 #define push_include push_include_cygwin
474 ruby_push_include(const char *path
, VALUE (*filter
)(VALUE
))
478 push_include(path
, filter
);
482 identical_path(VALUE path
)
487 locale_path(VALUE path
)
489 rb_enc_associate(path
, rb_locale_encoding());
494 ruby_incpush(const char *path
)
496 ruby_push_include(path
, locale_path
);
500 expand_include_path(VALUE path
)
502 char *p
= RSTRING_PTR(path
);
505 if (*p
== '.' && p
[1] == '/')
507 return rb_file_expand_path(path
, Qnil
);
511 ruby_incpush_expand(const char *path
)
513 ruby_push_include(path
, expand_include_path
);
517 #if defined _WIN32 || defined __CYGWIN__
518 static HMODULE libruby
;
521 DllMain(HINSTANCE dll
, DWORD reason
, LPVOID reserved
)
523 if (reason
== DLL_PROCESS_ATTACH
)
529 rb_libruby_handle(void)
535 translit_char_bin(char *p
, int from
, int to
)
538 if ((unsigned char)*p
== from
)
553 # define IF_UTF8_PATH(t, f) t
555 # define IF_UTF8_PATH(t, f) f
560 str_conv_enc(VALUE str
, rb_encoding
*from
, rb_encoding
*to
)
562 return rb_str_conv_enc_opts(str
, from
, to
,
563 ECONV_UNDEF_REPLACE
|ECONV_INVALID_REPLACE
,
567 # define str_conv_enc(str, from, to) (str)
570 void ruby_init_loadpath(void);
572 #if defined(LOAD_RELATIVE)
574 runtime_libruby_path(void)
576 #if defined _WIN32 || defined __CYGWIN__
581 len
= RSTRING_EMBED_LEN_MAX
;
584 VALUE wsopath
= rb_str_new(0, len
*sizeof(WCHAR
));
588 while (wlibpath
= (WCHAR
*)RSTRING_PTR(wsopath
),
589 ret
= GetModuleFileNameW(libruby
, wlibpath
, len
),
592 rb_str_modify_expand(wsopath
, len
*sizeof(WCHAR
));
593 rb_str_set_len(wsopath
, (len
+= len
)*sizeof(WCHAR
));
595 if (!ret
|| ret
> len
) rb_fatal("failed to get module file name");
596 #if defined __CYGWIN__
598 const int win_to_posix
= CCP_WIN_W_TO_POSIX
| CCP_RELATIVE
;
599 size_t newsize
= cygwin_conv_path(win_to_posix
, wlibpath
, 0, 0);
600 if (!newsize
) rb_fatal("failed to convert module path to cygwin");
601 path
= rb_str_new(0, newsize
);
602 libpath
= RSTRING_PTR(path
);
603 if (cygwin_conv_path(win_to_posix
, wlibpath
, libpath
, newsize
)) {
604 rb_str_resize(path
, 0);
610 for (len
= ret
, i
= 0; i
< len
; ++i
) {
611 if (wlibpath
[i
] == L
'\\') {
613 ret
= i
+1; /* chop after the last separator */
617 len
= WideCharToMultiByte(CP_UTF8
, 0, wlibpath
, ret
, NULL
, 0, NULL
, NULL
);
618 path
= rb_utf8_str_new(0, len
);
619 libpath
= RSTRING_PTR(path
);
620 WideCharToMultiByte(CP_UTF8
, 0, wlibpath
, ret
, libpath
, len
, NULL
, NULL
);
622 rb_str_resize(wsopath
, 0);
624 #elif defined(HAVE_DLADDR)
627 const void* addr
= (void *)(VALUE
)expand_include_path
;
629 if (!dladdr((void *)addr
, &dli
)) {
630 return rb_str_new(0, 0);
633 else if (origarg
.argc
> 0 && origarg
.argv
&& dli
.dli_fname
== origarg
.argv
[0]) {
634 fname
= rb_str_new_cstr("/proc/self/exe");
635 path
= rb_readlink(fname
, NULL
);
639 fname
= rb_str_new_cstr(dli
.dli_fname
);
640 path
= rb_realpath_internal(Qnil
, fname
, 1);
642 rb_str_resize(fname
, 0);
645 # error relative load path is not supported on this platform.
650 #define INITIAL_LOAD_PATH_MARK rb_intern_const("@gem_prelude_index")
652 VALUE ruby_archlibdir_path
, ruby_prefix_path
;
655 ruby_init_loadpath(void)
657 VALUE load_path
, archlibdir
= 0;
658 ID id_initial_load_path_mark
;
659 const char *paths
= ruby_initial_load_paths
;
660 #if defined LOAD_RELATIVE
661 #if !defined ENABLE_MULTIARCH
662 # define RUBY_ARCH_PATH ""
663 #elif defined RUBY_ARCH
664 # define RUBY_ARCH_PATH "/"RUBY_ARCH
666 # define RUBY_ARCH_PATH "/"RUBY_PLATFORM
673 sopath
= runtime_libruby_path();
674 libpath
= RSTRING_PTR(sopath
);
676 p
= strrchr(libpath
, '/');
678 static const char libdir
[] = "/"
679 #ifdef LIBDIR_BASENAME
685 const ptrdiff_t libdir_len
= (ptrdiff_t)sizeof(libdir
)
686 - rb_strlen_lit(RUBY_ARCH_PATH
) - 1;
687 static const char bindir
[] = "/bin";
688 const ptrdiff_t bindir_len
= (ptrdiff_t)sizeof(bindir
) - 1;
690 const char *p2
= NULL
;
692 #ifdef ENABLE_MULTIARCH
695 if (p
- libpath
>= bindir_len
&& !STRNCASECMP(p
- bindir_len
, bindir
, bindir_len
)) {
697 archlibdir
= rb_str_subseq(sopath
, 0, p
- libpath
);
698 rb_str_cat_cstr(archlibdir
, libdir
);
699 OBJ_FREEZE_RAW(archlibdir
);
701 else if (p
- libpath
>= libdir_len
&& !strncmp(p
- libdir_len
, libdir
, libdir_len
)) {
702 archlibdir
= rb_str_subseq(sopath
, 0, (p2
? p2
: p
) - libpath
);
703 OBJ_FREEZE_RAW(archlibdir
);
706 #ifdef ENABLE_MULTIARCH
712 p
= rb_enc_path_last_separator(libpath
, p
, rb_ascii8bit_encoding());
713 if (p
) goto multiarch
;
717 baselen
= p
- libpath
;
722 rb_str_resize(sopath
, baselen
);
723 libpath
= RSTRING_PTR(sopath
);
724 #define PREFIX_PATH() sopath
725 #define BASEPATH() rb_str_buf_cat(rb_str_buf_new(baselen+len), libpath, baselen)
726 #define RUBY_RELATIVE(path, len) rb_str_buf_cat(BASEPATH(), (path), (len))
728 const size_t exec_prefix_len
= strlen(ruby_exec_prefix
);
729 #define RUBY_RELATIVE(path, len) rubylib_path_new((path), (len))
730 #define PREFIX_PATH() RUBY_RELATIVE(ruby_exec_prefix, exec_prefix_len)
732 rb_gc_register_address(&ruby_prefix_path
);
733 ruby_prefix_path
= PREFIX_PATH();
734 OBJ_FREEZE_RAW(ruby_prefix_path
);
735 if (!archlibdir
) archlibdir
= ruby_prefix_path
;
736 rb_gc_register_address(&ruby_archlibdir_path
);
737 ruby_archlibdir_path
= archlibdir
;
739 load_path
= GET_VM()->load_path
;
741 ruby_push_include(getenv("RUBYLIB"), identical_path
);
743 id_initial_load_path_mark
= INITIAL_LOAD_PATH_MARK
;
745 size_t len
= strlen(paths
);
746 VALUE path
= RUBY_RELATIVE(paths
, len
);
747 rb_ivar_set(path
, id_initial_load_path_mark
, path
);
748 rb_ary_push(load_path
, path
);
752 rb_const_set(rb_cObject
, rb_intern_const("TMP_RUBY_PREFIX"), ruby_prefix_path
);
757 add_modules(VALUE
*req_list
, const char *mod
)
759 VALUE list
= *req_list
;
763 *req_list
= list
= rb_ary_tmp_new(0);
765 feature
= rb_str_cat_cstr(rb_str_tmp_new(0), mod
);
766 rb_ary_push(list
, feature
);
770 require_libraries(VALUE
*req_list
)
772 VALUE list
= *req_list
;
773 VALUE self
= rb_vm_top_self();
775 rb_encoding
*extenc
= rb_default_external_encoding();
777 CONST_ID(require
, "require");
778 while (list
&& RARRAY_LEN(list
) > 0) {
779 VALUE feature
= rb_ary_shift(list
);
780 rb_enc_associate(feature
, extenc
);
781 RBASIC_SET_CLASS_RAW(feature
, rb_cString
);
783 rb_funcallv(self
, require
, 1, &feature
);
788 static const struct rb_block
*
789 toplevel_context(rb_binding_t
*bind
)
795 process_sflag(int *sflag
)
800 VALUE argv
= rb_argv
;
802 n
= RARRAY_LEN(argv
);
803 args
= RARRAY_CONST_PTR(argv
);
806 char *s
= StringValuePtr(v
);
813 if (s
[1] == '-' && s
[2] == '\0')
817 /* check if valid name before replacing - with _ */
818 for (p
= s
+ 1; *p
; p
++) {
827 else if (*p
!= '_' && !ISALNUM(*p
)) {
830 rb_str_new2("invalid name for global variable - ");
831 if (!(p
= strchr(p
, '='))) {
832 rb_str_cat2(name_error
[0], s
);
835 rb_str_cat(name_error
[0], s
, p
- s
);
837 name_error
[1] = args
[-1];
838 rb_exc_raise(rb_class_new_instance(2, name_error
, rb_eNameError
));
843 for (p
= s
+ 1; *p
; ++p
) {
850 n
= RARRAY_LEN(argv
) - n
;
858 static long proc_options(long argc
, char **argv
, ruby_cmdline_options_t
*opt
, int envopt
);
861 moreswitches(const char *s
, ruby_cmdline_options_t
*opt
, int envopt
)
866 VALUE argstr
, argary
;
869 while (ISSPACE(*s
)) s
++;
871 argstr
= rb_str_tmp_new((len
= strlen(s
)) + (envopt
!=0));
872 argary
= rb_str_tmp_new(0);
874 p
= RSTRING_PTR(argstr
);
875 if (envopt
) *p
++ = ' ';
876 memcpy(p
, s
, len
+ 1);
878 rb_str_cat(argary
, (char *)&ap
, sizeof(ap
));
881 rb_str_cat(argary
, (char *)&ap
, sizeof(ap
));
882 while (*p
&& !ISSPACE(*p
)) ++p
;
885 while (ISSPACE(*p
)) ++p
;
887 argc
= RSTRING_LEN(argary
) / sizeof(ap
);
889 rb_str_cat(argary
, (char *)&ap
, sizeof(ap
));
890 argv
= ptr
= ALLOC_N(char *, argc
);
891 MEMMOVE(argv
, RSTRING_PTR(argary
), char *, argc
);
893 while ((i
= proc_options(argc
, argv
, opt
, envopt
)) > 1 && envopt
&& (argc
-= i
) > 0) {
906 rb_str_resize(argary
, 0);
907 rb_str_resize(argstr
, 0);
911 name_match_p(const char *name
, const char *str
, size_t len
)
913 if (len
== 0) return 0;
915 while (TOLOWER(*str
) == *name
) {
916 if (!--len
|| !*++str
) return 1;
919 if (*str
!= '-' && *str
!= '_') return 0;
920 while (ISALNUM(*name
)) name
++;
921 if (*name
!= '-' && *name
!= '_') return 0;
927 #define NAME_MATCH_P(name, str, len) \
928 ((len) < (int)sizeof(name) && name_match_p((name), (str), (len)))
930 #define UNSET_WHEN(name, bit, str, len) \
931 if (NAME_MATCH_P((name), (str), (len))) { \
932 *(unsigned int *)arg &= ~(bit); \
936 #define SET_WHEN(name, bit, str, len) \
937 if (NAME_MATCH_P((name), (str), (len))) { \
938 *(unsigned int *)arg |= (bit); \
942 #define LITERAL_NAME_ELEMENT(name) #name
945 feature_option(const char *str
, int len
, void *arg
, const unsigned int enable
)
947 static const char list
[] = EACH_FEATURES(LITERAL_NAME_ELEMENT
, ", ");
948 ruby_features_t
*argp
= arg
;
949 unsigned int mask
= ~0U;
950 unsigned int set
= 0U;
951 #if AMBIGUOUS_FEATURE_NAMES
953 # define FEATURE_FOUND ++matched
955 # define FEATURE_FOUND goto found
957 #define SET_FEATURE(bit) \
958 if (NAME_MATCH_P(#bit, str, len)) {set |= mask = FEATURE_BIT(bit); FEATURE_FOUND;}
959 EACH_FEATURES(SET_FEATURE
, ;);
960 if (NAME_MATCH_P("jit", str
, len
)) { // This allows you to cancel --jit
961 #if defined(MJIT_FORCE_ENABLE) || !YJIT_SUPPORTED_P
962 set
|= mask
= FEATURE_BIT(mjit
);
964 set
|= mask
= FEATURE_BIT(yjit
);
968 if (NAME_MATCH_P("all", str
, len
)) {
969 // YJIT and MJIT cannot be enabled at the same time. We enable only YJIT for --enable=all.
970 #if defined(MJIT_FORCE_ENABLE) || !YJIT_SUPPORTED_P
971 mask
&= ~(FEATURE_BIT(yjit
));
973 mask
&= ~(FEATURE_BIT(mjit
));
977 #if AMBIGUOUS_FEATURE_NAMES
978 if (matched
== 1) goto found
;
980 VALUE mesg
= rb_sprintf("ambiguous feature: `%.*s' (", len
, str
);
981 #define ADD_FEATURE_NAME(bit) \
982 if (FEATURE_BIT(bit) & set) { \
983 rb_str_cat_cstr(mesg, #bit); \
984 if (--matched) rb_str_cat_cstr(mesg, ", "); \
986 EACH_FEATURES(ADD_FEATURE_NAME
, ;);
987 rb_str_cat_cstr(mesg
, ")");
988 rb_exc_raise(rb_exc_new_str(rb_eRuntimeError
, mesg
));
989 #undef ADD_FEATURE_NAME
994 rb_warn("unknown argument for --%s: `%.*s'",
995 enable
? "enable" : "disable", len
, str
);
996 rb_warn("features are [%.*s].", (int)strlen(list
), list
);
1000 FEATURE_SET_TO(*argp
, mask
, (mask
& enable
));
1005 enable_option(const char *str
, int len
, void *arg
)
1007 feature_option(str
, len
, arg
, ~0U);
1011 disable_option(const char *str
, int len
, void *arg
)
1013 feature_option(str
, len
, arg
, 0U);
1016 RUBY_EXTERN
const int ruby_patchlevel
;
1017 int ruby_env_debug_option(const char *str
, int len
, void *arg
);
1020 debug_option(const char *str
, int len
, void *arg
)
1022 static const char list
[] = EACH_DEBUG_FEATURES(LITERAL_NAME_ELEMENT
, ", ");
1023 ruby_features_t
*argp
= arg
;
1024 #define SET_WHEN_DEBUG(bit) \
1025 if (NAME_MATCH_P(#bit, str, len)) { \
1026 FEATURE_SET(*argp, DEBUG_BIT(bit)); \
1029 EACH_DEBUG_FEATURES(SET_WHEN_DEBUG
, ;);
1031 if (ruby_patchlevel
< 0 && ruby_env_debug_option(str
, len
, 0)) return;
1033 rb_warn("unknown argument for --debug: `%.*s'", len
, str
);
1034 rb_warn("debug features are [%.*s].", (int)strlen(list
), list
);
1038 dump_option(const char *str
, int len
, void *arg
)
1040 static const char list
[] = EACH_DUMPS(LITERAL_NAME_ELEMENT
, ", ");
1041 #define SET_WHEN_DUMP(bit) SET_WHEN(#bit, DUMP_BIT(bit), str, len)
1042 EACH_DUMPS(SET_WHEN_DUMP
, ;);
1043 rb_warn("don't know how to dump `%.*s',", len
, str
);
1044 rb_warn("but only [%.*s].", (int)strlen(list
), list
);
1048 set_option_encoding_once(const char *type
, VALUE
*name
, const char *e
, long elen
)
1052 if (!elen
) elen
= strlen(e
);
1053 ename
= rb_str_new(e
, elen
);
1056 rb_funcall(ename
, rb_intern("casecmp"), 1, *name
) != INT2FIX(0)) {
1057 rb_raise(rb_eRuntimeError
,
1058 "%s already set to %"PRIsVALUE
, type
, *name
);
1063 #define set_internal_encoding_once(opt, e, elen) \
1064 set_option_encoding_once("default_internal", &(opt)->intern.enc.name, (e), (elen))
1065 #define set_external_encoding_once(opt, e, elen) \
1066 set_option_encoding_once("default_external", &(opt)->ext.enc.name, (e), (elen))
1067 #define set_source_encoding_once(opt, e, elen) \
1068 set_option_encoding_once("source", &(opt)->src.enc.name, (e), (elen))
1070 #define opt_match(s, l, name) \
1071 ((((l) > rb_strlen_lit(name)) ? (s)[rb_strlen_lit(name)] == '=' : \
1072 (l) == rb_strlen_lit(name)) && \
1073 memcmp((s), name, rb_strlen_lit(name)) == 0 && \
1074 (((s) += rb_strlen_lit(name)), 1))
1075 #define opt_match_noarg(s, l, name) \
1076 opt_match(s, l, name) && (*(s) ? (rb_warn("argument to --jit-" name " is ignored"), 1) : 1)
1077 #define opt_match_arg(s, l, name) \
1078 opt_match(s, l, name) && (*(s) ? 1 : (rb_raise(rb_eRuntimeError, "--jit-" name " needs an argument"), 0))
1080 #define yjit_opt_match_noarg(s, l, name) \
1081 opt_match(s, l, name) && (*(s) ? (rb_warn("argument to --yjit-" name " is ignored"), 1) : 1)
1082 #define yjit_opt_match_arg(s, l, name) \
1083 opt_match(s, l, name) && (*(s) && *(s+1) ? 1 : (rb_raise(rb_eRuntimeError, "--yjit-" name " needs an argument"), 0))
1086 setup_yjit_options(const char *s
, struct rb_yjit_options
*yjit_opt
)
1088 const char prefix
[] = "yjit-";
1089 if (strncmp(prefix
, s
, sizeof(prefix
)-1) != 0) {
1092 s
+= sizeof(prefix
)-1;
1093 const size_t l
= strlen(s
);
1098 if (yjit_opt_match_arg(s
, l
, "exec-mem-size")) {
1099 yjit_opt
->exec_mem_size
= atoi(s
+ 1);
1101 else if (yjit_opt_match_arg(s
, l
, "call-threshold")) {
1102 yjit_opt
->call_threshold
= atoi(s
+ 1);
1104 else if (yjit_opt_match_arg(s
, l
, "max-versions")) {
1105 yjit_opt
->max_versions
= atoi(s
+ 1);
1107 else if (yjit_opt_match_noarg(s
, l
, "greedy-versioning")) {
1108 yjit_opt
->greedy_versioning
= true;
1110 else if (yjit_opt_match_noarg(s
, l
, "no-type-prop")) {
1111 yjit_opt
->no_type_prop
= true;
1113 else if (yjit_opt_match_noarg(s
, l
, "stats")) {
1114 yjit_opt
->gen_stats
= true;
1117 rb_raise(rb_eRuntimeError
,
1118 "invalid yjit option `%s' (--help will show valid yjit options)", s
);
1125 setup_mjit_options(const char *s
, struct mjit_options
*mjit_opt
)
1127 if (*s
!= '-') return;
1128 const size_t l
= strlen(++s
);
1129 if (*s
== 0) return;
1130 else if (opt_match_noarg(s
, l
, "warnings")) {
1131 mjit_opt
->warnings
= 1;
1133 else if (opt_match(s
, l
, "debug")) {
1135 mjit_opt
->debug_flags
= strdup(s
+ 1);
1137 mjit_opt
->debug
= 1;
1139 else if (opt_match_noarg(s
, l
, "wait")) {
1142 else if (opt_match_noarg(s
, l
, "save-temps")) {
1143 mjit_opt
->save_temps
= 1;
1145 else if (opt_match(s
, l
, "verbose")) {
1146 mjit_opt
->verbose
= *s
? atoi(s
+ 1) : 1;
1148 else if (opt_match_arg(s
, l
, "max-cache")) {
1149 mjit_opt
->max_cache_size
= atoi(s
+ 1);
1151 else if (opt_match_arg(s
, l
, "min-calls")) {
1152 mjit_opt
->min_calls
= atoi(s
+ 1);
1155 rb_raise(rb_eRuntimeError
,
1156 "invalid MJIT option `%s' (--help will show valid MJIT options)", s
);
1162 proc_options(long argc
, char **argv
, ruby_cmdline_options_t
*opt
, int envopt
)
1164 long n
, argc0
= argc
;
1166 int warning
= opt
->warning
;
1168 if (argc
<= 0 || !argv
)
1171 for (argc
--, argv
++; argc
> 0; argc
--, argv
++) {
1172 const char *const arg
= argv
[0];
1173 if (!arg
|| arg
[0] != '-' || !arg
[1])
1180 if (envopt
) goto noenvopt
;
1181 opt
->do_split
= TRUE
;
1186 if (envopt
) goto noenvopt
;
1187 opt
->do_print
= TRUE
;
1190 if (envopt
) goto noenvopt
;
1191 opt
->do_loop
= TRUE
;
1197 ruby_verbose
= Qtrue
;
1202 if (envopt
) goto noenvopt
;
1203 opt
->dump
|= DUMP_BIT(yydebug
);
1212 opt
->dump
|= DUMP_BIT(version_v
);
1215 if (!opt
->warning
) {
1217 ruby_verbose
= Qtrue
;
1219 FEATURE_SET(opt
->warn
, RB_WARN_CATEGORY_ALL_BITS
);
1225 unsigned int bits
= 0;
1226 static const char no_prefix
[] = "no-";
1227 int enable
= strncmp(s
+= 2, no_prefix
, sizeof(no_prefix
)-1) != 0;
1228 if (!enable
) s
+= sizeof(no_prefix
)-1;
1229 size_t len
= strlen(s
);
1230 if (NAME_MATCH_P("deprecated", s
, len
)) {
1231 bits
= 1U << RB_WARN_CATEGORY_DEPRECATED
;
1233 else if (NAME_MATCH_P("experimental", s
, len
)) {
1234 bits
= 1U << RB_WARN_CATEGORY_EXPERIMENTAL
;
1237 rb_warn("unknown warning category: `%s'", s
);
1239 if (bits
) FEATURE_SET_TO(opt
->warn
, bits
, enable
? bits
: 0);
1244 int v
= 2; /* -W as -W2 */
1247 v
= scan_oct(s
, 1, &numlen
);
1252 if (!opt
->warning
) {
1255 ruby_verbose
= Qnil
;
1258 ruby_verbose
= Qfalse
;
1261 ruby_verbose
= Qtrue
;
1268 FEATURE_SET_TO(opt
->warn
, RB_WARN_CATEGORY_ALL_BITS
, 0);
1271 FEATURE_SET_TO(opt
->warn
, 1U << RB_WARN_CATEGORY_DEPRECATED
, 0);
1274 FEATURE_SET(opt
->warn
, RB_WARN_CATEGORY_ALL_BITS
);
1281 if (envopt
) goto noenvopt
;
1282 opt
->dump
|= DUMP_BIT(syntax
);
1287 if (envopt
) goto noenvopt
;
1289 if (!opt
->sflag
) opt
->sflag
= 1;
1294 if (envopt
) goto noenvopt
;
1295 opt
->dump
|= DUMP_BIT(usage
);
1299 if (envopt
) goto noenvopt
;
1300 opt
->do_line
= TRUE
;
1301 rb_output_rs
= rb_rs
;
1306 if (envopt
) goto noenvopt
;
1308 opt
->do_search
= TRUE
;
1313 if (envopt
) goto noenvopt
;
1317 rb_raise(rb_eRuntimeError
, "no code specified for -e");
1320 if (!opt
->e_script
) {
1321 opt
->e_script
= rb_str_new(0, 0);
1322 if (opt
->script
== 0)
1325 rb_str_cat2(opt
->e_script
, s
);
1326 rb_str_cat2(opt
->e_script
, "\n");
1332 add_modules(&opt
->req_list
, s
);
1334 else if (argc
> 1) {
1335 add_modules(&opt
->req_list
, argv
[1]);
1341 if (envopt
) goto noenvopt
;
1343 ruby_set_inplace_mode(s
+ 1);
1347 if (envopt
) goto noenvopt
;
1351 if (*s
&& chdir(s
) < 0) {
1352 rb_fatal("Can't chdir to %s", s
);
1358 if (envopt
) goto noenvopt
;
1359 if (!*++s
&& (!--argc
|| !(s
= *++argv
) || !*s
)) {
1360 rb_fatal("Can't chdir");
1363 rb_fatal("Can't chdir to %s", s
);
1368 if (envopt
) goto noenvopt
;
1370 rb_fs
= rb_reg_new(s
, strlen(s
), 0);
1375 if (!*++s
&& (!--argc
|| !(s
= *++argv
))) {
1376 rb_raise(rb_eRuntimeError
, "missing argument for -E");
1381 set_internal_encoding_once(opt
, "UTF-8", 0);
1387 const char *enc_name
= 0;
1390 enc_name
= "EUC-JP";
1393 enc_name
= "Windows-31J";
1398 case 'N': case 'n': case 'A': case 'a':
1399 enc_name
= "ASCII-8BIT";
1403 opt
->src
.enc
.name
= rb_str_new2(enc_name
);
1404 if (!opt
->ext
.enc
.name
)
1405 opt
->ext
.enc
.name
= opt
->src
.enc
.name
;
1414 ruby_incpush_expand(s
);
1415 else if (argc
> 1) {
1416 ruby_incpush_expand(argv
[1]);
1422 if (envopt
) goto noenvopt
;
1428 v
= scan_oct(s
, 4, &numlen
);
1432 else if (v
== 0 && numlen
>= 2) {
1433 rb_rs
= rb_str_new2("");
1437 rb_rs
= rb_str_new(&c
, 1);
1443 if (!s
[1] || (s
[1] == '\r' && !s
[2])) {
1449 # define is_option_end(c, allow_hyphen) \
1450 (!(c) || ((allow_hyphen) && (c) == '-') || (c) == '=')
1451 # define check_envopt(name, allow_envopt) \
1452 (((allow_envopt) || !envopt) ? (void)0 : \
1453 rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --" name))
1454 # define need_argument(name, s, needs_arg, next_arg) \
1455 ((*(s) ? !*++(s) : (next_arg) && (!argc || !((s) = argv[1]) || (--argc, ++argv, 0))) && (needs_arg) ? \
1456 rb_raise(rb_eRuntimeError, "missing argument for --" name) \
1458 # define is_option_with_arg(name, allow_hyphen, allow_envopt) \
1459 is_option_with_optarg(name, allow_hyphen, allow_envopt, Qtrue, Qtrue)
1460 # define is_option_with_optarg(name, allow_hyphen, allow_envopt, needs_arg, next_arg) \
1461 (strncmp((name), s, n = sizeof(name) - 1) == 0 && is_option_end(s[n], (allow_hyphen)) ? \
1462 (check_envopt(name, (allow_envopt)), s += n, \
1463 need_argument(name, s, needs_arg, next_arg), 1) : 0)
1465 if (strcmp("copyright", s
) == 0) {
1466 if (envopt
) goto noenvopt_long
;
1467 opt
->dump
|= DUMP_BIT(copyright
);
1469 else if (is_option_with_optarg("debug", Qtrue
, Qtrue
, Qfalse
, Qfalse
)) {
1471 ruby_each_words(s
, debug_option
, &opt
->features
);
1475 ruby_verbose
= Qtrue
;
1478 else if (is_option_with_arg("enable", Qtrue
, Qtrue
)) {
1479 ruby_each_words(s
, enable_option
, &opt
->features
);
1481 else if (is_option_with_arg("disable", Qtrue
, Qtrue
)) {
1482 ruby_each_words(s
, disable_option
, &opt
->features
);
1484 else if (is_option_with_arg("encoding", Qfalse
, Qtrue
)) {
1488 # define set_encoding_part(type) \
1489 if (!(p = strchr(s, ':'))) { \
1490 set_##type##_encoding_once(opt, s, 0); \
1494 set_##type##_encoding_once(opt, s, p-s); \
1496 set_encoding_part(external
);
1497 if (!*(s
= ++p
)) break;
1498 set_encoding_part(internal
);
1499 if (!*(s
= ++p
)) break;
1500 #if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
1501 set_encoding_part(source
);
1502 if (!*(s
= ++p
)) break;
1504 rb_raise(rb_eRuntimeError
, "extra argument for %s: %s",
1505 (arg
[1] == '-' ? "--encoding" : "-E"), s
);
1506 # undef set_encoding_part
1509 else if (is_option_with_arg("internal-encoding", Qfalse
, Qtrue
)) {
1510 set_internal_encoding_once(opt
, s
, 0);
1512 else if (is_option_with_arg("external-encoding", Qfalse
, Qtrue
)) {
1513 set_external_encoding_once(opt
, s
, 0);
1515 #if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
1516 else if (is_option_with_arg("source-encoding", Qfalse
, Qtrue
)) {
1517 set_source_encoding_once(opt
, s
, 0);
1520 else if (strcmp("version", s
) == 0) {
1521 if (envopt
) goto noenvopt_long
;
1522 opt
->dump
|= DUMP_BIT(version
);
1524 else if (strcmp("verbose", s
) == 0) {
1526 ruby_verbose
= Qtrue
;
1528 else if (strcmp("jit", s
) == 0) {
1530 rb_warn("Ruby was built without JIT support");
1531 #elif defined(MJIT_FORCE_ENABLE) || !YJIT_SUPPORTED_P
1532 FEATURE_SET(opt
->features
, FEATURE_BIT(mjit
));
1534 FEATURE_SET(opt
->features
, FEATURE_BIT(yjit
));
1537 else if (strncmp("mjit", s
, 4) == 0) {
1539 FEATURE_SET(opt
->features
, FEATURE_BIT(mjit
));
1540 setup_mjit_options(s
+ 4, &opt
->mjit
);
1542 rb_warn("MJIT support is disabled.");
1545 else if (strcmp("yjit", s
) == 0 || setup_yjit_options(s
, &opt
->yjit
)) {
1547 FEATURE_SET(opt
->features
, FEATURE_BIT(yjit
));
1549 rb_warn("Ruby was built without JIT support");
1552 else if (strcmp("yydebug", s
) == 0) {
1553 if (envopt
) goto noenvopt_long
;
1554 opt
->dump
|= DUMP_BIT(yydebug
);
1556 else if (is_option_with_arg("dump", Qfalse
, Qfalse
)) {
1557 ruby_each_words(s
, dump_option
, &opt
->dump
);
1559 else if (strcmp("help", s
) == 0) {
1560 if (envopt
) goto noenvopt_long
;
1561 opt
->dump
|= DUMP_BIT(help
);
1564 else if (is_option_with_arg("backtrace-limit", Qfalse
, Qfalse
)) {
1566 long n
= strtol(s
, &e
, 10);
1567 if (errno
== ERANGE
|| n
< 0 || *e
) rb_raise(rb_eRuntimeError
, "wrong limit for backtrace length");
1568 rb_backtrace_length_limit
= n
;
1571 rb_raise(rb_eRuntimeError
,
1572 "invalid option --%s (-h will show valid options)", s
);
1582 rb_raise(rb_eRuntimeError
,
1583 "invalid option -%c (-h will show valid options)",
1584 (int)(unsigned char)*s
);
1589 /* "EIdvwWrKU" only */
1590 rb_raise(rb_eRuntimeError
, "invalid switch in RUBYOPT: -%c", *s
);
1594 rb_raise(rb_eRuntimeError
, "invalid switch in RUBYOPT: --%s", s
);
1599 # undef is_option_end
1600 # undef check_envopt
1601 # undef need_argument
1602 # undef is_option_with_arg
1603 # undef is_option_with_optarg
1608 if (warning
) opt
->warning
= warning
;
1609 return argc0
- argc
;
1612 void Init_builtin_features(void);
1615 ruby_init_prelude(void)
1617 Init_builtin_features();
1618 rb_const_remove(rb_cObject
, rb_intern_const("TMP_RUBY_PREFIX"));
1621 void rb_call_builtin_inits(void);
1624 ruby_opt_init(ruby_cmdline_options_t
*opt
)
1626 if (opt
->dump
& dump_exit_bits
) return;
1628 if (opt
->features
.set
& FEATURE_BIT(gems
)) {
1629 rb_define_module("Gem");
1630 if (opt
->features
.set
& FEATURE_BIT(error_highlight
)) {
1631 rb_define_module("ErrorHighlight");
1633 if (opt
->features
.set
& FEATURE_BIT(did_you_mean
)) {
1634 rb_define_module("DidYouMean");
1638 rb_warning_category_update(opt
->warn
.mask
, opt
->warn
.set
);
1640 Init_ext(); /* load statically linked extensions before rubygems */
1641 rb_call_builtin_inits();
1642 ruby_init_prelude();
1644 ruby_set_script_name(opt
->script_name
);
1645 require_libraries(&opt
->req_list
);
1649 opt_enc_index(VALUE enc_name
)
1651 const char *s
= RSTRING_PTR(enc_name
);
1652 int i
= rb_enc_find_index(s
);
1655 rb_raise(rb_eRuntimeError
, "unknown encoding name - %s", s
);
1657 else if (rb_enc_dummy_p(rb_enc_from_index(i
))) {
1658 rb_raise(rb_eRuntimeError
, "dummy encoding is not acceptable - %s ", s
);
1663 #define rb_progname (GET_VM()->progname)
1664 #define rb_orig_progname (GET_VM()->orig_progname)
1669 false_value(ID _x
, VALUE
*_y
)
1675 true_value(ID _x
, VALUE
*_y
)
1680 #define rb_define_readonly_boolean(name, val) \
1681 rb_define_virtual_variable((name), (val) ? true_value : false_value, 0)
1688 line
= rb_lastline_get();
1689 if (!RB_TYPE_P(line
, T_STRING
)) {
1690 rb_raise(rb_eTypeError
, "$_ value need to be String (%s given)",
1691 NIL_P(line
) ? "nil" : rb_obj_classname(line
));
1698 * sub(pattern, replacement) -> $_
1699 * sub(pattern) {|...| block } -> $_
1701 * Equivalent to <code>$_.sub(<i>args</i>)</code>, except that
1702 * <code>$_</code> will be updated if substitution occurs.
1703 * Available only when -p/-n command line option specified.
1707 rb_f_sub(int argc
, VALUE
*argv
, VALUE _
)
1709 VALUE str
= rb_funcall_passing_block(uscore_get(), rb_intern("sub"), argc
, argv
);
1710 rb_lastline_set(str
);
1716 * gsub(pattern, replacement) -> $_
1717 * gsub(pattern) {|...| block } -> $_
1719 * Equivalent to <code>$_.gsub...</code>, except that <code>$_</code>
1720 * will be updated if substitution occurs.
1721 * Available only when -p/-n command line option specified.
1726 rb_f_gsub(int argc
, VALUE
*argv
, VALUE _
)
1728 VALUE str
= rb_funcall_passing_block(uscore_get(), rb_intern("gsub"), argc
, argv
);
1729 rb_lastline_set(str
);
1737 * Equivalent to <code>($_.dup).chop!</code>, except <code>nil</code>
1738 * is never returned. See String#chop!.
1739 * Available only when -p/-n command line option specified.
1746 VALUE str
= rb_funcall_passing_block(uscore_get(), rb_intern("chop"), 0, 0);
1747 rb_lastline_set(str
);
1755 * chomp(string) -> $_
1757 * Equivalent to <code>$_ = $_.chomp(<em>string</em>)</code>. See
1759 * Available only when -p/-n command line option specified.
1764 rb_f_chomp(int argc
, VALUE
*argv
, VALUE _
)
1766 VALUE str
= rb_funcall_passing_block(uscore_get(), rb_intern("chomp"), argc
, argv
);
1767 rb_lastline_set(str
);
1772 setup_pager_env(void)
1774 if (!getenv("LESS")) ruby_setenv("LESS", "-R"); // Output "raw" control characters.
1781 HANDLE h
= GetStdHandle(STD_OUTPUT_HANDLE
);
1783 if (!GetConsoleMode(h
, &m
)) return 0;
1784 # ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
1785 # define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4
1787 if (!(m
& ENABLE_VIRTUAL_TERMINAL_PROCESSING
)) return 0;
1790 #elif !defined(HAVE_WORKING_FORK)
1791 # define tty_enabled() 0
1795 copy_str(VALUE str
, rb_encoding
*enc
, bool intern
)
1798 if (rb_enc_str_coderange_scan(str
, enc
) == ENC_CODERANGE_BROKEN
)
1800 return rb_enc_associate(rb_str_dup(str
), enc
);
1802 return rb_enc_interned_str(RSTRING_PTR(str
), RSTRING_LEN(str
), enc
);
1806 process_options(int argc
, char **argv
, ruby_cmdline_options_t
*opt
)
1811 const rb_iseq_t
*iseq
;
1812 rb_encoding
*enc
, *lenc
;
1814 rb_encoding
*ienc
= 0;
1815 rb_encoding
*const uenc
= rb_utf8_encoding();
1818 char fbuf
[MAXPATHLEN
];
1819 int i
= (int)proc_options(argc
, argv
, opt
, 0);
1820 unsigned int dump
= opt
->dump
& dump_exit_bits
;
1821 rb_vm_t
*vm
= GET_VM();
1822 const long loaded_before_enc
= RARRAY_LEN(vm
->loaded_features
);
1824 if (opt
->dump
& (DUMP_BIT(usage
)|DUMP_BIT(help
))) {
1825 int tty
= isatty(1);
1826 const char *const progname
=
1827 (argc
> 0 && argv
&& argv
[0] ? argv
[0] :
1828 origarg
.argc
> 0 && origarg
.argv
&& origarg
.argv
[0] ? origarg
.argv
[0] :
1831 if ((opt
->dump
& DUMP_BIT(help
)) && tty
) {
1832 const char *pager_env
= getenv("RUBY_PAGER");
1833 if (!pager_env
) pager_env
= getenv("PAGER");
1834 if (pager_env
&& *pager_env
&& isatty(0)) {
1835 const char *columns_env
= getenv("COLUMNS");
1836 if (columns_env
) columns
= atoi(columns_env
);
1837 VALUE pager
= rb_str_new_cstr(pager_env
);
1838 #ifdef HAVE_WORKING_FORK
1840 if (rb_pipe(fds
) == 0) {
1841 rb_pid_t pid
= rb_fork();
1843 /* exec PAGER with reading from child */
1846 else if (pid
== 0) {
1847 /* send the help message to the parent PAGER */
1855 rb_f_exec(1, &pager
);
1857 rb_waitpid(pid
, 0, 0);
1862 VALUE port
= rb_io_popen(pager
, rb_str_new_lit("w"), Qnil
, Qnil
);
1864 int oldout
= dup(1);
1865 int olderr
= dup(2);
1866 int fd
= RFILE(port
)->fptr
->fd
;
1867 tty
= tty_enabled();
1870 usage(progname
, 1, tty
, columns
);
1880 usage(progname
, (opt
->dump
& DUMP_BIT(help
)), tty
, columns
);
1887 if ((opt
->features
.set
& FEATURE_BIT(rubyopt
)) && (s
= getenv("RUBYOPT"))) {
1888 VALUE src_enc_name
= opt
->src
.enc
.name
;
1889 VALUE ext_enc_name
= opt
->ext
.enc
.name
;
1890 VALUE int_enc_name
= opt
->intern
.enc
.name
;
1891 ruby_features_t feat
= opt
->features
;
1892 ruby_features_t warn
= opt
->warn
;
1894 opt
->src
.enc
.name
= opt
->ext
.enc
.name
= opt
->intern
.enc
.name
= 0;
1895 moreswitches(s
, opt
, 1);
1897 opt
->src
.enc
.name
= src_enc_name
;
1899 opt
->ext
.enc
.name
= ext_enc_name
;
1901 opt
->intern
.enc
.name
= int_enc_name
;
1902 FEATURE_SET_RESTORE(opt
->features
, feat
);
1903 FEATURE_SET_RESTORE(opt
->warn
, warn
);
1906 if (opt
->src
.enc
.name
)
1907 /* cannot set deprecated category, as enabling deprecation warnings based on flags
1908 * has not happened yet.
1910 rb_warning("-K is specified; it is for 1.8 compatibility and may cause odd behavior");
1913 if (opt
->features
.set
& FEATURE_BIT(mjit
)) {
1914 opt
->mjit
.on
= TRUE
; /* set mjit.on for ruby_show_version() API and check to call mjit_init() */
1917 if (opt
->features
.set
& FEATURE_BIT(yjit
)) {
1920 rb_warn("MJIT and YJIT cannot both be enabled at the same time. Exiting");
1924 rb_yjit_init(&opt
->yjit
);
1926 if (opt
->dump
& (DUMP_BIT(version
) | DUMP_BIT(version_v
))) {
1928 mjit_opts
.on
= opt
->mjit
.on
; /* used by ruby_show_version(). mjit_init() still can't be called here. */
1930 ruby_show_version();
1931 if (opt
->dump
& DUMP_BIT(version
)) return Qtrue
;
1933 if (opt
->dump
& DUMP_BIT(copyright
)) {
1934 ruby_show_copyright();
1938 if (!opt
->e_script
) {
1939 if (argc
<= 0) { /* no more args */
1945 opt
->script
= argv
[0];
1946 if (!opt
->script
|| opt
->script
[0] == '\0') {
1949 else if (opt
->do_search
) {
1950 const char *path
= getenv("RUBYPATH");
1954 opt
->script
= dln_find_file_r(argv
[0], path
, fbuf
, sizeof(fbuf
));
1957 opt
->script
= dln_find_file_r(argv
[0], getenv(PATH_ENV
), fbuf
, sizeof(fbuf
));
1960 opt
->script
= argv
[0];
1965 if (opt
->script
[0] == '-' && !opt
->script
[1]) {
1966 forbid_setid("program input from stdin");
1970 opt
->script_name
= rb_str_new_cstr(opt
->script
);
1971 opt
->script
= RSTRING_PTR(opt
->script_name
);
1974 translit_char_bin(RSTRING_PTR(opt
->script_name
), '\\', '/');
1975 #elif defined DOSISH
1976 translit_char(RSTRING_PTR(opt
->script_name
), '\\', '/');
1979 ruby_gc_set_params();
1980 ruby_init_loadpath();
1984 /* Using TMP_RUBY_PREFIX created by ruby_init_loadpath(). */
1985 mjit_init(&opt
->mjit
);
1988 Init_ruby_description();
1990 lenc
= rb_locale_encoding();
1991 rb_enc_associate(rb_progname
, lenc
);
1992 rb_obj_freeze(rb_progname
);
1993 parser
= rb_parser_new();
1994 if (opt
->dump
& DUMP_BIT(yydebug
)) {
1995 rb_parser_set_yydebug(parser
, Qtrue
);
1997 if (opt
->ext
.enc
.name
!= 0) {
1998 opt
->ext
.enc
.index
= opt_enc_index(opt
->ext
.enc
.name
);
2000 if (opt
->intern
.enc
.name
!= 0) {
2001 opt
->intern
.enc
.index
= opt_enc_index(opt
->intern
.enc
.name
);
2003 if (opt
->src
.enc
.name
!= 0) {
2004 opt
->src
.enc
.index
= opt_enc_index(opt
->src
.enc
.name
);
2005 src_encoding_index
= opt
->src
.enc
.index
;
2007 if (opt
->ext
.enc
.index
>= 0) {
2008 enc
= rb_enc_from_index(opt
->ext
.enc
.index
);
2011 enc
= IF_UTF8_PATH(uenc
, lenc
);
2013 rb_enc_set_default_external(rb_enc_from_encoding(enc
));
2014 if (opt
->intern
.enc
.index
>= 0) {
2015 enc
= rb_enc_from_index(opt
->intern
.enc
.index
);
2016 rb_enc_set_default_internal(rb_enc_from_encoding(enc
));
2017 opt
->intern
.enc
.index
= -1;
2022 script_name
= opt
->script_name
;
2023 rb_enc_associate(opt
->script_name
, IF_UTF8_PATH(uenc
, lenc
));
2026 opt
->script_name
= str_conv_enc(opt
->script_name
, uenc
, lenc
);
2027 opt
->script
= RSTRING_PTR(opt
->script_name
);
2030 rb_obj_freeze(opt
->script_name
);
2031 if (IF_UTF8_PATH(uenc
!= lenc
, 1)) {
2033 VALUE load_path
= vm
->load_path
;
2034 const ID id_initial_load_path_mark
= INITIAL_LOAD_PATH_MARK
;
2035 int modifiable
= FALSE
;
2037 rb_get_expanded_load_path();
2038 for (i
= 0; i
< RARRAY_LEN(load_path
); ++i
) {
2039 VALUE path
= RARRAY_AREF(load_path
, i
);
2040 int mark
= rb_attr_get(path
, id_initial_load_path_mark
) == path
;
2042 VALUE newpath
= rb_str_conv_enc(path
, uenc
, lenc
);
2043 if (newpath
== path
) continue;
2046 if (!(path
= copy_str(path
, lenc
, !mark
))) continue;
2048 if (mark
) rb_ivar_set(path
, id_initial_load_path_mark
, path
);
2050 rb_ary_modify(load_path
);
2053 RARRAY_ASET(load_path
, i
, path
);
2056 rb_ary_replace(vm
->load_path_snapshot
, load_path
);
2060 VALUE loaded_features
= vm
->loaded_features
;
2061 bool modified
= false;
2062 for (long i
= loaded_before_enc
; i
< RARRAY_LEN(loaded_features
); ++i
) {
2063 VALUE path
= RARRAY_AREF(loaded_features
, i
);
2064 if (!(path
= copy_str(path
, IF_UTF8_PATH(uenc
, lenc
), true))) continue;
2066 RARRAY_ASET(loaded_features
, i
, path
);
2069 rb_ary_replace(vm
->loaded_features_snapshot
, loaded_features
);
2073 if (opt
->features
.mask
& COMPILATION_FEATURES
) {
2074 VALUE option
= rb_hash_new();
2075 #define SET_COMPILE_OPTION(h, o, name) \
2076 rb_hash_aset((h), ID2SYM(rb_intern_const(#name)), \
2077 RBOOL(FEATURE_SET_P(o->features, FEATURE_BIT(name))));
2078 SET_COMPILE_OPTION(option
, opt
, frozen_string_literal
);
2079 SET_COMPILE_OPTION(option
, opt
, debug_frozen_string_literal
);
2080 rb_funcallv(rb_cISeq
, rb_intern_const("compile_option="), 1, &option
);
2081 #undef SET_COMPILE_OPTION
2083 ruby_set_argv(argc
, argv
);
2084 process_sflag(&opt
->sflag
);
2086 rb_parser_set_context(parser
, 0, TRUE
);
2088 if (opt
->e_script
) {
2089 VALUE progname
= rb_progname
;
2091 if (opt
->src
.enc
.index
>= 0) {
2092 eenc
= rb_enc_from_index(opt
->src
.enc
.index
);
2097 if (ienc
) eenc
= ienc
;
2102 opt
->e_script
= str_conv_enc(opt
->e_script
, uenc
, eenc
);
2105 rb_enc_associate(opt
->e_script
, eenc
);
2107 ruby_set_script_name(progname
);
2108 rb_parser_set_options(parser
, opt
->do_print
, opt
->do_loop
,
2109 opt
->do_line
, opt
->do_split
);
2110 ast
= rb_parser_compile_string(parser
, opt
->script
, opt
->e_script
, 1);
2114 f
= open_load_file(script_name
, &opt
->xflag
);
2115 ast
= load_file(parser
, opt
->script_name
, f
, 1, opt
);
2117 ruby_set_script_name(opt
->script_name
);
2118 if (dump
& DUMP_BIT(yydebug
)) {
2119 dump
&= ~DUMP_BIT(yydebug
);
2120 if (!dump
) return Qtrue
;
2123 if (opt
->ext
.enc
.index
>= 0) {
2124 enc
= rb_enc_from_index(opt
->ext
.enc
.index
);
2127 enc
= IF_UTF8_PATH(uenc
, lenc
);
2129 rb_enc_set_default_external(rb_enc_from_encoding(enc
));
2130 if (opt
->intern
.enc
.index
>= 0) {
2131 /* Set in the shebang line */
2132 enc
= rb_enc_from_index(opt
->intern
.enc
.index
);
2133 rb_enc_set_default_internal(rb_enc_from_encoding(enc
));
2135 else if (!rb_default_internal_encoding())
2136 /* Freeze default_internal */
2137 rb_enc_set_default_internal(Qnil
);
2138 rb_stdio_set_default_encoding();
2140 if (!ast
->body
.root
) {
2141 rb_ast_dispose(ast
);
2145 process_sflag(&opt
->sflag
);
2148 if (dump
& DUMP_BIT(syntax
)) {
2149 printf("Syntax OK\n");
2150 dump
&= ~DUMP_BIT(syntax
);
2151 if (!dump
) return Qtrue
;
2155 rb_define_global_function("sub", rb_f_sub
, -1);
2156 rb_define_global_function("gsub", rb_f_gsub
, -1);
2157 rb_define_global_function("chop", rb_f_chop
, 0);
2158 rb_define_global_function("chomp", rb_f_chomp
, -1);
2161 if (dump
& (DUMP_BIT(parsetree
)|DUMP_BIT(parsetree_with_comment
))) {
2162 rb_io_write(rb_stdout
, rb_parser_dump_tree(ast
->body
.root
, dump
& DUMP_BIT(parsetree_with_comment
)));
2163 rb_io_flush(rb_stdout
);
2164 dump
&= ~DUMP_BIT(parsetree
)&~DUMP_BIT(parsetree_with_comment
);
2166 rb_ast_dispose(ast
);
2173 if (!opt
->e_script
&& strcmp(opt
->script
, "-")) {
2174 path
= rb_realpath_internal(Qnil
, script_name
, 1);
2177 path
= str_conv_enc(path
, uenc
, lenc
);
2180 if (!ENCODING_GET(path
)) { /* ASCII-8BIT */
2181 rb_enc_copy(path
, opt
->script_name
);
2185 rb_binding_t
*toplevel_binding
;
2186 GetBindingPtr(rb_const_get(rb_cObject
, rb_intern("TOPLEVEL_BINDING")),
2188 const struct rb_block
*base_block
= toplevel_context(toplevel_binding
);
2189 iseq
= rb_iseq_new_main(&ast
->body
, opt
->script_name
, path
, vm_block_iseq(base_block
), !(dump
& DUMP_BIT(insns_without_opt
)));
2190 rb_ast_dispose(ast
);
2193 if (dump
& (DUMP_BIT(insns
) | DUMP_BIT(insns_without_opt
))) {
2194 rb_io_write(rb_stdout
, rb_iseq_disasm((const rb_iseq_t
*)iseq
));
2195 rb_io_flush(rb_stdout
);
2196 dump
&= ~DUMP_BIT(insns
);
2197 if (!dump
) return Qtrue
;
2199 if (opt
->dump
& dump_exit_bits
) return Qtrue
;
2201 rb_define_readonly_boolean("$-p", opt
->do_print
);
2202 rb_define_readonly_boolean("$-l", opt
->do_line
);
2203 rb_define_readonly_boolean("$-a", opt
->do_split
);
2205 rb_gvar_ractor_local("$-p");
2206 rb_gvar_ractor_local("$-l");
2207 rb_gvar_ractor_local("$-a");
2209 if ((rb_e_script
= opt
->e_script
) != 0) {
2210 rb_str_freeze(rb_e_script
);
2211 rb_gc_register_mark_object(opt
->e_script
);
2215 rb_execution_context_t
*ec
= GET_EC();
2217 if (opt
->e_script
) {
2219 rb_exec_event_hook_script_compiled(ec
, iseq
, opt
->e_script
);
2223 rb_exec_event_hook_script_compiled(ec
, iseq
, Qnil
);
2231 warn_cr_in_shebang(const char *str
, long len
)
2233 if (str
[len
-1] == '\n' && str
[len
-2] == '\r') {
2234 rb_warn("shebang line ending with \\r may cause problems");
2238 #define warn_cr_in_shebang(str, len) (void)0
2241 struct load_file_arg
{
2245 ruby_cmdline_options_t
*opt
;
2250 load_file_internal(VALUE argp_v
)
2252 struct load_file_arg
*argp
= (struct load_file_arg
*)argp_v
;
2253 VALUE parser
= argp
->parser
;
2254 VALUE orig_fname
= argp
->fname
;
2255 int script
= argp
->script
;
2256 ruby_cmdline_options_t
*opt
= argp
->opt
;
2263 CONST_ID(set_encoding
, "set_encoding");
2265 VALUE c
= 1; /* something not nil */
2269 int no_src_enc
= !opt
->src
.enc
.name
;
2270 int no_ext_enc
= !opt
->ext
.enc
.name
;
2271 int no_int_enc
= !opt
->intern
.enc
.name
;
2273 enc
= rb_ascii8bit_encoding();
2274 rb_funcall(f
, set_encoding
, 1, rb_enc_from_encoding(enc
));
2279 while (!NIL_P(line
= rb_io_gets(f
))) {
2281 RSTRING_GETMEM(line
, str
, len
);
2282 if (len
> 2 && str
[0] == '#' && str
[1] == '!') {
2283 if (line_start
== 1) warn_cr_in_shebang(str
, len
);
2284 if ((p
= strstr(str
+2, ruby_engine
)) != 0) {
2289 rb_loaderror("no Ruby script found in input");
2292 c
= rb_io_getbyte(f
);
2293 if (c
== INT2FIX('#')) {
2294 c
= rb_io_getbyte(f
);
2295 if (c
== INT2FIX('!') && !NIL_P(line
= rb_io_gets(f
))) {
2296 RSTRING_GETMEM(line
, str
, len
);
2297 warn_cr_in_shebang(str
, len
);
2298 if ((p
= strstr(str
, ruby_engine
)) == 0) {
2299 /* not ruby script, assume -x flag */
2300 goto search_shebang
;
2305 if (*str
== '\n') *str
-- = '\0';
2306 if (*str
== '\r') *str
-- = '\0';
2307 /* ruby_engine should not contain a space */
2308 if ((p
= strstr(p
, " -")) != 0) {
2310 moreswitches(p
+ 1, opt
, 0);
2313 /* push back shebang for pragma may exist in next line */
2314 rb_io_ungetbyte(f
, rb_str_new2("!\n"));
2316 else if (!NIL_P(c
)) {
2317 rb_io_ungetbyte(f
, c
);
2319 rb_io_ungetbyte(f
, INT2FIX('#'));
2320 if (no_src_enc
&& opt
->src
.enc
.name
) {
2321 opt
->src
.enc
.index
= opt_enc_index(opt
->src
.enc
.name
);
2322 src_encoding_index
= opt
->src
.enc
.index
;
2324 if (no_ext_enc
&& opt
->ext
.enc
.name
) {
2325 opt
->ext
.enc
.index
= opt_enc_index(opt
->ext
.enc
.name
);
2327 if (no_int_enc
&& opt
->intern
.enc
.name
) {
2328 opt
->intern
.enc
.index
= opt_enc_index(opt
->intern
.enc
.name
);
2331 else if (!NIL_P(c
)) {
2332 rb_io_ungetbyte(f
, c
);
2339 if (opt
->src
.enc
.index
>= 0) {
2340 enc
= rb_enc_from_index(opt
->src
.enc
.index
);
2342 else if (f
== rb_stdin
) {
2343 enc
= rb_locale_encoding();
2346 enc
= rb_utf8_encoding();
2348 rb_parser_set_options(parser
, opt
->do_print
, opt
->do_loop
,
2349 opt
->do_line
, opt
->do_split
);
2351 f
= rb_str_new(0, 0);
2352 rb_enc_associate(f
, enc
);
2353 return (VALUE
)rb_parser_compile_string_path(parser
, orig_fname
, f
, line_start
);
2355 rb_funcall(f
, set_encoding
, 2, rb_enc_from_encoding(enc
), rb_str_new_cstr("-"));
2356 ast
= rb_parser_compile_file_path(parser
, orig_fname
, f
, line_start
);
2357 rb_funcall(f
, set_encoding
, 1, rb_parser_encoding(parser
));
2358 if (script
&& rb_parser_end_seen_p(parser
)) {
2360 * DATA is a File that contains the data section of the executed file.
2361 * To create a data section use <tt>__END__</tt>:
2371 rb_define_global_const("DATA", f
);
2377 /* disabling O_NONBLOCK, and returns 0 on success, otherwise errno */
2379 disable_nonblock(int fd
)
2381 #if defined(HAVE_FCNTL) && defined(F_SETFL)
2382 if (fcntl(fd
, F_SETFL
, 0) < 0) {
2383 const int e
= errno
;
2385 # if defined ENOTSUP
2386 if (e
== ENOTSUP
) return 0;
2388 # if defined B_UNSUPPORTED
2389 if (e
== B_UNSUPPORTED
) return 0;
2398 open_load_file(VALUE fname_v
, int *xflag
)
2400 const char *fname
= (fname_v
= rb_str_encode_ospath(fname_v
),
2401 StringValueCStr(fname_v
));
2402 long flen
= RSTRING_LEN(fname_v
);
2406 if (flen
== 1 && fname
[0] == '-') {
2411 /* open(2) may block if fname is point to FIFO and it's empty. Let's
2413 #if defined O_NONBLOCK && HAVE_FCNTL && !(O_NONBLOCK & O_ACCMODE)
2414 /* TODO: fix conflicting O_NONBLOCK in ruby/win32.h */
2415 # define MODE_TO_LOAD (O_RDONLY | O_NONBLOCK)
2416 #elif defined O_NDELAY && HAVE_FCNTL && !(O_NDELAY & O_ACCMODE)
2417 # define MODE_TO_LOAD (O_RDONLY | O_NDELAY)
2419 # define MODE_TO_LOAD (O_RDONLY)
2421 int mode
= MODE_TO_LOAD
;
2422 #if defined DOSISH || defined __CYGWIN__
2423 # define isdirsep(x) ((x) == '/' || (x) == '\\')
2425 static const char exeext
[] = ".exe";
2426 enum {extlen
= sizeof(exeext
)-1};
2427 if (flen
> extlen
&& !isdirsep(fname
[flen
-extlen
-1]) &&
2428 STRNCASECMP(fname
+flen
-extlen
, exeext
, extlen
) == 0) {
2435 if ((fd
= rb_cloexec_open(fname
, mode
, 0)) < 0) {
2437 if (!rb_gc_for_fd(e
)) {
2438 rb_load_fail(fname_v
, strerror(e
));
2440 if ((fd
= rb_cloexec_open(fname
, mode
, 0)) < 0) {
2441 rb_load_fail(fname_v
, strerror(errno
));
2444 rb_update_max_fd(fd
);
2446 if (MODE_TO_LOAD
!= O_RDONLY
&& (e
= disable_nonblock(fd
)) != 0) {
2448 rb_load_fail(fname_v
, strerror(e
));
2451 e
= ruby_is_fd_loadable(fd
);
2455 rb_load_fail(fname_v
, strerror(e
));
2458 f
= rb_io_fdopen(fd
, mode
, fname
);
2461 We need to wait if FIFO is empty. It's FIFO's semantics.
2462 rb_thread_wait_fd() release GVL. So, it's safe.
2464 rb_io_wait(f
, RB_INT2NUM(RUBY_IO_READABLE
), Qnil
);
2471 restore_load_file(VALUE arg
)
2473 struct load_file_arg
*argp
= (struct load_file_arg
*)arg
;
2476 if (!NIL_P(f
) && f
!= rb_stdin
) {
2483 load_file(VALUE parser
, VALUE fname
, VALUE f
, int script
, ruby_cmdline_options_t
*opt
)
2485 struct load_file_arg arg
;
2486 arg
.parser
= parser
;
2488 arg
.script
= script
;
2491 return (rb_ast_t
*)rb_ensure(load_file_internal
, (VALUE
)&arg
,
2492 restore_load_file
, (VALUE
)&arg
);
2496 rb_load_file(const char *fname
)
2498 VALUE fname_v
= rb_str_new_cstr(fname
);
2499 return rb_load_file_str(fname_v
);
2503 rb_load_file_str(VALUE fname_v
)
2505 return rb_parser_load_file(rb_parser_new(), fname_v
);
2509 rb_parser_load_file(VALUE parser
, VALUE fname_v
)
2511 ruby_cmdline_options_t opt
;
2512 VALUE f
= open_load_file(fname_v
, &cmdline_options_init(&opt
)->xflag
);
2513 return load_file(parser
, fname_v
, f
, 0, &opt
);
2518 * Process.argv0 -> frozen_string
2520 * Returns the name of the script being executed. The value is not
2521 * affected by assigning a new value to $0.
2523 * This method first appeared in Ruby 2.1 to serve as a global
2524 * variable free means to get the script name.
2528 proc_argv0(VALUE process
)
2530 return rb_orig_progname
;
2533 static VALUE
ruby_setproctitle(VALUE title
);
2537 * Process.setproctitle(string) -> string
2539 * Sets the process title that appears on the ps(1) command. Not
2540 * necessarily effective on all platforms. No exception will be
2541 * raised regardless of the result, nor will NotImplementedError be
2542 * raised even if the platform does not support the feature.
2544 * Calling this method does not affect the value of $0.
2546 * Process.setproctitle('myapp: worker #%d' % worker_id)
2548 * This method first appeared in Ruby 2.1 to serve as a global
2549 * variable free means to change the process title.
2553 proc_setproctitle(VALUE process
, VALUE title
)
2555 return ruby_setproctitle(title
);
2559 ruby_setproctitle(VALUE title
)
2561 const char *ptr
= StringValueCStr(title
);
2562 setproctitle("%.*s", RSTRING_LENINT(title
), ptr
);
2567 set_arg0(VALUE val
, ID id
, VALUE
*_
)
2569 if (origarg
.argv
== 0)
2570 rb_raise(rb_eRuntimeError
, "$0 not initialized");
2572 rb_progname
= rb_str_new_frozen(ruby_setproctitle(val
));
2576 external_str_new_cstr(const char *p
)
2579 VALUE str
= rb_utf8_str_new_cstr(p
);
2580 str
= str_conv_enc(str
, NULL
, rb_default_external_encoding());
2583 return rb_external_str_new_cstr(p
);
2588 ruby_script(const char *name
)
2591 rb_orig_progname
= rb_progname
= external_str_new_cstr(name
);
2592 rb_vm_set_progname(rb_progname
);
2596 /*! Sets the current script name to this value.
2598 * Same as ruby_script() but accepts a VALUE.
2601 ruby_set_script_name(VALUE name
)
2603 rb_orig_progname
= rb_progname
= rb_str_dup(name
);
2604 rb_vm_set_progname(rb_progname
);
2608 init_ids(ruby_cmdline_options_t
*opt
)
2610 rb_uid_t uid
= getuid();
2611 rb_uid_t euid
= geteuid();
2612 rb_gid_t gid
= getgid();
2613 rb_gid_t egid
= getegid();
2615 if (uid
!= euid
) opt
->setids
|= 1;
2616 if (egid
!= gid
) opt
->setids
|= 2;
2621 forbid_setid(const char *s
, const ruby_cmdline_options_t
*opt
)
2623 if (opt
->setids
& 1)
2624 rb_raise(rb_eSecurityError
, "no %s allowed while running setuid", s
);
2625 if (opt
->setids
& 2)
2626 rb_raise(rb_eSecurityError
, "no %s allowed while running setgid", s
);
2630 verbose_getter(ID id
, VALUE
*ptr
)
2632 return *rb_ruby_verbose_ptr();
2636 verbose_setter(VALUE val
, ID id
, VALUE
*variable
)
2638 *rb_ruby_verbose_ptr() = RTEST(val
) ? Qtrue
: val
;
2642 opt_W_getter(ID id
, VALUE
*dmy
)
2644 VALUE v
= *rb_ruby_verbose_ptr();
2659 debug_getter(ID id
, VALUE
*dmy
)
2661 return *rb_ruby_debug_ptr();
2665 debug_setter(VALUE val
, ID id
, VALUE
*dmy
)
2667 *rb_ruby_debug_ptr() = val
;
2671 ruby_prog_init(void)
2673 rb_define_virtual_variable("$VERBOSE", verbose_getter
, verbose_setter
);
2674 rb_define_virtual_variable("$-v", verbose_getter
, verbose_setter
);
2675 rb_define_virtual_variable("$-w", verbose_getter
, verbose_setter
);
2676 rb_define_virtual_variable("$-W", opt_W_getter
, rb_gvar_readonly_setter
);
2677 rb_define_virtual_variable("$DEBUG", debug_getter
, debug_setter
);
2678 rb_define_virtual_variable("$-d", debug_getter
, debug_setter
);
2680 rb_gvar_ractor_local("$VERBOSE");
2681 rb_gvar_ractor_local("$-v");
2682 rb_gvar_ractor_local("$-w");
2683 rb_gvar_ractor_local("$-W");
2684 rb_gvar_ractor_local("$DEBUG");
2685 rb_gvar_ractor_local("$-d");
2687 rb_define_hooked_variable("$0", &rb_progname
, 0, set_arg0
);
2688 rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname
, 0, set_arg0
);
2690 rb_define_module_function(rb_mProcess
, "argv0", proc_argv0
, 0);
2691 rb_define_module_function(rb_mProcess
, "setproctitle", proc_setproctitle
, 1);
2694 * ARGV contains the command line arguments used to run ruby.
2696 * A library like OptionParser can be used to process command-line
2699 rb_define_global_const("ARGV", rb_argv
);
2703 ruby_set_argv(int argc
, char **argv
)
2709 for (i
= 0; i
< argc
; i
++) {
2710 VALUE arg
= external_str_new_cstr(argv
[i
]);
2713 rb_ary_push(av
, arg
);
2718 ruby_process_options(int argc
, char **argv
)
2720 ruby_cmdline_options_t opt
;
2722 const char *script_name
= (argc
> 0 && argv
[0]) ? argv
[0] : ruby_engine
;
2724 if (!origarg
.argv
|| origarg
.argc
<= 0) {
2725 origarg
.argc
= argc
;
2726 origarg
.argv
= argv
;
2728 ruby_script(script_name
); /* for the time being */
2729 rb_argv0
= rb_str_new4(rb_progname
);
2730 rb_gc_register_mark_object(rb_argv0
);
2731 iseq
= process_options(argc
, argv
, cmdline_options_init(&opt
));
2733 #ifndef HAVE_SETPROCTITLE
2734 ruby_init_setproctitle(argc
, argv
);
2737 return (void*)(struct RData
*)iseq
;
2741 fill_standard_fds(void)
2743 int f0
, f1
, f2
, fds
[2];
2745 f0
= fstat(0, &buf
) == -1 && errno
== EBADF
;
2746 f1
= fstat(1, &buf
) == -1 && errno
== EBADF
;
2747 f2
= fstat(2, &buf
) == -1 && errno
== EBADF
;
2749 if (pipe(fds
) == 0) {
2758 if (pipe(fds
) == 0) {
2760 if (f1
&& fds
[1] != 1)
2762 if (f2
&& fds
[1] != 2)
2764 if (fds
[1] != 1 && fds
[1] != 2)
2771 ruby_sysinit(int *argc
, char ***argv
)
2774 rb_w32_sysinit(argc
, argv
);
2776 if (*argc
>= 0 && *argv
) {
2777 origarg
.argc
= *argc
;
2778 origarg
.argv
= *argv
;
2780 fill_standard_fds();