diff options
Diffstat (limited to 'ruby.c')
| -rw-r--r-- | ruby.c | 538 |
1 files changed, 230 insertions, 308 deletions
@@ -17,7 +17,6 @@ #endif #include "ruby/ruby.h" #include "ruby/encoding.h" -#include "internal.h" #include "eval_intern.h" #include "dln.h" #include <stdio.h> @@ -52,13 +51,11 @@ char *getenv(); #endif -#define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) +VALUE rb_parser_get_yydebug(VALUE); +VALUE rb_parser_set_yydebug(VALUE, VALUE); -#if defined DISABLE_RUBYGEMS && DISABLE_RUBYGEMS -#define DEFAULT_RUBYGEMS_ENABLED "disabled" -#else -#define DEFAULT_RUBYGEMS_ENABLED "enabled" -#endif +const char *ruby_get_inplace_mode(void); +void ruby_set_inplace_mode(const char *); #define DISABLE_BIT(bit) (1U << disable_##bit) enum disable_flag_bits { @@ -70,10 +67,8 @@ enum disable_flag_bits { #define DUMP_BIT(bit) (1U << dump_##bit) enum dump_flag_bits { dump_version, - dump_version_v, dump_copyright, dump_usage, - dump_help, dump_yydebug, dump_syntax, dump_parsetree, @@ -116,96 +111,62 @@ cmdline_options_init(struct cmdline_options *opt) opt->src.enc.index = src_encoding_index; opt->ext.enc.index = -1; opt->intern.enc.index = -1; -#if defined DISABLE_RUBYGEMS && DISABLE_RUBYGEMS - opt->disable |= DISABLE_BIT(gems); -#endif return opt; } -static NODE *load_file(VALUE, VALUE, int, struct cmdline_options *); +static NODE *load_file(VALUE, const char *, int, struct cmdline_options *); static void forbid_setid(const char *, struct cmdline_options *); -#define forbid_setid(s) forbid_setid((s), opt) +#define forbid_setid(s) forbid_setid(s, opt) static struct { int argc; char **argv; +#if !defined(PSTAT_SETCMD) && !defined(HAVE_SETPROCTITLE) + size_t len; +#endif } origarg; static void -usage(const char *name, int help) +usage(const char *name) { /* This message really ought to be max 23 lines. * Removed -h because the user already knows that option. Others? */ - struct message { - const char *str; - unsigned short namelen, secondlen; - }; -#define M(shortopt, longopt, desc) { \ - shortopt " " longopt " " desc, \ - (unsigned short)sizeof(shortopt), \ - (unsigned short)sizeof(longopt), \ -} - static const struct message usage_msg[] = { - M("-0[octal]", "", "specify record separator (\\0, if no argument)"), - M("-a", "", "autosplit mode with -n or -p (splits $_ into $F)"), - M("-c", "", "check syntax only"), - M("-Cdirectory", "", "cd to directory before executing your script"), - M("-d", ", --debug", "set debugging flags (set $DEBUG to true)"), - M("-e 'command'", "", "one line of script. Several -e's allowed. Omit [programfile]"), - M("-Eex[:in]", ", --encoding=ex[:in]", "specify the default external and internal character encodings"), - M("-Fpattern", "", "split() pattern for autosplit (-a)"), - M("-i[extension]", "", "edit ARGV files in place (make backup if extension supplied)"), - M("-Idirectory", "", "specify $LOAD_PATH directory (may be used more than once)"), - M("-l", "", "enable line ending processing"), - M("-n", "", "assume 'while gets(); ... end' loop around your script"), - M("-p", "", "assume loop like -n but print line also like sed"), - M("-rlibrary", "", "require the library before executing your script"), - M("-s", "", "enable some switch parsing for switches after script name"), - M("-S", "", "look for the script using PATH environment variable"), - M("-T[level=1]", "", "turn on tainting checks"), - M("-v", ", --verbose", "print version number, then turn on verbose mode"), - M("-w", "", "turn warnings on for your script"), - M("-W[level=2]", "", "set warning level; 0=silence, 1=medium, 2=verbose"), - M("-x[directory]", "", "strip off text before #!ruby line and perhaps cd to directory"), - M("-h", "", "show this message, --help for more info"), - }; - static const struct message help_msg[] = { - M("--copyright", "", "print the copyright"), - M("--enable=feature[,...]", ", --disable=feature[,...]", - "enable or disable features"), - M("--external-encoding=encoding", ", --internal-encoding=encoding", - "specify the default external or internal character encoding"), - M("--version", "", "print the version"), - M("--help", "", "show this message, -h for short message"), + static const char *const usage_msg[] = { + "-0[octal] specify record separator (\\0, if no argument)", + "-a autosplit mode with -n or -p (splits $_ into $F)", + "-c check syntax only", + "-Cdirectory cd to directory, before executing your script", + "-d set debugging flags (set $DEBUG to true)", + "-e 'command' one line of script. Several -e's allowed. Omit [programfile]", + "-Eex[:in] specify the default external and internal character encodings", + "-Fpattern split() pattern for autosplit (-a)", + "-i[extension] edit ARGV files in place (make backup if extension supplied)", + "-Idirectory specify $LOAD_PATH directory (may be used more than once)", + "-l enable line ending processing", + "-n assume 'while gets(); ... end' loop around your script", + "-p assume loop like -n but print line also like sed", + "-rlibrary require the library, before executing your script", + "-s enable some switch parsing for switches after script name", + "-S look for the script using PATH environment variable", + "-T[level=1] turn on tainting checks", + "-v print version number, then turn on verbose mode", + "-w turn warnings on for your script", + "-W[level=2] set warning level; 0=silence, 1=medium, 2=verbose", + "-x[directory] strip off text before #!ruby line and perhaps cd to directory", + "--copyright print the copyright", + "--version print the version", + NULL }; - static const struct message features[] = { - M("gems", "", "rubygems (default: "DEFAULT_RUBYGEMS_ENABLED")"), - M("rubyopt", "", "RUBYOPT environment variable (default: enabled)"), - }; - int i, w = 16, num = numberof(usage_msg) - (help ? 1 : 0); -#define SHOW(m) do { \ - int wrap = help && (m).namelen + (m).secondlen - 2 > w; \ - printf(" %.*s%-*.*s%-*s%s\n", (m).namelen-1, (m).str, \ - (wrap ? 0 : w - (m).namelen + 1), \ - (help ? (m).secondlen-1 : 0), (m).str + (m).namelen, \ - (wrap ? w + 3 : 0), (wrap ? "\n" : ""), \ - (m).str + (m).namelen + (m).secondlen); \ - } while (0) + const char *const *p = usage_msg; printf("Usage: %s [switches] [--] [programfile] [arguments]\n", name); - for (i = 0; i < num; ++i) - SHOW(usage_msg[i]); - - if (!help) return; - - for (i = 0; i < numberof(help_msg); ++i) - SHOW(help_msg[i]); - puts("Features:"); - for (i = 0; i < numberof(features); ++i) - SHOW(features[i]); + while (*p) + printf(" %s\n", *p++); } +VALUE rb_get_load_path(void); + #ifdef MANGLED_PATH static VALUE rubylib_mangled_path(const char *s, unsigned int l) @@ -294,14 +255,7 @@ push_include_cygwin(const char *path, VALUE (*filter)(VALUE)) p = strncpy(RSTRING_PTR(buf), p, len); } } -#ifdef HAVE_CYGWIN_CONV_PATH -#define CONV_TO_POSIX_PATH(p, lib) \ - cygwin_conv_path(CCP_WIN_A_TO_POSIX|CCP_RELATIVE, (p), (lib), sizeof(lib)) -#else -#define CONV_TO_POSIX_PATH(p, lib) \ - cygwin_conv_to_posix_path((p), (lib)) -#endif - if (CONV_TO_POSIX_PATH(p, rubylib) == 0) + if (cygwin_conv_to_posix_path(p, rubylib) == 0) p = rubylib; push_include(p, filter); if (!*s) break; @@ -389,7 +343,7 @@ ruby_init_loadpath_safe(int safe_level) extern const char ruby_initial_load_paths[]; const char *paths = ruby_initial_load_paths; #if defined LOAD_RELATIVE -# if defined HAVE_DLADDR || defined HAVE_CYGWIN_CONV_PATH +# if defined HAVE_DLADDR || (defined __CYGWIN__ && defined CCP_WIN_A_TO_POSIX) # define VARIABLE_LIBPATH 1 # else # define VARIABLE_LIBPATH 0 @@ -416,6 +370,7 @@ ruby_init_loadpath_safe(int safe_level) #elif defined(HAVE_DLADDR) Dl_info dli; if (dladdr((void *)(VALUE)expand_include_path, &dli)) { + VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict); char fbuf[MAXPATHLEN]; char *f = dln_find_file_r(dli.dli_fname, getenv(PATH_ENV), fbuf, sizeof(fbuf)); VALUE fname = rb_str_new_cstr(f ? f : dli.dli_fname); @@ -456,21 +411,9 @@ ruby_init_loadpath_safe(int safe_level) #endif p = strrchr(libpath, '/'); if (p) { - static const char bindir[] = "/bin"; -#ifdef LIBDIR_BASENAME - static const char libdir[] = "/"LIBDIR_BASENAME; -#else - static const char libdir[] = "/lib"; -#endif - const ptrdiff_t bindir_len = (ptrdiff_t)sizeof(bindir) - 1; - const ptrdiff_t libdir_len = (ptrdiff_t)sizeof(libdir) - 1; *p = 0; - if (p - libpath >= bindir_len && !STRCASECMP(p - bindir_len, bindir)) { - p -= bindir_len; - *p = 0; - } - else if (p - libpath >= libdir_len && !strcmp(p - libdir_len, libdir)) { - p -= libdir_len; + if (p - libpath > 3 && !(STRCASECMP(p - 4, "/bin") && strcmp(p - 4, "/lib"))) { + p -= 4; *p = 0; } } @@ -483,25 +426,22 @@ ruby_init_loadpath_safe(int safe_level) #define PREFIX_PATH() rb_str_new(libpath, baselen) #else baselen = p - libpath; - rb_str_resize(sopath, baselen); + rb_str_set_len(sopath, baselen); libpath = RSTRING_PTR(sopath); #define PREFIX_PATH() sopath #endif #define BASEPATH() rb_str_buf_cat(rb_str_buf_new(baselen+len), libpath, baselen) -#define RUBY_RELATIVE(path, len) rb_str_buf_cat(BASEPATH(), (path), (len)) +#define RUBY_RELATIVE(path, len) rb_str_buf_cat(BASEPATH(), path, len) #else static const char exec_prefix[] = RUBY_EXEC_PREFIX; -#define RUBY_RELATIVE(path, len) rubylib_mangled_path((path), (len)) +#define RUBY_RELATIVE(path, len) rubylib_mangled_path(path, len) #define PREFIX_PATH() RUBY_RELATIVE(exec_prefix, sizeof(exec_prefix)-1) #endif load_path = GET_VM()->load_path; if (safe_level == 0) { -#ifdef MANGLED_PATH - rubylib_mangled_path("", 0); -#endif ruby_push_include(getenv("RUBYLIB"), identical_path); } @@ -522,51 +462,38 @@ static void add_modules(VALUE *req_list, const char *mod) { VALUE list = *req_list; - VALUE feature; if (!list) { *req_list = list = rb_ary_new(); RBASIC(list)->klass = 0; } - feature = rb_str_new2(mod); - RBASIC(feature)->klass = 0; - rb_ary_push(list, feature); + rb_ary_push(list, rb_obj_freeze(rb_str_new2(mod))); } +extern void Init_ext(void); +extern VALUE rb_vm_top_self(void); + static void require_libraries(VALUE *req_list) { VALUE list = *req_list; - VALUE self = rb_vm_top_self(); ID require; rb_thread_t *th = GET_THREAD(); - rb_encoding *extenc = rb_default_external_encoding(); + rb_block_t *prev_base_block = th->base_block; int prev_parse_in_eval = th->parse_in_eval; + th->base_block = 0; th->parse_in_eval = 0; Init_ext(); /* should be called here for some reason :-( */ CONST_ID(require, "require"); while (list && RARRAY_LEN(list) > 0) { VALUE feature = rb_ary_shift(list); - rb_enc_associate(feature, extenc); - RBASIC(feature)->klass = rb_cString; - OBJ_FREEZE(feature); - rb_funcall2(self, require, 1, &feature); + rb_funcall2(rb_vm_top_self(), require, 1, &feature); } *req_list = 0; th->parse_in_eval = prev_parse_in_eval; -} - -static rb_env_t* -toplevel_context(VALUE toplevel_binding) -{ - rb_env_t *env; - rb_binding_t *bind; - - GetBindingPtr(toplevel_binding, bind); - GetEnvPtr(bind->env, env); - return env; + th->base_block = prev_base_block; } static void @@ -633,6 +560,8 @@ process_sflag(int *sflag) } } +NODE *rb_parser_append_print(VALUE, NODE *); +NODE *rb_parser_while_loop(VALUE, NODE *, int, int); static long proc_options(long argc, char **argv, struct cmdline_options *opt, int envopt); static void @@ -683,16 +612,16 @@ moreswitches(const char *s, struct cmdline_options *opt, int envopt) } #define NAME_MATCH_P(name, str, len) \ - ((len) < (int)sizeof(name) && strncmp((str), (name), (len)) == 0) + ((len) < (int)sizeof(name) && strncmp((str), name, (len)) == 0) #define UNSET_WHEN(name, bit, str, len) \ - if (NAME_MATCH_P((name), (str), (len))) { \ + if (NAME_MATCH_P(name, str, len)) { \ *(unsigned int *)arg &= ~(bit); \ return; \ } #define SET_WHEN(name, bit, str, len) \ - if (NAME_MATCH_P((name), (str), (len))) { \ + if (NAME_MATCH_P(name, str, len)) { \ *(unsigned int *)arg |= (bit); \ return; \ } @@ -730,7 +659,6 @@ dump_option(const char *str, int len, void *arg) SET_WHEN_DUMP(version); SET_WHEN_DUMP(copyright); SET_WHEN_DUMP(usage); - SET_WHEN_DUMP(help); SET_WHEN_DUMP(yydebug); SET_WHEN_DUMP(syntax); SET_WHEN_DUMP(parsetree); @@ -757,11 +685,11 @@ set_option_encoding_once(const char *type, VALUE *name, const char *e, long elen } #define set_internal_encoding_once(opt, e, elen) \ - set_option_encoding_once("default_internal", &(opt)->intern.enc.name, (e), (elen)) + set_option_encoding_once("default_internal", &opt->intern.enc.name, e, elen) #define set_external_encoding_once(opt, e, elen) \ - set_option_encoding_once("default_external", &(opt)->ext.enc.name, (e), (elen)) + set_option_encoding_once("default_external", &opt->ext.enc.name, e, elen) #define set_source_encoding_once(opt, e, elen) \ - set_option_encoding_once("source", &(opt)->src.enc.name, (e), (elen)) + set_option_encoding_once("source", &opt->src.enc.name, e, elen) static long proc_options(long argc, char **argv, struct cmdline_options *opt, int envopt) @@ -774,7 +702,7 @@ proc_options(long argc, char **argv, struct cmdline_options *opt, int envopt) for (argc--, argv++; argc > 0; argc--, argv++) { const char *const arg = argv[0]; - if (!arg || arg[0] != '-' || !arg[1]) + if (arg[0] != '-' || !arg[1]) break; s = arg + 1; @@ -813,7 +741,7 @@ proc_options(long argc, char **argv, struct cmdline_options *opt, int envopt) s++; goto reswitch; } - opt->dump |= DUMP_BIT(version_v); + ruby_show_version(); opt->verbose = 1; case 'w': ruby_verbose = Qtrue; @@ -1036,17 +964,17 @@ proc_options(long argc, char **argv, struct cmdline_options *opt, int envopt) s++; # define is_option_end(c, allow_hyphen) \ - (!(c) || ((allow_hyphen) && (c) == '-') || (c) == '=') + (!(c) || (allow_hyphen && (c) == '-') || (c) == '=') # define check_envopt(name, allow_envopt) \ - (((allow_envopt) || !envopt) ? (void)0 : \ + ((allow_envopt || !envopt) ? (void)0 : \ rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --" name)) # define need_argument(name, s) \ - ((*(s)++ ? !*(s) : (!--argc || !((s) = *++argv))) ? \ + ((*s++ ? !*s : (!--argc || !(s = *++argv))) ? \ rb_raise(rb_eRuntimeError, "missing argument for --" name) \ : (void)0) # define is_option_with_arg(name, allow_hyphen, allow_envopt) \ - (strncmp((name), s, n = sizeof(name) - 1) == 0 && is_option_end(s[n], (allow_hyphen)) ? \ - (check_envopt(name, (allow_envopt)), s += n, need_argument(name, s), 1) : 0) + (strncmp(name, s, n = sizeof(name) - 1) == 0 && is_option_end(s[n], allow_hyphen) ? \ + (check_envopt(name, allow_envopt), s += n, need_argument(name, s), 1) : 0) if (strcmp("copyright", s) == 0) { if (envopt) goto noenvopt_long; @@ -1078,7 +1006,7 @@ proc_options(long argc, char **argv, struct cmdline_options *opt, int envopt) if (!*(s = ++p)) break; set_encoding_part(internal); if (!*(s = ++p)) break; -#if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING +#if ALLOW_DEFAULT_SOURCE_ENCODING set_encoding_part(source); if (!*(s = ++p)) break; #endif @@ -1093,7 +1021,7 @@ proc_options(long argc, char **argv, struct cmdline_options *opt, int envopt) else if (is_option_with_arg("external-encoding", Qfalse, Qtrue)) { set_external_encoding_once(opt, s, 0); } -#if defined ALLOW_DEFAULT_SOURCE_ENCODING && ALLOW_DEFAULT_SOURCE_ENCODING +#if ALLOW_DEFAULT_SOURCE_ENCODING else if (is_option_with_arg("source-encoding", Qfalse, Qtrue)) { set_source_encoding_once(opt, s, 0); } @@ -1115,7 +1043,7 @@ proc_options(long argc, char **argv, struct cmdline_options *opt, int envopt) } else if (strcmp("help", s) == 0) { if (envopt) goto noenvopt_long; - opt->dump |= DUMP_BIT(help); + opt->dump |= DUMP_BIT(usage); goto switch_end; } else { @@ -1165,9 +1093,12 @@ proc_options(long argc, char **argv, struct cmdline_options *opt, int envopt) return argc0 - argc; } +void Init_prelude(void); + static void -ruby_init_prelude(void) +ruby_init_gems(int enable) { + if (enable) rb_define_module("Gem"); Init_prelude(); rb_const_remove(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX")); } @@ -1211,7 +1142,7 @@ uscore_get(void) VALUE line; line = rb_lastline_get(); - if (!RB_TYPE_P(line, T_STRING)) { + if (TYPE(line) != T_STRING) { rb_raise(rb_eTypeError, "$_ value need to be String (%s given)", NIL_P(line) ? "nil" : rb_obj_classname(line)); } @@ -1229,9 +1160,11 @@ uscore_get(void) */ static VALUE -rb_f_sub(int argc, VALUE *argv) +rb_f_sub(argc, argv) + int argc; + VALUE *argv; { - VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("sub"), argc, argv); + VALUE str = rb_funcall3(uscore_get(), rb_intern("sub"), argc, argv); rb_lastline_set(str); return str; } @@ -1248,9 +1181,11 @@ rb_f_sub(int argc, VALUE *argv) */ static VALUE -rb_f_gsub(int argc, VALUE *argv) +rb_f_gsub(argc, argv) + int argc; + VALUE *argv; { - VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("gsub"), argc, argv); + VALUE str = rb_funcall3(uscore_get(), rb_intern("gsub"), argc, argv); rb_lastline_set(str); return str; } @@ -1268,7 +1203,7 @@ rb_f_gsub(int argc, VALUE *argv) static VALUE rb_f_chop(void) { - VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("chop"), 0, 0); + VALUE str = rb_funcall3(uscore_get(), rb_intern("chop"), 0, 0); rb_lastline_set(str); return str; } @@ -1286,15 +1221,17 @@ rb_f_chop(void) */ static VALUE -rb_f_chomp(int argc, VALUE *argv) +rb_f_chomp(argc, argv) + int argc; + VALUE *argv; { - VALUE str = rb_funcall_passing_block(uscore_get(), rb_intern("chomp"), argc, argv); + VALUE str = rb_funcall3(uscore_get(), rb_intern("chomp"), argc, argv); rb_lastline_set(str); return str; } -/* blank function in dmyext.c or generated by enc/make_encmake.rb */ -extern void Init_enc(void); +void rb_stdio_set_default_encoding(void); +VALUE rb_parser_dump_tree(NODE *node, int comment); static VALUE process_options(int argc, char **argv, struct cmdline_options *opt) @@ -1307,13 +1244,13 @@ process_options(int argc, char **argv, struct cmdline_options *opt) char fbuf[MAXPATHLEN]; int i = (int)proc_options(argc, argv, opt, 0); rb_thread_t *th = GET_THREAD(); - VALUE toplevel_binding = Qundef; + rb_env_t *env = 0; argc -= i; argv += i; - if (opt->dump & (DUMP_BIT(usage)|DUMP_BIT(help))) { - usage(origarg.argv[0], (opt->dump & DUMP_BIT(help))); + if (opt->dump & DUMP_BIT(usage)) { + usage(origarg.argv[0]); return Qtrue; } @@ -1333,12 +1270,9 @@ process_options(int argc, char **argv, struct cmdline_options *opt) opt->intern.enc.name = int_enc_name; } - if (opt->src.enc.name) - rb_warning("-K is specified; it is for 1.8 compatibility and may cause odd behavior"); - - if (opt->dump & (DUMP_BIT(version) | DUMP_BIT(version_v))) { + if (opt->dump & DUMP_BIT(version)) { ruby_show_version(); - if (opt->dump & DUMP_BIT(version)) return Qtrue; + return Qtrue; } if (opt->dump & DUMP_BIT(copyright)) { ruby_show_copyright(); @@ -1357,7 +1291,7 @@ process_options(int argc, char **argv, struct cmdline_options *opt) } else { opt->script = argv[0]; - if (!opt->script || opt->script[0] == '\0') { + if (opt->script[0] == '\0') { opt->script = "-"; } else if (opt->do_search) { @@ -1383,13 +1317,12 @@ process_options(int argc, char **argv, struct cmdline_options *opt) #if defined DOSISH || defined __CYGWIN__ translit_char(RSTRING_PTR(opt->script_name), '\\', '/'); #endif + rb_obj_freeze(opt->script_name); ruby_init_loadpath_safe(opt->safe_level); - Init_enc(); rb_enc_find_index("encdb"); lenc = rb_locale_encoding(); rb_enc_associate(rb_progname, lenc); - rb_obj_freeze(rb_progname); parser = rb_parser_new(); if (opt->dump & DUMP_BIT(yydebug)) { rb_parser_set_yydebug(parser, Qtrue); @@ -1417,30 +1350,27 @@ process_options(int argc, char **argv, struct cmdline_options *opt) opt->intern.enc.index = -1; } rb_enc_associate(opt->script_name, lenc); - rb_obj_freeze(opt->script_name); { long i; VALUE load_path = GET_VM()->load_path; for (i = 0; i < RARRAY_LEN(load_path); ++i) { - RARRAY_PTR(load_path)[i] = - rb_enc_associate(rb_str_dup(RARRAY_PTR(load_path)[i]), lenc); + rb_enc_associate(RARRAY_PTR(load_path)[i], lenc); } } - if (!(opt->disable & DISABLE_BIT(gems))) { -#if defined DISABLE_RUBYGEMS && DISABLE_RUBYGEMS - rb_require("rubygems"); -#else - rb_define_module("Gem"); -#endif - } - ruby_init_prelude(); + ruby_init_gems(!(opt->disable & DISABLE_BIT(gems))); ruby_set_argv(argc, argv); process_sflag(&opt->sflag); - toplevel_binding = rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING")); + { + /* set eval context */ + VALUE toplevel_binding = rb_const_get(rb_cObject, rb_intern("TOPLEVEL_BINDING")); + rb_binding_t *bind; + + GetBindingPtr(toplevel_binding, bind); + GetEnvPtr(bind->env, env); + } #define PREPARE_PARSE_MAIN(expr) do { \ - rb_env_t *env = toplevel_context(toplevel_binding); \ th->parse_in_eval--; \ th->base_block = &env->block; \ expr; \ @@ -1458,9 +1388,9 @@ process_options(int argc, char **argv, struct cmdline_options *opt) eenc = lenc; } rb_enc_associate(opt->e_script, eenc); - ruby_set_script_name(opt->script_name); + rb_vm_set_progname(rb_progname = opt->script_name); require_libraries(&opt->req_list); - ruby_set_script_name(progname); + rb_vm_set_progname(rb_progname = progname); PREPARE_PARSE_MAIN({ tree = rb_parser_compile_string(parser, opt->script, opt->e_script, 1); @@ -1472,10 +1402,11 @@ process_options(int argc, char **argv, struct cmdline_options *opt) } PREPARE_PARSE_MAIN({ - tree = load_file(parser, opt->script_name, 1, opt); + tree = load_file(parser, opt->script, 1, opt); }); } - ruby_set_script_name(opt->script_name); + rb_progname = opt->script_name; + rb_vm_set_progname(rb_progname); if (opt->dump & DUMP_BIT(yydebug)) return Qtrue; if (opt->ext.enc.index >= 0) { @@ -1533,9 +1464,7 @@ process_options(int argc, char **argv, struct cmdline_options *opt) PREPARE_PARSE_MAIN({ VALUE path = Qnil; - if (!opt->e_script && strcmp(opt->script, "-")) { - path = rb_realpath_internal(Qnil, opt->script_name, 1); - } + if (!opt->e_script && strcmp(opt->script, "-")) path = opt->script_name; iseq = rb_iseq_new_main(tree, opt->script_name, path); }); @@ -1550,14 +1479,13 @@ process_options(int argc, char **argv, struct cmdline_options *opt) rb_define_readonly_boolean("$-a", opt->do_split); rb_set_safe_level(opt->safe_level); - rb_gc_set_params(); return iseq; } struct load_file_arg { VALUE parser; - VALUE fname; + const char *fname; int script; struct cmdline_options *opt; }; @@ -1568,9 +1496,7 @@ load_file_internal(VALUE arg) extern VALUE rb_stdin; struct load_file_arg *argp = (struct load_file_arg *)arg; VALUE parser = argp->parser; - VALUE fname_v = rb_str_encode_ospath(argp->fname); - const char *fname = StringValueCStr(fname_v); - const char *orig_fname = StringValueCStr(argp->fname); + const char *fname = argp->fname; int script = argp->script; struct cmdline_options *opt = argp->opt; VALUE f; @@ -1578,8 +1504,9 @@ load_file_internal(VALUE arg) NODE *tree = 0; rb_encoding *enc; ID set_encoding; - int xflag = 0; + if (!fname) + rb_load_fail(fname); if (strcmp(fname, "-") == 0) { f = rb_stdin; } @@ -1588,27 +1515,14 @@ load_file_internal(VALUE arg) #if defined DOSISH || defined __CYGWIN__ { const char *ext = strrchr(fname, '.'); - if (ext && STRCASECMP(ext, ".exe") == 0) { + if (ext && STRCASECMP(ext, ".exe") == 0) mode |= O_BINARY; - xflag = 1; - } } #endif - if ((fd = rb_cloexec_open(fname, mode, 0)) < 0) { - rb_load_fail(fname_v, strerror(errno)); + if ((fd = open(fname, mode)) < 0) { + rb_load_fail(fname); } - rb_update_max_fd(fd); -#if !defined DOSISH && !defined __CYGWIN__ - { - struct stat st; - if (fstat(fd, &st) != 0) - rb_load_fail(fname_v, strerror(errno)); - if (S_ISDIR(st.st_mode)) { - errno = EISDIR; - rb_load_fail(fname_v, strerror(EISDIR)); - } - } -#endif + f = rb_io_fdopen(fd, mode, fname); } @@ -1624,7 +1538,7 @@ load_file_internal(VALUE arg) enc = rb_ascii8bit_encoding(); rb_funcall(f, set_encoding, 1, rb_enc_from_encoding(enc)); - if (xflag || opt->xflag) { + if (opt->xflag) { line_start--; search_shebang: forbid_setid("-x"); @@ -1639,7 +1553,7 @@ load_file_internal(VALUE arg) } } } - rb_loaderror("no Ruby script found in input"); + rb_raise(rb_eLoadError, "no Ruby script found in input"); } c = rb_io_getbyte(f); @@ -1689,7 +1603,7 @@ load_file_internal(VALUE arg) if (f != rb_stdin) rb_io_close(f); f = Qnil; } - ruby_set_script_name(opt->script_name); + rb_vm_set_progname(rb_progname = opt->script_name); require_libraries(&opt->req_list); /* Why here? unnatural */ } if (opt->src.enc.index >= 0) { @@ -1699,29 +1613,17 @@ load_file_internal(VALUE arg) enc = rb_locale_encoding(); } else { - enc = rb_utf8_encoding(); + enc = rb_usascii_encoding(); } if (NIL_P(f)) { f = rb_str_new(0, 0); rb_enc_associate(f, enc); - return (VALUE)rb_parser_compile_string(parser, orig_fname, f, line_start); + return (VALUE)rb_parser_compile_string(parser, fname, f, line_start); } rb_funcall(f, set_encoding, 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-")); - tree = rb_parser_compile_file(parser, orig_fname, f, line_start); + tree = rb_parser_compile_file(parser, fname, f, line_start); rb_funcall(f, set_encoding, 1, rb_parser_encoding(parser)); if (script && tree && rb_parser_end_seen_p(parser)) { - /* - * DATA is a File that contains the data section of the executed file. - * To create a data section use <tt>__END__</tt>: - * - * $ cat t.rb - * puts DATA.gets - * __END__ - * hello world! - * - * $ ruby t.rb - * hello world! - */ rb_define_global_const("DATA", f); } else if (f != rb_stdin) { @@ -1737,7 +1639,7 @@ restore_lineno(VALUE lineno) } static NODE * -load_file(VALUE parser, VALUE fname, int script, struct cmdline_options *opt) +load_file(VALUE parser, const char *fname, int script, struct cmdline_options *opt) { struct load_file_arg arg; arg.parser = parser; @@ -1751,11 +1653,66 @@ void * rb_load_file(const char *fname) { struct cmdline_options opt; - VALUE fname_v = rb_str_new_cstr(fname); - return load_file(rb_parser_new(), fname_v, 0, cmdline_options_init(&opt)); + return load_file(rb_parser_new(), fname, 0, cmdline_options_init(&opt)); } +#if !defined(PSTAT_SETCMD) && !defined(HAVE_SETPROCTITLE) +#if !defined(_WIN32) +#define USE_ENVSPACE_FOR_ARG0 +#endif + +#ifdef USE_ENVSPACE_FOR_ARG0 +extern char **environ; +#endif + +static size_t +get_arglen(int argc, char **argv) +{ + char *s = argv[0]; + int i; + + if (!argc) return 0; + s += strlen(s); + /* See if all the arguments are contiguous in memory */ + for (i = 1; i < argc; i++) { + if (argv[i] == s + 1) { + s++; + s += strlen(s); /* this one is ok too */ + } + else { + break; + } + } +#if defined(USE_ENVSPACE_FOR_ARG0) + if (environ && (s+1 == environ[0])) { + s++; + s += strlen(s); + for (i = 1; environ[i]; i++) { + if (environ[i] == s + 1) { + s++; + s += strlen(s); /* this one is ok too */ + } + } +# if defined(HAVE_SETENV) && defined(HAVE_UNSETENV) + { + char *t = malloc(s - environ[0] + 1); + for (i = 0; environ[i]; i++) { + size_t len = strlen(environ[i]) + 1; + memcpy(t, environ[i], len); + environ[i] = t; + t += len; + } + } +# else + ruby_setenv("", NULL); /* duplicate environ vars */ +# endif + } +#endif + return s - argv[0]; +} +#endif + static void set_arg0(VALUE val, ID id) { @@ -1767,37 +1724,54 @@ set_arg0(VALUE val, ID id) StringValue(val); s = RSTRING_PTR(val); i = RSTRING_LEN(val); - +#if defined(PSTAT_SETCMD) + if (i > PST_CLEN) { + union pstun un; + char buf[PST_CLEN + 1]; /* PST_CLEN is 64 (HP-UX 11.23) */ + strlcpy(buf, s, sizeof(buf)); + un.pst_command = buf; + pstat(PSTAT_SETCMD, un, PST_CLEN, 0, 0); + } + else { + union pstun un; + un.pst_command = s; + pstat(PSTAT_SETCMD, un, i, 0, 0); + } +#elif defined(HAVE_SETPROCTITLE) setproctitle("%.*s", (int)i, s); +#else + + if ((size_t)i > origarg.len - origarg.argc) { + i = (long)(origarg.len - origarg.argc); + } + + memcpy(origarg.argv[0], s, i); + + { + int j; + char *t = origarg.argv[0] + i; + *t = '\0'; + if ((size_t)(i + 1) < origarg.len) { + memset(t + 1, '\0', origarg.len - i - 1); + } + for (j = 1; j < origarg.argc; j++) { + origarg.argv[j] = t; + } + } +#endif rb_progname = rb_obj_freeze(rb_external_str_new(s, i)); } -/*! Sets the current script name to this value. - * - * This is similiar to <code>$0 = name</code> in Ruby level but also affects - * <code>Method#location</code> and others. - */ void ruby_script(const char *name) { if (name) { - rb_progname = rb_external_str_new(name, strlen(name)); + rb_progname = rb_obj_freeze(rb_external_str_new(name, strlen(name))); rb_vm_set_progname(rb_progname); } } -/*! Sets the current script name to this value. - * - * Same as ruby_script() but accepts a VALUE. - */ -void -ruby_set_script_name(VALUE name) -{ - rb_progname = rb_str_dup(name); - rb_vm_set_progname(rb_progname); -} - static void init_ids(struct cmdline_options *opt) { @@ -1843,12 +1817,10 @@ opt_W_getter(ID id, void *data) return INT2FIX(1); case Qtrue: return INT2FIX(2); - default: - return Qnil; } + return Qnil; /* not reached */ } -/*! Defines built-in variables */ void ruby_prog_init(void) { @@ -1862,13 +1834,6 @@ ruby_prog_init(void) rb_define_hooked_variable("$0", &rb_progname, 0, set_arg0); rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0); - /* - * ARGV contains the command line arguments used to run ruby with the - * first value containing the name of the executable. - * - * A library like OptionParser can be used to process command-line - * arguments. - */ rb_define_global_const("ARGV", rb_argv); } @@ -1886,7 +1851,7 @@ ruby_set_argv(int argc, char **argv) #endif rb_ary_clear(av); for (i = 0; i < argc; i++) { - VALUE arg = rb_external_str_new_cstr(argv[i]); + VALUE arg = rb_external_str_new(argv[i], strlen(argv[i])); OBJ_FREEZE(arg); rb_ary_push(av, arg); @@ -1898,59 +1863,14 @@ ruby_process_options(int argc, char **argv) { struct cmdline_options opt; VALUE iseq; - const char *script_name = (argc > 0 && argv[0]) ? argv[0] : "ruby"; - ruby_script(script_name); /* for the time being */ + ruby_script(argv[0]); /* for the time being */ rb_argv0 = rb_str_new4(rb_progname); rb_gc_register_mark_object(rb_argv0); iseq = process_options(argc, argv, cmdline_options_init(&opt)); - -#ifndef HAVE_SETPROCTITLE - { - extern void ruby_init_setproctitle(int argc, char *argv[]); - ruby_init_setproctitle(argc, argv); - } -#endif - return (void*)(struct RData*)iseq; } -static void -fill_standard_fds(void) -{ - int f0, f1, f2, fds[2]; - struct stat buf; - f0 = fstat(0, &buf) == -1 && errno == EBADF; - f1 = fstat(1, &buf) == -1 && errno == EBADF; - f2 = fstat(2, &buf) == -1 && errno == EBADF; - if (f0) { - if (pipe(fds) == 0) { - close(fds[1]); - if (fds[0] != 0) { - dup2(fds[0], 0); - close(fds[0]); - } - } - } - if (f1 || f2) { - if (pipe(fds) == 0) { - close(fds[0]); - if (f1 && fds[1] != 1) - dup2(fds[1], 1); - if (f2 && fds[1] != 2) - dup2(fds[1], 2); - if (fds[1] != 1 && fds[1] != 2) - close(fds[1]); - } - } -} - -/*! Initializes the process for ruby(1). - * - * This function assumes this process is ruby(1) and it has just started. - * Usually programs that embeds CRuby interpreter should not call this function, - * and should do their own initialization. - */ void ruby_sysinit(int *argc, char ***argv) { @@ -1960,8 +1880,10 @@ ruby_sysinit(int *argc, char ***argv) #endif origarg.argc = *argc; origarg.argv = *argv; +#if !defined(PSTAT_SETCMD) && !defined(HAVE_SETPROCTITLE) + origarg.len = get_arglen(origarg.argc, origarg.argv); +#endif #if defined(USE_DLN_A_OUT) dln_argv0 = origarg.argv[0]; #endif - fill_standard_fds(); } |
