Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / nettle / tools / input.c
blob2069e07c03af7157b3ac2f124d09a6b312275edb
1 /* input.c */
3 /* nettle, low-level cryptographics library
5 * Copyright (C) 2002, 2003 Niels Möller
6 *
7 * The nettle library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or (at your
10 * option) any later version.
12 * The nettle library is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with the nettle library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 * MA 02111-1301, USA.
23 #if HAVE_CONFIG_H
24 # include "config.h"
25 #endif
27 #include <assert.h>
28 #include <errno.h>
29 #include <stdlib.h>
30 #include <string.h>
32 #include "input.h"
34 void
35 sexp_input_init(struct sexp_input *input, FILE *f)
37 input->f = f;
38 input->coding = NULL;
41 static void
42 sexp_get_raw_char(struct sexp_input *input)
44 int c = getc(input->f);
46 if (c < 0)
48 if (ferror(input->f))
49 die("Read error: %s\n", strerror(errno));
51 input->ctype = SEXP_EOF_CHAR;
53 else
55 input->ctype = SEXP_NORMAL_CHAR;
56 input->c = c;
60 void
61 sexp_get_char(struct sexp_input *input)
63 if (input->coding)
64 for (;;)
66 unsigned done;
68 sexp_get_raw_char(input);
69 if (input->ctype == SEXP_EOF_CHAR)
70 die("Unexpected end of file in coded data.\n");
72 if (input->c == input->terminator)
74 input->ctype = SEXP_END_CHAR;
75 return;
78 done = 1;
80 /* Decodes in place. Should always work, when we decode one
81 * character at a time. */
82 if (!input->coding->decode_update(&input->state,
83 &done, &input->c,
84 1, &input->c))
85 die("Invalid coded data.\n");
87 if (done)
88 return;
90 else
91 sexp_get_raw_char(input);
94 static uint8_t
95 sexp_next_char(struct sexp_input *input)
97 sexp_get_char(input);
98 if (input->ctype != SEXP_NORMAL_CHAR)
99 die("Unexpected end of file.\n");
101 return input->c;
104 static void
105 sexp_push_char(struct sexp_input *input,
106 struct nettle_buffer *string)
108 assert(input->ctype == SEXP_NORMAL_CHAR);
110 if (!NETTLE_BUFFER_PUTC(string, input->c))
111 die("Virtual memory exhasuted.\n");
114 static void
115 sexp_input_start_coding(struct sexp_input *input,
116 const struct nettle_armor *coding,
117 uint8_t terminator)
119 assert(!input->coding);
121 input->coding = coding;
122 input->coding->decode_init(&input->state);
123 input->terminator = terminator;
126 static void
127 sexp_input_end_coding(struct sexp_input *input)
129 assert(input->coding);
131 if (!input->coding->decode_final(&input->state))
132 die("Invalid coded data.\n");
134 input->coding = NULL;
138 /* Return 0 at end-of-string */
139 static int
140 sexp_get_quoted_char(struct sexp_input *input)
142 sexp_next_char(input);
144 for (;;)
145 switch (input->c)
147 default:
148 return 1;
149 case '\"':
150 return 0;
151 case '\\':
152 sexp_next_char(input);
154 switch (input->c)
156 case 'b': input->c = '\b'; return 1;
157 case 't': input->c = '\t'; return 1;
158 case 'n': input->c = '\n'; return 1;
159 case 'f': input->c = '\f'; return 1;
160 case 'r': input->c = '\r'; return 1;
161 case '\\': input->c = '\\'; return 1;
162 case 'o':
163 case 'x':
164 /* FIXME: Not implemnted */
165 abort();
166 case '\n':
167 if (sexp_next_char(input) == '\r')
168 sexp_next_char(input);
170 break;
171 case '\r':
172 if (sexp_next_char(input) == '\n')
173 sexp_next_char(input);
175 break;
177 return 1;
181 static void
182 sexp_get_token_string(struct sexp_input *input,
183 struct nettle_buffer *string)
185 assert(!input->coding);
186 assert(input->ctype == SEXP_NORMAL_CHAR);
188 if (!TOKEN_CHAR(input->c))
189 die("Invalid token.\n");
193 sexp_push_char(input, string);
194 sexp_get_char(input);
196 while (input->ctype == SEXP_NORMAL_CHAR && TOKEN_CHAR(input->c));
198 assert (string->size);
201 static void
202 sexp_get_string(struct sexp_input *input,
203 struct nettle_buffer *string)
205 nettle_buffer_reset(string);
206 input->token = SEXP_STRING;
208 switch (input->c)
210 case '\"':
211 while (sexp_get_quoted_char(input))
212 sexp_push_char(input, string);
214 sexp_get_char(input);
215 break;
217 case '#':
218 sexp_input_start_coding(input, &nettle_base16, '#');
219 goto decode;
221 case '|':
222 sexp_input_start_coding(input, &nettle_base64, '|');
224 decode:
225 for (;;)
227 sexp_get_char(input);
228 switch (input->ctype)
230 case SEXP_NORMAL_CHAR:
231 sexp_push_char(input, string);
232 break;
233 case SEXP_EOF_CHAR:
234 die("Unexpected end of file in coded string.\n");
235 case SEXP_END_CHAR:
236 sexp_input_end_coding(input);
237 sexp_get_char(input);
238 return;
242 break;
244 default:
245 sexp_get_token_string(input, string);
246 break;
250 static void
251 sexp_get_string_length(struct sexp_input *input, enum sexp_mode mode,
252 struct nettle_buffer *string)
254 unsigned length;
256 nettle_buffer_reset(string);
257 input->token = SEXP_STRING;
259 length = input->c - '0';
261 if (!length)
262 /* There must be no more digits */
263 sexp_next_char(input);
265 else
267 assert(length < 10);
268 /* Get rest of digits */
269 for (;;)
271 sexp_next_char(input);
273 if (input->c < '0' || input->c > '9')
274 break;
276 /* FIXME: Check for overflow? */
277 length = length * 10 + input->c - '0';
281 switch(input->c)
283 case ':':
284 /* Verbatim */
285 for (; length; length--)
287 sexp_next_char(input);
288 sexp_push_char(input, string);
291 break;
293 case '"':
294 if (mode != SEXP_ADVANCED)
295 die("Encountered quoted string in canonical mode.\n");
297 for (; length; length--)
298 if (sexp_get_quoted_char(input))
299 sexp_push_char(input, string);
300 else
301 die("Unexpected end of string.\n");
303 if (sexp_get_quoted_char(input))
304 die("Quoted string longer than expected.\n");
306 break;
308 case '#':
309 sexp_input_start_coding(input, &nettle_base16, '#');
310 goto decode;
312 case '|':
313 sexp_input_start_coding(input, &nettle_base64, '|');
315 decode:
316 for (; length; length--)
318 sexp_next_char(input);
319 sexp_push_char(input, string);
321 sexp_get_char(input);
322 if (input->ctype != SEXP_END_CHAR)
323 die("Coded string too long.\n");
325 sexp_input_end_coding(input);
327 break;
329 default:
330 die("Invalid string.\n");
333 /* Skip the ending character. */
334 sexp_get_char(input);
337 static void
338 sexp_get_comment(struct sexp_input *input, struct nettle_buffer *string)
340 nettle_buffer_reset(string);
342 assert(input->ctype == SEXP_NORMAL_CHAR);
343 assert(input->c == ';');
347 sexp_push_char(input, string);
348 sexp_get_raw_char(input);
350 while (input->ctype == SEXP_NORMAL_CHAR && input->c != '\n');
352 input->token = SEXP_COMMENT;
355 /* When called, input->c should be the first character of the current
356 * token.
358 * When returning, input->c should be the first character of the next
359 * token. */
360 void
361 sexp_get_token(struct sexp_input *input, enum sexp_mode mode,
362 struct nettle_buffer *string)
364 for(;;)
365 switch(input->ctype)
367 case SEXP_EOF_CHAR:
368 input->token = SEXP_EOF;
369 return;
371 case SEXP_END_CHAR:
372 input->token = SEXP_CODING_END;
373 sexp_input_end_coding(input);
374 sexp_get_char(input);
375 return;
377 case SEXP_NORMAL_CHAR:
378 switch(input->c)
380 case '0': case '1': case '2': case '3': case '4':
381 case '5': case '6': case '7': case '8': case '9':
382 sexp_get_string_length(input, mode, string);
383 return;
385 case '(':
386 input->token = SEXP_LIST_START;
387 sexp_get_char(input);
388 return;
390 case ')':
391 input->token = SEXP_LIST_END;
392 sexp_get_char(input);
393 return;
395 case '[':
396 input->token = SEXP_DISPLAY_START;
397 sexp_get_char(input);
398 return;
400 case ']':
401 input->token = SEXP_DISPLAY_END;
402 sexp_get_char(input);
403 return;
405 case '{':
406 if (mode == SEXP_CANONICAL)
407 die("Unexpected transport data in canonical mode.\n");
409 sexp_input_start_coding(input, &nettle_base64, '}');
410 sexp_get_char(input);
412 input->token = SEXP_TRANSPORT_START;
414 return;
416 case ' ': /* SPC, TAB, LF, CR */
417 case '\t':
418 case '\n':
419 case '\r':
420 if (mode == SEXP_CANONICAL)
421 die("Whitespace encountered in canonical mode.\n");
423 sexp_get_char(input);
424 break;
426 case ';': /* Comments */
427 if (mode == SEXP_CANONICAL)
428 die("Comment encountered in canonical mode.\n");
430 sexp_get_comment(input, string);
431 return;
433 default:
434 /* Ought to be a string */
435 if (mode != SEXP_ADVANCED)
436 die("Encountered advanced string in canonical mode.\n");
438 sexp_get_string(input, string);
439 return;