BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file NCDSugar.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 <stdlib.h>
31  
32 #include <misc/debug.h>
33  
34 #include "NCDSugar.h"
35  
36 struct desugar_state {
37 NCDProgram *prog;
38 size_t template_name_ctr;
39 };
40  
41 static int add_template (struct desugar_state *state, NCDBlock block, NCDValue *out_name_val);
42 static int desugar_block (struct desugar_state *state, NCDBlock *block);
43 static int desugar_if (struct desugar_state *state, NCDBlock *block, NCDStatement *stmt, NCDStatement **out_next);
44 static int desugar_do (struct desugar_state *state, NCDBlock *block, NCDStatement *stmt, NCDStatement **out_next);
45 static int desugar_foreach (struct desugar_state *state, NCDBlock *block, NCDStatement *stmt, NCDStatement **out_next);
46 static int desugar_blockstmt (struct desugar_state *state, NCDBlock *block, NCDStatement *stmt, NCDStatement **out_next);
47  
48 static int add_template (struct desugar_state *state, NCDBlock block, NCDValue *out_name_val)
49 {
50 char name[40];
51 snprintf(name, sizeof(name), "__tmpl%zu", state->template_name_ctr);
52 state->template_name_ctr++;
53  
54 if (!desugar_block(state, &block)) {
55 NCDBlock_Free(&block);
56 return 0;
57 }
58  
59 NCDProcess proc_tmp;
60 if (!NCDProcess_Init(&proc_tmp, 1, name, block)) {
61 NCDBlock_Free(&block);
62 return 0;
63 }
64  
65 NCDProgramElem elem;
66 NCDProgramElem_InitProcess(&elem, proc_tmp);
67  
68 if (!NCDProgram_PrependElem(state->prog, elem)) {
69 NCDProgramElem_Free(&elem);
70 return 0;
71 }
72  
73 if (!NCDValue_InitString(out_name_val, name)) {
74 return 0;
75 }
76  
77 return 1;
78 }
79  
80 static int desugar_block (struct desugar_state *state, NCDBlock *block)
81 {
82 NCDStatement *stmt = NCDBlock_FirstStatement(block);
83  
84 while (stmt) {
85 switch (NCDStatement_Type(stmt)) {
86 case NCDSTATEMENT_REG: {
87 stmt = NCDBlock_NextStatement(block, stmt);
88 } break;
89  
90 case NCDSTATEMENT_IF: {
91 int iftype = NCDStatement_IfType(stmt);
92  
93 int res = 0;
94 if (iftype == NCDIFTYPE_IF) {
95 res = desugar_if(state, block, stmt, &stmt);
96 } else if (iftype == NCDIFTYPE_DO) {
97 res = desugar_do(state, block, stmt, &stmt);
98 }
99  
100 if (!res) {
101 return 0;
102 }
103 } break;
104  
105 case NCDSTATEMENT_FOREACH: {
106 if (!desugar_foreach(state, block, stmt, &stmt)) {
107 return 0;
108 }
109 } break;
110  
111 case NCDSTATEMENT_BLOCK: {
112 if (!desugar_blockstmt(state, block, stmt, &stmt)) {
113 return 0;
114 }
115 } break;
116  
117 default: {
118 return 0;
119 } break;
120 }
121 }
122  
123 return 1;
124 }
125  
126 static int desugar_if (struct desugar_state *state, NCDBlock *block, NCDStatement *stmt, NCDStatement **out_next)
127 {
128 ASSERT(NCDStatement_Type(stmt) == NCDSTATEMENT_IF)
129 ASSERT(NCDStatement_IfType(stmt) == NCDIFTYPE_IF)
130  
131 NCDValue args;
132 NCDValue_InitList(&args);
133  
134 NCDIfBlock *ifblock = NCDStatement_IfBlock(stmt);
135  
136 while (NCDIfBlock_FirstIf(ifblock)) {
137 NCDIf ifc = NCDIfBlock_GrabIf(ifblock, NCDIfBlock_FirstIf(ifblock));
138  
139 NCDValue if_cond;
140 NCDBlock if_block;
141 NCDIf_FreeGrab(&ifc, &if_cond, &if_block);
142  
143 if (!NCDValue_ListAppend(&args, if_cond)) {
144 NCDValue_Free(&if_cond);
145 NCDBlock_Free(&if_block);
146 goto fail_args;
147 }
148  
149 NCDValue action_arg;
150 if (!add_template(state, if_block, &action_arg)) {
151 goto fail_args;
152 }
153  
154 if (!NCDValue_ListAppend(&args, action_arg)) {
155 NCDValue_Free(&action_arg);
156 goto fail_args;
157 }
158 }
159  
160 NCDValue action_arg;
161  
162 if (NCDStatement_IfElse(stmt)) {
163 NCDBlock else_block = NCDStatement_IfGrabElse(stmt);
164  
165 if (!add_template(state, else_block, &action_arg)) {
166 goto fail_args;
167 }
168 } else {
169 if (!NCDValue_InitString(&action_arg, "<none>")) {
170 goto fail_args;
171 }
172 }
173  
174 if (!NCDValue_ListAppend(&args, action_arg)) {
175 NCDValue_Free(&action_arg);
176 goto fail_args;
177 }
178  
179 NCDValue func;
180 if (!NCDValue_InitString(&func, "ifel")) {
181 goto fail_args;
182 }
183  
184 NCDValue invoc;
185 if (!NCDValue_InitInvoc(&invoc, func, args)) {
186 NCDValue_Free(&func);
187 goto fail_args;
188 }
189  
190 NCDValue stmt_args;
191 NCDValue_InitList(&stmt_args);
192  
193 if (!NCDValue_ListAppend(&stmt_args, invoc)) {
194 NCDValue_Free(&stmt_args);
195 NCDValue_Free(&invoc);
196 goto fail0;
197 }
198  
199 NCDStatement new_stmt;
200 if (!NCDStatement_InitReg(&new_stmt, NCDStatement_Name(stmt), NULL, "embcall", stmt_args)) {
201 NCDValue_Free(&stmt_args);
202 goto fail0;
203 }
204  
205 stmt = NCDBlock_ReplaceStatement(block, stmt, new_stmt);
206  
207 *out_next = NCDBlock_NextStatement(block, stmt);
208 return 1;
209  
210 fail_args:
211 NCDValue_Free(&args);
212 fail0:
213 return 0;
214 }
215  
216  
217 static int desugar_do (struct desugar_state *state, NCDBlock *block, NCDStatement *stmt, NCDStatement **out_next)
218 {
219 ASSERT(NCDStatement_Type(stmt) == NCDSTATEMENT_IF)
220 ASSERT(NCDStatement_IfType(stmt) == NCDIFTYPE_DO)
221  
222 NCDIfBlock *ifblock = NCDStatement_IfBlock(stmt);
223  
224 NCDValue stmt_args;
225 NCDValue_InitList(&stmt_args);
226  
227 while (NCDIfBlock_FirstIf(ifblock)) {
228 NCDIf the_if = NCDIfBlock_GrabIf(ifblock, NCDIfBlock_FirstIf(ifblock));
229 NCDBlock if_block = NCDIf_FreeGrabBlock(&the_if);
230  
231 NCDValue action_arg;
232 if (!add_template(state, if_block, &action_arg)) {
233 goto fail1;
234 }
235  
236 if (!NCDValue_ListAppend(&stmt_args, action_arg)) {
237 NCDValue_Free(&action_arg);
238 goto fail1;
239 }
240 }
241  
242 NCDStatement new_stmt;
243 if (!NCDStatement_InitReg(&new_stmt, NCDStatement_Name(stmt), NULL, "do", stmt_args)) {
244 goto fail1;
245 }
246  
247 stmt = NCDBlock_ReplaceStatement(block, stmt, new_stmt);
248  
249 *out_next = NCDBlock_NextStatement(block, stmt);
250 return 1;
251  
252 fail1:
253 NCDValue_Free(&stmt_args);
254 return 0;
255 }
256  
257 static int desugar_foreach (struct desugar_state *state, NCDBlock *block, NCDStatement *stmt, NCDStatement **out_next)
258 {
259 ASSERT(NCDStatement_Type(stmt) == NCDSTATEMENT_FOREACH)
260  
261 NCDValue args;
262 NCDValue_InitList(&args);
263  
264 NCDValue collection;
265 NCDBlock foreach_block;
266 NCDStatement_ForeachGrab(stmt, &collection, &foreach_block);
267  
268 NCDValue template_arg;
269 if (!add_template(state, foreach_block, &template_arg)) {
270 NCDValue_Free(&collection);
271 goto fail;
272 }
273  
274 if (!NCDValue_ListAppend(&args, collection)) {
275 NCDValue_Free(&template_arg);
276 NCDValue_Free(&collection);
277 goto fail;
278 }
279  
280 if (!NCDValue_ListAppend(&args, template_arg)) {
281 NCDValue_Free(&template_arg);
282 goto fail;
283 }
284  
285 NCDValue name1_arg;
286 if (!NCDValue_InitString(&name1_arg, NCDStatement_ForeachName1(stmt))) {
287 goto fail;
288 }
289  
290 if (!NCDValue_ListAppend(&args, name1_arg)) {
291 NCDValue_Free(&name1_arg);
292 goto fail;
293 }
294  
295 if (NCDStatement_ForeachName2(stmt)) {
296 NCDValue name2_arg;
297 if (!NCDValue_InitString(&name2_arg, NCDStatement_ForeachName2(stmt))) {
298 goto fail;
299 }
300  
301 if (!NCDValue_ListAppend(&args, name2_arg)) {
302 NCDValue_Free(&name2_arg);
303 goto fail;
304 }
305 }
306  
307 NCDStatement new_stmt;
308 if (!NCDStatement_InitReg(&new_stmt, NCDStatement_Name(stmt), NULL, "foreach_emb", args)) {
309 goto fail;
310 }
311  
312 stmt = NCDBlock_ReplaceStatement(block, stmt, new_stmt);
313  
314 *out_next = NCDBlock_NextStatement(block, stmt);
315 return 1;
316  
317 fail:
318 NCDValue_Free(&args);
319 return 0;
320 }
321  
322 static int desugar_blockstmt (struct desugar_state *state, NCDBlock *block, NCDStatement *stmt, NCDStatement **out_next)
323 {
324 ASSERT(NCDStatement_Type(stmt) == NCDSTATEMENT_BLOCK)
325  
326 NCDValue args;
327 NCDValue_InitList(&args);
328  
329 NCDBlock block_block = NCDStatement_BlockGrabBlock(stmt);
330  
331 NCDValue template_arg;
332 if (!add_template(state, block_block, &template_arg)) {
333 goto fail;
334 }
335  
336 if (!NCDValue_ListAppend(&args, template_arg)) {
337 NCDValue_Free(&template_arg);
338 goto fail;
339 }
340  
341 NCDStatement new_stmt;
342 if (!NCDStatement_InitReg(&new_stmt, NCDStatement_Name(stmt), NULL, "inline_code", args)) {
343 goto fail;
344 }
345  
346 stmt = NCDBlock_ReplaceStatement(block, stmt, new_stmt);
347  
348 *out_next = NCDBlock_NextStatement(block, stmt);
349 return 1;
350  
351 fail:
352 NCDValue_Free(&args);
353 return 0;
354 }
355  
356 int NCDSugar_Desugar (NCDProgram *prog)
357 {
358 ASSERT(!NCDProgram_ContainsElemType(prog, NCDPROGRAMELEM_INCLUDE))
359 ASSERT(!NCDProgram_ContainsElemType(prog, NCDPROGRAMELEM_INCLUDE_GUARD))
360  
361 struct desugar_state state;
362 state.prog = prog;
363 state.template_name_ctr = 0;
364  
365 for (NCDProgramElem *elem = NCDProgram_FirstElem(prog); elem; elem = NCDProgram_NextElem(prog, elem)) {
366 ASSERT(NCDProgramElem_Type(elem) == NCDPROGRAMELEM_PROCESS)
367 NCDProcess *proc = NCDProgramElem_Process(elem);
368  
369 if (!desugar_block(&state, NCDProcess_Block(proc))) {
370 return 0;
371 }
372 }
373  
374 return 1;
375 }