Changeset 439 for EcnlProtoTool/trunk/prototool/src/mruby.c
- Timestamp:
- Jul 9, 2020, 8:51:43 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/prototool/src/mruby.c
r321 r439 1 #include <mruby.h> 2 3 #ifdef MRB_DISABLE_STDIO 4 # error mruby-bin-mruby conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb' 5 #endif 6 1 7 #include <stdlib.h> 2 8 #include <string.h> 3 4 #include "mruby.h" 5 #include "mruby/array.h" 6 #include "mruby/compile.h" 7 #include "mruby/dump.h" 8 #include "mruby/variable.h" 9 10 #ifdef MRB_DISABLE_STDIO 11 static void 12 p(mrb_state *mrb, mrb_value obj) 13 { 14 mrb_value val = mrb_inspect(mrb, obj); 15 16 fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout); 17 putc('\n', stdout); 18 } 19 #else 20 #define p(mrb,obj) mrb_p(mrb,obj) 21 #endif 22 23 struct _args 24 { 25 FILE *rfp; 26 char* cmdline; 27 mrb_bool fname : 1; 28 mrb_bool mrbfile : 1; 29 mrb_bool check_syntax : 1; 30 mrb_bool verbose : 1; 31 int argc; 32 char** argv; 9 #include <mruby/array.h> 10 #include <mruby/compile.h> 11 #include <mruby/dump.h> 12 #include <mruby/variable.h> 13 14 struct _args { 15 FILE *rfp; 16 char *cmdline; 17 mrb_bool fname : 1; 18 mrb_bool mrbfile : 1; 19 mrb_bool check_syntax : 1; 20 mrb_bool verbose : 1; 21 mrb_bool version : 1; 22 mrb_bool debug : 1; 23 int argc; 24 char **argv; 25 int libc; 26 char **libv; 27 }; 28 29 struct options { 30 int argc; 31 char **argv; 32 char *program; 33 char *opt; 34 char short_opt[2]; 33 35 }; 34 36 … … 36 38 usage(const char *name) 37 39 { 38 static const char *const usage_msg[] = { 39 "switches:", 40 "-b load and execute RiteBinary (mrb) file", 41 "-c check syntax only", 42 "-e 'command' one line of script", 43 "-v print version number, then run in verbose mode", 44 "--verbose run in verbose mode", 45 "--version print the version", 46 "--copyright print the copyright", 47 NULL 48 }; 49 const char *const *p = usage_msg; 50 51 printf("Usage: %s [switches] programfile\n", name); 52 while (*p) 53 printf(" %s\n", *p++); 40 static const char *const usage_msg[] = { 41 "switches:", 42 "-b load and execute RiteBinary (mrb) file", 43 "-c check syntax only", 44 "-d set debugging flags (set $DEBUG to true)", 45 "-e 'command' one line of script", 46 "-r library load the library before executing your script", 47 "-v print version number, then run in verbose mode", 48 "--verbose run in verbose mode", 49 "--version print the version", 50 "--copyright print the copyright", 51 NULL 52 }; 53 const char *const *p = usage_msg; 54 55 printf("Usage: %s [switches] [programfile] [arguments]\n", name); 56 while (*p) 57 printf(" %s\n", *p++); 58 } 59 60 static void 61 options_init(struct options *opts, int argc, char **argv) 62 { 63 opts->argc = argc; 64 opts->argv = argv; 65 opts->program = *argv; 66 *opts->short_opt = 0; 67 } 68 69 static const char * 70 options_opt(struct options *opts) 71 { 72 /* concatenated short options (e.g. `-cv`) */ 73 if (*opts->short_opt && *++opts->opt) { 74 short_opt: 75 opts->short_opt[0] = *opts->opt; 76 opts->short_opt[1] = 0; 77 return opts->short_opt; 78 } 79 80 while (++opts->argv, --opts->argc) { 81 opts->opt = *opts->argv; 82 83 /* empty || not start with `-` || `-` */ 84 if (!opts->opt[0] || opts->opt[0] != '-' || !opts->opt[1]) return NULL; 85 86 if (opts->opt[1] == '-') { 87 /* `--` */ 88 if (!opts->opt[2]) { 89 ++opts->argv, --opts->argc; 90 return NULL; 91 } 92 /* long option */ 93 opts->opt += 2; 94 *opts->short_opt = 0; 95 return opts->opt; 96 } 97 else { 98 /* short option */ 99 ++opts->opt; 100 goto short_opt; 101 } 102 } 103 return NULL; 104 } 105 106 static const char * 107 options_arg(struct options *opts) 108 { 109 if (*opts->short_opt && opts->opt[1]) { 110 /* concatenated short option and option argument (e.g. `-rLIBRARY`) */ 111 *opts->short_opt = 0; 112 return opts->opt + 1; 113 } 114 --opts->argc, ++opts->argv; 115 return opts->argc ? *opts->argv : NULL; 116 } 117 118 static char * 119 dup_arg_item(mrb_state *mrb, const char *item) 120 { 121 size_t buflen = strlen(item) + 1; 122 char *buf = (char*)mrb_malloc(mrb, buflen); 123 memcpy(buf, item, buflen); 124 return buf; 54 125 } 55 126 … … 57 128 parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args) 58 129 { 59 char **origargv = argv; 60 static const struct _args args_zero = { 0 }; 61 62 *args = args_zero; 63 64 for (argc--, argv++; argc > 0; argc--, argv++) { 65 char *item; 66 if (argv[0][0] != '-') break; 67 68 if (strlen(*argv) <= 1) { 69 argc--; argv++; 70 args->rfp = stdin; 71 break; 72 } 73 74 item = argv[0] + 1; 75 switch (*item++) { 76 case 'b': 77 args->mrbfile = TRUE; 78 break; 79 case 'c': 80 args->check_syntax = TRUE; 81 break; 82 case 'e': 83 if (item[0]) { 84 goto append_cmdline; 85 } 86 else if (argc > 1) { 87 argc--; argv++; 88 item = argv[0]; 89 append_cmdline: 90 if (!args->cmdline) { 91 size_t buflen; 92 char *buf; 93 94 buflen = strlen(item) + 1; 95 buf = (char *)mrb_malloc(mrb, buflen); 96 memcpy(buf, item, buflen); 97 args->cmdline = buf; 98 } 99 else { 100 size_t cmdlinelen; 101 size_t itemlen; 102 103 cmdlinelen = strlen(args->cmdline); 104 itemlen = strlen(item); 105 args->cmdline = 106 (char *)mrb_realloc(mrb, args->cmdline, cmdlinelen + itemlen + 2); 107 args->cmdline[cmdlinelen] = '\n'; 108 memcpy(args->cmdline + cmdlinelen + 1, item, itemlen + 1); 109 } 110 } 111 else { 112 printf("%s: No code specified for -e\n", *origargv); 113 return EXIT_SUCCESS; 114 } 115 break; 116 case 'v': 117 if (!args->verbose) mrb_show_version(mrb); 118 args->verbose = TRUE; 119 break; 120 case '-': 121 if (strcmp((*argv) + 2, "version") == 0) { 122 mrb_show_version(mrb); 123 exit(EXIT_SUCCESS); 124 } 125 else if (strcmp((*argv) + 2, "verbose") == 0) { 126 args->verbose = TRUE; 127 break; 128 } 129 else if (strcmp((*argv) + 2, "copyright") == 0) { 130 mrb_show_copyright(mrb); 131 exit(EXIT_SUCCESS); 132 } 133 default: 134 return EXIT_FAILURE; 135 } 136 } 137 138 if (args->rfp == NULL && args->cmdline == NULL) { 139 if (*argv == NULL) args->rfp = stdin; 140 else { 141 args->rfp = fopen(argv[0], args->mrbfile ? "rb" : "r"); 142 if (args->rfp == NULL) { 143 printf("%s: Cannot open program file. (%s)\n", *origargv, *argv); 144 return EXIT_FAILURE; 145 } 146 args->fname = TRUE; 147 args->cmdline = argv[0]; 148 argc--; argv++; 149 } 150 } 151 args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1)); 152 memcpy(args->argv, argv, (argc + 1) * sizeof(char*)); 153 args->argc = argc; 154 155 return EXIT_SUCCESS; 130 static const struct _args args_zero = { 0 }; 131 struct options opts[1]; 132 const char *opt, *item; 133 134 *args = args_zero; 135 options_init(opts, argc, argv); 136 while ((opt = options_opt(opts))) { 137 if (strcmp(opt, "b") == 0) { 138 args->mrbfile = TRUE; 139 } 140 else if (strcmp(opt, "c") == 0) { 141 args->check_syntax = TRUE; 142 } 143 else if (strcmp(opt, "d") == 0) { 144 args->debug = TRUE; 145 } 146 else if (strcmp(opt, "e") == 0) { 147 if ((item = options_arg(opts))) { 148 if (!args->cmdline) { 149 args->cmdline = dup_arg_item(mrb, item); 150 } 151 else { 152 size_t cmdlinelen; 153 size_t itemlen; 154 155 cmdlinelen = strlen(args->cmdline); 156 itemlen = strlen(item); 157 args->cmdline = 158 (char *)mrb_realloc(mrb, args->cmdline, cmdlinelen + itemlen + 2); 159 args->cmdline[cmdlinelen] = '\n'; 160 memcpy(args->cmdline + cmdlinelen + 1, item, itemlen + 1); 161 } 162 } 163 else { 164 fprintf(stderr, "%s: No code specified for -e\n", opts->program); 165 return EXIT_FAILURE; 166 } 167 } 168 else if (strcmp(opt, "h") == 0) { 169 usage(opts->program); 170 exit(EXIT_SUCCESS); 171 } 172 else if (strcmp(opt, "r") == 0) { 173 if ((item = options_arg(opts))) { 174 if (args->libc == 0) { 175 args->libv = (char**)mrb_malloc(mrb, sizeof(char*)); 176 } 177 else { 178 args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1)); 179 } 180 args->libv[args->libc++] = dup_arg_item(mrb, item); 181 } 182 else { 183 fprintf(stderr, "%s: No library specified for -r\n", opts->program); 184 return EXIT_FAILURE; 185 } 186 } 187 else if (strcmp(opt, "v") == 0) { 188 if (!args->verbose) { 189 mrb_show_version(mrb); 190 args->version = TRUE; 191 } 192 args->verbose = TRUE; 193 } 194 else if (strcmp(opt, "version") == 0) { 195 mrb_show_version(mrb); 196 exit(EXIT_SUCCESS); 197 } 198 else if (strcmp(opt, "verbose") == 0) { 199 args->verbose = TRUE; 200 } 201 else if (strcmp(opt, "copyright") == 0) { 202 mrb_show_copyright(mrb); 203 exit(EXIT_SUCCESS); 204 } 205 else { 206 fprintf(stderr, "%s: invalid option %s%s (-h will show valid options)\n", 207 opts->program, opt[1] ? "--" : "-", opt); 208 return EXIT_FAILURE; 209 } 210 } 211 212 argc = opts->argc; argv = opts->argv; 213 if (args->cmdline == NULL) { 214 if (*argv == NULL) { 215 if (args->version) exit(EXIT_SUCCESS); 216 args->rfp = stdin; 217 } 218 else { 219 args->rfp = strcmp(argv[0], "-") == 0 ? 220 stdin : fopen(argv[0], args->mrbfile ? "rb" : "r"); 221 if (args->rfp == NULL) { 222 fprintf(stderr, "%s: Cannot open program file: %s\n", opts->program, argv[0]); 223 return EXIT_FAILURE; 224 } 225 args->fname = TRUE; 226 args->cmdline = argv[0]; 227 argc--; argv++; 228 } 229 } 230 args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1)); 231 memcpy(args->argv, argv, (argc+1) * sizeof(char*)); 232 args->argc = argc; 233 234 return EXIT_SUCCESS; 156 235 } 157 236 … … 159 238 cleanup(mrb_state *mrb, struct _args *args) 160 239 { 161 if (args->rfp && args->rfp != stdin) 162 fclose(args->rfp); 163 if (!args->fname) 164 mrb_free(mrb, args->cmdline); 165 mrb_free(mrb, args->argv); 166 mrb_close(mrb); 240 if (args->rfp && args->rfp != stdin) 241 fclose(args->rfp); 242 if (!args->fname) 243 mrb_free(mrb, args->cmdline); 244 mrb_free(mrb, args->argv); 245 if (args->libc) { 246 while (args->libc--) { 247 mrb_free(mrb, args->libv[args->libc]); 248 } 249 mrb_free(mrb, args->libv); 250 } 251 mrb_close(mrb); 167 252 } 168 253 … … 170 255 mruby_main(int argc, char **argv) 171 256 { 172 mrb_state *mrb = mrb_open(); 173 int n = -1; 174 int i; 175 struct _args args; 176 mrb_value ARGV; 177 mrbc_context *c; 178 mrb_value v; 179 mrb_sym zero_sym; 180 181 if (mrb == NULL) { 182 fputs("Invalid mrb_state, exiting mruby\n", stderr); 183 return EXIT_FAILURE; 184 } 185 186 n = parse_args(mrb, argc, argv, &args); 187 if (n == EXIT_FAILURE || (args.cmdline == NULL && args.rfp == NULL)) { 188 cleanup(mrb, &args); 189 usage(argv[0]); 190 return n; 191 } 192 else { 193 int ai = mrb_gc_arena_save(mrb); 194 ARGV = mrb_ary_new_capa(mrb, args.argc); 195 for (i = 0; i < args.argc; i++) { 196 mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, args.argv[i])); 197 } 198 mrb_define_global_const(mrb, "ARGV", ARGV); 199 200 c = mrbc_context_new(mrb); 201 if (args.verbose) 202 c->dump_result = TRUE; 203 if (args.check_syntax) 204 c->no_exec = TRUE; 205 206 /* Set $0 */ 207 zero_sym = mrb_intern_lit(mrb, "$0"); 208 if (args.rfp) { 209 const char *cmdline; 210 cmdline = args.cmdline ? args.cmdline : "-"; 211 mrbc_filename(mrb, c, cmdline); 212 mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline)); 213 } 214 else { 215 mrbc_filename(mrb, c, "-e"); 216 mrb_gv_set(mrb, zero_sym, mrb_str_new_lit(mrb, "-e")); 217 } 218 219 /* Load program */ 220 if (args.mrbfile) { 221 v = mrb_load_irep_file_cxt(mrb, args.rfp, c); 222 } 223 else if (args.rfp) { 224 v = mrb_load_file_cxt(mrb, args.rfp, c); 225 } 226 else { 227 v = mrb_load_string_cxt(mrb, args.cmdline, c); 228 } 229 230 mrb_gc_arena_restore(mrb, ai); 231 mrbc_context_free(mrb, c); 232 if (mrb->exc) { 233 if (!mrb_undef_p(v)) { 234 mrb_print_error(mrb); 235 } 236 n = -1; 237 } 238 else if (args.check_syntax) { 239 printf("Syntax OK\n"); 240 } 241 } 242 cleanup(mrb, &args); 243 244 return n == 0 ? EXIT_SUCCESS : EXIT_FAILURE; 245 } 257 mrb_state *mrb = mrb_open(); 258 int n = -1; 259 int i; 260 struct _args args; 261 mrb_value ARGV; 262 mrbc_context *c; 263 mrb_value v; 264 mrb_sym zero_sym; 265 266 if (mrb == NULL) { 267 fprintf(stderr, "%s: Invalid mrb_state, exiting mruby\n", *argv); 268 return EXIT_FAILURE; 269 } 270 271 n = parse_args(mrb, argc, argv, &args); 272 if (n == EXIT_FAILURE || (args.cmdline == NULL && args.rfp == NULL)) { 273 cleanup(mrb, &args); 274 return n; 275 } 276 else { 277 int ai = mrb_gc_arena_save(mrb); 278 ARGV = mrb_ary_new_capa(mrb, args.argc); 279 for (i = 0; i < args.argc; i++) { 280 char* utf8 = mrb_utf8_from_locale(args.argv[i], -1); 281 if (utf8) { 282 mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8)); 283 mrb_utf8_free(utf8); 284 } 285 } 286 mrb_define_global_const(mrb, "ARGV", ARGV); 287 mrb_gv_set(mrb, mrb_intern_lit(mrb, "$DEBUG"), mrb_bool_value(args.debug)); 288 289 c = mrbc_context_new(mrb); 290 if (args.verbose) 291 c->dump_result = TRUE; 292 if (args.check_syntax) 293 c->no_exec = TRUE; 294 295 /* Set $0 */ 296 zero_sym = mrb_intern_lit(mrb, "$0"); 297 if (args.rfp) { 298 const char *cmdline; 299 cmdline = args.cmdline ? args.cmdline : "-"; 300 mrbc_filename(mrb, c, cmdline); 301 mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline)); 302 } 303 else { 304 mrbc_filename(mrb, c, "-e"); 305 mrb_gv_set(mrb, zero_sym, mrb_str_new_lit(mrb, "-e")); 306 } 307 308 /* Load libraries */ 309 for (i = 0; i < args.libc; i++) { 310 FILE *lfp = fopen(args.libv[i], args.mrbfile ? "rb" : "r"); 311 if (lfp == NULL) { 312 fprintf(stderr, "%s: Cannot open library file: %s\n", *argv, args.libv[i]); 313 mrbc_context_free(mrb, c); 314 cleanup(mrb, &args); 315 return EXIT_FAILURE; 316 } 317 if (args.mrbfile) { 318 v = mrb_load_irep_file_cxt(mrb, lfp, c); 319 } 320 else { 321 v = mrb_load_file_cxt(mrb, lfp, c); 322 } 323 fclose(lfp); 324 } 325 326 /* Load program */ 327 if (args.mrbfile) { 328 v = mrb_load_irep_file_cxt(mrb, args.rfp, c); 329 } 330 else if (args.rfp) { 331 v = mrb_load_file_cxt(mrb, args.rfp, c); 332 } 333 else { 334 char* utf8 = mrb_utf8_from_locale(args.cmdline, -1); 335 if (!utf8) abort(); 336 v = mrb_load_string_cxt(mrb, utf8, c); 337 mrb_utf8_free(utf8); 338 } 339 340 mrb_gc_arena_restore(mrb, ai); 341 mrbc_context_free(mrb, c); 342 if (mrb->exc) { 343 if (!mrb_undef_p(v)) { 344 mrb_print_error(mrb); 345 } 346 n = EXIT_FAILURE; 347 } 348 else if (args.check_syntax) { 349 puts("Syntax OK"); 350 } 351 } 352 cleanup(mrb, &args); 353 354 return n; 355 }
Note:
See TracChangeset
for help on using the changeset viewer.