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