tizen 2.4 release
[external/nettle.git] / tools / parse.c
1 /* parse.c */
2
3 /* nettle, low-level cryptographics library
4  *
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.
11  * 
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.
16  * 
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.
21  */
22
23 #if HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #include <assert.h>
28 #include <stdlib.h>
29
30 #include "parse.h"
31
32 #include "input.h"
33
34 void
35 sexp_compound_token_init(struct sexp_compound_token *token)
36 {
37   token->type = 0;
38   nettle_buffer_init(&token->display);
39   nettle_buffer_init(&token->string);
40 }
41
42 void
43 sexp_compound_token_clear(struct sexp_compound_token *token)
44 {
45   nettle_buffer_clear(&token->display);
46   nettle_buffer_clear(&token->string);
47 }
48
49 void
50 sexp_parse_init(struct sexp_parser *parser,
51                 struct sexp_input *input,
52                 enum sexp_mode mode)
53 {
54   parser->input = input;
55   parser->mode = mode;
56
57   /* Start counting with 1 for the top level, to make comparisons
58    * between transport and level simpler.
59    *
60    * FIXME: Is that trick ugly? */
61   parser->level = 1;
62   parser->transport = 0;
63 }
64
65 /* Get next token, and check that it is of the expected kind. */
66 static void
67 sexp_check_token(struct sexp_parser *parser,
68                  enum sexp_token token,
69                  struct nettle_buffer *string)
70 {
71   sexp_get_token(parser->input,
72                  parser->transport ? SEXP_CANONICAL : parser->mode,
73                  string);
74
75   if (parser->input->token != token)
76     die("Syntax error.\n");
77 }
78
79 /* Performs further processing of the input, in particular display
80  * types and transport decoding.
81  *
82  * This is complicated a little by the requirement that a
83  * transport-encoded block, {xxxxx}, must include exactly one
84  * expression. We check at the end of strings and list whether or not
85  * we should expect a SEXP_CODING_END as the next token. */
86 void
87 sexp_parse(struct sexp_parser *parser,
88            struct sexp_compound_token *token)
89 {
90   for (;;)
91     {
92       sexp_get_token(parser->input,
93                      parser->transport ? SEXP_CANONICAL : parser->mode,
94                      &token->string);
95
96       switch(parser->input->token)
97         {
98         case SEXP_LIST_END:
99           if (parser->level == parser->transport)
100             die("Unmatched end of list in transport encoded data.\n");
101           parser->level--;
102
103           if (!parser->level)
104             die("Unmatched end of list.\n");
105
106           token->type = SEXP_LIST_END;
107
108         check_transport_end:
109           if (parser->level == parser->transport)
110             {
111               sexp_check_token(parser, SEXP_CODING_END, &token->string);
112               assert(parser->transport);
113               assert(parser->level == parser->transport);
114
115               parser->level--;
116               parser->transport = 0;
117             }
118           return;
119     
120         case SEXP_EOF:
121           if (parser->level > 1)
122             die("Unexpected end of file.\n");
123
124           token->type = SEXP_EOF;
125           return;
126
127         case SEXP_LIST_START:
128           parser->level++;
129           token->type = SEXP_LIST_START;
130           return;
131
132         case SEXP_DISPLAY_START:
133           sexp_check_token(parser, SEXP_STRING, &token->display);
134           sexp_check_token(parser, SEXP_DISPLAY_END, &token->display);
135           sexp_check_token(parser, SEXP_STRING, &token->string);
136
137           token->type = SEXP_DISPLAY;
138           goto check_transport_end;
139
140         case SEXP_STRING:
141           token->type = SEXP_STRING;
142           goto check_transport_end;
143
144         case SEXP_COMMENT:
145           token->type = SEXP_COMMENT;
146           return;
147
148         case SEXP_TRANSPORT_START:
149           if (parser->mode == SEXP_CANONICAL)
150             die("Base64 not allowed in canonical mode.\n");
151           parser->level++;
152           parser->transport = parser->level;
153
154           continue;
155
156         case SEXP_CODING_END:
157           die("Unexpected end of transport encoding.\n");
158           
159         default:
160           /* Internal error. */
161           abort();
162         }
163     }
164 }