source: EcnlProtoTool/trunk/prototool/src/mruby.c@ 439

Last change on this file since 439 was 439, checked in by coas-nagasima, 4 years ago

mrubyを2.1.1に更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 8.7 KB
Line 
1#include <mruby.h>
2
3#ifdef MRB_DISABLE_STDIO
4# error mruby-bin-mruby conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
5#endif
6
7#include <stdlib.h>
8#include <string.h>
9#include <mruby/array.h>
10#include <mruby/compile.h>
11#include <mruby/dump.h>
12#include <mruby/variable.h>
13
14struct _args {
15 FILE *rfp;
16 char *cmdline;
17 mrb_bool fname : 1;
18 mrb_bool mrbfile : 1;
19 mrb_bool check_syntax : 1;
20 mrb_bool verbose : 1;
21 mrb_bool version : 1;
22 mrb_bool debug : 1;
23 int argc;
24 char **argv;
25 int libc;
26 char **libv;
27};
28
29struct options {
30 int argc;
31 char **argv;
32 char *program;
33 char *opt;
34 char short_opt[2];
35};
36
37static void
38usage(const char *name)
39{
40 static const char *const usage_msg[] = {
41 "switches:",
42 "-b load and execute RiteBinary (mrb) file",
43 "-c check syntax only",
44 "-d set debugging flags (set $DEBUG to true)",
45 "-e 'command' one line of script",
46 "-r library load the library before executing your script",
47 "-v print version number, then run in verbose mode",
48 "--verbose run in verbose mode",
49 "--version print the version",
50 "--copyright print the copyright",
51 NULL
52 };
53 const char *const *p = usage_msg;
54
55 printf("Usage: %s [switches] [programfile] [arguments]\n", name);
56 while (*p)
57 printf(" %s\n", *p++);
58}
59
60static void
61options_init(struct options *opts, int argc, char **argv)
62{
63 opts->argc = argc;
64 opts->argv = argv;
65 opts->program = *argv;
66 *opts->short_opt = 0;
67}
68
69static const char *
70options_opt(struct options *opts)
71{
72 /* concatenated short options (e.g. `-cv`) */
73 if (*opts->short_opt && *++opts->opt) {
74 short_opt:
75 opts->short_opt[0] = *opts->opt;
76 opts->short_opt[1] = 0;
77 return opts->short_opt;
78 }
79
80 while (++opts->argv, --opts->argc) {
81 opts->opt = *opts->argv;
82
83 /* empty || not start with `-` || `-` */
84 if (!opts->opt[0] || opts->opt[0] != '-' || !opts->opt[1]) return NULL;
85
86 if (opts->opt[1] == '-') {
87 /* `--` */
88 if (!opts->opt[2]) {
89 ++opts->argv, --opts->argc;
90 return NULL;
91 }
92 /* long option */
93 opts->opt += 2;
94 *opts->short_opt = 0;
95 return opts->opt;
96 }
97 else {
98 /* short option */
99 ++opts->opt;
100 goto short_opt;
101 }
102 }
103 return NULL;
104}
105
106static const char *
107options_arg(struct options *opts)
108{
109 if (*opts->short_opt && opts->opt[1]) {
110 /* concatenated short option and option argument (e.g. `-rLIBRARY`) */
111 *opts->short_opt = 0;
112 return opts->opt + 1;
113 }
114 --opts->argc, ++opts->argv;
115 return opts->argc ? *opts->argv : NULL;
116}
117
118static char *
119dup_arg_item(mrb_state *mrb, const char *item)
120{
121 size_t buflen = strlen(item) + 1;
122 char *buf = (char*)mrb_malloc(mrb, buflen);
123 memcpy(buf, item, buflen);
124 return buf;
125}
126
127static int
128parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
129{
130 static const struct _args args_zero = { 0 };
131 struct options opts[1];
132 const char *opt, *item;
133
134 *args = args_zero;
135 options_init(opts, argc, argv);
136 while ((opt = options_opt(opts))) {
137 if (strcmp(opt, "b") == 0) {
138 args->mrbfile = TRUE;
139 }
140 else if (strcmp(opt, "c") == 0) {
141 args->check_syntax = TRUE;
142 }
143 else if (strcmp(opt, "d") == 0) {
144 args->debug = TRUE;
145 }
146 else if (strcmp(opt, "e") == 0) {
147 if ((item = options_arg(opts))) {
148 if (!args->cmdline) {
149 args->cmdline = dup_arg_item(mrb, item);
150 }
151 else {
152 size_t cmdlinelen;
153 size_t itemlen;
154
155 cmdlinelen = strlen(args->cmdline);
156 itemlen = strlen(item);
157 args->cmdline =
158 (char *)mrb_realloc(mrb, args->cmdline, cmdlinelen + itemlen + 2);
159 args->cmdline[cmdlinelen] = '\n';
160 memcpy(args->cmdline + cmdlinelen + 1, item, itemlen + 1);
161 }
162 }
163 else {
164 fprintf(stderr, "%s: No code specified for -e\n", opts->program);
165 return EXIT_FAILURE;
166 }
167 }
168 else if (strcmp(opt, "h") == 0) {
169 usage(opts->program);
170 exit(EXIT_SUCCESS);
171 }
172 else if (strcmp(opt, "r") == 0) {
173 if ((item = options_arg(opts))) {
174 if (args->libc == 0) {
175 args->libv = (char**)mrb_malloc(mrb, sizeof(char*));
176 }
177 else {
178 args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1));
179 }
180 args->libv[args->libc++] = dup_arg_item(mrb, item);
181 }
182 else {
183 fprintf(stderr, "%s: No library specified for -r\n", opts->program);
184 return EXIT_FAILURE;
185 }
186 }
187 else if (strcmp(opt, "v") == 0) {
188 if (!args->verbose) {
189 mrb_show_version(mrb);
190 args->version = TRUE;
191 }
192 args->verbose = TRUE;
193 }
194 else if (strcmp(opt, "version") == 0) {
195 mrb_show_version(mrb);
196 exit(EXIT_SUCCESS);
197 }
198 else if (strcmp(opt, "verbose") == 0) {
199 args->verbose = TRUE;
200 }
201 else if (strcmp(opt, "copyright") == 0) {
202 mrb_show_copyright(mrb);
203 exit(EXIT_SUCCESS);
204 }
205 else {
206 fprintf(stderr, "%s: invalid option %s%s (-h will show valid options)\n",
207 opts->program, opt[1] ? "--" : "-", opt);
208 return EXIT_FAILURE;
209 }
210 }
211
212 argc = opts->argc; argv = opts->argv;
213 if (args->cmdline == NULL) {
214 if (*argv == NULL) {
215 if (args->version) exit(EXIT_SUCCESS);
216 args->rfp = stdin;
217 }
218 else {
219 args->rfp = strcmp(argv[0], "-") == 0 ?
220 stdin : fopen(argv[0], args->mrbfile ? "rb" : "r");
221 if (args->rfp == NULL) {
222 fprintf(stderr, "%s: Cannot open program file: %s\n", opts->program, argv[0]);
223 return EXIT_FAILURE;
224 }
225 args->fname = TRUE;
226 args->cmdline = argv[0];
227 argc--; argv++;
228 }
229 }
230 args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1));
231 memcpy(args->argv, argv, (argc+1) * sizeof(char*));
232 args->argc = argc;
233
234 return EXIT_SUCCESS;
235}
236
237static void
238cleanup(mrb_state *mrb, struct _args *args)
239{
240 if (args->rfp && args->rfp != stdin)
241 fclose(args->rfp);
242 if (!args->fname)
243 mrb_free(mrb, args->cmdline);
244 mrb_free(mrb, args->argv);
245 if (args->libc) {
246 while (args->libc--) {
247 mrb_free(mrb, args->libv[args->libc]);
248 }
249 mrb_free(mrb, args->libv);
250 }
251 mrb_close(mrb);
252}
253
254int
255mruby_main(int argc, char **argv)
256{
257 mrb_state *mrb = mrb_open();
258 int n = -1;
259 int i;
260 struct _args args;
261 mrb_value ARGV;
262 mrbc_context *c;
263 mrb_value v;
264 mrb_sym zero_sym;
265
266 if (mrb == NULL) {
267 fprintf(stderr, "%s: Invalid mrb_state, exiting mruby\n", *argv);
268 return EXIT_FAILURE;
269 }
270
271 n = parse_args(mrb, argc, argv, &args);
272 if (n == EXIT_FAILURE || (args.cmdline == NULL && args.rfp == NULL)) {
273 cleanup(mrb, &args);
274 return n;
275 }
276 else {
277 int ai = mrb_gc_arena_save(mrb);
278 ARGV = mrb_ary_new_capa(mrb, args.argc);
279 for (i = 0; i < args.argc; i++) {
280 char* utf8 = mrb_utf8_from_locale(args.argv[i], -1);
281 if (utf8) {
282 mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8));
283 mrb_utf8_free(utf8);
284 }
285 }
286 mrb_define_global_const(mrb, "ARGV", ARGV);
287 mrb_gv_set(mrb, mrb_intern_lit(mrb, "$DEBUG"), mrb_bool_value(args.debug));
288
289 c = mrbc_context_new(mrb);
290 if (args.verbose)
291 c->dump_result = TRUE;
292 if (args.check_syntax)
293 c->no_exec = TRUE;
294
295 /* Set $0 */
296 zero_sym = mrb_intern_lit(mrb, "$0");
297 if (args.rfp) {
298 const char *cmdline;
299 cmdline = args.cmdline ? args.cmdline : "-";
300 mrbc_filename(mrb, c, cmdline);
301 mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline));
302 }
303 else {
304 mrbc_filename(mrb, c, "-e");
305 mrb_gv_set(mrb, zero_sym, mrb_str_new_lit(mrb, "-e"));
306 }
307
308 /* Load libraries */
309 for (i = 0; i < args.libc; i++) {
310 FILE *lfp = fopen(args.libv[i], args.mrbfile ? "rb" : "r");
311 if (lfp == NULL) {
312 fprintf(stderr, "%s: Cannot open library file: %s\n", *argv, args.libv[i]);
313 mrbc_context_free(mrb, c);
314 cleanup(mrb, &args);
315 return EXIT_FAILURE;
316 }
317 if (args.mrbfile) {
318 v = mrb_load_irep_file_cxt(mrb, lfp, c);
319 }
320 else {
321 v = mrb_load_file_cxt(mrb, lfp, c);
322 }
323 fclose(lfp);
324 }
325
326 /* Load program */
327 if (args.mrbfile) {
328 v = mrb_load_irep_file_cxt(mrb, args.rfp, c);
329 }
330 else if (args.rfp) {
331 v = mrb_load_file_cxt(mrb, args.rfp, c);
332 }
333 else {
334 char* utf8 = mrb_utf8_from_locale(args.cmdline, -1);
335 if (!utf8) abort();
336 v = mrb_load_string_cxt(mrb, utf8, c);
337 mrb_utf8_free(utf8);
338 }
339
340 mrb_gc_arena_restore(mrb, ai);
341 mrbc_context_free(mrb, c);
342 if (mrb->exc) {
343 if (!mrb_undef_p(v)) {
344 mrb_print_error(mrb);
345 }
346 n = EXIT_FAILURE;
347 }
348 else if (args.check_syntax) {
349 puts("Syntax OK");
350 }
351 }
352 cleanup(mrb, &args);
353
354 return n;
355}
Note: See TracBrowser for help on using the repository browser.