Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
mruby.c
Go to the documentation of this file.
1 #include "mruby.h"
2 #include "mruby/proc.h"
3 #include "mruby/array.h"
4 #include "mruby/string.h"
5 #include "mruby/compile.h"
6 #include "mruby/dump.h"
7 #include "mruby/variable.h"
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #ifndef ENABLE_STDIO
13 static void
14 p(mrb_state *mrb, mrb_value obj)
15 {
16  obj = mrb_funcall(mrb, obj, "inspect", 0);
17  fwrite(RSTRING_PTR(obj), RSTRING_LEN(obj), 1, stdout);
18  putc('\n', stdout);
19 }
20 #else
21 #define p(mrb,obj) mrb_p(mrb,obj)
22 #endif
23 
26 
27 struct _args {
28  FILE *rfp;
29  char* cmdline;
33  mrb_bool verbose : 1;
34  int argc;
35  char** argv;
36 };
37 
38 static void
39 usage(const char *name)
40 {
41  static const char *const usage_msg[] = {
42  "switches:",
43  "-b load and execute RiteBinary (mrb) file",
44  "-c check syntax only",
45  "-e 'command' one line of script",
46  "-v print version number, then run in verbose mode",
47  "--verbose run in verbose mode",
48  "--version print the version",
49  "--copyright print the copyright",
50  NULL
51  };
52  const char *const *p = usage_msg;
53 
54  printf("Usage: %s [switches] programfile\n", name);
55  while (*p)
56  printf(" %s\n", *p++);
57 }
58 
59 static int
60 parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
61 {
62  char **origargv = argv;
63  static const struct _args args_zero = { 0 };
64 
65  *args = args_zero;
66 
67  for (argc--,argv++; argc > 0; argc--,argv++) {
68  char *item;
69  if (argv[0][0] != '-') break;
70 
71  if (strlen(*argv) <= 1) {
72  argc--; argv++;
73  args->rfp = stdin;
74  break;
75  }
76 
77  item = argv[0] + 1;
78  switch (*item++) {
79  case 'b':
80  args->mrbfile = 1;
81  break;
82  case 'c':
83  args->check_syntax = 1;
84  break;
85  case 'e':
86  if (item[0]) {
87  goto append_cmdline;
88  }
89  else if (argc > 1) {
90  argc--; argv++;
91  item = argv[0];
92 append_cmdline:
93  if (!args->cmdline) {
94  size_t buflen;
95  char *buf;
96 
97  buflen = strlen(item) + 1;
98  buf = (char *)mrb_malloc(mrb, buflen);
99  memcpy(buf, item, buflen);
100  args->cmdline = buf;
101  }
102  else {
103  size_t cmdlinelen;
104  size_t itemlen;
105 
106  cmdlinelen = strlen(args->cmdline);
107  itemlen = strlen(item);
108  args->cmdline =
109  (char *)mrb_realloc(mrb, args->cmdline, cmdlinelen + itemlen + 2);
110  args->cmdline[cmdlinelen] = '\n';
111  memcpy(args->cmdline + cmdlinelen + 1, item, itemlen + 1);
112  }
113  }
114  else {
115  printf("%s: No code specified for -e\n", *origargv);
116  return EXIT_SUCCESS;
117  }
118  break;
119  case 'v':
120  if (!args->verbose) mrb_show_version(mrb);
121  args->verbose = 1;
122  break;
123  case '-':
124  if (strcmp((*argv) + 2, "version") == 0) {
125  mrb_show_version(mrb);
126  exit(EXIT_SUCCESS);
127  }
128  else if (strcmp((*argv) + 2, "verbose") == 0) {
129  args->verbose = 1;
130  break;
131  }
132  else if (strcmp((*argv) + 2, "copyright") == 0) {
133  mrb_show_copyright(mrb);
134  exit(EXIT_SUCCESS);
135  }
136  default:
137  return EXIT_FAILURE;
138  }
139  }
140 
141  if (args->rfp == NULL && args->cmdline == NULL) {
142  if (*argv == NULL) args->rfp = stdin;
143  else {
144  args->rfp = fopen(argv[0], args->mrbfile ? "rb" : "r");
145  if (args->rfp == NULL) {
146  printf("%s: Cannot open program file. (%s)\n", *origargv, *argv);
147  return 0;
148  }
149  args->fname = 1;
150  args->cmdline = argv[0];
151  argc--; argv++;
152  }
153  }
154  args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1));
155  memcpy(args->argv, argv, (argc+1) * sizeof(char*));
156  args->argc = argc;
157 
158  return EXIT_SUCCESS;
159 }
160 
161 static void
162 cleanup(mrb_state *mrb, struct _args *args)
163 {
164  if (args->rfp && args->rfp != stdin)
165  fclose(args->rfp);
166  if (args->cmdline && !args->fname)
167  mrb_free(mrb, args->cmdline);
168  if (args->argv)
169  mrb_free(mrb, args->argv);
170  mrb_close(mrb);
171 }
172 
173 int
174 main(int argc, char **argv)
175 {
176  mrb_state *mrb = mrb_open();
177  int n = -1;
178  int i;
179  struct _args args;
180  mrb_value ARGV;
181 
182  if (mrb == NULL) {
183  fputs("Invalid mrb_state, exiting mruby\n", stderr);
184  return EXIT_FAILURE;
185  }
186 
187  n = parse_args(mrb, argc, argv, &args);
188  if (n == EXIT_FAILURE || (args.cmdline == NULL && args.rfp == NULL)) {
189  cleanup(mrb, &args);
190  usage(argv[0]);
191  return n;
192  }
193 
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(mrb, args.argv[i], strlen(args.argv[i])));
197  }
198  mrb_define_global_const(mrb, "ARGV", ARGV);
199 
200  if (args.mrbfile) {
201  n = mrb_read_irep_file(mrb, args.rfp);
202  if (n < 0) {
203  fprintf(stderr, "failed to load mrb file: %s\n", args.cmdline);
204  }
205  else if (!args.check_syntax) {
206  mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));
207  n = 0;
208  if (mrb->exc) {
209  mrb_print_error(mrb);
210  n = -1;
211  }
212  }
213  }
214  else {
215  mrbc_context *c = mrbc_context_new(mrb);
216  mrb_sym zero_sym = mrb_intern2(mrb, "$0", 2);
217  mrb_value v;
218 
219  if (args.verbose)
220  c->dump_result = 1;
221  if (args.check_syntax)
222  c->no_exec = 1;
223 
224  if (args.rfp) {
225  char *cmdline;
226  cmdline = args.cmdline ? args.cmdline : "-";
227  mrbc_filename(mrb, c, cmdline);
228  mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline));
229  v = mrb_load_file_cxt(mrb, args.rfp, c);
230  }
231  else {
232  mrbc_filename(mrb, c, "-e");
233  mrb_gv_set(mrb, zero_sym, mrb_str_new(mrb, "-e", 2));
234  v = mrb_load_string_cxt(mrb, args.cmdline, c);
235  }
236 
237  mrbc_context_free(mrb, c);
238  if (mrb->exc) {
239  if (!mrb_undef_p(v)) {
240  mrb_print_error(mrb);
241  }
242  n = -1;
243  }
244  else if (args.check_syntax) {
245  printf("Syntax OK\n");
246  }
247  }
248  cleanup(mrb, &args);
249 
250  return n == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
251 }