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/mrbc.c

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