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