41741c0152abdd2e51c9672573f67e9ab195b4f7
[m6w6/ext-psi] / src / parser.h
1 #ifndef _PSI_PARSER_H
2 #define _PSI_PARSER_H
3
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <stdarg.h>
7 #include <string.h>
8
9 #include <Zend/zend_types.h>
10
11 #include "parser_proc.h"
12
13 #define BSIZE 256
14
15 #define PSI_T_POINTER PSI_T_ASTERISK
16 #define PSI_T_LONG_DOUBLE (PSI_T_DOUBLE << 16)
17
18 typedef int token_t;
19
20 size_t psi_t_alignment(token_t);
21 size_t psi_t_size(token_t);
22
23 typedef struct PSI_Token {
24 token_t type;
25 unsigned size, line, col;
26 char *text, *file;
27 char buf[1];
28 } PSI_Token;
29
30 typedef union impl_val {
31 char cval;
32 int8_t i8;
33 uint8_t u8;
34 short sval;
35 int16_t i16;
36 uint16_t u16;
37 int ival;
38 int32_t i32;
39 uint32_t u32;
40 long lval;
41 int64_t i64;
42 uint64_t u64;
43 float fval;
44 double dval;
45 #ifdef HAVE_LONG_DOUBLE
46 long double ldval;
47 #endif
48 union {
49 zend_bool bval;
50 zend_long lval;
51 zend_string *str;
52 } zend;
53 void *ptr;
54 uint8_t _dbg[sizeof(void *)];
55 } impl_val;
56
57 typedef struct decl_type {
58 PSI_Token *token;
59 char *name;
60 token_t type;
61 struct decl_type *real;
62 struct decl_struct *strct;
63 struct decl_enum *enm;
64 struct decl *func;
65 } decl_type;
66
67 static inline decl_type *init_decl_type(token_t type, const char *name) {
68 decl_type *t = calloc(1, sizeof(*t));
69 t->type = type;
70 t->name = strdup(name);
71 return t;
72 }
73
74 static inline decl_type *real_decl_type(decl_type *type) {
75 while (type->real) {
76 type = type->real;
77 }
78 return type;
79 }
80
81 static inline void free_decl_type(decl_type *type) {
82 if (type->token) {
83 free(type->token);
84 }
85 free(type->name);
86 free(type);
87 }
88
89 typedef struct decl_typedef {
90 PSI_Token *token;
91 char *alias;
92 decl_type *type;
93 } decl_typedef;
94
95 static inline decl_typedef *init_decl_typedef(const char *name, decl_type *type) {
96 decl_typedef *t = calloc(1, sizeof(*t));
97 t->alias = strdup(name);
98 t->type = type;
99 return t;
100 }
101
102 static inline void free_decl_typedef(decl_typedef *t) {
103 if (t->token) {
104 free(t->token);
105 }
106 free(t->alias);
107 free_decl_type(t->type);
108 free(t);
109 }
110
111 typedef struct decl_typedefs {
112 size_t count;
113 decl_typedef **list;
114 } decl_typedefs;
115
116 static inline decl_typedefs *add_decl_typedef(decl_typedefs *defs, decl_typedef *def) {
117 if (!defs) {
118 defs = calloc(1, sizeof(*defs));
119 }
120 defs->list = realloc(defs->list, ++defs->count * sizeof(*defs->list));
121 defs->list[defs->count-1] = def;
122 return defs;
123 }
124
125 static void free_decl_typedefs(decl_typedefs *defs) {
126 size_t i;
127
128 for (i = 0; i < defs->count; ++i) {
129 free_decl_typedef(defs->list[i]);
130 }
131 free(defs->list);
132 free(defs);
133 }
134
135 typedef struct decl_var {
136 PSI_Token *token;
137 char *name;
138 unsigned pointer_level;
139 unsigned array_size;
140 struct decl_arg *arg;
141 } decl_var;
142
143 static inline decl_var *init_decl_var(const char *name, unsigned pl, unsigned as) {
144 decl_var *v = calloc(1, sizeof(*v));
145 v->name = (char *) strdup((const char *) name);
146 v->pointer_level = pl;
147 v->array_size = as;
148 return v;
149 }
150
151 static inline void free_decl_var(decl_var *var) {
152 if (var->token) {
153 free(var->token);
154 }
155 free(var->name);
156 free(var);
157 }
158
159 typedef struct decl_struct_layout {
160 size_t pos;
161 size_t len;
162 } decl_struct_layout;
163
164 static inline decl_struct_layout *init_decl_struct_layout(size_t pos, size_t len) {
165 decl_struct_layout *l = calloc(1, sizeof(*l));
166 ZEND_ASSERT(pos+len);
167 l->pos = pos;
168 l->len = len;
169 return l;
170 }
171
172 static inline void free_decl_struct_layout(decl_struct_layout *l) {
173 free(l);
174 }
175
176 typedef struct decl_arg {
177 PSI_Token *token;
178 decl_type *type;
179 decl_var *var;
180 decl_struct_layout *layout;
181 struct let_stmt *let;
182 impl_val val;
183 void *ptr;
184 void *mem;
185 } decl_arg;
186
187 static inline decl_arg *init_decl_arg(decl_type *type, decl_var *var) {
188 decl_arg *arg = calloc(1, sizeof(*arg));
189 arg->token = var->token;
190 arg->type = type;
191 arg->var = var;
192 var->arg = arg;
193 arg->ptr = &arg->val;
194 return arg;
195 }
196
197 static inline void free_decl_arg(decl_arg *arg) {
198 free_decl_type(arg->type);
199 free_decl_var(arg->var);
200 if (arg->layout) {
201 free_decl_struct_layout(arg->layout);
202 }
203 free(arg);
204 }
205
206 typedef struct decl_vars {
207 decl_var **vars;
208 size_t count;
209 } decl_vars;
210
211 static inline decl_vars *init_decl_vars(decl_var *var) {
212 decl_vars *vars = calloc(1, sizeof(*vars));
213 if (var) {
214 vars->count = 1;
215 vars->vars = calloc(1, sizeof(*vars->vars));
216 vars->vars[0] = var;
217 }
218 return vars;
219 }
220
221 static inline decl_vars *add_decl_var(decl_vars *vars, decl_var *var) {
222 vars->vars = realloc(vars->vars, ++vars->count * sizeof(*vars->vars));
223 vars->vars[vars->count-1] = var;
224 return vars;
225 }
226
227 static inline void free_decl_vars(decl_vars *vars) {
228 size_t i;
229
230 for (i = 0; i < vars->count; ++i) {
231 free_decl_var(vars->vars[i]);
232 }
233 free(vars->vars);
234 free(vars);
235 }
236
237 typedef struct decl_args {
238 decl_arg **args;
239 size_t count;
240 unsigned varargs:1;
241 } decl_args;
242
243 static inline decl_args *init_decl_args(decl_arg *arg) {
244 decl_args *args = calloc(1, sizeof(*args));
245 if (arg) {
246 args->count = 1;
247 args->args = calloc(1, sizeof(*args->args));
248 args->args[0] = arg;
249 }
250 return args;
251 }
252
253 static inline decl_args *add_decl_arg(decl_args *args, decl_arg *arg) {
254 args->args = realloc(args->args, ++args->count * sizeof(*args->args));
255 args->args[args->count-1] = arg;
256 return args;
257 }
258
259 static inline void free_decl_args(decl_args *args) {
260 size_t i;
261
262 for (i = 0; i < args->count; ++i) {
263 free_decl_arg(args->args[i]);
264 }
265 free(args->args);
266 free(args);
267 }
268
269 typedef struct decl_abi {
270 PSI_Token *token;
271 char *convention;
272 } decl_abi;
273
274 static inline decl_abi *init_decl_abi(const char *convention) {
275 decl_abi *abi = calloc(1, sizeof(*abi));
276 abi->convention = strdup(convention);
277 return abi;
278 }
279
280 static inline void free_decl_abi(decl_abi *abi) {
281 if (abi->token) {
282 free(abi->token);
283 }
284 free(abi->convention);
285 free(abi);
286 }
287
288 typedef struct decl_callinfo {
289 void *sym;
290 void *info;
291 size_t argc;
292 void **args;
293 void **rval;
294 } decl_callinfo;
295
296 typedef struct decl {
297 decl_abi *abi;
298 decl_arg *func;
299 decl_args *args;
300 struct impl *impl;
301 decl_callinfo call;
302 } decl;
303
304 static inline decl* init_decl(decl_abi *abi, decl_arg *func, decl_args *args) {
305 decl *d = calloc(1, sizeof(*d));
306 d->abi = abi;
307 d->func = func;
308 d->args = args;
309 return d;
310 }
311
312 static inline void free_decl(decl *d) {
313 free_decl_abi(d->abi);
314 free_decl_arg(d->func);
315 if (d->args) {
316 free_decl_args(d->args);
317 }
318 free(d);
319 }
320
321 typedef struct decls {
322 size_t count;
323 decl **list;
324 } decls;
325
326 static inline decls *add_decl(decls *decls, decl *decl) {
327 if (!decls) {
328 decls = calloc(1, sizeof(*decls));
329 }
330 decls->list = realloc(decls->list, ++decls->count * sizeof(*decls->list));
331 decls->list[decls->count-1] = decl;
332 return decls;
333 }
334
335 static inline void free_decls(decls *decls) {
336 size_t i;
337
338 for (i = 0; i < decls->count; ++i) {
339 free_decl(decls->list[i]);
340 }
341 free(decls->list);
342 free(decls);
343 }
344
345
346 typedef struct decl_struct {
347 PSI_Token *token;
348 char *name;
349 decl_args *args;
350 size_t size;
351 struct {
352 void *type;
353 void (*dtor)(void *type);
354 } engine;
355 } decl_struct;
356
357 static inline decl_struct *init_decl_struct(const char *name, decl_args *args) {
358 decl_struct *s = calloc(1, sizeof(*s));
359 s->name = strdup(name);
360 s->args = args;
361 return s;
362 }
363
364 static inline void free_decl_struct(decl_struct *s) {
365 if (s->token) {
366 free(s->token);
367 }
368 if (s->args) {
369 free_decl_args(s->args);
370 }
371 if (s->engine.type && s->engine.dtor) {
372 s->engine.dtor(s->engine.type);
373 }
374 free(s->name);
375 free(s);
376 }
377
378 typedef struct decl_structs {
379 size_t count;
380 decl_struct **list;
381 } decl_structs;
382
383 static inline decl_structs *add_decl_struct(decl_structs *ss, decl_struct *s) {
384 if (!ss) {
385 ss = calloc(1, sizeof(*ss));
386 }
387 ss->list = realloc(ss->list, ++ss->count * sizeof(*ss->list));
388 ss->list[ss->count-1] = s;
389 return ss;
390 }
391
392 static inline void free_decl_structs(decl_structs *ss) {
393 size_t i;
394
395 for (i = 0; i < ss->count; ++i) {
396 free_decl_struct(ss->list[i]);
397 }
398 free(ss->list);
399 free(ss);
400 }
401
402 typedef struct impl_type {
403 char *name;
404 token_t type;
405 } impl_type;
406
407 static inline impl_type *init_impl_type(token_t type, const char *name) {
408 impl_type *t = calloc(1, sizeof(*t));
409
410 t->type = type;
411 t->name = strdup(name);
412 return t;
413 }
414
415 static inline void free_impl_type(impl_type *type) {
416 free(type->name);
417 free(type);
418 }
419
420 typedef struct impl_var {
421 PSI_Token *token;
422 char *name;
423 unsigned reference:1;
424 } impl_var;
425
426 static inline impl_var *init_impl_var(const char *name, int is_reference) {
427 impl_var *var = calloc(1, sizeof(*var));
428 var->name = strdup(name);
429 var->reference = is_reference;
430 return var;
431 }
432
433 static inline void free_impl_var(impl_var *var) {
434 if (var->token) {
435 free(var->token);
436 }
437 free(var->name);
438 free(var);
439 }
440
441 typedef struct impl_def_val {
442 token_t type;
443 char *text;
444 } impl_def_val;
445
446 static inline impl_def_val *init_impl_def_val(token_t t, const char *text) {
447 impl_def_val *def = calloc(1, sizeof(*def));
448 def->type = t;
449 def->text = strdup(text);
450 return def;
451 }
452
453 static inline void free_impl_def_val(impl_def_val *def) {
454 free(def->text);
455 free(def);
456 }
457
458 typedef struct const_type {
459 token_t type;
460 char *name;
461 } const_type;
462
463 static inline const_type *init_const_type(token_t type, const char *name) {
464 const_type *ct = calloc(1, sizeof(*ct));
465 ct->type = type;
466 ct->name = strdup(name);
467 return ct;
468 }
469
470 static inline void free_const_type(const_type *type) {
471 free(type->name);
472 free(type);
473 }
474
475 typedef struct constant {
476 const_type *type;
477 char *name;
478 impl_def_val *val;
479 } constant;
480
481 static inline constant *init_constant(const_type *type, const char *name, impl_def_val *val) {
482 constant *c = calloc(1, sizeof(*c));
483 c->type = type;
484 c->name = strdup(name);
485 c->val = val;
486 return c;
487 }
488
489 static inline void free_constant(constant *constant) {
490 free_const_type(constant->type);
491 free(constant->name);
492 free_impl_def_val(constant->val);
493 free(constant);
494 }
495
496 typedef struct constants {
497 size_t count;
498 constant **list;
499 } constants;
500
501 static inline constants *add_constant(constants *constants, constant *constant) {
502 if (!constants) {
503 constants = calloc(1, sizeof(*constants));
504 }
505 constants->list = realloc(constants->list, ++constants->count * sizeof(*constants->list));
506 constants->list[constants->count-1] = constant;
507 return constants;
508 }
509
510 static inline void free_constants(constants *c) {
511 size_t i;
512
513 for (i = 0; i < c->count; ++i) {
514 free_constant(c->list[i]);
515 }
516 free(c->list);
517 free(c);
518 }
519
520 typedef struct impl_arg {
521 impl_type *type;
522 impl_var *var;
523 impl_def_val *def;
524 impl_val val;
525 zval *_zv;
526 } impl_arg;
527
528 static inline impl_arg *init_impl_arg(impl_type *type, impl_var *var, impl_def_val *def) {
529 impl_arg *arg = calloc(1, sizeof(*arg));
530 arg->type = type;
531 arg->var = var;
532 arg->def = def;
533 return arg;
534 }
535
536 static inline void free_impl_arg(impl_arg *arg) {
537 free_impl_type(arg->type);
538 free_impl_var(arg->var);
539 if (arg->def) {
540 free_impl_def_val(arg->def);
541 }
542 free(arg);
543 }
544
545 typedef struct impl_vararg {
546 impl_arg *name;
547 struct impl_args *args;
548 token_t *types;
549 impl_val *values;
550 void **free_list;
551 } impl_vararg;
552
553 typedef struct impl_args {
554 impl_arg **args;
555 size_t count;
556 impl_vararg vararg;
557 } impl_args;
558
559 static inline impl_args *init_impl_args(impl_arg *arg) {
560 impl_args *args = calloc(1, sizeof(*args));
561 if (arg) {
562 args->count = 1;
563 args->args = calloc(1, sizeof(*args->args));
564 args->args[0] = arg;
565 }
566 return args;
567 }
568
569 static inline impl_args *add_impl_arg(impl_args *args, impl_arg *arg) {
570 args->args = realloc(args->args, ++args->count * sizeof(*args->args));
571 args->args[args->count-1] = arg;
572 return args;
573 }
574
575 static inline void free_impl_args(impl_args *args) {
576 size_t i;
577
578 for (i = 0; i < args->count; ++i) {
579 free_impl_arg(args->args[i]);
580 }
581 if (args->vararg.name) {
582 free_impl_arg(args->vararg.name);
583 }
584 free(args->args);
585 free(args);
586 }
587
588 typedef struct impl_func {
589 PSI_Token *token;
590 char *name;
591 impl_args *args;
592 impl_type *return_type;
593 unsigned return_reference:1;
594 } impl_func;
595
596 static inline impl_func *init_impl_func(char *name, impl_args *args, impl_type *type, int ret_reference) {
597 impl_func *func = calloc(1, sizeof(*func));
598 func->name = strdup(name);
599 func->args = args ? args : init_impl_args(NULL);
600 func->return_type = type;
601 func->return_reference = ret_reference;
602 return func;
603 }
604
605 static inline void free_impl_func(impl_func *f) {
606 if (f->token) {
607 free(f->token);
608 }
609 free_impl_type(f->return_type);
610 free_impl_args(f->args);
611 free(f->name);
612 free(f);
613 }
614
615 typedef struct num_exp {
616 PSI_Token *token;
617 token_t t;
618 union {
619 char *numb;
620 constant *cnst;
621 decl_var *dvar;
622 struct decl_enum_item *enm;
623 } u;
624 token_t operator;
625 int (*calculator)(int t1, impl_val *v1, int t2, impl_val *v2, impl_val *res);
626 struct num_exp *operand;
627 } num_exp;
628
629 static inline num_exp *init_num_exp(token_t t, void *num) {
630 num_exp *exp = calloc(1, sizeof(*exp));
631 switch (exp->t = t) {
632 case PSI_T_NUMBER:
633 case PSI_T_NSNAME:
634 exp->u.numb = strdup(num);
635 break;
636 case PSI_T_NAME:
637 exp->u.dvar = num;
638 break;
639 EMPTY_SWITCH_DEFAULT_CASE();
640 }
641 return exp;
642 }
643
644 static inline PSI_Token *PSI_TokenCopy(PSI_Token *src);
645 static inline num_exp *copy_num_exp(num_exp *exp) {
646 decl_var *dvar;
647 num_exp *num = calloc(1, sizeof(*num));
648
649 memcpy(num, exp, sizeof(*num));
650
651 if (num->token) {
652 num->token = PSI_TokenCopy(num->token);
653 }
654 if (num->operand) {
655 num->operand = copy_num_exp(num->operand);
656 }
657 switch (num->t) {
658 case PSI_T_NUMBER:
659 case PSI_T_NSNAME:
660 num->u.numb = strdup(num->u.numb);
661 break;
662 case PSI_T_NAME:
663 dvar = init_decl_var(num->u.dvar->name, num->u.dvar->pointer_level, num->u.dvar->array_size);
664 dvar->arg = num->u.dvar->arg;
665 if (num->u.dvar->token) {
666 dvar->token = PSI_TokenCopy(num->u.dvar->token);
667 }
668 num->u.dvar = dvar;
669 break;
670 }
671 return num;
672 }
673
674 static inline void free_num_exp(num_exp *exp) {
675 if (exp->token) {
676 free(exp->token);
677 }
678 switch (exp->t) {
679 case PSI_T_NUMBER:
680 free(exp->u.numb);
681 break;
682 case PSI_T_NSNAME:
683 break;
684 case PSI_T_NAME:
685 free_decl_var(exp->u.dvar);
686 break;
687 case PSI_T_ENUM:
688 break;
689 EMPTY_SWITCH_DEFAULT_CASE();
690 }
691 if (exp->operand) {
692 free_num_exp(exp->operand);
693 }
694 free(exp);
695 }
696
697 typedef struct decl_enum_item {
698 PSI_Token *token;
699 char *name;
700 num_exp *num;
701 num_exp inc;
702 struct decl_enum_item *prev;
703 } decl_enum_item;
704
705 static inline decl_enum_item *init_decl_enum_item(const char *name, num_exp *num) {
706 decl_enum_item *i = calloc(1, sizeof(*i));
707
708 i->name = strdup(name);
709 i->num = num;
710 return i;
711 }
712
713 static inline void free_decl_enum_item(decl_enum_item *i) {
714 if (i->token) {
715 free(i->token);
716 }
717 if (i->num && i->num != &i->inc) {
718 free_num_exp(i->num);
719 }
720 free(i->name);
721 free(i);
722 }
723
724 typedef struct decl_enum_items {
725 decl_enum_item **list;
726 size_t count;
727 } decl_enum_items;
728
729 static inline decl_enum_items *init_decl_enum_items(decl_enum_item *i) {
730 decl_enum_items *l = calloc(1, sizeof(*l));
731
732 if (i) {
733 l->count = 1;
734 l->list = calloc(1, sizeof(*l->list));
735 l->list[0] = i;
736 }
737 return l;
738 }
739
740 static inline decl_enum_items *add_decl_enum_item(decl_enum_items *l, decl_enum_item *i) {
741 l->list = realloc(l->list, sizeof(*l->list) * (l->count + 1));
742 l->list[l->count] = i;
743 if (l->count) {
744 i->prev = l->list[l->count - 1];
745 }
746 ++l->count;
747 return l;
748 }
749
750 static inline void free_decl_enum_items(decl_enum_items *l) {
751 if (l->list) {
752 size_t j;
753
754 for (j = 0; j < l->count; ++j) {
755 free_decl_enum_item(l->list[j]);
756 }
757 free(l->list);
758 }
759 free(l);
760 }
761
762 typedef struct decl_enum {
763 PSI_Token *token;
764 char *name;
765 decl_enum_items *items;
766 } decl_enum;
767
768 static inline decl_enum *init_decl_enum(const char *name, decl_enum_items *l) {
769 decl_enum *e = calloc(1, sizeof(*e));
770
771 e->name = strdup(name);
772 e->items = l;
773 return e;
774 }
775
776 static inline void free_decl_enum(decl_enum *e) {
777 if (e->token) {
778 free(e->token);
779 }
780 if (e->items) {
781 free_decl_enum_items(e->items);
782 }
783 free(e->name);
784 free(e);
785 }
786
787 typedef struct decl_enums {
788 decl_enum **list;
789 size_t count;
790 } decl_enums;
791
792 static inline decl_enums* add_decl_enum(decl_enums *es, decl_enum *e) {
793 if (!es) {
794 es = calloc(1, sizeof(*es));
795 }
796 es->list = realloc(es->list, ++es->count * sizeof(*es->list));
797 es->list[es->count-1] = e;
798 return es;
799 }
800
801 static inline void free_decl_enums(decl_enums *es) {
802 if (es->list) {
803 size_t j;
804
805 for (j = 0; j < es->count; ++j) {
806 free_decl_enum(es->list[j]);
807 }
808 }
809 free(es->list);
810 free(es);
811 }
812
813 typedef struct let_calloc {
814 num_exp *nmemb;
815 num_exp *size;
816 } let_calloc;
817
818 static inline let_calloc *init_let_calloc(num_exp *nmemb, num_exp *size) {
819 let_calloc *alloc = calloc(1, sizeof(*alloc));
820 alloc->nmemb = nmemb;
821 alloc->size = size;
822 return alloc;
823 }
824
825 static inline void free_let_calloc(let_calloc *alloc) {
826 free_num_exp(alloc->nmemb);
827 free_num_exp(alloc->size);
828 free(alloc);
829 }
830
831 typedef struct let_func {
832 token_t type;
833 char *name;
834 impl_var *var;
835 impl_arg *arg;
836 } let_func;
837
838 static inline let_func *init_let_func(token_t type, const char *name, impl_var *var) {
839 let_func *func = calloc(1, sizeof(*func));
840 func->type = type;
841 func->name = strdup(name);
842 func->var = var;
843 return func;
844 }
845
846 static inline void free_let_func(let_func *func) {
847 free_impl_var(func->var);
848 free(func->name);
849 free(func);
850 }
851
852 #define PSI_LET_REFERENCE 0x1;
853 typedef struct let_val {
854 enum let_val_kind {
855 PSI_LET_NULL,
856 PSI_LET_NUMEXP,
857 PSI_LET_CALLOC,
858 PSI_LET_FUNC,
859 PSI_LET_TMP,
860 } kind;
861 union {
862 num_exp *num;
863 let_calloc *alloc;
864 let_func *func;
865 decl_var *var;
866 } data;
867 union {
868 struct {
869 unsigned is_reference:1;
870 } one;
871 unsigned all;
872 } flags;
873 } let_val;
874
875 static inline let_val *init_let_val(enum let_val_kind kind, void *data) {
876 let_val *let = calloc(1, sizeof(*let));
877 switch (let->kind = kind) {
878 case PSI_LET_NULL:
879 break;
880 case PSI_LET_NUMEXP:
881 let->data.num = data;
882 break;
883 case PSI_LET_CALLOC:
884 let->data.alloc = data;
885 break;
886 case PSI_LET_FUNC:
887 let->data.func = data;
888 break;
889 case PSI_LET_TMP:
890 let->data.var = data;
891 break;
892 EMPTY_SWITCH_DEFAULT_CASE();
893 }
894 return let;
895 }
896
897 static inline void free_let_val(let_val *let) {
898 switch (let->kind) {
899 case PSI_LET_NULL:
900 break;
901 case PSI_LET_NUMEXP:
902 free_num_exp(let->data.num);
903 break;
904 case PSI_LET_CALLOC:
905 free_let_calloc(let->data.alloc);
906 break;
907 case PSI_LET_FUNC:
908 free_let_func(let->data.func);
909 break;
910 case PSI_LET_TMP:
911 free_decl_var(let->data.var);
912 break;
913 EMPTY_SWITCH_DEFAULT_CASE();
914 }
915 free(let);
916 }
917
918 typedef struct let_stmt {
919 decl_var *var;
920 let_val *val;
921
922 void *ptr;
923 } let_stmt;
924
925 static inline let_stmt *init_let_stmt(decl_var *var, let_val *val) {
926 let_stmt *let = calloc(1, sizeof(*let));
927 let->var = var;
928 let->val = val;
929 return let;
930 }
931
932 static inline void free_let_stmt(let_stmt *stmt) {
933 if (stmt->val) {
934 if (stmt->val->kind == PSI_LET_TMP && stmt->var->arg) {
935 free_decl_arg(stmt->var->arg);
936 }
937 free_let_val(stmt->val);
938 }
939 free_decl_var(stmt->var);
940 free(stmt);
941 }
942
943 struct set_value;
944
945 typedef struct set_func {
946 PSI_Token *token;
947 token_t type;
948 char *name;
949 void (*handler)(zval *, struct set_value *set, impl_val *ret_val);
950 } set_func;
951
952 static inline set_func *init_set_func(token_t type, const char *name) {
953 set_func *func = calloc(1, sizeof(*func));
954 func->type = type;
955 func->name = strdup(name);
956 return func;
957 }
958
959 static inline void free_set_func(set_func *func) {
960 if (func->token) {
961 free(func->token);
962 }
963 free(func->name);
964 free(func);
965 }
966
967 typedef struct set_value {
968 set_func *func;
969 decl_vars *vars;
970 num_exp *num;
971 struct {
972 struct set_value *set;
973 impl_val *val;
974 } outer;
975 struct set_value **inner;
976 size_t count;
977 } set_value;
978
979 static inline set_value *init_set_value(set_func *func, decl_vars *vars) {
980 set_value *val = calloc(1, sizeof(*val));
981 val->func = func;
982 val->vars = vars;
983 return val;
984 }
985 static inline set_value *add_inner_set_value(set_value *val, set_value *inner) {
986 val->inner = realloc(val->inner, ++val->count * sizeof(*val->inner));
987 val->inner[val->count-1] = inner;
988 inner->outer.set = val;
989 return val;
990 }
991
992 static inline void free_set_value(set_value *val) {
993 if (val->func) {
994 free_set_func(val->func);
995 }
996 if (val->vars) {
997 free_decl_vars(val->vars);
998 }
999 if (val->inner && (!val->outer.set || val->outer.set->inner != val->inner)) {
1000 size_t i;
1001 for (i = 0; i < val->count; ++i) {
1002 free_set_value(val->inner[i]);
1003 }
1004 free(val->inner);
1005 }
1006 if (val->num) {
1007 free_num_exp(val->num);
1008 }
1009 free(val);
1010 }
1011
1012 typedef struct set_stmt {
1013 impl_var *var;
1014 set_value *val;
1015 impl_arg *arg;
1016 } set_stmt;
1017
1018 static inline set_stmt *init_set_stmt(impl_var *var, set_value *val) {
1019 set_stmt *set = calloc(1, sizeof(*set));
1020 set->var = var;
1021 set->val = val;
1022 return set;
1023 }
1024
1025 static inline void free_set_stmt(set_stmt *set) {
1026 free_impl_var(set->var);
1027 free_set_value(set->val);
1028 free(set);
1029 }
1030
1031 typedef struct return_stmt {
1032 PSI_Token *token;
1033 set_value *set;
1034 decl_arg *decl;
1035 } return_stmt;
1036
1037 static inline return_stmt *init_return_stmt(set_value *val) {
1038 return_stmt *ret = calloc(1, sizeof(*ret));
1039 ret->set = val;
1040 return ret;
1041 }
1042
1043 static inline void free_return_stmt(return_stmt *ret) {
1044 if (ret->token) {
1045 free(ret->token);
1046 }
1047 free_set_value(ret->set);
1048 free(ret);
1049 }
1050
1051 typedef struct free_call {
1052 PSI_Token *token;
1053 char *func;
1054 decl_vars *vars;
1055 decl *decl;
1056 } free_call;
1057
1058 static inline free_call *init_free_call(const char *func, decl_vars *vars) {
1059 free_call *f = calloc(1, sizeof(*f));
1060 f->func = strdup(func);
1061 f->vars = vars;
1062 return f;
1063 }
1064
1065 static inline void free_free_call(free_call *f) {
1066 if (f->token) {
1067 free(f->token);
1068 }
1069 free(f->func);
1070 free_decl_vars(f->vars);
1071 free(f);
1072 }
1073
1074 typedef struct free_calls {
1075 free_call **list;
1076 size_t count;
1077 } free_calls;
1078
1079 static inline free_calls *init_free_calls(free_call *f) {
1080 free_calls *fcs = calloc(1, sizeof(*fcs));
1081 if (f) {
1082 fcs->count = 1;
1083 fcs->list = calloc(1, sizeof(*fcs->list));
1084 fcs->list[0] = f;
1085 }
1086 return fcs;
1087 }
1088
1089 static inline void free_free_calls(free_calls *fcs) {
1090 size_t i;
1091
1092 for (i = 0; i < fcs->count; ++i) {
1093 free_free_call(fcs->list[i]);
1094 }
1095 free(fcs->list);
1096 free(fcs);
1097 }
1098
1099 static inline free_calls *add_free_call(free_calls *fcs, free_call *f) {
1100 fcs->list = realloc(fcs->list, ++fcs->count * sizeof(*fcs->list));
1101 fcs->list[fcs->count-1] = f;
1102 return fcs;
1103 }
1104
1105 typedef struct free_stmt {
1106 free_calls *calls;
1107 } free_stmt;
1108
1109 static inline free_stmt *init_free_stmt(free_calls *calls) {
1110 free_stmt *f = calloc(1, sizeof(*f));
1111 f->calls = calls;
1112 return f;
1113 }
1114
1115 static inline void free_free_stmt(free_stmt *f) {
1116 free_free_calls(f->calls);
1117 free(f);
1118 }
1119
1120 typedef struct impl_stmt {
1121 token_t type;
1122 union {
1123 let_stmt *let;
1124 set_stmt *set;
1125 return_stmt *ret;
1126 free_stmt *fre;
1127 void *ptr;
1128 } s;
1129 } impl_stmt;
1130
1131 static inline impl_stmt *init_impl_stmt(token_t type, void *ptr) {
1132 impl_stmt *stmt = calloc(1, sizeof(*stmt));
1133 stmt->type = type;
1134 stmt->s.ptr = ptr;
1135 return stmt;
1136 }
1137
1138 static inline void free_impl_stmt(impl_stmt *stmt) {
1139 switch (stmt->type) {
1140 case PSI_T_LET:
1141 free_let_stmt(stmt->s.let);
1142 break;
1143 case PSI_T_SET:
1144 free_set_stmt(stmt->s.set);
1145 break;
1146 case PSI_T_RETURN:
1147 free_return_stmt(stmt->s.ret);
1148 break;
1149 case PSI_T_FREE:
1150 free_free_stmt(stmt->s.fre);
1151 break;
1152 }
1153 free(stmt);
1154 }
1155
1156 typedef struct impl_stmts {
1157 struct {
1158 return_stmt **list;
1159 size_t count;
1160 } ret;
1161 struct {
1162 let_stmt **list;
1163 size_t count;
1164 } let;
1165 struct {
1166 set_stmt **list;
1167 size_t count;
1168 } set;
1169 struct {
1170 free_stmt **list;
1171 size_t count;
1172 } fre;
1173 } impl_stmts;
1174
1175 static inline void *add_impl_stmt_ex(void *list, size_t count, void *stmt) {
1176 list = realloc(list, count * sizeof(list));
1177 ((void **)list)[count-1] = stmt;
1178 return list;
1179 }
1180
1181 static inline impl_stmts *add_impl_stmt(impl_stmts *stmts, impl_stmt *stmt) {
1182 switch (stmt->type) {
1183 case PSI_T_RETURN:
1184 stmts->ret.list = add_impl_stmt_ex(stmts->ret.list, ++stmts->ret.count, stmt->s.ret);
1185 break;
1186 case PSI_T_LET:
1187 stmts->let.list = add_impl_stmt_ex(stmts->let.list, ++stmts->let.count, stmt->s.let);
1188 break;
1189 case PSI_T_SET:
1190 stmts->set.list = add_impl_stmt_ex(stmts->set.list, ++stmts->set.count, stmt->s.set);
1191 break;
1192 case PSI_T_FREE:
1193 stmts->fre.list = add_impl_stmt_ex(stmts->fre.list, ++stmts->fre.count, stmt->s.fre);
1194 break;
1195 }
1196 free(stmt);
1197 return stmts;
1198 }
1199
1200 static inline impl_stmts *init_impl_stmts(impl_stmt *stmt) {
1201 impl_stmts *stmts = calloc(1, sizeof(*stmts));
1202 return add_impl_stmt(stmts, stmt);
1203 }
1204
1205 static inline void free_impl_stmts(impl_stmts *stmts) {
1206 size_t i;
1207
1208 for (i = 0; i < stmts->let.count; ++i) {
1209 free_let_stmt(stmts->let.list[i]);
1210 }
1211 free(stmts->let.list);
1212 for (i = 0; i < stmts->ret.count; ++i) {
1213 free_return_stmt(stmts->ret.list[i]);
1214 }
1215 free(stmts->ret.list);
1216 for (i = 0; i < stmts->set.count; ++i) {
1217 free_set_stmt(stmts->set.list[i]);
1218 }
1219 free(stmts->set.list);
1220 for (i = 0; i < stmts->fre.count; ++i) {
1221 free_free_stmt(stmts->fre.list[i]);
1222 }
1223 free(stmts->fre.list);
1224 free(stmts);
1225 }
1226
1227 typedef struct impl {
1228 impl_func *func;
1229 impl_stmts *stmts;
1230 decl *decl;
1231 } impl;
1232
1233 static inline impl *init_impl(impl_func *func, impl_stmts *stmts) {
1234 impl *i = calloc(1, sizeof(*i));
1235 i->func = func;
1236 i->stmts = stmts;
1237 return i;
1238 }
1239
1240 static inline void free_impl(impl *impl) {
1241 free_impl_func(impl->func);
1242 free_impl_stmts(impl->stmts);
1243 free(impl);
1244 }
1245
1246 typedef struct impls {
1247 size_t count;
1248 impl **list;
1249 } impls;
1250
1251 static inline impls *add_impl(impls *impls, impl *impl) {
1252 if (!impls) {
1253 impls = calloc(1, sizeof(*impls));
1254 }
1255 impls->list = realloc(impls->list, ++impls->count * sizeof(*impls->list));
1256 impls->list[impls->count-1] = impl;
1257 return impls;
1258 }
1259
1260 static void free_impls(impls *impls) {
1261 size_t i;
1262
1263 for (i = 0; i < impls->count; ++i) {
1264 free_impl(impls->list[i]);
1265 }
1266 free(impls->list);
1267 free(impls);
1268 }
1269
1270 typedef struct decl_file {
1271 char *ln;
1272 char *fn;
1273 } decl_file;
1274
1275 static inline void free_decl_file(decl_file *file) {
1276 if (file->ln) {
1277 free(file->ln);
1278 }
1279 if (file->fn) {
1280 free(file->fn);
1281 }
1282 memset(file, 0, sizeof(*file));
1283 }
1284
1285 typedef struct decl_libs {
1286 void **dl;
1287 size_t count;
1288 } decl_libs;
1289
1290 static inline void free_decl_libs(decl_libs *libs) {
1291 if (libs->dl) {
1292 size_t i;
1293 for (i = 0; i < libs->count; ++i) {
1294 if (libs->dl[i]) {
1295 dlclose(libs->dl[i]);
1296 }
1297 }
1298 free(libs->dl);
1299 }
1300 memset(libs, 0, sizeof(*libs));
1301 }
1302
1303 static inline void add_decl_lib(decl_libs *libs, void *dlopened) {
1304 libs->dl = realloc(libs->dl, ++libs->count * sizeof(*libs->dl));
1305 libs->dl[libs->count-1] = dlopened;
1306 }
1307
1308 static inline impl_val *deref_impl_val(impl_val *ret_val, decl_var *var) {
1309 unsigned i;
1310
1311 ZEND_ASSERT(var->arg->var != var);
1312 #if 0
1313 fprintf(stderr, "deref: %s pl=%u:%u as=%u:%u %p\n",
1314 var->name, var->pointer_level, var->arg->var->pointer_level,
1315 var->array_size, var->arg->var->array_size, ret_val);
1316 #endif
1317 for (i = 0; i < var->pointer_level; ++i) {
1318 #if 0
1319 fprintf(stderr, "-- %p %p %p\n", ret_val, *(void**)ret_val, ret_val->ptr);
1320 #endif
1321 ret_val = *(void **) ret_val;
1322 }
1323 return ret_val;
1324 }
1325
1326 static inline impl_val *enref_impl_val(void *ptr, decl_var *var) {
1327 impl_val *val, *val_ptr;
1328 unsigned i;
1329
1330 ZEND_ASSERT(var->arg->var == var);
1331 #if 0
1332 fprintf(stderr, "enref: %s pl=%u:%u as=%u:%u\n",
1333 var->name, var->pointer_level, var->arg->var->pointer_level,
1334 var->array_size, var->arg->var->array_size);
1335 #endif
1336 if (!var->pointer_level ){//&& real_decl_type(var->arg->type)->type != PSI_T_STRUCT) {
1337 return ptr;
1338 }
1339
1340 val = val_ptr = calloc(var->pointer_level + 1, sizeof(void *));
1341 for (i = !var->arg->var->array_size; i < var->pointer_level; ++i) {
1342 #if 0
1343 fprintf(stderr, "++\n");
1344 #endif
1345 val_ptr->ptr = (void **) val_ptr + 1;
1346 val_ptr = val_ptr->ptr;
1347 }
1348 val_ptr->ptr = ptr;
1349 return val;
1350 }
1351
1352 static inline impl_val *struct_member_ref(decl_arg *set_arg, impl_val *struct_ptr, impl_val **to_free) {
1353 void *ptr = (char *) struct_ptr + set_arg->layout->pos;
1354 #if 0
1355 fprintf(stderr, "struct member %s: %p\n", set_arg->var->name, ptr);
1356 #endif
1357 return ptr;
1358 }
1359
1360
1361 #define PSI_ERROR 16
1362 #define PSI_WARNING 32
1363 typedef void (*psi_error_cb)(PSI_Token *token, int type, const char *msg, ...);
1364
1365 #define PSI_DATA(D) ((PSI_Data *) (D))
1366 #define PSI_DATA_MEMBERS \
1367 constants *consts; \
1368 decl_typedefs *defs; \
1369 decl_structs *structs; \
1370 decl_enums *enums; \
1371 decls *decls; \
1372 impls *impls; \
1373 union { \
1374 decl_file file; \
1375 decl_libs libs; \
1376 } psi; \
1377 psi_error_cb error
1378 typedef struct PSI_Data {
1379 PSI_DATA_MEMBERS;
1380 } PSI_Data;
1381
1382 static inline PSI_Data *PSI_DataExchange(PSI_Data *dest, PSI_Data *src) {
1383 if (!dest) {
1384 dest = malloc(sizeof(*dest));
1385 }
1386 memcpy(dest, src, sizeof(*dest));
1387 memset(src, 0, sizeof(*src));
1388 return dest;
1389 }
1390
1391 static inline void PSI_DataDtor(PSI_Data *data) {
1392 if (data->consts) {
1393 free_constants(data->consts);
1394 }
1395 if (data->defs) {
1396 free_decl_typedefs(data->defs);
1397 }
1398 if (data->structs) {
1399 free_decl_structs(data->structs);
1400 }
1401 if (data->enums) {
1402 free_decl_enums(data->enums);
1403 }
1404 if (data->decls) {
1405 free_decls(data->decls);
1406 }
1407 if (data->impls) {
1408 free_impls(data->impls);
1409 }
1410 free_decl_file(&data->psi.file);
1411 }
1412
1413 typedef struct PSI_Parser {
1414 PSI_DATA_MEMBERS;
1415 FILE *fp;
1416 token_t num;
1417 void *proc;
1418 unsigned flags, errors, line, col;
1419 char *cur, *tok, *lim, *eof, *ctx, *mrk, buf[BSIZE];
1420 } PSI_Parser;
1421
1422 static inline size_t PSI_TokenAllocSize(size_t token_len, size_t fname_len) {
1423 return sizeof(PSI_Token) + token_len + fname_len + 2;
1424 }
1425
1426 static inline PSI_Token *PSI_TokenAlloc(PSI_Parser *P) {
1427 PSI_Token *T;
1428 size_t token_len, fname_len;
1429 token_t token_typ;
1430
1431 if (P->cur < P->tok) {
1432 return NULL;
1433 }
1434
1435 token_typ = P->num;
1436 token_len = P->cur - P->tok;
1437 fname_len = strlen(P->psi.file.fn);
1438
1439 T = calloc(1, PSI_TokenAllocSize(token_len, fname_len));
1440 T->type = token_typ;
1441 T->size = token_len;
1442 T->text = &T->buf[0];
1443 T->file = &T->buf[token_len + 1];
1444 T->line = P->line;
1445 T->col = P->col;
1446
1447 memcpy(T->text, P->tok, token_len);
1448 memcpy(T->file, P->psi.file.fn, fname_len);
1449
1450 return T;
1451 }
1452
1453 static inline PSI_Token *PSI_TokenCopy(PSI_Token *src) {
1454 size_t strct_len = PSI_TokenAllocSize(src->size, strlen(src->file));
1455 PSI_Token *ptr = malloc(strct_len);
1456
1457 memcpy(ptr, src, strct_len);
1458
1459 ptr->text = &ptr->buf[0];
1460 ptr->file = &ptr->buf[ptr->size + 1];
1461
1462 return ptr;
1463 }
1464
1465 static inline PSI_Token *PSI_TokenCat(unsigned argc, ...) {
1466 va_list argv;
1467 unsigned i;
1468 PSI_Token *T = NULL;
1469
1470 va_start(argv, argc);
1471 for (i = 0; i < argc; ++i) {
1472 PSI_Token *arg = va_arg(argv, PSI_Token *);
1473
1474 if (T) {
1475 size_t token_len = T->size, fname_len = strlen(T->file);
1476
1477 T = realloc(T, PSI_TokenAllocSize(T->size += arg->size + 1, fname_len));
1478 T->text = &T->buf[0];
1479 T->file = &T->buf[T->size + 1];
1480 T->buf[token_len] = ' ';
1481 memmove(&T->buf[T->size + 1], &T->buf[token_len + 1], fname_len + 1);
1482 memcpy(&T->buf[token_len + 1], arg->text, arg->size + 1);
1483 } else {
1484 T = PSI_TokenCopy(arg);
1485 T->type = PSI_T_NAME;
1486 }
1487 }
1488 va_end(argv);
1489
1490 return T;
1491 }
1492
1493 static inline PSI_Token *PSI_TokenAppend(PSI_Token *T, unsigned argc, ...) {
1494 va_list argv;
1495 unsigned i;
1496
1497 va_start(argv, argc);
1498 for (i = 0; i < argc; ++i) {
1499 char *str = va_arg(argv, char *);
1500 size_t str_len = strlen(str), token_len = T->size, fname_len = strlen(T->file);
1501
1502 T = realloc(T, PSI_TokenAllocSize(T->size += str_len + 1, fname_len));
1503 T->text = &T->buf[0];
1504 T->file = &T->buf[T->size + 1];
1505 T->buf[token_len] = ' ';
1506 memmove(&T->buf[T->size + 1], &T->buf[token_len + 1], fname_len + 1);
1507 memcpy(&T->buf[token_len + 1], str, str_len + 1);
1508 }
1509 va_end(argv);
1510
1511 return T;
1512 }
1513
1514 static inline PSI_Token *PSI_TokenTranslit(PSI_Token *T, char *from, char *to) {
1515 php_strtr(T->text, T->size, from, to, MIN(strlen(from), strlen(to)));
1516 return T;
1517 }
1518
1519 static inline uint64_t psi_hash(char *digest_buf, ...)
1520 {
1521 uint64_t hash = 5381;
1522 uint8_t c;
1523 const uint8_t *ptr;
1524 va_list argv;
1525
1526 va_start(argv, digest_buf);
1527 while ((ptr = va_arg(argv, const uint8_t *))) {
1528 while ((c = *ptr++)) {
1529 hash = ((hash << 5) + hash) + c;
1530 }
1531 }
1532 va_end(argv);
1533
1534 if (digest_buf) {
1535 sprintf(digest_buf, "%" PRIx64, hash);
1536 }
1537
1538 return hash;
1539 }
1540
1541 static inline uint64_t PSI_TokenHash(PSI_Token *t, char *digest_buf) {
1542 char loc_buf[48];
1543
1544 sprintf(loc_buf, "%u%u", t->line, t->col);
1545 return psi_hash(digest_buf, t->file, loc_buf, NULL);
1546 }
1547
1548 #define PSI_PARSER_DEBUG 0x1
1549
1550 PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb error, unsigned flags);
1551 void PSI_ParserSyntaxError(PSI_Parser *P, const char *fn, size_t ln, const char *msg, ...);
1552 size_t PSI_ParserFill(PSI_Parser *P, size_t n);
1553 token_t PSI_ParserScan(PSI_Parser *P);
1554 void PSI_ParserParse(PSI_Parser *P, PSI_Token *src);
1555 void PSI_ParserDtor(PSI_Parser *P);
1556 void PSI_ParserFree(PSI_Parser **P);
1557
1558 #endif