altos/scheme: Add ports. Split scheme code up.
[fw/altos] / src / scheme / test / ao_scheme_test.c
1 /*
2  * Copyright © 2016 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  */
14
15 #include "ao_scheme.h"
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <getopt.h>
19
20 static char save_file[] = "scheme.image";
21
22 int
23 ao_scheme_os_save(void)
24 {
25         FILE    *save = fopen(save_file, "w");
26
27         if (!save) {
28                 perror(save_file);
29                 return 0;
30         }
31         fwrite(ao_scheme_pool, 1, AO_SCHEME_POOL_TOTAL, save);
32         fclose(save);
33         return 1;
34 }
35
36 int
37 ao_scheme_os_restore_save(struct ao_scheme_os_save *save, int offset)
38 {
39         FILE    *restore = fopen(save_file, "r");
40         size_t  ret;
41
42         if (!restore) {
43                 perror(save_file);
44                 return 0;
45         }
46         fseek(restore, offset, SEEK_SET);
47         ret = fread(save, sizeof (struct ao_scheme_os_save), 1, restore);
48         fclose(restore);
49         if (ret != 1)
50                 return 0;
51         return 1;
52 }
53
54 int
55 ao_scheme_os_restore(void)
56 {
57         FILE    *restore = fopen(save_file, "r");
58         size_t  ret;
59
60         if (!restore) {
61                 perror(save_file);
62                 return 0;
63         }
64         ret = fread(ao_scheme_pool, 1, AO_SCHEME_POOL_TOTAL, restore);
65         fclose(restore);
66         if (ret != AO_SCHEME_POOL_TOTAL)
67                 return 0;
68         return 1;
69 }
70
71 static const struct option options[] = {
72         { .name = "load", .has_arg = 1, .val = 'l' },
73         { 0, 0, 0, 0 },
74 };
75
76 static void usage(char *program)
77 {
78         fprintf(stderr, "usage: %s [--load=<library> ...] <program ...>\n", program);
79 }
80
81 static void
82 check_exit(ao_poly v)
83 {
84         if (ao_scheme_exception & AO_SCHEME_EXIT) {
85                 int     ret;
86
87                 if (v == _ao_scheme_bool_true)
88                         ret = 0;
89                 else {
90                         ret = 1;
91                         if (ao_scheme_is_integer(v))
92                                 ret = ao_scheme_poly_integer(v);
93                 }
94                 exit(ret);
95         }
96 }
97
98 static void
99 run_file(char *name)
100 {
101         FILE    *in;
102         int     c;
103         ao_poly v;
104
105         in = fopen(name, "r");
106         if (!in) {
107                 perror(name);
108                 exit(1);
109         }
110         c = getc(in);
111         if (c == '#') {
112                 do {
113                         c = getc(in);
114                 } while (c != EOF && c != '\n');
115         } else {
116                 ungetc(c, in);
117         }
118         v = ao_scheme_read_eval_print(in, NULL, false);
119         fclose(in);
120         check_exit(v);
121 }
122
123 int
124 main (int argc, char **argv)
125 {
126         int     o;
127
128         while ((o = getopt_long(argc, argv, "?l:", options, NULL)) != -1) {
129                 switch (o) {
130                 case '?':
131                         usage(argv[0]);
132                         exit(0);
133                 case 'l':
134                         ao_scheme_set_argv(&argv[argc]);
135                         run_file(optarg);
136                         break;
137                 default:
138                         usage(argv[0]);
139                         exit(1);
140                 }
141         }
142         ao_scheme_set_argv(argv + optind);
143         if (argv[optind]) {
144                 run_file(argv[optind]);
145         } else {
146                 ao_poly v;
147                 v = ao_scheme_read_eval_print(stdin, stdout, true);
148                 check_exit(v);
149                 putchar('\n');
150         }
151
152 #ifdef DBG_MEM_STATS
153         printf ("collects: full: %lu incremental %lu\n",
154                 ao_scheme_collects[AO_SCHEME_COLLECT_FULL],
155                 ao_scheme_collects[AO_SCHEME_COLLECT_INCREMENTAL]);
156
157         printf ("freed: full %lu incremental %lu\n",
158                 ao_scheme_freed[AO_SCHEME_COLLECT_FULL],
159                 ao_scheme_freed[AO_SCHEME_COLLECT_INCREMENTAL]);
160
161         printf("loops: full %lu incremental %lu\n",
162                 ao_scheme_loops[AO_SCHEME_COLLECT_FULL],
163                 ao_scheme_loops[AO_SCHEME_COLLECT_INCREMENTAL]);
164
165         printf("loops per collect: full %f incremental %f\n",
166                (double) ao_scheme_loops[AO_SCHEME_COLLECT_FULL] /
167                (double) ao_scheme_collects[AO_SCHEME_COLLECT_FULL],
168                (double) ao_scheme_loops[AO_SCHEME_COLLECT_INCREMENTAL] /
169                (double) ao_scheme_collects[AO_SCHEME_COLLECT_INCREMENTAL]);
170
171         printf("freed per collect: full %f incremental %f\n",
172                (double) ao_scheme_freed[AO_SCHEME_COLLECT_FULL] /
173                (double) ao_scheme_collects[AO_SCHEME_COLLECT_FULL],
174                (double) ao_scheme_freed[AO_SCHEME_COLLECT_INCREMENTAL] /
175                (double) ao_scheme_collects[AO_SCHEME_COLLECT_INCREMENTAL]);
176
177         printf("freed per loop: full %f incremental %f\n",
178                (double) ao_scheme_freed[AO_SCHEME_COLLECT_FULL] /
179                (double) ao_scheme_loops[AO_SCHEME_COLLECT_FULL],
180                (double) ao_scheme_freed[AO_SCHEME_COLLECT_INCREMENTAL] /
181                (double) ao_scheme_loops[AO_SCHEME_COLLECT_INCREMENTAL]);
182 #endif
183         return 0;
184 }