text: #include <mruby.h>
  
  #ifdef MRB_NO_STDIO
  # error mruby-bin-mruby conflicts 'MRB_NO_STDIO' in your build configuration
  #endif
  
  #include <stdlib.h>
  #include <string.h>
  #include <mruby/array.h>
  #include <mruby/compile.h>
  #include <mruby/dump.h>
  #include <mruby/variable.h>
  #include <mruby/proc.h>
  #include "asyncify.h"
  #include "setjmp.h"
  
  #if defined(_WIN32) || defined(_WIN64)
  # include <io.h> /* for setmode */
  # include <fcntl.h>
  #endif
  
  struct _args {
    FILE *rfp;
    char *cmdline;
    mrb_bool fname        : 1;
    mrb_bool mrbfile      : 1;
    mrb_bool check_syntax : 1;
    mrb_bool verbose      : 1;
    mrb_bool version      : 1;
    mrb_bool debug        : 1;
    int argc;
    char **argv;
    int libc;
    char **libv;
  };
  
  struct options {
    int argc;
    char **argv;
    char *program;
    char *opt;
    char short_opt[2];
  };
  
  static void
  usage(const char *name)
  {
    static const char *const usage_msg[] = {
    "switches:",
    "-b           load and execute RiteBinary (mrb) file",
    "-c           check syntax only",
    "-d           set debugging flags (set $DEBUG to true)",
    "-e 'command' one line of script",
    "-r library   load the library before executing your script",
    "-v           print version number, then run in verbose mode",
    "--verbose    run in verbose mode",
    "--version    print the version",
    "--copyright  print the copyright",
    NULL
    };
    const char *const *p = usage_msg;
  
    printf("Usage: %s [switches] [programfile] [arguments]\n", name);
    while (*p)
      printf("  %s\n", *p++);
  }
  
  static mrb_bool
  mrb_extension_p(const char *path)
  {
    const char *e = strrchr(path, '.');
    if (e && e[1] == 'm' && e[2] == 'r' && e[3] == 'b' && e[4] == '\0') {
      return TRUE;
    }
    return FALSE;
  }
  
  static void
  options_init(struct options *opts, int argc, char **argv)
  {
    opts->argc = argc;
    opts->argv = argv;
    opts->program = *argv;
    *opts->short_opt = 0;
  }
  
  static const char *
  options_opt(struct options *opts)
  {
    /* concatenated short options (e.g. `-cv`) */
    if (*opts->short_opt && *++opts->opt) {
     short_opt:
      opts->short_opt[0] = *opts->opt;
      opts->short_opt[1] = 0;
      return opts->short_opt;
    }
  
    while (++opts->argv, --opts->argc) {
      opts->opt = *opts->argv;
  
      /*  empty         || not start with `-`  || `-` */
      if (!opts->opt[0] || opts->opt[0] != '-' || !opts->opt[1]) return NULL;
  
      if (opts->opt[1] == '-') {
        /* `--` */
        if (!opts->opt[2]) {
          ++opts->argv, --opts->argc;
          return NULL;
        }
        /* long option */
        opts->opt += 2;
        *opts->short_opt = 0;
        return opts->opt;
      }
      else {
        /* short option */
        ++opts->opt;
        goto short_opt;
      }
    }
    return NULL;
  }
  
  static const char *
  options_arg(struct options *opts)
  {
    if (*opts->short_opt && opts->opt[1]) {
      /* concatenated short option and option argument (e.g. `-rLIBRARY`) */
      *opts->short_opt = 0;
      return opts->opt + 1;
    }
    --opts->argc, ++opts->argv;
    return opts->argc ? *opts->argv : NULL;
  }
  
  static char *
  dup_arg_item(mrb_state *mrb, const char *item)
  {
    size_t buflen = strlen(item) + 1;
    char *buf = (char*)mrb_malloc(mrb, buflen);
    memcpy(buf, item, buflen);
    return buf;
  }
  
  static int
  parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
  {
    static const struct _args args_zero = { 0 };
    struct options opts[1];
    const char *opt, *item;
  
    *args = args_zero;
    options_init(opts, argc, argv);
    while ((opt = options_opt(opts))) {
      if (strcmp(opt, "b") == 0) {
        args->mrbfile = TRUE;
      }
      else if (strcmp(opt, "c") == 0) {
        args->check_syntax = TRUE;
      }
      else if (strcmp(opt, "d") == 0) {
        args->debug = TRUE;
      }
      else if (strcmp(opt, "e") == 0) {
        if ((item = options_arg(opts))) {
          if (!args->cmdline) {
            args->cmdline = dup_arg_item(mrb, item);
          }
          else {
            size_t cmdlinelen;
            size_t itemlen;
  
            cmdlinelen = strlen(args->cmdline);
            itemlen = strlen(item);
            args->cmdline =
              (char *)mrb_realloc(mrb, args->cmdline, cmdlinelen + itemlen + 2);
            args->cmdline[cmdlinelen] = '\n';
            memcpy(args->cmdline + cmdlinelen + 1, item, itemlen + 1);
          }
        }
        else {
          fprintf(stderr, "%s: No code specified for -e\n", opts->program);
          return EXIT_FAILURE;
        }
      }
      else if (strcmp(opt, "h") == 0) {
        usage(opts->program);
        exit(EXIT_SUCCESS);
      }
      else if (strcmp(opt, "r") == 0) {
        if ((item = options_arg(opts))) {
          if (args->libc == 0) {
            args->libv = (char**)mrb_malloc(mrb, sizeof(char*));
          }
          else {
            args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1));
          }
          args->libv[args->libc++] = dup_arg_item(mrb, item);
        }
        else {
          fprintf(stderr, "%s: No library specified for -r\n", opts->program);
          return EXIT_FAILURE;
        }
      }
      else if (strcmp(opt, "v") == 0) {
        if (!args->verbose) {
          mrb_show_version(mrb);
          args->version = TRUE;
        }
        args->verbose = TRUE;
      }
      else if (strcmp(opt, "version") == 0) {
        mrb_show_version(mrb);
        exit(EXIT_SUCCESS);
      }
      else if (strcmp(opt, "verbose") == 0) {
        args->verbose = TRUE;
      }
      else if (strcmp(opt, "copyright") == 0) {
        mrb_show_copyright(mrb);
        exit(EXIT_SUCCESS);
      }
      else {
        fprintf(stderr, "%s: invalid option %s%s (-h will show valid options)\n",
                opts->program, opt[1] ? "--" : "-", opt);
        return EXIT_FAILURE;
      }
    }
  
    argc = opts->argc; argv = opts->argv;
    if (args->cmdline == NULL) {
      if (*argv == NULL) {
        if (args->version) exit(EXIT_SUCCESS);
        args->rfp = stdin;
      }
      else {
        args->rfp = strcmp(argv[0], "-") == 0 ?
          stdin : fopen(argv[0], "rb");
        if (args->rfp == NULL) {
          fprintf(stderr, "%s: Cannot open program file: %s\n", opts->program, argv[0]);
          return EXIT_FAILURE;
        }
        args->fname = TRUE;
        args->cmdline = argv[0];
        argc--; argv++;
      }
    }
  #if defined(_WIN32) || defined(_WIN64)
    if (args->rfp == stdin) {
      _setmode(_fileno(stdin), O_BINARY);
    }
  #endif
    args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1));
    memcpy(args->argv, argv, (argc+1) * sizeof(char*));
    args->argc = argc;
  
    return EXIT_SUCCESS;
  }
  
  static void
  cleanup(mrb_state *mrb, struct _args *args)
  {
    if (args->rfp && args->rfp != stdin)
      fclose(args->rfp);
    if (!args->fname)
      mrb_free(mrb, args->cmdline);
    mrb_free(mrb, args->argv);
    if (args->libc) {
      while (args->libc--) {
        mrb_free(mrb, args->libv[args->libc]);
      }
      mrb_free(mrb, args->libv);
    }
    mrb_close(mrb);
  }
  
  __attribute__((noinline))
  int
  __main(int argc, char **argv)
  {
    mrb_state *mrb = mrb_open();
    int n = -1;
    int i;
    struct _args args;
    mrb_value ARGV;
    mrbc_context *c;
    mrb_value v;
  
    if (mrb == NULL) {
      fprintf(stderr, "%s: Invalid mrb_state, exiting mruby\n", *argv);
      return EXIT_FAILURE;
    }
  
    n = parse_args(mrb, argc, argv, &args);
    if (n == EXIT_FAILURE || (args.cmdline == NULL && args.rfp == NULL)) {
      cleanup(mrb, &args);
      return n;
    }
    else {
      int ai = mrb_gc_arena_save(mrb);
      ARGV = mrb_ary_new_capa(mrb, args.argc);
      for (i = 0; i < args.argc; i++) {
        char* utf8 = mrb_utf8_from_locale(args.argv[i], -1);
        if (utf8) {
          mrb_ary_push(mrb, ARGV, mrb_str_new_cstr(mrb, utf8));
          mrb_utf8_free(utf8);
        }
      }
      mrb_define_global_const(mrb, "ARGV", ARGV);
      mrb_gv_set(mrb, mrb_intern_lit(mrb, "$DEBUG"), mrb_bool_value(args.debug));
  
      c = mrbc_context_new(mrb);
      if (args.verbose)
        c->dump_result = TRUE;
      if (args.check_syntax)
        c->no_exec = TRUE;
  
      /* Set $0 */
      const char *cmdline;
      if (args.rfp) {
        cmdline = args.cmdline ? args.cmdline : "-";
      }
      else {
        cmdline = "-e";
      }
      mrb_gv_set(mrb, mrb_intern_lit(mrb, "$0"), mrb_str_new_cstr(mrb, cmdline));
  
      /* Load libraries */
      for (i = 0; i < args.libc; i++) {
        struct REnv *e;
        FILE *lfp = fopen(args.libv[i], "rb");
        if (lfp == NULL) {
          fprintf(stderr, "%s: Cannot open library file: %s\n", *argv, args.libv[i]);
          mrbc_context_free(mrb, c);
          cleanup(mrb, &args);
          return EXIT_FAILURE;
        }
        mrbc_filename(mrb, c, args.libv[i]);
        if (mrb_extension_p(args.libv[i])) {
          v = mrb_load_irep_file_cxt(mrb, lfp, c);
        }
        else {
          v = mrb_load_detect_file_cxt(mrb, lfp, c);
        }
        fclose(lfp);
        e = mrb_vm_ci_env(mrb->c->cibase);
        mrb_vm_ci_env_set(mrb->c->cibase, NULL);
        mrb_env_unshare(mrb, e);
        mrbc_cleanup_local_variables(mrb, c);
      }
  
      /* set program file name */
      mrbc_filename(mrb, c, cmdline);
  
      /* Load program */
      if (args.mrbfile || mrb_extension_p(cmdline)) {
        v = mrb_load_irep_file_cxt(mrb, args.rfp, c);
      }
      else if (args.rfp) {
        v = mrb_load_detect_file_cxt(mrb, args.rfp, c);
      }
      else {
        char* utf8 = mrb_utf8_from_locale(args.cmdline, -1);
        if (!utf8) abort();
        v = mrb_load_string_cxt(mrb, utf8, c);
        mrb_utf8_free(utf8);
      }
  
      mrb_gc_arena_restore(mrb, ai);
      mrbc_context_free(mrb, c);
      if (mrb->exc) {
        if (!mrb_undef_p(v)) {
          mrb_print_error(mrb);
        }
        n = EXIT_FAILURE;
      }
      else if (args.check_syntax) {
        puts("Syntax OK");
      }
    }
    cleanup(mrb, &args);
  
    return n;
  }
  
  int
  main(int argc, char **argv) {
      int ret;
      // This has enough logic to handle one longjmp.
      while (1) {
          // Call into the program. This is either the first call, or a resume.
          ret = main(argc, argv);
          if (!__active_jmp_buf) {
              // The program has run to the end.
              return ret;
          }
          // The program is still working, just the stack has unwound to here.
          asyncify_stop_unwind();
          if (__active_jmp_buf->state == 1) {
              // Setjmp unwound to here. Prepare to rewind it twice.
              async_buf_note_unwound(&__active_jmp_buf->setjmp_buf);
          } else if (__active_jmp_buf->state == 2) {
              // Longjmp unwound to here. Rewind to the setjmp.
              async_buf_rewind(&__active_jmp_buf->setjmp_buf);
          }
          asyncify_start_rewind(&__active_jmp_buf->setjmp_buf);
      }
  }
  