Projects : gscm : gscm_usrbin

gscm/src/main.c

Dir - Raw

1/* Gales Scheme executable entry point and option parser
2 * J. Welsh, 2017
3 */
4
5#include "gscm.h"
6
7#ifndef GSCM_DEF_HEAP
8#define GSCM_DEF_HEAP 128
9#endif
10
11#define STR_(token) #token
12#define STR(token_or_macro) STR_(token_or_macro)
13
14static const char usage[] =
15"Usage: gscm [-Hcgh] [-m SIZE] [--] [FILE [ARG ...]]"
16"\n"
17"\nExecute Scheme source FILE (- for standard input, unless -- is used), with FILE and any ARGs stored in the global list *ARGS*. If no FILE is given, start a read-eval-print loop."
18"\n"
19"\n-H: Use huge pages if supported"
20"\n-c: Load saved core instead of source (TODO)"
21"\n-g: Print memory stats to standard error on garbage collection"
22"\n-h: Print this help message"
23"\n-m: Heap size in MiB. Twice this is fully allocated at startup from the OS kernel's point of view (half reserved for garbage collection). A larger heap reduces GC frequency but may increase virtual memory overhead (TLB thrashing)."
24"\n"
25"\nBuild configuration:"
26"\n Word size (bytes): " STR(__SIZEOF_POINTER__)
27"\n Default heap (-m): " STR(GSCM_DEF_HEAP)
28"\n Library path: " GSCMLIB
29"\n";
30
31/* Strictly parse non-negative decimal integer in null-terminated string src. On success, return true and store the result in dst. On failure (empty string, non-digit or overflow), return false. */
32static int parse_ulong_dec(unsigned long *dst, const char *src) {
33 unsigned long acc = 0;
34 if (!*src) return 0;
35 do {
36 unsigned char digit = ((unsigned char)(*src)) - '0';
37 if (digit > 9) return 0;
38 if (acc > (-1UL)/10) return 0;
39 acc *= 10;
40 if (acc + digit < acc) return 0;
41 acc += digit;
42 } while (*++src);
43 *dst = acc;
44 return 1;
45}
46
47int main(int argc, char **argv) {
48 sc_value heap_mb = GSCM_DEF_HEAP, heap_alloc;
49#define SHIFT (++argv, --argc)
50 if (argc) SHIFT;
51 while (argc) {
52 char *arg = *argv;
53 if (arg[0] != '-' || !arg[1] || (arg[1] == '-' && !arg[2])) break;
54 while (*++arg) switch (*arg) {
55 case 'H':
56 sc_hugepages = 1; break;
57 /* case 'c': break; */
58 case 'g':
59 sc_gc_verbose = 1; break;
60 case 'h':
61 sc_write_error(usage); return 0;
62 case 'm':
63 if (!*++arg) {
64 SHIFT;
65 if (!argc) {
66 sc_write_error("gscm: -m missing argument\n");
67 goto err;
68 }
69 arg = *argv;
70 }
71 if (!(parse_ulong_dec(&heap_mb, arg) && heap_mb)) {
72 sc_write_error("gscm: bad -m argument\n");
73 goto err;
74 }
75 goto next_arg;
76 default:
77 {
78 char tail[] = {*arg, '\n', 0};
79 sc_write_error("gscm: bad option: ");
80 sc_write_error(tail);
81 goto err;
82 }
83 }
84next_arg:
85 SHIFT;
86 }
87 heap_alloc = heap_mb<<21;
88 if (heap_alloc>>21 != heap_mb) {
89 sc_write_error("gscm: heap size too big (integer overflow)\n");
90 return 1;
91 }
92 sc_init(heap_alloc);
93 return sc_toplevel(argc, argv);
94err:
95 sc_write_error(usage);
96 return 1;
97}