Skip to content

Commit 9de7130

Browse files
committed
Support short options concatenation to mruby command
#### Before this patch: ``` $ bin/mruby -ce 1 bin/mruby: Cannot open program file: 1 ``` #### After this patch: ``` $ bin/mruby -ce 1 Syntax OK ```
1 parent 74310f4 commit 9de7130

File tree

2 files changed

+106
-70
lines changed

2 files changed

+106
-70
lines changed

Diff for: mrbgems/mruby-bin-mruby/bintest/mruby.rb

+2-4
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,8 @@ def assert_mruby(exp_out, exp_err, exp_success, args)
8080
end
8181

8282
assert('mruby -d option') do
83-
o = `#{cmd('mruby')} -e #{shellquote('p $DEBUG')}`
84-
assert_equal "false\n", o
85-
o = `#{cmd('mruby')} -d -e #{shellquote('p $DEBUG')}`
86-
assert_equal "true\n", o
83+
assert_mruby("false\n", "", true, ["-e", "p $DEBUG"])
84+
assert_mruby("true\n", "", true, ["-dep $DEBUG"])
8785
end
8886

8987
assert('mruby -e option (no code specified)') do

Diff for: mrbgems/mruby-bin-mruby/tools/mruby/mruby.c

+104-66
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,26 @@
99

1010
struct _args {
1111
FILE *rfp;
12-
char* cmdline;
12+
char *cmdline;
1313
mrb_bool fname : 1;
1414
mrb_bool mrbfile : 1;
1515
mrb_bool check_syntax : 1;
1616
mrb_bool verbose : 1;
1717
mrb_bool debug : 1;
1818
int argc;
19-
char** argv;
19+
char **argv;
2020
int libc;
2121
char **libv;
2222
};
2323

24+
struct options {
25+
int argc;
26+
char **argv;
27+
char *program;
28+
char *opt;
29+
char short_opt[2];
30+
};
31+
2432
static void
2533
usage(const char *name)
2634
{
@@ -44,6 +52,51 @@ usage(const char *name)
4452
printf(" %s\n", *p++);
4553
}
4654

55+
static void
56+
options_init(struct options *opts, int argc, char **argv)
57+
{
58+
opts->argc = argc;
59+
opts->argv = argv;
60+
opts->program = *argv;
61+
*opts->short_opt = 0;
62+
}
63+
64+
static const char *
65+
options_opt(struct options *opts)
66+
{
67+
if (*opts->short_opt && *++opts->opt) {
68+
short_opt:
69+
opts->short_opt[0] = *opts->opt;
70+
opts->short_opt[1] = 0;
71+
return opts->short_opt;
72+
}
73+
while (++opts->argv, --opts->argc) {
74+
opts->opt = *opts->argv;
75+
if (!opts->opt[0] || opts->opt[0] != '-' || !opts->opt[1]) return NULL;
76+
if (opts->opt[1] == '-') {
77+
opts->opt += 2;
78+
*opts->short_opt = 0;
79+
return opts->opt;
80+
}
81+
else {
82+
++opts->opt;
83+
goto short_opt;
84+
}
85+
}
86+
return NULL;
87+
}
88+
89+
static const char *
90+
options_arg(struct options *opts)
91+
{
92+
if (*opts->short_opt && opts->opt[1]) {
93+
*opts->short_opt = 0;
94+
return opts->opt + 1;
95+
}
96+
--opts->argc, ++opts->argv;
97+
return opts->argc ? *opts->argv : NULL;
98+
}
99+
47100
static char *
48101
dup_arg_item(mrb_state *mrb, const char *item)
49102
{
@@ -56,40 +109,24 @@ dup_arg_item(mrb_state *mrb, const char *item)
56109
static int
57110
parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
58111
{
59-
char **origargv = argv;
60112
static const struct _args args_zero = { 0 };
113+
struct options opts[1];
114+
const char *opt, *item;
61115

62116
*args = args_zero;
63-
64-
for (argc--,argv++; argc > 0; argc--,argv++) {
65-
char *item;
66-
if (argv[0][0] != '-') break;
67-
68-
if (strlen(*argv) <= 1) {
69-
argc--; argv++;
70-
args->rfp = stdin;
71-
break;
72-
}
73-
74-
item = argv[0] + 1;
75-
switch (*item++) {
76-
case 'b':
117+
options_init(opts, argc, argv);
118+
while ((opt = options_opt(opts))) {
119+
if (strcmp(opt, "b") == 0) {
77120
args->mrbfile = TRUE;
78-
break;
79-
case 'c':
121+
}
122+
else if (strcmp(opt, "c") == 0) {
80123
args->check_syntax = TRUE;
81-
break;
82-
case 'd':
124+
}
125+
else if (strcmp(opt, "d") == 0) {
83126
args->debug = TRUE;
84-
break;
85-
case 'e':
86-
if (item[0]) {
87-
goto append_cmdline;
88-
}
89-
else if (argc > 1) {
90-
argc--; argv++;
91-
item = argv[0];
92-
append_cmdline:
127+
}
128+
else if (strcmp(opt, "e") == 0) {
129+
if ((item = options_arg(opts))) {
93130
if (!args->cmdline) {
94131
args->cmdline = dup_arg_item(mrb, item);
95132
}
@@ -106,59 +143,60 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
106143
}
107144
}
108145
else {
109-
fprintf(stderr, "%s: No code specified for -e\n", *origargv);
146+
fprintf(stderr, "%s: No code specified for -e\n", opts->program);
110147
return EXIT_FAILURE;
111148
}
112-
break;
113-
case 'h':
114-
usage(*origargv);
149+
}
150+
else if (strcmp(opt, "h") == 0) {
151+
usage(opts->program);
115152
exit(EXIT_SUCCESS);
116-
case 'r':
117-
if (!item[0]) {
118-
if (argc <= 1) {
119-
fprintf(stderr, "%s: No library specified for -r\n", *origargv);
120-
return EXIT_FAILURE;
153+
}
154+
else if (strcmp(opt, "r") == 0) {
155+
if ((item = options_arg(opts))) {
156+
if (args->libc == 0) {
157+
args->libv = (char**)mrb_malloc(mrb, sizeof(char*));
121158
}
122-
argc--; argv++;
123-
item = argv[0];
124-
}
125-
if (args->libc == 0) {
126-
args->libv = (char**)mrb_malloc(mrb, sizeof(char*));
159+
else {
160+
args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1));
161+
}
162+
args->libv[args->libc++] = dup_arg_item(mrb, item);
127163
}
128164
else {
129-
args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1));
165+
fprintf(stderr, "%s: No library specified for -r\n", opts->program);
166+
return EXIT_FAILURE;
130167
}
131-
args->libv[args->libc++] = dup_arg_item(mrb, item);
132-
break;
133-
case 'v':
168+
}
169+
else if (strcmp(opt, "v") == 0) {
134170
if (!args->verbose) mrb_show_version(mrb);
135171
args->verbose = TRUE;
172+
}
173+
else if (strcmp(opt, "version") == 0) {
174+
mrb_show_version(mrb);
175+
exit(EXIT_SUCCESS);
176+
}
177+
else if (strcmp(opt, "verbose") == 0) {
178+
args->verbose = TRUE;
136179
break;
137-
case '-':
138-
if (strcmp((*argv) + 2, "version") == 0) {
139-
mrb_show_version(mrb);
140-
exit(EXIT_SUCCESS);
141-
}
142-
else if (strcmp((*argv) + 2, "verbose") == 0) {
143-
args->verbose = TRUE;
144-
break;
145-
}
146-
else if (strcmp((*argv) + 2, "copyright") == 0) {
147-
mrb_show_copyright(mrb);
148-
exit(EXIT_SUCCESS);
149-
}
150-
default:
151-
fprintf(stderr, "%s: invalid option %s (-h will show valid options)\n", *origargv, *argv);
180+
}
181+
else if (strcmp(opt, "copyright") == 0) {
182+
mrb_show_copyright(mrb);
183+
exit(EXIT_SUCCESS);
184+
}
185+
else {
186+
fprintf(stderr, "%s: invalid option %s%s (-h will show valid options)\n",
187+
opts->program, opt[1] ? "--" : "-", opt);
152188
return EXIT_FAILURE;
153189
}
154190
}
155191

156-
if (args->rfp == NULL && args->cmdline == NULL) {
192+
if (args->cmdline == NULL) {
193+
argc = opts->argc; argv = opts->argv;
157194
if (*argv == NULL) args->rfp = stdin;
158195
else {
159-
args->rfp = fopen(argv[0], args->mrbfile ? "rb" : "r");
196+
args->rfp = strcmp(argv[0], "-") == 0 ?
197+
stdin : fopen(argv[0], args->mrbfile ? "rb" : "r");
160198
if (args->rfp == NULL) {
161-
fprintf(stderr, "%s: Cannot open program file: %s\n", *origargv, *argv);
199+
fprintf(stderr, "%s: Cannot open program file: %s\n", opts->program, argv[0]);
162200
return EXIT_FAILURE;
163201
}
164202
args->fname = TRUE;

0 commit comments

Comments
 (0)