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/cmdlineopt.h"
51 #include "internal/error.h"
52 #include "internal/file.h"
53 #include "internal/inits.h"
54 #include "internal/io.h"
55 #include "internal/load.h"
56 #include "internal/loadpath.h"
57 #include "internal/missing.h"
58 #include "internal/object.h"
59 #include "internal/parse.h"
60 #include "internal/process.h"
61 #include "internal/variable.h"
62 #include "ruby/encoding.h"
63 #include "ruby/thread.h"
64 #include "ruby/util.h"
65 #include "ruby/version.h"
66 #include "ruby/internal/error.h"
69 # define MAXPATHLEN 1024
72 # define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
75 void Init_ruby_description(void);
81 #ifndef DISABLE_RUBYGEMS
82 # define DISABLE_RUBYGEMS 0
85 #define DEFAULT_RUBYGEMS_ENABLED "disabled"
87 #define DEFAULT_RUBYGEMS_ENABLED "enabled"
90 void rb_warning_category_update(unsigned int mask
, unsigned int bits
);
93 #define FEATURE_BIT(bit) (1U << feature_##bit)
94 #define EACH_FEATURES(X, SEP) \
103 X(frozen_string_literal) \
108 /* END OF FEATURES */
109 #define EACH_DEBUG_FEATURES(X, SEP) \
110 X(frozen_string_literal) \
111 /* END OF DEBUG FEATURES */
112 #define AMBIGUOUS_FEATURE_NAMES 0 /* no ambiguous feature names now */
113 #define DEFINE_FEATURE(bit) feature_##bit
114 #define DEFINE_DEBUG_FEATURE(bit) feature_debug_##bit
115 enum feature_flag_bits
{
116 EACH_FEATURES(DEFINE_FEATURE
, COMMA
),
117 feature_debug_flag_first
,
118 #if defined(MJIT_FORCE_ENABLE) || !YJIT_SUPPORTED_P
119 DEFINE_FEATURE(jit
) = feature_mjit
,
121 DEFINE_FEATURE(jit
) = feature_yjit
,
123 feature_debug_flag_begin
= feature_debug_flag_first
- 1,
124 EACH_DEBUG_FEATURES(DEFINE_DEBUG_FEATURE
, COMMA
),
128 #define DEBUG_BIT(bit) (1U << feature_debug_##bit)
130 #define DUMP_BIT(bit) (1U << dump_##bit)
131 #define DEFINE_DUMP(bit) dump_##bit
132 #define EACH_DUMPS(X, SEP) \
147 X(parsetree_with_comment) \
151 X(insns_without_opt) \
153 enum dump_flag_bits
{
155 EACH_DUMPS(DEFINE_DUMP
, COMMA
),
156 dump_exit_bits
= (DUMP_BIT(yydebug
) | DUMP_BIT(syntax
) |
157 DUMP_BIT(parsetree
) | DUMP_BIT(parsetree_with_comment
) |
158 DUMP_BIT(insns
) | DUMP_BIT(insns_without_opt
))
162 rb_feature_set_to(ruby_features_t
*feat
, unsigned int bit_mask
, unsigned int bit_set
)
164 feat
->mask
|= bit_mask
;
165 feat
->set
= (feat
->set
& ~bit_mask
) | bit_set
;
168 #define FEATURE_SET_TO(feat, bit_mask, bit_set) \
169 rb_feature_set_to(&(feat), bit_mask, bit_set)
170 #define FEATURE_SET(feat, bits) FEATURE_SET_TO(feat, bits, bits)
171 #define FEATURE_SET_RESTORE(feat, save) FEATURE_SET_TO(feat, (save).mask, (save).set & (save).mask)
172 #define FEATURE_SET_P(feat, bits) ((feat).set & (bits))
174 static void init_ids(ruby_cmdline_options_t
*);
176 #define src_encoding_index GET_VM()->src_encoding_index
179 COMPILATION_FEATURES
= (
181 | FEATURE_BIT(frozen_string_literal
)
182 | FEATURE_BIT(debug_frozen_string_literal
)
185 (FEATURE_BIT(debug_flag_first
)-1)
189 & ~FEATURE_BIT(frozen_string_literal
)
195 static ruby_cmdline_options_t
*
196 cmdline_options_init(ruby_cmdline_options_t
*opt
)
198 MEMZERO(opt
, *opt
, 1);
200 opt
->src
.enc
.index
= src_encoding_index
;
201 opt
->ext
.enc
.index
= -1;
202 opt
->intern
.enc
.index
= -1;
203 opt
->features
.set
= DEFAULT_FEATURES
;
204 #ifdef MJIT_FORCE_ENABLE /* to use with: ./configure cppflags="-DMJIT_FORCE_ENABLE" */
205 opt
->features
.set
|= FEATURE_BIT(mjit
);
206 #elif defined(YJIT_FORCE_ENABLE)
207 opt
->features
.set
|= FEATURE_BIT(yjit
);
210 if (getenv("RUBY_YJIT_ENABLE")) {
211 opt
->features
.set
|= FEATURE_BIT(yjit
);
217 static rb_ast_t
*load_file(VALUE parser
, VALUE fname
, VALUE f
, int script
,
218 ruby_cmdline_options_t
*opt
);
219 static VALUE
open_load_file(VALUE fname_v
, int *xflag
);
220 static void forbid_setid(const char *, const ruby_cmdline_options_t
*);
221 #define forbid_setid(s) forbid_setid((s), opt)
228 static const char esc_standout
[] = "\n\033[1;7m";
229 static const char esc_bold
[] = "\033[1m";
230 static const char esc_reset
[] = "\033[0m";
231 static const char esc_none
[] = "";
234 show_usage_line(const char *str
, unsigned int namelen
, unsigned int secondlen
, int help
, int highlight
, unsigned int w
)
236 const char *sb
= highlight
? esc_bold
: esc_none
;
237 const char *se
= highlight
? esc_reset
: esc_none
;
238 const int wrap
= help
&& namelen
+ secondlen
- 1 > w
;
239 printf(" %s%.*s%-*.*s%s%-*s%s\n", sb
, namelen
-1, str
,
240 (wrap
? 0 : w
- namelen
+ 1),
241 (help
? secondlen
-1 : 0), str
+ namelen
, se
,
242 (wrap
? w
+ 3 : 0), (wrap
? "\n" : ""),
243 str
+ namelen
+ secondlen
);
247 usage(const char *name
, int help
, int highlight
, int columns
)
249 /* This message really ought to be max 23 lines.
250 * Removed -h because the user already knows that option. Others? */
252 #define M(shortopt, longopt, desc) RUBY_OPT_MESSAGE(shortopt, longopt, desc)
255 # define PLATFORM_JIT_OPTION "--yjit"
257 # define PLATFORM_JIT_OPTION "--mjit"
259 static const struct ruby_opt_message usage_msg
[] = {
260 M("-0[octal]", "", "specify record separator (\\0, if no argument)"),
261 M("-a", "", "autosplit mode with -n or -p (splits $_ into $F)"),
262 M("-c", "", "check syntax only"),
263 M("-Cdirectory", "", "cd to directory before executing your script"),
264 M("-d", ", --debug", "set debugging flags (set $DEBUG to true)"),
265 M("-e 'command'", "", "one line of script. Several -e's allowed. Omit [programfile]"),
266 M("-Eex[:in]", ", --encoding=ex[:in]", "specify the default external and internal character encodings"),
267 M("-Fpattern", "", "split() pattern for autosplit (-a)"),
268 M("-i[extension]", "", "edit ARGV files in place (make backup if extension supplied)"),
269 M("-Idirectory", "", "specify $LOAD_PATH directory (may be used more than once)"),
270 M("-l", "", "enable line ending processing"),
271 M("-n", "", "assume 'while gets(); ... end' loop around your script"),
272 M("-p", "", "assume loop like -n but print line also like sed"),
273 M("-rlibrary", "", "require the library before executing your script"),
274 M("-s", "", "enable some switch parsing for switches after script name"),
275 M("-S", "", "look for the script using PATH environment variable"),
276 M("-v", "", "print the version number, then turn on verbose mode"),
277 M("-w", "", "turn warnings on for your script"),
278 M("-W[level=2|:category]", "", "set warning level; 0=silence, 1=medium, 2=verbose"),
279 M("-x[directory]", "", "strip off text before #!ruby line and perhaps cd to directory"),
280 M("--jit", "", "enable JIT for the platform, same as " PLATFORM_JIT_OPTION
" (experimental)"),
282 M("--mjit", "", "enable C compiler-based JIT compiler (experimental)"),
285 M("--yjit", "", "enable in-process JIT compiler (experimental)"),
287 M("-h", "", "show this message, --help for more info"),
289 static const struct ruby_opt_message help_msg
[] = {
290 M("--copyright", "", "print the copyright"),
291 M("--dump={insns|parsetree|...}[,...]", "",
292 "dump debug information. see below for available dump list"),
293 M("--enable={jit|rubyopt|...}[,...]", ", --disable={jit|rubyopt|...}[,...]",
294 "enable or disable features. see below for available features"),
295 M("--external-encoding=encoding", ", --internal-encoding=encoding",
296 "specify the default external or internal character encoding"),
297 M("--backtrace-limit=num", "", "limit the maximum length of backtrace"),
298 M("--verbose", "", "turn on verbose mode and disable script from stdin"),
299 M("--version", "", "print the version number, then exit"),
300 M("--help", "", "show this message, -h for short message"),
302 static const struct ruby_opt_message dumps
[] = {
303 M("insns", "", "instruction sequences"),
304 M("insns_without_opt", "", "instruction sequences compiled with no optimization"),
305 M("yydebug", "", "yydebug of yacc parser generator"),
306 M("parsetree", "", "AST"),
307 M("parsetree_with_comment", "", "AST with comments"),
309 static const struct ruby_opt_message features
[] = {
310 M("gems", "", "rubygems (only for debugging, default: "DEFAULT_RUBYGEMS_ENABLED
")"),
311 M("error_highlight", "", "error_highlight (default: "DEFAULT_RUBYGEMS_ENABLED
")"),
312 M("did_you_mean", "", "did_you_mean (default: "DEFAULT_RUBYGEMS_ENABLED
")"),
313 M("rubyopt", "", "RUBYOPT environment variable (default: enabled)"),
314 M("frozen-string-literal", "", "freeze all string literals (default: disabled)"),
316 M("mjit", "", "C compiler-based JIT compiler (default: disabled)"),
319 M("yjit", "", "in-process JIT compiler (default: disabled)"),
322 static const struct ruby_opt_message warn_categories
[] = {
323 M("deprecated", "", "deprecated features"),
324 M("experimental", "", "experimental features"),
327 extern const struct ruby_opt_message mjit_option_messages
[];
330 static const struct ruby_opt_message yjit_options
[] = {
332 M("--yjit-stats", "", "Enable collecting YJIT statistics"),
334 M("--yjit-exec-mem-size=num", "", "Size of executable memory block in MiB (default: 256)"),
335 M("--yjit-call-threshold=num", "", "Number of calls to trigger JIT (default: 10)"),
336 M("--yjit-max-versions=num", "", "Maximum number of versions per basic block (default: 4)"),
337 M("--yjit-greedy-versioning", "", "Greedy versioning mode (default: disabled)"),
341 const char *sb
= highlight
? esc_standout
+1 : esc_none
;
342 const char *se
= highlight
? esc_reset
: esc_none
;
343 const int num
= numberof(usage_msg
) - (help
? 1 : 0);
344 unsigned int w
= (columns
> 80 ? (columns
- 79) / 2 : 0) + 16;
345 #define SHOW(m) show_usage_line((m).str, (m).namelen, (m).secondlen, help, highlight, w)
347 printf("%sUsage:%s %s [switches] [--] [programfile] [arguments]\n", sb
, se
, name
);
348 for (i
= 0; i
< num
; ++i
)
353 if (highlight
) sb
= esc_standout
;
355 for (i
= 0; i
< numberof(help_msg
); ++i
)
357 printf("%s""Dump List:%s\n", sb
, se
);
358 for (i
= 0; i
< numberof(dumps
); ++i
)
360 printf("%s""Features:%s\n", sb
, se
);
361 for (i
= 0; i
< numberof(features
); ++i
)
363 printf("%s""Warning categories:%s\n", sb
, se
);
364 for (i
= 0; i
< numberof(warn_categories
); ++i
)
365 SHOW(warn_categories
[i
]);
367 printf("%s""MJIT options (experimental):%s\n", sb
, se
);
368 for (i
= 0; mjit_option_messages
[i
].str
; ++i
)
369 SHOW(mjit_option_messages
[i
]);
372 printf("%s""YJIT options (experimental):%s\n", sb
, se
);
373 for (i
= 0; i
< numberof(yjit_options
); ++i
)
374 SHOW(yjit_options
[i
]);
378 #define rubylib_path_new rb_str_new
381 push_include(const char *path
, VALUE (*filter
)(VALUE
))
383 const char sep
= PATH_SEP_CHAR
;
385 VALUE load_path
= GET_VM()->load_path
;
392 for (s
= p
; *s
&& *s
!= sep
; s
= CharNext(s
));
393 rb_ary_push(load_path
, (*filter
)(rubylib_path_new(p
, s
- p
)));
400 push_include_cygwin(const char *path
, VALUE (*filter
)(VALUE
))
403 char rubylib
[FILENAME_MAX
];
412 for (s
= p
; *s
&& *s
!= ';'; s
= CharNext(s
));
416 buf
= rb_str_new(p
, len
);
417 p
= RSTRING_PTR(buf
);
420 rb_str_resize(buf
, len
);
421 p
= strncpy(RSTRING_PTR(buf
), p
, len
);
424 #ifdef HAVE_CYGWIN_CONV_PATH
425 #define CONV_TO_POSIX_PATH(p, lib) \
426 cygwin_conv_path(CCP_WIN_A_TO_POSIX|CCP_RELATIVE, (p), (lib), sizeof(lib))
428 # error no cygwin_conv_path
430 if (CONV_TO_POSIX_PATH(p
, rubylib
) == 0)
432 push_include(p
, filter
);
438 #define push_include push_include_cygwin
442 ruby_push_include(const char *path
, VALUE (*filter
)(VALUE
))
446 push_include(path
, filter
);
450 identical_path(VALUE path
)
455 locale_path(VALUE path
)
457 rb_enc_associate(path
, rb_locale_encoding());
462 ruby_incpush(const char *path
)
464 ruby_push_include(path
, locale_path
);
468 expand_include_path(VALUE path
)
470 char *p
= RSTRING_PTR(path
);
473 if (*p
== '.' && p
[1] == '/')
475 return rb_file_expand_path(path
, Qnil
);
479 ruby_incpush_expand(const char *path
)
481 ruby_push_include(path
, expand_include_path
);
485 #if defined _WIN32 || defined __CYGWIN__
486 static HMODULE libruby
;
489 DllMain(HINSTANCE dll
, DWORD reason
, LPVOID reserved
)
491 if (reason
== DLL_PROCESS_ATTACH
)
497 rb_libruby_handle(void)
503 translit_char_bin(char *p
, int from
, int to
)
506 if ((unsigned char)*p
== from
)
521 # define IF_UTF8_PATH(t, f) t
523 # define IF_UTF8_PATH(t, f) f
528 str_conv_enc(VALUE str
, rb_encoding
*from
, rb_encoding
*to
)
530 return rb_str_conv_enc_opts(str
, from
, to
,
531 ECONV_UNDEF_REPLACE
|ECONV_INVALID_REPLACE
,
535 # define str_conv_enc(str, from, to) (str)
538 void ruby_init_loadpath(void);
540 #if defined(LOAD_RELATIVE)
542 runtime_libruby_path(void)
544 #if defined _WIN32 || defined __CYGWIN__
549 len
= RSTRING_EMBED_LEN_MAX
;
552 VALUE wsopath
= rb_str_new(0, len
*sizeof(WCHAR
));
556 while (wlibpath
= (WCHAR
*)RSTRING_PTR(wsopath
),
557 ret
= GetModuleFileNameW(libruby
, wlibpath
, len
),
560 rb_str_modify_expand(wsopath
, len
*sizeof(WCHAR
));
561 rb_str_set_len(wsopath
, (len
+= len
)*sizeof(WCHAR
));
563 if (!ret
|| ret
> len
) rb_fatal("failed to get module file name");
564 #if defined __CYGWIN__
566 const int win_to_posix
= CCP_WIN_W_TO_POSIX
| CCP_RELATIVE
;
567 size_t newsize
= cygwin_conv_path(win_to_posix
, wlibpath
, 0, 0);
568 if (!newsize
) rb_fatal("failed to convert module path to cygwin");
569 path
= rb_str_new(0, newsize
);
570 libpath
= RSTRING_PTR(path
);
571 if (cygwin_conv_path(win_to_posix
, wlibpath
, libpath
, newsize
)) {
572 rb_str_resize(path
, 0);
578 for (len
= ret
, i
= 0; i
< len
; ++i
) {
579 if (wlibpath
[i
] == L
'\\') {
581 ret
= i
+1; /* chop after the last separator */
585 len
= WideCharToMultiByte(CP_UTF8
, 0, wlibpath
, ret
, NULL
, 0, NULL
, NULL
);
586 path
= rb_utf8_str_new(0, len
);
587 libpath
= RSTRING_PTR(path
);
588 WideCharToMultiByte(CP_UTF8
, 0, wlibpath
, ret
, libpath
, len
, NULL
, NULL
);
590 rb_str_resize(wsopath
, 0);
592 #elif defined(HAVE_DLADDR)
595 const void* addr
= (void *)(VALUE
)expand_include_path
;
597 if (!dladdr((void *)addr
, &dli
)) {
598 return rb_str_new(0, 0);
601 else if (origarg
.argc
> 0 && origarg
.argv
&& dli
.dli_fname
== origarg
.argv
[0]) {
602 fname
= rb_str_new_cstr("/proc/self/exe");
603 path
= rb_readlink(fname
, NULL
);
607 fname
= rb_str_new_cstr(dli
.dli_fname
);
608 path
= rb_realpath_internal(Qnil
, fname
, 1);
610 rb_str_resize(fname
, 0);
613 # error relative load path is not supported on this platform.
618 #define INITIAL_LOAD_PATH_MARK rb_intern_const("@gem_prelude_index")
620 VALUE ruby_archlibdir_path
, ruby_prefix_path
;
623 ruby_init_loadpath(void)
625 VALUE load_path
, archlibdir
= 0;
626 ID id_initial_load_path_mark
;
627 const char *paths
= ruby_initial_load_paths
;
628 #if defined LOAD_RELATIVE
629 #if !defined ENABLE_MULTIARCH
630 # define RUBY_ARCH_PATH ""
631 #elif defined RUBY_ARCH
632 # define RUBY_ARCH_PATH "/"RUBY_ARCH
634 # define RUBY_ARCH_PATH "/"RUBY_PLATFORM
641 sopath
= runtime_libruby_path();
642 libpath
= RSTRING_PTR(sopath
);
644 p
= strrchr(libpath
, '/');
646 static const char libdir
[] = "/"
647 #ifdef LIBDIR_BASENAME
653 const ptrdiff_t libdir_len
= (ptrdiff_t)sizeof(libdir
)
654 - rb_strlen_lit(RUBY_ARCH_PATH
) - 1;
655 static const char bindir
[] = "/bin";
656 const ptrdiff_t bindir_len
= (ptrdiff_t)sizeof(bindir
) - 1;
658 const char *p2
= NULL
;
660 #ifdef ENABLE_MULTIARCH
663 if (p
- libpath
>= bindir_len
&& !STRNCASECMP(p
- bindir_len
, bindir
, bindir_len
)) {
665 archlibdir
= rb_str_subseq(sopath
, 0, p
- libpath
);
666 rb_str_cat_cstr(archlibdir
, libdir
);
667 OBJ_FREEZE_RAW(archlibdir
);
669 else if (p
- libpath
>= libdir_len
&& !strncmp(p
- libdir_len
, libdir
, libdir_len
)) {
670 archlibdir
= rb_str_subseq(sopath
, 0, (p2
? p2
: p
) - libpath
);
671 OBJ_FREEZE_RAW(archlibdir
);
674 #ifdef ENABLE_MULTIARCH
680 p
= rb_enc_path_last_separator(libpath
, p
, rb_ascii8bit_encoding());
681 if (p
) goto multiarch
;
685 baselen
= p
- libpath
;
690 rb_str_resize(sopath
, baselen
);
691 libpath
= RSTRING_PTR(sopath
);
692 #define PREFIX_PATH() sopath
693 #define BASEPATH() rb_str_buf_cat(rb_str_buf_new(baselen+len), libpath, baselen)
694 #define RUBY_RELATIVE(path, len) rb_str_buf_cat(BASEPATH(), (path), (len))
696 const size_t exec_prefix_len
= strlen(ruby_exec_prefix
);
697 #define RUBY_RELATIVE(path, len) rubylib_path_new((path), (len))
698 #define PREFIX_PATH() RUBY_RELATIVE(ruby_exec_prefix, exec_prefix_len)
700 rb_gc_register_address(&ruby_prefix_path
);
701 ruby_prefix_path
= PREFIX_PATH();
702 OBJ_FREEZE_RAW(ruby_prefix_path
);
703 if (!archlibdir
) archlibdir
= ruby_prefix_path
;
704 rb_gc_register_address(&ruby_archlibdir_path
);
705 ruby_archlibdir_path
= archlibdir
;
707 load_path
= GET_VM()->load_path
;
709 ruby_push_include(getenv("RUBYLIB"), identical_path
);
711 id_initial_load_path_mark
= INITIAL_LOAD_PATH_MARK
;
713 size_t len
= strlen(paths
);
714 VALUE path
= RUBY_RELATIVE(paths
, len
);
715 rb_ivar_set(path
, id_initial_load_path_mark
, path
);
716 rb_ary_push(load_path
, path
);
720 rb_const_set(rb_cObject
, rb_intern_const("TMP_RUBY_PREFIX"), ruby_prefix_path
);
725 add_modules(VALUE
*req_list
, const char *mod
)
727 VALUE list
= *req_list
;
731 *req_list
= list
= rb_ary_tmp_new(0);
733 feature
= rb_str_cat_cstr(rb_str_tmp_new(0), mod
);
734 rb_ary_push(list
, feature
);
738 require_libraries(VALUE
*req_list
)
740 VALUE list
= *req_list
;
741 VALUE self
= rb_vm_top_self();
743 rb_encoding
*extenc
= rb_default_external_encoding();
745 CONST_ID(require
, "require");
746 while (list
&& RARRAY_LEN(list
) > 0) {
747 VALUE feature
= rb_ary_shift(list
);
748 rb_enc_associate(feature
, extenc
);
749 RBASIC_SET_CLASS_RAW(feature
, rb_cString
);
751 rb_funcallv(self
, require
, 1, &feature
);
756 static const struct rb_block
*
757 toplevel_context(rb_binding_t
*bind
)
763 process_sflag(int *sflag
)
768 VALUE argv
= rb_argv
;
770 n
= RARRAY_LEN(argv
);
771 args
= RARRAY_CONST_PTR(argv
);
774 char *s
= StringValuePtr(v
);
781 if (s
[1] == '-' && s
[2] == '\0')
785 /* check if valid name before replacing - with _ */
786 for (p
= s
+ 1; *p
; p
++) {
795 else if (*p
!= '_' && !ISALNUM(*p
)) {
798 rb_str_new2("invalid name for global variable - ");
799 if (!(p
= strchr(p
, '='))) {
800 rb_str_cat2(name_error
[0], s
);
803 rb_str_cat(name_error
[0], s
, p
- s
);
805 name_error
[1] = args
[-1];
806 rb_exc_raise(rb_class_new_instance(2, name_error
, rb_eNameError
));
811 for (p
= s
+ 1; *p
; ++p
) {
818 n
= RARRAY_LEN(argv
) - n
;
826 static long proc_options(long argc
, char **argv
, ruby_cmdline_options_t
*opt
, int envopt
);
829 moreswitches(const char *s
, ruby_cmdline_options_t
*opt
, int envopt
)
834 VALUE argstr
, argary
;
837 while (ISSPACE(*s
)) s
++;
839 argstr
= rb_str_tmp_new((len
= strlen(s
)) + (envopt
!=0));
840 argary
= rb_str_tmp_new(0);
842 p
= RSTRING_PTR(argstr
);
843 if (envopt
) *p
++ = ' ';
844 memcpy(p
, s
, len
+ 1);
846 rb_str_cat(argary
, (char *)&ap
, sizeof(ap
));
849 rb_str_cat(argary
, (char *)&ap
, sizeof(ap
));
850 while (*p
&& !ISSPACE(*p
)) ++p
;
853 while (ISSPACE(*p
)) ++p
;
855 argc
= RSTRING_LEN(argary
) / sizeof(ap
);
857 rb_str_cat(argary
, (char *)&ap
, sizeof(ap
));
858 argv
= ptr
= ALLOC_N(char *, argc
);
859 MEMMOVE(argv
, RSTRING_PTR(argary
), char *, argc
);
861 while ((i
= proc_options(argc
, argv
, opt
, envopt
)) > 1 && envopt
&& (argc
-= i
) > 0) {
874 rb_str_resize(argary
, 0);
875 rb_str_resize(argstr
, 0);
879 name_match_p(const char *name
, const char *str
, size_t len
)
881 if (len
== 0) return 0;
883 while (TOLOWER(*str
) == *name
) {
884 if (!--len
|| !*++str
) return 1;
887 if (*str
!= '-' && *str
!= '_') return 0;
888 while (ISALNUM(*name
)) name
++;
889 if (*name
!= '-' && *name
!= '_') return 0;
895 #define NAME_MATCH_P(name, str, len) \
896 ((len) < (int)sizeof(name) && name_match_p((name), (str), (len)))
898 #define UNSET_WHEN(name, bit, str, len) \
899 if (NAME_MATCH_P((name), (str), (len))) { \
900 *(unsigned int *)arg &= ~(bit); \
904 #define SET_WHEN(name, bit, str, len) \
905 if (NAME_MATCH_P((name), (str), (len))) { \
906 *(unsigned int *)arg |= (bit); \
910 #define LITERAL_NAME_ELEMENT(name) #name
913 feature_option(const char *str
, int len
, void *arg
, const unsigned int enable
)
915 static const char list
[] = EACH_FEATURES(LITERAL_NAME_ELEMENT
, ", ");
916 ruby_features_t
*argp
= arg
;
917 unsigned int mask
= ~0U;
918 unsigned int set
= 0U;
919 #if AMBIGUOUS_FEATURE_NAMES
921 # define FEATURE_FOUND ++matched
923 # define FEATURE_FOUND goto found
925 #define SET_FEATURE(bit) \
926 if (NAME_MATCH_P(#bit, str, len)) {set |= mask = FEATURE_BIT(bit); FEATURE_FOUND;}
927 EACH_FEATURES(SET_FEATURE
, ;);
928 if (NAME_MATCH_P("jit", str
, len
)) { // This allows you to cancel --jit
929 set
|= mask
= FEATURE_BIT(jit
);
932 if (NAME_MATCH_P("all", str
, len
)) {
933 // YJIT and MJIT cannot be enabled at the same time. We enable only one for --enable=all.
934 mask
&= ~(FEATURE_BIT(yjit
) | FEATURE_BIT(mjit
)) | FEATURE_BIT(jit
);
937 #if AMBIGUOUS_FEATURE_NAMES
938 if (matched
== 1) goto found
;
940 VALUE mesg
= rb_sprintf("ambiguous feature: `%.*s' (", len
, str
);
941 #define ADD_FEATURE_NAME(bit) \
942 if (FEATURE_BIT(bit) & set) { \
943 rb_str_cat_cstr(mesg, #bit); \
944 if (--matched) rb_str_cat_cstr(mesg, ", "); \
946 EACH_FEATURES(ADD_FEATURE_NAME
, ;);
947 rb_str_cat_cstr(mesg
, ")");
948 rb_exc_raise(rb_exc_new_str(rb_eRuntimeError
, mesg
));
949 #undef ADD_FEATURE_NAME
954 rb_warn("unknown argument for --%s: `%.*s'",
955 enable
? "enable" : "disable", len
, str
);
956 rb_warn("features are [%.*s].", (int)strlen(list
), list
);
960 FEATURE_SET_TO(*argp
, mask
, (mask
& enable
));
965 enable_option(const char *str
, int len
, void *arg
)
967 feature_option(str
, len
, arg
, ~0U);
971 disable_option(const char *str
, int len
, void *arg
)
973 feature_option(str
, len
, arg
, 0U);
976 RUBY_EXTERN
const int ruby_patchlevel
;
977 int ruby_env_debug_option(const char *str
, int len
, void *arg
);
980 debug_option(const char *str
, int len
, void *arg
)
982 static const char list
[] = EACH_DEBUG_FEATURES(LITERAL_NAME_ELEMENT
, ", ");
983 ruby_features_t
*argp
= arg
;
984 #define SET_WHEN_DEBUG(bit) \
985 if (NAME_MATCH_P(#bit, str, len)) { \
986 FEATURE_SET(*argp, DEBUG_BIT(bit)); \
989 EACH_DEBUG_FEATURES(SET_WHEN_DEBUG
, ;);
991 if (ruby_patchlevel
< 0 && ruby_env_debug_option(str
, len
, 0)) return;
993 rb_warn("unknown argument for --debug: `%.*s'", len
, str
);
994 rb_warn("debug features are [%.*s].", (int)strlen(list
), list
);
998 dump_option(const char *str
, int len
, void *arg
)
1000 static const char list
[] = EACH_DUMPS(LITERAL_NAME_ELEMENT
, ", ");
1001 #define SET_WHEN_DUMP(bit) SET_WHEN(#bit, DUMP_BIT(bit), str, len)
1002 EACH_DUMPS(SET_WHEN_DUMP
, ;);
1003 rb_warn("don't know how to dump `%.*s',", len
, str
);
1004 rb_warn("but only [%.*s].", (int)strlen(list
), list
);
1008 set_option_encoding_once(const char *type
, VALUE
*name
, const char *e
, long elen
)
1012 if (!elen
) elen
= strlen(e
);
1013 ename
= rb_str_new(e
, elen
);
1016 rb_funcall(ename
, rb_intern("casecmp"), 1, *name
) != INT2FIX(0)) {
1017 rb_raise(rb_eRuntimeError
,
1018 "%s already set to %"PRIsVALUE
, type
, *name
);
1023 #define set_internal_encoding_once(opt, e, elen) \
1024 set_option_encoding_once("default_internal", &(opt)->intern.enc.name, (e), (elen))
1025 #define set_external_encoding_once(opt, e, elen) \
1026 set_option_encoding_once("default_external", &(opt)->ext.enc.name, (e), (elen))
1027 #define set_source_encoding_once(opt, e, elen) \
1028 set_option_encoding_once("source", &(opt)->src.enc.name, (e), (elen))
1030 #define yjit_opt_match_noarg(s, l, name) \
1031 opt_match(s, l, name) && (*(s) ? (rb_warn("argument to --yjit-" name " is ignored"), 1) : 1)
1032 #define yjit_opt_match_arg(s, l, name) \
1033 opt_match(s, l, name) && (*(s) && *(s+1) ? 1 : (rb_raise(rb_eRuntimeError, "--yjit-" name " needs an argument"), 0))
1035 #if YJIT_SUPPORTED_P
1037 setup_yjit_options(const char *s
, struct rb_yjit_options
*yjit_opt
)
1039 const size_t l
= strlen(s
);
1043 else if (yjit_opt_match_arg(s
, l
, "exec-mem-size")) {
1044 yjit_opt
->exec_mem_size
= atoi(s
+ 1);
1046 else if (yjit_opt_match_arg(s
, l
, "call-threshold")) {
1047 yjit_opt
->call_threshold
= atoi(s
+ 1);
1049 else if (yjit_opt_match_arg(s
, l
, "max-versions")) {
1050 yjit_opt
->max_versions
= atoi(s
+ 1);
1052 else if (yjit_opt_match_noarg(s
, l
, "greedy-versioning")) {
1053 yjit_opt
->greedy_versioning
= true;
1055 else if (yjit_opt_match_noarg(s
, l
, "no-type-prop")) {
1056 yjit_opt
->no_type_prop
= true;
1058 else if (yjit_opt_match_noarg(s
, l
, "stats")) {
1059 yjit_opt
->gen_stats
= true;
1062 rb_raise(rb_eRuntimeError
,
1063 "invalid yjit option `%s' (--help will show valid yjit options)", s
);
1069 proc_options(long argc
, char **argv
, ruby_cmdline_options_t
*opt
, int envopt
)
1071 long n
, argc0
= argc
;
1073 int warning
= opt
->warning
;
1075 if (argc
<= 0 || !argv
)
1078 for (argc
--, argv
++; argc
> 0; argc
--, argv
++) {
1079 const char *const arg
= argv
[0];
1080 if (!arg
|| arg
[0] != '-' || !arg
[1])
1087 if (envopt
) goto noenvopt
;
1088 opt
->do_split
= TRUE
;
1093 if (envopt
) goto noenvopt
;
1094 opt
->do_print
= TRUE
;
1097 if (envopt
) goto noenvopt
;
1098 opt
->do_loop
= TRUE
;
1104 ruby_verbose
= Qtrue
;
1109 if (envopt
) goto noenvopt
;
1110 opt
->dump
|= DUMP_BIT(yydebug
);
1119 opt
->dump
|= DUMP_BIT(version_v
);
1122 if (!opt
->warning
) {
1124 ruby_verbose
= Qtrue
;
1126 FEATURE_SET(opt
->warn
, RB_WARN_CATEGORY_ALL_BITS
);
1132 unsigned int bits
= 0;
1133 static const char no_prefix
[] = "no-";
1134 int enable
= strncmp(s
+= 2, no_prefix
, sizeof(no_prefix
)-1) != 0;
1135 if (!enable
) s
+= sizeof(no_prefix
)-1;
1136 size_t len
= strlen(s
);
1137 if (NAME_MATCH_P("deprecated", s
, len
)) {
1138 bits
= 1U << RB_WARN_CATEGORY_DEPRECATED
;
1140 else if (NAME_MATCH_P("experimental", s
, len
)) {
1141 bits
= 1U << RB_WARN_CATEGORY_EXPERIMENTAL
;
1144 rb_warn("unknown warning category: `%s'", s
);
1146 if (bits
) FEATURE_SET_TO(opt
->warn
, bits
, enable
? bits
: 0);
1151 int v
= 2; /* -W as -W2 */
1154 v
= scan_oct(s
, 1, &numlen
);
1159 if (!opt
->warning
) {
1162 ruby_verbose
= Qnil
;
1165 ruby_verbose
= Qfalse
;
1168 ruby_verbose
= Qtrue
;
1175 FEATURE_SET_TO(opt
->warn
, RB_WARN_CATEGORY_ALL_BITS
, 0);
1178 FEATURE_SET_TO(opt
->warn
, 1U << RB_WARN_CATEGORY_DEPRECATED
, 0);
1181 FEATURE_SET(opt
->warn
, RB_WARN_CATEGORY_ALL_BITS
);
1188 if (envopt
) goto noenvopt
;
1189 opt
->dump
|= DUMP_BIT(syntax
);
1194 if (envopt
) goto noenvopt
;
1196 if (!opt
->sflag
) opt
->sflag
= 1;
1201 if (envopt
) goto noenvopt
;
1202 opt
->dump
|= DUMP_BIT(usage
);
1206 if (envopt
) goto noenvopt
;
1207 opt
->do_line
= TRUE
;
1208 rb_output_rs
= rb_rs
;
1213 if (envopt
) goto noenvopt
;
1215 opt
->do_search
= TRUE
;
1220 if (envopt
) goto noenvopt
;
1224 rb_raise(rb_eRuntimeError
, "no code specified for -e");
1227 if (!opt
->e_script
) {
1228 opt
->e_script
= rb_str_new(0, 0);
1229 if (opt
->script
== 0)
1232 rb_str_cat2(opt
->e_script
, s
);
1233 rb_str_cat2(opt
->e_script
, "\n");
1239 add_modules(&opt
->req_list
, s
);
1241 else if (argc
> 1) {
1242 add_modules(&opt
->req_list
, argv
[1]);
1248 if (envopt
) goto noenvopt
;
1250 ruby_set_inplace_mode(s
+ 1);
1254 if (envopt
) goto noenvopt
;
1258 if (*s
&& chdir(s
) < 0) {
1259 rb_fatal("Can't chdir to %s", s
);
1265 if (envopt
) goto noenvopt
;
1266 if (!*++s
&& (!--argc
|| !(s
= *++argv
) || !*s
)) {
1267 rb_fatal("Can't chdir");
1270 rb_fatal("Can't chdir to %s", s
);
1275 if (envopt
) goto noenvopt
;
1277 rb_fs
= rb_reg_new(s
, strlen(s
), 0);
1282 if (!*++s
&& (!--argc
|| !(s
= *++argv
))) {
1283 rb_raise(rb_eRuntimeError
, "missing argument for -E");
1288 set_internal_encoding_once(opt
, "UTF-8", 0);
1294 const char *enc_name
= 0;
1297 enc_name
= "EUC-JP";
1300 enc_name
= "Windows-31J";
1305 case 'N': case 'n': case 'A': case 'a':
1306 enc_name
= "ASCII-8BIT";
1310 opt
->src
.enc
.name
= rb_str_new2(enc_name
);
1311 if (!opt
->ext
.enc
.name
)
1312 opt
->ext
.enc
.name
= opt
->src
.enc
.name
;
1321 ruby_incpush_expand(s
);
1322 else if (argc
> 1) {
1323 ruby_incpush_expand(argv
[1]);
1329 if (envopt
) goto noenvopt
;
1335 v
= scan_oct(s
, 4, &numlen
);
1339 else if (v
== 0 && numlen
>= 2) {
1340 rb_rs
= rb_str_new2("");
1344 rb_rs
= rb_str_new(&c
, 1);
1350 if (!s
[1] || (s
[1] == '\r' && !s
[2])) {
1356 # define is_option_end(c, allow_hyphen) \
1357 (!(c) || ((allow_hyphen) && (c) == '-') || (c) == '=')
1358 # define check_envopt(name, allow_envopt) \
1359 (((allow_envopt) || !envopt) ? (void)0 : \
1360 rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --" name))
1361 # define need_argument(name, s, needs_arg, next_arg) \
1362 ((*(s) ? !*++(s) : (next_arg) && (!argc || !((s) = argv[1]) || (--argc, ++argv, 0))) && (needs_arg) ? \
1363 rb_raise(rb_eRuntimeError, "missing argument for --" name) \
1365 # define is_option_with_arg(name, allow_hyphen, allow_envopt) \
1366 is_option_with_optarg(name, allow_hyphen, allow_envopt, Qtrue, Qtrue)
1367 # define is_option_with_optarg(name, allow_hyphen, allow_envopt, needs_arg, next_arg) \
1368 (strncmp((name), s, n = sizeof(name) - 1) == 0 && is_option_end(s[n], (allow_hyphen)) && \
1369 (s[n] != '-' || s[n+1]) ? \
1370 (check_envopt(name, (allow_envopt)), s += n, \
1371 need_argument(name, s, needs_arg, next_arg), 1) : 0)
1373 if (strcmp("copyright", s
) == 0) {
1374 if (envopt
) goto noenvopt_long
;
1375 opt
->dump
|= DUMP_BIT(copyright
);
1377 else if (is_option_with_optarg("debug", Qtrue
, Qtrue
, Qfalse
, Qfalse
)) {
1379 ruby_each_words(s
, debug_option
, &opt
->features
);
1383 ruby_verbose
= Qtrue
;
1386 else if (is_option_with_arg("enable", Qtrue
, Qtrue
)) {
1387 ruby_each_words(s
, enable_option
, &opt
->features
);
1389 else if (is_option_with_arg("disable", Qtrue
, Qtrue
)) {
1390 ruby_each_words(s
, disable_option
, &opt
->features
);
1392 else if (is_option_with_arg("encoding", Qfalse
, Qtrue
)) {
1396 # define set_encoding_part(type) \
1397 if (!(p = strchr(s, ':'))) { \
1398 set_##type##_encoding_once(opt, s, 0); \
1402 set_##type##_encoding_once(opt, s, p-s); \
1404 set_encoding_part(external
);
1405 if (!*(s
= ++p
)) break;
1406 set_encoding_part(internal
);
1407 if (!*(s
= ++p
)) break;
1408 #if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
1409 set_encoding_part(source
);
1410 if (!*(s
= ++p
)) break;
1412 rb_raise(rb_eRuntimeError
, "extra argument for %s: %s",
1413 (arg
[1] == '-' ? "--encoding" : "-E"), s
);
1414 # undef set_encoding_part
1417 else if (is_option_with_arg("internal-encoding", Qfalse
, Qtrue
)) {
1418 set_internal_encoding_once(opt
, s
, 0);
1420 else if (is_option_with_arg("external-encoding", Qfalse
, Qtrue
)) {
1421 set_external_encoding_once(opt
, s
, 0);
1423 #if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
1424 else if (is_option_with_arg("source-encoding", Qfalse
, Qtrue
)) {
1425 set_source_encoding_once(opt
, s
, 0);
1428 else if (strcmp("version", s
) == 0) {
1429 if (envopt
) goto noenvopt_long
;
1430 opt
->dump
|= DUMP_BIT(version
);
1432 else if (strcmp("verbose", s
) == 0) {
1434 ruby_verbose
= Qtrue
;
1436 else if (strcmp("jit", s
) == 0) {
1438 rb_warn("Ruby was built without JIT support");
1440 FEATURE_SET(opt
->features
, FEATURE_BIT(jit
));
1443 else if (is_option_with_optarg("mjit", '-', true, false, false)) {
1445 extern void mjit_setup_options(const char *s
, struct mjit_options
*mjit_opt
);
1446 FEATURE_SET(opt
->features
, FEATURE_BIT(mjit
));
1447 mjit_setup_options(s
, &opt
->mjit
);
1449 rb_warn("MJIT support is disabled.");
1452 else if (is_option_with_optarg("yjit", '-', true, false, false)) {
1453 #if YJIT_SUPPORTED_P
1454 FEATURE_SET(opt
->features
, FEATURE_BIT(yjit
));
1455 setup_yjit_options(s
, &opt
->yjit
);
1457 rb_warn("Ruby was built without JIT support");
1460 else if (strcmp("yydebug", s
) == 0) {
1461 if (envopt
) goto noenvopt_long
;
1462 opt
->dump
|= DUMP_BIT(yydebug
);
1464 else if (is_option_with_arg("dump", Qfalse
, Qfalse
)) {
1465 ruby_each_words(s
, dump_option
, &opt
->dump
);
1467 else if (strcmp("help", s
) == 0) {
1468 if (envopt
) goto noenvopt_long
;
1469 opt
->dump
|= DUMP_BIT(help
);
1472 else if (is_option_with_arg("backtrace-limit", Qfalse
, Qfalse
)) {
1474 long n
= strtol(s
, &e
, 10);
1475 if (errno
== ERANGE
|| n
< 0 || *e
) rb_raise(rb_eRuntimeError
, "wrong limit for backtrace length");
1476 rb_backtrace_length_limit
= n
;
1479 rb_raise(rb_eRuntimeError
,
1480 "invalid option --%s (-h will show valid options)", s
);
1490 rb_raise(rb_eRuntimeError
,
1491 "invalid option -%c (-h will show valid options)",
1492 (int)(unsigned char)*s
);
1497 /* "EIdvwWrKU" only */
1498 rb_raise(rb_eRuntimeError
, "invalid switch in RUBYOPT: -%c", *s
);
1502 rb_raise(rb_eRuntimeError
, "invalid switch in RUBYOPT: --%s", s
);
1507 # undef is_option_end
1508 # undef check_envopt
1509 # undef need_argument
1510 # undef is_option_with_arg
1511 # undef is_option_with_optarg
1516 if (warning
) opt
->warning
= warning
;
1517 return argc0
- argc
;
1520 void Init_builtin_features(void);
1523 ruby_init_prelude(void)
1525 Init_builtin_features();
1526 rb_const_remove(rb_cObject
, rb_intern_const("TMP_RUBY_PREFIX"));
1529 void rb_call_builtin_inits(void);
1532 ruby_opt_init(ruby_cmdline_options_t
*opt
)
1534 if (opt
->dump
& dump_exit_bits
) return;
1536 if (opt
->features
.set
& FEATURE_BIT(gems
)) {
1537 rb_define_module("Gem");
1538 if (opt
->features
.set
& FEATURE_BIT(error_highlight
)) {
1539 rb_define_module("ErrorHighlight");
1541 if (opt
->features
.set
& FEATURE_BIT(did_you_mean
)) {
1542 rb_define_module("DidYouMean");
1546 rb_warning_category_update(opt
->warn
.mask
, opt
->warn
.set
);
1548 Init_ext(); /* load statically linked extensions before rubygems */
1549 rb_call_builtin_inits();
1550 ruby_init_prelude();
1552 ruby_set_script_name(opt
->script_name
);
1553 require_libraries(&opt
->req_list
);
1557 opt_enc_index(VALUE enc_name
)
1559 const char *s
= RSTRING_PTR(enc_name
);
1560 int i
= rb_enc_find_index(s
);
1563 rb_raise(rb_eRuntimeError
, "unknown encoding name - %s", s
);
1565 else if (rb_enc_dummy_p(rb_enc_from_index(i
))) {
1566 rb_raise(rb_eRuntimeError
, "dummy encoding is not acceptable - %s ", s
);
1571 #define rb_progname (GET_VM()->progname)
1572 #define rb_orig_progname (GET_VM()->orig_progname)
1577 false_value(ID _x
, VALUE
*_y
)
1583 true_value(ID _x
, VALUE
*_y
)
1588 #define rb_define_readonly_boolean(name, val) \
1589 rb_define_virtual_variable((name), (val) ? true_value : false_value, 0)
1596 line
= rb_lastline_get();
1597 if (!RB_TYPE_P(line
, T_STRING
)) {
1598 rb_raise(rb_eTypeError
, "$_ value need to be String (%s given)",
1599 NIL_P(line
) ? "nil" : rb_obj_classname(line
));
1606 * sub(pattern, replacement) -> $_
1607 * sub(pattern) {|...| block } -> $_
1609 * Equivalent to <code>$_.sub(<i>args</i>)</code>, except that
1610 * <code>$_</code> will be updated if substitution occurs.
1611 * Available only when -p/-n command line option specified.
1615 rb_f_sub(int argc
, VALUE
*argv
, VALUE _
)
1617 VALUE str
= rb_funcall_passing_block(uscore_get(), rb_intern("sub"), argc
, argv
);
1618 rb_lastline_set(str
);
1624 * gsub(pattern, replacement) -> $_
1625 * gsub(pattern) {|...| block } -> $_
1627 * Equivalent to <code>$_.gsub...</code>, except that <code>$_</code>
1628 * will be updated if substitution occurs.
1629 * Available only when -p/-n command line option specified.
1634 rb_f_gsub(int argc
, VALUE
*argv
, VALUE _
)
1636 VALUE str
= rb_funcall_passing_block(uscore_get(), rb_intern("gsub"), argc
, argv
);
1637 rb_lastline_set(str
);
1645 * Equivalent to <code>($_.dup).chop!</code>, except <code>nil</code>
1646 * is never returned. See String#chop!.
1647 * Available only when -p/-n command line option specified.
1654 VALUE str
= rb_funcall_passing_block(uscore_get(), rb_intern("chop"), 0, 0);
1655 rb_lastline_set(str
);
1663 * chomp(string) -> $_
1665 * Equivalent to <code>$_ = $_.chomp(<em>string</em>)</code>. See
1667 * Available only when -p/-n command line option specified.
1672 rb_f_chomp(int argc
, VALUE
*argv
, VALUE _
)
1674 VALUE str
= rb_funcall_passing_block(uscore_get(), rb_intern("chomp"), argc
, argv
);
1675 rb_lastline_set(str
);
1680 setup_pager_env(void)
1682 if (!getenv("LESS")) ruby_setenv("LESS", "-R"); // Output "raw" control characters.
1689 HANDLE h
= GetStdHandle(STD_OUTPUT_HANDLE
);
1691 if (!GetConsoleMode(h
, &m
)) return 0;
1692 # ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
1693 # define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4
1695 if (!(m
& ENABLE_VIRTUAL_TERMINAL_PROCESSING
)) return 0;
1698 #elif !defined(HAVE_WORKING_FORK)
1699 # define tty_enabled() 0
1703 copy_str(VALUE str
, rb_encoding
*enc
, bool intern
)
1706 if (rb_enc_str_coderange_scan(str
, enc
) == ENC_CODERANGE_BROKEN
)
1708 return rb_enc_associate(rb_str_dup(str
), enc
);
1710 return rb_enc_interned_str(RSTRING_PTR(str
), RSTRING_LEN(str
), enc
);
1714 process_options(int argc
, char **argv
, ruby_cmdline_options_t
*opt
)
1719 const rb_iseq_t
*iseq
;
1720 rb_encoding
*enc
, *lenc
;
1722 rb_encoding
*ienc
= 0;
1723 rb_encoding
*const uenc
= rb_utf8_encoding();
1726 char fbuf
[MAXPATHLEN
];
1727 int i
= (int)proc_options(argc
, argv
, opt
, 0);
1728 unsigned int dump
= opt
->dump
& dump_exit_bits
;
1729 rb_vm_t
*vm
= GET_VM();
1730 const long loaded_before_enc
= RARRAY_LEN(vm
->loaded_features
);
1732 if (opt
->dump
& (DUMP_BIT(usage
)|DUMP_BIT(help
))) {
1733 int tty
= isatty(1);
1734 const char *const progname
=
1735 (argc
> 0 && argv
&& argv
[0] ? argv
[0] :
1736 origarg
.argc
> 0 && origarg
.argv
&& origarg
.argv
[0] ? origarg
.argv
[0] :
1739 if ((opt
->dump
& DUMP_BIT(help
)) && tty
) {
1740 const char *pager_env
= getenv("RUBY_PAGER");
1741 if (!pager_env
) pager_env
= getenv("PAGER");
1742 if (pager_env
&& *pager_env
&& isatty(0)) {
1743 const char *columns_env
= getenv("COLUMNS");
1744 if (columns_env
) columns
= atoi(columns_env
);
1745 VALUE pager
= rb_str_new_cstr(pager_env
);
1746 #ifdef HAVE_WORKING_FORK
1748 if (rb_pipe(fds
) == 0) {
1749 rb_pid_t pid
= rb_fork();
1751 /* exec PAGER with reading from child */
1754 else if (pid
== 0) {
1755 /* send the help message to the parent PAGER */
1763 rb_f_exec(1, &pager
);
1765 rb_waitpid(pid
, 0, 0);
1770 VALUE port
= rb_io_popen(pager
, rb_str_new_lit("w"), Qnil
, Qnil
);
1772 int oldout
= dup(1);
1773 int olderr
= dup(2);
1774 int fd
= RFILE(port
)->fptr
->fd
;
1775 tty
= tty_enabled();
1778 usage(progname
, 1, tty
, columns
);
1788 usage(progname
, (opt
->dump
& DUMP_BIT(help
)), tty
, columns
);
1795 if ((opt
->features
.set
& FEATURE_BIT(rubyopt
)) && (s
= getenv("RUBYOPT"))) {
1796 VALUE src_enc_name
= opt
->src
.enc
.name
;
1797 VALUE ext_enc_name
= opt
->ext
.enc
.name
;
1798 VALUE int_enc_name
= opt
->intern
.enc
.name
;
1799 ruby_features_t feat
= opt
->features
;
1800 ruby_features_t warn
= opt
->warn
;
1802 opt
->src
.enc
.name
= opt
->ext
.enc
.name
= opt
->intern
.enc
.name
= 0;
1803 moreswitches(s
, opt
, 1);
1805 opt
->src
.enc
.name
= src_enc_name
;
1807 opt
->ext
.enc
.name
= ext_enc_name
;
1809 opt
->intern
.enc
.name
= int_enc_name
;
1810 FEATURE_SET_RESTORE(opt
->features
, feat
);
1811 FEATURE_SET_RESTORE(opt
->warn
, warn
);
1814 if (opt
->src
.enc
.name
)
1815 /* cannot set deprecated category, as enabling deprecation warnings based on flags
1816 * has not happened yet.
1818 rb_warning("-K is specified; it is for 1.8 compatibility and may cause odd behavior");
1821 if (opt
->features
.set
& FEATURE_BIT(mjit
)) {
1822 opt
->mjit
.on
= TRUE
; /* set mjit.on for ruby_show_version() API and check to call mjit_init() */
1825 if (opt
->features
.set
& FEATURE_BIT(yjit
)) {
1828 rb_warn("MJIT and YJIT cannot both be enabled at the same time. Exiting");
1832 #if YJIT_SUPPORTED_P
1833 rb_yjit_init(&opt
->yjit
);
1836 if (opt
->dump
& (DUMP_BIT(version
) | DUMP_BIT(version_v
))) {
1838 mjit_opts
.on
= opt
->mjit
.on
; /* used by ruby_show_version(). mjit_init() still can't be called here. */
1840 ruby_show_version();
1841 if (opt
->dump
& DUMP_BIT(version
)) return Qtrue
;
1843 if (opt
->dump
& DUMP_BIT(copyright
)) {
1844 ruby_show_copyright();
1848 if (!opt
->e_script
) {
1849 if (argc
<= 0) { /* no more args */
1855 opt
->script
= argv
[0];
1856 if (!opt
->script
|| opt
->script
[0] == '\0') {
1859 else if (opt
->do_search
) {
1860 const char *path
= getenv("RUBYPATH");
1864 opt
->script
= dln_find_file_r(argv
[0], path
, fbuf
, sizeof(fbuf
));
1867 opt
->script
= dln_find_file_r(argv
[0], getenv(PATH_ENV
), fbuf
, sizeof(fbuf
));
1870 opt
->script
= argv
[0];
1875 if (opt
->script
[0] == '-' && !opt
->script
[1]) {
1876 forbid_setid("program input from stdin");
1880 opt
->script_name
= rb_str_new_cstr(opt
->script
);
1881 opt
->script
= RSTRING_PTR(opt
->script_name
);
1884 translit_char_bin(RSTRING_PTR(opt
->script_name
), '\\', '/');
1885 #elif defined DOSISH
1886 translit_char(RSTRING_PTR(opt
->script_name
), '\\', '/');
1889 ruby_gc_set_params();
1890 ruby_init_loadpath();
1894 /* Using TMP_RUBY_PREFIX created by ruby_init_loadpath(). */
1895 mjit_init(&opt
->mjit
);
1898 Init_ruby_description();
1900 lenc
= rb_locale_encoding();
1901 rb_enc_associate(rb_progname
, lenc
);
1902 rb_obj_freeze(rb_progname
);
1903 parser
= rb_parser_new();
1904 if (opt
->dump
& DUMP_BIT(yydebug
)) {
1905 rb_parser_set_yydebug(parser
, Qtrue
);
1907 if (opt
->ext
.enc
.name
!= 0) {
1908 opt
->ext
.enc
.index
= opt_enc_index(opt
->ext
.enc
.name
);
1910 if (opt
->intern
.enc
.name
!= 0) {
1911 opt
->intern
.enc
.index
= opt_enc_index(opt
->intern
.enc
.name
);
1913 if (opt
->src
.enc
.name
!= 0) {
1914 opt
->src
.enc
.index
= opt_enc_index(opt
->src
.enc
.name
);
1915 src_encoding_index
= opt
->src
.enc
.index
;
1917 if (opt
->ext
.enc
.index
>= 0) {
1918 enc
= rb_enc_from_index(opt
->ext
.enc
.index
);
1921 enc
= IF_UTF8_PATH(uenc
, lenc
);
1923 rb_enc_set_default_external(rb_enc_from_encoding(enc
));
1924 if (opt
->intern
.enc
.index
>= 0) {
1925 enc
= rb_enc_from_index(opt
->intern
.enc
.index
);
1926 rb_enc_set_default_internal(rb_enc_from_encoding(enc
));
1927 opt
->intern
.enc
.index
= -1;
1932 script_name
= opt
->script_name
;
1933 rb_enc_associate(opt
->script_name
, IF_UTF8_PATH(uenc
, lenc
));
1936 opt
->script_name
= str_conv_enc(opt
->script_name
, uenc
, lenc
);
1937 opt
->script
= RSTRING_PTR(opt
->script_name
);
1940 rb_obj_freeze(opt
->script_name
);
1941 if (IF_UTF8_PATH(uenc
!= lenc
, 1)) {
1943 VALUE load_path
= vm
->load_path
;
1944 const ID id_initial_load_path_mark
= INITIAL_LOAD_PATH_MARK
;
1945 int modifiable
= FALSE
;
1947 rb_get_expanded_load_path();
1948 for (i
= 0; i
< RARRAY_LEN(load_path
); ++i
) {
1949 VALUE path
= RARRAY_AREF(load_path
, i
);
1950 int mark
= rb_attr_get(path
, id_initial_load_path_mark
) == path
;
1952 VALUE newpath
= rb_str_conv_enc(path
, uenc
, lenc
);
1953 if (newpath
== path
) continue;
1956 if (!(path
= copy_str(path
, lenc
, !mark
))) continue;
1958 if (mark
) rb_ivar_set(path
, id_initial_load_path_mark
, path
);
1960 rb_ary_modify(load_path
);
1963 RARRAY_ASET(load_path
, i
, path
);
1966 rb_ary_replace(vm
->load_path_snapshot
, load_path
);
1970 VALUE loaded_features
= vm
->loaded_features
;
1971 bool modified
= false;
1972 for (long i
= loaded_before_enc
; i
< RARRAY_LEN(loaded_features
); ++i
) {
1973 VALUE path
= RARRAY_AREF(loaded_features
, i
);
1974 if (!(path
= copy_str(path
, IF_UTF8_PATH(uenc
, lenc
), true))) continue;
1976 rb_ary_modify(loaded_features
);
1979 RARRAY_ASET(loaded_features
, i
, path
);
1982 rb_ary_replace(vm
->loaded_features_snapshot
, loaded_features
);
1986 if (opt
->features
.mask
& COMPILATION_FEATURES
) {
1987 VALUE option
= rb_hash_new();
1988 #define SET_COMPILE_OPTION(h, o, name) \
1989 rb_hash_aset((h), ID2SYM(rb_intern_const(#name)), \
1990 RBOOL(FEATURE_SET_P(o->features, FEATURE_BIT(name))));
1991 SET_COMPILE_OPTION(option
, opt
, frozen_string_literal
);
1992 SET_COMPILE_OPTION(option
, opt
, debug_frozen_string_literal
);
1993 rb_funcallv(rb_cISeq
, rb_intern_const("compile_option="), 1, &option
);
1994 #undef SET_COMPILE_OPTION
1996 ruby_set_argv(argc
, argv
);
1997 process_sflag(&opt
->sflag
);
1999 rb_parser_set_context(parser
, 0, TRUE
);
2001 if (opt
->e_script
) {
2002 VALUE progname
= rb_progname
;
2004 if (opt
->src
.enc
.index
>= 0) {
2005 eenc
= rb_enc_from_index(opt
->src
.enc
.index
);
2010 if (ienc
) eenc
= ienc
;
2015 opt
->e_script
= str_conv_enc(opt
->e_script
, uenc
, eenc
);
2018 rb_enc_associate(opt
->e_script
, eenc
);
2020 ruby_set_script_name(progname
);
2021 rb_parser_set_options(parser
, opt
->do_print
, opt
->do_loop
,
2022 opt
->do_line
, opt
->do_split
);
2023 ast
= rb_parser_compile_string(parser
, opt
->script
, opt
->e_script
, 1);
2027 f
= open_load_file(script_name
, &opt
->xflag
);
2028 ast
= load_file(parser
, opt
->script_name
, f
, 1, opt
);
2030 ruby_set_script_name(opt
->script_name
);
2031 if (dump
& DUMP_BIT(yydebug
)) {
2032 dump
&= ~DUMP_BIT(yydebug
);
2033 if (!dump
) return Qtrue
;
2036 if (opt
->ext
.enc
.index
>= 0) {
2037 enc
= rb_enc_from_index(opt
->ext
.enc
.index
);
2040 enc
= IF_UTF8_PATH(uenc
, lenc
);
2042 rb_enc_set_default_external(rb_enc_from_encoding(enc
));
2043 if (opt
->intern
.enc
.index
>= 0) {
2044 /* Set in the shebang line */
2045 enc
= rb_enc_from_index(opt
->intern
.enc
.index
);
2046 rb_enc_set_default_internal(rb_enc_from_encoding(enc
));
2048 else if (!rb_default_internal_encoding())
2049 /* Freeze default_internal */
2050 rb_enc_set_default_internal(Qnil
);
2051 rb_stdio_set_default_encoding();
2053 if (!ast
->body
.root
) {
2054 rb_ast_dispose(ast
);
2058 process_sflag(&opt
->sflag
);
2061 if (dump
& DUMP_BIT(syntax
)) {
2062 printf("Syntax OK\n");
2063 dump
&= ~DUMP_BIT(syntax
);
2064 if (!dump
) return Qtrue
;
2068 rb_define_global_function("sub", rb_f_sub
, -1);
2069 rb_define_global_function("gsub", rb_f_gsub
, -1);
2070 rb_define_global_function("chop", rb_f_chop
, 0);
2071 rb_define_global_function("chomp", rb_f_chomp
, -1);
2074 if (dump
& (DUMP_BIT(parsetree
)|DUMP_BIT(parsetree_with_comment
))) {
2075 rb_io_write(rb_stdout
, rb_parser_dump_tree(ast
->body
.root
, dump
& DUMP_BIT(parsetree_with_comment
)));
2076 rb_io_flush(rb_stdout
);
2077 dump
&= ~DUMP_BIT(parsetree
)&~DUMP_BIT(parsetree_with_comment
);
2079 rb_ast_dispose(ast
);
2086 if (!opt
->e_script
&& strcmp(opt
->script
, "-")) {
2087 path
= rb_realpath_internal(Qnil
, script_name
, 1);
2090 path
= str_conv_enc(path
, uenc
, lenc
);
2093 if (!ENCODING_GET(path
)) { /* ASCII-8BIT */
2094 rb_enc_copy(path
, opt
->script_name
);
2098 rb_binding_t
*toplevel_binding
;
2099 GetBindingPtr(rb_const_get(rb_cObject
, rb_intern("TOPLEVEL_BINDING")),
2101 const struct rb_block
*base_block
= toplevel_context(toplevel_binding
);
2102 iseq
= rb_iseq_new_main(&ast
->body
, opt
->script_name
, path
, vm_block_iseq(base_block
), !(dump
& DUMP_BIT(insns_without_opt
)));
2103 rb_ast_dispose(ast
);
2106 if (dump
& (DUMP_BIT(insns
) | DUMP_BIT(insns_without_opt
))) {
2107 rb_io_write(rb_stdout
, rb_iseq_disasm((const rb_iseq_t
*)iseq
));
2108 rb_io_flush(rb_stdout
);
2109 dump
&= ~DUMP_BIT(insns
);
2110 if (!dump
) return Qtrue
;
2112 if (opt
->dump
& dump_exit_bits
) return Qtrue
;
2114 rb_define_readonly_boolean("$-p", opt
->do_print
);
2115 rb_define_readonly_boolean("$-l", opt
->do_line
);
2116 rb_define_readonly_boolean("$-a", opt
->do_split
);
2118 rb_gvar_ractor_local("$-p");
2119 rb_gvar_ractor_local("$-l");
2120 rb_gvar_ractor_local("$-a");
2122 if ((rb_e_script
= opt
->e_script
) != 0) {
2123 rb_str_freeze(rb_e_script
);
2124 rb_gc_register_mark_object(opt
->e_script
);
2128 rb_execution_context_t
*ec
= GET_EC();
2130 if (opt
->e_script
) {
2132 rb_exec_event_hook_script_compiled(ec
, iseq
, opt
->e_script
);
2136 rb_exec_event_hook_script_compiled(ec
, iseq
, Qnil
);
2144 warn_cr_in_shebang(const char *str
, long len
)
2146 if (str
[len
-1] == '\n' && str
[len
-2] == '\r') {
2147 rb_warn("shebang line ending with \\r may cause problems");
2151 #define warn_cr_in_shebang(str, len) (void)0
2154 struct load_file_arg
{
2158 ruby_cmdline_options_t
*opt
;
2163 load_file_internal(VALUE argp_v
)
2165 struct load_file_arg
*argp
= (struct load_file_arg
*)argp_v
;
2166 VALUE parser
= argp
->parser
;
2167 VALUE orig_fname
= argp
->fname
;
2168 int script
= argp
->script
;
2169 ruby_cmdline_options_t
*opt
= argp
->opt
;
2176 CONST_ID(set_encoding
, "set_encoding");
2178 VALUE c
= 1; /* something not nil */
2182 int no_src_enc
= !opt
->src
.enc
.name
;
2183 int no_ext_enc
= !opt
->ext
.enc
.name
;
2184 int no_int_enc
= !opt
->intern
.enc
.name
;
2186 enc
= rb_ascii8bit_encoding();
2187 rb_funcall(f
, set_encoding
, 1, rb_enc_from_encoding(enc
));
2192 while (!NIL_P(line
= rb_io_gets(f
))) {
2194 RSTRING_GETMEM(line
, str
, len
);
2195 if (len
> 2 && str
[0] == '#' && str
[1] == '!') {
2196 if (line_start
== 1) warn_cr_in_shebang(str
, len
);
2197 if ((p
= strstr(str
+2, ruby_engine
)) != 0) {
2202 rb_loaderror("no Ruby script found in input");
2205 c
= rb_io_getbyte(f
);
2206 if (c
== INT2FIX('#')) {
2207 c
= rb_io_getbyte(f
);
2208 if (c
== INT2FIX('!') && !NIL_P(line
= rb_io_gets(f
))) {
2209 RSTRING_GETMEM(line
, str
, len
);
2210 warn_cr_in_shebang(str
, len
);
2211 if ((p
= strstr(str
, ruby_engine
)) == 0) {
2212 /* not ruby script, assume -x flag */
2213 goto search_shebang
;
2218 if (*str
== '\n') *str
-- = '\0';
2219 if (*str
== '\r') *str
-- = '\0';
2220 /* ruby_engine should not contain a space */
2221 if ((p
= strstr(p
, " -")) != 0) {
2223 moreswitches(p
+ 1, opt
, 0);
2226 /* push back shebang for pragma may exist in next line */
2227 rb_io_ungetbyte(f
, rb_str_new2("!\n"));
2229 else if (!NIL_P(c
)) {
2230 rb_io_ungetbyte(f
, c
);
2232 rb_io_ungetbyte(f
, INT2FIX('#'));
2233 if (no_src_enc
&& opt
->src
.enc
.name
) {
2234 opt
->src
.enc
.index
= opt_enc_index(opt
->src
.enc
.name
);
2235 src_encoding_index
= opt
->src
.enc
.index
;
2237 if (no_ext_enc
&& opt
->ext
.enc
.name
) {
2238 opt
->ext
.enc
.index
= opt_enc_index(opt
->ext
.enc
.name
);
2240 if (no_int_enc
&& opt
->intern
.enc
.name
) {
2241 opt
->intern
.enc
.index
= opt_enc_index(opt
->intern
.enc
.name
);
2244 else if (!NIL_P(c
)) {
2245 rb_io_ungetbyte(f
, c
);
2252 if (opt
->src
.enc
.index
>= 0) {
2253 enc
= rb_enc_from_index(opt
->src
.enc
.index
);
2255 else if (f
== rb_stdin
) {
2256 enc
= rb_locale_encoding();
2259 enc
= rb_utf8_encoding();
2261 rb_parser_set_options(parser
, opt
->do_print
, opt
->do_loop
,
2262 opt
->do_line
, opt
->do_split
);
2264 f
= rb_str_new(0, 0);
2265 rb_enc_associate(f
, enc
);
2266 return (VALUE
)rb_parser_compile_string_path(parser
, orig_fname
, f
, line_start
);
2268 rb_funcall(f
, set_encoding
, 2, rb_enc_from_encoding(enc
), rb_str_new_cstr("-"));
2269 ast
= rb_parser_compile_file_path(parser
, orig_fname
, f
, line_start
);
2270 rb_funcall(f
, set_encoding
, 1, rb_parser_encoding(parser
));
2271 if (script
&& rb_parser_end_seen_p(parser
)) {
2273 * DATA is a File that contains the data section of the executed file.
2274 * To create a data section use <tt>__END__</tt>:
2284 rb_define_global_const("DATA", f
);
2290 /* disabling O_NONBLOCK, and returns 0 on success, otherwise errno */
2292 disable_nonblock(int fd
)
2294 #if defined(HAVE_FCNTL) && defined(F_SETFL)
2295 if (fcntl(fd
, F_SETFL
, 0) < 0) {
2296 const int e
= errno
;
2298 # if defined ENOTSUP
2299 if (e
== ENOTSUP
) return 0;
2301 # if defined B_UNSUPPORTED
2302 if (e
== B_UNSUPPORTED
) return 0;
2311 open_load_file(VALUE fname_v
, int *xflag
)
2313 const char *fname
= (fname_v
= rb_str_encode_ospath(fname_v
),
2314 StringValueCStr(fname_v
));
2315 long flen
= RSTRING_LEN(fname_v
);
2319 if (flen
== 1 && fname
[0] == '-') {
2324 /* open(2) may block if fname is point to FIFO and it's empty. Let's
2326 const int MODE_TO_LOAD
= O_RDONLY
| (
2327 #if defined O_NONBLOCK && HAVE_FCNTL
2328 /* TODO: fix conflicting O_NONBLOCK in ruby/win32.h */
2329 !(O_NONBLOCK
& O_ACCMODE
) ? O_NONBLOCK
:
2331 #if defined O_NDELAY && HAVE_FCNTL
2332 !(O_NDELAY
& O_ACCMODE
) ? O_NDELAY
:
2335 int mode
= MODE_TO_LOAD
;
2336 #if defined DOSISH || defined __CYGWIN__
2337 # define isdirsep(x) ((x) == '/' || (x) == '\\')
2339 static const char exeext
[] = ".exe";
2340 enum {extlen
= sizeof(exeext
)-1};
2341 if (flen
> extlen
&& !isdirsep(fname
[flen
-extlen
-1]) &&
2342 STRNCASECMP(fname
+flen
-extlen
, exeext
, extlen
) == 0) {
2349 if ((fd
= rb_cloexec_open(fname
, mode
, 0)) < 0) {
2351 if (!rb_gc_for_fd(e
)) {
2352 rb_load_fail(fname_v
, strerror(e
));
2354 if ((fd
= rb_cloexec_open(fname
, mode
, 0)) < 0) {
2355 rb_load_fail(fname_v
, strerror(errno
));
2358 rb_update_max_fd(fd
);
2360 if (MODE_TO_LOAD
!= O_RDONLY
&& (e
= disable_nonblock(fd
)) != 0) {
2362 rb_load_fail(fname_v
, strerror(e
));
2365 e
= ruby_is_fd_loadable(fd
);
2369 rb_load_fail(fname_v
, strerror(e
));
2372 f
= rb_io_fdopen(fd
, mode
, fname
);
2375 We need to wait if FIFO is empty. It's FIFO's semantics.
2376 rb_thread_wait_fd() release GVL. So, it's safe.
2378 rb_io_wait(f
, RB_INT2NUM(RUBY_IO_READABLE
), Qnil
);
2385 restore_load_file(VALUE arg
)
2387 struct load_file_arg
*argp
= (struct load_file_arg
*)arg
;
2390 if (!NIL_P(f
) && f
!= rb_stdin
) {
2397 load_file(VALUE parser
, VALUE fname
, VALUE f
, int script
, ruby_cmdline_options_t
*opt
)
2399 struct load_file_arg arg
;
2400 arg
.parser
= parser
;
2402 arg
.script
= script
;
2405 return (rb_ast_t
*)rb_ensure(load_file_internal
, (VALUE
)&arg
,
2406 restore_load_file
, (VALUE
)&arg
);
2410 rb_load_file(const char *fname
)
2412 VALUE fname_v
= rb_str_new_cstr(fname
);
2413 return rb_load_file_str(fname_v
);
2417 rb_load_file_str(VALUE fname_v
)
2419 return rb_parser_load_file(rb_parser_new(), fname_v
);
2423 rb_parser_load_file(VALUE parser
, VALUE fname_v
)
2425 ruby_cmdline_options_t opt
;
2426 VALUE f
= open_load_file(fname_v
, &cmdline_options_init(&opt
)->xflag
);
2427 return load_file(parser
, fname_v
, f
, 0, &opt
);
2432 * Process.argv0 -> frozen_string
2434 * Returns the name of the script being executed. The value is not
2435 * affected by assigning a new value to $0.
2437 * This method first appeared in Ruby 2.1 to serve as a global
2438 * variable free means to get the script name.
2442 proc_argv0(VALUE process
)
2444 return rb_orig_progname
;
2447 static VALUE
ruby_setproctitle(VALUE title
);
2451 * Process.setproctitle(string) -> string
2453 * Sets the process title that appears on the ps(1) command. Not
2454 * necessarily effective on all platforms. No exception will be
2455 * raised regardless of the result, nor will NotImplementedError be
2456 * raised even if the platform does not support the feature.
2458 * Calling this method does not affect the value of $0.
2460 * Process.setproctitle('myapp: worker #%d' % worker_id)
2462 * This method first appeared in Ruby 2.1 to serve as a global
2463 * variable free means to change the process title.
2467 proc_setproctitle(VALUE process
, VALUE title
)
2469 return ruby_setproctitle(title
);
2473 ruby_setproctitle(VALUE title
)
2475 const char *ptr
= StringValueCStr(title
);
2476 setproctitle("%.*s", RSTRING_LENINT(title
), ptr
);
2481 set_arg0(VALUE val
, ID id
, VALUE
*_
)
2483 if (origarg
.argv
== 0)
2484 rb_raise(rb_eRuntimeError
, "$0 not initialized");
2486 rb_progname
= rb_str_new_frozen(ruby_setproctitle(val
));
2490 external_str_new_cstr(const char *p
)
2493 VALUE str
= rb_utf8_str_new_cstr(p
);
2494 str
= str_conv_enc(str
, NULL
, rb_default_external_encoding());
2497 return rb_external_str_new_cstr(p
);
2502 ruby_script(const char *name
)
2505 rb_orig_progname
= rb_progname
= external_str_new_cstr(name
);
2506 rb_vm_set_progname(rb_progname
);
2510 /*! Sets the current script name to this value.
2512 * Same as ruby_script() but accepts a VALUE.
2515 ruby_set_script_name(VALUE name
)
2517 rb_orig_progname
= rb_progname
= rb_str_dup(name
);
2518 rb_vm_set_progname(rb_progname
);
2522 init_ids(ruby_cmdline_options_t
*opt
)
2524 rb_uid_t uid
= getuid();
2525 rb_uid_t euid
= geteuid();
2526 rb_gid_t gid
= getgid();
2527 rb_gid_t egid
= getegid();
2529 if (uid
!= euid
) opt
->setids
|= 1;
2530 if (egid
!= gid
) opt
->setids
|= 2;
2535 forbid_setid(const char *s
, const ruby_cmdline_options_t
*opt
)
2537 if (opt
->setids
& 1)
2538 rb_raise(rb_eSecurityError
, "no %s allowed while running setuid", s
);
2539 if (opt
->setids
& 2)
2540 rb_raise(rb_eSecurityError
, "no %s allowed while running setgid", s
);
2544 verbose_getter(ID id
, VALUE
*ptr
)
2546 return *rb_ruby_verbose_ptr();
2550 verbose_setter(VALUE val
, ID id
, VALUE
*variable
)
2552 *rb_ruby_verbose_ptr() = RTEST(val
) ? Qtrue
: val
;
2556 opt_W_getter(ID id
, VALUE
*dmy
)
2558 VALUE v
= *rb_ruby_verbose_ptr();
2573 debug_getter(ID id
, VALUE
*dmy
)
2575 return *rb_ruby_debug_ptr();
2579 debug_setter(VALUE val
, ID id
, VALUE
*dmy
)
2581 *rb_ruby_debug_ptr() = val
;
2585 ruby_prog_init(void)
2587 rb_define_virtual_variable("$VERBOSE", verbose_getter
, verbose_setter
);
2588 rb_define_virtual_variable("$-v", verbose_getter
, verbose_setter
);
2589 rb_define_virtual_variable("$-w", verbose_getter
, verbose_setter
);
2590 rb_define_virtual_variable("$-W", opt_W_getter
, rb_gvar_readonly_setter
);
2591 rb_define_virtual_variable("$DEBUG", debug_getter
, debug_setter
);
2592 rb_define_virtual_variable("$-d", debug_getter
, debug_setter
);
2594 rb_gvar_ractor_local("$VERBOSE");
2595 rb_gvar_ractor_local("$-v");
2596 rb_gvar_ractor_local("$-w");
2597 rb_gvar_ractor_local("$-W");
2598 rb_gvar_ractor_local("$DEBUG");
2599 rb_gvar_ractor_local("$-d");
2601 rb_define_hooked_variable("$0", &rb_progname
, 0, set_arg0
);
2602 rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname
, 0, set_arg0
);
2604 rb_define_module_function(rb_mProcess
, "argv0", proc_argv0
, 0);
2605 rb_define_module_function(rb_mProcess
, "setproctitle", proc_setproctitle
, 1);
2608 * ARGV contains the command line arguments used to run ruby.
2610 * A library like OptionParser can be used to process command-line
2613 rb_define_global_const("ARGV", rb_argv
);
2617 ruby_set_argv(int argc
, char **argv
)
2623 for (i
= 0; i
< argc
; i
++) {
2624 VALUE arg
= external_str_new_cstr(argv
[i
]);
2627 rb_ary_push(av
, arg
);
2632 ruby_process_options(int argc
, char **argv
)
2634 ruby_cmdline_options_t opt
;
2636 const char *script_name
= (argc
> 0 && argv
[0]) ? argv
[0] : ruby_engine
;
2638 if (!origarg
.argv
|| origarg
.argc
<= 0) {
2639 origarg
.argc
= argc
;
2640 origarg
.argv
= argv
;
2642 ruby_script(script_name
); /* for the time being */
2643 rb_argv0
= rb_str_new4(rb_progname
);
2644 rb_gc_register_mark_object(rb_argv0
);
2645 iseq
= process_options(argc
, argv
, cmdline_options_init(&opt
));
2647 #ifndef HAVE_SETPROCTITLE
2648 ruby_init_setproctitle(argc
, argv
);
2651 return (void*)(struct RData
*)iseq
;
2655 fill_standard_fds(void)
2657 int f0
, f1
, f2
, fds
[2];
2659 f0
= fstat(0, &buf
) == -1 && errno
== EBADF
;
2660 f1
= fstat(1, &buf
) == -1 && errno
== EBADF
;
2661 f2
= fstat(2, &buf
) == -1 && errno
== EBADF
;
2663 if (pipe(fds
) == 0) {
2672 if (pipe(fds
) == 0) {
2674 if (f1
&& fds
[1] != 1)
2676 if (f2
&& fds
[1] != 2)
2678 if (fds
[1] != 1 && fds
[1] != 2)
2685 ruby_sysinit(int *argc
, char ***argv
)
2688 rb_w32_sysinit(argc
, argv
);
2690 if (*argc
>= 0 && *argv
) {
2691 origarg
.argc
= *argc
;
2692 origarg
.argv
= *argv
;
2694 fill_standard_fds();