Changeset 439 for EcnlProtoTool/trunk/prototool/src/mirb.c
- Timestamp:
- Jul 9, 2020, 8:51:43 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/prototool/src/mirb.c
r321 r439 7 7 */ 8 8 9 #include <mruby.h> 10 11 #ifdef MRB_DISABLE_STDIO 12 # error mruby-bin-mirb conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb' 13 #endif 14 15 #include <mruby/array.h> 16 #include <mruby/proc.h> 17 #include <mruby/compile.h> 18 #include <mruby/dump.h> 19 #include <mruby/string.h> 20 #include <mruby/variable.h> 21 #include <mruby/throw.h> 22 9 23 #include <stdlib.h> 10 24 #include <string.h> 11 #include <stdio.h>12 25 #include <ctype.h> 26 27 #include <signal.h> 28 #include <setjmp.h> 13 29 14 30 #ifdef ENABLE_READLINE … … 17 33 #define MIRB_ADD_HISTORY(line) add_history(line) 18 34 #define MIRB_READLINE(ch) readline(ch) 35 #if !defined(RL_READLINE_VERSION) || RL_READLINE_VERSION < 0x600 36 /* libedit & older readline do not have rl_free() */ 37 #define MIRB_LINE_FREE(line) free(line) 38 #else 39 #define MIRB_LINE_FREE(line) rl_free(line) 40 #endif 19 41 #define MIRB_WRITE_HISTORY(path) write_history(path) 20 42 #define MIRB_READ_HISTORY(path) read_history(path) … … 25 47 #define MIRB_ADD_HISTORY(line) linenoiseHistoryAdd(line) 26 48 #define MIRB_READLINE(ch) linenoise(ch) 49 #define MIRB_LINE_FREE(line) linenoiseFree(line) 27 50 #define MIRB_WRITE_HISTORY(path) linenoiseHistorySave(path) 28 51 #define MIRB_READ_HISTORY(path) linenoiseHistoryLoad(history_path) … … 30 53 #endif 31 54 32 #include "mruby.h" 33 #include "mruby/array.h" 34 #include "mruby/proc.h" 35 #include "mruby/compile.h" 36 #include "mruby/string.h" 55 #ifndef _WIN32 56 #define MIRB_SIGSETJMP(env) sigsetjmp(env, 1) 57 #define MIRB_SIGLONGJMP(env, val) siglongjmp(env, val) 58 #define SIGJMP_BUF sigjmp_buf 59 #else 60 #define MIRB_SIGSETJMP(env) setjmp(env) 61 #define MIRB_SIGLONGJMP(env, val) longjmp(env, val) 62 #define SIGJMP_BUF jmp_buf 63 #endif 37 64 38 65 #ifdef ENABLE_READLINE … … 43 70 get_history_path(mrb_state *mrb) 44 71 { 45 46 72 char *path = NULL; 73 const char *home = getenv("HOME"); 47 74 48 75 #ifdef _WIN32 49 50 51 52 #endif 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 76 if (home != NULL) { 77 home = getenv("USERPROFILE"); 78 } 79 #endif 80 81 if (home != NULL) { 82 int len = snprintf(NULL, 0, "%s/%s", home, history_file_name); 83 if (len >= 0) { 84 size_t size = len + 1; 85 path = (char *)mrb_malloc_simple(mrb, size); 86 if (path != NULL) { 87 int n = snprintf(path, size, "%s/%s", home, history_file_name); 88 if (n != len) { 89 mrb_free(mrb, path); 90 path = NULL; 91 } 92 } 93 } 94 } 95 96 return path; 70 97 } 71 98 … … 75 102 p(mrb_state *mrb, mrb_value obj, int prompt) 76 103 { 77 mrb_value val; 78 79 val = mrb_funcall(mrb, obj, "inspect", 0); 80 if (prompt) { 81 if (!mrb->exc) { 82 fputs(" => ", stdout); 83 } 84 else { 85 val = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0); 86 } 87 } 88 if (!mrb_string_p(val)) { 89 val = mrb_obj_as_string(mrb, obj); 90 } 91 fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout); 92 putc('\n', stdout); 104 mrb_value val; 105 char* msg; 106 107 val = mrb_funcall(mrb, obj, "inspect", 0); 108 if (prompt) { 109 if (!mrb->exc) { 110 fputs(" => ", stdout); 111 } 112 else { 113 val = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0); 114 } 115 } 116 if (!mrb_string_p(val)) { 117 val = mrb_obj_as_string(mrb, obj); 118 } 119 msg = mrb_locale_from_utf8(RSTRING_PTR(val), (int)RSTRING_LEN(val)); 120 fwrite(msg, strlen(msg), 1, stdout); 121 mrb_locale_free(msg); 122 putc('\n', stdout); 93 123 } 94 124 … … 98 128 is_code_block_open(struct mrb_parser_state *parser) 99 129 { 100 mrb_bool code_block_open = FALSE; 101 102 /* check for heredoc */ 103 if (parser->parsing_heredoc != NULL) return TRUE; 104 if (parser->heredoc_end_now) { 105 parser->heredoc_end_now = FALSE; 106 return FALSE; 107 } 108 109 /* check for unterminated string */ 110 if (parser->lex_strterm) return TRUE; 111 112 /* check if parser error are available */ 113 if (0 < parser->nerr) { 114 const char unexpected_end[] = "syntax error, unexpected $end"; 115 const char *message = parser->error_buffer[0].message; 116 117 /* a parser error occur, we have to check if */ 118 /* we need to read one more line or if there is */ 119 /* a different issue which we have to show to */ 120 /* the user */ 121 122 if (strncmp(message, unexpected_end, sizeof(unexpected_end) - 1) == 0) { 123 code_block_open = TRUE; 124 } 125 else if (strcmp(message, "syntax error, unexpected keyword_end") == 0) { 126 code_block_open = FALSE; 127 } 128 else if (strcmp(message, "syntax error, unexpected tREGEXP_BEG") == 0) { 129 code_block_open = FALSE; 130 } 131 return code_block_open; 132 } 133 134 switch (parser->lstate) { 135 136 /* all states which need more code */ 137 138 case EXPR_BEG: 139 /* beginning of a statement, */ 140 /* that means previous line ended */ 141 code_block_open = FALSE; 142 break; 143 case EXPR_DOT: 144 /* a message dot was the last token, */ 145 /* there has to come more */ 146 code_block_open = TRUE; 147 break; 148 case EXPR_CLASS: 149 /* a class keyword is not enough! */ 150 /* we need also a name of the class */ 151 code_block_open = TRUE; 152 break; 153 case EXPR_FNAME: 154 /* a method name is necessary */ 155 code_block_open = TRUE; 156 break; 157 case EXPR_VALUE: 158 /* if, elsif, etc. without condition */ 159 code_block_open = TRUE; 160 break; 161 162 /* now all the states which are closed */ 163 164 case EXPR_ARG: 165 /* an argument is the last token */ 166 code_block_open = FALSE; 167 break; 168 169 /* all states which are unsure */ 170 171 case EXPR_CMDARG: 172 break; 173 case EXPR_END: 174 /* an expression was ended */ 175 break; 176 case EXPR_ENDARG: 177 /* closing parenthese */ 178 break; 179 case EXPR_ENDFN: 180 /* definition end */ 181 break; 182 case EXPR_MID: 183 /* jump keyword like break, return, ... */ 184 break; 185 case EXPR_MAX_STATE: 186 /* don't know what to do with this token */ 187 break; 188 default: 189 /* this state is unexpected! */ 190 break; 191 } 192 193 return code_block_open; 130 mrb_bool code_block_open = FALSE; 131 132 /* check for heredoc */ 133 if (parser->parsing_heredoc != NULL) return TRUE; 134 135 /* check for unterminated string */ 136 if (parser->lex_strterm) return TRUE; 137 138 /* check if parser error are available */ 139 if (0 < parser->nerr) { 140 const char unexpected_end[] = "syntax error, unexpected $end"; 141 const char *message = parser->error_buffer[0].message; 142 143 /* a parser error occur, we have to check if */ 144 /* we need to read one more line or if there is */ 145 /* a different issue which we have to show to */ 146 /* the user */ 147 148 if (strncmp(message, unexpected_end, sizeof(unexpected_end) - 1) == 0) { 149 code_block_open = TRUE; 150 } 151 else if (strcmp(message, "syntax error, unexpected keyword_end") == 0) { 152 code_block_open = FALSE; 153 } 154 else if (strcmp(message, "syntax error, unexpected tREGEXP_BEG") == 0) { 155 code_block_open = FALSE; 156 } 157 return code_block_open; 158 } 159 160 switch (parser->lstate) { 161 162 /* all states which need more code */ 163 164 case EXPR_BEG: 165 /* beginning of a statement, */ 166 /* that means previous line ended */ 167 code_block_open = FALSE; 168 break; 169 case EXPR_DOT: 170 /* a message dot was the last token, */ 171 /* there has to come more */ 172 code_block_open = TRUE; 173 break; 174 case EXPR_CLASS: 175 /* a class keyword is not enough! */ 176 /* we need also a name of the class */ 177 code_block_open = TRUE; 178 break; 179 case EXPR_FNAME: 180 /* a method name is necessary */ 181 code_block_open = TRUE; 182 break; 183 case EXPR_VALUE: 184 /* if, elsif, etc. without condition */ 185 code_block_open = TRUE; 186 break; 187 188 /* now all the states which are closed */ 189 190 case EXPR_ARG: 191 /* an argument is the last token */ 192 code_block_open = FALSE; 193 break; 194 195 /* all states which are unsure */ 196 197 case EXPR_CMDARG: 198 break; 199 case EXPR_END: 200 /* an expression was ended */ 201 break; 202 case EXPR_ENDARG: 203 /* closing parenthese */ 204 break; 205 case EXPR_ENDFN: 206 /* definition end */ 207 break; 208 case EXPR_MID: 209 /* jump keyword like break, return, ... */ 210 break; 211 case EXPR_MAX_STATE: 212 /* don't know what to do with this token */ 213 break; 214 default: 215 /* this state is unexpected! */ 216 break; 217 } 218 219 return code_block_open; 194 220 } 195 221 196 222 struct _args { 197 mrb_bool verbose : 1; 198 int argc; 199 char** argv; 223 FILE *rfp; 224 mrb_bool verbose : 1; 225 mrb_bool debug : 1; 226 int argc; 227 char** argv; 228 int libc; 229 char **libv; 200 230 }; 201 231 … … 203 233 usage(const char *name) 204 234 { 205 static const char *const usage_msg[] = { 206 "switches:", 207 "-v print version number, then run in verbose mode", 208 "--verbose run in verbose mode", 209 "--version print the version", 210 "--copyright print the copyright", 211 NULL 212 }; 213 const char *const *p = usage_msg; 214 215 printf("Usage: %s [switches]\n", name); 216 while (*p) 217 printf(" %s\n", *p++); 235 static const char *const usage_msg[] = { 236 "switches:", 237 "-d set $DEBUG to true (same as `mruby -d`)", 238 "-r library same as `mruby -r`", 239 "-v print version number, then run in verbose mode", 240 "--verbose run in verbose mode", 241 "--version print the version", 242 "--copyright print the copyright", 243 NULL 244 }; 245 const char *const *p = usage_msg; 246 247 printf("Usage: %s [switches] [programfile] [arguments]\n", name); 248 while (*p) 249 printf(" %s\n", *p++); 250 } 251 252 static char * 253 dup_arg_item(mrb_state *mrb, const char *item) 254 { 255 size_t buflen = strlen(item) + 1; 256 char *buf = (char*)mrb_malloc(mrb, buflen); 257 memcpy(buf, item, buflen); 258 return buf; 218 259 } 219 260 … … 221 262 parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args) 222 263 { 223 static const struct _args args_zero = {0}; 224 225 *args = args_zero; 226 227 for (argc--, argv++; argc > 0; argc--, argv++) { 228 char *item; 229 if (argv[0][0] != '-') break; 230 231 item = argv[0] + 1; 232 switch (*item++) { 233 case 'v': 234 if (!args->verbose) mrb_show_version(mrb); 235 args->verbose = TRUE; 236 break; 237 case '-': 238 if (strcmp((*argv) + 2, "version") == 0) { 239 mrb_show_version(mrb); 240 exit(EXIT_SUCCESS); 241 } 242 else if (strcmp((*argv) + 2, "verbose") == 0) { 243 args->verbose = TRUE; 244 break; 245 } 246 else if (strcmp((*argv) + 2, "copyright") == 0) { 247 mrb_show_copyright(mrb); 248 exit(EXIT_SUCCESS); 249 } 250 default: 251 return EXIT_FAILURE; 252 } 253 } 254 return EXIT_SUCCESS; 264 char **origargv = argv; 265 static const struct _args args_zero = { 0 }; 266 267 *args = args_zero; 268 269 for (argc--,argv++; argc > 0; argc--,argv++) { 270 char *item; 271 if (argv[0][0] != '-') break; 272 273 item = argv[0] + 1; 274 switch (*item++) { 275 case 'd': 276 args->debug = TRUE; 277 break; 278 case 'r': 279 if (!item[0]) { 280 if (argc <= 1) { 281 printf("%s: No library specified for -r\n", *origargv); 282 return EXIT_FAILURE; 283 } 284 argc--; argv++; 285 item = argv[0]; 286 } 287 if (args->libc == 0) { 288 args->libv = (char**)mrb_malloc(mrb, sizeof(char*)); 289 } 290 else { 291 args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1)); 292 } 293 args->libv[args->libc++] = dup_arg_item(mrb, item); 294 break; 295 case 'v': 296 if (!args->verbose) mrb_show_version(mrb); 297 args->verbose = TRUE; 298 break; 299 case '-': 300 if (strcmp((*argv) + 2, "version") == 0) { 301 mrb_show_version(mrb); 302 exit(EXIT_SUCCESS); 303 } 304 else if (strcmp((*argv) + 2, "verbose") == 0) { 305 args->verbose = TRUE; 306 break; 307 } 308 else if (strcmp((*argv) + 2, "copyright") == 0) { 309 mrb_show_copyright(mrb); 310 exit(EXIT_SUCCESS); 311 } 312 default: 313 return EXIT_FAILURE; 314 } 315 } 316 317 if (args->rfp == NULL) { 318 if (*argv != NULL) { 319 args->rfp = fopen(argv[0], "r"); 320 if (args->rfp == NULL) { 321 printf("Cannot open program file. (%s)\n", *argv); 322 return EXIT_FAILURE; 323 } 324 argc--; argv++; 325 } 326 } 327 args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1)); 328 memcpy(args->argv, argv, (argc+1) * sizeof(char*)); 329 args->argc = argc; 330 331 return EXIT_SUCCESS; 255 332 } 256 333 … … 258 335 cleanup(mrb_state *mrb, struct _args *args) 259 336 { 260 mrb_close(mrb); 337 if (args->rfp) 338 fclose(args->rfp); 339 mrb_free(mrb, args->argv); 340 if (args->libc) { 341 while (args->libc--) { 342 mrb_free(mrb, args->libv[args->libc]); 343 } 344 mrb_free(mrb, args->libv); 345 } 346 mrb_close(mrb); 261 347 } 262 348 … … 265 351 print_hint(void) 266 352 { 267 353 printf("mirb - Embeddable Interactive Ruby Shell\n\n"); 268 354 } 269 355 … … 273 359 print_cmdline(int code_block_open) 274 360 { 275 276 277 278 279 280 281 361 if (code_block_open) { 362 printf("* "); 363 } 364 else { 365 printf("> "); 366 } 367 fflush(stdout); 282 368 } 283 369 #endif … … 288 374 check_keyword(const char *buf, const char *word) 289 375 { 290 const char *p = buf; 291 size_t len = strlen(word); 292 293 /* skip preceding spaces */ 294 while (*p && isspace((unsigned char)*p)) { 295 p++; 296 } 297 /* check keyword */ 298 if (strncmp(p, word, len) != 0) { 299 return 0; 300 } 301 p += len; 302 /* skip trailing spaces */ 303 while (*p) { 304 if (!isspace((unsigned char)*p)) return 0; 305 p++; 306 } 307 return 1; 308 } 376 const char *p = buf; 377 size_t len = strlen(word); 378 379 /* skip preceding spaces */ 380 while (*p && ISSPACE(*p)) { 381 p++; 382 } 383 /* check keyword */ 384 if (strncmp(p, word, len) != 0) { 385 return 0; 386 } 387 p += len; 388 /* skip trailing spaces */ 389 while (*p) { 390 if (!ISSPACE(*p)) return 0; 391 p++; 392 } 393 return 1; 394 } 395 396 397 #ifndef ENABLE_READLINE 398 volatile sig_atomic_t input_canceled = 0; 399 void 400 ctrl_c_handler(int signo) 401 { 402 input_canceled = 1; 403 } 404 #else 405 SIGJMP_BUF ctrl_c_buf; 406 void 407 ctrl_c_handler(int signo) 408 { 409 MIRB_SIGLONGJMP(ctrl_c_buf, 1); 410 } 411 #endif 412 413 #ifndef DISABLE_MIRB_UNDERSCORE 414 void decl_lv_underscore(mrb_state *mrb, mrbc_context *cxt) 415 { 416 struct RProc *proc; 417 struct mrb_parser_state *parser; 418 419 parser = mrb_parse_string(mrb, "_=nil", cxt); 420 if (parser == NULL) { 421 fputs("create parser state error\n", stderr); 422 mrb_close(mrb); 423 exit(EXIT_FAILURE); 424 } 425 426 proc = mrb_generate_code(mrb, parser); 427 mrb_vm_run(mrb, proc, mrb_top_self(mrb), 0); 428 429 mrb_parser_free(parser); 430 } 431 #endif 309 432 310 433 int 311 434 mirb_main(int argc, char **argv) 312 435 { 313 char ruby_code[1024] = {0};314 char last_code_line[1024] = {0};436 char ruby_code[4096] = { 0 }; 437 char last_code_line[1024] = { 0 }; 315 438 #ifndef ENABLE_READLINE 316 317 int char_index;439 int last_char; 440 size_t char_index; 318 441 #else 319 char *history_path; 320 #endif 321 mrbc_context *cxt; 322 struct mrb_parser_state *parser; 323 mrb_state *mrb; 324 mrb_value result; 325 struct _args args; 326 int n; 327 mrb_bool code_block_open = FALSE; 328 int ai; 329 unsigned int stack_keep = 0; 330 331 /* new interpreter instance */ 332 mrb = mrb_open(); 333 if (mrb == NULL) { 334 fputs("Invalid mrb interpreter, exiting mirb\n", stderr); 335 return EXIT_FAILURE; 336 } 337 mrb_define_global_const(mrb, "ARGV", mrb_ary_new_capa(mrb, 0)); 338 339 n = parse_args(mrb, argc, argv, &args); 340 if (n == EXIT_FAILURE) { 341 cleanup(mrb, &args); 342 usage(argv[0]); 343 return n; 344 } 442 char *history_path; 443 char* line; 444 #endif 445 mrbc_context *cxt; 446 struct mrb_parser_state *parser; 447 mrb_state *mrb; 448 mrb_value result; 449 struct _args args; 450 mrb_value ARGV; 451 int n; 452 int i; 453 mrb_bool code_block_open = FALSE; 454 int ai; 455 unsigned int stack_keep = 0; 456 457 /* new interpreter instance */ 458 mrb = mrb_open(); 459 if (mrb == NULL) { 460 fputs("Invalid mrb interpreter, exiting mirb\n", stderr); 461 return EXIT_FAILURE; 462 } 463 464 n = parse_args(mrb, argc, argv, &args); 465 if (n == EXIT_FAILURE) { 466 cleanup(mrb, &args); 467 usage(argv[0]); 468 return n; 469 } 470 471 ARGV = mrb_ary_new_capa(mrb, args.argc); 472 for (i = 0; i < args.argc; i++) { 473 char* utf8 = mrb_utf8_from_locale(args.argv[i], -1); 474 if (utf8) { 475 mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8)); 476 mrb_utf8_free(utf8); 477 } 478 } 479 mrb_define_global_const(mrb, "ARGV", ARGV); 480 mrb_gv_set(mrb, mrb_intern_lit(mrb, "$DEBUG"), mrb_bool_value(args.debug)); 345 481 346 482 #ifdef ENABLE_READLINE 347 history_path = get_history_path(mrb); 348 if (history_path == NULL) { 349 fputs("failed to get history path\n", stderr); 350 mrb_close(mrb); 351 return EXIT_FAILURE; 352 } 353 354 MIRB_USING_HISTORY(); 355 MIRB_READ_HISTORY(history_path); 356 #endif 357 358 print_hint(); 359 360 cxt = mrbc_context_new(mrb); 361 cxt->capture_errors = TRUE; 362 cxt->lineno = 1; 363 mrbc_filename(mrb, cxt, "(mirb)"); 364 if (args.verbose) cxt->dump_result = TRUE; 365 366 ai = mrb_gc_arena_save(mrb); 367 368 while (TRUE) { 369 char *utf8; 483 history_path = get_history_path(mrb); 484 if (history_path == NULL) { 485 fputs("failed to get history path\n", stderr); 486 mrb_close(mrb); 487 return EXIT_FAILURE; 488 } 489 490 MIRB_USING_HISTORY(); 491 MIRB_READ_HISTORY(history_path); 492 #endif 493 494 print_hint(); 495 496 cxt = mrbc_context_new(mrb); 497 498 #ifndef DISABLE_MIRB_UNDERSCORE 499 decl_lv_underscore(mrb, cxt); 500 #endif 501 502 /* Load libraries */ 503 for (i = 0; i < args.libc; i++) { 504 FILE *lfp = fopen(args.libv[i], "r"); 505 if (lfp == NULL) { 506 printf("Cannot open library file. (%s)\n", args.libv[i]); 507 cleanup(mrb, &args); 508 return EXIT_FAILURE; 509 } 510 mrb_load_file_cxt(mrb, lfp, cxt); 511 fclose(lfp); 512 } 513 514 cxt->capture_errors = TRUE; 515 cxt->lineno = 1; 516 mrbc_filename(mrb, cxt, "(mirb)"); 517 if (args.verbose) cxt->dump_result = TRUE; 518 519 ai = mrb_gc_arena_save(mrb); 520 521 while (TRUE) { 522 char *utf8; 523 struct mrb_jmpbuf c_jmp; 524 525 MRB_TRY(&c_jmp); 526 mrb->jmp = &c_jmp; 527 if (args.rfp) { 528 if (fgets(last_code_line, sizeof(last_code_line)-1, args.rfp) != NULL) 529 goto done; 530 break; 531 } 370 532 371 533 #ifndef ENABLE_READLINE 372 print_cmdline(code_block_open); 373 374 char_index = 0; 375 while ((last_char = getchar()) != '\n') { 376 if (last_char == EOF) break; 377 if (char_index > sizeof(last_code_line) - 2) { 378 fputs("input string too long\n", stderr); 379 continue; 380 } 381 last_code_line[char_index++] = last_char; 382 } 383 if (last_char == EOF) { 384 fputs("\n", stdout); 385 break; 386 } 387 388 last_code_line[char_index++] = '\n'; 389 last_code_line[char_index] = '\0'; 534 print_cmdline(code_block_open); 535 536 signal(SIGINT, ctrl_c_handler); 537 char_index = 0; 538 while ((last_char = getchar()) != '\n') { 539 if (last_char == EOF) break; 540 if (char_index >= sizeof(last_code_line)-2) { 541 fputs("input string too long\n", stderr); 542 continue; 543 } 544 last_code_line[char_index++] = last_char; 545 } 546 signal(SIGINT, SIG_DFL); 547 if (input_canceled) { 548 ruby_code[0] = '\0'; 549 last_code_line[0] = '\0'; 550 code_block_open = FALSE; 551 puts("^C"); 552 input_canceled = 0; 553 continue; 554 } 555 if (last_char == EOF) { 556 fputs("\n", stdout); 557 break; 558 } 559 560 last_code_line[char_index++] = '\n'; 561 last_code_line[char_index] = '\0'; 390 562 #else 391 char* line = MIRB_READLINE(code_block_open ? "* " : "> "); 392 if (line == NULL) { 393 printf("\n"); 394 break; 395 } 396 if (strlen(line) > sizeof(last_code_line) - 2) { 397 fputs("input string too long\n", stderr); 398 continue; 399 } 400 strlcpy(last_code_line, line, sizeof(last_code_line)); 401 strlcat(last_code_line, "\n", sizeof(last_code_line)); 402 MIRB_ADD_HISTORY(line); 403 free(line); 404 #endif 405 406 if (code_block_open) { 407 if (strlen(ruby_code) + strlen(last_code_line) > sizeof(ruby_code) - 1) { 408 fputs("concatenated input string too long\n", stderr); 409 continue; 410 } 411 strlcat(ruby_code, last_code_line, sizeof(ruby_code)); 412 } 413 else { 414 if (check_keyword(last_code_line, "quit") || check_keyword(last_code_line, "exit")) { 415 break; 416 } 417 strlcpy(ruby_code, last_code_line, sizeof(ruby_code)); 418 } 419 420 utf8 = mrb_utf8_from_locale(ruby_code, -1); 421 if (!utf8) abort(); 422 423 /* parse code */ 424 parser = mrb_parser_new(mrb); 425 if (parser == NULL) { 426 fputs("create parser state error\n", stderr); 427 break; 428 } 429 parser->s = utf8; 430 parser->send = utf8 + strlen(utf8); 431 parser->lineno = cxt->lineno; 432 mrb_parser_parse(parser, cxt); 433 code_block_open = is_code_block_open(parser); 434 mrb_utf8_free(utf8); 435 436 if (code_block_open) { 437 /* no evaluation of code */ 438 } 439 else { 440 if (0 < parser->nerr) { 441 /* syntax error */ 442 printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message); 443 } 444 else { 445 /* generate bytecode */ 446 struct RProc *proc = mrb_generate_code(mrb, parser); 447 if (proc == NULL) { 448 fputs("codegen error\n", stderr); 449 mrb_parser_free(parser); 450 break; 451 } 452 453 if (args.verbose) { 454 mrb_codedump_all(mrb, proc); 455 } 456 /* pass a proc for evaulation */ 457 /* evaluate the bytecode */ 458 result = mrb_context_run(mrb, 459 proc, 460 mrb_top_self(mrb), 461 stack_keep); 462 stack_keep = proc->body.irep->nlocals; 463 /* did an exception occur? */ 464 if (mrb->exc) { 465 p(mrb, mrb_obj_value(mrb->exc), 0); 466 mrb->exc = 0; 467 } 468 else { 469 /* no */ 470 if (!mrb_respond_to(mrb, result, mrb_intern_lit(mrb, "inspect"))) { 471 result = mrb_any_to_s(mrb, result); 472 } 473 p(mrb, result, 1); 474 } 475 } 476 ruby_code[0] = '\0'; 477 last_code_line[0] = '\0'; 478 mrb_gc_arena_restore(mrb, ai); 479 } 480 mrb_parser_free(parser); 481 cxt->lineno++; 482 } 563 if (MIRB_SIGSETJMP(ctrl_c_buf) == 0) { 564 ; 565 } 566 else { 567 ruby_code[0] = '\0'; 568 last_code_line[0] = '\0'; 569 code_block_open = FALSE; 570 puts("^C"); 571 } 572 signal(SIGINT, ctrl_c_handler); 573 line = MIRB_READLINE(code_block_open ? "* " : "> "); 574 signal(SIGINT, SIG_DFL); 575 576 if (line == NULL) { 577 printf("\n"); 578 break; 579 } 580 if (strlen(line) > sizeof(last_code_line)-2) { 581 fputs("input string too long\n", stderr); 582 continue; 583 } 584 strcpy(last_code_line, line); 585 strcat(last_code_line, "\n"); 586 MIRB_ADD_HISTORY(line); 587 MIRB_LINE_FREE(line); 588 #endif 589 590 done: 591 if (code_block_open) { 592 if (strlen(ruby_code)+strlen(last_code_line) > sizeof(ruby_code)-1) { 593 fputs("concatenated input string too long\n", stderr); 594 continue; 595 } 596 strcat(ruby_code, last_code_line); 597 } 598 else { 599 if (check_keyword(last_code_line, "quit") || check_keyword(last_code_line, "exit")) { 600 break; 601 } 602 strcpy(ruby_code, last_code_line); 603 } 604 605 utf8 = mrb_utf8_from_locale(ruby_code, -1); 606 if (!utf8) abort(); 607 608 /* parse code */ 609 parser = mrb_parser_new(mrb); 610 if (parser == NULL) { 611 fputs("create parser state error\n", stderr); 612 break; 613 } 614 parser->s = utf8; 615 parser->send = utf8 + strlen(utf8); 616 parser->lineno = cxt->lineno; 617 mrb_parser_parse(parser, cxt); 618 code_block_open = is_code_block_open(parser); 619 mrb_utf8_free(utf8); 620 621 if (code_block_open) { 622 /* no evaluation of code */ 623 } 624 else { 625 if (0 < parser->nwarn) { 626 /* warning */ 627 char* msg = mrb_locale_from_utf8(parser->warn_buffer[0].message, -1); 628 printf("line %d: %s\n", parser->warn_buffer[0].lineno, msg); 629 mrb_locale_free(msg); 630 } 631 if (0 < parser->nerr) { 632 /* syntax error */ 633 char* msg = mrb_locale_from_utf8(parser->error_buffer[0].message, -1); 634 printf("line %d: %s\n", parser->error_buffer[0].lineno, msg); 635 mrb_locale_free(msg); 636 } 637 else { 638 /* generate bytecode */ 639 struct RProc *proc = mrb_generate_code(mrb, parser); 640 if (proc == NULL) { 641 fputs("codegen error\n", stderr); 642 mrb_parser_free(parser); 643 break; 644 } 645 646 if (args.verbose) { 647 mrb_codedump_all(mrb, proc); 648 } 649 /* adjust stack length of toplevel environment */ 650 if (mrb->c->cibase->env) { 651 struct REnv *e = mrb->c->cibase->env; 652 if (e && MRB_ENV_STACK_LEN(e) < proc->body.irep->nlocals) { 653 MRB_ENV_SET_STACK_LEN(e, proc->body.irep->nlocals); 654 } 655 } 656 /* pass a proc for evaluation */ 657 /* evaluate the bytecode */ 658 result = mrb_vm_run(mrb, 659 proc, 660 mrb_top_self(mrb), 661 stack_keep); 662 stack_keep = proc->body.irep->nlocals; 663 /* did an exception occur? */ 664 if (mrb->exc) { 665 p(mrb, mrb_obj_value(mrb->exc), 0); 666 mrb->exc = 0; 667 } 668 else { 669 /* no */ 670 if (!mrb_respond_to(mrb, result, mrb_intern_lit(mrb, "inspect"))){ 671 result = mrb_any_to_s(mrb, result); 672 } 673 p(mrb, result, 1); 674 #ifndef DISABLE_MIRB_UNDERSCORE 675 *(mrb->c->stack + 1) = result; 676 #endif 677 } 678 } 679 ruby_code[0] = '\0'; 680 last_code_line[0] = '\0'; 681 mrb_gc_arena_restore(mrb, ai); 682 } 683 mrb_parser_free(parser); 684 cxt->lineno++; 685 MRB_CATCH(&c_jmp) { 686 p(mrb, mrb_obj_value(mrb->exc), 0); 687 mrb->exc = 0; 688 } 689 MRB_END_EXC(&c_jmp); 690 } 483 691 484 692 #ifdef ENABLE_READLINE 485 MIRB_WRITE_HISTORY(history_path); 486 mrb_free(mrb, history_path); 487 #endif 488 489 mrbc_context_free(mrb, cxt); 490 mrb_close(mrb); 491 492 return 0; 493 } 693 MIRB_WRITE_HISTORY(history_path); 694 mrb_free(mrb, history_path); 695 #endif 696 697 if (args.rfp) fclose(args.rfp); 698 mrb_free(mrb, args.argv); 699 if (args.libv) { 700 for (i = 0; i < args.libc; ++i) { 701 mrb_free(mrb, args.libv[i]); 702 } 703 mrb_free(mrb, args.libv); 704 } 705 mrbc_context_free(mrb, cxt); 706 mrb_close(mrb); 707 708 return 0; 709 }
Note:
See TracChangeset
for help on using the changeset viewer.