awk: Add our README files
[dragonfly.git] / contrib / ldns / parse.c
1 /*
2  * a generic (simple) parser. Use to parse rr's, private key 
3  * information and /etc/resolv.conf files
4  *
5  * a Net::DNS like library for C
6  * LibDNS Team @ NLnet Labs
7  * (c) NLnet Labs, 2005-2006
8  * See the file LICENSE for the license
9  */
10 #include <ldns/config.h>
11 #include <ldns/ldns.h>
12
13 #include <limits.h>
14 #include <strings.h>
15
16 ldns_lookup_table ldns_directive_types[] = {
17         { LDNS_DIR_TTL, "$TTL" },  
18         { LDNS_DIR_ORIGIN, "$ORIGIN" }, 
19         { LDNS_DIR_INCLUDE, "$INCLUDE" },  
20         { 0, NULL }
21 };
22
23 /* add max_limit here? */
24 ssize_t
25 ldns_fget_token(FILE *f, char *token, const char *delim, size_t limit)
26 {       
27         return ldns_fget_token_l(f, token, delim, limit, NULL);
28 }
29
30 ssize_t
31 ldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *line_nr)
32 {       
33         int c, prev_c;
34         int p; /* 0 -> no parenthese seen, >0 nr of ( seen */
35         int com, quoted;
36         char *t;
37         size_t i;
38         const char *d;
39         const char *del;
40
41         /* standard delimeters */
42         if (!delim) {
43                 /* from isspace(3) */
44                 del = LDNS_PARSE_NORMAL;
45         } else {
46                 del = delim;
47         }
48
49         p = 0;
50         i = 0;
51         com = 0;
52         quoted = 0;
53         prev_c = 0;
54         t = token;
55         if (del[0] == '"') {
56                 quoted = 1;
57         }
58         while ((c = getc(f)) != EOF) {
59                 if (c == '(' && prev_c != '\\' && !quoted) {
60                         /* this only counts for non-comments */
61                         if (com == 0) {
62                                 p++;
63                         }
64                         prev_c = c;
65                         continue;
66                 }
67
68                 if (c == ')' && prev_c != '\\' && !quoted) {
69                         /* this only counts for non-comments */
70                         if (com == 0) {
71                                 p--;
72                         }
73                         prev_c = c;
74                         continue;
75                 }
76
77                 if (p < 0) {
78                         /* more ) then ( - close off the string */
79                         *t = '\0';
80                         return 0;
81                 }
82
83                 /* do something with comments ; */
84                 if (c == ';' && quoted == 0) {
85                         if (prev_c != '\\') {
86                                 com = 1;
87                         }
88                 }
89                 if (c == '\"' && com == 0 && prev_c != '\\') {
90                         quoted = 1 - quoted;
91                 }
92
93                 if (c == '\n' && com != 0) {
94                         /* comments */
95                         com = 0;
96                         *t = ' ';
97                         if (line_nr) {
98                                 *line_nr = *line_nr + 1;
99                         }
100                         if (p == 0 && i > 0) {
101                                 goto tokenread;
102                         } else {
103                                 prev_c = c;
104                                 continue;
105                         }
106                 }
107
108                 if (com == 1) {
109                         *t = ' ';
110                         prev_c = c;
111                         continue;
112                 }
113
114                 
115                 if (c == '\n' && p != 0 && t > token) {
116                         /* in parentheses */
117                         if (line_nr) {
118                                 *line_nr = *line_nr + 1;
119                         }
120                         prev_c = c;
121                         continue;
122                 }
123
124                 /* check if we hit the delim */
125                 for (d = del; *d; d++) {
126                         if (c == *d && i > 0 && prev_c != '\\') {
127                                 if (c == '\n' && line_nr) {
128                                         *line_nr = *line_nr + 1;
129                                 }
130                                 goto tokenread;
131                         }
132                 }
133                 if (c != '\0' && c != '\n') {
134                         *t++ = c;
135                         i++;
136                 }
137                 if (limit > 0 && i >= limit) {
138                         *t = '\0';
139                         return -1;
140                 }
141                 if (c == '\\' && prev_c == '\\')
142                         prev_c = 0;
143                 else    prev_c = c;
144         }
145         *t = '\0';
146         if (c == EOF) {
147                 return (ssize_t)i;
148         }
149
150         if (i == 0) {
151                 /* nothing read */
152                 return -1;
153         }
154         if (p != 0) {
155                 return -1;
156         }
157         return (ssize_t)i;
158
159 tokenread:
160         ldns_fskipcs_l(f, delim, line_nr);
161         *t = '\0';
162         if (p != 0) {
163                 return -1;
164         }
165
166         return (ssize_t)i;
167 }
168
169 ssize_t
170 ldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data,
171                const char *d_del, size_t data_limit)
172 {
173        return ldns_fget_keyword_data_l(f, keyword, k_del, data, d_del, 
174                        data_limit, NULL);
175 }
176
177 ssize_t
178 ldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char *data,
179                const char *d_del, size_t data_limit, int *line_nr)
180 {
181        /* we assume: keyword|sep|data */
182        char *fkeyword;
183        ssize_t i;
184
185        fkeyword = LDNS_XMALLOC(char, LDNS_MAX_KEYWORDLEN);
186        i = 0;
187
188        i = ldns_fget_token(f, fkeyword, k_del, LDNS_MAX_KEYWORDLEN);
189
190        /* case??? i instead of strlen? */
191        if (strncmp(fkeyword, keyword, LDNS_MAX_KEYWORDLEN - 1) == 0) {
192                /* whee! */
193                /* printf("%s\n%s\n", "Matching keyword", fkeyword); */
194                i = ldns_fget_token_l(f, data, d_del, data_limit, line_nr);
195                LDNS_FREE(fkeyword);
196                return i;
197        } else {
198                /*printf("no match for %s (read: %s)\n", keyword, fkeyword);*/
199                LDNS_FREE(fkeyword);
200                return -1;
201        }
202 }
203
204
205 ssize_t
206 ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit)
207 {       
208         int c, lc;
209         int p; /* 0 -> no parenthese seen, >0 nr of ( seen */
210         int com, quoted;
211         char *t;
212         size_t i;
213         const char *d;
214         const char *del;
215
216         /* standard delimiters */
217         if (!delim) {
218                 /* from isspace(3) */
219                 del = LDNS_PARSE_NORMAL;
220         } else {
221                 del = delim;
222         }
223
224         p = 0;
225         i = 0;
226         com = 0;
227         quoted = 0;
228         t = token;
229         lc = 0;
230         if (delim[0] == '"') {
231                 quoted = 1;
232         }
233
234         while ((c = ldns_bgetc(b)) != EOF) {
235                 if (c == '(' && lc != '\\' && !quoted) {
236                         /* this only counts for non-comments */
237                         if (com == 0) {
238                                 p++;
239                         }
240                         lc = c;
241                         continue;
242                 }
243
244                 if (c == ')' && lc != '\\' && !quoted) {
245                         /* this only counts for non-comments */
246                         if (com == 0) {
247                                 p--;
248                         }
249                         lc = c;
250                         continue;
251                 }
252
253                 if (p < 0) {
254                         /* more ) then ( */
255                         *t = '\0';
256                         lc = c;
257                         return 0;
258                 }
259
260                 /* do something with comments ; */
261                 if (c == ';' && quoted == 0) {
262                         if (lc != '\\') {
263                                 com = 1;
264                         }
265                 }
266                 if (c == '"' && com == 0 && lc != '\\') {
267                         quoted = 1 - quoted;
268                 }
269
270                 if (c == '\n' && com != 0) {
271                         /* comments */
272                         com = 0;
273                         *t = ' ';
274                         lc = c;
275                         continue;
276                 }
277
278                 if (com == 1) {
279                         *t = ' ';
280                         lc = c;
281                         continue;
282                 }
283
284                 if (c == '\n' && p != 0) {
285                         /* in parentheses */
286                         lc = c;
287                         continue;
288                 }
289
290                 /* check if we hit the delim */
291                 for (d = del; *d; d++) {
292                         if (c == *d && lc != '\\') {
293                                 goto tokenread;
294                         }
295                 }
296                 
297                 *t++ = c;
298                 i++;
299                 if (limit > 0 && i >= limit - 1) {
300                         *t = '\0';
301                         return -1;
302                 }
303
304                 if (c == '\\' && lc == '\\') {
305                         lc = 0;
306                 } else {
307                         lc = c;
308                 }
309         }
310         *t = '\0';
311         if (i == 0) {
312                 /* nothing read */
313                 return -1;
314         }
315         if (p != 0) {
316                 return -1;
317         }
318         return (ssize_t)i;
319
320 tokenread:
321         ldns_bskipcs(b, delim);
322         *t = '\0';
323         
324         if (p != 0) {
325                 return -1; 
326         }
327         return (ssize_t)i;
328 }
329
330 void
331 ldns_bskipc(ldns_buffer *buffer, char c)
332 {
333         while (c == (char) ldns_buffer_read_u8_at(buffer, ldns_buffer_position(buffer))) {
334                 if (ldns_buffer_available_at(buffer, 
335                                         buffer->_position + sizeof(char), sizeof(char))) {
336                         buffer->_position += sizeof(char);
337                 } else {
338                         return;
339                 }
340         }
341 }
342
343 void
344 ldns_bskipcs(ldns_buffer *buffer, const char *s)
345 {
346         bool found;
347         char c;
348         const char *d;
349
350         while(ldns_buffer_available_at(buffer, buffer->_position, sizeof(char))) {
351                 c = (char) ldns_buffer_read_u8_at(buffer, buffer->_position);
352                 found = false;
353                 for (d = s; *d; d++) {
354                         if (*d == c) {
355                                 found = true;
356                         }
357                 }
358                 if (found && buffer->_limit > buffer->_position) {
359                         buffer->_position += sizeof(char);
360                 } else {
361                         return;
362                 }
363         }
364 }
365
366 void
367 ldns_fskipc(FILE *fp, char c)
368 {
369         fp = fp;
370         c = c;
371 }
372
373
374 void
375 ldns_fskipcs(FILE *fp, const char *s)
376 {
377         ldns_fskipcs_l(fp, s, NULL);
378 }
379
380 void
381 ldns_fskipcs_l(FILE *fp, const char *s, int *line_nr)
382 {
383         bool found;
384         int c;
385         const char *d;
386
387         while ((c = fgetc(fp)) != EOF) {
388                 if (line_nr && c == '\n') {
389                         *line_nr = *line_nr + 1;
390                 }
391                 found = false;
392                 for (d = s; *d; d++) {
393                         if (*d == c) {
394                                 found = true;
395                         }
396                 }
397                 if (!found) {
398                         /* with getc, we've read too far */
399                         ungetc(c, fp);
400                         return;
401                 }
402         }
403 }
404
405 ssize_t
406 ldns_bget_keyword_data(ldns_buffer *b, const char *keyword, const char *k_del, char
407 *data, const char *d_del, size_t data_limit)
408 {
409        /* we assume: keyword|sep|data */
410        char *fkeyword;
411        ssize_t i;
412
413        fkeyword = LDNS_XMALLOC(char, LDNS_MAX_KEYWORDLEN);
414        i = 0;
415
416        i = ldns_bget_token(b, fkeyword, k_del, data_limit);
417
418        /* case??? */
419        if (strncmp(fkeyword, keyword, strlen(keyword)) == 0) {
420                /* whee, the match! */
421                /* retrieve it's data */
422                i = ldns_bget_token(b, data, d_del, 0);
423                return i;
424        } else {
425                return -1;
426        }
427 }
428