flush
[m6w6/ext-psi] / src / types / decl_args.c
1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #else
29 # include "php_config.h"
30 #endif
31
32 #include <stdlib.h>
33 #include <stdio.h>
34
35 #include "data.h"
36
37 decl_args *init_decl_args(decl_arg *arg) {
38 decl_args *args = calloc(1, sizeof(*args));
39 if (arg) {
40 args->count = 1;
41 args->args = calloc(1, sizeof(*args->args));
42 args->args[0] = arg;
43 }
44 return args;
45 }
46
47 decl_args *add_decl_arg(decl_args *args, decl_arg *arg) {
48 args->args = realloc(args->args, ++args->count * sizeof(*args->args));
49 args->args[args->count - 1] = arg;
50 return args;
51 }
52
53 void free_decl_args(decl_args *args) {
54 size_t i;
55 for (i = 0; i < args->count; ++i) {
56 free_decl_arg(args->args[i]);
57 }
58 free(args->args);
59 free(args);
60 }
61
62 void dump_decl_args(int fd, decl_args *args, unsigned level) {
63 size_t i;
64
65 for (i = 0; i < args->count; ++i) {
66 if (i) {
67 dprintf(fd, ", ");
68 }
69 dump_decl_arg(fd, args->args[i], level);
70 }
71 if (args->varargs) {
72 dprintf(fd, ", ...");
73 }
74 }
75
76 void dump_decl_args_with_layout(int fd, decl_args *args, unsigned level) {
77 size_t j;
78
79 dprintf(fd, " {\n");
80 if (args) {
81 ++level;
82 for (j = 0; j < args->count; ++j) {
83 decl_arg *sarg = args->args[j];
84
85 dprintf(fd, "%s", psi_t_indent(level));
86 dump_decl_arg(fd, sarg, level);
87 dprintf(fd, "::(%zu, %zu);\n", sarg->layout->pos, sarg->layout->len);
88 }
89 --level;
90 }
91 dprintf(fd, "%s", psi_t_indent(level));
92 dprintf(fd, "}");
93 }
94
95 decl_arg *locate_decl_arg(decl_args *args, const char *name) {
96 size_t i;
97
98 if (args) for (i = 0; i < args->count; ++i) {
99 decl_arg *arg = args->args[i];
100
101 if (!strcmp(name, arg->var->name)) {
102 return arg;
103 }
104 }
105
106 return NULL;
107 }
108
109 size_t alignof_decl_args(decl_args *args) {
110 size_t i, maxalign = 0;
111
112 for (i = 0; i < args->count; ++i) {
113 decl_arg *darg = args->args[i];
114 size_t align = alignof_decl_arg(darg);
115
116 if (align > maxalign) {
117 maxalign = align;
118 }
119 }
120
121 return maxalign;
122 }
123
124 int validate_decl_arg_args(struct psi_data *data, decl_arg *darg, void *current) {
125 decl_type *real = real_decl_type(darg->type);
126
127 /* pre-validate any structs/unions/enums */
128 switch (real->type) {
129 case PSI_T_STRUCT:
130 if (current && current == real->real.strct) {
131 return 1;
132 }
133 if (!locate_decl_type_struct(data->structs, real)) {
134 return 0;
135 }
136 if (!validate_decl_struct(data, real->real.strct)) {
137 return 0;
138 }
139 break;
140 case PSI_T_UNION:
141 if (current && current == real->real.unn) {
142 return 1;
143 }
144 if (!locate_decl_type_union(data->unions, real)) {
145 return 0;
146 }
147 if (!validate_decl_union(data, real->real.unn)) {
148 return 0;
149 }
150 break;
151 case PSI_T_ENUM:
152 if (current && current == real->real.enm) {
153 return 1;
154 }
155 if (!locate_decl_type_enum(data->enums, real)) {
156 return 0;
157 }
158 if (!validate_decl_enum(data, real->real.enm)) {
159 return 0;
160 }
161 break;
162 }
163
164 return 1;
165 }
166
167 static int sort_args_cmp(const void *_a, const void *_b) {
168 decl_arg *a = *(decl_arg **)_a, *b = *(decl_arg **)_b;
169
170 if (a->layout->pos == b->layout->pos) {
171 if (a->layout->len == b->layout->len) {
172 return 0;
173 } else if (a->layout->len > b->layout->len) {
174 return -1;
175 } else {
176 return 1;
177 }
178 } else if (a->layout->pos > b->layout->pos) {
179 return 1;
180 } else {
181 return -1;
182 }
183 }
184
185 static void sort_args_swp(void *a, void *b) {
186 decl_arg **_a = a, **_b = b, *_c;
187
188 _c = *_b;
189 *_b = *_a;
190 *_a = _c;
191 }
192
193 #include "Zend/zend_sort.h"
194
195 void sort_decl_args(decl_args *args) {
196 zend_insert_sort((void *) args->args, args->count,
197 sizeof(args), sort_args_cmp, sort_args_swp);
198 }
199