BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file NCDValParser.c
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29  
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33  
34 #include <base/BLog.h>
35 #include <ncd/NCDConfigTokenizer.h>
36 #include <ncd/NCDValCons.h>
37  
38 #include "NCDValParser.h"
39  
40 #include <generated/blog_channel_NCDValParser.h>
41  
42 struct token {
43 char *str;
44 size_t len;
45 };
46  
47 struct value {
48 int have;
49 NCDValConsVal v;
50 };
51  
52 #define ERROR_FLAG_MEMORY (1 << 0)
53 #define ERROR_FLAG_TOKENIZATION (1 << 1)
54 #define ERROR_FLAG_SYNTAX (1 << 2)
55 #define ERROR_FLAG_DUPLICATE_KEY (1 << 3)
56 #define ERROR_FLAG_DEPTH (1 << 4)
57  
58 struct parser_state {
59 NCDValCons cons;
60 NCDValRef value;
61 int cons_error;
62 int error_flags;
63 void *parser;
64 };
65  
66 static void free_token (struct token o)
67 {
68 if (o.str) {
69 free(o.str);
70 }
71 };
72  
73 static void handle_cons_error (struct parser_state *state)
74 {
75 switch (state->cons_error) {
76 case NCDVALCONS_ERROR_MEMORY:
77 state->error_flags |= ERROR_FLAG_MEMORY;
78 break;
79 case NCDVALCONS_ERROR_DUPLICATE_KEY:
80 state->error_flags |= ERROR_FLAG_DUPLICATE_KEY;
81 break;
82 case NCDVALCONS_ERROR_DEPTH:
83 state->error_flags |= ERROR_FLAG_DEPTH;
84 break;
85 default:
86 ASSERT(0);
87 }
88 }
89  
90 // rename non-static functions defined by our Lemon parser
91 // to avoid clashes with other Lemon parsers
92 #define ParseTrace ParseTrace_NCDValParser
93 #define ParseAlloc ParseAlloc_NCDValParser
94 #define ParseFree ParseFree_NCDValParser
95 #define Parse Parse_NCDValParser
96  
97 // include the generated Lemon parser
98 #include "../generated/NCDValParser_parse.c"
99 #include "../generated/NCDValParser_parse.h"
100  
101 static int tokenizer_output (void *user, int token, char *value, size_t value_len, size_t line, size_t line_char)
102 {
103 struct parser_state *state = user;
104 ASSERT(!state->error_flags)
105  
106 if (token == NCD_ERROR) {
107 state->error_flags |= ERROR_FLAG_TOKENIZATION;
108 goto fail;
109 }
110  
111 struct token minor;
112 minor.str = value;
113 minor.len = value_len;
114  
115 switch (token) {
116 case NCD_EOF: {
117 Parse(state->parser, 0, minor, state);
118 } break;
119  
120 case NCD_TOKEN_CURLY_OPEN: {
121 Parse(state->parser, CURLY_OPEN, minor, state);
122 } break;
123  
124 case NCD_TOKEN_CURLY_CLOSE: {
125 Parse(state->parser, CURLY_CLOSE, minor, state);
126 } break;
127  
128 case NCD_TOKEN_COMMA: {
129 Parse(state->parser, COMMA, minor, state);
130 } break;
131  
132 case NCD_TOKEN_STRING: {
133 Parse(state->parser, STRING, minor, state);
134 } break;
135  
136 case NCD_TOKEN_COLON: {
137 Parse(state->parser, COLON, minor, state);
138 } break;
139  
140 case NCD_TOKEN_BRACKET_OPEN: {
141 Parse(state->parser, BRACKET_OPEN, minor, state);
142 } break;
143  
144 case NCD_TOKEN_BRACKET_CLOSE: {
145 Parse(state->parser, BRACKET_CLOSE, minor, state);
146 } break;
147  
148 default:
149 state->error_flags |= ERROR_FLAG_TOKENIZATION;
150 free_token(minor);
151 goto fail;
152 }
153  
154 if (state->error_flags) {
155 goto fail;
156 }
157  
158 return 1;
159  
160 fail:
161 ASSERT(state->error_flags)
162  
163 if ((state->error_flags & ERROR_FLAG_MEMORY)) {
164 BLog(BLOG_ERROR, "line %zu, character %zu: memory allocation error", line, line_char);
165 }
166  
167 if ((state->error_flags & ERROR_FLAG_TOKENIZATION)) {
168 BLog(BLOG_ERROR, "line %zu, character %zu: tokenization error", line, line_char);
169 }
170  
171 if ((state->error_flags & ERROR_FLAG_SYNTAX)) {
172 BLog(BLOG_ERROR, "line %zu, character %zu: syntax error", line, line_char);
173 }
174  
175 if ((state->error_flags & ERROR_FLAG_DUPLICATE_KEY)) {
176 BLog(BLOG_ERROR, "line %zu, character %zu: duplicate key in map error", line, line_char);
177 }
178  
179 if ((state->error_flags & ERROR_FLAG_DEPTH)) {
180 BLog(BLOG_ERROR, "line %zu, character %zu: depth limit exceeded", line, line_char);
181 }
182  
183 return 0;
184 }
185  
186 int NCDValParser_Parse (MemRef str, NCDValMem *mem, NCDValRef *out_value)
187 {
188 ASSERT(str.len == 0 || str.ptr)
189 ASSERT(mem)
190 ASSERT(out_value)
191  
192 int ret = 0;
193  
194 struct parser_state state;
195 state.value = NCDVal_NewInvalid();
196 state.error_flags = 0;
197  
198 if (!NCDValCons_Init(&state.cons, mem)) {
199 BLog(BLOG_ERROR, "NCDValCons_Init failed");
200 goto fail0;
201 }
202  
203 if (!(state.parser = ParseAlloc(malloc))) {
204 BLog(BLOG_ERROR, "ParseAlloc failed");
205 goto fail1;
206 }
207  
208 NCDConfigTokenizer_Tokenize(str, tokenizer_output, &state);
209  
210 ParseFree(state.parser, free);
211  
212 if (state.error_flags) {
213 goto fail1;
214 }
215  
216 ASSERT(!NCDVal_IsInvalid(state.value))
217  
218 *out_value = state.value;
219 ret = 1;
220  
221 fail1:
222 NCDValCons_Free(&state.cons);
223 fail0:
224 return ret;
225 }