#include "mruby.h" #include "mruby/proc.h" #include "mruby/dump.h" #include "mruby/cdump.h" #include "mruby/compile.h" #include #include #include #define RITEBIN_EXT ".mrb" #define C_EXT ".c" void mrb_show_version(mrb_state *); void mrb_show_copyright(mrb_state *); void parser_dump(mrb_state*, struct mrb_ast_node*, int); void codedump_all(mrb_state*, int); struct _args { FILE *rfp; FILE *wfp; char *initname; char *ext; int check_syntax : 1; int dump_type : 2; int verbose : 1; }; static void usage(const char *name) { static const char *const usage_msg[] = { "switches:", "-c check syntax only", "-o place the output into ", "-v print version number, then trun on verbose mode", "-B binary output in C language format", "-C function output in C language format", "--verbose run at verbose mode", "--version print the version", "--copyright print the copyright", NULL }; const char *const *p = usage_msg; printf("Usage: %s [switches] programfile\n", name); while(*p) printf(" %s\n", *p++); } static char * get_outfilename(char *infile, char *ext) { char *outfile; char *p; outfile = (char*)malloc(strlen(infile) + strlen(ext) + 1); strcpy(outfile, infile); if (*ext) { if ((p = strrchr(outfile, '.')) == NULL) p = &outfile[strlen(outfile)]; strcpy(p, ext); } return outfile; } static int parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args) { char *infile = NULL; char *outfile = NULL; char **origargv = argv; memset(args, 0, sizeof(*args)); args->ext = RITEBIN_EXT; for (argc--,argv++; argc > 0; argc--,argv++) { if (**argv == '-') { if (strlen(*argv) <= 1) return -1; switch ((*argv)[1]) { case 'o': outfile = get_outfilename((*argv) + 2, ""); break; case 'B': case 'C': args->ext = C_EXT; args->initname = (*argv) + 2; if (*args->initname == '\0') { printf("%s: Function name is not specified.\n", *origargv); return -2; } args->dump_type = ((*argv)[1] == 'B') ? DUMP_TYPE_BIN : DUMP_TYPE_CODE; break; case 'c': args->check_syntax = 1; break; case 'v': mrb_show_version(mrb); args->verbose = 1; break; case '-': if (strcmp((*argv) + 2, "version") == 0) { mrb_show_version(mrb); exit(0); } else if (strcmp((*argv) + 2, "verbose") == 0) { args->verbose = 1; break; } else if (strcmp((*argv) + 2, "copyright") == 0) { mrb_show_copyright(mrb); exit(0); } else return -3; return 0; } } else if (args->rfp == NULL) { infile = *argv; if ((args->rfp = fopen(infile, "r")) == NULL) { printf("%s: Cannot open program file. (%s)\n", *origargv, infile); return 0; } } } if (infile == NULL) return -4; if (args->check_syntax) return 0; if (outfile == NULL) outfile = get_outfilename(infile, args->ext); if ((args->wfp = fopen(outfile, "wb")) == NULL) { printf("%s: Cannot open output file. (%s)\n", *origargv, outfile); return 0; } return 0; } static void cleanup(struct _args *args) { if (args->rfp) fclose(args->rfp); if (args->wfp) fclose(args->wfp); } int main(int argc, char **argv) { mrb_state *mrb = mrb_open(); int n = -1; struct _args args; struct mrb_parser_state *p; if (mrb == NULL) { fprintf(stderr, "Invalid mrb_state, exiting mrbc"); return EXIT_FAILURE; } n = parse_args(mrb, argc, argv, &args); if (n < 0 || args.rfp == NULL) { cleanup(&args); usage(argv[0]); mrb_close(mrb); return n; } p = mrb_parse_file(mrb, args.rfp); if (!p || !p->tree || p->nerr) { cleanup(&args); mrb_close(mrb); return -1; } if (args.verbose) parser_dump(mrb, p->tree, 0); n = mrb_generate_code(mrb, p->tree); mrb_pool_close(p->pool); if (args.verbose) codedump_all(mrb, n); if (n < 0 || args.check_syntax) { cleanup(&args); mrb_close(mrb); return n; } if (args.initname) { if (args.dump_type == DUMP_TYPE_BIN) n = mrb_bdump_irep(mrb, n, args.wfp, args.initname); else n = mrb_cdump_irep(mrb, n, args.wfp, args.initname); } else { n = mrb_dump_irep(mrb, n, args.wfp); } cleanup(&args); mrb_close(mrb); return n; } void mrb_init_mrblib(mrb_state *mrb) { }