summaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/mrbc/mrbc.c256
1 files changed, 160 insertions, 96 deletions
diff --git a/tools/mrbc/mrbc.c b/tools/mrbc/mrbc.c
index b42ca2234..7cfee6eaf 100644
--- a/tools/mrbc/mrbc.c
+++ b/tools/mrbc/mrbc.c
@@ -14,12 +14,13 @@ 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 *filename;
- char *initname;
- char *ext;
+struct mrbc_args {
+ int argc;
+ char **argv;
+ int idx;
+ const char *prog;
+ const char *outfile;
+ const char *initname;
mrb_bool check_syntax : 1;
mrb_bool verbose : 1;
mrb_bool debug_info : 1;
@@ -65,42 +66,45 @@ get_outfilename(mrb_state *mrb, char *infile, char *ext)
}
static int
-parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
+parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
{
- char *infile = NULL;
char *outfile = NULL;
- char **origargv = argv;
- int result = EXIT_SUCCESS;
- static const struct _args args_zero = { 0 };
+ static const struct mrbc_args args_zero = { 0 };
+ int i;
*args = args_zero;
- args->ext = RITEBIN_EXT;
+ args->argc = argc;
+ args->argv = argv;
+ args->prog = argv[0];
- for (argc--,argv++; argc > 0; argc--,argv++) {
- if (**argv == '-') {
- if (strlen(*argv) == 1) {
- args->filename = infile = "-";
- args->rfp = stdin;
- break;
- }
-
- switch ((*argv)[1]) {
+ for (i=1; i<argc; i++) {
+ if (argv[i][0] == '-') {
+ switch ((argv[i])[1]) {
case 'o':
- if (outfile) {
- printf("%s: An output file is already specified. (%s)\n",
- *origargv, outfile);
- result = EXIT_FAILURE;
- goto exit;
+ if (args->outfile) {
+ fprintf(stderr, "%s: an output file is already specified. (%s)\n",
+ args->prog, outfile);
+ return -1;
+ }
+ if (argv[i][2] == '\0' && argv[i+1]) {
+ i++;
+ args->outfile = get_outfilename(mrb, argv[i], "");
+ }
+ else {
+ args->outfile = get_outfilename(mrb, argv[i] + 2, "");
}
- outfile = get_outfilename(mrb, (*argv) + 2, "");
break;
case 'B':
- args->ext = C_EXT;
- args->initname = (*argv) + 2;
+ if (argv[i][2] == '\0' && argv[i+1]) {
+ i++;
+ args->initname = argv[i];
+ }
+ else {
+ args->initname = argv[i]+2;
+ }
if (*args->initname == '\0') {
- printf("%s: Function name is not specified.\n", *origargv);
- result = EXIT_FAILURE;
- goto exit;
+ fprintf(stderr, "%s: function name is not specified.\n", args->prog);
+ return -1;
}
break;
case 'c':
@@ -114,79 +118,124 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
args->debug_info = 1;
break;
case '-':
- if (strcmp((*argv) + 2, "version") == 0) {
+ if (argv[i][1] == '\n') {
+ return i;
+ }
+ if (strcmp(argv[i] + 2, "version") == 0) {
mrb_show_version(mrb);
exit(EXIT_SUCCESS);
}
- else if (strcmp((*argv) + 2, "verbose") == 0) {
+ else if (strcmp(argv[i] + 2, "verbose") == 0) {
args->verbose = 1;
break;
}
- else if (strcmp((*argv) + 2, "copyright") == 0) {
+ else if (strcmp(argv[i] + 2, "copyright") == 0) {
mrb_show_copyright(mrb);
exit(EXIT_SUCCESS);
}
- result = EXIT_FAILURE;
- goto exit;
+ return -1;
default:
- break;
+ return i;
}
}
- else if (args->rfp == NULL) {
- args->filename = infile = *argv;
- if ((args->rfp = fopen(infile, "r")) == NULL) {
- printf("%s: Cannot open program file. (%s)\n", *origargv, infile);
- goto exit;
- }
+ else {
+ break;
}
}
+ return i;
+}
+
+static void
+cleanup(mrb_state *mrb, struct mrbc_args *args)
+{
+ if (args->outfile)
+ mrb_free(mrb, (void*)args->outfile);
+ mrb_close(mrb);
+}
+
+static int
+partial_hook(struct mrb_parser_state *p)
+{
+ mrbc_context *c = p->cxt;
+ struct mrbc_args *args = (struct mrbc_args *)c->partial_data;
- if (infile == NULL) {
- result = EXIT_FAILURE;
- goto exit;
+ if (p->f) fclose(p->f);
+ if (args->idx >= args->argc) {
+ p->f = NULL;
+ return -1;
}
- if (!args->check_syntax) {
- if (outfile == NULL) {
- if (strcmp("-", infile) == 0) {
- outfile = infile;
- }
- else {
- outfile = get_outfilename(mrb, infile, args->ext);
- }
- }
- if (strcmp("-", outfile) == 0) {
- args->wfp = stdout;
- }
- else if ((args->wfp = fopen(outfile, "wb")) == NULL) {
- printf("%s: Cannot open output file. (%s)\n", *origargv, outfile);
- result = EXIT_FAILURE;
- goto exit;
- }
+ mrbc_filename(p->mrb, c, args->argv[args->idx++]);
+ p->f = fopen(c->filename, "r");
+ if (p->f == NULL) {
+ fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, c->filename);
+ return -1;
+ }
+ p->filename = c->filename;
+ p->lineno = 1;
+ return 0;
+}
+
+static int
+load_file(mrb_state *mrb, struct mrbc_args *args)
+{
+ mrbc_context *c;
+ mrb_value result;
+ char *input = args->argv[args->idx];
+ FILE *infile;
+
+ c = mrbc_context_new(mrb);
+ if (args->verbose)
+ c->dump_result = 1;
+ c->no_exec = 1;
+ if (input[0] == '-' && input[1] == '\0') {
+ infile = stdin;
+ }
+ else if ((infile = fopen(input, "r")) == NULL) {
+ fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, input);
+ return EXIT_FAILURE;
+ }
+ mrbc_filename(mrb, c, input);
+ args->idx++;
+ if (args->idx < args->argc) {
+ mrbc_partial_hook(mrb, c, partial_hook, (void*)args);
}
-exit:
- if (outfile && infile != outfile) mrb_free(mrb, outfile);
- return result;
+ result = mrb_load_file_cxt(mrb, infile, c);
+ if (mrb_undef_p(result) || mrb_fixnum(result) < 0) {
+ mrbc_context_free(mrb, c);
+ return EXIT_FAILURE;
+ }
+ mrbc_context_free(mrb, c);
+ return EXIT_SUCCESS;
}
-static void
-cleanup(mrb_state *mrb, struct _args *args)
+static int
+dump_file(mrb_state *mrb, FILE *wfp, const char *outfile, struct mrbc_args *args)
{
- if (args->rfp)
- fclose(args->rfp);
- if (args->wfp)
- fclose(args->wfp);
- mrb_close(mrb);
+ int n = MRB_DUMP_OK;
+
+ if (args->initname) {
+ n = mrb_dump_irep_cfunc(mrb, 0, args->debug_info, wfp, args->initname);
+ if (n == MRB_DUMP_INVALID_ARGUMENT) {
+ fprintf(stderr, "%s: invalid C language symbol name\n", args->initname);
+ }
+ }
+ else {
+ n = mrb_dump_irep_binary(mrb, 0, args->debug_info, wfp);
+ }
+ if (n != MRB_DUMP_OK) {
+ fprintf(stderr, "%s: error in mrb dump (%s) %d\n", args->prog, outfile, n);
+ }
+ return n;
}
int
main(int argc, char **argv)
{
mrb_state *mrb = mrb_open();
- int n = -1;
- struct _args args;
- mrbc_context *c;
- mrb_value result;
+ int n, result;
+ struct mrbc_args args;
+ FILE *wfp;
if (mrb == NULL) {
fputs("Invalid mrb_state, exiting mrbc\n", stderr);
@@ -194,39 +243,54 @@ main(int argc, char **argv)
}
n = parse_args(mrb, argc, argv, &args);
- if (n == EXIT_FAILURE || args.rfp == NULL) {
+ if (n < 0) {
cleanup(mrb, &args);
usage(argv[0]);
- return n;
+ return EXIT_FAILURE;
+ }
+ if (n == argc) {
+ fprintf(stderr, "%s: no program file given\n", args.prog);
+ return EXIT_FAILURE;
+ }
+ if (args.outfile == NULL) {
+ if (n + 1 == argc) {
+ args.outfile = get_outfilename(mrb, argv[n], args.initname ? C_EXT : RITEBIN_EXT);
+ }
+ else {
+ fprintf(stderr, "%s: output file should be specified to compile multiple files\n", args.prog);
+ return EXIT_FAILURE;
+ }
}
- c = mrbc_context_new(mrb);
- if (args.verbose)
- c->dump_result = 1;
- c->no_exec = 1;
- c->filename = args.filename;
- result = mrb_load_file_cxt(mrb, args.rfp, c);
- if (mrb_undef_p(result) || mrb_fixnum(result) < 0) {
+ args.idx = n;
+ if (load_file(mrb, &args) == EXIT_FAILURE) {
cleanup(mrb, &args);
return EXIT_FAILURE;
}
if (args.check_syntax) {
- puts("Syntax OK");
+ printf("%s:%s:Syntax OK", args.prog, argv[n]);
+ }
+
+ if (args.check_syntax) {
cleanup(mrb, &args);
return EXIT_SUCCESS;
}
- if (args.initname) {
- n = mrb_dump_irep_cfunc(mrb, n, args.debug_info, args.wfp, args.initname);
- if (n == MRB_DUMP_INVALID_ARGUMENT) {
- printf("%s: Invalid C language symbol name\n", args.initname);
+
+ if (args.outfile) {
+ if (strcmp("-", args.outfile) == 0) {
+ wfp = stdout;
+ }
+ else if ((wfp = fopen(args.outfile, "w")) == NULL) {
+ fprintf(stderr, "%s: cannot open output file:(%s)\n", args.prog, args.outfile);
return EXIT_FAILURE;
}
}
- else {
- n = mrb_dump_irep_binary(mrb, n, args.debug_info, args.wfp);
- }
-
+ result = dump_file(mrb, wfp, args.outfile, &args);
+ fclose(wfp);
cleanup(mrb, &args);
+ if (result != MRB_DUMP_OK) {
+ return EXIT_FAILURE;
+ }
return EXIT_SUCCESS;
}