Change the kernel dev_t, representing a pointer to a specinfo structure,
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / isccc / sexpr.c
1 /*
2  * Portions Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Portions Copyright (C) 2001  Internet Software Consortium.
4  * Portions Copyright (C) 2001  Nominum, Inc.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
12  * OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY
13  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18
19 /* $Id: sexpr.c,v 1.2.2.1 2004/03/09 06:12:25 marka Exp $ */
20
21 #include <config.h>
22
23 #include <ctype.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <isc/assertions.h>
28 #include <isccc/sexpr.h>
29 #include <isccc/util.h>
30
31 static isccc_sexpr_t sexpr_t = { ISCCC_SEXPRTYPE_T, { NULL } };
32
33 #define CAR(s)                  (s)->value.as_dottedpair.car
34 #define CDR(s)                  (s)->value.as_dottedpair.cdr
35
36 isccc_sexpr_t *
37 isccc_sexpr_cons(isccc_sexpr_t *car, isccc_sexpr_t *cdr)
38 {
39         isccc_sexpr_t *sexpr;
40
41         sexpr = malloc(sizeof *sexpr);
42         if (sexpr == NULL)
43                 return (NULL);
44         sexpr->type = ISCCC_SEXPRTYPE_DOTTEDPAIR;
45         CAR(sexpr) = car;
46         CDR(sexpr) = cdr;
47
48         return (sexpr);
49 }
50
51 isccc_sexpr_t *
52 isccc_sexpr_tconst(void)
53 {
54         return (&sexpr_t);
55 }
56
57 isccc_sexpr_t *
58 isccc_sexpr_fromstring(const char *str)
59 {
60         isccc_sexpr_t *sexpr;
61
62         sexpr = malloc(sizeof *sexpr);
63         if (sexpr == NULL)
64                 return (NULL);
65         sexpr->type = ISCCC_SEXPRTYPE_STRING;
66         sexpr->value.as_string = strdup(str);
67         if (sexpr->value.as_string == NULL) {
68                 free(sexpr);
69                 return (NULL);
70         }
71
72         return (sexpr);
73 }
74
75 isccc_sexpr_t *
76 isccc_sexpr_frombinary(const isccc_region_t *region)
77 {
78         isccc_sexpr_t *sexpr;
79         unsigned int region_size;
80
81         sexpr = malloc(sizeof *sexpr);
82         if (sexpr == NULL)
83                 return (NULL);
84         sexpr->type = ISCCC_SEXPRTYPE_BINARY;
85         region_size = REGION_SIZE(*region);
86         /*
87          * We add an extra byte when we malloc so we can NUL terminate
88          * the binary data.  This allows the caller to use it as a C
89          * string.  It's up to the caller to ensure this is safe.  We don't
90          * add 1 to the length of the binary region, because the NUL is
91          * not part of the binary data.
92          */
93         sexpr->value.as_region.rstart = malloc(region_size + 1);
94         if (sexpr->value.as_region.rstart == NULL) {
95                 free(sexpr);
96                 return (NULL);
97         }
98         sexpr->value.as_region.rend = sexpr->value.as_region.rstart +
99                 region_size;
100         memcpy(sexpr->value.as_region.rstart, region->rstart, region_size);
101         /*
102          * NUL terminate.
103          */
104         sexpr->value.as_region.rstart[region_size] = '\0';
105
106         return (sexpr);
107 }
108
109 void
110 isccc_sexpr_free(isccc_sexpr_t **sexprp)
111 {
112         isccc_sexpr_t *sexpr;
113         isccc_sexpr_t *item;
114
115         sexpr = *sexprp;
116         if (sexpr == NULL)
117                 return;
118         switch (sexpr->type) {
119         case ISCCC_SEXPRTYPE_STRING:
120                 free(sexpr->value.as_string);
121                 break;
122         case ISCCC_SEXPRTYPE_DOTTEDPAIR:
123                 item = CAR(sexpr);
124                 if (item != NULL)
125                         isccc_sexpr_free(&item);
126                 item = CDR(sexpr);
127                 if (item != NULL)
128                         isccc_sexpr_free(&item);
129                 break;
130         case ISCCC_SEXPRTYPE_BINARY:
131                 free(sexpr->value.as_region.rstart);
132                 break;
133         }
134         free(sexpr);
135
136         *sexprp = NULL;
137 }
138
139 static isc_boolean_t
140 printable(isccc_region_t *r)
141 {
142         unsigned char *curr;
143
144         curr = r->rstart;
145         while (curr != r->rend) {
146                 if (!isprint(*curr))
147                         return (ISC_FALSE);
148                 curr++;
149         }
150
151         return (ISC_TRUE);
152 }
153
154 void
155 isccc_sexpr_print(isccc_sexpr_t *sexpr, FILE *stream)
156 {
157         isccc_sexpr_t *cdr;
158         unsigned int size, i;
159         unsigned char *curr;
160
161         if (sexpr == NULL) {
162                 fprintf(stream, "nil");
163                 return;
164         }
165
166         switch (sexpr->type) {
167         case ISCCC_SEXPRTYPE_T:
168                 fprintf(stream, "t");
169                 break;
170         case ISCCC_SEXPRTYPE_STRING:
171                 fprintf(stream, "\"%s\"", sexpr->value.as_string);
172                 break;
173         case ISCCC_SEXPRTYPE_DOTTEDPAIR:
174                 fprintf(stream, "(");
175                 do {
176                         isccc_sexpr_print(CAR(sexpr), stream);
177                         cdr = CDR(sexpr);
178                         if (cdr != NULL) {
179                                 fprintf(stream, " ");
180                                 if (cdr->type != ISCCC_SEXPRTYPE_DOTTEDPAIR) {
181                                         fprintf(stream, ". ");
182                                         isccc_sexpr_print(cdr, stream);
183                                         cdr = NULL;
184                                 }
185                         }
186                         sexpr = cdr;
187                 } while (sexpr != NULL);
188                 fprintf(stream, ")");
189                 break;
190         case ISCCC_SEXPRTYPE_BINARY:
191                 size = REGION_SIZE(sexpr->value.as_region);
192                 curr = sexpr->value.as_region.rstart;
193                 if (printable(&sexpr->value.as_region)) {
194                         fprintf(stream, "'%.*s'", (int)size, curr);
195                 } else {
196                         fprintf(stream, "0x");
197                         for (i = 0; i < size; i++)
198                                 fprintf(stream, "%02x", *curr++);
199                 }
200                 break;
201         default:
202                 INSIST(0);
203         }
204 }
205
206 isccc_sexpr_t *
207 isccc_sexpr_car(isccc_sexpr_t *list)
208 {
209         REQUIRE(list->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
210
211         return (CAR(list));
212 }
213
214 isccc_sexpr_t *
215 isccc_sexpr_cdr(isccc_sexpr_t *list)
216 {
217         REQUIRE(list->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
218
219         return (CDR(list));
220 }
221
222 void
223 isccc_sexpr_setcar(isccc_sexpr_t *pair, isccc_sexpr_t *car)
224 {
225         REQUIRE(pair->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
226
227         CAR(pair) = car;
228 }
229
230 void
231 isccc_sexpr_setcdr(isccc_sexpr_t *pair, isccc_sexpr_t *cdr)
232 {
233         REQUIRE(pair->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
234
235         CDR(pair) = cdr;
236 }
237
238 isccc_sexpr_t *
239 isccc_sexpr_addtolist(isccc_sexpr_t **l1p, isccc_sexpr_t *l2)
240 {
241         isccc_sexpr_t *last, *elt, *l1;
242
243         REQUIRE(l1p != NULL);
244         l1 = *l1p;
245         REQUIRE(l1 == NULL || l1->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
246
247         elt = isccc_sexpr_cons(l2, NULL);
248         if (elt == NULL)
249                 return (NULL);
250         if (l1 == NULL) {
251                 *l1p = elt;
252                 return (elt);
253         }
254         for (last = l1; CDR(last) != NULL; last = CDR(last))
255                 /* Nothing */;
256         CDR(last) = elt;
257
258         return (elt);
259 }
260
261 isc_boolean_t
262 isccc_sexpr_listp(isccc_sexpr_t *sexpr)
263 {
264         if (sexpr == NULL || sexpr->type == ISCCC_SEXPRTYPE_DOTTEDPAIR)
265                 return (ISC_TRUE);
266         return (ISC_FALSE);
267 }
268
269 isc_boolean_t
270 isccc_sexpr_emptyp(isccc_sexpr_t *sexpr)
271 {
272         if (sexpr == NULL)
273                 return (ISC_TRUE);
274         return (ISC_FALSE);
275 }
276
277 isc_boolean_t
278 isccc_sexpr_stringp(isccc_sexpr_t *sexpr)
279 {
280         if (sexpr != NULL && sexpr->type == ISCCC_SEXPRTYPE_STRING)
281                 return (ISC_TRUE);
282         return (ISC_FALSE);
283 }
284
285 isc_boolean_t
286 isccc_sexpr_binaryp(isccc_sexpr_t *sexpr)
287 {
288         if (sexpr != NULL && sexpr->type == ISCCC_SEXPRTYPE_BINARY)
289                 return (ISC_TRUE);
290         return (ISC_FALSE);
291 }
292
293 char *
294 isccc_sexpr_tostring(isccc_sexpr_t *sexpr)
295 {
296         REQUIRE(sexpr != NULL &&
297                 (sexpr->type == ISCCC_SEXPRTYPE_STRING ||
298                  sexpr->type == ISCCC_SEXPRTYPE_BINARY));
299         
300         if (sexpr->type == ISCCC_SEXPRTYPE_BINARY)
301                 return ((char *)sexpr->value.as_region.rstart);
302         return (sexpr->value.as_string);
303 }
304
305 isccc_region_t *
306 isccc_sexpr_tobinary(isccc_sexpr_t *sexpr)
307 {
308         REQUIRE(sexpr != NULL && sexpr->type == ISCCC_SEXPRTYPE_BINARY);
309         return (&sexpr->value.as_region);
310 }