w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

mruby.c
Go to the documentation of this file.
1 #include <mruby.h>
2 
3 #ifdef MRB_NO_STDIO
4 # error mruby-bin-mruby conflicts 'MRB_NO_STDIO' in your build configuration
5 #endif
6 
7 #include <stdlib.h>
8 #include <string.h>
9 #include <mruby/array.h>
10 #include <mruby/compile.h>
11 #include <mruby/dump.h>
12 #include <mruby/variable.h>
13 #include <mruby/proc.h>
14 
15 #if defined(_WIN32) || defined(_WIN64)
16 # include <io.h> /* for setmode */
17 # include <fcntl.h>
18 #endif
19 
20 struct _args {
21  FILE *rfp;
22  char *cmdline;
24  mrb_bool mrbfile : 1;
26  mrb_bool verbose : 1;
28  mrb_bool debug : 1;
29  int argc;
30  char **argv;
31  int libc;
32  char **libv;
33 };
34 
35 struct options {
36  int argc;
37  char **argv;
38  char *program;
39  char *opt;
40  char short_opt[2];
41 };
42 
43 static void
44 usage(const char *name)
45 {
46  static const char *const usage_msg[] = {
47  "switches:",
48  "-b load and execute RiteBinary (mrb) file",
49  "-c check syntax only",
50  "-d set debugging flags (set $DEBUG to true)",
51  "-e 'command' one line of script",
52  "-r library load the library before executing your script",
53  "-v print version number, then run in verbose mode",
54  "--verbose run in verbose mode",
55  "--version print the version",
56  "--copyright print the copyright",
57  NULL
58  };
59  const char *const *p = usage_msg;
60 
61  printf("Usage: %s [switches] [programfile] [arguments]\n", name);
62  while (*p)
63  printf(" %s\n", *p++);
64 }
65 
66 static void
67 options_init(struct options *opts, int argc, char **argv)
68 {
69  opts->argc = argc;
70  opts->argv = argv;
71  opts->program = *argv;
72  *opts->short_opt = 0;
73 }
74 
75 static const char *
77 {
78  /* concatenated short options (e.g. `-cv`) */
79  if (*opts->short_opt && *++opts->opt) {
80  short_opt:
81  opts->short_opt[0] = *opts->opt;
82  opts->short_opt[1] = 0;
83  return opts->short_opt;
84  }
85 
86  while (++opts->argv, --opts->argc) {
87  opts->opt = *opts->argv;
88 
89  /* empty || not start with `-` || `-` */
90  if (!opts->opt[0] || opts->opt[0] != '-' || !opts->opt[1]) return NULL;
91 
92  if (opts->opt[1] == '-') {
93  /* `--` */
94  if (!opts->opt[2]) {
95  ++opts->argv, --opts->argc;
96  return NULL;
97  }
98  /* long option */
99  opts->opt += 2;
100  *opts->short_opt = 0;
101  return opts->opt;
102  }
103  else {
104  /* short option */
105  ++opts->opt;
106  goto short_opt;
107  }
108  }
109  return NULL;
110 }
111 
112 static const char *
114 {
115  if (*opts->short_opt && opts->opt[1]) {
116  /* concatenated short option and option argument (e.g. `-rLIBRARY`) */
117  *opts->short_opt = 0;
118  return opts->opt + 1;
119  }
120  --opts->argc, ++opts->argv;
121  return opts->argc ? *opts->argv : NULL;
122 }
123 
124 static char *
125 dup_arg_item(mrb_state *mrb, const char *item)
126 {
127  size_t buflen = strlen(item) + 1;
128  char *buf = (char*)mrb_malloc(mrb, buflen);
129  memcpy(buf, item, buflen);
130  return buf;
131 }
132 
133 static int
134 parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
135 {
136  static const struct _args args_zero = { 0 };
137  struct options opts[1];
138  const char *opt, *item;
139 
140  *args = args_zero;
142  while ((opt = options_opt(opts))) {
143  if (strcmp(opt, "b") == 0) {
144  args->mrbfile = TRUE;
145  }
146  else if (strcmp(opt, "c") == 0) {
147  args->check_syntax = TRUE;
148  }
149  else if (strcmp(opt, "d") == 0) {
150  args->debug = TRUE;
151  }
152  else if (strcmp(opt, "e") == 0) {
153  if ((item = options_arg(opts))) {
154  if (!args->cmdline) {
155  args->cmdline = dup_arg_item(mrb, item);
156  }
157  else {
158  size_t cmdlinelen;
159  size_t itemlen;
160 
161  cmdlinelen = strlen(args->cmdline);
162  itemlen = strlen(item);
163  args->cmdline =
164  (char *)mrb_realloc(mrb, args->cmdline, cmdlinelen + itemlen + 2);
165  args->cmdline[cmdlinelen] = '\n';
166  memcpy(args->cmdline + cmdlinelen + 1, item, itemlen + 1);
167  }
168  }
169  else {
170  fprintf(stderr, "%s: No code specified for -e\n", opts->program);
171  return EXIT_FAILURE;
172  }
173  }
174  else if (strcmp(opt, "h") == 0) {
175  usage(opts->program);
177  }
178  else if (strcmp(opt, "r") == 0) {
179  if ((item = options_arg(opts))) {
180  if (args->libc == 0) {
181  args->libv = (char**)mrb_malloc(mrb, sizeof(char*));
182  }
183  else {
184  args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1));
185  }
186  args->libv[args->libc++] = dup_arg_item(mrb, item);
187  }
188  else {
189  fprintf(stderr, "%s: No library specified for -r\n", opts->program);
190  return EXIT_FAILURE;
191  }
192  }
193  else if (strcmp(opt, "v") == 0) {
194  if (!args->verbose) {
195  mrb_show_version(mrb);
196  args->version = TRUE;
197  }
198  args->verbose = TRUE;
199  }
200  else if (strcmp(opt, "version") == 0) {
201  mrb_show_version(mrb);
203  }
204  else if (strcmp(opt, "verbose") == 0) {
205  args->verbose = TRUE;
206  }
207  else if (strcmp(opt, "copyright") == 0) {
208  mrb_show_copyright(mrb);
210  }
211  else {
212  fprintf(stderr, "%s: invalid option %s%s (-h will show valid options)\n",
213  opts->program, opt[1] ? "--" : "-", opt);
214  return EXIT_FAILURE;
215  }
216  }
217 
218  argc = opts->argc; argv = opts->argv;
219  if (args->cmdline == NULL) {
220  if (*argv == NULL) {
221  if (args->version) exit(EXIT_SUCCESS);
222  args->rfp = stdin;
223  }
224  else {
225  args->rfp = strcmp(argv[0], "-") == 0 ?
226  stdin : fopen(argv[0], "rb");
227  if (args->rfp == NULL) {
228  fprintf(stderr, "%s: Cannot open program file: %s\n", opts->program, argv[0]);
229  return EXIT_FAILURE;
230  }
231  args->fname = TRUE;
232  args->cmdline = argv[0];
233  argc--; argv++;
234  }
235  }
236 #if defined(_WIN32) || defined(_WIN64)
237  if (args->rfp == stdin) {
238  _setmode(_fileno(stdin), O_BINARY);
239  }
240 #endif
241  args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1));
242  memcpy(args->argv, argv, (argc+1) * sizeof(char*));
243  args->argc = argc;
244 
245  return EXIT_SUCCESS;
246 }
247 
248 static void
249 cleanup(mrb_state *mrb, struct _args *args)
250 {
251  if (args->rfp && args->rfp != stdin)
252  fclose(args->rfp);
253  if (!args->fname)
254  mrb_free(mrb, args->cmdline);
255  mrb_free(mrb, args->argv);
256  if (args->libc) {
257  while (args->libc--) {
258  mrb_free(mrb, args->libv[args->libc]);
259  }
260  mrb_free(mrb, args->libv);
261  }
262  mrb_close(mrb);
263 }
264 
265 int
266 main(int argc, char **argv)
267 {
268  mrb_state *mrb = mrb_open();
269  int n = -1;
270  int i;
271  struct _args args;
272  mrb_value ARGV;
273  mrbc_context *c;
274  mrb_value v;
275  mrb_sym zero_sym;
276 
277  if (mrb == NULL) {
278  fprintf(stderr, "%s: Invalid mrb_state, exiting mruby\n", *argv);
279  return EXIT_FAILURE;
280  }
281 
282  n = parse_args(mrb, argc, argv, &args);
283  if (n == EXIT_FAILURE || (args.cmdline == NULL && args.rfp == NULL)) {
284  cleanup(mrb, &args);
285  return n;
286  }
287  else {
288  int ai = mrb_gc_arena_save(mrb);
289  ARGV = mrb_ary_new_capa(mrb, args.argc);
290  for (i = 0; i < args.argc; i++) {
291  char* utf8 = mrb_utf8_from_locale(args.argv[i], -1);
292  if (utf8) {
293  mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8));
295  }
296  }
297  mrb_define_global_const(mrb, "ARGV", ARGV);
298  mrb_gv_set(mrb, mrb_intern_lit(mrb, "$DEBUG"), mrb_bool_value(args.debug));
299 
300  c = mrbc_context_new(mrb);
301  if (args.verbose)
302  c->dump_result = TRUE;
303  if (args.check_syntax)
304  c->no_exec = TRUE;
305 
306  /* Set $0 */
307  zero_sym = mrb_intern_lit(mrb, "$0");
308  if (args.rfp) {
309  const char *cmdline;
310  cmdline = args.cmdline ? args.cmdline : "-";
311  mrbc_filename(mrb, c, cmdline);
312  mrb_gv_set(mrb, zero_sym, mrb_str_new_cstr(mrb, cmdline));
313  }
314  else {
315  mrbc_filename(mrb, c, "-e");
316  mrb_gv_set(mrb, zero_sym, mrb_str_new_lit(mrb, "-e"));
317  }
318 
319  /* Load libraries */
320  for (i = 0; i < args.libc; i++) {
321  struct REnv *e;
322  FILE *lfp = fopen(args.libv[i], "rb");
323  if (lfp == NULL) {
324  fprintf(stderr, "%s: Cannot open library file: %s\n", *argv, args.libv[i]);
325  mrbc_context_free(mrb, c);
326  cleanup(mrb, &args);
327  return EXIT_FAILURE;
328  }
329  if (args.mrbfile) {
330  v = mrb_load_irep_file_cxt(mrb, lfp, c);
331  }
332  else {
333  v = mrb_load_detect_file_cxt(mrb, lfp, c);
334  }
335  fclose(lfp);
336  e = mrb_vm_ci_env(mrb->c->cibase);
337  mrb_vm_ci_env_set(mrb->c->cibase, NULL);
338  mrb_env_unshare(mrb, e);
340  }
341 
342  /* Load program */
343  if (args.mrbfile) {
344  v = mrb_load_irep_file_cxt(mrb, args.rfp, c);
345  }
346  else if (args.rfp) {
347  v = mrb_load_detect_file_cxt(mrb, args.rfp, c);
348  }
349  else {
350  char* utf8 = mrb_utf8_from_locale(args.cmdline, -1);
351  if (!utf8) abort();
352  v = mrb_load_string_cxt(mrb, utf8, c);
354  }
355 
356  mrb_gc_arena_restore(mrb, ai);
357  mrbc_context_free(mrb, c);
358  if (mrb->exc) {
359  if (!mrb_undef_p(v)) {
360  mrb_print_error(mrb);
361  }
362  n = EXIT_FAILURE;
363  }
364  else if (args.check_syntax) {
365  puts("Syntax OK");
366  }
367  }
368  cleanup(mrb, &args);
369 
370  return n;
371 }
#define buflen
Definition: afm2pl.c:181
#define name
#define mrb_undef_p(o)
Definition: boxing_word.h:145
static int item
Definition: brushtopbm.c:66
#define n
Definition: t4ht.c:1290
@ TRUE
Definition: dd.h:102
Options opts[]
Definition: dt2dv.c:309
mrb_value mrb_load_irep_file_cxt(mrb_state *, FILE *, mrbc_context *)
Definition: load.c:712
int v
Definition: dviconv.c:10
#define fopen
Definition: xxstdio.h:21
int strcmp()
Definition: coll.cpp:143
int printf()
#define c(n)
Definition: gpos-common.c:150
#define memcpy(d, s, n)
Definition: gsftopk.c:64
#define EXIT_SUCCESS
Definition: cdjpeg.h:175
#define EXIT_FAILURE
Definition: cdjpeg.h:169
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p
Definition: afcover.h:72
small capitals from c petite p scientific i
Definition: afcover.h:80
void exit()
#define O_BINARY
Definition: config.h:393
#define buf
#define fclose
Definition: debug.h:100
#define fprintf
Definition: mendex.h:64
void abort()
int main(int argc, char **argv)
Definition: mruby.c:266
static int parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
Definition: mruby.c:134
static void cleanup(mrb_state *mrb, struct _args *args)
Definition: mruby.c:249
static char * dup_arg_item(mrb_state *mrb, const char *item)
Definition: mruby.c:125
static void usage(const char *name)
Definition: mruby.c:44
static const char * options_opt(struct options *opts)
Definition: mruby.c:76
static void options_init(struct options *opts, int argc, char **argv)
Definition: mruby.c:67
static const char * options_arg(struct options *opts)
Definition: mruby.c:113
mrb_state * mrb_open(void)
Definition: state.c:73
#define mrb_intern_lit(mrb, lit)
Definition: mruby.h:1102
void mrb_show_version(mrb_state *mrb)
Definition: print.c:62
void * mrb_realloc(mrb_state *, void *, size_t)
Definition: gc.c:238
#define mrb_str_new_lit(mrb, lit)
Definition: mruby.h:1136
static void mrb_gc_arena_restore(mrb_state *mrb, int idx)
Definition: mruby.h:1239
static int mrb_gc_arena_save(mrb_state *mrb)
Definition: mruby.h:1233
void mrb_print_error(mrb_state *mrb)
Definition: print.c:56
void mrb_show_copyright(mrb_state *mrb)
Definition: print.c:68
void mrb_close(mrb_state *mrb)
Definition: state.c:182
mrb_value mrb_str_new_cstr(mrb_state *, const char *)
Definition: string.c:203
#define mrb_utf8_from_locale(p, l)
Definition: mruby.h:1150
#define mrb_utf8_free(p)
Definition: mruby.h:1153
void mrb_free(mrb_state *, void *)
Definition: gc.c:288
void * mrb_malloc(mrb_state *, size_t)
Definition: gc.c:256
utf< uint8 > utf8
Definition: UtfCodec.h:249
#define cmdline(i)
Definition: omfonts.c:51
mrb_value mrb_ary_new_capa(mrb_state *, mrb_int)
Definition: array.c:46
void mrb_ary_push(mrb_state *mrb, mrb_value array, mrb_value value)
Definition: array.c:495
mrb_value mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *cxt)
Definition: y.tab.c:12922
void mrbc_cleanup_local_variables(mrb_state *mrb, mrbc_context *c)
Definition: y.tab.c:12687
mrb_value mrb_load_detect_file_cxt(mrb_state *mrb, FILE *fp, mrbc_context *c)
Definition: y.tab.c:12868
mrbc_context * mrbc_context_new(mrb_state *mrb)
Definition: y.tab.c:12650
const char * mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s)
Definition: y.tab.c:12664
void mrbc_context_free(mrb_state *mrb, mrbc_context *cxt)
Definition: y.tab.c:12656
#define mrb_define_global_const(mrb, name, v)
Definition: scanning.h:24
void mrb_env_unshare(mrb_state *, struct REnv *)
Definition: vm.c:278
static struct REnv * mrb_vm_ci_env(const mrb_callinfo *ci)
Definition: proc.h:172
static void mrb_vm_ci_env_set(mrb_callinfo *ci, struct REnv *e)
Definition: proc.h:183
void mrb_gv_set(mrb_state *mrb, mrb_sym sym, mrb_value val)
Definition: variable.c:940
ShellFileEnvironment e
Definition: sh6.c:388
#define ARGV
Definition: proc.h:18
Definition: mrdb.c:27
char ** libv
Definition: mirb.c:240
mrb_bool mrbfile
Definition: mrdb.c:33
mrb_bool check_syntax
Definition: mruby.c:25
mrb_bool fname
Definition: mruby.c:23
char * cmdline
Definition: mruby.c:22
char ** argv
Definition: mrdb.c:32
mrb_bool verbose
Definition: mirb.c:235
mrb_bool debug
Definition: mirb.c:236
FILE * rfp
Definition: mrdb.c:28
int argc
Definition: mrdb.c:31
mrb_bool version
Definition: mruby.c:27
int libc
Definition: mirb.c:239
Definition: usprintf.c:39
mrb_callinfo * cibase
Definition: mruby.h:179
struct mrb_context * c
Definition: mruby.h:235
struct RObject * exc
Definition: mruby.h:239
int argc
Definition: mruby.c:36
char * program
Definition: mruby.c:38
char short_opt[2]
Definition: mruby.c:40
char * opt
Definition: mruby.c:39
char ** argv
Definition: mruby.c:37
#define FILE
Definition: t1stdio.h:34
*job_name strlen((char *) job_name) - 4)
static mrb_value mrb_bool_value(mrb_bool boolean)
Definition: value.h:360
#define argv
Definition: xmain.c:270
#define argc
Definition: xmain.c:269