Ignore:
Timestamp:
Jul 9, 2020, 8:51:43 AM (4 years ago)
Author:
coas-nagasima
Message:

mrubyを2.1.1に更新

File:
1 edited

Legend:

Unmodified
Added
Removed
  • EcnlProtoTool/trunk/prototool/src/mirb.c

    r321 r439  
    77*/
    88
     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
    923#include <stdlib.h>
    1024#include <string.h>
    11 #include <stdio.h>
    1225#include <ctype.h>
     26
     27#include <signal.h>
     28#include <setjmp.h>
    1329
    1430#ifdef ENABLE_READLINE
     
    1733#define MIRB_ADD_HISTORY(line) add_history(line)
    1834#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
    1941#define MIRB_WRITE_HISTORY(path) write_history(path)
    2042#define MIRB_READ_HISTORY(path) read_history(path)
     
    2547#define MIRB_ADD_HISTORY(line) linenoiseHistoryAdd(line)
    2648#define MIRB_READLINE(ch) linenoise(ch)
     49#define MIRB_LINE_FREE(line) linenoiseFree(line)
    2750#define MIRB_WRITE_HISTORY(path) linenoiseHistorySave(path)
    2851#define MIRB_READ_HISTORY(path) linenoiseHistoryLoad(history_path)
     
    3053#endif
    3154
    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
    3764
    3865#ifdef ENABLE_READLINE
     
    4370get_history_path(mrb_state *mrb)
    4471{
    45         char *path = NULL;
    46         const char *home = getenv("HOME");
     72  char *path = NULL;
     73  const char *home = getenv("HOME");
    4774
    4875#ifdef _WIN32
    49         if (home != NULL) {
    50                 home = getenv("USERPROFILE");
    51         }
    52 #endif
    53 
    54         if (home != NULL) {
    55                 int len = snprintf(NULL, 0, "%s/%s", home, history_file_name);
    56                 if (len >= 0) {
    57                         size_t size = len + 1;
    58                         path = (char *)mrb_malloc_simple(mrb, size);
    59                         if (path != NULL) {
    60                                 int n = snprintf(path, size, "%s/%s", home, history_file_name);
    61                                 if (n != len) {
    62                                         mrb_free(mrb, path);
    63                                         path = NULL;
    64                                 }
    65                         }
    66                 }
    67         }
    68 
    69         return path;
     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;
    7097}
    7198
     
    75102p(mrb_state *mrb, mrb_value obj, int prompt)
    76103{
    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);
    93123}
    94124
     
    98128is_code_block_open(struct mrb_parser_state *parser)
    99129{
    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;
    194220}
    195221
    196222struct _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;
    200230};
    201231
     
    203233usage(const char *name)
    204234{
    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
     252static char *
     253dup_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;
    218259}
    219260
     
    221262parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
    222263{
    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;
    255332}
    256333
     
    258335cleanup(mrb_state *mrb, struct _args *args)
    259336{
    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);
    261347}
    262348
     
    265351print_hint(void)
    266352{
    267         printf("mirb - Embeddable Interactive Ruby Shell\n\n");
     353  printf("mirb - Embeddable Interactive Ruby Shell\n\n");
    268354}
    269355
     
    273359print_cmdline(int code_block_open)
    274360{
    275         if (code_block_open) {
    276                 printf("* ");
    277         }
    278         else {
    279                 printf("> ");
    280         }
    281         fflush(stdout);
     361  if (code_block_open) {
     362    printf("* ");
     363  }
     364  else {
     365    printf("> ");
     366  }
     367  fflush(stdout);
    282368}
    283369#endif
     
    288374check_keyword(const char *buf, const char *word)
    289375{
    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
     398volatile sig_atomic_t input_canceled = 0;
     399void
     400ctrl_c_handler(int signo)
     401{
     402  input_canceled = 1;
     403}
     404#else
     405SIGJMP_BUF ctrl_c_buf;
     406void
     407ctrl_c_handler(int signo)
     408{
     409  MIRB_SIGLONGJMP(ctrl_c_buf, 1);
     410}
     411#endif
     412
     413#ifndef DISABLE_MIRB_UNDERSCORE
     414void 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
    309432
    310433int
    311434mirb_main(int argc, char **argv)
    312435{
    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 };
    315438#ifndef ENABLE_READLINE
    316         int last_char;
    317         int char_index;
     439  int last_char;
     440  size_t char_index;
    318441#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));
    345481
    346482#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    }
    370532
    371533#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';
    390562#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  }
    483691
    484692#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.