3 /* nettle, low-level cryptographics library
5 * Copyright (C) 2002, 2003 Niels Möller
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,
35 sexp_input_init(struct sexp_input *input, FILE *f)
42 sexp_get_raw_char(struct sexp_input *input)
44 int c = getc(input->f);
49 die("Read error: %s\n", strerror(errno));
51 input->ctype = SEXP_EOF_CHAR;
55 input->ctype = SEXP_NORMAL_CHAR;
61 sexp_get_char(struct sexp_input *input)
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;
80 /* Decodes in place. Should always work, when we decode one
81 * character at a time. */
82 if (!input->coding->decode_update(&input->state,
85 die("Invalid coded data.\n");
91 sexp_get_raw_char(input);
95 sexp_next_char(struct sexp_input *input)
98 if (input->ctype != SEXP_NORMAL_CHAR)
99 die("Unexpected end of file.\n");
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");
115 sexp_input_start_coding(struct sexp_input *input,
116 const struct nettle_armor *coding,
119 assert(!input->coding);
121 input->coding = coding;
122 input->coding->decode_init(&input->state);
123 input->terminator = terminator;
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 */
140 sexp_get_quoted_char(struct sexp_input *input)
142 sexp_next_char(input);
152 sexp_next_char(input);
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;
164 /* FIXME: Not implemnted */
167 if (sexp_next_char(input) == '\r')
168 sexp_next_char(input);
172 if (sexp_next_char(input) == '\n')
173 sexp_next_char(input);
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);
202 sexp_get_string(struct sexp_input *input,
203 struct nettle_buffer *string)
205 nettle_buffer_reset(string);
206 input->token = SEXP_STRING;
211 while (sexp_get_quoted_char(input))
212 sexp_push_char(input, string);
214 sexp_get_char(input);
218 sexp_input_start_coding(input, &nettle_base16, '#');
222 sexp_input_start_coding(input, &nettle_base64, '|');
227 sexp_get_char(input);
228 switch (input->ctype)
230 case SEXP_NORMAL_CHAR:
231 sexp_push_char(input, string);
234 die("Unexpected end of file in coded string.\n");
236 sexp_input_end_coding(input);
237 sexp_get_char(input);
245 sexp_get_token_string(input, string);
251 sexp_get_string_length(struct sexp_input *input, enum sexp_mode mode,
252 struct nettle_buffer *string)
256 nettle_buffer_reset(string);
257 input->token = SEXP_STRING;
259 length = input->c - '0';
262 /* There must be no more digits */
263 sexp_next_char(input);
268 /* Get rest of digits */
271 sexp_next_char(input);
273 if (input->c < '0' || input->c > '9')
276 /* FIXME: Check for overflow? */
277 length = length * 10 + input->c - '0';
285 for (; length; length--)
287 sexp_next_char(input);
288 sexp_push_char(input, string);
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);
301 die("Unexpected end of string.\n");
303 if (sexp_get_quoted_char(input))
304 die("Quoted string longer than expected.\n");
309 sexp_input_start_coding(input, &nettle_base16, '#');
313 sexp_input_start_coding(input, &nettle_base64, '|');
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);
330 die("Invalid string.\n");
333 /* Skip the ending character. */
334 sexp_get_char(input);
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
358 * When returning, input->c should be the first character of the next
361 sexp_get_token(struct sexp_input *input, enum sexp_mode mode,
362 struct nettle_buffer *string)
368 input->token = SEXP_EOF;
372 input->token = SEXP_CODING_END;
373 sexp_input_end_coding(input);
374 sexp_get_char(input);
377 case SEXP_NORMAL_CHAR:
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);
386 input->token = SEXP_LIST_START;
387 sexp_get_char(input);
391 input->token = SEXP_LIST_END;
392 sexp_get_char(input);
396 input->token = SEXP_DISPLAY_START;
397 sexp_get_char(input);
401 input->token = SEXP_DISPLAY_END;
402 sexp_get_char(input);
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;
416 case ' ': /* SPC, TAB, LF, CR */
420 if (mode == SEXP_CANONICAL)
421 die("Whitespace encountered in canonical mode.\n");
423 sexp_get_char(input);
426 case ';': /* Comments */
427 if (mode == SEXP_CANONICAL)
428 die("Comment encountered in canonical mode.\n");
430 sexp_get_comment(input, string);
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);