altos/lisp: Append a CRC to the saved image to validate on restore
[fw/altos] / src / lisp / ao_lisp_make_const.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_lisp.h"
16 #include <stdlib.h>
17 #include <ctype.h>
18
19 static struct ao_lisp_builtin *
20 ao_lisp_make_builtin(enum ao_lisp_builtin_id func, int args) {
21         struct ao_lisp_builtin *b = ao_lisp_alloc(sizeof (struct ao_lisp_builtin));
22
23         b->type = AO_LISP_BUILTIN;
24         b->func = func;
25         b->args = args;
26         return b;
27 }
28
29 struct builtin_func {
30         char    *name;
31         int     args;
32         int     func;
33 };
34
35 struct builtin_func funcs[] = {
36         "eval",         AO_LISP_FUNC_LAMBDA,    builtin_eval,
37         "read",         AO_LISP_FUNC_LAMBDA,    builtin_read,
38         "lambda",       AO_LISP_FUNC_NLAMBDA,   builtin_lambda,
39         "lexpr",        AO_LISP_FUNC_NLAMBDA,   builtin_lexpr,
40         "nlambda",      AO_LISP_FUNC_NLAMBDA,   builtin_nlambda,
41         "macro",        AO_LISP_FUNC_NLAMBDA,   builtin_macro,
42         "car",          AO_LISP_FUNC_LAMBDA,    builtin_car,
43         "cdr",          AO_LISP_FUNC_LAMBDA,    builtin_cdr,
44         "cons",         AO_LISP_FUNC_LAMBDA,    builtin_cons,
45         "last",         AO_LISP_FUNC_LAMBDA,    builtin_last,
46         "length",       AO_LISP_FUNC_LAMBDA,    builtin_length,
47         "quote",        AO_LISP_FUNC_NLAMBDA,   builtin_quote,
48         "set",          AO_LISP_FUNC_LAMBDA,    builtin_set,
49         "setq",         AO_LISP_FUNC_MACRO,     builtin_setq,
50         "cond",         AO_LISP_FUNC_NLAMBDA,   builtin_cond,
51         "progn",        AO_LISP_FUNC_NLAMBDA,   builtin_progn,
52         "while",        AO_LISP_FUNC_NLAMBDA,   builtin_while,
53         "print",        AO_LISP_FUNC_LEXPR,     builtin_print,
54         "patom",        AO_LISP_FUNC_LEXPR,     builtin_patom,
55         "+",            AO_LISP_FUNC_LEXPR,     builtin_plus,
56         "-",            AO_LISP_FUNC_LEXPR,     builtin_minus,
57         "*",            AO_LISP_FUNC_LEXPR,     builtin_times,
58         "/",            AO_LISP_FUNC_LEXPR,     builtin_divide,
59         "%",            AO_LISP_FUNC_LEXPR,     builtin_mod,
60         "=",            AO_LISP_FUNC_LEXPR,     builtin_equal,
61         "<",            AO_LISP_FUNC_LEXPR,     builtin_less,
62         ">",            AO_LISP_FUNC_LEXPR,     builtin_greater,
63         "<=",           AO_LISP_FUNC_LEXPR,     builtin_less_equal,
64         ">=",           AO_LISP_FUNC_LEXPR,     builtin_greater_equal,
65         "pack",         AO_LISP_FUNC_LAMBDA,    builtin_pack,
66         "unpack",       AO_LISP_FUNC_LAMBDA,    builtin_unpack,
67         "flush",        AO_LISP_FUNC_LAMBDA,    builtin_flush,
68         "delay",        AO_LISP_FUNC_LAMBDA,    builtin_delay,
69         "led",          AO_LISP_FUNC_LEXPR,     builtin_led,
70         "save",         AO_LISP_FUNC_LAMBDA,    builtin_save,
71         "restore",      AO_LISP_FUNC_LAMBDA,    builtin_restore,
72 };
73
74 #define N_FUNC (sizeof funcs / sizeof funcs[0])
75
76 struct ao_lisp_frame    *globals;
77
78 static int
79 is_atom(int offset)
80 {
81         struct ao_lisp_atom *a;
82
83         for (a = ao_lisp_atoms; a; a = ao_lisp_poly_atom(a->next))
84                 if (((uint8_t *) a->name - ao_lisp_const) == offset)
85                         return strlen(a->name);
86         return 0;
87 }
88
89 #define AO_FEC_CRC_INIT 0xffff
90
91 static inline uint16_t
92 ao_fec_crc_byte(uint8_t byte, uint16_t crc)
93 {
94         uint8_t bit;
95
96         for (bit = 0; bit < 8; bit++) {
97                 if (((crc & 0x8000) >> 8) ^ (byte & 0x80))
98                         crc = (crc << 1) ^ 0x8005;
99                 else
100                         crc = (crc << 1);
101                 byte <<= 1;
102         }
103         return crc;
104 }
105
106 uint16_t
107 ao_fec_crc(const uint8_t *bytes, uint8_t len)
108 {
109         uint16_t        crc = AO_FEC_CRC_INIT;
110
111         while (len--)
112                 crc = ao_fec_crc_byte(*bytes++, crc);
113         return crc;
114 }
115
116 int
117 main(int argc, char **argv)
118 {
119         int     f, o, i;
120         ao_poly sexpr, val;
121         struct ao_lisp_atom     *a;
122         struct ao_lisp_builtin  *b;
123         int     in_atom;
124
125         printf("/*\n");
126         printf(" * Generated file, do not edit\n");
127         for (f = 0; f < N_FUNC; f++) {
128                 b = ao_lisp_make_builtin(funcs[f].func, funcs[f].args);
129                 a = ao_lisp_atom_intern(funcs[f].name);
130                 ao_lisp_atom_set(ao_lisp_atom_poly(a),
131                                  ao_lisp_builtin_poly(b));
132         }
133
134         /* boolean constants */
135         ao_lisp_atom_set(ao_lisp_atom_poly(ao_lisp_atom_intern("nil")),
136                          AO_LISP_NIL);
137         a = ao_lisp_atom_intern("t");
138         ao_lisp_atom_set(ao_lisp_atom_poly(a),
139                          ao_lisp_atom_poly(a));
140
141         /* end of file value */
142         a = ao_lisp_atom_intern("eof");
143         ao_lisp_atom_set(ao_lisp_atom_poly(a),
144                          ao_lisp_atom_poly(a));
145
146         ao_lisp_read_eval_print();
147
148         /* Reduce to referenced values */
149         ao_lisp_collect();
150         printf(" */\n");
151
152         printf("#define AO_LISP_POOL_CONST %d\n", ao_lisp_top);
153         printf("extern const uint8_t ao_lisp_const[AO_LISP_POOL_CONST] __attribute__((aligned(4)));\n");
154         printf("#define ao_builtin_atoms 0x%04x\n", ao_lisp_atom_poly(ao_lisp_atoms));
155         printf("#define ao_builtin_frame 0x%04x\n", ao_lisp_frame_poly(ao_lisp_frame_global));
156         printf("#define ao_lisp_const_checksum ((uint16_t) 0x%04x)\n", ao_fec_crc(ao_lisp_const, ao_lisp_top));
157
158         for (a = ao_lisp_atoms; a; a = ao_lisp_poly_atom(a->next)) {
159                 char    *n = a->name, c;
160                 printf ("#define _ao_lisp_atom_");
161                 while ((c = *n++)) {
162                         if (isalnum(c))
163                                 printf("%c", c);
164                         else
165                                 printf("%02x", c);
166                 }
167                 printf("  0x%04x\n", ao_lisp_atom_poly(a));
168         }
169         printf("#ifdef AO_LISP_CONST_BITS\n");
170         printf("const uint8_t ao_lisp_const[] = {");
171         for (o = 0; o < ao_lisp_top; o++) {
172                 uint8_t c;
173                 if ((o & 0xf) == 0)
174                         printf("\n\t");
175                 else
176                         printf(" ");
177                 c = ao_lisp_const[o];
178                 if (!in_atom)
179                         in_atom = is_atom(o);
180                 if (in_atom) {
181                         printf (" '%c',", c);
182                         in_atom--;
183                 } else {
184                         printf("0x%02x,", c);
185                 }
186         }
187         printf("\n};\n");
188         printf("#endif /* AO_LISP_CONST_BITS */\n");
189 }