1
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5
6 #include "php.h"
7 #include "php_phalcon.h"
8 #include "phalcon.h"
9
10 #include <ext/standard/php_smart_str.h>
11
12 #include "parser.php5.h"
13 #include "scanner.h"
14 #include "volt.h"
15
16 #include "kernel/main.h"
17 #include "kernel/memory.h"
18 #include "kernel/fcall.h"
19 #include "kernel/exception.h"
20
21 #define PHVOLT_DEFINE_INIT_ZVAL(var) zval *var; MAKE_STD_ZVAL(var);
22 #define phvolt_add_assoc_stringl(var, index, str, len, copy) add_assoc_stringl(var, index, str, len, copy);
23 #define PHVOLT_ADDREF_P(var) Z_ADDREF_P(var)
24
phvolt_ret_literal_zval(int type,phvolt_parser_token * T,phvolt_scanner_state * state)25 static zval *phvolt_ret_literal_zval(int type, phvolt_parser_token *T, phvolt_scanner_state *state)
26 {
27 PHVOLT_DEFINE_INIT_ZVAL(ret);
28
29 array_init_size(ret, 5);
30 add_assoc_long(ret, "type", type);
31 if (T) {
32 phvolt_add_assoc_stringl(ret, "value", T->token, T->token_len, 0);
33 //efree(T->token);
34 efree(T);
35 }
36
37 PHVOLT_ADDREF_P(state->active_file);
38
39 add_assoc_zval(ret, "file", state->active_file);
40 add_assoc_long(ret, "line", state->active_line);
41
42 return ret;
43 }
44
phvolt_ret_if_statement(zval * expr,zval * true_statements,zval * false_statements,phvolt_scanner_state * state)45 static zval *phvolt_ret_if_statement(zval *expr, zval *true_statements, zval *false_statements, phvolt_scanner_state *state)
46 {
47 PHVOLT_DEFINE_INIT_ZVAL(ret);
48
49 array_init_size(ret, 7);
50 add_assoc_long(ret, "type", PHVOLT_T_IF);
51 add_assoc_zval(ret, "expr", expr);
52
53 if (true_statements) {
54 add_assoc_zval(ret, "true_statements", true_statements);
55 }
56 if (false_statements) {
57 add_assoc_zval(ret, "false_statements", false_statements);
58 }
59
60 PHVOLT_ADDREF_P(state->active_file);
61
62 add_assoc_zval(ret, "file", state->active_file);
63 add_assoc_long(ret, "line", state->active_line);
64
65 return ret;
66 }
67
phvolt_ret_elseif_statement(zval * expr,phvolt_scanner_state * state)68 static zval *phvolt_ret_elseif_statement(zval *expr, phvolt_scanner_state *state)
69 {
70 PHVOLT_DEFINE_INIT_ZVAL(ret);
71
72 array_init_size(ret, 5);
73 add_assoc_long(ret, "type", PHVOLT_T_ELSEIF);
74 add_assoc_zval(ret, "expr", expr);
75
76 PHVOLT_ADDREF_P(state->active_file);
77
78 add_assoc_zval(ret, "file", state->active_file);
79 add_assoc_long(ret, "line", state->active_line);
80
81 return ret;
82 }
83
phvolt_ret_elsefor_statement(phvolt_scanner_state * state)84 static zval *phvolt_ret_elsefor_statement(phvolt_scanner_state *state)
85 {
86 PHVOLT_DEFINE_INIT_ZVAL(ret);
87
88 array_init_size(ret, 4);
89 add_assoc_long(ret, "type", PHVOLT_T_ELSEFOR);
90
91 PHVOLT_ADDREF_P(state->active_file);
92
93 add_assoc_zval(ret, "file", state->active_file);
94 add_assoc_long(ret, "line", state->active_line);
95
96 return ret;
97 }
98
phvolt_ret_switch_statement(zval * expr,zval * case_clauses,phvolt_scanner_state * state)99 static zval *phvolt_ret_switch_statement(zval *expr, zval *case_clauses, phvolt_scanner_state *state)
100 {
101 PHVOLT_DEFINE_INIT_ZVAL(ret);
102
103 array_init_size(ret, 6);
104
105 add_assoc_long(ret, "type", PHVOLT_T_SWITCH);
106 add_assoc_zval(ret, "expr", expr);
107
108 if (case_clauses) {
109 add_assoc_zval(ret, "case_clauses", case_clauses);
110 }
111
112 PHVOLT_ADDREF_P(state->active_file);
113
114 add_assoc_zval(ret, "file", state->active_file);
115 add_assoc_long(ret, "line", state->active_line);
116
117 return ret;
118 }
119
phvolt_ret_case_clause(zval * expr,phvolt_scanner_state * state)120 static zval *phvolt_ret_case_clause(zval *expr, phvolt_scanner_state *state)
121 {
122 PHVOLT_DEFINE_INIT_ZVAL(ret);
123
124 array_init_size(ret, 5);
125
126 if (expr) {
127 add_assoc_long(ret, "type", PHVOLT_T_CASE);
128 add_assoc_zval(ret, "expr", expr);
129 } else {
130 add_assoc_long(ret, "type", PHVOLT_T_DEFAULT);
131 }
132
133 PHVOLT_ADDREF_P(state->active_file);
134
135 add_assoc_zval(ret, "file", state->active_file);
136 add_assoc_long(ret, "line", state->active_line);
137
138 return ret;
139 }
140
phvolt_ret_for_statement(phvolt_parser_token * variable,phvolt_parser_token * key,zval * expr,zval * if_expr,zval * block_statements,phvolt_scanner_state * state)141 static zval *phvolt_ret_for_statement(phvolt_parser_token *variable, phvolt_parser_token *key, zval *expr, zval *if_expr, zval *block_statements, phvolt_scanner_state *state)
142 {
143 PHVOLT_DEFINE_INIT_ZVAL(ret);
144
145 array_init_size(ret, 9);
146 add_assoc_long(ret, "type", PHVOLT_T_FOR);
147
148 phvolt_add_assoc_stringl(ret, "variable", variable->token, variable->token_len, 0);
149 //efree(variable->token);
150 efree(variable);
151
152 if (key) {
153 phvolt_add_assoc_stringl(ret, "key", key->token, key->token_len, 0);
154 //efree(key->token);
155 efree(key);
156 }
157
158 add_assoc_zval(ret, "expr", expr);
159 if (if_expr) {
160 add_assoc_zval(ret, "if_expr", if_expr);
161 }
162
163 add_assoc_zval(ret, "block_statements", block_statements);
164
165 PHVOLT_ADDREF_P(state->active_file);
166
167 add_assoc_zval(ret, "file", state->active_file);
168 add_assoc_long(ret, "line", state->active_line);
169
170 return ret;
171 }
172
phvolt_ret_cache_statement(zval * expr,zval * lifetime,zval * block_statements,phvolt_scanner_state * state)173 static zval *phvolt_ret_cache_statement(zval *expr, zval *lifetime, zval *block_statements, phvolt_scanner_state *state)
174 {
175 PHVOLT_DEFINE_INIT_ZVAL(ret);
176
177 array_init(ret);
178
179 add_assoc_long(ret, "type", PHVOLT_T_CACHE);
180 add_assoc_zval(ret, "expr", expr);
181
182 if (lifetime) {
183 add_assoc_zval(ret, "lifetime", lifetime);
184 }
185 add_assoc_zval(ret, "block_statements", block_statements);
186
187 PHVOLT_ADDREF_P(state->active_file);
188
189 add_assoc_zval(ret, "file", state->active_file);
190 add_assoc_long(ret, "line", state->active_line);
191
192 return ret;
193 }
194
phvolt_ret_raw_statement(zval * statement,phvolt_scanner_state * state)195 static zval *phvolt_ret_raw_statement(zval *statement, phvolt_scanner_state *state)
196 {
197 PHVOLT_DEFINE_INIT_ZVAL(ret);
198
199 array_init(ret);
200
201 add_assoc_long(ret, "type", PHVOLT_T_RAW);
202 add_assoc_zval(ret, "content", statement);
203
204 PHVOLT_ADDREF_P(state->active_file);
205
206 add_assoc_zval(ret, "file", state->active_file);
207 add_assoc_long(ret, "line", state->active_line);
208
209 return ret;
210 }
211
phvolt_ret_set_statement(zval * assignments)212 static zval *phvolt_ret_set_statement(zval *assignments)
213 {
214 PHVOLT_DEFINE_INIT_ZVAL(ret);
215
216 array_init_size(ret, 3);
217 add_assoc_long(ret, "type", PHVOLT_T_SET);
218
219 add_assoc_zval(ret, "assignments", assignments);
220
221 return ret;
222 }
223
phvolt_ret_set_assignment(zval * assignable_expr,int operator,zval * expr,phvolt_scanner_state * state)224 static zval *phvolt_ret_set_assignment(zval *assignable_expr, int operator, zval *expr, phvolt_scanner_state *state)
225 {
226
227 PHVOLT_DEFINE_INIT_ZVAL(ret);
228
229 array_init_size(ret, 5);
230
231 add_assoc_zval(ret, "variable", assignable_expr);
232 add_assoc_long(ret, "op", operator);
233 add_assoc_zval(ret, "expr", expr);
234
235 PHVOLT_ADDREF_P(state->active_file);
236
237 add_assoc_zval(ret, "file", state->active_file);
238 add_assoc_long(ret, "line", state->active_line);
239
240 return ret;
241 }
242
phvolt_ret_echo_statement(zval * expr,phvolt_scanner_state * state)243 static zval *phvolt_ret_echo_statement(zval *expr, phvolt_scanner_state *state)
244 {
245 PHVOLT_DEFINE_INIT_ZVAL(ret);
246
247 array_init_size(ret, 4);
248 add_assoc_long(ret, "type", PHVOLT_T_ECHO);
249 add_assoc_zval(ret, "expr", expr);
250
251 PHVOLT_ADDREF_P(state->active_file);
252
253 add_assoc_zval(ret, "file", state->active_file);
254 add_assoc_long(ret, "line", state->active_line);
255
256 return ret;
257 }
258
phvolt_ret_block_statement(phvolt_parser_token * name,zval * block_statements,phvolt_scanner_state * state)259 static zval *phvolt_ret_block_statement(phvolt_parser_token *name, zval *block_statements, phvolt_scanner_state *state)
260 {
261 PHVOLT_DEFINE_INIT_ZVAL(ret);
262
263 array_init_size(ret, 6);
264
265 add_assoc_long(ret, "type", PHVOLT_T_BLOCK);
266
267 phvolt_add_assoc_stringl(ret, "name", name->token, name->token_len, 0);
268 //efree(name->token);
269 efree(name);
270
271 if (block_statements) {
272 add_assoc_zval(ret, "block_statements", block_statements);
273 }
274
275 PHVOLT_ADDREF_P(state->active_file);
276
277 add_assoc_zval(ret, "file", state->active_file);
278 add_assoc_long(ret, "line", state->active_line);
279
280 return ret;
281 }
282
phvolt_ret_macro_statement(phvolt_parser_token * macro_name,zval * parameters,zval * block_statements,phvolt_scanner_state * state)283 static zval *phvolt_ret_macro_statement(phvolt_parser_token *macro_name, zval *parameters, zval *block_statements, phvolt_scanner_state *state)
284 {
285 PHVOLT_DEFINE_INIT_ZVAL(ret);
286
287 array_init(ret);
288 add_assoc_long(ret, "type", PHVOLT_T_MACRO);
289
290 phvolt_add_assoc_stringl(ret, "name", macro_name->token, macro_name->token_len, 0);
291 //efree(macro_name->token);
292 efree(macro_name);
293
294 if (parameters) {
295 add_assoc_zval(ret, "parameters", parameters);
296 }
297
298 if (block_statements) {
299 add_assoc_zval(ret, "block_statements", block_statements);
300 }
301
302 PHVOLT_ADDREF_P(state->active_file);
303
304 add_assoc_zval(ret, "file", state->active_file);
305 add_assoc_long(ret, "line", state->active_line);
306
307 return ret;
308 }
309
phvolt_ret_macro_parameter(phvolt_parser_token * variable,zval * default_value,phvolt_scanner_state * state)310 static zval *phvolt_ret_macro_parameter(phvolt_parser_token *variable, zval *default_value, phvolt_scanner_state *state)
311 {
312 PHVOLT_DEFINE_INIT_ZVAL(ret);
313
314 array_init_size(ret, 5);
315
316 phvolt_add_assoc_stringl(ret, "variable", variable->token, variable->token_len, 0);
317 //efree(variable->token);
318 efree(variable);
319
320 if (default_value) {
321 add_assoc_zval(ret, "default", default_value);
322 }
323
324 PHVOLT_ADDREF_P(state->active_file);
325
326 add_assoc_zval(ret, "file", state->active_file);
327 add_assoc_long(ret, "line", state->active_line);
328
329 return ret;
330 }
331
phvolt_ret_extends_statement(zval * path,phvolt_scanner_state * state)332 static zval *phvolt_ret_extends_statement(zval *path, phvolt_scanner_state *state)
333 {
334 PHVOLT_DEFINE_INIT_ZVAL(ret);
335
336 array_init_size(ret, 4);
337
338 add_assoc_long(ret, "type", PHVOLT_T_EXTENDS);
339 add_assoc_zval(ret, "path", path);
340
341 PHVOLT_ADDREF_P(state->active_file);
342
343 add_assoc_zval(ret, "file", state->active_file);
344 add_assoc_long(ret, "line", state->active_line);
345
346 return ret;
347 }
348
phvolt_ret_include_statement(zval * path,zval * params,phvolt_scanner_state * state)349 static zval *phvolt_ret_include_statement(zval *path, zval *params, phvolt_scanner_state *state)
350 {
351 PHVOLT_DEFINE_INIT_ZVAL(ret);
352
353 array_init_size(ret, 5);
354
355 add_assoc_long(ret, "type", PHVOLT_T_INCLUDE);
356
357 add_assoc_zval(ret, "path", path);
358 if (params) {
359 add_assoc_zval(ret, "params", params);
360 }
361
362 PHVOLT_ADDREF_P(state->active_file);
363
364 add_assoc_zval(ret, "file", state->active_file);
365 add_assoc_long(ret, "line", state->active_line);
366
367 return ret;
368 }
369
phvolt_ret_do_statement(zval * expr,phvolt_scanner_state * state)370 static zval *phvolt_ret_do_statement(zval *expr, phvolt_scanner_state *state)
371 {
372 PHVOLT_DEFINE_INIT_ZVAL(ret);
373
374 array_init_size(ret, 5);
375
376 add_assoc_long(ret, "type", PHVOLT_T_DO);
377 add_assoc_zval(ret, "expr", expr);
378
379 PHVOLT_ADDREF_P(state->active_file);
380
381 add_assoc_zval(ret, "file", state->active_file);
382 add_assoc_long(ret, "line", state->active_line);
383
384 return ret;
385 }
386
phvolt_ret_return_statement(zval * expr,phvolt_scanner_state * state)387 static zval *phvolt_ret_return_statement(zval *expr, phvolt_scanner_state *state)
388 {
389 PHVOLT_DEFINE_INIT_ZVAL(ret);
390
391 array_init_size(ret, 4);
392
393 add_assoc_long(ret, "type", PHVOLT_T_RETURN);
394 add_assoc_zval(ret, "expr", expr);
395
396 PHVOLT_ADDREF_P(state->active_file);
397
398 add_assoc_zval(ret, "file", state->active_file);
399 add_assoc_long(ret, "line", state->active_line);
400
401 return ret;
402 }
403
phvolt_ret_autoescape_statement(int enable,zval * block_statements,phvolt_scanner_state * state)404 static zval *phvolt_ret_autoescape_statement(int enable, zval *block_statements, phvolt_scanner_state *state)
405 {
406 PHVOLT_DEFINE_INIT_ZVAL(ret);
407
408 array_init_size(ret, 5);
409
410 add_assoc_long(ret, "type", PHVOLT_T_AUTOESCAPE);
411 add_assoc_long(ret, "enable", enable);
412 add_assoc_zval(ret, "block_statements", block_statements);
413
414 PHVOLT_ADDREF_P(state->active_file);
415
416 add_assoc_zval(ret, "file", state->active_file);
417 add_assoc_long(ret, "line", state->active_line);
418
419 return ret;
420 }
421
phvolt_ret_empty_statement(phvolt_scanner_state * state)422 static zval *phvolt_ret_empty_statement(phvolt_scanner_state *state)
423 {
424 PHVOLT_DEFINE_INIT_ZVAL(ret);
425
426 array_init_size(ret, 3);
427 add_assoc_long(ret, "type", PHVOLT_T_EMPTY_STATEMENT);
428
429 PHVOLT_ADDREF_P(state->active_file);
430
431 add_assoc_zval(ret, "file", state->active_file);
432 add_assoc_long(ret, "line", state->active_line);
433
434 return ret;
435 }
436
phvolt_ret_break_statement(phvolt_scanner_state * state)437 static zval *phvolt_ret_break_statement(phvolt_scanner_state *state)
438 {
439 PHVOLT_DEFINE_INIT_ZVAL(ret);
440
441 array_init_size(ret, 3);
442 add_assoc_long(ret, "type", PHVOLT_T_BREAK);
443
444 PHVOLT_ADDREF_P(state->active_file);
445
446 add_assoc_zval(ret, "file", state->active_file);
447 add_assoc_long(ret, "line", state->active_line);
448
449 return ret;
450 }
451
phvolt_ret_continue_statement(phvolt_scanner_state * state)452 static zval *phvolt_ret_continue_statement(phvolt_scanner_state *state)
453 {
454 PHVOLT_DEFINE_INIT_ZVAL(ret);
455
456 array_init_size(ret, 3);
457 add_assoc_long(ret, "type", PHVOLT_T_CONTINUE);
458
459 PHVOLT_ADDREF_P(state->active_file);
460
461 add_assoc_zval(ret, "file", state->active_file);
462 add_assoc_long(ret, "line", state->active_line);
463
464 return ret;
465 }
466
phvolt_ret_zval_list(zval * list_left,zval * right_list)467 static zval *phvolt_ret_zval_list(zval *list_left, zval *right_list)
468 {
469 HashTable *list;
470
471 PHVOLT_DEFINE_INIT_ZVAL(ret);
472
473 array_init(ret);
474
475 if (list_left) {
476
477 list = Z_ARRVAL_P(list_left);
478 if (zend_hash_index_exists(list, 0)) {
479 {
480 HashPosition pos;
481 zend_hash_internal_pointer_reset_ex(list, &pos);
482 for (;; zend_hash_move_forward_ex(list, &pos)) {
483
484 zval ** item;
485
486 if (zend_hash_get_current_data_ex(list, (void**) &item, &pos) == FAILURE) {
487 break;
488 }
489
490 Z_ADDREF_PP(item);
491 add_next_index_zval(ret, *item);
492
493 }
494 zval_ptr_dtor(&list_left);
495 }
496 } else {
497 add_next_index_zval(ret, list_left);
498 }
499 }
500
501 add_next_index_zval(ret, right_list);
502
503 return ret;
504 }
505
phvolt_ret_named_item(phvolt_parser_token * name,zval * expr,phvolt_scanner_state * state)506 static zval *phvolt_ret_named_item(phvolt_parser_token *name, zval *expr, phvolt_scanner_state *state)
507 {
508 PHVOLT_DEFINE_INIT_ZVAL(ret);
509
510 array_init(ret);
511 add_assoc_zval(ret, "expr", expr);
512 if (name != NULL) {
513 phvolt_add_assoc_stringl(ret, "name", name->token, name->token_len, 0);
514 //efree(name->token);
515 efree(name);
516 }
517
518 PHVOLT_ADDREF_P(state->active_file);
519
520 add_assoc_zval(ret, "file", state->active_file);
521 add_assoc_long(ret, "line", state->active_line);
522
523 return ret;
524 }
525
phvolt_ret_expr(int type,zval * left,zval * right,zval * ternary,phvolt_scanner_state * state)526 static zval *phvolt_ret_expr(int type, zval *left, zval *right, zval *ternary, phvolt_scanner_state *state)
527 {
528 PHVOLT_DEFINE_INIT_ZVAL(ret);
529
530 array_init(ret);
531 add_assoc_long(ret, "type", type);
532
533 if (ternary) {
534 add_assoc_zval(ret, "ternary", ternary);
535 }
536
537 if (left) {
538 add_assoc_zval(ret, "left", left);
539 }
540
541 if (right) {
542 add_assoc_zval(ret, "right", right);
543 }
544
545 PHVOLT_ADDREF_P(state->active_file);
546
547 add_assoc_zval(ret, "file", state->active_file);
548 add_assoc_long(ret, "line", state->active_line);
549
550 return ret;
551 }
552
phvolt_ret_slice(zval * left,zval * start,zval * end,phvolt_scanner_state * state)553 static zval *phvolt_ret_slice(zval *left, zval *start, zval *end, phvolt_scanner_state *state)
554 {
555 PHVOLT_DEFINE_INIT_ZVAL(ret);
556
557 array_init(ret);
558 add_assoc_long(ret, "type", PHVOLT_T_SLICE);
559 add_assoc_zval(ret, "left", left);
560
561 if (start != NULL) {
562 add_assoc_zval(ret, "start", start);
563 }
564
565 if (end != NULL) {
566 add_assoc_zval(ret, "end", end);
567 }
568
569 PHVOLT_ADDREF_P(state->active_file);
570
571 add_assoc_zval(ret, "file", state->active_file);
572 add_assoc_long(ret, "line", state->active_line);
573
574 return ret;
575 }
576
phvolt_ret_func_call(zval * expr,zval * arguments,phvolt_scanner_state * state)577 static zval *phvolt_ret_func_call(zval *expr, zval *arguments, phvolt_scanner_state *state)
578 {
579
580 PHVOLT_DEFINE_INIT_ZVAL(ret);
581
582 array_init(ret);
583 add_assoc_long(ret, "type", PHVOLT_T_FCALL);
584 add_assoc_zval(ret, "name", expr);
585
586 if (arguments) {
587 add_assoc_zval(ret, "arguments", arguments);
588 }
589
590 PHVOLT_ADDREF_P(state->active_file);
591
592 add_assoc_zval(ret, "file", state->active_file);
593 add_assoc_long(ret, "line", state->active_line);
594
595 return ret;
596 }
597
phvolt_ret_macro_call_statement(zval * expr,zval * arguments,zval * caller,phvolt_scanner_state * state)598 static zval *phvolt_ret_macro_call_statement(zval *expr, zval *arguments, zval *caller, phvolt_scanner_state *state)
599 {
600
601 PHVOLT_DEFINE_INIT_ZVAL(ret);
602
603 array_init(ret);
604 add_assoc_long(ret, "type", PHVOLT_T_CALL);
605 add_assoc_zval(ret, "name", expr);
606
607 if (arguments) {
608 add_assoc_zval(ret, "arguments", arguments);
609 }
610
611 if (caller) {
612 add_assoc_zval(ret, "caller", caller);
613 }
614
615 PHVOLT_ADDREF_P(state->active_file);
616
617 add_assoc_zval(ret, "file", state->active_file);
618 add_assoc_long(ret, "line", state->active_line);
619
620 return ret;
621 }
622