altos/lisp: Split out read debug, add memory validation
[fw/altos] / src / lisp / ao_lisp_error.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 <stdarg.h>
17
18 void
19 ao_lisp_error_poly(char *name, ao_poly poly, ao_poly last)
20 {
21         int first = 1;
22         printf("\t\t%s(", name);
23         if (ao_lisp_poly_type(poly) == AO_LISP_CONS) {
24                 if (poly) {
25                         while (poly) {
26                                 struct ao_lisp_cons *cons = ao_lisp_poly_cons(poly);
27                                 if (!first)
28                                         printf("\t\t         ");
29                                 else
30                                         first = 0;
31                                 ao_lisp_poly_write(cons->car);
32                                 printf("\n");
33                                 if (poly == last)
34                                         break;
35                                 poly = cons->cdr;
36                         }
37                         printf("\t\t         )\n");
38                 } else
39                         printf(")\n");
40         } else {
41                 ao_lisp_poly_write(poly);
42                 printf("\n");
43         }
44 }
45
46 static void tabs(int indent)
47 {
48         while (indent--)
49                 printf("\t");
50 }
51
52 void
53 ao_lisp_error_frame(int indent, char *name, struct ao_lisp_frame *frame)
54 {
55         int                     f;
56
57         tabs(indent);
58         printf ("%s{", name);
59         if (frame) {
60                 struct ao_lisp_frame_vals       *vals = ao_lisp_poly_frame_vals(frame->vals);
61                 if (frame->type & AO_LISP_FRAME_PRINT)
62                         printf("recurse...");
63                 else {
64                         frame->type |= AO_LISP_FRAME_PRINT;
65                         for (f = 0; f < frame->num; f++) {
66                                 if (f != 0) {
67                                         tabs(indent);
68                                         printf("         ");
69                                 }
70                                 ao_lisp_poly_write(vals->vals[f].atom);
71                                 printf(" = ");
72                                 ao_lisp_poly_write(vals->vals[f].val);
73                                 printf("\n");
74                         }
75                         if (frame->prev)
76                                 ao_lisp_error_frame(indent + 1, "prev:   ", ao_lisp_poly_frame(frame->prev));
77                         frame->type &= ~AO_LISP_FRAME_PRINT;
78                 }
79                 tabs(indent);
80                 printf("        }\n");
81         } else
82                 printf ("}\n");
83 }
84
85 void
86 ao_lisp_vprintf(char *format, va_list args)
87 {
88         char c;
89
90         while ((c = *format++) != '\0') {
91                 if (c == '%') {
92                         switch (c = *format++) {
93                         case 'v':
94                                 ao_lisp_poly_write((ao_poly) va_arg(args, unsigned int));
95                                 break;
96                         case 'p':
97                                 printf("%p", va_arg(args, void *));
98                                 break;
99                         case 'd':
100                                 printf("%d", va_arg(args, int));
101                                 break;
102                         case 's':
103                                 printf("%s", va_arg(args, char *));
104                                 break;
105                         default:
106                                 putchar(c);
107                                 break;
108                         }
109                 } else
110                         putchar(c);
111         }
112 }
113
114 void
115 ao_lisp_printf(char *format, ...)
116 {
117         va_list args;
118         va_start(args, format);
119         ao_lisp_vprintf(format, args);
120         va_end(args);
121 }
122
123 ao_poly
124 ao_lisp_error(int error, char *format, ...)
125 {
126         va_list args;
127
128         ao_lisp_exception |= error;
129         va_start(args, format);
130         ao_lisp_vprintf(format, args);
131         putchar('\n');
132         va_end(args);
133         ao_lisp_printf("Value:  %v\n", ao_lisp_v);
134         ao_lisp_printf("Frame:  %v\n", ao_lisp_frame_poly(ao_lisp_frame_current));
135         printf("Stack:\n");
136         ao_lisp_stack_write(ao_lisp_stack_poly(ao_lisp_stack));
137         ao_lisp_printf("Globals: %v\n", ao_lisp_frame_poly(ao_lisp_frame_global));
138         return AO_LISP_NIL;
139 }