From 5cdd7f52cc2c6cc25200e1738f53421b18698836 Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 30 Oct 2008 01:34:23 +0000 Subject: [PATCH] * ruby.c (moreswitches): splits option string and passes arguments. * ruby.c (proc_options): checks if allowed in RUBYOPT. * ruby.c (process_options): allows long style options in RUBYOPT. * ruby.c (load_file_internal): ditto in shebang. [ruby-dev:36979] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20053 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 10 +++ ruby.c | 189 +++++++++++++++++++++++++++++++----------------------- 2 files changed, 117 insertions(+), 82 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6a294b4029..438467f797 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +Thu Oct 30 10:34:20 2008 Nobuyoshi Nakada + + * ruby.c (moreswitches): splits option string and passes arguments. + + * ruby.c (proc_options): checks if allowed in RUBYOPT. + + * ruby.c (process_options): allows long style options in RUBYOPT. + + * ruby.c (load_file_internal): ditto in shebang. [ruby-dev:36979] + Thu Oct 30 09:31:45 2008 Nobuyoshi Nakada * encoding.c (rb_locale_encoding): makes an alias for locale. diff --git a/ruby.c b/ruby.c index 7bbc5b0139..eb93fc3dfe 100644 --- a/ruby.c +++ b/ruby.c @@ -514,27 +514,53 @@ process_sflag(struct cmdline_options *opt) NODE *rb_parser_append_print(VALUE, NODE *); NODE *rb_parser_while_loop(VALUE, NODE *, int, int); -static int proc_options(int argc, char **argv, struct cmdline_options *opt); +static int proc_options(int argc, char **argv, struct cmdline_options *opt, int envopt); -static char * -moreswitches(const char *s, struct cmdline_options *opt) +static void +moreswitches(const char *s, struct cmdline_options *opt, int envopt) { - int argc; - char *argv[3]; - const char *p = s; + int argc, i; + char **argv, *p; + const char *ap = 0; + VALUE argstr, argary; - argc = 2; - argv[0] = argv[2] = 0; - while (*s && !ISSPACE(*s)) - s++; - argv[1] = ALLOCA_N(char, s - p + 2); - argv[1][0] = '-'; - strncpy(argv[1] + 1, p, s - p); - argv[1][s - p + 1] = '\0'; - proc_options(argc, argv, opt); - while (*s && ISSPACE(*s)) - s++; - return (char *)s; + while (ISSPACE(*s)) s++; + if (!*s) return; + argstr = rb_str_tmp_new(strlen(s) + 2); + argary = rb_str_tmp_new(0); + + p = RSTRING_PTR(argstr); + *p++ = ' '; + strcpy(p, s); + ap = 0; + rb_str_cat(argary, (char *)&ap, sizeof(ap)); + while (*p) { + ap = p; + rb_str_cat(argary, (char *)&ap, sizeof(ap)); + while (*p && !ISSPACE(*p)) ++p; + if (!*p) break; + *p++ = '\0'; + while (ISSPACE(*p)) ++p; + } + argc = RSTRING_LEN(argary) / sizeof(ap); + ap = 0; + rb_str_cat(argary, (char *)&ap, sizeof(ap)); + argv = (char **)RSTRING_PTR(argary); + + while ((i = proc_options(argc, argv, opt, envopt)) > 1 && (argc -= i) > 0) { + argv += i; + if (**argv != '-') { + *--*argv = '-'; + } + if ((*argv)[1]) { + ++argc; + --argv; + } + } + + /* get rid of GC */ + rb_str_resize(argary, 0); + rb_str_resize(argstr, 0); } #define NAME_MATCH_P(name, str, len) \ @@ -619,7 +645,7 @@ set_external_encoding_once(struct cmdline_options *opt, const char *e, int elen) } static int -proc_options(int argc, char **argv, struct cmdline_options *opt) +proc_options(int argc, char **argv, struct cmdline_options *opt, int envopt) { int n, argc0 = argc; const char *s; @@ -635,14 +661,17 @@ proc_options(int argc, char **argv, struct cmdline_options *opt) reswitch: switch (*s) { case 'a': + if (envopt) goto noenvopt; opt->do_split = Qtrue; s++; goto reswitch; case 'p': + if (envopt) goto noenvopt; opt->do_print = Qtrue; /* through */ case 'n': + if (envopt) goto noenvopt; opt->do_loop = Qtrue; s++; goto reswitch; @@ -654,6 +683,7 @@ proc_options(int argc, char **argv, struct cmdline_options *opt) goto reswitch; case 'y': + if (envopt) goto noenvopt; opt->yydebug = 1; s++; goto reswitch; @@ -696,34 +726,40 @@ proc_options(int argc, char **argv, struct cmdline_options *opt) goto reswitch; case 'c': + if (envopt) goto noenvopt; opt->do_check = Qtrue; s++; goto reswitch; case 's': + if (envopt) goto noenvopt; forbid_setid("-s"); opt->sflag = 1; s++; goto reswitch; case 'h': + if (envopt) goto noenvopt; usage(origarg.argv[0]); rb_exit(EXIT_SUCCESS); break; case 'l': + if (envopt) goto noenvopt; opt->do_line = Qtrue; rb_output_rs = rb_rs; s++; goto reswitch; case 'S': + if (envopt) goto noenvopt; forbid_setid("-S"); opt->do_search = Qtrue; s++; goto reswitch; case 'e': + if (envopt) goto noenvopt; forbid_setid("-e"); if (!*++s) { s = argv[1]; @@ -753,11 +789,13 @@ proc_options(int argc, char **argv, struct cmdline_options *opt) break; case 'i': + if (envopt) goto noenvopt; forbid_setid("-i"); ruby_set_inplace_mode(s + 1); break; case 'x': + if (envopt) goto noenvopt; opt->xflag = Qtrue; s++; if (*s && chdir(s) < 0) { @@ -767,6 +805,7 @@ proc_options(int argc, char **argv, struct cmdline_options *opt) case 'C': case 'X': + if (envopt) goto noenvopt; s++; if (!*s) { s = argv[1]; @@ -781,13 +820,16 @@ proc_options(int argc, char **argv, struct cmdline_options *opt) break; case 'F': + if (envopt) goto noenvopt; if (*++s) { rb_fs = rb_reg_new(s, strlen(s), 0); } break; case 'E': - if (!*++s) goto next_encoding; + if (!*++s && (!--argc || !(s = *++argv))) { + rb_raise(rb_eRuntimeError, "missing argument for -E"); + } goto encoding; case 'U': @@ -847,6 +889,7 @@ proc_options(int argc, char **argv, struct cmdline_options *opt) break; case '0': + if (envopt) goto noenvopt; { int numlen; int v; @@ -872,35 +915,36 @@ proc_options(int argc, char **argv, struct cmdline_options *opt) goto switch_end; } s++; - if (strcmp("copyright", s) == 0) + +# define is_option_end(c, allow_hyphen) \ + (!(c) || (allow_hyphen && (c) == '-') || (c) == '=') +# define check_envopt(name, allow_envopt) \ + ((allow_envopt || !envopt) ? (void)0 : \ + rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --" name)) +# define need_argument(name, s) \ + ((*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) + + if (strcmp("copyright", s) == 0) { + if (envopt) goto noenvopt_long; opt->copyright = 1; + } else if (strcmp("debug", s) == 0) { ruby_debug = Qtrue; ruby_verbose = Qtrue; } - else if (strncmp("enable", s, n = 6) == 0 && - (!s[n] || s[n] == '-' || s[n] == '=')) { - if ((s += n + 1)[-1] ? !*s : (!--argc || !(s = *++argv))) { - rb_raise(rb_eRuntimeError, "missing argument for --enable"); - } + else if (is_option_with_arg("enable", Qtrue, Qtrue)) { ruby_each_words(s, enable_option, &opt->disable); } - else if (strncmp("disable", s, n = 7) == 0 && - (!s[n] || s[n] == '-' || s[n] == '=')) { - if ((s += n + 1)[-1] ? !*s : (!--argc || !(s = *++argv))) { - rb_raise(rb_eRuntimeError, "missing argument for --disable"); - } + else if (is_option_with_arg("disable", Qtrue, Qtrue)) { ruby_each_words(s, disable_option, &opt->disable); } - else if (strncmp("encoding", s, n = 8) == 0 && (!s[n] || s[n] == '=')) { + else if (is_option_with_arg("encoding", Qfalse, Qtrue)) { char *p; - s += n; - if (!*s++) { - next_encoding: - if (!--argc || !(s = *++argv)) { - rb_raise(rb_eRuntimeError, "missing argument for --encoding"); - } - } encoding: p = strchr(s, ':'); if (p) { @@ -912,19 +956,23 @@ proc_options(int argc, char **argv, struct cmdline_options *opt) else set_external_encoding_once(opt, s, 0); } - else if (strcmp("version", s) == 0) + else if (strcmp("version", s) == 0) { + if (envopt) goto noenvopt_long; opt->version = 1; + } else if (strcmp("verbose", s) == 0) { opt->verbose = 1; ruby_verbose = Qtrue; } - else if (strcmp("yydebug", s) == 0) + else if (strcmp("yydebug", s) == 0) { + if (envopt) goto noenvopt_long; opt->yydebug = 1; - else if (strncmp("dump", s, n = 4) == 0 && (!s[n] || s[n] == '=')) { - if (!(s += n + 1)[-1] && (!--argc || !(s = *++argv)) && *s != '-') break; + } + else if (is_option_with_arg("dump", Qfalse, Qfalse)) { ruby_each_words(s, dump_option, &opt->dump); } else if (strcmp("help", s) == 0) { + if (envopt) goto noenvopt_long; usage(origarg.argv[0]); rb_exit(EXIT_SUCCESS); } @@ -953,8 +1001,21 @@ proc_options(int argc, char **argv, struct cmdline_options *opt) } goto switch_end; + noenvopt: + /* "EIdvwWrKU" only */ + rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: -%c", *s); + break; + + noenvopt_long: + rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --%s", s); + break; + case 0: break; +# undef is_option_end +# undef check_envopt +# undef need_argument +# undef is_option_with_arg } } @@ -1002,7 +1063,7 @@ process_options(VALUE arg) rb_encoding *enc, *lenc; const char *s; char fbuf[MAXPATHLEN]; - int i = proc_options(argc, argv, opt); + int i = proc_options(argc, argv, opt, 0); int safe; argc -= i; @@ -1015,40 +1076,7 @@ process_options(VALUE arg) VALUE int_enc_name = opt->intern.enc.name; opt->src.enc.name = opt->ext.enc.name = opt->intern.enc.name = 0; - while (ISSPACE(*s)) - s++; - if (*s == 'T' || (*s == '-' && *(s + 1) == 'T')) { - int numlen; - int v = 1; - - if (*s != 'T') - ++s; - if (*++s) { - v = scan_oct(s, 2, &numlen); - if (numlen == 0) - v = 1; - } - rb_set_safe_level(v); - } - else { - while (s && *s) { - if (*s == '-') { - s++; - if (ISSPACE(*s)) { - do { - s++; - } while (ISSPACE(*s)); - continue; - } - } - if (!*s) - break; - if (!strchr("EIdvwWrKU", *s)) - rb_raise(rb_eRuntimeError, - "invalid switch in RUBYOPT: -%c", *s); - s = moreswitches(s, opt); - } - } + moreswitches(s, opt, 1); if (src_enc_name) opt->src.enc.name = src_enc_name; if (ext_enc_name) @@ -1320,10 +1348,7 @@ load_file_internal(VALUE arg) if (RSTRING_PTR(line)[RSTRING_LEN(line) - 2] == '\r') RSTRING_PTR(line)[RSTRING_LEN(line) - 2] = '\0'; if ((p = strstr(p, " -")) != 0) { - p++; /* skip space before `-' */ - while (*p == '-') { - p = moreswitches(p + 1, opt); - } + moreswitches(p + 1, opt, 0); } /* push back shebang for pragma may exist in next line */