Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)
ruby.c
Go to the documentation of this file.
1/**********************************************************************
2
3 ruby.c -
4
5 $Author$
6 created at: Tue Aug 10 12:47:31 JST 1993
7
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
11
12**********************************************************************/
13
15
16#include <ctype.h>
17#include <stdio.h>
18#include <sys/types.h>
19
20#ifdef __CYGWIN__
21# include <windows.h>
22# include <sys/cygwin.h>
23#endif
24
25#ifdef __hpux
26# include <sys/pstat.h>
27#endif
28
29#if (defined(LOAD_RELATIVE) || defined(__MACH__)) && defined(HAVE_DLADDR)
30# include <dlfcn.h>
31#endif
32
33#ifdef HAVE_UNISTD_H
34# include <unistd.h>
35#endif
36
37#if defined(HAVE_FCNTL_H)
38# include <fcntl.h>
39#elif defined(HAVE_SYS_FCNTL_H)
40# include <sys/fcntl.h>
41#endif
42
43#ifdef HAVE_SYS_PARAM_H
44# include <sys/param.h>
45#endif
46
47#include "dln.h"
48#include "eval_intern.h"
49#include "internal.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"
61#include "mjit.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"
67
68#ifndef MAXPATHLEN
69# define MAXPATHLEN 1024
70#endif
71#ifndef O_ACCMODE
72# define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
73#endif
74
75void Init_ruby_description(void);
76
77#ifndef HAVE_STDLIB_H
78char *getenv();
79#endif
80
81#ifndef DISABLE_RUBYGEMS
82# define DISABLE_RUBYGEMS 0
83#endif
84#if DISABLE_RUBYGEMS
85#define DEFAULT_RUBYGEMS_ENABLED "disabled"
86#else
87#define DEFAULT_RUBYGEMS_ENABLED "enabled"
88#endif
89
90void rb_warning_category_update(unsigned int mask, unsigned int bits);
91
92#define COMMA ,
93#define FEATURE_BIT(bit) (1U << feature_##bit)
94#define EACH_FEATURES(X, SEP) \
95 X(gems) \
96 SEP \
97 X(did_you_mean) \
98 SEP \
99 X(rubyopt) \
100 SEP \
101 X(frozen_string_literal) \
102 SEP \
103 X(jit) \
104 /* END OF FEATURES */
105#define EACH_DEBUG_FEATURES(X, SEP) \
106 X(frozen_string_literal) \
107 /* END OF DEBUG FEATURES */
108#define AMBIGUOUS_FEATURE_NAMES 0 /* no ambiguous feature names now */
109#define DEFINE_FEATURE(bit) feature_##bit
110#define DEFINE_DEBUG_FEATURE(bit) feature_debug_##bit
118
119#define DEBUG_BIT(bit) (1U << feature_debug_##bit)
120
121#define DUMP_BIT(bit) (1U << dump_##bit)
122#define DEFINE_DUMP(bit) dump_##bit
123#define EACH_DUMPS(X, SEP) \
124 X(version) \
125 SEP \
126 X(copyright) \
127 SEP \
128 X(usage) \
129 SEP \
130 X(help) \
131 SEP \
132 X(yydebug) \
133 SEP \
134 X(syntax) \
135 SEP \
136 X(parsetree) \
137 SEP \
138 X(parsetree_with_comment) \
139 SEP \
140 X(insns) \
141 /* END OF DUMPS */
146 DUMP_BIT(parsetree) | DUMP_BIT(parsetree_with_comment) |
147 DUMP_BIT(insns))
149
151
152typedef struct {
153 unsigned int mask;
154 unsigned int set;
156
157static inline void
158rb_feature_set_to(ruby_features_t *feat, unsigned int bit_mask, unsigned int bit_set)
159{
160 feat->mask |= bit_mask;
161 feat->set = (feat->set & ~bit_mask) | bit_set;
162}
163
164#define FEATURE_SET_TO(feat, bit_mask, bit_set) \
165 rb_feature_set_to(&(feat), bit_mask, bit_set)
166#define FEATURE_SET(feat, bits) FEATURE_SET_TO(feat, bits, bits)
167#define FEATURE_SET_RESTORE(feat, save) FEATURE_SET_TO(feat, (save).mask, (save).set & (save).mask)
168#define FEATURE_SET_P(feat, bits) ((feat).set & (bits))
169
171 const char *script;
174 struct {
175 struct {
177 int index;
183 unsigned int dump;
184#if USE_MJIT
185 struct mjit_options mjit;
186#endif
188 unsigned int warning: 1;
189 unsigned int verbose: 1;
190 unsigned int do_loop: 1;
191 unsigned int do_print: 1;
192 unsigned int do_line: 1;
193 unsigned int do_split: 1;
194 unsigned int do_search: 1;
195 unsigned int setids: 2;
196};
197
198static void init_ids(ruby_cmdline_options_t *);
199
200#define src_encoding_index GET_VM()->src_encoding_index
201
202enum {
204 0
205 | FEATURE_BIT(frozen_string_literal)
206 | FEATURE_BIT(debug_frozen_string_literal)
207 ),
209 (FEATURE_BIT(debug_flag_first)-1)
210#if DISABLE_RUBYGEMS
211 & ~FEATURE_BIT(gems)
212#endif
213 & ~FEATURE_BIT(frozen_string_literal)
214 & ~FEATURE_BIT(jit)
215 )
217
219cmdline_options_init(ruby_cmdline_options_t *opt)
220{
221 MEMZERO(opt, *opt, 1);
222 init_ids(opt);
224 opt->ext.enc.index = -1;
225 opt->intern.enc.index = -1;
227#ifdef MJIT_FORCE_ENABLE /* to use with: ./configure cppflags="-DMJIT_FORCE_ENABLE" */
228 opt->features.set |= FEATURE_BIT(jit);
229#endif
230 return opt;
231}
232
233static rb_ast_t *load_file(VALUE parser, VALUE fname, VALUE f, int script,
235static VALUE open_load_file(VALUE fname_v, int *xflag);
236static void forbid_setid(const char *, const ruby_cmdline_options_t *);
237#define forbid_setid(s) forbid_setid((s), opt)
238
239static struct {
240 int argc;
241 char **argv;
242} origarg;
243
244static const char esc_standout[] = "\n\033[1;7m";
245static const char esc_bold[] = "\033[1m";
246static const char esc_reset[] = "\033[0m";
247static const char esc_none[] = "";
248
249static void
250show_usage_line(const char *str, unsigned int namelen, unsigned int secondlen, int help, int highlight, unsigned int w)
251{
252 const char *sb = highlight ? esc_bold : esc_none;
253 const char *se = highlight ? esc_reset : esc_none;
254 const int wrap = help && namelen + secondlen - 1 > w;
255 printf(" %s%.*s%-*.*s%s%-*s%s\n", sb, namelen-1, str,
256 (wrap ? 0 : w - namelen + 1),
257 (help ? secondlen-1 : 0), str + namelen, se,
258 (wrap ? w + 3 : 0), (wrap ? "\n" : ""),
259 str + namelen + secondlen);
260}
261
262static void
263usage(const char *name, int help, int highlight, int columns)
264{
265 /* This message really ought to be max 23 lines.
266 * Removed -h because the user already knows that option. Others? */
267
268 struct message {
269 const char *str;
270 unsigned short namelen, secondlen;
271 };
272#define M(shortopt, longopt, desc) { \
273 shortopt " " longopt " " desc, \
274 (unsigned short)sizeof(shortopt), \
275 (unsigned short)sizeof(longopt), \
276}
277 static const struct message usage_msg[] = {
278 M("-0[octal]", "", "specify record separator (\\0, if no argument)"),
279 M("-a", "", "autosplit mode with -n or -p (splits $_ into $F)"),
280 M("-c", "", "check syntax only"),
281 M("-Cdirectory", "", "cd to directory before executing your script"),
282 M("-d", ", --debug", "set debugging flags (set $DEBUG to true)"),
283 M("-e 'command'", "", "one line of script. Several -e's allowed. Omit [programfile]"),
284 M("-Eex[:in]", ", --encoding=ex[:in]", "specify the default external and internal character encodings"),
285 M("-Fpattern", "", "split() pattern for autosplit (-a)"),
286 M("-i[extension]", "", "edit ARGV files in place (make backup if extension supplied)"),
287 M("-Idirectory", "", "specify $LOAD_PATH directory (may be used more than once)"),
288 M("-l", "", "enable line ending processing"),
289 M("-n", "", "assume 'while gets(); ... end' loop around your script"),
290 M("-p", "", "assume loop like -n but print line also like sed"),
291 M("-rlibrary", "", "require the library before executing your script"),
292 M("-s", "", "enable some switch parsing for switches after script name"),
293 M("-S", "", "look for the script using PATH environment variable"),
294 M("-v", "", "print the version number, then turn on verbose mode"),
295 M("-w", "", "turn warnings on for your script"),
296 M("-W[level=2|:category]", "", "set warning level; 0=silence, 1=medium, 2=verbose"),
297 M("-x[directory]", "", "strip off text before #!ruby line and perhaps cd to directory"),
298 M("--jit", "", "enable JIT with default options (experimental)"),
299 M("--jit-[option]","", "enable JIT with an option (experimental)"),
300 M("-h", "", "show this message, --help for more info"),
301 };
302 static const struct message help_msg[] = {
303 M("--copyright", "", "print the copyright"),
304 M("--dump={insns|parsetree|...}[,...]", "",
305 "dump debug information. see below for available dump list"),
306 M("--enable={gems|rubyopt|...}[,...]", ", --disable={gems|rubyopt|...}[,...]",
307 "enable or disable features. see below for available features"),
308 M("--external-encoding=encoding", ", --internal-encoding=encoding",
309 "specify the default external or internal character encoding"),
310 M("--verbose", "", "turn on verbose mode and disable script from stdin"),
311 M("--version", "", "print the version number, then exit"),
312 M("--help", "", "show this message, -h for short message"),
313 M("--backtrace-limit=num", "", "limit the maximum length of backtrace"),
314 };
315 static const struct message dumps[] = {
316 M("insns", "", "instruction sequences"),
317 M("yydebug", "", "yydebug of yacc parser generator"),
318 M("parsetree", "", "AST"),
319 M("parsetree_with_comment", "", "AST with comments"),
320 };
321 static const struct message features[] = {
322 M("gems", "", "rubygems (default: "DEFAULT_RUBYGEMS_ENABLED")"),
323 M("did_you_mean", "", "did_you_mean (default: "DEFAULT_RUBYGEMS_ENABLED")"),
324 M("rubyopt", "", "RUBYOPT environment variable (default: enabled)"),
325 M("frozen-string-literal", "", "freeze all string literals (default: disabled)"),
326 M("jit", "", "JIT compiler (default: disabled)"),
327 };
328 static const struct message warn_categories[] = {
329 M("deprecated", "", "deprecated features"),
330 M("experimental", "", "experimental features"),
331 };
332 static const struct message mjit_options[] = {
333 M("--jit-warnings", "", "Enable printing JIT warnings"),
334 M("--jit-debug", "", "Enable JIT debugging (very slow), or add cflags if specified"),
335 M("--jit-wait", "", "Wait until JIT compilation finishes every time (for testing)"),
336 M("--jit-save-temps", "", "Save JIT temporary files in $TMP or /tmp (for testing)"),
337 M("--jit-verbose=num", "", "Print JIT logs of level num or less to stderr (default: 0)"),
338 M("--jit-max-cache=num", "", "Max number of methods to be JIT-ed in a cache (default: 100)"),
339 M("--jit-min-calls=num", "", "Number of calls to trigger JIT (for testing, default: 10000)"),
340 };
341 int i;
342 const char *sb = highlight ? esc_standout+1 : esc_none;
343 const char *se = highlight ? esc_reset : esc_none;
344 const int num = numberof(usage_msg) - (help ? 1 : 0);
345 unsigned int w = (columns > 80 ? (columns - 79) / 2 : 0) + 16;
346#define SHOW(m) show_usage_line((m).str, (m).namelen, (m).secondlen, help, highlight, w)
347
348 printf("%sUsage:%s %s [switches] [--] [programfile] [arguments]\n", sb, se, name);
349 for (i = 0; i < num; ++i)
350 SHOW(usage_msg[i]);
351
352 if (!help) return;
353
354 if (highlight) sb = esc_standout;
355
356 for (i = 0; i < numberof(help_msg); ++i)
357 SHOW(help_msg[i]);
358 printf("%s""Dump List:%s\n", sb, se);
359 for (i = 0; i < numberof(dumps); ++i)
360 SHOW(dumps[i]);
361 printf("%s""Features:%s\n", sb, se);
362 for (i = 0; i < numberof(features); ++i)
363 SHOW(features[i]);
364 printf("%s""Warning categories:%s\n", sb, se);
365 for (i = 0; i < numberof(warn_categories); ++i)
366 SHOW(warn_categories[i]);
367 printf("%s""JIT options (experimental):%s\n", sb, se);
368 for (i = 0; i < numberof(mjit_options); ++i)
369 SHOW(mjit_options[i]);
370}
371
372#define rubylib_path_new rb_str_new
373
374static void
375push_include(const char *path, VALUE (*filter)(VALUE))
376{
377 const char sep = PATH_SEP_CHAR;
378 const char *p, *s;
379 VALUE load_path = GET_VM()->load_path;
380
381 p = path;
382 while (*p) {
383 while (*p == sep)
384 p++;
385 if (!*p) break;
386 for (s = p; *s && *s != sep; s = CharNext(s));
387 rb_ary_push(load_path, (*filter)(rubylib_path_new(p, s - p)));
388 p = s;
389 }
390}
391
392#ifdef __CYGWIN__
393static void
394push_include_cygwin(const char *path, VALUE (*filter)(VALUE))
395{
396 const char *p, *s;
397 char rubylib[FILENAME_MAX];
398 VALUE buf = 0;
399
400 p = path;
401 while (*p) {
402 unsigned int len;
403 while (*p == ';')
404 p++;
405 if (!*p) break;
406 for (s = p; *s && *s != ';'; s = CharNext(s));
407 len = s - p;
408 if (*s) {
409 if (!buf) {
410 buf = rb_str_new(p, len);
411 p = RSTRING_PTR(buf);
412 }
413 else {
415 p = strncpy(RSTRING_PTR(buf), p, len);
416 }
417 }
418#ifdef HAVE_CYGWIN_CONV_PATH
419#define CONV_TO_POSIX_PATH(p, lib) \
420 cygwin_conv_path(CCP_WIN_A_TO_POSIX|CCP_RELATIVE, (p), (lib), sizeof(lib))
421#else
422# error no cygwin_conv_path
423#endif
424 if (CONV_TO_POSIX_PATH(p, rubylib) == 0)
425 p = rubylib;
426 push_include(p, filter);
427 if (!*s) break;
428 p = s + 1;
429 }
430}
431
432#define push_include push_include_cygwin
433#endif
434
435void
436ruby_push_include(const char *path, VALUE (*filter)(VALUE))
437{
438 if (path == 0)
439 return;
440 push_include(path, filter);
441}
442
443static VALUE
444identical_path(VALUE path)
445{
446 return path;
447}
448static VALUE
449locale_path(VALUE path)
450{
452 return path;
453}
454
455void
456ruby_incpush(const char *path)
457{
458 ruby_push_include(path, locale_path);
459}
460
461static VALUE
462expand_include_path(VALUE path)
463{
464 char *p = RSTRING_PTR(path);
465 if (!p)
466 return path;
467 if (*p == '.' && p[1] == '/')
468 return path;
469 return rb_file_expand_path(path, Qnil);
470}
471
472void
473ruby_incpush_expand(const char *path)
474{
475 ruby_push_include(path, expand_include_path);
476}
477
478#undef UTF8_PATH
479#if defined _WIN32 || defined __CYGWIN__
480static HMODULE libruby;
481
482BOOL WINAPI
483DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved)
484{
485 if (reason == DLL_PROCESS_ATTACH)
486 libruby = dll;
487 return TRUE;
488}
489
490HANDLE
491rb_libruby_handle(void)
492{
493 return libruby;
494}
495
496static inline void
497translit_char_bin(char *p, int from, int to)
498{
499 while (*p) {
500 if ((unsigned char)*p == from)
501 *p = to;
502 p++;
503 }
504}
505#endif
506
507#ifdef _WIN32
508# define UTF8_PATH 1
509#endif
510
511#ifndef UTF8_PATH
512# define UTF8_PATH 0
513#endif
514#if UTF8_PATH
515# define IF_UTF8_PATH(t, f) t
516#else
517# define IF_UTF8_PATH(t, f) f
518#endif
519
520#if UTF8_PATH
521static VALUE
523{
524 return rb_str_conv_enc_opts(str, from, to,
526 Qnil);
527}
528#else
529# define str_conv_enc(str, from, to) (str)
530#endif
531
532void ruby_init_loadpath(void);
533
534#if defined(LOAD_RELATIVE) || defined(__MACH__)
535static VALUE
536runtime_libruby_path(void)
537{
538#if defined _WIN32 || defined __CYGWIN__
540 VALUE path;
541 VALUE wsopath = rb_str_new(0, len*sizeof(WCHAR));
542 WCHAR *wlibpath;
543 char *libpath;
544
545 while (wlibpath = (WCHAR *)RSTRING_PTR(wsopath),
546 ret = GetModuleFileNameW(libruby, wlibpath, len),
547 (ret == len))
548 {
549 rb_str_modify_expand(wsopath, len*sizeof(WCHAR));
550 rb_str_set_len(wsopath, (len += len)*sizeof(WCHAR));
551 }
552 if (!ret || ret > len) rb_fatal("failed to get module file name");
553#if defined __CYGWIN__
554 {
555 const int win_to_posix = CCP_WIN_W_TO_POSIX | CCP_RELATIVE;
556 size_t newsize = cygwin_conv_path(win_to_posix, wlibpath, 0, 0);
557 if (!newsize) rb_fatal("failed to convert module path to cygwin");
558 path = rb_str_new(0, newsize);
559 libpath = RSTRING_PTR(path);
560 if (cygwin_conv_path(win_to_posix, wlibpath, libpath, newsize)) {
561 rb_str_resize(path, 0);
562 }
563 }
564#else
565 {
566 DWORD i;
567 for (len = ret, i = 0; i < len; ++i) {
568 if (wlibpath[i] == L'\\') {
569 wlibpath[i] = L'/';
570 ret = i+1; /* chop after the last separator */
571 }
572 }
573 }
574 len = WideCharToMultiByte(CP_UTF8, 0, wlibpath, ret, NULL, 0, NULL, NULL);
575 path = rb_utf8_str_new(0, len);
576 libpath = RSTRING_PTR(path);
577 WideCharToMultiByte(CP_UTF8, 0, wlibpath, ret, libpath, len, NULL, NULL);
578#endif
579 rb_str_resize(wsopath, 0);
580 return path;
581#elif defined(HAVE_DLADDR)
582 Dl_info dli;
583 VALUE fname, path;
584 const void* addr = (void *)(VALUE)expand_include_path;
585
586 if (!dladdr((void *)addr, &dli)) {
587 return rb_str_new(0, 0);
588 }
589#ifdef __linux__
590 else if (origarg.argc > 0 && origarg.argv && dli.dli_fname == origarg.argv[0]) {
591 fname = rb_str_new_cstr("/proc/self/exe");
592 path = rb_readlink(fname, NULL);
593 }
594#endif
595 else {
596 fname = rb_str_new_cstr(dli.dli_fname);
597 path = rb_realpath_internal(Qnil, fname, 1);
598 }
599 rb_str_resize(fname, 0);
600 return path;
601#else
602# error relative load path is not supported on this platform.
603#endif
604}
605#endif
606
607#define INITIAL_LOAD_PATH_MARK rb_intern_const("@gem_prelude_index")
608
610#if defined(__MACH__)
611// A path to libruby.dylib itself or where it's statically linked to.
612VALUE rb_libruby_selfpath;
613#endif
614
615void
617{
618 VALUE load_path, archlibdir = 0;
619 ID id_initial_load_path_mark;
620 const char *paths = ruby_initial_load_paths;
621#if defined(LOAD_RELATIVE) || defined(__MACH__)
622 VALUE libruby_path = runtime_libruby_path();
623# if defined(__MACH__)
624 rb_libruby_selfpath = libruby_path;
625 rb_gc_register_address(&rb_libruby_selfpath);
626# endif
627#endif
628
629#if defined LOAD_RELATIVE
630#if !defined ENABLE_MULTIARCH
631# define RUBY_ARCH_PATH ""
632#elif defined RUBY_ARCH
633# define RUBY_ARCH_PATH "/"RUBY_ARCH
634#else
635# define RUBY_ARCH_PATH "/"RUBY_PLATFORM
636#endif
637 char *libpath;
638 VALUE sopath;
639 size_t baselen;
640 const char *p;
641
642 sopath = libruby_path;
643 libpath = RSTRING_PTR(sopath);
644
645 p = strrchr(libpath, '/');
646 if (p) {
647 static const char libdir[] = "/"
648#ifdef LIBDIR_BASENAME
649 LIBDIR_BASENAME
650#else
651 "lib"
652#endif
653 RUBY_ARCH_PATH;
654 const ptrdiff_t libdir_len = (ptrdiff_t)sizeof(libdir)
655 - rb_strlen_lit(RUBY_ARCH_PATH) - 1;
656 static const char bindir[] = "/bin";
657 const ptrdiff_t bindir_len = (ptrdiff_t)sizeof(bindir) - 1;
658
659 const char *p2 = NULL;
660
661#ifdef ENABLE_MULTIARCH
662 multiarch:
663#endif
664 if (p - libpath >= bindir_len && !STRNCASECMP(p - bindir_len, bindir, bindir_len)) {
665 p -= bindir_len;
666 archlibdir = rb_str_subseq(sopath, 0, p - libpath);
667 rb_str_cat_cstr(archlibdir, libdir);
668 OBJ_FREEZE_RAW(archlibdir);
669 }
670 else if (p - libpath >= libdir_len && !strncmp(p - libdir_len, libdir, libdir_len)) {
671 archlibdir = rb_str_subseq(sopath, 0, (p2 ? p2 : p) - libpath);
672 OBJ_FREEZE_RAW(archlibdir);
673 p -= libdir_len;
674 }
675#ifdef ENABLE_MULTIARCH
676 else if (p2) {
677 p = p2;
678 }
679 else {
680 p2 = p;
682 if (p) goto multiarch;
683 p = p2;
684 }
685#endif
686 }
687 baselen = p - libpath;
688 rb_str_resize(sopath, baselen);
689 libpath = RSTRING_PTR(sopath);
690#define PREFIX_PATH() sopath
691#define BASEPATH() rb_str_buf_cat(rb_str_buf_new(baselen+len), libpath, baselen)
692#define RUBY_RELATIVE(path, len) rb_str_buf_cat(BASEPATH(), (path), (len))
693#else
694 const size_t exec_prefix_len = strlen(ruby_exec_prefix);
695#define RUBY_RELATIVE(path, len) rubylib_path_new((path), (len))
696#define PREFIX_PATH() RUBY_RELATIVE(ruby_exec_prefix, exec_prefix_len)
697#endif
701 if (!archlibdir) archlibdir = ruby_prefix_path;
703 ruby_archlibdir_path = archlibdir;
704
705 load_path = GET_VM()->load_path;
706
707 ruby_push_include(getenv("RUBYLIB"), identical_path);
708
709 id_initial_load_path_mark = INITIAL_LOAD_PATH_MARK;
710 while (*paths) {
711 size_t len = strlen(paths);
712 VALUE path = RUBY_RELATIVE(paths, len);
713 rb_ivar_set(path, id_initial_load_path_mark, path);
714 rb_ary_push(load_path, path);
715 paths += len + 1;
716 }
717
718 rb_const_set(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"), ruby_prefix_path);
719}
720
721
722static void
723add_modules(VALUE *req_list, const char *mod)
724{
725 VALUE list = *req_list;
726 VALUE feature;
727
728 if (!list) {
729 *req_list = list = rb_ary_tmp_new(0);
730 }
731 feature = rb_str_cat_cstr(rb_str_tmp_new(0), mod);
732 rb_ary_push(list, feature);
733}
734
735static void
736require_libraries(VALUE *req_list)
737{
738 VALUE list = *req_list;
739 VALUE self = rb_vm_top_self();
740 ID require;
742
743 CONST_ID(require, "require");
744 while (list && RARRAY_LEN(list) > 0) {
745 VALUE feature = rb_ary_shift(list);
746 rb_enc_associate(feature, extenc);
747 RBASIC_SET_CLASS_RAW(feature, rb_cString);
748 OBJ_FREEZE(feature);
749 rb_funcallv(self, require, 1, &feature);
750 }
751 *req_list = 0;
752}
753
754static const struct rb_block*
755toplevel_context(rb_binding_t *bind)
756{
757 return &bind->block;
758}
759
760static void
761process_sflag(int *sflag)
762{
763 if (*sflag > 0) {
764 long n;
765 const VALUE *args;
767
768 n = RARRAY_LEN(argv);
769 args = RARRAY_CONST_PTR(argv);
770 while (n > 0) {
771 VALUE v = *args++;
772 char *s = StringValuePtr(v);
773 char *p;
774 int hyphen = FALSE;
775
776 if (s[0] != '-')
777 break;
778 n--;
779 if (s[1] == '-' && s[2] == '\0')
780 break;
781
782 v = Qtrue;
783 /* check if valid name before replacing - with _ */
784 for (p = s + 1; *p; p++) {
785 if (*p == '=') {
786 *p++ = '\0';
787 v = rb_str_new2(p);
788 break;
789 }
790 if (*p == '-') {
791 hyphen = TRUE;
792 }
793 else if (*p != '_' && !ISALNUM(*p)) {
794 VALUE name_error[2];
795 name_error[0] =
796 rb_str_new2("invalid name for global variable - ");
797 if (!(p = strchr(p, '='))) {
798 rb_str_cat2(name_error[0], s);
799 }
800 else {
801 rb_str_cat(name_error[0], s, p - s);
802 }
803 name_error[1] = args[-1];
805 }
806 }
807 s[0] = '$';
808 if (hyphen) {
809 for (p = s + 1; *p; ++p) {
810 if (*p == '-')
811 *p = '_';
812 }
813 }
814 rb_gv_set(s, v);
815 }
816 n = RARRAY_LEN(argv) - n;
817 while (n--) {
819 }
820 *sflag = -1;
821 }
822}
823
824static long proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt);
825
826static void
827moreswitches(const char *s, ruby_cmdline_options_t *opt, int envopt)
828{
829 long argc, i, len;
830 char **argv, *p;
831 const char *ap = 0;
832 VALUE argstr, argary;
833 void *ptr;
834
835 while (ISSPACE(*s)) s++;
836 if (!*s) return;
837 argstr = rb_str_tmp_new((len = strlen(s)) + (envopt!=0));
838 argary = rb_str_tmp_new(0);
839
840 p = RSTRING_PTR(argstr);
841 if (envopt) *p++ = ' ';
842 memcpy(p, s, len + 1);
843 ap = 0;
844 rb_str_cat(argary, (char *)&ap, sizeof(ap));
845 while (*p) {
846 ap = p;
847 rb_str_cat(argary, (char *)&ap, sizeof(ap));
848 while (*p && !ISSPACE(*p)) ++p;
849 if (!*p) break;
850 *p++ = '\0';
851 while (ISSPACE(*p)) ++p;
852 }
853 argc = RSTRING_LEN(argary) / sizeof(ap);
854 ap = 0;
855 rb_str_cat(argary, (char *)&ap, sizeof(ap));
856 argv = ptr = ALLOC_N(char *, argc);
857 MEMMOVE(argv, RSTRING_PTR(argary), char *, argc);
858
859 while ((i = proc_options(argc, argv, opt, envopt)) > 1 && envopt && (argc -= i) > 0) {
860 argv += i;
861 if (**argv != '-') {
862 *--*argv = '-';
863 }
864 if ((*argv)[1]) {
865 ++argc;
866 --argv;
867 }
868 }
869
871 /* get rid of GC */
872 rb_str_resize(argary, 0);
873 rb_str_resize(argstr, 0);
874}
875
876static int
877name_match_p(const char *name, const char *str, size_t len)
878{
879 if (len == 0) return 0;
880 while (1) {
881 while (TOLOWER(*str) == *name) {
882 if (!--len || !*++str) return 1;
883 ++name;
884 }
885 if (*str != '-' && *str != '_') return 0;
886 while (ISALNUM(*name)) name++;
887 if (*name != '-' && *name != '_') return 0;
888 ++name;
889 ++str;
890 }
891}
892
893#define NAME_MATCH_P(name, str, len) \
894 ((len) < (int)sizeof(name) && name_match_p((name), (str), (len)))
895
896#define UNSET_WHEN(name, bit, str, len) \
897 if (NAME_MATCH_P((name), (str), (len))) { \
898 *(unsigned int *)arg &= ~(bit); \
899 return; \
900 }
901
902#define SET_WHEN(name, bit, str, len) \
903 if (NAME_MATCH_P((name), (str), (len))) { \
904 *(unsigned int *)arg |= (bit); \
905 return; \
906 }
907
908#define LITERAL_NAME_ELEMENT(name) #name
909
910static void
911feature_option(const char *str, int len, void *arg, const unsigned int enable)
912{
913 static const char list[] = EACH_FEATURES(LITERAL_NAME_ELEMENT, ", ");
914 ruby_features_t *argp = arg;
915 unsigned int mask = ~0U;
916 unsigned int set = 0U;
917#if AMBIGUOUS_FEATURE_NAMES
918 int matched = 0;
919# define FEATURE_FOUND ++matched
920#else
921# define FEATURE_FOUND goto found
922#endif
923#define SET_FEATURE(bit) \
924 if (NAME_MATCH_P(#bit, str, len)) {set |= mask = FEATURE_BIT(bit); FEATURE_FOUND;}
926 if (NAME_MATCH_P("all", str, len)) {
927 goto found;
928 }
929#if AMBIGUOUS_FEATURE_NAMES
930 if (matched == 1) goto found;
931 if (matched > 1) {
932 VALUE mesg = rb_sprintf("ambiguous feature: `%.*s' (", len, str);
933#define ADD_FEATURE_NAME(bit) \
934 if (FEATURE_BIT(bit) & set) { \
935 rb_str_cat_cstr(mesg, #bit); \
936 if (--matched) rb_str_cat_cstr(mesg, ", "); \
937 }
938 EACH_FEATURES(ADD_FEATURE_NAME, ;);
939 rb_str_cat_cstr(mesg, ")");
941#undef ADD_FEATURE_NAME
942 }
943#endif
944 rb_warn("unknown argument for --%s: `%.*s'",
945 enable ? "enable" : "disable", len, str);
946 rb_warn("features are [%.*s].", (int)strlen(list), list);
947 return;
948
949 found:
950 FEATURE_SET_TO(*argp, mask, (mask & enable));
951 return;
952}
953
954static void
955enable_option(const char *str, int len, void *arg)
956{
957 feature_option(str, len, arg, ~0U);
958}
959
960static void
961disable_option(const char *str, int len, void *arg)
962{
963 feature_option(str, len, arg, 0U);
964}
965
967int ruby_env_debug_option(const char *str, int len, void *arg);
968
969static void
970debug_option(const char *str, int len, void *arg)
971{
972 static const char list[] = EACH_DEBUG_FEATURES(LITERAL_NAME_ELEMENT, ", ");
973 ruby_features_t *argp = arg;
974#define SET_WHEN_DEBUG(bit) \
975 if (NAME_MATCH_P(#bit, str, len)) { \
976 FEATURE_SET(*argp, DEBUG_BIT(bit)); \
977 return; \
978 }
980#ifdef RUBY_DEVEL
981 if (ruby_patchlevel < 0 && ruby_env_debug_option(str, len, 0)) return;
982#endif
983 rb_warn("unknown argument for --debug: `%.*s'", len, str);
984 rb_warn("debug features are [%.*s].", (int)strlen(list), list);
985}
986
987static void
988dump_option(const char *str, int len, void *arg)
989{
990 static const char list[] = EACH_DUMPS(LITERAL_NAME_ELEMENT, ", ");
991#define SET_WHEN_DUMP(bit) SET_WHEN(#bit, DUMP_BIT(bit), str, len)
993 rb_warn("don't know how to dump `%.*s',", len, str);
994 rb_warn("but only [%.*s].", (int)strlen(list), list);
995}
996
997static void
998set_option_encoding_once(const char *type, VALUE *name, const char *e, long elen)
999{
1000 VALUE ename;
1001
1002 if (!elen) elen = strlen(e);
1003 ename = rb_str_new(e, elen);
1004
1005 if (*name &&
1006 rb_funcall(ename, rb_intern("casecmp"), 1, *name) != INT2FIX(0)) {
1008 "%s already set to %"PRIsVALUE, type, *name);
1009 }
1010 *name = ename;
1011}
1012
1013#define set_internal_encoding_once(opt, e, elen) \
1014 set_option_encoding_once("default_internal", &(opt)->intern.enc.name, (e), (elen))
1015#define set_external_encoding_once(opt, e, elen) \
1016 set_option_encoding_once("default_external", &(opt)->ext.enc.name, (e), (elen))
1017#define set_source_encoding_once(opt, e, elen) \
1018 set_option_encoding_once("source", &(opt)->src.enc.name, (e), (elen))
1019
1020#if USE_MJIT
1021static void
1022setup_mjit_options(const char *s, struct mjit_options *mjit_opt)
1023{
1024#define opt_match(s, l, name) \
1025 ((((l) > rb_strlen_lit(name)) ? (s)[rb_strlen_lit(name)] == '=' : \
1026 (l) == rb_strlen_lit(name)) && \
1027 memcmp((s), name, rb_strlen_lit(name)) == 0 && \
1028 (((s) += rb_strlen_lit(name)), 1))
1029#define opt_match_noarg(s, l, name) \
1030 opt_match(s, l, name) && (*(s) ? (rb_warn("argument to --jit-" name " is ignored"), 1) : 1)
1031#define opt_match_arg(s, l, name) \
1032 opt_match(s, l, name) && (*(s) ? 1 : (rb_raise(rb_eRuntimeError, "--jit-" name " needs an argument"), 0))
1033 if (*s != '-') return;
1034 const size_t l = strlen(++s);
1035 if (*s == 0) return;
1036 else if (opt_match_noarg(s, l, "warnings")) {
1037 mjit_opt->warnings = 1;
1038 }
1039 else if (opt_match(s, l, "debug")) {
1040 if (*s)
1041 mjit_opt->debug_flags = strdup(s + 1);
1042 else
1043 mjit_opt->debug = 1;
1044 }
1045 else if (opt_match_noarg(s, l, "wait")) {
1046 mjit_opt->wait = 1;
1047 }
1048 else if (opt_match_noarg(s, l, "save-temps")) {
1049 mjit_opt->save_temps = 1;
1050 }
1051 else if (opt_match(s, l, "verbose")) {
1052 mjit_opt->verbose = *s ? atoi(s + 1) : 1;
1053 }
1054 else if (opt_match_arg(s, l, "max-cache")) {
1055 mjit_opt->max_cache_size = atoi(s + 1);
1056 }
1057 else if (opt_match_arg(s, l, "min-calls")) {
1058 mjit_opt->min_calls = atoi(s + 1);
1059 }
1060 else {
1062 "invalid MJIT option `%s' (--help will show valid MJIT options)", s);
1063 }
1064}
1065#endif
1066
1067static long
1068proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt)
1069{
1070 long n, argc0 = argc;
1071 const char *s;
1072 int warning = opt->warning;
1073
1074 if (argc <= 0 || !argv)
1075 return 0;
1076
1077 for (argc--, argv++; argc > 0; argc--, argv++) {
1078 const char *const arg = argv[0];
1079 if (!arg || arg[0] != '-' || !arg[1])
1080 break;
1081
1082 s = arg + 1;
1083 reswitch:
1084 switch (*s) {
1085 case 'a':
1086 if (envopt) goto noenvopt;
1087 opt->do_split = TRUE;
1088 s++;
1089 goto reswitch;
1090
1091 case 'p':
1092 if (envopt) goto noenvopt;
1093 opt->do_print = TRUE;
1094 /* through */
1095 case 'n':
1096 if (envopt) goto noenvopt;
1097 opt->do_loop = TRUE;
1098 s++;
1099 goto reswitch;
1100
1101 case 'd':
1102 ruby_debug = Qtrue;
1104 s++;
1105 goto reswitch;
1106
1107 case 'y':
1108 if (envopt) goto noenvopt;
1109 opt->dump |= DUMP_BIT(yydebug);
1110 s++;
1111 goto reswitch;
1112
1113 case 'v':
1114 if (opt->verbose) {
1115 s++;
1116 goto reswitch;
1117 }
1118 opt->dump |= DUMP_BIT(version_v);
1119 opt->verbose = 1;
1120 case 'w':
1121 if (!opt->warning) {
1122 warning = 1;
1124 }
1126 s++;
1127 goto reswitch;
1128
1129 case 'W':
1130 if (s[1] == ':') {
1131 unsigned int bits = 0;
1132 static const char no_prefix[] = "no-";
1133 int enable = strncmp(s += 2, no_prefix, sizeof(no_prefix)-1) != 0;
1134 if (!enable) s += sizeof(no_prefix)-1;
1135 size_t len = strlen(s);
1136 if (NAME_MATCH_P("deprecated", s, len)) {
1138 }
1139 else if (NAME_MATCH_P("experimental", s, len)) {
1141 }
1142 else {
1143 rb_warn("unknown warning category: `%s'", s);
1144 }
1145 if (bits) FEATURE_SET_TO(opt->warn, bits, enable ? bits : 0);
1146 break;
1147 }
1148 {
1149 size_t numlen;
1150 int v = 2; /* -W as -W2 */
1151
1152 if (*++s) {
1153 v = scan_oct(s, 1, &numlen);
1154 if (numlen == 0)
1155 v = 2;
1156 s += numlen;
1157 }
1158 if (!opt->warning) {
1159 switch (v) {
1160 case 0:
1162 break;
1163 case 1:
1165 break;
1166 default:
1168 break;
1169 }
1170 }
1171 warning = 1;
1172 switch (v) {
1173 case 0:
1175 break;
1176 case 1:
1178 break;
1179 default:
1181 break;
1182 }
1183 }
1184 goto reswitch;
1185
1186 case 'c':
1187 if (envopt) goto noenvopt;
1188 opt->dump |= DUMP_BIT(syntax);
1189 s++;
1190 goto reswitch;
1191
1192 case 's':
1193 if (envopt) goto noenvopt;
1194 forbid_setid("-s");
1195 if (!opt->sflag) opt->sflag = 1;
1196 s++;
1197 goto reswitch;
1198
1199 case 'h':
1200 if (envopt) goto noenvopt;
1201 opt->dump |= DUMP_BIT(usage);
1202 goto switch_end;
1203
1204 case 'l':
1205 if (envopt) goto noenvopt;
1206 opt->do_line = TRUE;
1208 s++;
1209 goto reswitch;
1210
1211 case 'S':
1212 if (envopt) goto noenvopt;
1213 forbid_setid("-S");
1214 opt->do_search = TRUE;
1215 s++;
1216 goto reswitch;
1217
1218 case 'e':
1219 if (envopt) goto noenvopt;
1220 forbid_setid("-e");
1221 if (!*++s) {
1222 if (!--argc)
1223 rb_raise(rb_eRuntimeError, "no code specified for -e");
1224 s = *++argv;
1225 }
1226 if (!opt->e_script) {
1227 opt->e_script = rb_str_new(0, 0);
1228 if (opt->script == 0)
1229 opt->script = "-e";
1230 }
1231 rb_str_cat2(opt->e_script, s);
1232 rb_str_cat2(opt->e_script, "\n");
1233 break;
1234
1235 case 'r':
1236 forbid_setid("-r");
1237 if (*++s) {
1238 add_modules(&opt->req_list, s);
1239 }
1240 else if (argc > 1) {
1241 add_modules(&opt->req_list, argv[1]);
1242 argc--, argv++;
1243 }
1244 break;
1245
1246 case 'i':
1247 if (envopt) goto noenvopt;
1248 forbid_setid("-i");
1249 ruby_set_inplace_mode(s + 1);
1250 break;
1251
1252 case 'x':
1253 if (envopt) goto noenvopt;
1254 forbid_setid("-x");
1255 opt->xflag = TRUE;
1256 s++;
1257 if (*s && chdir(s) < 0) {
1258 rb_fatal("Can't chdir to %s", s);
1259 }
1260 break;
1261
1262 case 'C':
1263 case 'X':
1264 if (envopt) goto noenvopt;
1265 if (!*++s && (!--argc || !(s = *++argv) || !*s)) {
1266 rb_fatal("Can't chdir");
1267 }
1268 if (chdir(s) < 0) {
1269 rb_fatal("Can't chdir to %s", s);
1270 }
1271 break;
1272
1273 case 'F':
1274 if (envopt) goto noenvopt;
1275 if (*++s) {
1276 rb_fs = rb_reg_new(s, strlen(s), 0);
1277 }
1278 break;
1279
1280 case 'E':
1281 if (!*++s && (!--argc || !(s = *++argv))) {
1282 rb_raise(rb_eRuntimeError, "missing argument for -E");
1283 }
1284 goto encoding;
1285
1286 case 'U':
1287 set_internal_encoding_once(opt, "UTF-8", 0);
1288 ++s;
1289 goto reswitch;
1290
1291 case 'K':
1292 if (*++s) {
1293 const char *enc_name = 0;
1294 switch (*s) {
1295 case 'E': case 'e':
1296 enc_name = "EUC-JP";
1297 break;
1298 case 'S': case 's':
1299 enc_name = "Windows-31J";
1300 break;
1301 case 'U': case 'u':
1302 enc_name = "UTF-8";
1303 break;
1304 case 'N': case 'n': case 'A': case 'a':
1305 enc_name = "ASCII-8BIT";
1306 break;
1307 }
1308 if (enc_name) {
1309 opt->src.enc.name = rb_str_new2(enc_name);
1310 if (!opt->ext.enc.name)
1311 opt->ext.enc.name = opt->src.enc.name;
1312 }
1313 s++;
1314 }
1315 goto reswitch;
1316
1317 case 'I':
1318 forbid_setid("-I");
1319 if (*++s)
1321 else if (argc > 1) {
1323 argc--, argv++;
1324 }
1325 break;
1326
1327 case '0':
1328 if (envopt) goto noenvopt;
1329 {
1330 size_t numlen;
1331 int v;
1332 char c;
1333
1334 v = scan_oct(s, 4, &numlen);
1335 s += numlen;
1336 if (v > 0377)
1337 rb_rs = Qnil;
1338 else if (v == 0 && numlen >= 2) {
1339 rb_rs = rb_str_new2("");
1340 }
1341 else {
1342 c = v & 0xff;
1343 rb_rs = rb_str_new(&c, 1);
1344 }
1345 }
1346 goto reswitch;
1347
1348 case '-':
1349 if (!s[1] || (s[1] == '\r' && !s[2])) {
1350 argc--, argv++;
1351 goto switch_end;
1352 }
1353 s++;
1354
1355# define is_option_end(c, allow_hyphen) \
1356 (!(c) || ((allow_hyphen) && (c) == '-') || (c) == '=')
1357# define check_envopt(name, allow_envopt) \
1358 (((allow_envopt) || !envopt) ? (void)0 : \
1359 rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --" name))
1360# define need_argument(name, s, needs_arg, next_arg) \
1361 ((*(s) ? !*++(s) : (next_arg) && (!argc || !((s) = argv[1]) || (--argc, ++argv, 0))) && (needs_arg) ? \
1362 rb_raise(rb_eRuntimeError, "missing argument for --" name) \
1363 : (void)0)
1364# define is_option_with_arg(name, allow_hyphen, allow_envopt) \
1365 is_option_with_optarg(name, allow_hyphen, allow_envopt, Qtrue, Qtrue)
1366# define is_option_with_optarg(name, allow_hyphen, allow_envopt, needs_arg, next_arg) \
1367 (strncmp((name), s, n = sizeof(name) - 1) == 0 && is_option_end(s[n], (allow_hyphen)) ? \
1368 (check_envopt(name, (allow_envopt)), s += n, \
1369 need_argument(name, s, needs_arg, next_arg), 1) : 0)
1370
1371 if (strcmp("copyright", s) == 0) {
1372 if (envopt) goto noenvopt_long;
1373 opt->dump |= DUMP_BIT(copyright);
1374 }
1375 else if (is_option_with_optarg("debug", Qtrue, Qtrue, Qfalse, Qfalse)) {
1376 if (s && *s) {
1377 ruby_each_words(s, debug_option, &opt->features);
1378 }
1379 else {
1380 ruby_debug = Qtrue;
1382 }
1383 }
1384 else if (is_option_with_arg("enable", Qtrue, Qtrue)) {
1385 ruby_each_words(s, enable_option, &opt->features);
1386 }
1387 else if (is_option_with_arg("disable", Qtrue, Qtrue)) {
1388 ruby_each_words(s, disable_option, &opt->features);
1389 }
1390 else if (is_option_with_arg("encoding", Qfalse, Qtrue)) {
1391 char *p;
1392 encoding:
1393 do {
1394# define set_encoding_part(type) \
1395 if (!(p = strchr(s, ':'))) { \
1396 set_##type##_encoding_once(opt, s, 0); \
1397 break; \
1398 } \
1399 else if (p > s) { \
1400 set_##type##_encoding_once(opt, s, p-s); \
1401 }
1402 set_encoding_part(external);
1403 if (!*(s = ++p)) break;
1404 set_encoding_part(internal);
1405 if (!*(s = ++p)) break;
1406#if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
1407 set_encoding_part(source);
1408 if (!*(s = ++p)) break;
1409#endif
1410 rb_raise(rb_eRuntimeError, "extra argument for %s: %s",
1411 (arg[1] == '-' ? "--encoding" : "-E"), s);
1412# undef set_encoding_part
1413 } while (0);
1414 }
1415 else if (is_option_with_arg("internal-encoding", Qfalse, Qtrue)) {
1416 set_internal_encoding_once(opt, s, 0);
1417 }
1418 else if (is_option_with_arg("external-encoding", Qfalse, Qtrue)) {
1419 set_external_encoding_once(opt, s, 0);
1420 }
1421#if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING
1422 else if (is_option_with_arg("source-encoding", Qfalse, Qtrue)) {
1423 set_source_encoding_once(opt, s, 0);
1424 }
1425#endif
1426 else if (strcmp("version", s) == 0) {
1427 if (envopt) goto noenvopt_long;
1428 opt->dump |= DUMP_BIT(version);
1429 }
1430 else if (strcmp("verbose", s) == 0) {
1431 opt->verbose = 1;
1433 }
1434 else if (strncmp("jit", s, 3) == 0) {
1435#if USE_MJIT
1436 FEATURE_SET(opt->features, FEATURE_BIT(jit));
1437 setup_mjit_options(s + 3, &opt->mjit);
1438#else
1439 rb_warn("MJIT support is disabled.");
1440#endif
1441 }
1442 else if (strcmp("yydebug", s) == 0) {
1443 if (envopt) goto noenvopt_long;
1444 opt->dump |= DUMP_BIT(yydebug);
1445 }
1446 else if (is_option_with_arg("dump", Qfalse, Qfalse)) {
1447 ruby_each_words(s, dump_option, &opt->dump);
1448 }
1449 else if (strcmp("help", s) == 0) {
1450 if (envopt) goto noenvopt_long;
1451 opt->dump |= DUMP_BIT(help);
1452 goto switch_end;
1453 }
1454 else if (is_option_with_arg("backtrace-limit", Qfalse, Qfalse)) {
1455 char *e;
1456 long n = strtol(s, &e, 10);
1457 if (errno == ERANGE || n < 0 || *e) rb_raise(rb_eRuntimeError, "wrong limit for backtrace length");
1459 }
1460 else {
1462 "invalid option --%s (-h will show valid options)", s);
1463 }
1464 break;
1465
1466 case '\r':
1467 if (!s[1])
1468 break;
1469
1470 default:
1471 {
1473 "invalid option -%c (-h will show valid options)",
1474 (int)(unsigned char)*s);
1475 }
1476 goto switch_end;
1477
1478 noenvopt:
1479 /* "EIdvwWrKU" only */
1480 rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: -%c", *s);
1481 break;
1482
1483 noenvopt_long:
1484 rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --%s", s);
1485 break;
1486
1487 case 0:
1488 break;
1489# undef is_option_end
1490# undef check_envopt
1491# undef need_argument
1492# undef is_option_with_arg
1493# undef is_option_with_optarg
1494 }
1495 }
1496
1497 switch_end:
1498 if (warning) opt->warning = warning;
1499 return argc0 - argc;
1500}
1501
1502void Init_builtin_features(void);
1503
1504static void
1505ruby_init_prelude(void)
1506{
1508 rb_const_remove(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"));
1509}
1510
1511void rb_call_builtin_inits(void);
1512
1513static void
1514ruby_opt_init(ruby_cmdline_options_t *opt)
1515{
1516 if (opt->dump & dump_exit_bits) return;
1517
1518 if (opt->features.set & FEATURE_BIT(gems)) {
1519 rb_define_module("Gem");
1520 if (opt->features.set & FEATURE_BIT(did_you_mean)) {
1521 rb_define_module("DidYouMean");
1522 }
1523 }
1524
1526
1527 Init_ext(); /* load statically linked extensions before rubygems */
1529 ruby_init_prelude();
1530
1532 require_libraries(&opt->req_list);
1533}
1534
1535static int
1536opt_enc_index(VALUE enc_name)
1537{
1538 const char *s = RSTRING_PTR(enc_name);
1539 int i = rb_enc_find_index(s);
1540
1541 if (i < 0) {
1542 rb_raise(rb_eRuntimeError, "unknown encoding name - %s", s);
1543 }
1544 else if (rb_enc_dummy_p(rb_enc_from_index(i))) {
1545 rb_raise(rb_eRuntimeError, "dummy encoding is not acceptable - %s ", s);
1546 }
1547 return i;
1548}
1549
1550#define rb_progname (GET_VM()->progname)
1551#define rb_orig_progname (GET_VM()->orig_progname)
1554
1555static VALUE
1556false_value(ID _x, VALUE *_y)
1557{
1558 return Qfalse;
1559}
1560
1561static VALUE
1562true_value(ID _x, VALUE *_y)
1563{
1564 return Qtrue;
1565}
1566
1567#define rb_define_readonly_boolean(name, val) \
1568 rb_define_virtual_variable((name), (val) ? true_value : false_value, 0)
1569
1570static VALUE
1571uscore_get(void)
1572{
1573 VALUE line;
1574
1575 line = rb_lastline_get();
1576 if (!RB_TYPE_P(line, T_STRING)) {
1577 rb_raise(rb_eTypeError, "$_ value need to be String (%s given)",
1578 NIL_P(line) ? "nil" : rb_obj_classname(line));
1579 }
1580 return line;
1581}
1582
1583/*
1584 * call-seq:
1585 * sub(pattern, replacement) -> $_
1586 * sub(pattern) {|...| block } -> $_
1587 *
1588 * Equivalent to <code>$_.sub(<i>args</i>)</code>, except that
1589 * <code>$_</code> will be updated if substitution occurs.
1590 * Available only when -p/-n command line option specified.
1591 */
1592
1593static VALUE
1594rb_f_sub(int argc, VALUE *argv, VALUE _)
1595{
1596 VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("sub"), argc, argv);
1598 return str;
1599}
1600
1601/*
1602 * call-seq:
1603 * gsub(pattern, replacement) -> $_
1604 * gsub(pattern) {|...| block } -> $_
1605 *
1606 * Equivalent to <code>$_.gsub...</code>, except that <code>$_</code>
1607 * will be updated if substitution occurs.
1608 * Available only when -p/-n command line option specified.
1609 *
1610 */
1611
1612static VALUE
1613rb_f_gsub(int argc, VALUE *argv, VALUE _)
1614{
1615 VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("gsub"), argc, argv);
1617 return str;
1618}
1619
1620/*
1621 * call-seq:
1622 * chop -> $_
1623 *
1624 * Equivalent to <code>($_.dup).chop!</code>, except <code>nil</code>
1625 * is never returned. See String#chop!.
1626 * Available only when -p/-n command line option specified.
1627 *
1628 */
1629
1630static VALUE
1631rb_f_chop(VALUE _)
1632{
1633 VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("chop"), 0, 0);
1635 return str;
1636}
1637
1638
1639/*
1640 * call-seq:
1641 * chomp -> $_
1642 * chomp(string) -> $_
1643 *
1644 * Equivalent to <code>$_ = $_.chomp(<em>string</em>)</code>. See
1645 * String#chomp.
1646 * Available only when -p/-n command line option specified.
1647 *
1648 */
1649
1650static VALUE
1651rb_f_chomp(int argc, VALUE *argv, VALUE _)
1652{
1653 VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("chomp"), argc, argv);
1655 return str;
1656}
1657
1658static void
1659setup_pager_env(void)
1660{
1661 if (!getenv("LESS")) ruby_setenv("LESS", "-R"); // Output "raw" control characters.
1662}
1663
1664#ifdef _WIN32
1665static int
1666tty_enabled(void)
1667{
1668 HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
1669 DWORD m;
1670 if (!GetConsoleMode(h, &m)) return 0;
1671# ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
1672# define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4
1673# endif
1674 if (!(m & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) return 0;
1675 return 1;
1676}
1677#elif !defined(HAVE_WORKING_FORK)
1678# define tty_enabled() 0
1679#endif
1680
1681static VALUE
1682copy_str(VALUE str, rb_encoding *enc, bool intern)
1683{
1684 if (!intern) {
1686 return 0;
1687 return rb_enc_associate(rb_str_dup(str), enc);
1688 }
1690}
1691
1692static VALUE
1693process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
1694{
1695 rb_ast_t *ast = 0;
1696 VALUE parser;
1697 VALUE script_name;
1698 const rb_iseq_t *iseq;
1699 rb_encoding *enc, *lenc;
1700#if UTF8_PATH
1701 rb_encoding *ienc = 0;
1702 rb_encoding *const uenc = rb_utf8_encoding();
1703#endif
1704 const char *s;
1705 char fbuf[MAXPATHLEN];
1706 int i = (int)proc_options(argc, argv, opt, 0);
1707 unsigned int dump = opt->dump & dump_exit_bits;
1708 rb_vm_t *vm = GET_VM();
1709 const long loaded_before_enc = RARRAY_LEN(vm->loaded_features);
1710
1711 if (opt->dump & (DUMP_BIT(usage)|DUMP_BIT(help))) {
1712 int tty = isatty(1);
1713 const char *const progname =
1714 (argc > 0 && argv && argv[0] ? argv[0] :
1715 origarg.argc > 0 && origarg.argv && origarg.argv[0] ? origarg.argv[0] :
1716 ruby_engine);
1717 int columns = 0;
1718 if ((opt->dump & DUMP_BIT(help)) && tty) {
1719 const char *pager_env = getenv("RUBY_PAGER");
1720 if (!pager_env) pager_env = getenv("PAGER");
1721 if (pager_env && *pager_env && isatty(0)) {
1722 const char *columns_env = getenv("COLUMNS");
1723 if (columns_env) columns = atoi(columns_env);
1724 VALUE pager = rb_str_new_cstr(pager_env);
1725#ifdef HAVE_WORKING_FORK
1726 int fds[2];
1727 if (rb_pipe(fds) == 0) {
1728 rb_pid_t pid = rb_fork();
1729 if (pid > 0) {
1730 /* exec PAGER with reading from child */
1731 dup2(fds[0], 0);
1732 }
1733 else if (pid == 0) {
1734 /* send the help message to the parent PAGER */
1735 dup2(fds[1], 1);
1736 dup2(fds[1], 2);
1737 }
1738 close(fds[0]);
1739 close(fds[1]);
1740 if (pid > 0) {
1741 setup_pager_env();
1742 rb_f_exec(1, &pager);
1743 kill(SIGTERM, pid);
1744 rb_waitpid(pid, 0, 0);
1745 }
1746 }
1747#else
1748 setup_pager_env();
1749 VALUE port = rb_io_popen(pager, rb_str_new_lit("w"), Qnil, Qnil);
1750 if (!NIL_P(port)) {
1751 int oldout = dup(1);
1752 int olderr = dup(2);
1753 int fd = RFILE(port)->fptr->fd;
1754 tty = tty_enabled();
1755 dup2(fd, 1);
1756 dup2(fd, 2);
1757 usage(progname, 1, tty, columns);
1758 fflush(stdout);
1759 dup2(oldout, 1);
1760 dup2(olderr, 2);
1761 rb_io_close(port);
1762 return Qtrue;
1763 }
1764#endif
1765 }
1766 }
1767 usage(progname, (opt->dump & DUMP_BIT(help)), tty, columns);
1768 return Qtrue;
1769 }
1770
1771 argc -= i;
1772 argv += i;
1773
1774 if ((opt->features.set & FEATURE_BIT(rubyopt)) && (s = getenv("RUBYOPT"))) {
1775 VALUE src_enc_name = opt->src.enc.name;
1776 VALUE ext_enc_name = opt->ext.enc.name;
1777 VALUE int_enc_name = opt->intern.enc.name;
1778 ruby_features_t feat = opt->features;
1779 ruby_features_t warn = opt->warn;
1780
1781 opt->src.enc.name = opt->ext.enc.name = opt->intern.enc.name = 0;
1782 moreswitches(s, opt, 1);
1783 if (src_enc_name)
1784 opt->src.enc.name = src_enc_name;
1785 if (ext_enc_name)
1786 opt->ext.enc.name = ext_enc_name;
1787 if (int_enc_name)
1788 opt->intern.enc.name = int_enc_name;
1789 FEATURE_SET_RESTORE(opt->features, feat);
1790 FEATURE_SET_RESTORE(opt->warn, warn);
1791 }
1792
1793 if (opt->src.enc.name)
1794 /* cannot set deprecated category, as enabling deprecation warnings based on flags
1795 * has not happened yet.
1796 */
1797 rb_warning("-K is specified; it is for 1.8 compatibility and may cause odd behavior");
1798
1799#if USE_MJIT
1800 if (opt->features.set & FEATURE_BIT(jit)) {
1801 opt->mjit.on = TRUE; /* set mjit.on for ruby_show_version() API and check to call mjit_init() */
1802 }
1803#endif
1804 if (opt->dump & (DUMP_BIT(version) | DUMP_BIT(version_v))) {
1805#if USE_MJIT
1806 mjit_opts.on = opt->mjit.on; /* used by ruby_show_version(). mjit_init() still can't be called here. */
1807#endif
1809 if (opt->dump & DUMP_BIT(version)) return Qtrue;
1810 }
1811 if (opt->dump & DUMP_BIT(copyright)) {
1813 return Qtrue;
1814 }
1815
1816 if (!opt->e_script) {
1817 if (argc <= 0) { /* no more args */
1818 if (opt->verbose)
1819 return Qtrue;
1820 opt->script = "-";
1821 }
1822 else {
1823 opt->script = argv[0];
1824 if (!opt->script || opt->script[0] == '\0') {
1825 opt->script = "-";
1826 }
1827 else if (opt->do_search) {
1828 char *path = getenv("RUBYPATH");
1829
1830 opt->script = 0;
1831 if (path) {
1832 opt->script = dln_find_file_r(argv[0], path, fbuf, sizeof(fbuf));
1833 }
1834 if (!opt->script) {
1835 opt->script = dln_find_file_r(argv[0], getenv(PATH_ENV), fbuf, sizeof(fbuf));
1836 }
1837 if (!opt->script)
1838 opt->script = argv[0];
1839 }
1840 argc--;
1841 argv++;
1842 }
1843 if (opt->script[0] == '-' && !opt->script[1]) {
1844 forbid_setid("program input from stdin");
1845 }
1846 }
1847
1848 opt->script_name = rb_str_new_cstr(opt->script);
1849 opt->script = RSTRING_PTR(opt->script_name);
1850
1851#if _WIN32
1852 translit_char_bin(RSTRING_PTR(opt->script_name), '\\', '/');
1853#elif defined DOSISH
1854 translit_char(RSTRING_PTR(opt->script_name), '\\', '/');
1855#endif
1856
1859
1860#if USE_MJIT
1861 if (opt->mjit.on)
1862 /* Using TMP_RUBY_PREFIX created by ruby_init_loadpath(). */
1863 mjit_init(&opt->mjit);
1864#endif
1865
1867 Init_enc();
1868 lenc = rb_locale_encoding();
1871 parser = rb_parser_new();
1872 if (opt->dump & DUMP_BIT(yydebug)) {
1874 }
1875 if (opt->ext.enc.name != 0) {
1876 opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
1877 }
1878 if (opt->intern.enc.name != 0) {
1879 opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
1880 }
1881 if (opt->src.enc.name != 0) {
1882 opt->src.enc.index = opt_enc_index(opt->src.enc.name);
1884 }
1885 if (opt->ext.enc.index >= 0) {
1886 enc = rb_enc_from_index(opt->ext.enc.index);
1887 }
1888 else {
1889 enc = IF_UTF8_PATH(uenc, lenc);
1890 }
1892 if (opt->intern.enc.index >= 0) {
1893 enc = rb_enc_from_index(opt->intern.enc.index);
1895 opt->intern.enc.index = -1;
1896#if UTF8_PATH
1897 ienc = enc;
1898#endif
1899 }
1900 script_name = opt->script_name;
1901 rb_enc_associate(opt->script_name, IF_UTF8_PATH(uenc, lenc));
1902#if UTF8_PATH
1903 if (uenc != lenc) {
1904 opt->script_name = str_conv_enc(opt->script_name, uenc, lenc);
1905 opt->script = RSTRING_PTR(opt->script_name);
1906 }
1907#endif
1909 if (IF_UTF8_PATH(uenc != lenc, 1)) {
1910 long i;
1911 VALUE load_path = vm->load_path;
1912 const ID id_initial_load_path_mark = INITIAL_LOAD_PATH_MARK;
1913 int modifiable = FALSE;
1914
1916 for (i = 0; i < RARRAY_LEN(load_path); ++i) {
1917 VALUE path = RARRAY_AREF(load_path, i);
1918 int mark = rb_attr_get(path, id_initial_load_path_mark) == path;
1919#if UTF8_PATH
1920 VALUE newpath = rb_str_conv_enc(path, uenc, lenc);
1921 if (newpath == path) continue;
1922 path = newpath;
1923#else
1924 if (!(path = copy_str(path, lenc, !mark))) continue;
1925#endif
1926 if (mark) rb_ivar_set(path, id_initial_load_path_mark, path);
1927 if (!modifiable) {
1928 rb_ary_modify(load_path);
1929 modifiable = TRUE;
1930 }
1931 RARRAY_ASET(load_path, i, path);
1932 }
1933 if (modifiable) {
1934 rb_ary_replace(vm->load_path_snapshot, load_path);
1935 }
1936 }
1937 {
1938 VALUE loaded_features = vm->loaded_features;
1939 bool modified = false;
1940 for (long i = loaded_before_enc; i < RARRAY_LEN(loaded_features); ++i) {
1941 VALUE path = RARRAY_AREF(loaded_features, i);
1942 if (!(path = copy_str(path, IF_UTF8_PATH(uenc, lenc), true))) continue;
1943 modified = true;
1944 RARRAY_ASET(loaded_features, i, path);
1945 }
1946 if (modified) {
1947 rb_ary_replace(vm->loaded_features_snapshot, loaded_features);
1948 }
1949 }
1950
1951 if (opt->features.mask & COMPILATION_FEATURES) {
1952 VALUE option = rb_hash_new();
1953#define SET_COMPILE_OPTION(h, o, name) \
1954 rb_hash_aset((h), ID2SYM(rb_intern_const(#name)), \
1955 (FEATURE_SET_P(o->features, FEATURE_BIT(name)) ? Qtrue : Qfalse));
1956 SET_COMPILE_OPTION(option, opt, frozen_string_literal);
1957 SET_COMPILE_OPTION(option, opt, debug_frozen_string_literal);
1958 rb_funcallv(rb_cISeq, rb_intern_const("compile_option="), 1, &option);
1959#undef SET_COMPILE_OPTION
1960 }
1962 process_sflag(&opt->sflag);
1963
1964 rb_parser_set_context(parser, 0, TRUE);
1965
1966 if (opt->e_script) {
1967 VALUE progname = rb_progname;
1968 rb_encoding *eenc;
1969 if (opt->src.enc.index >= 0) {
1970 eenc = rb_enc_from_index(opt->src.enc.index);
1971 }
1972 else {
1973 eenc = lenc;
1974#if UTF8_PATH
1975 if (ienc) eenc = ienc;
1976#endif
1977 }
1978#if UTF8_PATH
1979 if (eenc != uenc) {
1980 opt->e_script = str_conv_enc(opt->e_script, uenc, eenc);
1981 }
1982#endif
1983 rb_enc_associate(opt->e_script, eenc);
1984 ruby_opt_init(opt);
1985 ruby_set_script_name(progname);
1986 rb_parser_set_options(parser, opt->do_print, opt->do_loop,
1987 opt->do_line, opt->do_split);
1988 ast = rb_parser_compile_string(parser, opt->script, opt->e_script, 1);
1989 }
1990 else {
1991 VALUE f;
1992 f = open_load_file(script_name, &opt->xflag);
1993 ast = load_file(parser, opt->script_name, f, 1, opt);
1994 }
1996 if (dump & DUMP_BIT(yydebug)) {
1997 dump &= ~DUMP_BIT(yydebug);
1998 if (!dump) return Qtrue;
1999 }
2000
2001 if (opt->ext.enc.index >= 0) {
2002 enc = rb_enc_from_index(opt->ext.enc.index);
2003 }
2004 else {
2005 enc = IF_UTF8_PATH(uenc, lenc);
2006 }
2008 if (opt->intern.enc.index >= 0) {
2009 /* Set in the shebang line */
2010 enc = rb_enc_from_index(opt->intern.enc.index);
2012 }
2013 else if (!rb_default_internal_encoding())
2014 /* Freeze default_internal */
2017
2018 if (!ast->body.root) {
2019 rb_ast_dispose(ast);
2020 return Qfalse;
2021 }
2022
2023 process_sflag(&opt->sflag);
2024 opt->xflag = 0;
2025
2026 if (dump & DUMP_BIT(syntax)) {
2027 printf("Syntax OK\n");
2028 dump &= ~DUMP_BIT(syntax);
2029 if (!dump) return Qtrue;
2030 }
2031
2032 if (opt->do_loop) {
2033 rb_define_global_function("sub", rb_f_sub, -1);
2034 rb_define_global_function("gsub", rb_f_gsub, -1);
2035 rb_define_global_function("chop", rb_f_chop, 0);
2036 rb_define_global_function("chomp", rb_f_chomp, -1);
2037 }
2038
2039 if (dump & (DUMP_BIT(parsetree)|DUMP_BIT(parsetree_with_comment))) {
2040 rb_io_write(rb_stdout, rb_parser_dump_tree(ast->body.root, dump & DUMP_BIT(parsetree_with_comment)));
2042 dump &= ~DUMP_BIT(parsetree)&~DUMP_BIT(parsetree_with_comment);
2043 if (!dump) {
2044 rb_ast_dispose(ast);
2045 return Qtrue;
2046 }
2047 }
2048
2049 {
2050 VALUE path = Qnil;
2051 if (!opt->e_script && strcmp(opt->script, "-")) {
2052 path = rb_realpath_internal(Qnil, script_name, 1);
2053#if UTF8_PATH
2054 if (uenc != lenc) {
2055 path = str_conv_enc(path, uenc, lenc);
2056 }
2057#endif
2058 if (!ENCODING_GET(path)) { /* ASCII-8BIT */
2059 rb_enc_copy(path, opt->script_name);
2060 }
2061 }
2062
2063 rb_binding_t *toplevel_binding;
2064 GetBindingPtr(rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING")),
2065 toplevel_binding);
2066 const struct rb_block *base_block = toplevel_context(toplevel_binding);
2067 iseq = rb_iseq_new_main(&ast->body, opt->script_name, path, vm_block_iseq(base_block));
2068 rb_ast_dispose(ast);
2069 }
2070
2071 if (dump & DUMP_BIT(insns)) {
2074 dump &= ~DUMP_BIT(insns);
2075 if (!dump) return Qtrue;
2076 }
2077 if (opt->dump & dump_exit_bits) return Qtrue;
2078
2082
2083 rb_gvar_ractor_local("$-p");
2084 rb_gvar_ractor_local("$-l");
2085 rb_gvar_ractor_local("$-a");
2086
2087 if ((rb_e_script = opt->e_script) != 0) {
2089 }
2090
2091 {
2092 rb_execution_context_t *ec = GET_EC();
2093
2094 if (opt->e_script) {
2095 /* -e */
2096 rb_exec_event_hook_script_compiled(ec, iseq, opt->e_script);
2097 }
2098 else {
2099 /* file */
2100 rb_exec_event_hook_script_compiled(ec, iseq, Qnil);
2101 }
2102 }
2103 return (VALUE)iseq;
2104}
2105
2106#ifndef DOSISH
2107static void
2108warn_cr_in_shebang(const char *str, long len)
2109{
2110 if (str[len-1] == '\n' && str[len-2] == '\r') {
2111 rb_warn("shebang line ending with \\r may cause problems");
2112 }
2113}
2114#else
2115#define warn_cr_in_shebang(str, len) (void)0
2116#endif
2117
2124};
2125
2126static VALUE
2127load_file_internal(VALUE argp_v)
2128{
2129 struct load_file_arg *argp = (struct load_file_arg *)argp_v;
2130 VALUE parser = argp->parser;
2131 VALUE orig_fname = argp->fname;
2132 int script = argp->script;
2134 VALUE f = argp->f;
2135 int line_start = 1;
2136 rb_ast_t *ast = 0;
2137 rb_encoding *enc;
2138 ID set_encoding;
2139
2140 CONST_ID(set_encoding, "set_encoding");
2141 if (script) {
2142 VALUE c = 1; /* something not nil */
2143 VALUE line;
2144 char *p, *str;
2145 long len;
2146 int no_src_enc = !opt->src.enc.name;
2147 int no_ext_enc = !opt->ext.enc.name;
2148 int no_int_enc = !opt->intern.enc.name;
2149
2150 enc = rb_ascii8bit_encoding();
2151 rb_funcall(f, set_encoding, 1, rb_enc_from_encoding(enc));
2152
2153 if (opt->xflag) {
2154 line_start--;
2155 search_shebang:
2156 while (!NIL_P(line = rb_io_gets(f))) {
2157 line_start++;
2158 RSTRING_GETMEM(line, str, len);
2159 if (len > 2 && str[0] == '#' && str[1] == '!') {
2160 if (line_start == 1) warn_cr_in_shebang(str, len);
2161 if ((p = strstr(str+2, ruby_engine)) != 0) {
2162 goto start_read;
2163 }
2164 }
2165 }
2166 rb_loaderror("no Ruby script found in input");
2167 }
2168
2169 c = rb_io_getbyte(f);
2170 if (c == INT2FIX('#')) {
2171 c = rb_io_getbyte(f);
2172 if (c == INT2FIX('!') && !NIL_P(line = rb_io_gets(f))) {
2173 RSTRING_GETMEM(line, str, len);
2174 warn_cr_in_shebang(str, len);
2175 if ((p = strstr(str, ruby_engine)) == 0) {
2176 /* not ruby script, assume -x flag */
2177 goto search_shebang;
2178 }
2179
2180 start_read:
2181 str += len - 1;
2182 if (*str == '\n') *str-- = '\0';
2183 if (*str == '\r') *str-- = '\0';
2184 /* ruby_engine should not contain a space */
2185 if ((p = strstr(p, " -")) != 0) {
2186 opt->warning = 0;
2187 moreswitches(p + 1, opt, 0);
2188 }
2189
2190 /* push back shebang for pragma may exist in next line */
2191 rb_io_ungetbyte(f, rb_str_new2("!\n"));
2192 }
2193 else if (!NIL_P(c)) {
2194 rb_io_ungetbyte(f, c);
2195 }
2196 rb_io_ungetbyte(f, INT2FIX('#'));
2197 if (no_src_enc && opt->src.enc.name) {
2198 opt->src.enc.index = opt_enc_index(opt->src.enc.name);
2200 }
2201 if (no_ext_enc && opt->ext.enc.name) {
2202 opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
2203 }
2204 if (no_int_enc && opt->intern.enc.name) {
2205 opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
2206 }
2207 }
2208 else if (!NIL_P(c)) {
2209 rb_io_ungetbyte(f, c);
2210 }
2211 if (NIL_P(c)) {
2212 argp->f = f = Qnil;
2213 }
2214 ruby_opt_init(opt);
2215 }
2216 if (opt->src.enc.index >= 0) {
2218 }
2219 else if (f == rb_stdin) {
2220 enc = rb_locale_encoding();
2221 }
2222 else {
2223 enc = rb_utf8_encoding();
2224 }
2226 opt->do_line, opt->do_split);
2227 if (NIL_P(f)) {
2228 f = rb_str_new(0, 0);
2229 rb_enc_associate(f, enc);
2230 return (VALUE)rb_parser_compile_string_path(parser, orig_fname, f, line_start);
2231 }
2232 rb_funcall(f, set_encoding, 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-"));
2233 ast = rb_parser_compile_file_path(parser, orig_fname, f, line_start);
2234 rb_funcall(f, set_encoding, 1, rb_parser_encoding(parser));
2236 /*
2237 * DATA is a File that contains the data section of the executed file.
2238 * To create a data section use <tt>__END__</tt>:
2239 *
2240 * $ cat t.rb
2241 * puts DATA.gets
2242 * __END__
2243 * hello world!
2244 *
2245 * $ ruby t.rb
2246 * hello world!
2247 */
2248 rb_define_global_const("DATA", f);
2249 argp->f = Qnil;
2250 }
2251 return (VALUE)ast;
2252}
2253
2254static VALUE
2255open_load_file(VALUE fname_v, int *xflag)
2256{
2257 const char *fname = (fname_v = rb_str_encode_ospath(fname_v),
2258 StringValueCStr(fname_v));
2259 long flen = RSTRING_LEN(fname_v);
2260 VALUE f;
2261 int e;
2262
2263 if (flen == 1 && fname[0] == '-') {
2264 f = rb_stdin;
2265 }
2266 else {
2267 int fd;
2268 /* open(2) may block if fname is point to FIFO and it's empty. Let's
2269 use O_NONBLOCK. */
2270#if defined O_NONBLOCK && HAVE_FCNTL && !(O_NONBLOCK & O_ACCMODE)
2271 /* TODO: fix conflicting O_NONBLOCK in ruby/win32.h */
2272# define MODE_TO_LOAD (O_RDONLY | O_NONBLOCK)
2273#elif defined O_NDELAY && HAVE_FCNTL && !(O_NDELAY & O_ACCMODE)
2274# define MODE_TO_LOAD (O_RDONLY | O_NDELAY)
2275#else
2276# define MODE_TO_LOAD (O_RDONLY)
2277#endif
2278 int mode = MODE_TO_LOAD;
2279#if defined DOSISH || defined __CYGWIN__
2280# define isdirsep(x) ((x) == '/' || (x) == '\\')
2281 {
2282 static const char exeext[] = ".exe";
2283 enum {extlen = sizeof(exeext)-1};
2284 if (flen > extlen && !isdirsep(fname[flen-extlen-1]) &&
2285 STRNCASECMP(fname+flen-extlen, exeext, extlen) == 0) {
2286 mode |= O_BINARY;
2287 *xflag = 1;
2288 }
2289 }
2290#endif
2291
2292 if ((fd = rb_cloexec_open(fname, mode, 0)) < 0) {
2293 e = errno;
2294 if (!rb_gc_for_fd(e)) {
2295 rb_load_fail(fname_v, strerror(e));
2296 }
2297 if ((fd = rb_cloexec_open(fname, mode, 0)) < 0) {
2298 rb_load_fail(fname_v, strerror(errno));
2299 }
2300 }
2301 rb_update_max_fd(fd);
2302
2303#if defined HAVE_FCNTL && MODE_TO_LOAD != O_RDONLY
2304# ifdef ENOTSUP
2305# define IS_SUPPORTED_OP(e) ((e) != ENOTSUP)
2306# else
2307# define IS_SUPPORTED_OP(e) ((void)(e), 1)
2308# endif
2309 /* disabling O_NONBLOCK */
2310 if (fcntl(fd, F_SETFL, 0) < 0 && IS_SUPPORTED_OP(e = errno)) {
2311 (void)close(fd);
2312 rb_load_fail(fname_v, strerror(e));
2313 }
2314#endif
2315
2316 e = ruby_is_fd_loadable(fd);
2317 if (!e) {
2318 e = errno;
2319 (void)close(fd);
2320 rb_load_fail(fname_v, strerror(e));
2321 }
2322
2323 f = rb_io_fdopen(fd, mode, fname);
2324 if (e < 0) {
2325 /*
2326 We need to wait if FIFO is empty. It's FIFO's semantics.
2327 rb_thread_wait_fd() release GVL. So, it's safe.
2328 */
2330 }
2331 }
2332 return f;
2333}
2334
2335static VALUE
2336restore_load_file(VALUE arg)
2337{
2338 struct load_file_arg *argp = (struct load_file_arg *)arg;
2339 VALUE f = argp->f;
2340
2341 if (!NIL_P(f) && f != rb_stdin) {
2342 rb_io_close(f);
2343 }
2344 return Qnil;
2345}
2346
2347static rb_ast_t *
2349{
2350 struct load_file_arg arg;
2351 arg.parser = parser;
2352 arg.fname = fname;
2353 arg.script = script;
2354 arg.opt = opt;
2355 arg.f = f;
2356 return (rb_ast_t *)rb_ensure(load_file_internal, (VALUE)&arg,
2357 restore_load_file, (VALUE)&arg);
2358}
2359
2360void *
2362{
2363 VALUE fname_v = rb_str_new_cstr(fname);
2364 return rb_load_file_str(fname_v);
2365}
2366
2367void *
2369{
2370 return rb_parser_load_file(rb_parser_new(), fname_v);
2371}
2372
2373void *
2375{
2377 VALUE f = open_load_file(fname_v, &cmdline_options_init(&opt)->xflag);
2378 return load_file(parser, fname_v, f, 0, &opt);
2379}
2380
2381/*
2382 * call-seq:
2383 * Process.argv0 -> frozen_string
2384 *
2385 * Returns the name of the script being executed. The value is not
2386 * affected by assigning a new value to $0.
2387 *
2388 * This method first appeared in Ruby 2.1 to serve as a global
2389 * variable free means to get the script name.
2390 */
2391
2392static VALUE
2393proc_argv0(VALUE process)
2394{
2395 return rb_orig_progname;
2396}
2397
2398static VALUE ruby_setproctitle(VALUE title);
2399
2400/*
2401 * call-seq:
2402 * Process.setproctitle(string) -> string
2403 *
2404 * Sets the process title that appears on the ps(1) command. Not
2405 * necessarily effective on all platforms. No exception will be
2406 * raised regardless of the result, nor will NotImplementedError be
2407 * raised even if the platform does not support the feature.
2408 *
2409 * Calling this method does not affect the value of $0.
2410 *
2411 * Process.setproctitle('myapp: worker #%d' % worker_id)
2412 *
2413 * This method first appeared in Ruby 2.1 to serve as a global
2414 * variable free means to change the process title.
2415 */
2416
2417static VALUE
2418proc_setproctitle(VALUE process, VALUE title)
2419{
2420 return ruby_setproctitle(title);
2421}
2422
2423static VALUE
2424ruby_setproctitle(VALUE title)
2425{
2426 const char *ptr = StringValueCStr(title);
2427 setproctitle("%.*s", RSTRING_LENINT(title), ptr);
2428 return title;
2429}
2430
2431static void
2432set_arg0(VALUE val, ID id, VALUE *_)
2433{
2434 if (origarg.argv == 0)
2435 rb_raise(rb_eRuntimeError, "$0 not initialized");
2436
2437 rb_progname = rb_str_new_frozen(ruby_setproctitle(val));
2438}
2439
2440static inline VALUE
2441external_str_new_cstr(const char *p)
2442{
2443#if UTF8_PATH
2446 return str;
2447#else
2448 return rb_external_str_new_cstr(p);
2449#endif
2450}
2451
2457void
2458ruby_script(const char *name)
2459{
2460 if (name) {
2461 rb_orig_progname = rb_progname = external_str_new_cstr(name);
2463 }
2464}
2465
2470void
2472{
2475}
2476
2477static void
2478init_ids(ruby_cmdline_options_t *opt)
2479{
2480 rb_uid_t uid = getuid();
2481 rb_uid_t euid = geteuid();
2482 rb_gid_t gid = getgid();
2483 rb_gid_t egid = getegid();
2484
2485 if (uid != euid) opt->setids |= 1;
2486 if (egid != gid) opt->setids |= 2;
2487}
2488
2489#undef forbid_setid
2490static void
2491forbid_setid(const char *s, const ruby_cmdline_options_t *opt)
2492{
2493 if (opt->setids & 1)
2494 rb_raise(rb_eSecurityError, "no %s allowed while running setuid", s);
2495 if (opt->setids & 2)
2496 rb_raise(rb_eSecurityError, "no %s allowed while running setgid", s);
2497}
2498
2499static VALUE
2500verbose_getter(ID id, VALUE *ptr)
2501{
2502 return *rb_ruby_verbose_ptr();
2503}
2504
2505static void
2506verbose_setter(VALUE val, ID id, VALUE *variable)
2507{
2508 *rb_ruby_verbose_ptr() = RTEST(val) ? Qtrue : val;
2509}
2510
2511static VALUE
2512opt_W_getter(ID id, VALUE *dmy)
2513{
2515
2516 switch (v) {
2517 case Qnil:
2518 return INT2FIX(0);
2519 case Qfalse:
2520 return INT2FIX(1);
2521 case Qtrue:
2522 return INT2FIX(2);
2523 default:
2524 return Qnil;
2525 }
2526}
2527
2528static VALUE
2529debug_getter(ID id, VALUE *dmy)
2530{
2531 return *rb_ruby_debug_ptr();
2532}
2533
2534static void
2535debug_setter(VALUE val, ID id, VALUE *dmy)
2536{
2537 *rb_ruby_debug_ptr() = val;
2538}
2539
2541void
2543{
2544 rb_define_virtual_variable("$VERBOSE", verbose_getter, verbose_setter);
2545 rb_define_virtual_variable("$-v", verbose_getter, verbose_setter);
2546 rb_define_virtual_variable("$-w", verbose_getter, verbose_setter);
2548 rb_define_virtual_variable("$DEBUG", debug_getter, debug_setter);
2549 rb_define_virtual_variable("$-d", debug_getter, debug_setter);
2550
2551 rb_gvar_ractor_local("$VERBOSE");
2552 rb_gvar_ractor_local("$-v");
2553 rb_gvar_ractor_local("$-w");
2554 rb_gvar_ractor_local("$-W");
2555 rb_gvar_ractor_local("$DEBUG");
2556 rb_gvar_ractor_local("$-d");
2557
2558 rb_define_hooked_variable("$0", &rb_progname, 0, set_arg0);
2559 rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0);
2560
2561 rb_define_module_function(rb_mProcess, "argv0", proc_argv0, 0);
2562 rb_define_module_function(rb_mProcess, "setproctitle", proc_setproctitle, 1);
2563
2564 /*
2565 * ARGV contains the command line arguments used to run ruby.
2566 *
2567 * A library like OptionParser can be used to process command-line
2568 * arguments.
2569 */
2571}
2572
2573void
2575{
2576 int i;
2577 VALUE av = rb_argv;
2578
2579#if defined(USE_DLN_A_OUT)
2580 if (origarg.argc > 0 && origarg.argv)
2581 dln_argv0 = origarg.argv[0];
2582 else if (argc > 0 && argv)
2583 dln_argv0 = argv[0];
2584#endif
2585 rb_ary_clear(av);
2586 for (i = 0; i < argc; i++) {
2587 VALUE arg = external_str_new_cstr(argv[i]);
2588
2589 OBJ_FREEZE(arg);
2590 rb_ary_push(av, arg);
2591 }
2592}
2593
2594void *
2596{
2598 VALUE iseq;
2599 const char *script_name = (argc > 0 && argv[0]) ? argv[0] : ruby_engine;
2600
2601 if (!origarg.argv || origarg.argc <= 0) {
2602 origarg.argc = argc;
2603 origarg.argv = argv;
2604 }
2605 ruby_script(script_name); /* for the time being */
2608 iseq = process_options(argc, argv, cmdline_options_init(&opt));
2609
2610#ifndef HAVE_SETPROCTITLE
2612#endif
2613
2614 return (void*)(struct RData*)iseq;
2615}
2616
2617static void
2618fill_standard_fds(void)
2619{
2620 int f0, f1, f2, fds[2];
2621 struct stat buf;
2622 f0 = fstat(0, &buf) == -1 && errno == EBADF;
2623 f1 = fstat(1, &buf) == -1 && errno == EBADF;
2624 f2 = fstat(2, &buf) == -1 && errno == EBADF;
2625 if (f0) {
2626 if (pipe(fds) == 0) {
2627 close(fds[1]);
2628 if (fds[0] != 0) {
2629 dup2(fds[0], 0);
2630 close(fds[0]);
2631 }
2632 }
2633 }
2634 if (f1 || f2) {
2635 if (pipe(fds) == 0) {
2636 close(fds[0]);
2637 if (f1 && fds[1] != 1)
2638 dup2(fds[1], 1);
2639 if (f2 && fds[1] != 2)
2640 dup2(fds[1], 2);
2641 if (fds[1] != 1 && fds[1] != 2)
2642 close(fds[1]);
2643 }
2644 }
2645}
2646
2654void
2655ruby_sysinit(int *argc, char ***argv)
2656{
2657#if defined(_WIN32)
2659#endif
2660 if (*argc >= 0 && *argv) {
2661 origarg.argc = *argc;
2662 origarg.argv = *argv;
2663#if defined(USE_DLN_A_OUT)
2664 dln_argv0 = origarg.argv[0];
2665#endif
2666 }
2667 fill_standard_fds();
2668}
VALUE rb_ary_shift(VALUE ary)
Definition: array.c:1413
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1301
void rb_ary_modify(VALUE ary)
Definition: array.c:606
VALUE rb_ary_replace(VALUE copy, VALUE orig)
Definition: array.c:4484
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:846
VALUE rb_ary_clear(VALUE ary)
Definition: array.c:4534
#define L(x)
Definition: asm.h:125
int bits(struct state *s, int need)
Definition: blast.c:72
Our own, locale independent, character handling routines.
#define ISSPACE
Definition: ctype.h:38
#define STRNCASECMP
Definition: ctype.h:53
#define TOLOWER
Definition: ctype.h:51
#define ISALNUM
Definition: ctype.h:41
#define rb_define_module_function(klass, mid, func, arity)
Defines klass#mid and makes it a module function.
Definition: cxxanyargs.hpp:672
#define rb_define_global_function(mid, func, arity)
Defines rb_mKernel #mid.
Definition: cxxanyargs.hpp:678
#define mod(x, y)
Definition: date_strftime.c:28
enum @11::@13::@14 mask
struct RIMemo * ptr
Definition: debug.c:88
char * strchr(char *, char)
#define RUBY_EXTERN
Definition: dllexport.h:36
#define isdirsep(x)
Definition: dln.c:116
void Init_enc(void)
Definition: dmyenc.c:5
#define require(name)
Definition: dmyenc.c:1
void Init_ext(void)
Definition: dmyext.c:2
#define PATH_ENV
Definition: dosish.h:49
#define PATH_SEP_CHAR
Definition: dosish.h:47
int rb_enc_dummy_p(rb_encoding *enc)
Definition: encoding.c:203
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:1064
rb_encoding * rb_utf8_encoding(void)
Definition: encoding.c:1537
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1525
rb_encoding * rb_enc_from_index(int index)
Definition: encoding.c:414
rb_encoding * rb_default_internal_encoding(void)
Definition: encoding.c:1734
void rb_enc_copy(VALUE obj1, VALUE obj2)
Definition: encoding.c:1188
void rb_enc_set_default_internal(VALUE encoding)
Definition: encoding.c:1784
rb_encoding * rb_default_external_encoding(void)
Definition: encoding.c:1647
rb_encoding * rb_locale_encoding(void)
Definition: encoding.c:1583
VALUE rb_enc_from_encoding(rb_encoding *encoding)
Definition: encoding.c:188
void rb_enc_set_default_external(VALUE encoding)
Definition: encoding.c:1701
int rb_enc_find_index(const char *name)
Definition: encoding.c:879
big_t * num
Definition: enough.c:232
uint8_t len
Definition: escape.c:17
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
#define numberof(array)
Definition: etc.c:649
#define CharNext(p)
Definition: eval_intern.h:316
char * strrchr(const char *, const char)
void rb_vm_set_progname(VALUE filename)
Definition: vm.c:3690
#define RSTRING_LEN(string)
Definition: fbuffer.h:22
#define RSTRING_PTR(string)
Definition: fbuffer.h:19
#define memcpy(d, s, n)
Definition: ffi_common.h:55
int ruby_is_fd_loadable(int fd)
Definition: file.c:6277
#define O_BINARY
VALUE rb_str_encode_ospath(VALUE path)
Definition: file.c:251
char * rb_enc_path_last_separator(const char *path, const char *end, rb_encoding *enc)
Definition: file.c:3470
VALUE rb_file_expand_path(VALUE fname, VALUE dname)
Definition: file.c:4103
VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict)
Definition: file.c:4496
#define PRIsVALUE
Definition: function.c:10
void ruby_xfree(void *x)
Deallocates a storage instance.
Definition: gc.c:10914
void ruby_gc_set_params(void)
Definition: gc.c:10122
void rb_gc_register_address(VALUE *addr)
Inform the garbage collector that valptr points to a live Ruby object that should not be moved.
Definition: gc.c:8040
void rb_gc_register_mark_object(VALUE obj)
Inform the garbage collector that object is a live Ruby object that should not be moved.
Definition: gc.c:8022
VALUE rb_mProcess
Definition: process.c:8608
VALUE rb_stdin
Definition: io.c:196
VALUE rb_stdout
Definition: globals.h:118
VALUE rb_cString
Definition: string.c:80
VALUE rb_define_module(const char *name)
Definition: class.c:871
#define OBJ_FREEZE_RAW
Definition: fl_type.h:135
#define OBJ_FREEZE
Definition: fl_type.h:134
void ruby_set_argv(int argc, char **argv)
Definition: ruby.c:2574
void ruby_incpush(const char *path)
Definition: ruby.c:456
void ruby_script(const char *name)
Sets the current script name to this value.
Definition: ruby.c:2458
void ruby_set_script_name(VALUE name)
Sets the current script name to this value.
Definition: ruby.c:2471
void ruby_init_loadpath(void)
Definition: ruby.c:616
void * ruby_process_options(int argc, char **argv)
Definition: ruby.c:2595
void ruby_prog_init(void)
Defines built-in variables.
Definition: ruby.c:2542
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2917
void rb_warning_category_update(unsigned int mask, unsigned int bits)
Definition: error.c:175
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:712
VALUE rb_eTypeError
Definition: error.c:1057
void rb_fatal(const char *fmt,...)
Definition: error.c:2968
void rb_load_fail(VALUE path, const char *err)
Definition: error.c:3219
VALUE rb_eNameError
Definition: error.c:1062
VALUE rb_eRuntimeError
Definition: error.c:1055
void rb_warn(const char *fmt,...)
Definition: error.c:408
VALUE rb_exc_new_str(VALUE etype, VALUE str)
Definition: error.c:1107
void rb_loaderror(const char *fmt,...)
Definition: error.c:2936
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:1148
long rb_backtrace_length_limit
Definition: error.c:68
VALUE rb_eSecurityError
Definition: error.c:1066
void rb_warning(const char *fmt,...)
Definition: error.c:439
VALUE rb_cObject
Object class.
Definition: object.c:49
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
Definition: object.c:1953
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
Definition: object.c:1101
void ruby_show_copyright(void)
Prints the copyright notice of the CRuby interpreter to stdout.
Definition: version.c:138
void ruby_sysinit(int *argc, char ***argv)
Initializes the process for libruby.
Definition: ruby.c:2655
void ruby_show_version(void)
Prints the version information of the CRuby interpreter to stdout.
Definition: version.c:119
VALUE rb_hash_new(void)
Definition: hash.c:1538
void ruby_setenv(const char *name, const char *value)
Definition: hash.c:5145
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
Definition: string.c:1100
#define ECONV_UNDEF_REPLACE
Definition: encoding.h:387
VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts)
Definition: string.c:984
#define ENCODING_GET(obj)
Definition: encoding.h:51
#define ECONV_INVALID_REPLACE
Definition: encoding.h:385
VALUE rb_enc_interned_str(const char *, long, rb_encoding *)
Definition: string.c:11562
#define ENC_CODERANGE_BROKEN
Definition: encoding.h:95
Thin wrapper to ruby/config.h.
Declares rb_raise().
#define ruby_debug
Definition: error.h:69
@ RB_WARN_CATEGORY_DEPRECATED
Definition: error.h:34
@ RB_WARN_CATEGORY_ALL_BITS
Definition: error.h:36
@ RB_WARN_CATEGORY_EXPERIMENTAL
Definition: error.h:35
#define ruby_verbose
Definition: error.h:68
VALUE * rb_ruby_verbose_ptr(void)
Definition: vm.c:3768
VALUE * rb_ruby_debug_ptr(void)
Definition: vm.c:3775
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:1077
VALUE rb_funcall_passing_block(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:1149
VALUE rb_io_getbyte(VALUE)
Definition: io.c:4331
VALUE rb_io_close(VALUE)
Definition: io.c:4935
VALUE rb_io_fdopen(int, int, const char *)
Definition: io.c:8183
VALUE rb_io_gets(VALUE)
Definition: io.c:3738
VALUE rb_io_write(VALUE, VALUE)
Definition: io.c:1953
void rb_update_max_fd(int fd)
Definition: io.c:233
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Definition: io.c:307
VALUE rb_io_flush(VALUE)
Definition: io.c:2052
VALUE rb_fs
Definition: string.c:502
VALUE rb_output_rs
Definition: io.c:201
int rb_pipe(int *pipes)
Definition: io.c:6499
VALUE rb_io_ungetbyte(VALUE, VALUE)
Definition: io.c:4393
VALUE rb_lastline_get(void)
Definition: vm.c:1556
void rb_lastline_set(VALUE)
Definition: vm.c:1562
rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags)
Definition: process.c:1443
VALUE rb_f_exec(int, const VALUE *)
Definition: process.c:3109
VALUE rb_reg_new(const char *, long, int)
Definition: re.c:2960
#define rb_str_new2
Definition: string.h:276
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2859
#define rb_utf8_str_new_cstr(str)
Definition: string.h:246
#define rb_str_cat2
Definition: string.h:285
#define rb_str_new_lit(str)
Definition: string.h:287
#define rb_str_new(str, len)
Definition: string.h:213
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2962
void rb_str_set_len(VALUE, long)
Definition: string.c:2842
#define rb_external_str_new_cstr(str)
Definition: string.h:251
VALUE rb_str_tmp_new(long)
Definition: string.c:1427
VALUE rb_str_subseq(VALUE, long, long)
Definition: string.c:2624
#define rb_strlen_lit(str)
Definition: string.h:286
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:1273
void rb_str_modify_expand(VALUE, long)
Definition: string.c:2270
#define rb_str_cat_cstr(buf, str)
Definition: string.h:266
#define rb_utf8_str_new(str, len)
Definition: string.h:230
VALUE rb_str_dup(VALUE)
Definition: string.c:1631
#define rb_str_new_cstr(str)
Definition: string.h:219
#define rb_str_new4
Definition: string.h:278
void rb_thread_wait_fd(int)
Definition: thread.c:4305
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:2624
void rb_const_set(VALUE, ID, VALUE)
Definition: variable.c:3003
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1242
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1493
VALUE rb_const_remove(VALUE, ID)
Definition: variable.c:2727
ID rb_intern(const char *)
Definition: symbol.c:785
#define CONST_ID
Definition: symbol.h:47
VALUE rb_gv_set(const char *, VALUE)
Definition: variable.c:754
void rb_define_global_const(const char *, VALUE)
Definition: variable.c:3162
rb_gvar_setter_t rb_gvar_readonly_setter
Definition: variable.h:46
int dup2(int, int)
Definition: dup2.c:27
char * strstr(const char *, const char *)
Definition: strstr.c:8
char * strerror(int)
Definition: strerror.c:11
void setproctitle(const char *fmt,...)
Definition: setproctitle.c:139
#define strdup(s)
Definition: util.h:39
void ruby_each_words(const char *, void(*)(const char *, int, void *), void *)
Definition: util.c:589
#define scan_oct(s, l, e)
Definition: util.h:22
const char ruby_engine[]
Definition: version.c:46
Internal header aggregating init functions.
Internal header for File.
Internal header for IO.
void ruby_set_inplace_mode(const char *)
Definition: io.c:13050
int rb_gc_for_fd(int err)
Definition: io.c:1010
void rb_stdio_set_default_encoding(void)
Definition: io.c:12002
VALUE rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt)
Definition: io.c:7040
Internal header for require.
VALUE rb_get_expanded_load_path(void)
Definition: load.c:104
Internal header corresponding missing.
void ruby_init_setproctitle(int argc, char *argv[])
Internal header for Object.
Internal header for the parser.
Internal header for Process.
int rb_enc_str_coderange_scan(VALUE str, rb_encoding *enc)
Definition: string.c:719
void rb_gvar_ractor_local(const char *name)
Definition: variable.c:359
VALUE rb_vm_top_self(void)
Definition: vm.c:3752
#define rb_funcallv(...)
Definition: internal.h:77
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
VALUE rb_cISeq
Definition: iseq.c:46
rb_iseq_t * rb_iseq_new_main(const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_iseq_t *parent)
Definition: iseq.c:833
VALUE rb_iseq_disasm(const rb_iseq_t *iseq)
Definition: iseq.c:2335
Internal header for $LOAD_PATH.
const char ruby_exec_prefix[]
Definition: loadpath.c:59
const char ruby_initial_load_paths[]
Definition: loadpath.c:62
#define INT2FIX
Definition: long.h:48
#define MEMZERO(p, type, n)
Definition: memory.h:128
#define ALLOC_N
Definition: memory.h:133
#define MEMMOVE(p1, p2, type, n)
Definition: memory.h:130
struct mjit_options mjit_opts
Definition: mjit_worker.c:199
void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
Define a function-backended global variable.
Definition: cxxanyargs.hpp:136
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:56
void rb_define_virtual_variable(const char *q, type *w, void_type *e)
Define a function-backended global variable.
Definition: cxxanyargs.hpp:73
const char * name
Definition: nkf.c:208
#define TRUE
Definition: nkf.h:175
#define FALSE
Definition: nkf.h:174
VALUE rb_parser_dump_tree(const NODE *node, int comment)
Definition: node.c:1120
void rb_ast_dispose(rb_ast_t *ast)
Definition: node.c:1448
#define RARRAY_CONST_PTR(s)
Definition: psych_emitter.c:4
#define RARRAY_AREF(a, i)
Definition: psych_emitter.c:7
#define RARRAY_LEN
Definition: rarray.h:52
#define NULL
Definition: regenc.h:69
#define RFILE(obj)
Definition: rfile.h:35
VALUE rb_parser_new(void)
Definition: ripper.c:20781
rb_ast_t * rb_parser_compile_string(VALUE vparser, const char *f, VALUE s, int line)
Definition: ripper.c:14008
rb_ast_t * rb_parser_compile_string_path(VALUE vparser, VALUE f, VALUE s, int line)
Definition: ripper.c:14014
void rb_parser_set_options(VALUE vparser, int print, int loop, int chomp, int split)
Definition: ripper.c:20599
VALUE rb_parser_set_context(VALUE vparser, const struct rb_iseq_struct *base, int main)
Definition: ripper.c:20791
VALUE rb_parser_encoding(VALUE vparser)
Definition: ripper.c:20854
#define yydebug
Definition: ripper.c:144
VALUE rb_parser_set_yydebug(VALUE self, VALUE flag)
Definition: ripper.c:20886
VALUE rb_parser_end_seen_p(VALUE vparser)
Definition: ripper.c:20839
rb_ast_t * rb_parser_compile_file_path(VALUE vparser, VALUE fname, VALUE file, int start)
Definition: ripper.c:14029
#define StringValuePtr(v)
Definition: rstring.h:51
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Definition: rstring.h:211
#define RSTRING_EMBED_LEN_MAX
Definition: rstring.h:39
#define StringValueCStr(v)
Definition: rstring.h:52
#define rb_argv
Definition: ruby.h:29
const char * rb_obj_classname(VALUE)
Definition: variable.c:308
#define INITIAL_LOAD_PATH_MARK
Definition: ruby.c:607
#define str_conv_enc(str, from, to)
Definition: ruby.c:529
VALUE rb_argv0
Definition: ruby.c:1552
int ruby_env_debug_option(const char *str, int len, void *arg)
Definition: debug.c:176
#define set_source_encoding_once(opt, e, elen)
Definition: ruby.c:1017
@ DEFAULT_FEATURES
Definition: ruby.c:208
@ COMPILATION_FEATURES
Definition: ruby.c:203
#define rb_orig_progname
Definition: ruby.c:1551
VALUE rb_e_script
Definition: ruby.c:1553
#define FEATURE_BIT(bit)
Definition: ruby.c:93
#define src_encoding_index
Definition: ruby.c:200
void ruby_incpush_expand(const char *path)
Definition: ruby.c:473
#define rb_define_readonly_boolean(name, val)
Definition: ruby.c:1567
#define EACH_DEBUG_FEATURES(X, SEP)
Definition: ruby.c:105
#define IF_UTF8_PATH(t, f)
Definition: ruby.c:517
#define is_option_with_arg(name, allow_hyphen, allow_envopt)
VALUE ruby_prefix_path
Definition: ruby.c:609
feature_flag_bits
Definition: ruby.c:111
@ feature_flag_count
Definition: ruby.c:116
@ feature_debug_flag_first
Definition: ruby.c:113
@ feature_debug_flag_begin
Definition: ruby.c:114
#define DUMP_BIT(bit)
Definition: ruby.c:121
void Init_builtin_features(void)
Definition: builtin.c:66
#define RUBY_RELATIVE(path, len)
#define tty_enabled()
Definition: ruby.c:1678
#define SET_WHEN_DEBUG(bit)
VALUE ruby_archlibdir_path
Definition: ruby.c:609
#define FEATURE_SET_RESTORE(feat, save)
Definition: ruby.c:167
#define DEFINE_DUMP(bit)
Definition: ruby.c:122
#define SET_FEATURE(bit)
#define DEFINE_DEBUG_FEATURE(bit)
Definition: ruby.c:110
#define is_option_with_optarg(name, allow_hyphen, allow_envopt, needs_arg, next_arg)
#define FEATURE_SET_TO(feat, bit_mask, bit_set)
Definition: ruby.c:164
#define SHOW(m)
#define FEATURE_SET(feat, bits)
Definition: ruby.c:166
dump_flag_bits
Definition: ruby.c:142
@ dump_version_v
Definition: ruby.c:143
@ dump_exit_bits
Definition: ruby.c:145
#define NAME_MATCH_P(name, str, len)
Definition: ruby.c:893
void * rb_load_file_str(VALUE fname_v)
Definition: ruby.c:2368
#define DEFINE_FEATURE(bit)
Definition: ruby.c:109
#define EACH_FEATURES(X, SEP)
Definition: ruby.c:94
void Init_ruby_description(void)
Definition: version.c:100
#define COMMA
Definition: ruby.c:92
#define SET_COMPILE_OPTION(h, o, name)
#define SET_WHEN_DUMP(bit)
#define M(shortopt, longopt, desc)
void rb_call_builtin_inits(void)
Definition: inits.c:85
void * rb_parser_load_file(VALUE parser, VALUE fname_v)
Definition: ruby.c:2374
#define set_internal_encoding_once(opt, e, elen)
Definition: ruby.c:1013
#define EACH_DUMPS(X, SEP)
Definition: ruby.c:123
char * getenv()
int argc
Definition: ruby.c:240
#define set_encoding_part(type)
const int ruby_patchlevel
Definition: version.c:42
#define MAXPATHLEN
Definition: ruby.c:69
#define rb_progname
Definition: ruby.c:1550
void * rb_load_file(const char *fname)
Definition: ruby.c:2361
void ruby_push_include(const char *path, VALUE(*filter)(VALUE))
Definition: ruby.c:436
#define DEFAULT_RUBYGEMS_ENABLED
Definition: ruby.c:87
#define set_external_encoding_once(opt, e, elen)
Definition: ruby.c:1015
#define forbid_setid(s)
Definition: ruby.c:237
#define rubylib_path_new
Definition: ruby.c:372
char ** argv
Definition: ruby.c:241
#define PREFIX_PATH()
#define LITERAL_NAME_ELEMENT(name)
Definition: ruby.c:908
#define MODE_TO_LOAD
#define Qtrue
#define RTEST
#define Qnil
#define Qfalse
#define NIL_P
#define f
VALUE rb_sprintf(const char *,...)
Definition: sprintf.c:1203
#define _(args)
Definition: stdarg.h:31
size_t strlen(const char *)
#define rb_rs
Definition: string.c:8464
Definition: rdata.h:67
VALUE parser
Definition: ruby.c:2119
VALUE fname
Definition: ruby.c:2120
VALUE f
Definition: ruby.c:2123
ruby_cmdline_options_t * opt
Definition: ruby.c:2122
int script
Definition: ruby.c:2121
const NODE * root
Definition: node.h:399
rb_ast_body_t body
Definition: node.h:406
const struct rb_block block
Definition: vm_core.h:1113
VALUE load_path
Definition: vm_core.h:616
VALUE load_path_snapshot
Definition: vm_core.h:617
VALUE loaded_features_snapshot
Definition: vm_core.h:621
VALUE loaded_features
Definition: vm_core.h:620
unsigned int verbose
Definition: ruby.c:189
unsigned int do_search
Definition: ruby.c:194
unsigned int do_loop
Definition: ruby.c:190
unsigned int dump
Definition: ruby.c:183
ruby_features_t warn
Definition: ruby.c:182
VALUE script_name
Definition: ruby.c:172
ruby_features_t features
Definition: ruby.c:181
unsigned int warning
Definition: ruby.c:188
unsigned int do_split
Definition: ruby.c:193
const char * script
Definition: ruby.c:171
struct ruby_cmdline_options::@161 ext
unsigned int do_line
Definition: ruby.c:192
unsigned int do_print
Definition: ruby.c:191
struct ruby_cmdline_options::@161 intern
struct ruby_cmdline_options::@161 src
unsigned int setids
Definition: ruby.c:195
struct ruby_cmdline_options::@161::@162 enc
unsigned int mask
Definition: ruby.c:153
unsigned int set
Definition: ruby.c:154
Definition: dtoa.c:302
void help(int exitval)
Definition: untgz.c:581
unsigned long VALUE
Definition: value.h:38
unsigned long ID
Definition: value.h:39
#define T_STRING
Definition: value_type.h:77
#define GetBindingPtr(obj, ptr)
Definition: vm_core.h:1109
VALUE rb_readlink(VALUE path, rb_encoding *resultenc)
Definition: file.c:619
#define dln_find_file_r
Definition: win32.c:92
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING
#define stat
Definition: win32.h:195
rb_uid_t getuid(void)
Definition: win32.c:2821
rb_uid_t geteuid(void)
Definition: win32.c:2828
int kill(int, int)
Definition: win32.c:4845
void rb_w32_sysinit(int *, char ***)
Definition: win32.c:884
#define fstat(fd, st)
Definition: win32.h:202
int fcntl(int, int,...)
Definition: win32.c:4338
rb_gid_t getegid(void)
Definition: win32.c:2842
#define F_SETFL
Definition: win32.h:581
rb_gid_t getgid(void)
Definition: win32.c:2835
IUnknown DWORD
Definition: win32ole.c:33