source: EcnlProtoTool/trunk/mruby-1.2.0/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c@ 270

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

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 7.8 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include "mruby.h"
5#include "mruby/compile.h"
6#include "mruby/dump.h"
7#include "mruby/proc.h"
8
9#define RITEBIN_EXT ".mrb"
10#define C_EXT ".c"
11
12struct mrbc_args {
13 int argc;
14 char **argv;
15 int idx;
16 const char *prog;
17 const char *outfile;
18 const char *initname;
19 mrb_bool check_syntax : 1;
20 mrb_bool verbose : 1;
21 unsigned int flags : 4;
22};
23
24static void
25usage(const char *name)
26{
27 static const char *const usage_msg[] = {
28 "switches:",
29 "-c check syntax only",
30 "-o<outfile> place the output into <outfile>",
31 "-v print version number, then turn on verbose mode",
32 "-g produce debugging information",
33 "-B<symbol> binary <symbol> output in C language format",
34 "-e generate little endian iseq data",
35 "-E generate big endian iseq data",
36 "--verbose run at verbose mode",
37 "--version print the version",
38 "--copyright print the copyright",
39 NULL
40 };
41 const char *const *p = usage_msg;
42
43 printf("Usage: %s [switches] programfile\n", name);
44 while (*p)
45 printf(" %s\n", *p++);
46}
47
48static char *
49get_outfilename(mrb_state *mrb, char *infile, const char *ext)
50{
51 size_t infilelen;
52 size_t extlen;
53 char *outfile;
54 char *p;
55
56 infilelen = strlen(infile);
57 extlen = strlen(ext);
58 outfile = (char*)mrb_malloc(mrb, infilelen + extlen + 1);
59 memcpy(outfile, infile, infilelen + 1);
60 if (*ext) {
61 if ((p = strrchr(outfile, '.')) == NULL)
62 p = outfile + infilelen;
63 memcpy(p, ext, extlen + 1);
64 }
65
66 return outfile;
67}
68
69static int
70parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
71{
72 char *outfile = NULL;
73 static const struct mrbc_args args_zero = { 0 };
74 int i;
75
76 *args = args_zero;
77 args->argc = argc;
78 args->argv = argv;
79 args->prog = argv[0];
80
81 for (i=1; i<argc; i++) {
82 if (argv[i][0] == '-') {
83 switch ((argv[i])[1]) {
84 case 'o':
85 if (args->outfile) {
86 fprintf(stderr, "%s: an output file is already specified. (%s)\n",
87 args->prog, outfile);
88 return -1;
89 }
90 if (argv[i][2] == '\0' && argv[i+1]) {
91 i++;
92 args->outfile = get_outfilename(mrb, argv[i], "");
93 }
94 else {
95 args->outfile = get_outfilename(mrb, argv[i] + 2, "");
96 }
97 break;
98 case 'B':
99 if (argv[i][2] == '\0' && argv[i+1]) {
100 i++;
101 args->initname = argv[i];
102 }
103 else {
104 args->initname = argv[i]+2;
105 }
106 if (*args->initname == '\0') {
107 fprintf(stderr, "%s: function name is not specified.\n", args->prog);
108 return -1;
109 }
110 break;
111 case 'c':
112 args->check_syntax = TRUE;
113 break;
114 case 'v':
115 if (!args->verbose) mrb_show_version(mrb);
116 args->verbose = TRUE;
117 break;
118 case 'g':
119 args->flags |= DUMP_DEBUG_INFO;
120 break;
121 case 'E':
122 args->flags = DUMP_ENDIAN_BIG | (args->flags & ~DUMP_ENDIAN_MASK);
123 break;
124 case 'e':
125 args->flags = DUMP_ENDIAN_LIL | (args->flags & ~DUMP_ENDIAN_MASK);
126 break;
127 case 'h':
128 return -1;
129 case '-':
130 if (argv[i][1] == '\n') {
131 return i;
132 }
133 if (strcmp(argv[i] + 2, "version") == 0) {
134 mrb_show_version(mrb);
135 exit(EXIT_SUCCESS);
136 }
137 else if (strcmp(argv[i] + 2, "verbose") == 0) {
138 args->verbose = TRUE;
139 break;
140 }
141 else if (strcmp(argv[i] + 2, "copyright") == 0) {
142 mrb_show_copyright(mrb);
143 exit(EXIT_SUCCESS);
144 }
145 return -1;
146 default:
147 return i;
148 }
149 }
150 else {
151 break;
152 }
153 }
154 if (args->verbose && args->initname && (args->flags & DUMP_ENDIAN_MASK) == 0) {
155 fprintf(stderr, "%s: generating %s endian C file. specify -e/-E for cross compiling.\n",
156 args->prog, bigendian_p() ? "big" : "little");
157 }
158 return i;
159}
160
161static void
162cleanup(mrb_state *mrb, struct mrbc_args *args)
163{
164 mrb_free(mrb, (void*)args->outfile);
165 mrb_close(mrb);
166}
167
168static int
169partial_hook(struct mrb_parser_state *p)
170{
171 mrbc_context *c = p->cxt;
172 struct mrbc_args *args = (struct mrbc_args *)c->partial_data;
173 const char *fn;
174
175 if (p->f) fclose(p->f);
176 if (args->idx >= args->argc) {
177 p->f = NULL;
178 return -1;
179 }
180 fn = args->argv[args->idx++];
181 p->f = fopen(fn, "r");
182 if (p->f == NULL) {
183 fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, fn);
184 return -1;
185 }
186 mrb_parser_set_filename(p, fn);
187 return 0;
188}
189
190static mrb_value
191load_file(mrb_state *mrb, struct mrbc_args *args)
192{
193 mrbc_context *c;
194 mrb_value result;
195 char *input = args->argv[args->idx];
196 FILE *infile;
197 mrb_bool need_close = FALSE;
198
199 c = mrbc_context_new(mrb);
200 if (args->verbose)
201 c->dump_result = TRUE;
202 c->no_exec = TRUE;
203 if (input[0] == '-' && input[1] == '\0') {
204 infile = stdin;
205 }
206 else {
207 need_close = TRUE;
208 if ((infile = fopen(input, "r")) == NULL) {
209 fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, input);
210 return mrb_nil_value();
211 }
212 }
213 mrbc_filename(mrb, c, input);
214 args->idx++;
215 if (args->idx < args->argc) {
216 need_close = FALSE;
217 mrbc_partial_hook(mrb, c, partial_hook, (void*)args);
218 }
219
220 result = mrb_load_file_cxt(mrb, infile, c);
221 if (need_close) fclose(infile);
222 mrbc_context_free(mrb, c);
223 if (mrb_undef_p(result)) {
224 return mrb_nil_value();
225 }
226 return result;
227}
228
229static int
230dump_file(mrb_state *mrb, FILE *wfp, const char *outfile, struct RProc *proc, struct mrbc_args *args)
231{
232 int n = MRB_DUMP_OK;
233 mrb_irep *irep = proc->body.irep;
234
235 if (args->initname) {
236 n = mrb_dump_irep_cfunc(mrb, irep, args->flags, wfp, args->initname);
237 if (n == MRB_DUMP_INVALID_ARGUMENT) {
238 fprintf(stderr, "%s: invalid C language symbol name\n", args->initname);
239 }
240 }
241 else {
242 n = mrb_dump_irep_binary(mrb, irep, args->flags, wfp);
243 }
244 if (n != MRB_DUMP_OK) {
245 fprintf(stderr, "%s: error in mrb dump (%s) %d\n", args->prog, outfile, n);
246 }
247 return n;
248}
249
250int
251main(int argc, char **argv)
252{
253 mrb_state *mrb = mrb_open();
254 int n, result;
255 struct mrbc_args args;
256 FILE *wfp;
257 mrb_value load;
258
259 if (mrb == NULL) {
260 fputs("Invalid mrb_state, exiting mrbc\n", stderr);
261 return EXIT_FAILURE;
262 }
263
264 n = parse_args(mrb, argc, argv, &args);
265 if (n < 0) {
266 cleanup(mrb, &args);
267 usage(argv[0]);
268 return EXIT_FAILURE;
269 }
270 if (n == argc) {
271 fprintf(stderr, "%s: no program file given\n", args.prog);
272 return EXIT_FAILURE;
273 }
274 if (args.outfile == NULL && !args.check_syntax) {
275 if (n + 1 == argc) {
276 args.outfile = get_outfilename(mrb, argv[n], args.initname ? C_EXT : RITEBIN_EXT);
277 }
278 else {
279 fprintf(stderr, "%s: output file should be specified to compile multiple files\n", args.prog);
280 return EXIT_FAILURE;
281 }
282 }
283
284 args.idx = n;
285 load = load_file(mrb, &args);
286 if (mrb_nil_p(load)) {
287 cleanup(mrb, &args);
288 return EXIT_FAILURE;
289 }
290 if (args.check_syntax) {
291 printf("%s:%s:Syntax OK\n", args.prog, argv[n]);
292 }
293
294 if (args.check_syntax) {
295 cleanup(mrb, &args);
296 return EXIT_SUCCESS;
297 }
298
299 if (args.outfile) {
300 if (strcmp("-", args.outfile) == 0) {
301 wfp = stdout;
302 }
303 else if ((wfp = fopen(args.outfile, "wb")) == NULL) {
304 fprintf(stderr, "%s: cannot open output file:(%s)\n", args.prog, args.outfile);
305 return EXIT_FAILURE;
306 }
307 }
308 else {
309 fprintf(stderr, "Output file is required\n");
310 return EXIT_FAILURE;
311 }
312 result = dump_file(mrb, wfp, args.outfile, mrb_proc_ptr(load), &args);
313 fclose(wfp);
314 cleanup(mrb, &args);
315 if (result != MRB_DUMP_OK) {
316 return EXIT_FAILURE;
317 }
318 return EXIT_SUCCESS;
319}
320
321void
322mrb_init_mrblib(mrb_state *mrb)
323{
324}
325
326#ifndef DISABLE_GEMS
327void
328mrb_init_mrbgems(mrb_state *mrb)
329{
330}
331
332void
333mrb_final_mrbgems(mrb_state *mrb)
334{
335}
336#endif
Note: See TracBrowser for help on using the repository browser.