3 #ifdef MRB_DISABLE_STDIO
4 # error mruby-bin-mrbc conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
9 #include <mruby/compile.h>
10 #include <mruby/dump.h>
11 #include <mruby/proc.h>
13 #define RITEBIN_EXT ".mrb"
23 mrb_bool check_syntax : 1;
25 mrb_bool remove_lv : 1;
26 unsigned int flags : 4;
30 usage(const char *name)
32 static const char *const usage_msg[] = {
34 "-c check syntax only",
35 "-o<outfile> place the output into <outfile>",
36 "-v print version number, then turn on verbose mode",
37 "-g produce debugging information",
38 "-B<symbol> binary <symbol> output in C language format",
39 "--remove-lv remove local variables",
40 "--verbose run at verbose mode",
41 "--version print the version",
42 "--copyright print the copyright",
45 const char *const *p = usage_msg;
47 printf("Usage: %s [switches] programfile\n", name);
49 printf(" %s\n", *p++);
53 get_outfilename(mrb_state *mrb, char *infile, const char *ext)
55 size_t ilen, flen, elen;
59 ilen = strlen(infile);
63 if ((p = strrchr(infile, '.'))) {
71 outfile = (char*)mrb_malloc(mrb, flen+1);
72 strncpy(outfile, infile, ilen+1);
74 strncpy(outfile+ilen, ext, elen+1);
81 parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
83 static const struct mrbc_args args_zero = { 0 };
91 for (i=1; i<argc; i++) {
92 if (argv[i][0] == '-') {
93 switch ((argv[i])[1]) {
96 fprintf(stderr, "%s: an output file is already specified. (%s)\n",
97 args->prog, args->outfile);
100 if (argv[i][2] == '\0' && argv[i+1]) {
102 args->outfile = get_outfilename(mrb, argv[i], "");
105 args->outfile = get_outfilename(mrb, argv[i] + 2, "");
109 if (argv[i][2] == '\0' && argv[i+1]) {
111 args->initname = argv[i];
114 args->initname = argv[i]+2;
116 if (*args->initname == '\0') {
117 fprintf(stderr, "%s: function name is not specified.\n", args->prog);
122 args->check_syntax = TRUE;
125 if (!args->verbose) mrb_show_version(mrb);
126 args->verbose = TRUE;
129 args->flags |= DUMP_DEBUG_INFO;
133 fprintf(stderr, "%s: -e/-E option no longer needed.\n", args->prog);
138 if (argv[i][1] == '\n') {
141 if (strcmp(argv[i] + 2, "version") == 0) {
142 mrb_show_version(mrb);
145 else if (strcmp(argv[i] + 2, "verbose") == 0) {
146 args->verbose = TRUE;
149 else if (strcmp(argv[i] + 2, "copyright") == 0) {
150 mrb_show_copyright(mrb);
153 else if (strcmp(argv[i] + 2, "remove-lv") == 0) {
154 args->remove_lv = TRUE;
170 cleanup(mrb_state *mrb, struct mrbc_args *args)
172 mrb_free(mrb, (void*)args->outfile);
177 partial_hook(struct mrb_parser_state *p)
179 mrbc_context *c = p->cxt;
180 struct mrbc_args *args = (struct mrbc_args *)c->partial_data;
183 if (p->f) fclose(p->f);
184 if (args->idx >= args->argc) {
188 fn = args->argv[args->idx++];
189 p->f = fopen(fn, "rb");
191 fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, fn);
194 mrb_parser_set_filename(p, fn);
199 load_file(mrb_state *mrb, struct mrbc_args *args)
203 char *input = args->argv[args->idx];
205 mrb_bool need_close = FALSE;
207 c = mrbc_context_new(mrb);
209 c->dump_result = TRUE;
211 if (input[0] == '-' && input[1] == '\0') {
216 if ((infile = fopen(input, "rb")) == NULL) {
217 fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, input);
218 return mrb_nil_value();
221 mrbc_filename(mrb, c, input);
223 if (args->idx < args->argc) {
225 mrbc_partial_hook(mrb, c, partial_hook, (void*)args);
228 result = mrb_load_file_cxt(mrb, infile, c);
229 if (need_close) fclose(infile);
230 mrbc_context_free(mrb, c);
231 if (mrb_undef_p(result)) {
232 return mrb_nil_value();
238 dump_file(mrb_state *mrb, FILE *wfp, const char *outfile, struct RProc *proc, struct mrbc_args *args)
241 mrb_irep *irep = proc->body.irep;
243 if (args->remove_lv) {
244 mrb_irep_remove_lv(mrb, irep);
246 if (args->initname) {
247 n = mrb_dump_irep_cfunc(mrb, irep, args->flags, wfp, args->initname);
248 if (n == MRB_DUMP_INVALID_ARGUMENT) {
249 fprintf(stderr, "%s: invalid C language symbol name\n", args->initname);
253 n = mrb_dump_irep_binary(mrb, irep, args->flags, wfp);
255 if (n != MRB_DUMP_OK) {
256 fprintf(stderr, "%s: error in mrb dump (%s) %d\n", args->prog, outfile, n);
262 main(int argc, char **argv)
264 mrb_state *mrb = mrb_open();
266 struct mrbc_args args;
271 fputs("Invalid mrb_state, exiting mrbc\n", stderr);
275 n = parse_args(mrb, argc, argv, &args);
282 fprintf(stderr, "%s: no program file given\n", args.prog);
285 if (args.outfile == NULL && !args.check_syntax) {
287 args.outfile = get_outfilename(mrb, argv[n], args.initname ? C_EXT : RITEBIN_EXT);
290 fprintf(stderr, "%s: output file should be specified to compile multiple files\n", args.prog);
296 load = load_file(mrb, &args);
297 if (mrb_nil_p(load)) {
301 if (args.check_syntax) {
302 printf("%s:%s:Syntax OK\n", args.prog, argv[n]);
305 if (args.check_syntax) {
311 if (strcmp("-", args.outfile) == 0) {
314 else if ((wfp = fopen(args.outfile, "wb")) == NULL) {
315 fprintf(stderr, "%s: cannot open output file:(%s)\n", args.prog, args.outfile);
320 fprintf(stderr, "Output file is required\n");
323 result = dump_file(mrb, wfp, args.outfile, mrb_proc_ptr(load), &args);
326 if (result != MRB_DUMP_OK) {
333 mrb_init_mrblib(mrb_state *mrb)
339 mrb_init_mrbgems(mrb_state *mrb)
344 mrb_final_mrbgems(mrb_state *mrb)