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/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
    17#include <stdlib.h>
    28#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
     14struct _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
     29struct options {
     30  int argc;
     31  char **argv;
     32  char *program;
     33  char *opt;
     34  char short_opt[2];
    3335};
    3436
     
    3638usage(const char *name)
    3739{
    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
     60static void
     61options_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
     69static const char *
     70options_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
     106static const char *
     107options_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
     118static char *
     119dup_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;
    54125}
    55126
     
    57128parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
    58129{
    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;
    156235}
    157236
     
    159238cleanup(mrb_state *mrb, struct _args *args)
    160239{
    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);
    167252}
    168253
     
    170255mruby_main(int argc, char **argv)
    171256{
    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.