Unverified Commit a89d15cd authored by Yukihiro "Matz" Matsumoto's avatar Yukihiro "Matz" Matsumoto Committed by GitHub

Merge pull request #4827 from shuujii/support-short-options-concatenation-to-mruby-command

Support short options concatenation to `mruby` command
parents 1d1c8125 9de7130a
...@@ -80,10 +80,8 @@ assert('mruby -c option') do ...@@ -80,10 +80,8 @@ assert('mruby -c option') do
end end
assert('mruby -d option') do assert('mruby -d option') do
o = `#{cmd('mruby')} -e #{shellquote('p $DEBUG')}` assert_mruby("false\n", "", true, ["-e", "p $DEBUG"])
assert_equal "false\n", o assert_mruby("true\n", "", true, ["-dep $DEBUG"])
o = `#{cmd('mruby')} -d -e #{shellquote('p $DEBUG')}`
assert_equal "true\n", o
end end
assert('mruby -e option (no code specified)') do assert('mruby -e option (no code specified)') do
......
...@@ -9,18 +9,26 @@ ...@@ -9,18 +9,26 @@
struct _args { struct _args {
FILE *rfp; FILE *rfp;
char* cmdline; char *cmdline;
mrb_bool fname : 1; mrb_bool fname : 1;
mrb_bool mrbfile : 1; mrb_bool mrbfile : 1;
mrb_bool check_syntax : 1; mrb_bool check_syntax : 1;
mrb_bool verbose : 1; mrb_bool verbose : 1;
mrb_bool debug : 1; mrb_bool debug : 1;
int argc; int argc;
char** argv; char **argv;
int libc; int libc;
char **libv; char **libv;
}; };
struct options {
int argc;
char **argv;
char *program;
char *opt;
char short_opt[2];
};
static void static void
usage(const char *name) usage(const char *name)
{ {
...@@ -44,6 +52,51 @@ usage(const char *name) ...@@ -44,6 +52,51 @@ usage(const char *name)
printf(" %s\n", *p++); printf(" %s\n", *p++);
} }
static void
options_init(struct options *opts, int argc, char **argv)
{
opts->argc = argc;
opts->argv = argv;
opts->program = *argv;
*opts->short_opt = 0;
}
static const char *
options_opt(struct options *opts)
{
if (*opts->short_opt && *++opts->opt) {
short_opt:
opts->short_opt[0] = *opts->opt;
opts->short_opt[1] = 0;
return opts->short_opt;
}
while (++opts->argv, --opts->argc) {
opts->opt = *opts->argv;
if (!opts->opt[0] || opts->opt[0] != '-' || !opts->opt[1]) return NULL;
if (opts->opt[1] == '-') {
opts->opt += 2;
*opts->short_opt = 0;
return opts->opt;
}
else {
++opts->opt;
goto short_opt;
}
}
return NULL;
}
static const char *
options_arg(struct options *opts)
{
if (*opts->short_opt && opts->opt[1]) {
*opts->short_opt = 0;
return opts->opt + 1;
}
--opts->argc, ++opts->argv;
return opts->argc ? *opts->argv : NULL;
}
static char * static char *
dup_arg_item(mrb_state *mrb, const char *item) dup_arg_item(mrb_state *mrb, const char *item)
{ {
...@@ -56,40 +109,24 @@ dup_arg_item(mrb_state *mrb, const char *item) ...@@ -56,40 +109,24 @@ dup_arg_item(mrb_state *mrb, const char *item)
static int static int
parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args) parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
{ {
char **origargv = argv;
static const struct _args args_zero = { 0 }; static const struct _args args_zero = { 0 };
struct options opts[1];
const char *opt, *item;
*args = args_zero; *args = args_zero;
options_init(opts, argc, argv);
for (argc--,argv++; argc > 0; argc--,argv++) { while ((opt = options_opt(opts))) {
char *item; if (strcmp(opt, "b") == 0) {
if (argv[0][0] != '-') break;
if (strlen(*argv) <= 1) {
argc--; argv++;
args->rfp = stdin;
break;
}
item = argv[0] + 1;
switch (*item++) {
case 'b':
args->mrbfile = TRUE; args->mrbfile = TRUE;
break; }
case 'c': else if (strcmp(opt, "c") == 0) {
args->check_syntax = TRUE; args->check_syntax = TRUE;
break; }
case 'd': else if (strcmp(opt, "d") == 0) {
args->debug = TRUE; args->debug = TRUE;
break;
case 'e':
if (item[0]) {
goto append_cmdline;
} }
else if (argc > 1) { else if (strcmp(opt, "e") == 0) {
argc--; argv++; if ((item = options_arg(opts))) {
item = argv[0];
append_cmdline:
if (!args->cmdline) { if (!args->cmdline) {
args->cmdline = dup_arg_item(mrb, item); args->cmdline = dup_arg_item(mrb, item);
} }
...@@ -106,22 +143,16 @@ append_cmdline: ...@@ -106,22 +143,16 @@ append_cmdline:
} }
} }
else { else {
fprintf(stderr, "%s: No code specified for -e\n", *origargv); fprintf(stderr, "%s: No code specified for -e\n", opts->program);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
break;
case 'h':
usage(*origargv);
exit(EXIT_SUCCESS);
case 'r':
if (!item[0]) {
if (argc <= 1) {
fprintf(stderr, "%s: No library specified for -r\n", *origargv);
return EXIT_FAILURE;
} }
argc--; argv++; else if (strcmp(opt, "h") == 0) {
item = argv[0]; usage(opts->program);
exit(EXIT_SUCCESS);
} }
else if (strcmp(opt, "r") == 0) {
if ((item = options_arg(opts))) {
if (args->libc == 0) { if (args->libc == 0) {
args->libv = (char**)mrb_malloc(mrb, sizeof(char*)); args->libv = (char**)mrb_malloc(mrb, sizeof(char*));
} }
...@@ -129,36 +160,43 @@ append_cmdline: ...@@ -129,36 +160,43 @@ append_cmdline:
args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1)); args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1));
} }
args->libv[args->libc++] = dup_arg_item(mrb, item); args->libv[args->libc++] = dup_arg_item(mrb, item);
break; }
case 'v': else {
fprintf(stderr, "%s: No library specified for -r\n", opts->program);
return EXIT_FAILURE;
}
}
else if (strcmp(opt, "v") == 0) {
if (!args->verbose) mrb_show_version(mrb); if (!args->verbose) mrb_show_version(mrb);
args->verbose = TRUE; args->verbose = TRUE;
break; }
case '-': else if (strcmp(opt, "version") == 0) {
if (strcmp((*argv) + 2, "version") == 0) {
mrb_show_version(mrb); mrb_show_version(mrb);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
else if (strcmp((*argv) + 2, "verbose") == 0) { else if (strcmp(opt, "verbose") == 0) {
args->verbose = TRUE; args->verbose = TRUE;
break; break;
} }
else if (strcmp((*argv) + 2, "copyright") == 0) { else if (strcmp(opt, "copyright") == 0) {
mrb_show_copyright(mrb); mrb_show_copyright(mrb);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
default: else {
fprintf(stderr, "%s: invalid option %s (-h will show valid options)\n", *origargv, *argv); fprintf(stderr, "%s: invalid option %s%s (-h will show valid options)\n",
opts->program, opt[1] ? "--" : "-", opt);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
if (args->rfp == NULL && args->cmdline == NULL) { if (args->cmdline == NULL) {
argc = opts->argc; argv = opts->argv;
if (*argv == NULL) args->rfp = stdin; if (*argv == NULL) args->rfp = stdin;
else { else {
args->rfp = fopen(argv[0], args->mrbfile ? "rb" : "r"); args->rfp = strcmp(argv[0], "-") == 0 ?
stdin : fopen(argv[0], args->mrbfile ? "rb" : "r");
if (args->rfp == NULL) { if (args->rfp == NULL) {
fprintf(stderr, "%s: Cannot open program file: %s\n", *origargv, *argv); fprintf(stderr, "%s: Cannot open program file: %s\n", opts->program, argv[0]);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
args->fname = TRUE; args->fname = TRUE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment