altos/lisp: add length, pack, unpack and flush
[fw/altos] / src / lisp / ao_lisp_string.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; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include "ao_lisp.h"
19
20 static void string_mark(void *addr)
21 {
22         (void) addr;
23 }
24
25 static int string_size(void *addr)
26 {
27         if (!addr)
28                 return 0;
29         return strlen(addr) + 1;
30 }
31
32 static void string_move(void *addr)
33 {
34         (void) addr;
35 }
36
37 const struct ao_lisp_type ao_lisp_string_type = {
38         .mark = string_mark,
39         .size = string_size,
40         .move = string_move,
41 };
42
43 char *
44 ao_lisp_string_new(int len) {
45         char    *a = ao_lisp_alloc(len + 1);
46         if (!a)
47                 return NULL;
48         a[len] = '\0';
49         return a;
50 }
51
52 char *
53 ao_lisp_string_copy(char *a)
54 {
55         int     alen = strlen(a);
56
57         char    *r = ao_lisp_alloc(alen + 1);
58         if (!r)
59                 return NULL;
60         strcpy(r, a);
61         return r;
62 }
63
64 char *
65 ao_lisp_string_cat(char *a, char *b)
66 {
67         int     alen = strlen(a);
68         int     blen = strlen(b);
69         char    *r = ao_lisp_alloc(alen + blen + 1);
70         if (!r)
71                 return NULL;
72         strcpy(r, a);
73         strcpy(r+alen, b);
74         return r;
75 }
76
77 ao_poly
78 ao_lisp_string_pack(struct ao_lisp_cons *cons)
79 {
80         int     len = ao_lisp_cons_length(cons);
81         char    *r = ao_lisp_alloc(len + 1);
82         char    *s = r;
83
84         while (cons) {
85                 if (ao_lisp_poly_type(cons->car) != AO_LISP_INT)
86                         return ao_lisp_error(AO_LISP_INVALID, "non-int passed to pack");
87                 *s++ = ao_lisp_poly_int(cons->car);
88                 cons = ao_lisp_poly_cons(cons->cdr);
89         }
90         *s++ = 0;
91         return ao_lisp_string_poly(r);
92 }
93
94 ao_poly
95 ao_lisp_string_unpack(char *a)
96 {
97         struct ao_lisp_cons     *cons = NULL, *tail = NULL;
98         int                     c;
99
100         ao_lisp_root_add(&ao_lisp_cons_type, &cons);
101         ao_lisp_root_add(&ao_lisp_cons_type, &tail);
102         while ((c = *a++)) {
103                 struct ao_lisp_cons     *n = ao_lisp_cons_cons(ao_lisp_int_poly(c), NULL);
104                 if (!n) {
105                         cons = NULL;
106                         break;
107                 }
108                 if (tail)
109                         tail->cdr = ao_lisp_cons_poly(n);
110                 else
111                         cons = n;
112                 tail = n;
113         }
114         ao_lisp_root_clear(&cons);
115         ao_lisp_root_clear(&tail);
116         return ao_lisp_cons_poly(cons);
117 }
118
119 void
120 ao_lisp_string_print(ao_poly p)
121 {
122         char    *s = ao_lisp_poly_string(p);
123         char    c;
124
125         putchar('"');
126         while ((c = *s++)) {
127                 switch (c) {
128                 case '\n':
129                         printf ("\\n");
130                         break;
131                 case '\r':
132                         printf ("\\r");
133                         break;
134                 case '\t':
135                         printf ("\\t");
136                         break;
137                 default:
138                         putchar(c);
139                         break;
140                 }
141         }
142         putchar('"');
143 }
144
145 void
146 ao_lisp_string_patom(ao_poly p)
147 {
148         char    *s = ao_lisp_poly_string(p);
149         char    c;
150
151         while ((c = *s++))
152                 putchar(c);
153 }