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