1/****************************************************************/
2/* This command-line parser is used by both Racket and GRacket. */
3/****************************************************************/
4
5#ifdef NEED_CONSOLE_PRINTF
6static void (*console_printf)(char *str, ...);
7# define PRINTF console_printf
8#endif
9
10#include "../start/config.inc"
11
12#ifdef DOS_FILE_SYSTEM
13static void record_dll_path(void)
14{
15  GC_CAN_IGNORE wchar_t *dlldir;
16  dlldir = extract_dlldir();
17  if (dlldir)
18    scheme_set_dll_path(dlldir);
19}
20#endif
21
22#ifndef DONT_PARSE_COMMAND_LINE
23static int is_number_arg(const char *s)
24{
25  while (*s) {
26    if (*s < '0' || *s > '9') {
27      if (*s == '.') {
28	s++;
29	while (*s) {
30	  if (*s < '0' || *s > '9')
31	    return 0;
32	  else
33	    s++;
34	}
35	return 1;
36      } else
37	return 0;
38    } else
39      s++;
40  }
41
42  return 1;
43}
44
45char *add_to_str(const char *addr, long amt)
46{
47  long addr_v;
48  char buf[32];
49  addr_v = atoi(addr) + amt;
50  sprintf(buf, "%ld", addr_v);
51  return strdup(buf);
52}
53
54static char *make_embedded_load(const self_exe_t self_exe, const char *file, const char *start, const char *end)
55{
56  char *s;
57  int slen, elen, flen;
58
59  if (file == NULL) {
60    long fileoff;
61    fileoff = get_segment_offset(self_exe);
62    start = add_to_str(start, fileoff);
63    end = add_to_str(end, fileoff);
64    file = SELF_PATH_TO_BYTES(self_exe);
65  }
66
67  slen = strlen(start);
68  elen = strlen(end);
69  flen = strlen(file);
70
71  s = (char *)malloc(slen + elen + flen + 3);
72  memcpy(s, start, slen + 1);
73  memcpy(s + slen + 1, end, elen + 1);
74  memcpy(s + slen + elen + 2, file, flen + 1);
75
76  return s;
77}
78
79static Scheme_Object *check_make_path(const char *prog, const char *real_switch, char *arg)
80{
81  if (!*arg) {
82    PRINTF("%s: empty path after %s switch\n",
83           prog, real_switch);
84    exit(1);
85  }
86  return scheme_make_path(arg);
87}
88#endif
89
90enum {
91  mzcmd_EVAL            = 0,
92  mzcmd_LOAD            = 1,
93  mzcmd_MAIN            = 2,
94  mzcmd_REQUIRE_FILE    = 3,
95  mzcmd_REQUIRE_LIB     = 4,
96  mzcmd_REQUIRE_PLANET  = 5,
97  mzcmd_EMBEDDED        = 6,
98  mzcmd_EMBEDDED_REG    = 7,
99};
100
101/* To avoid having to create a specific mark procedure for
102   prcise GC, split argument information into purely atomic
103   and purely non-atomic records. */
104
105typedef struct {
106  int init_ns;
107#ifndef DONT_PARSE_COMMAND_LINE
108  int num_enl;
109#endif
110#ifndef DONT_LOAD_INIT_FILE
111  int no_init_file;
112#endif
113#ifndef DONT_RUN_REP
114  int use_repl;
115  int script_mode;
116#endif
117#ifndef NO_YIELD_BEFORE_EXIT
118  int add_yield;
119#endif
120#ifdef CMDLINE_STDIO_FLAG
121  int alternate_rep;
122  int no_front;
123#endif
124} FinishArgsAtoms;
125
126typedef struct {
127  FinishArgsAtoms *a;
128#ifndef DONT_PARSE_COMMAND_LINE
129  char **evals_and_loads;
130  int *eval_kind;
131  Scheme_Object *main_args;
132#endif
133  Scheme_Env *global_env;
134  char *init_lib;
135} FinishArgs;
136
137typedef void (*Repl_Proc)(Scheme_Env *, FinishArgs *f);
138
139static void configure_environment(Scheme_Object *mod)
140{
141  Scheme_Object *mli, *dyreq, *a[3], *gi, *v, *vs;
142  Scheme_Object *submod, *cr, *mdp, *mpij;
143
144  /* Modern style: look for `runtime-configure' submodule to initialize
145     the configuration: */
146
147  submod = scheme_intern_symbol("submod");
148  cr = scheme_intern_symbol("configure-runtime");
149
150  if (scheme_is_module_path_index(mod)) {
151    mpij = scheme_builtin_value("module-path-index-join");
152    a[0] = scheme_make_pair(submod,
153                            scheme_make_pair(scheme_make_utf8_string("."),
154                                             scheme_make_pair(cr, scheme_make_null())));
155    a[1] = mod;
156    submod = scheme_apply(mpij, 2, a);
157  } else if (SCHEME_PAIRP(mod) && SAME_OBJ(SCHEME_CAR(mod), submod))
158    submod = scheme_append(mod, scheme_make_pair(cr, scheme_make_null()));
159  else
160    submod = scheme_make_pair(submod,
161                              scheme_make_pair(mod,
162                                               scheme_make_pair(cr, scheme_make_null())));
163  mdp = scheme_builtin_value("module-declared?");
164
165  a[0] = submod;
166  a[1] = scheme_make_true();
167  v = scheme_apply(mdp, 2, a);
168  if (!SAME_OBJ(scheme_make_false(), v)) {
169    dyreq = scheme_builtin_value("dynamic-require");
170
171    a[0] = submod;
172    a[1] = scheme_make_false();
173    (void)scheme_apply(dyreq, 2, a);
174  }
175
176  /* Old style: use `module->language-info' (after new style, for
177     compatibility): */
178
179  mli = scheme_builtin_value("module->language-info");
180
181  a[0] = mod;
182  a[1] = scheme_make_true();
183  v = scheme_apply(mli, 2, a);
184  if (SCHEME_VECTORP(v) && SCHEME_VEC_SIZE(v) == 3) {
185    dyreq = scheme_builtin_value("dynamic-require");
186
187    a[0] = SCHEME_VEC_ELS(v)[0];
188    a[1] = SCHEME_VEC_ELS(v)[1];
189    gi = scheme_apply(dyreq, 2, a);
190
191    a[0] = SCHEME_VEC_ELS(v)[2];
192    gi = scheme_apply(gi, 1, a);
193
194    a[0] = cr;
195    a[1] = scheme_make_null();
196    vs = scheme_apply(gi, 2, a);
197    a[0] = vs;
198    while (SCHEME_PAIRP(vs)) {
199      v = SCHEME_CAR(vs);
200      vs = SCHEME_CDR(vs);
201      if (SCHEME_VECTORP(v) && SCHEME_VEC_SIZE(v) == 3) {
202        /* ok */
203      } else {
204        break;
205      }
206    }
207    if (!SAME_OBJ(vs, scheme_make_null())) {
208      scheme_wrong_type("runtime-configure", "list of vectors of three values",
209                        -1, 0, a);
210    }
211
212    vs = a[0];
213    while (SCHEME_PAIRP(vs)) {
214      v = SCHEME_CAR(vs);
215      vs = SCHEME_CDR(vs);
216
217      a[0] = SCHEME_VEC_ELS(v)[0];
218      a[1] = SCHEME_VEC_ELS(v)[1];
219      a[2] = SCHEME_VEC_ELS(v)[2];
220      v = scheme_apply(dyreq, 2, a);
221
222      a[0] = a[2];
223      scheme_apply_multi(v, 1, a);
224    }
225  }
226}
227
228static int finish_cmd_line_run(FinishArgs *fa, Repl_Proc repl)
229{
230  volatile int exit_val = 0;
231  volatile int did_config = 0;
232
233  if (fa->a->init_ns) {
234    Scheme_Object *a[1], *nsreq;
235    Scheme_Thread * volatile p;
236    mz_jmp_buf * volatile save, newbuf;
237
238    nsreq = scheme_builtin_value("namespace-require");
239
240    a[0] = scheme_make_pair(scheme_intern_symbol("lib"),
241                            scheme_make_pair(scheme_make_utf8_string(fa->init_lib),
242                                             scheme_make_null()));
243
244    p = scheme_get_current_thread();
245    save = p->error_buf;
246    p->error_buf = &newbuf;
247    if (!scheme_setjmp(newbuf)) {
248      if (!did_config) {
249        configure_environment(a[0]);
250        did_config = 1;
251      }
252      scheme_apply(nsreq, 1, a);
253    } else {
254      exit_val = 1;
255    }
256    p->error_buf = save;
257  }
258
259#ifndef DONT_PARSE_COMMAND_LINE
260  {
261    volatile int i;
262    mz_jmp_buf * volatile save, newbuf;
263
264    for (i = 0; i < fa->a->num_enl; i++) {
265      if ((fa->eval_kind[i] == mzcmd_LOAD)
266          && strcmp(fa->evals_and_loads[i], "-")) {
267        if (!scheme_load(fa->evals_and_loads[i])) {
268	  exit_val = 1;
269	  break;
270	}
271      } else if ((fa->eval_kind[i] == mzcmd_EVAL)
272                 || (fa->eval_kind[i] == mzcmd_LOAD) /* stdin */
273                 || (fa->eval_kind[i] == mzcmd_REQUIRE_FILE)
274                 || (fa->eval_kind[i] == mzcmd_REQUIRE_LIB)
275                 || (fa->eval_kind[i] == mzcmd_REQUIRE_PLANET)
276                 || (fa->eval_kind[i] == mzcmd_EMBEDDED)
277                 || (fa->eval_kind[i] == mzcmd_EMBEDDED_REG)) {
278	Scheme_Thread * volatile p;
279	p = scheme_get_current_thread();
280	save = p->error_buf;
281	p->error_buf = &newbuf;
282
283        if (!scheme_setjmp(newbuf)) {
284          if (fa->eval_kind[i] == mzcmd_EVAL) {
285            scheme_eval_string_all_with_prompt(fa->evals_and_loads[i], fa->global_env, 2);
286          } else if (fa->eval_kind[i] == mzcmd_LOAD) {
287            /* eval from stdin */
288            scheme_eval_all_with_prompt(NULL, fa->global_env, 2);
289          } else if (fa->eval_kind[i] == mzcmd_EMBEDDED_REG) {
290            scheme_register_embedded_load(-1, fa->evals_and_loads[i]);
291            scheme_embedded_load(-1, fa->evals_and_loads[i], 1);
292          } else if (fa->eval_kind[i] == mzcmd_EMBEDDED) {
293            scheme_embedded_load(-1, fa->evals_and_loads[i], 0);
294          } else {
295            Scheme_Object *a[2], *nsreq, *mpi;
296            char *name;
297            nsreq = scheme_builtin_value("namespace-require");
298            if (fa->eval_kind[i] == mzcmd_REQUIRE_LIB) {
299              name = "lib";
300            } else if (fa->eval_kind[i] == mzcmd_REQUIRE_PLANET) {
301              name = "planet";
302            } else {
303              name = "file";
304            }
305            a[0] = scheme_make_pair(scheme_intern_symbol(name),
306                                    scheme_make_pair(scheme_make_utf8_string(fa->evals_and_loads[i]),
307                                                     scheme_make_null()));
308            if (!scheme_is_module_path(a[0])) {
309              scheme_signal_error("require: bad module path: %V derived from command-line argument: %s",
310                                  a[0],
311                                  fa->evals_and_loads[i]);
312            }
313            /* Use a module path index so that multiple resolutions are not unduly
314               sensitive to changes in the current directory or other configurations: */
315            mpi = scheme_make_modidx(a[0], scheme_make_false(), scheme_make_false());
316            if (!did_config)
317              configure_environment(mpi);
318            /* Run the module: */
319            a[0] = mpi;
320            scheme_apply(nsreq, 1, a);
321            /* If there's a `main' submodule, run it: */
322            a[0] = scheme_make_modidx(scheme_make_pair(scheme_intern_symbol("submod"),
323                                                       scheme_make_pair(scheme_make_utf8_string("."),
324                                                                        scheme_make_pair(scheme_intern_symbol("main"),
325                                                                                         scheme_make_null()))),
326                                      mpi,
327                                      scheme_make_false());
328            if (scheme_module_is_declared(a[0], 1)) {
329              a[1] = scheme_make_false();
330              scheme_apply(scheme_builtin_value("dynamic-require"), 2, a);
331            }
332          }
333        } else {
334          scheme_clear_escape();
335	  exit_val = 1;
336	  p->error_buf = save;
337	  break;
338	}
339	p->error_buf = save;
340      } else if (fa->eval_kind[i] == mzcmd_MAIN) {
341	Scheme_Thread * volatile p;
342	p = scheme_get_current_thread();
343	save = p->error_buf;
344	p->error_buf = &newbuf;
345	if (!scheme_setjmp(newbuf)) {
346	  Scheme_Object *e, *a[2], *ndi, *idb, *b, *cp;
347
348          ndi = scheme_builtin_value("namespace-datum-introduce");
349          e = scheme_intern_symbol("main");
350          a[0] = e;
351          e = scheme_apply(ndi, 1, a);
352
353          /* Check that `main' is imported and/or defined: */
354          idb = scheme_builtin_value("identifier-binding");
355          a[0] = e;
356          b = scheme_apply(idb, 1, a);
357          if (b == scheme_make_false()) {
358            if (!scheme_lookup_global(scheme_intern_symbol("main"), fa->global_env)) {
359              scheme_signal_error("main: not defined or required into the top-level environment");
360            }
361          }
362
363          e = scheme_make_pair(e, scheme_vector_to_list(fa->main_args));
364          e = scheme_datum_to_kernel_stx(e);
365
366	  e = scheme_eval_multi_with_prompt(e, fa->global_env);
367
368          if (SAME_OBJ(e, SCHEME_MULTIPLE_VALUES)) {
369            Scheme_Object **mv;
370            int cnt;
371            mv = p->ku.multiple.array;
372            cnt = p->ku.multiple.count;
373            scheme_detach_multple_array(mv);
374            e = scheme_make_null();
375            while (cnt--) {
376              e = scheme_make_pair(mv[cnt], e);
377            }
378          } else {
379            e = scheme_make_pair(e, scheme_make_null());
380          }
381
382          cp = scheme_get_param(scheme_current_config(), MZCONFIG_PRINT_HANDLER);
383
384          while (SCHEME_PAIRP(e)) {
385            a[0] = SCHEME_CAR(e);
386            scheme_apply_multi(cp, 1, a);
387            e = SCHEME_CDR(e);
388          }
389	} else {
390          scheme_clear_escape();
391	  exit_val = 1;
392	  p->error_buf = save;
393	  break;
394	}
395	p->error_buf = save;
396      }
397      did_config = 1;
398    }
399  }
400#endif /* DONT_PARSE_COMMAND_LINE */
401
402#ifdef STANDALONE_WITH_EMBEDDED_EXTENSION
403  {
404    Scheme_Object *f, *a[1];
405    mz_jmp_buf * volatile save, newbuf;
406    Scheme_Thread * volatile p;
407    p = scheme_get_current_thread();
408    save = p->error_buf;
409    p->error_buf = &newbuf;
410    if (!scheme_setjmp(newbuf)) {
411      f = scheme_initialize(fa->global_env);
412      a[0] = scheme_make_true();
413      f = _scheme_apply_multi(f, 1, a);
414      if (SAME_OBJ(f, SCHEME_MULTIPLE_VALUES)
415	  && (scheme_multiple_count == 2)) {
416	f = scheme_multiple_array[0];
417	scheme_apply_multi_with_prompt(f, 0, NULL);
418      }
419    } else {
420      scheme_clear_escape();
421      exit_val = 1;
422    }
423    p->error_buf = save;
424  }
425#endif
426
427#ifndef DONT_LOAD_INIT_FILE
428  if (fa->a->use_repl && !fa->a->no_init_file) {
429    Scheme_Object *a[2];
430    a[0] = get_init_filename(fa->global_env,
431                             INIT_FILENAME_CONF_SYM,
432                             DEFAULT_INIT_MODULE,
433                             USER_INIT_MODULE);
434    if (a[0]) {
435        mz_jmp_buf * volatile save, newbuf;
436        Scheme_Thread * volatile p;
437        p = scheme_get_current_thread();
438        save = p->error_buf;
439        p->error_buf = &newbuf;
440        if (!scheme_setjmp(newbuf)) {
441          a[1] = scheme_make_integer(0);
442          scheme_dynamic_require(2, a);
443        } else {
444          scheme_clear_escape();
445          exit_val = 1;
446        }
447        p->error_buf = save;
448    }
449  }
450#endif /* DONT_LOAD_INIT_FILE */
451
452#ifndef DONT_RUN_REP
453  if (fa->a->use_repl) {
454    /* enter read-eval-print loop */
455    mz_jmp_buf * volatile save, newbuf;
456    Scheme_Thread * volatile p;
457    p = scheme_get_current_thread();
458    save = p->error_buf;
459    p->error_buf = &newbuf;
460    if (!scheme_setjmp(newbuf)) {
461      repl(fa->global_env, fa);
462      exit_val = 0;
463    } else {
464      scheme_clear_escape();
465      exit_val = 1;
466#ifndef NO_YIELD_BEFORE_EXIT
467      fa->a->add_yield = 0;
468#endif
469    }
470    p->error_buf = save;
471  }
472#endif /* DONT_RUN_REP */
473
474#ifndef NO_YIELD_BEFORE_EXIT
475  if (fa->a->add_yield) {
476    mz_jmp_buf * volatile save, newbuf;
477    Scheme_Thread * volatile p;
478    Scheme_Object *yh, *yha[1];
479    p = scheme_get_current_thread();
480    save = p->error_buf;
481    p->error_buf = &newbuf;
482    if (!scheme_setjmp(newbuf)) {
483      yh = scheme_get_param(scheme_current_config(), MZCONFIG_EXE_YIELD_HANDLER);
484      yha[0] = scheme_make_integer(exit_val);
485      scheme_apply(yh, 1, yha);
486    } else {
487      scheme_clear_escape();
488    }
489    p->error_buf = save;
490  }
491#endif
492
493  if (scheme_flush_managed(NULL, 1))
494    exit_val = 1;
495
496  return exit_val;
497}
498
499static Scheme_Object *reverse_path_list(Scheme_Object *l, int rel_to_cwd)
500{
501  Scheme_Object *r, *path;
502
503  r = scheme_make_null();
504  while (SCHEME_PAIRP(l)) {
505    path = SCHEME_CAR(l);
506    if (rel_to_cwd)
507      path = scheme_path_to_complete_path(path, NULL);
508    r = scheme_make_pair(path, r);
509    l = SCHEME_CDR(l);
510  }
511
512  return r;
513}
514
515#include <ctype.h>
516
517static Scheme_Object *get_log_level(char *prog, char *real_switch, const char *envvar, const char *what, GC_CAN_IGNORE char *str)
518{
519  int k, len, default_lvl = -1;
520  Scheme_Object *l, *last = NULL;
521  GC_CAN_IGNORE char *s, *orig_str = str;
522
523  l =  scheme_make_null();
524
525  while (1) {
526    while (*str && isspace(*((unsigned char *)str))) {
527      str++;
528    }
529
530    if (!*str) {
531      if (default_lvl == -1) default_lvl = 0;
532      if (last)
533        SCHEME_CDR(last) = scheme_make_integer(default_lvl);
534      else
535        l = scheme_make_integer(default_lvl);
536      return l;
537    }
538
539    if (!strncmp(str, "none", 4)) {
540      k = 0;
541      len = 4;
542    } else if (!strncmp(str, "fatal", 5)) {
543      k = SCHEME_LOG_FATAL;
544      len = 5;
545    } else if (!strncmp(str, "error", 5)) {
546      k = SCHEME_LOG_ERROR;
547      len = 5;
548    } else if (!strncmp(str, "warning", 7)) {
549      k = SCHEME_LOG_WARNING;
550      len = 7;
551    } else if (!strncmp(str, "info", 4)) {
552      k = SCHEME_LOG_INFO;
553      len = 4;
554    } else if (!strncmp(str, "debug", 5)) {
555      k  = SCHEME_LOG_DEBUG;
556      len = 5;
557    } else {
558      k = -1;
559      len = 0;
560    }
561
562    str += len;
563
564    if (k != -1) {
565      if (*str == '@') {
566        str++;
567        for (s = str; *s && !isspace(*((unsigned char *)s)); s++) {
568        }
569        l = scheme_make_pair(scheme_make_sized_byte_string(str, s - str, 1), l);
570        if (!last) last = l;
571        l = scheme_make_pair(scheme_make_integer(k), l);
572        str = s;
573      } else if (isspace(*((unsigned char *)str)) || !*str) {
574        if (default_lvl == -1)
575          default_lvl = k;
576        else
577          k = -1;
578      } else
579        k = -1;
580      if (*str) str++;
581    }
582
583    if (k == -1) {
584      PRINTF("%s: %s <levels> %s%s%s must be one of the following\n"
585             " <level>s:\n"
586             "   none fatal error warning info debug\n"
587             " or up to one such <level> in whitespace-separated sequence of\n"
588             "   <level>@<name>\n"
589             " given: %s\n",
590             prog, what,
591             real_switch ? "after " : "in ",
592             real_switch ? real_switch : envvar,
593             real_switch ? " switch" : " environment variable",
594             orig_str);
595      return NULL;
596    }
597  }
598}
599
600static Scheme_Object *get_arg_log_level(char *prog, char *real_switch, const char *what, int argc, char **argv)
601{
602  if (argc < 2) {
603    PRINTF("%s: missing %s level after %s switch\n",
604           prog, what, real_switch);
605    return NULL;
606  }
607
608  return get_log_level(prog, real_switch, NULL, what, argv[1]);
609}
610
611static Scheme_Object *adjust_collects_path(Scheme_Object *collects_path, int *_skip_coll_dirs)
612{
613  /* Setup path for "collects" collection directory: */
614  if (!collects_path) {
615    GC_CAN_IGNORE char *coldir;
616    coldir = extract_coldir();
617    if (!coldir[0])
618      collects_path = scheme_make_false();
619    else
620      collects_path = scheme_make_path(coldir);
621  } else if (!SAME_OBJ(collects_path, scheme_make_false()))
622    collects_path = scheme_path_to_complete_path(collects_path, NULL);
623
624  if (SAME_OBJ(collects_path, scheme_make_false())) {
625    /* empty list of directories => don't set collection dirs
626       and don't use collection links files */
627    if (_skip_coll_dirs) {
628      *_skip_coll_dirs = 1;
629      scheme_set_ignore_link_paths(1);
630    }
631    collects_path = scheme_make_path(".");
632  }
633
634  return collects_path;
635}
636
637static Scheme_Object *adjust_config_path(Scheme_Object *config_path)
638{
639  if (!config_path) {
640    char *s;
641    s = getenv("PLTCONFIGDIR");
642    if (s) {
643      s = scheme_expand_filename(s, -1, NULL, NULL, 0);
644      if (s) config_path = scheme_make_path(s);
645    }
646  }
647
648  if (!config_path)
649    config_path = scheme_make_path(extract_configdir());
650  else
651    config_path = scheme_path_to_complete_path(config_path, NULL);
652
653  return config_path;
654}
655
656#ifdef USE_OSKIT_CONSOLE
657/* Hack to disable normal input mode: */
658int osk_not_console = 0;
659#endif
660
661#ifndef MZ_XFORM
662# ifndef GC_CAN_IGNORE
663#  define GC_CAN_IGNORE /**/
664# endif
665#endif
666
667static Scheme_Object *create_cmdline_args_vector(int argc, char *args[])
668{
669  int i;
670  Scheme_Object *v;
671  v = scheme_make_vector(argc, NULL);
672  for (i = 0; i < argc; i++) {
673    Scheme_Object *so;
674    so = scheme_make_locale_string(args[i]);
675    SCHEME_SET_CHAR_STRING_IMMUTABLE(so);
676    SCHEME_VEC_ELS(v)[i] = so;
677  }
678  if (argc)
679    SCHEME_SET_VECTOR_IMMUTABLE(v);
680  return v;
681}
682
683
684static int run_from_cmd_line(int argc, char *_argv[],
685			     Scheme_Env *(*mk_basic_env)(void),
686			     int (*cont_run)(FinishArgs *f))
687{
688  GC_CAN_IGNORE char **argv = _argv;
689  Scheme_Env *global_env;
690  char *prog, *sprog = NULL;
691  Scheme_Object *sch_argv;
692  int skip_coll_dirs = 0;
693  Scheme_Object *collects_path = NULL, *collects_extra = NULL, *addon_dir = NULL;
694  Scheme_Object *config_path = NULL;
695  Scheme_Object *host_collects_path = NULL, *host_config_path = NULL;
696  char *compiled_paths = NULL;
697  Scheme_Object *collects_paths_l, *collects_paths_r;
698#ifndef DONT_PARSE_COMMAND_LINE
699  char **evals_and_loads, *real_switch = NULL, specific_switch[2];
700  int *eval_kind, num_enl;
701  int no_more_switches = 0;
702  int show_vers = 0;
703  char *embedding_file;
704#endif
705#if !defined(DONT_RUN_REP) || !defined(DONT_PARSE_COMMAND_LINE)
706  int use_repl = 0;
707  int script_mode = 0;
708#endif
709#if !defined(DONT_LOAD_INIT_FILE) || !defined(DONT_PARSE_COMMAND_LINE)
710  int no_init_file = 0;
711#endif
712#ifndef NO_YIELD_BEFORE_EXIT
713  int add_yield = 1;
714#endif
715#ifdef CMDLINE_STDIO_FLAG
716  int alternate_rep = 0;
717  int no_front = 0;
718  char *wm_class = NULL;
719#endif
720  char *init_lib = INITIAL_NAMESPACE_MODULE;
721  int was_config_flag = 0, saw_nc_flag = 0;
722  int no_compiled = 0;
723  int init_ns = 0, no_init_ns = 0;
724  int cross_compile = 0;
725  Scheme_Object *syslog_level = NULL, *stderr_level = NULL, *stdout_level = NULL;
726  FinishArgs *fa;
727  FinishArgsAtoms *fa_a;
728  self_exe_t self_exe;
729
730  scheme_set_default_locale();
731
732  prog = argv[0];
733  argv++;
734  --argc;
735
736#ifdef NEED_CONSOLE_PRINTF
737  console_printf = scheme_get_console_printf();
738#endif
739
740  self_exe = get_self_path(prog);
741
742  extract_built_in_arguments(self_exe, &prog, &sprog, &argc, &argv);
743
744#ifndef DONT_PARSE_COMMAND_LINE
745  evals_and_loads = (char **)malloc(sizeof(char *) * argc);
746  eval_kind = (int *)malloc(sizeof(int) * argc);
747  num_enl = 0;
748
749  while (!no_more_switches
750         && argc
751         && argv[0][0] == '-'
752         && argv[0][1]
753         && !is_number_arg(argv[0] + 1)) {
754    real_switch = argv[0];
755
756    if (!strcmp("--help", argv[0]))
757      argv[0] = "-h";
758    else if (!strcmp("--eval", argv[0]))
759      argv[0] = "-e";
760    else if (!strcmp("--load", argv[0]))
761      argv[0] = "-f";
762    else if (!strcmp("--require", argv[0]))
763      argv[0] = "-t";
764    else if (!strcmp("--lib", argv[0]))
765      argv[0] = "-l";
766    else if (!strcmp("--script", argv[0]))
767      argv[0] = "-r";
768    else if (!strcmp("--require-script", argv[0]))
769      argv[0] = "-u";
770    else if (!strcmp("--main", argv[0]))
771      argv[0] = "-m";
772    else if (!strcmp("--name", argv[0]))
773      argv[0] = "-N";
774    else if (!strcmp("--exec", argv[0]))
775      argv[0] = "-E";
776    else if (!strcmp("--no-compiled", argv[0]))
777      argv[0] = "-c";
778    else if (!strcmp("--no-lib", argv[0]))
779      argv[0] = "-n";
780    else if (!strcmp("--no-user-path", argv[0]))
781      argv[0] = "-U";
782    else if (!strcmp("--version", argv[0]))
783      argv[0] = "-v";
784    else if (!strcmp("--no-init-file", argv[0]))
785      argv[0] = "-q";
786    else if (!strcmp("--no-jit", argv[0]))
787      argv[0] = "-j";
788    else if (!strcmp("--compile-any", argv[0]))
789      argv[0] = "-M";
790    else if (!strcmp("--no-delay", argv[0]))
791      argv[0] = "-d";
792    else if (!strcmp("--repl", argv[0]))
793      argv[0] = "-i";
794    else if (!strcmp("--binary", argv[0]))
795      argv[0] = "-b";
796    else if (!strcmp("--warn", argv[0]))
797      argv[0] = "-W";
798    else if (!strcmp("--syslog", argv[0]))
799      argv[0] = "-L";
800    else if (!strcmp("--collects", argv[0]))
801      argv[0] = "-X";
802    else if (!strcmp("--search", argv[0]))
803      argv[0] = "-S";
804    else if (!strcmp("--compiled", argv[0]))
805      argv[0] = "-R";
806    else if (!strcmp("--addon", argv[0]))
807      argv[0] = "-A";
808    else if (!strcmp("--config", argv[0]))
809      argv[0] = "-G";
810    else if (!strcmp("--cross", argv[0]))
811      argv[0] = "-C";
812# ifdef CMDLINE_STDIO_FLAG
813    else if (!strcmp("--stdio", argv[0]))
814      argv[0] = "-z";
815    else if (!strcmp("--back", argv[0]))
816      argv[0] = "-K";
817    else if (!strcmp("--wm-class", argv[0]))
818      argv[0] = "-J";
819# endif
820# ifndef NO_YIELD_BEFORE_EXIT
821    else if (!strcmp("--no-yield", argv[0]))
822      argv[0] = "-V";
823# endif
824
825    if (!argv[0][1] || (argv[0][1] == '-' && argv[0][2])) {
826      specific_switch[0] = 0;
827      goto bad_switch;
828    } else {
829      GC_CAN_IGNORE char *str;
830      char *se;
831      for (str = argv[0] + 1; *str; str++) {
832	switch (*str) {
833	case 'h':
834	  goto show_help;
835	  break;
836	case 'e':
837	  if (argc < 2) {
838	    PRINTF("%s: missing expression after %s switch\n",
839		   prog, real_switch);
840	    goto show_need_help;
841	  }
842	  argv++;
843	  --argc;
844	  evals_and_loads[num_enl] = argv[0];
845	  eval_kind[num_enl++] = mzcmd_EVAL;
846          init_ns = 1;
847	  break;
848	case 'X':
849	  if (argc < 2) {
850	    PRINTF("%s: missing path after %s switch\n",
851		   prog, real_switch);
852	    goto show_need_help;
853	  }
854	  argv++;
855	  --argc;
856          if (!*(argv[0])) {
857            /* #f => no collects path */
858            collects_path = scheme_make_false();
859          } else
860            collects_path = check_make_path(prog, real_switch, argv[0]);
861          was_config_flag = 1;
862	  break;
863	case 'G':
864	  if (argc < 2) {
865	    PRINTF("%s: missing path after %s switch\n",
866		   prog, real_switch);
867	    goto show_need_help;
868	  }
869	  argv++;
870	  --argc;
871          config_path = check_make_path(prog, real_switch, argv[0]);
872          was_config_flag = 1;
873	  break;
874        case 'R':
875          if (argc < 2) {
876	    PRINTF("%s: missing path after %s switch\n",
877		   prog, real_switch);
878	    goto show_need_help;
879	  }
880	  argv++;
881	  --argc;
882	  compiled_paths = argv[0];
883          was_config_flag = 1;
884	  break;
885	case 'A':
886	  if (argc < 2) {
887	    PRINTF("%s: missing path after %s switch\n",
888		   prog, real_switch);
889	    goto show_need_help;
890	  }
891	  argv++;
892	  --argc;
893	  addon_dir = check_make_path(prog, real_switch, argv[0]);
894          was_config_flag = 1;
895            break;
896        case 'C':
897          if (!cross_compile) {
898            cross_compile = 1;
899            scheme_set_cross_compile_mode(1);
900            was_config_flag = 1;
901            host_config_path = config_path;
902            host_collects_path = collects_path;
903          }
904	  break;
905	case 'U':
906	  scheme_set_ignore_user_paths(1);
907          was_config_flag = 1;
908	  break;
909        case 'I':
910          if (argc < 2) {
911	    PRINTF("%s: missing path after %s switch\n",
912		   prog, real_switch);
913	    goto show_need_help;
914	  }
915	  argv++;
916	  --argc;
917	  init_lib = argv[0];
918          was_config_flag = 1;
919          break;
920	case 'S':
921	  if (argc < 2) {
922	    PRINTF("%s: missing path after %s switch\n",
923		   prog, real_switch);
924	    goto show_need_help;
925	  }
926	  argv++;
927	  --argc;
928	  if (!collects_extra)
929	    collects_extra = scheme_make_null();
930          collects_extra = scheme_make_pair(check_make_path(prog, real_switch, argv[0]), collects_extra);
931          was_config_flag = 1;
932	  break;
933        case 'c':
934          no_compiled = 1;
935          was_config_flag = 1;
936          break;
937	case 'm':
938          evals_and_loads[num_enl] = "";
939          eval_kind[num_enl++] = mzcmd_MAIN;
940          init_ns = 1;
941	  break;
942	case 'r':
943	  script_mode = 1;
944	  no_more_switches = 1;
945          if (argc > 1)
946            sprog = argv[1];
947	case 'f':
948	  if (argc < 2) {
949	    PRINTF("%s: missing file name after %s switch\n",
950		   prog, real_switch);
951	    goto show_need_help;
952	  }
953	  argv++;
954	  --argc;
955	  evals_and_loads[num_enl] = argv[0];
956	  eval_kind[num_enl++] = mzcmd_LOAD;
957          init_ns = 1;
958	  break;
959	case 'u':
960	  script_mode = 1;
961	  no_more_switches = 1;
962          if (argc > 1)
963            sprog = argv[1];
964	case 't':
965	  if (argc < 2) {
966	    PRINTF("%s: missing file name after %s switch\n",
967		   prog, real_switch);
968	    goto show_need_help;
969	  }
970	  argv++;
971	  --argc;
972	  evals_and_loads[num_enl] = argv[0];
973	  eval_kind[num_enl++] = mzcmd_REQUIRE_FILE;
974          if (!init_ns)
975            no_init_ns = 1;
976	  break;
977	case 'l':
978	  if (argc < 2) {
979	    PRINTF("%s: missing library name after %s switch\n",
980		   prog, real_switch);
981	    goto show_need_help;
982	  }
983	  argv++;
984	  --argc;
985	  evals_and_loads[num_enl] = argv[0];
986	  eval_kind[num_enl++] = mzcmd_REQUIRE_LIB;
987          if (!init_ns)
988            no_init_ns = 1;
989	  break;
990	case 'p':
991	  if (argc < 2) {
992	    PRINTF("%s: missing package name after %s switch\n",
993		   prog, real_switch);
994	    goto show_need_help;
995	  }
996	  argv++;
997	  --argc;
998	  evals_and_loads[num_enl] = argv[0];
999	  eval_kind[num_enl++] = mzcmd_REQUIRE_PLANET;
1000          if (!init_ns)
1001            no_init_ns = 1;
1002	  break;
1003        case 'k':
1004        case 'Y':
1005          if (*str == 'Y') {
1006            if (argc < 2) {
1007              PRINTF("%s: missing file name after %s switch\n",
1008                     prog, real_switch);
1009              goto show_need_help;
1010            }
1011            argv++;
1012            --argc;
1013            embedding_file = argv[0];
1014          } else
1015            embedding_file = NULL;
1016	  if (argc < 4) {
1017	    PRINTF("%s: missing %s after %s switch\n",
1018		   prog,
1019		   (argc < 2) ? "starting and ending offsets" : "second ending offset",
1020		   real_switch);
1021	    goto show_need_help;
1022	  }
1023	  argv++;
1024	  --argc;
1025	  se = make_embedded_load(self_exe, embedding_file, argv[0], argv[1]);
1026	  evals_and_loads[num_enl] = se;
1027	  argv++;
1028	  --argc;
1029	  eval_kind[num_enl++] = mzcmd_EMBEDDED_REG;
1030	  se = make_embedded_load(self_exe, embedding_file, argv[0], argv[1]);
1031	  evals_and_loads[num_enl] = se;
1032	  argv++;
1033	  --argc;
1034	  eval_kind[num_enl++] = mzcmd_EMBEDDED;
1035	  break;
1036	case 'N':
1037	case 'E':
1038	  if (argc < 2) {
1039	    PRINTF("%s: missing name after %s switch\n",
1040		   prog,
1041		   real_switch);
1042	    goto show_need_help;
1043	  }
1044	  argv++;
1045	  --argc;
1046          if (!*(argv[0])) {
1047            PRINTF("%s: empty path after %s switch\n",
1048		   prog,
1049		   real_switch);
1050	    goto show_need_help;
1051          }
1052          if (*str == 'N')
1053            sprog = argv[0];
1054          else
1055            prog = argv[0];
1056          was_config_flag = 1;
1057	  break;
1058	case 'q':
1059	  no_init_file = 1;
1060          was_config_flag = 1;
1061	  break;
1062        case 'n':
1063          no_init_ns = 1;
1064          break;
1065	case 'v':
1066	  show_vers = 1;
1067	  break;
1068#ifndef NO_YIELD_BEFORE_EXIT
1069	case 'V':
1070	  show_vers = 1;
1071	  add_yield = 0;
1072	  break;
1073#endif
1074	case 'i':
1075	  use_repl = 1;
1076          init_ns = 1;
1077	  break;
1078	case '-':
1079	  no_more_switches = 1;
1080          was_config_flag = 1;
1081	  break;
1082	case 'j':
1083	  scheme_set_startup_use_jit(0);
1084          was_config_flag = 1;
1085	  break;
1086	case 'M':
1087	  scheme_set_startup_compile_machine_independent(1);
1088          was_config_flag = 1;
1089	  break;
1090	case 'd':
1091	  scheme_set_startup_load_on_demand(0);
1092          was_config_flag = 1;
1093	  break;
1094	case 'b':
1095	  scheme_set_binary_mode_stdio(1);
1096          was_config_flag = 1;
1097	  break;
1098#ifdef CMDLINE_STDIO_FLAG
1099       	case 'z':
1100	  alternate_rep = 1;
1101	  no_front = 1;
1102          was_config_flag = 1;
1103	  break;
1104	case 'K':
1105	  no_front = 1;
1106          was_config_flag = 1;
1107	  break;
1108        case 'J':
1109          if (argc < 2) {
1110	    PRINTF("%s: missing name after %s switch\n",
1111		   prog,
1112		   real_switch);
1113	    goto show_need_help;
1114	  }
1115	  argv++;
1116	  --argc;
1117          wm_class = argv[0];
1118          was_config_flag = 1;
1119          break;
1120#endif
1121#ifdef USE_OSKIT_CONSOLE
1122	case 'S':
1123	  osk_not_console = 1;
1124	  break;
1125#endif
1126        case 'W':
1127          stderr_level = get_arg_log_level(prog, real_switch, "stderr", argc, argv);
1128          if (!stderr_level)
1129            goto show_need_help;
1130          --argc;
1131          argv++;
1132          was_config_flag = 1;
1133          break;
1134        case 'O':
1135          stdout_level = get_arg_log_level(prog, real_switch, "stdout", argc, argv);
1136          if (!stdout_level)
1137            goto show_need_help;
1138          --argc;
1139          argv++;
1140          was_config_flag = 1;
1141          break;
1142	case 'L':
1143          syslog_level = get_arg_log_level(prog, real_switch, "syslog", argc, argv);
1144          if (!syslog_level)
1145            goto show_need_help;
1146          --argc;
1147          argv++;
1148          was_config_flag = 1;
1149          break;
1150        case 'Z':
1151          if (argc < 2) {
1152	    PRINTF("%s: missing argument to ignore after %s switch\n",
1153		   prog,
1154		   real_switch);
1155	    goto show_need_help;
1156	  }
1157          --argc;
1158          argv++;
1159          was_config_flag = 1;
1160          break;
1161	default:
1162          specific_switch[0] = *str;
1163          specific_switch[1] = 0;
1164	  goto bad_switch;
1165	}
1166
1167        if (was_config_flag)
1168          was_config_flag = 0;
1169        else
1170          saw_nc_flag = 1;
1171      }
1172      argv++;
1173      --argc;
1174    }
1175  }
1176
1177  if (!saw_nc_flag) {
1178    if (!argc) {
1179      /* No args => repl */
1180      use_repl = 1;
1181      init_ns = 1;
1182    } else {
1183      /* No switches => -u mode */
1184      script_mode = 1;
1185      sprog = argv[0];
1186      evals_and_loads[num_enl] = argv[0];
1187      eval_kind[num_enl++] = mzcmd_REQUIRE_FILE;
1188      argv++;
1189      --argc;
1190    }
1191  }
1192
1193  if (use_repl) {
1194    show_vers = 1;
1195  }
1196
1197  if (no_init_ns)
1198    init_ns = 0;
1199
1200  if (show_vers) {
1201#ifndef RACKET_CMD_LINE
1202    if (!use_repl
1203#ifdef CMDLINE_STDIO_FLAG
1204	|| alternate_rep
1205#endif
1206	)
1207#endif
1208      PRINTF("%s", BANNER);
1209
1210   CMDLINE_FFLUSH(stdout);
1211  }
1212#endif /* DONT_PARSE_COMMAND_LINE */
1213
1214  if (!syslog_level) {
1215    char *s;
1216    s = getenv("PLTSYSLOG");
1217    if (s) {
1218      syslog_level = get_log_level(prog, NULL, "PLTSYSLOG", "syslog", s);
1219    }
1220  }
1221  if (!stderr_level) {
1222    char *s;
1223    s = getenv("PLTSTDERR");
1224    if (s) {
1225      stderr_level = get_log_level(prog, NULL, "PLTSTDERR", "stderr", s);
1226    }
1227  }
1228  if (!stdout_level) {
1229    char *s;
1230    s = getenv("PLTSTDOUT");
1231    if (s) {
1232      stdout_level = get_log_level(prog, NULL, "PLTSTDOUT", "stdout", s);
1233    }
1234  }
1235  if (getenv("PLTDISABLEGC")) {
1236    scheme_enable_garbage_collection(0);
1237  }
1238  {
1239    char *s;
1240    s = getenv("PLT_INCREMENTAL_GC");
1241    if (s) {
1242      if ((s[0] == '0') || (s[0] == 'n') || (s[0] == 'N'))
1243        scheme_incremental_garbage_collection(0);
1244      else if ((s[0] == '1') || (s[0] == 'y') || (s[0] == 'Y'))
1245        scheme_incremental_garbage_collection(1);
1246      else {
1247        PRINTF("%s: unrecognized value for PLT_INCREMENTAL_GC;\n"
1248                " a value that starts \"1\", \"y\", or \"Y\" permanently enables incremental mode,\n"
1249                " and a value that starts \"0\", \"n\", or \"N\" disables incremental mode,\n"
1250                " and the default enables incremental mode as requested via `collect-garbage'\n"
1251                "  unrecognized value: %s\n",
1252                prog, s);
1253      }
1254    }
1255  }
1256  {
1257    char *s;
1258    s = getenv("PLT_COMPILED_FILE_CHECK");
1259    if (s) {
1260      if (!strcmp(s, "modify-seconds"))
1261        scheme_set_compiled_file_check(SCHEME_COMPILED_FILE_CHECK_MODIFY_SECONDS);
1262      else if (!strcmp(s, "exists"))
1263        scheme_set_compiled_file_check(SCHEME_COMPILED_FILE_CHECK_EXISTS);
1264      else {
1265        PRINTF("%s: unrecognized value for PLT_COMPILED_FILE_CHECK;\n"
1266                " recognized values are \"modify-seconds\" and \"exists\"\n"
1267                "  unrecognized value: %s\n",
1268                prog, s);
1269      }
1270    }
1271  }
1272
1273  if (getenv("PLT_COMPILE_ANY")) {
1274    scheme_set_startup_compile_machine_independent(1);
1275  }
1276
1277  scheme_set_logging2_spec(syslog_level, stderr_level, stdout_level);
1278
1279  collects_path = adjust_collects_path(collects_path, &skip_coll_dirs);
1280  scheme_set_collects_path(collects_path);
1281
1282  if (cross_compile) {
1283    host_collects_path = adjust_collects_path(host_collects_path, NULL);
1284    scheme_set_host_collects_path(host_collects_path);
1285  }
1286
1287  config_path = adjust_config_path(config_path);
1288  scheme_set_config_path(config_path);
1289
1290  if (cross_compile) {
1291    host_config_path = adjust_config_path(host_config_path);
1292    scheme_set_host_config_path(host_config_path);
1293  }
1294
1295  /* Make list of additional collection paths: */
1296  if (collects_extra)
1297    collects_paths_r = reverse_path_list(collects_extra, 1);
1298  else
1299    collects_paths_r = scheme_make_null();
1300
1301  {
1302    int len, offset;
1303    GC_CAN_IGNORE char *coldir;
1304    collects_paths_l = scheme_make_null();
1305    coldir = extract_coldir();
1306    offset = 0;
1307    while (1) {
1308      len = strlen(coldir XFORM_OK_PLUS offset);
1309      offset += len + 1;
1310      if (!coldir[offset])
1311        break;
1312      collects_paths_l = scheme_make_pair(scheme_make_path(coldir XFORM_OK_PLUS offset),
1313                                          collects_paths_l);
1314    }
1315    collects_paths_l = reverse_path_list(collects_paths_l, 0);
1316  }
1317
1318  sch_argv = create_cmdline_args_vector(argc, argv);
1319  scheme_set_command_line_arguments(sch_argv);
1320
1321  scheme_set_exec_cmd(prog);
1322  if (!sprog)
1323    sprog = prog;
1324
1325  (void)scheme_set_run_cmd(sprog);
1326#ifdef CAN_SET_OS_PROCESS_NAME
1327  set_os_process_name(sprog);
1328#endif
1329
1330  if (no_compiled)
1331    scheme_set_compiled_file_paths(scheme_make_null());
1332  else {
1333    const char *s;
1334    s = getenv("PLT_ZO_PATH");
1335    if (s)
1336      scheme_set_compiled_file_paths(scheme_make_pair(scheme_make_path(s),
1337                                                      scheme_make_null()));
1338#ifdef COMPILED_PATH_AS_BC
1339    else {
1340# ifdef DOS_FILE_SYSTEM
1341      s = "compiled\\bc";
1342# else
1343      s = "compiled/bc";
1344# endif
1345      scheme_set_compiled_file_paths(scheme_make_pair(scheme_make_path(s),
1346                                                      scheme_make_null()));
1347    }
1348#endif
1349  }
1350
1351  /* Setup compiled-file search path: */
1352  if (!compiled_paths) {
1353    compiled_paths = getenv("PLTCOMPILEDROOTS");
1354  }
1355
1356  /* Setup path for "addon" directory: */
1357  if (!addon_dir) {
1358    char *s;
1359    s = getenv("PLTADDONDIR");
1360    if (s) {
1361      s = scheme_expand_filename(s, -1, NULL, NULL, 0);
1362      if (s) addon_dir = scheme_make_path(s);
1363    }
1364  }
1365  if (addon_dir) {
1366    addon_dir = scheme_path_to_complete_path(addon_dir, NULL);
1367    scheme_set_addon_dir(addon_dir);
1368  }
1369
1370  /* Creates the main kernel environment */
1371  global_env = mk_basic_env();
1372
1373  if (!skip_coll_dirs)
1374    scheme_init_collection_paths_post(global_env, collects_paths_l, collects_paths_r);
1375  scheme_init_compiled_roots(global_env, compiled_paths);
1376
1377  scheme_seal_parameters();
1378
1379  fa_a = (FinishArgsAtoms *)scheme_malloc_atomic(sizeof(FinishArgsAtoms));
1380  fa = (FinishArgs *)scheme_malloc(sizeof(FinishArgs));
1381  fa->a = fa_a;
1382  fa->a->init_ns = init_ns;
1383#ifndef DONT_PARSE_COMMAND_LINE
1384  fa->evals_and_loads = evals_and_loads;
1385  fa->eval_kind = eval_kind;
1386  fa->a->num_enl = num_enl;
1387  fa->main_args = sch_argv;
1388#endif
1389#ifndef DONT_LOAD_INIT_FILE
1390  fa->a->no_init_file = no_init_file;
1391#endif
1392#ifndef DONT_RUN_REP
1393  fa->a->use_repl = use_repl;
1394  fa->a->script_mode = script_mode;
1395#endif
1396#ifndef NO_YIELD_BEFORE_EXIT
1397  fa->a->add_yield = add_yield;
1398#endif
1399#ifdef CMDLINE_STDIO_FLAG
1400  fa->a->alternate_rep = alternate_rep;
1401  fa->a->no_front = no_front;
1402  if (no_front)
1403    scheme_register_process_global("Racket-GUI-no-front", (void *)0x1);
1404  if (wm_class)
1405    scheme_register_process_global("Racket-GUI-wm-class", (void *)wm_class);
1406#endif
1407  fa->init_lib = init_lib;
1408  fa->global_env = global_env;
1409
1410  scheme_set_can_break(1);
1411
1412  return cont_run(fa);
1413
1414#ifndef DONT_PARSE_COMMAND_LINE
1415 show_help:
1416  prog = (char *) ("%s"
1417         PROGRAM_LC " [<option> ...] <argument> ...\n"
1418# ifndef RACKET_CMD_LINE
1419#  ifdef wx_x
1420  "\n"
1421  "X configuration options (must precede all other options):\n\n"
1422  "  -display <display>, -geometry <geometry>, -fn <font>,\n"
1423  "  -font <font>, -bg <color>, -background <color>, -fg <color>,\n"
1424  "  -foreground <color>, -iconic, -name <name>, -rv, -reverse,\n"
1425  "  +rv, -selectionTimeout <timeout>, -synchronous, -title <title>,\n"
1426  "  -xnllanguage <language>, -xrm <file>\n"
1427#  endif
1428# endif
1429  "\n"
1430  "File and expression options:\n\n"
1431  "  -e <exprs>, --eval <exprs>\n"
1432  "     Evaluate <exprs>, print results\n"
1433  "  -f <file>, --load <file>\n"
1434  "     Like -e '(load \"<file>\")' without printing\n"
1435  "  -t <file>, --require <file>\n"
1436  "     Like -e '(require (file \"<file>\"))' [*]\n"
1437  "  -l <path>, --lib <path>\n"
1438  "     Like -e '(require (lib \"<path>\"))' [*]\n"
1439  "  -p <package>\n"
1440  "     Like -e '(require (planet \"<package>\")' [*]\n"
1441  "  -r <file>, --script <file>\n"
1442  "     Same as -f <file> -N <file> --\n"
1443  "  -u <file>, --require-script <file>\n"
1444  "     Same as -t <file> -N <file> --\n"
1445  "  -k <n> <m> <p>\n"
1446  "     Load executable-embedded code from offset <n> to <p>\n"
1447  "  -Y <file> <n> <m> <p>\n"
1448  "     Like -k <n> <m> <p>, but from <file>\n"
1449  "  -m, --main\n"
1450  "     Call `main` with command-line arguments, print results\n"
1451  "\n"
1452  " [*] Also `require`s a `main` submodule, if any\n"
1453  "\n"
1454  "Interaction options:\n\n"
1455  "  -i, --repl\n"
1456  "     Run interactive read-eval-print loop; implies -v\n"
1457  "  -n, --no-lib\n"
1458  "     Skip `(require (lib \"<init-lib>\"))` for -i/-e/-f/-r\n"
1459  "  -v, --version\n"
1460  "     Show version\n"
1461# ifdef CMDLINE_STDIO_FLAG
1462  "  -K, --back\n"
1463  "     Don't bring application to the foreground (Mac OS X)\n"
1464# endif
1465# ifndef NO_YIELD_BEFORE_EXIT
1466  "  -V, --no-yield\n"
1467  "     Skip `((executable-yield-handler) <status>)` on exit\n"
1468# endif
1469  "\n"
1470  "Configuration options:\n\n"
1471  "  -c, --no-compiled\n"
1472  "     Disable loading of compiled files\n"
1473  "  -q, --no-init-file\n"
1474  "     Skip load of " INIT_FILENAME " for -i\n"
1475# ifdef CMDLINE_STDIO_FLAG
1476  "  -z, --text-repl\n"
1477  "     Use text `read-eval-print-loop` for -i\n"
1478# endif
1479  "  -I <path>\n"
1480  "     Set <init-lib> to <path> (sets language)\n"
1481  "  -X <dir>, --collects <dir>\n"
1482  "     Main collects at <dir> (or \"\" disables all)\n"
1483  "  -S <dir>, --search <dir>\n"
1484  "     More collects at <dir> (after main collects)\n"
1485  "  -G <dir>, --config <dir>\n"
1486  "     Main configuration directory at <dir>\n"
1487  "  -A <dir>, --addon <dir>\n"
1488  "     Addon directory at <dir>\n"
1489  "  -U, --no-user-path\n"
1490  "     Ignore user-specific collects, etc.\n"
1491  "  -R <paths>, --compiled <paths>\n"
1492  "     Set compiled-file search roots to <paths>\n"
1493  "  -C, --cross\n"
1494  "     Cross-build mode; save current collects and config\n"
1495  "     as host\n"
1496  "  -N <file>, --name <file>\n"
1497  "     Sets `(find-system-path 'run-file)` to <file>\n"
1498  "  -E <file>, --exec <file>\n"
1499  "     Sets `(find-system-path 'exec-file)` to <file>\n"
1500# ifdef CMDLINE_STDIO_FLAG
1501  "  -J <name>, ---wm-class <name>\n"
1502  "     Set WM_CLASS class to <name> (Unix)\n"
1503# endif
1504# ifdef MZ_USE_JIT
1505  "  -j, --no-jit\n"
1506  "     Disable the just-in-time compiler\n"
1507# else
1508  "  -j, --no-jit\n"
1509  "     No effect, since the just-in-time compiler is unavailable\n"
1510# endif
1511  "  -M, --compile-any\n"
1512  "     Compile to machine-independent form\n"
1513  "  -d, --no-delay\n"
1514  "     Disable on-demand loading of syntax and code\n"
1515  "  -b, --binary\n"
1516  "     No effect, since stdin and stdout/stderr are\n"
1517  "     always binary\n"
1518  "  -W <levels>, --warn <levels>\n"
1519  "     Set stderr logging to <levels>\n"
1520  "  -O <levels>, --stdout <levels>\n"
1521  "     Set stdout logging to <levels>\n"
1522  "  -L <levels>, --syslog <levels>\n"
1523  "     Set syslog logging to <levels>\n"
1524  "\n"
1525  "Meta options:\n\n"
1526  "  --\n"
1527  "     No argument following this switch is used as a switch\n"
1528  "  -Z\n"
1529  "     Ignore the argument following this switch\n"
1530  "  -h, --help\n"
1531  "     Show this information and exits, ignoring other options\n"
1532  "\n"
1533  "Default options:\n\n"
1534  "  * If only configuration options are provided, -i is added\n"
1535  "  * If only configuration options are before the first\n"
1536  "    argument, -u is added\n"
1537  "  * If -t/-l/-p/-u appears before the first -i/-e/-f/-r,\n"
1538  "    -n is added\n"
1539  "  * <init-lib> defaults to " INITIAL_NAMESPACE_MODULE "\n"
1540  "\n"
1541  "Switch syntax:\n\n"
1542  "  Multiple single-letter switches can be collapsed, with\n"
1543  "  arguments placed after the collapsed switches; the first\n"
1544  "  collapsed switch cannot be --\n\n"
1545  "  For example,\n"
1546  "\n"
1547  "      -ifve file expr\n"
1548  "\n"
1549  "  is the same as\n"
1550  "\n"
1551  "      -i -f file -v -e expr\n"
1552  "\n"
1553  "Start-up sequence:\n\n"
1554  "  1. Set `current-library-collection-paths`\n"
1555  "  2. Require `(lib \"<init-lib>\")` [when -i/-e/-f/-r, unless -n]\n"
1556  "  3. Evaluate/load expressions/files in order, until first error\n"
1557  "  4. Load \"" INIT_FILENAME "\" [when -i]\n"
1558  "  5. Run read-eval-print loop [when -i]\n"
1559# ifndef NO_YIELD_BEFORE_EXIT
1560  "  6. Run `((executable-yield-handler) <status>)` [unless -V]\n"
1561# endif
1562  );
1563  PRINTF(prog, BANNER);
1564#if defined(WINDOWS_FILE_HANDLES)
1565  CMDLINE_FFLUSH(stdout);
1566#endif
1567  return 0;
1568 bad_switch:
1569  if (specific_switch[0] && real_switch[2]) {
1570    PRINTF("%s: bad switch: -%s within: %s\n", prog, specific_switch, real_switch);
1571  } else {
1572    PRINTF("%s: bad switch: %s\n", prog, real_switch);
1573  }
1574 show_need_help:
1575  PRINTF("Use the --help or -h flag for help.\n");
1576#if defined(DETECT_WIN32_CONSOLE_STDIN)
1577  CMDLINE_FFLUSH(stdout);
1578#endif
1579  return 1;
1580#endif
1581}
1582
1583#if defined(OS_X) && defined(MZ_PRECISE_GC) && defined(EXTRA_EXCEPTION_STUBS)
1584
1585/* These declarations avoid linker problems when using
1586   -mmacosx-version-min. See gc2/vm_osx.c for details. */
1587
1588START_XFORM_SKIP;
1589
1590#include <mach/mach.h>
1591#include <mach/mach_error.h>
1592
1593# ifdef __cplusplus
1594extern "C" {
1595# endif
1596
1597extern kern_return_t GC_catch_exception_raise_state(mach_port_t port,
1598                                                    exception_type_t exception_type,
1599                                                    exception_data_t exception_data,
1600                                                    mach_msg_type_number_t data_cnt,
1601                                                    thread_state_flavor_t *flavor,
1602                                                    thread_state_t in_state,
1603                                                    mach_msg_type_number_t is_cnt,
1604                                                    thread_state_t out_state,
1605                                                    mach_msg_type_number_t os_cnt);
1606extern kern_return_t GC_catch_exception_raise_state_identitity
1607  (mach_port_t port,  mach_port_t thread_port, mach_port_t task_port,
1608   exception_type_t exception_type, exception_data_t exception_data,
1609   mach_msg_type_number_t data_count, thread_state_flavor_t *state_flavor,
1610   thread_state_t in_state, mach_msg_type_number_t in_state_count,
1611   thread_state_t out_state, mach_msg_type_number_t out_state_count);
1612extern kern_return_t GC_catch_exception_raise(mach_port_t port,
1613                                              mach_port_t thread_port,
1614                                              mach_port_t task_port,
1615                                              exception_type_t exception_type,
1616                                              exception_data_t exception_data,
1617                                              mach_msg_type_number_t data_count);
1618
1619kern_return_t catch_exception_raise_state(mach_port_t port,
1620					  exception_type_t exception_type,
1621					  exception_data_t exception_data,
1622					  mach_msg_type_number_t data_cnt,
1623					  thread_state_flavor_t *flavor,
1624					  thread_state_t in_state,
1625					  mach_msg_type_number_t is_cnt,
1626					  thread_state_t out_state,
1627					  mach_msg_type_number_t os_cnt)
1628{
1629  return GC_catch_exception_raise_state(port, exception_type, exception_data,
1630                                        data_cnt, flavor,
1631                                        in_state, is_cnt,
1632                                        out_state, os_cnt);
1633}
1634
1635kern_return_t catch_exception_raise_state_identitity
1636  (mach_port_t port,  mach_port_t thread_port, mach_port_t task_port,
1637   exception_type_t exception_type, exception_data_t exception_data,
1638   mach_msg_type_number_t data_count, thread_state_flavor_t *state_flavor,
1639   thread_state_t in_state, mach_msg_type_number_t in_state_count,
1640   thread_state_t out_state, mach_msg_type_number_t out_state_count)
1641{
1642  return GC_catch_exception_raise_state_identitity(port, thread_port, task_port,
1643                                                   exception_type, exception_data,
1644                                                   data_count, state_flavor,
1645                                                   in_state, in_state_count,
1646                                                   out_state, out_state_count);
1647}
1648
1649kern_return_t catch_exception_raise(mach_port_t port,
1650				    mach_port_t thread_port,
1651				    mach_port_t task_port,
1652				    exception_type_t exception_type,
1653				    exception_data_t exception_data,
1654				    mach_msg_type_number_t data_count)
1655{
1656  return GC_catch_exception_raise(port, thread_port, task_port,
1657                                  exception_type, exception_data, data_count);
1658}
1659
1660# ifdef __cplusplus
1661};
1662# endif
1663END_XFORM_SKIP;
1664#endif
1665