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
);