Line data Source code
1 : /* Copyright 2017 noseglasses <shinynoseglasses@gmail.com>
2 : *
3 : * This program is free software: you can redistribute it and/or modify
4 : * it under the terms of the GNU Lesser General Public License as published by
5 : * the Free Software Foundation, either version 3 of the License, or
6 : * (at your option) any later version.
7 : *
8 : * This program is distributed in the hope that it will be useful,
9 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 : * GNU Lesser General Public License for more details.
12 : *
13 : * You should have received a copy of the GNU Lesser General Public License
14 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 : */
16 :
17 : #include "detail/ppg_token_detail.h"
18 : #include "ppg_global.h"
19 : #include "ppg_debug.h"
20 : #include "ppg_action.h"
21 : #include "ppg_action_flags.h"
22 : #include "ppg_signals.h"
23 : #include "detail/ppg_context_detail.h"
24 : #include "ppg_input.h"
25 : #include "detail/ppg_event_buffer_detail.h"
26 : #include "detail/ppg_malloc_detail.h"
27 :
28 : #include <stdlib.h>
29 : #include <string.h>
30 :
31 832 : void ppg_token_store_action(PPG_Token__ *token,
32 : PPG_Action action)
33 : {
34 832 : token->action = action;
35 :
36 832 : PPG_LOG("A tk 0x%" PRIXPTR ": 0x%" PRIXPTR "\n",
37 : (uintptr_t)token, (uintptr_t)token->action.callback.user_data);
38 832 : }
39 :
40 1430 : void ppg_token_reset_control_state(PPG_Token__ *token)
41 : {
42 1430 : PPG_LOG("Resetting tk 0x%" PRIXPTR "\n", (uintptr_t)token);
43 :
44 1430 : token->misc.state = PPG_Token_Initialized;
45 1430 : token->misc.action_state = PPG_Action_Disabled;
46 1430 : }
47 :
48 41 : PPG_Token__ *ppg_token_alloc(void)
49 : {
50 41 : return (PPG_Token__*)PPG_MALLOC(sizeof(PPG_Token__));
51 : }
52 :
53 1013 : static void ppg_token_allocate_children(PPG_Token__ *token, PPG_Count n_children) {
54 :
55 : token->children
56 1013 : = (struct PPG_TokenStruct **)PPG_MALLOC(n_children*sizeof(struct PPG_TokenStruct*));
57 1013 : token->n_allocated_children = n_children;
58 1013 : }
59 :
60 1013 : static void ppg_token_grow_children(PPG_Token__ *token) {
61 :
62 1013 : if(token->n_allocated_children == 0) {
63 :
64 452 : ppg_token_allocate_children(token, 1);
65 : }
66 : else {
67 561 : PPG_Token__ **oldSucessors = token->children;
68 :
69 561 : ppg_token_allocate_children(token, 2*token->n_allocated_children);
70 :
71 1419 : for(PPG_Count i = 0; i < token->n_children; ++i) {
72 858 : token->children[i] = oldSucessors[i];
73 : }
74 :
75 561 : free(oldSucessors);
76 : }
77 1013 : }
78 :
79 1286 : void ppg_token_add_child(PPG_Token__ *token, PPG_Token__ *child) {
80 :
81 1286 : if(token->n_allocated_children == token->n_children) {
82 1013 : ppg_token_grow_children(token);
83 : }
84 :
85 1286 : token->children[token->n_children] = child;
86 :
87 1286 : child->parent = token;
88 :
89 1286 : ++token->n_children;
90 1286 : }
91 :
92 1363 : void ppg_token_free_children(PPG_Token__ *token)
93 : {
94 1363 : if(!token->children) { return; }
95 :
96 : // printf("Token %p frees %d children\n", token, token->n_children);
97 :
98 1738 : for(PPG_Count i = 0; i < token->n_children; ++i) {
99 :
100 : // printf("Child %d of %p\n", i, token);
101 1286 : ppg_token_free(token->children[i]);
102 : }
103 :
104 452 : free(token->children);
105 :
106 452 : token->children = NULL;
107 452 : token->n_allocated_children = 0;
108 : }
109 :
110 1363 : PPG_Token__* ppg_token_destroy(PPG_Token__ *token) {
111 :
112 : // printf("Destroying token %p\n", token);
113 :
114 1363 : ppg_token_free_children(token);
115 :
116 1363 : return token;
117 : }
118 :
119 6864 : static bool ppg_token_equals(PPG_Token__ *p1, PPG_Token__ *p2)
120 : {
121 6864 : if(p1->vtable != p2->vtable) { return false; }
122 :
123 6777 : return p1->vtable->equals(p1, p2);
124 : }
125 :
126 1322 : void ppg_token_free(PPG_Token__ *token) {
127 :
128 1322 : PPG_CALL_VIRT_METHOD(token, destroy);
129 :
130 1322 : free(token);
131 1322 : }
132 :
133 3374 : PPG_Token__* ppg_token_get_equivalent_child(
134 : PPG_Token__ *parent_token,
135 : PPG_Token__ *sample)
136 : {
137 3374 : if(parent_token->n_children == 0) { return NULL; }
138 :
139 7692 : for(PPG_Count i = 0; i < parent_token->n_children; ++i) {
140 6864 : if(ppg_token_equals(
141 6864 : parent_token->children[i],
142 : sample)
143 : ) {
144 2094 : return parent_token->children[i];
145 : }
146 : }
147 :
148 828 : return NULL;
149 : }
150 :
151 868 : size_t ppg_token_dynamic_member_size(PPG_Token__ *token)
152 : {
153 868 : return token->n_children*sizeof(PPG_Token__ *);
154 : }
155 :
156 18 : size_t ppg_token_dynamic_size(PPG_Token__ *token)
157 : {
158 18 : return sizeof(PPG_Token__)
159 18 : + ppg_token_dynamic_member_size(token);
160 : }
161 :
162 868 : char *ppg_token_copy_dynamic_members(PPG_Token__ *token, char *buffer)
163 : {
164 868 : size_t n_bytes = token->n_children*sizeof(PPG_Token__ *);
165 :
166 868 : memcpy((void*)buffer, (void*)token->children, n_bytes);
167 :
168 868 : return buffer + n_bytes;
169 : }
170 :
171 18 : char *ppg_token_placement_clone(PPG_Token__ *token, char *buffer)
172 : {
173 18 : *((PPG_Token__ *)buffer) = *token;
174 :
175 18 : PPG_Token__ *clone = (PPG_Token__ *)buffer;
176 :
177 : // printf("Replacing children pointer %p with %p\n", clone->children, (PPG_Token__ **)(buffer + sizeof(PPG_Token__)));
178 :
179 18 : clone->children = (PPG_Token__ **)(buffer + sizeof(PPG_Token__));
180 :
181 18 : return ppg_token_copy_dynamic_members(token, buffer + sizeof(PPG_Token__));
182 : }
183 :
184 :
185 868 : void ppg_token_register_pointers_for_compression(
186 : PPG_Token__ *token,
187 : PPG_Compression_Context__ *ccontext)
188 : {
189 : // ppg_compression_context_register_vptr((void**)&token->vtable, ccontext);
190 868 : PPG_LOG("\tcb.: 0x%" PRIXPTR "\n", (uintptr_t)token->action.callback.func);
191 868 : ppg_compression_context_register_symbol((void**)&token->action.callback.func, ccontext);
192 :
193 868 : if(token->action.callback.user_data) {
194 638 : PPG_LOG("\tu.d.: 0x%" PRIXPTR "\n", (uintptr_t)token->action.callback.user_data);
195 638 : ppg_compression_context_register_symbol((void**)&token->action.callback.user_data, ccontext);
196 : }
197 868 : }
198 :
199 : #if PPG_PRINT_SELF_ENABLED
200 :
201 2154 : void ppg_token_print_self_start(PPG_Token__ *p, PPG_Count indent)
202 : {
203 2154 : PPG_I PPG_LOG("\tprnt: 0x%" PRIXPTR "\n", (uintptr_t)p->parent);
204 2154 : PPG_I PPG_LOG("\tst: %d\n", (PPG_Count)p->misc.state);
205 2154 : PPG_I PPG_LOG("\tflgs: %d\n", (PPG_Count)p->misc.flags);
206 2154 : PPG_I PPG_LOG("\ta.st: %d\n", (PPG_Count)p->misc.action_state);
207 2154 : PPG_I PPG_LOG("\ta.flgs: %d\n", (PPG_Count)p->misc.action_flags);
208 2154 : PPG_I PPG_LOG("\ta.u_f: 0x%" PRIXPTR "\n", (uintptr_t)p->action.callback.func);
209 2154 : PPG_I PPG_LOG("\ta.u_d: 0x%" PRIXPTR "\n", (uintptr_t)p->action.callback.user_data);
210 2154 : PPG_I PPG_LOG("\tst: %d\n", (PPG_Count)p->misc.state);
211 2154 : PPG_I PPG_LOG("\tlyr: %d\n", p->layer);
212 2154 : PPG_I PPG_LOG("\tcldr: 0x%" PRIXPTR "\n", (uintptr_t)p->children);
213 2154 : }
214 :
215 2154 : void ppg_token_print_self_end(PPG_Token__ *p, PPG_Count indent, bool recurse)
216 : {
217 : // PPG_I PPG_LOG("\tchldr: 0x%" PRIXPTR "\n", (uintptr_t)&p->children);
218 2154 : PPG_I PPG_LOG("\tn alloc chld: %d\n", p->n_allocated_children);
219 2154 : PPG_I PPG_LOG("\tn chld: %d\n", p->n_children);
220 :
221 2154 : if(recurse) {
222 2754 : for(PPG_Count i = 0; i < p->n_children; ++i) {
223 1350 : PPG_I PPG_LOG("\tchld: %d\n", i);
224 1350 : PPG_CALL_VIRT_METHOD(p->children[i], print_self, indent + 1, recurse);
225 : }
226 : }
227 2154 : }
228 :
229 54 : static void ppg_token_print_self(PPG_Token__ *p, PPG_Count indent, bool recurse)
230 : {
231 54 : PPG_I PPG_LOG("<*** tk (0x%" PRIXPTR ") ***>\n", (uintptr_t)p);
232 54 : ppg_token_print_self_start(p, indent);
233 54 : ppg_token_print_self_end(p, indent, recurse);
234 54 : }
235 : #endif
236 :
237 : #if PPG_HAVE_DEBUGGING
238 0 : bool ppg_token_check_initialized(PPG_Token__ *token)
239 : {
240 0 : bool assertion_failed = false;
241 :
242 0 : PPG_ASSERT_WARN(token->misc.state == PPG_Token_Initialized);
243 0 : PPG_ASSERT_WARN(token->misc.action_state == PPG_Action_Disabled);
244 : /*
245 : #if PPG_PRINT_SELF_ENABLED
246 : if(assertion_failed) {
247 : PPG_PRINT_TOKEN(token)
248 : }
249 : #endif*/
250 :
251 0 : return assertion_failed;
252 : }
253 :
254 0 : bool ppg_token_recurse_check_initialized(PPG_Token__ *token)
255 : {
256 0 : bool assertion_failed = false;
257 :
258 : assertion_failed
259 0 : |= PPG_CALL_VIRT_METHOD(token, check_initialized);
260 :
261 0 : for(PPG_Count i = 0; i < token->n_children; ++i) {
262 : assertion_failed
263 0 : |= ppg_token_recurse_check_initialized(token->children[i]);
264 : }
265 :
266 0 : return assertion_failed;
267 : }
268 :
269 : #endif
270 :
271 4340 : void ppg_token_traverse_tree(PPG_Token__ *token,
272 : PPG_Token_Tree_Visitor pre_children_visitor,
273 : PPG_Token_Tree_Visitor post_children_visitor,
274 : void *user_data)
275 : {
276 4340 : if(pre_children_visitor) {
277 3472 : pre_children_visitor(token, user_data);
278 : }
279 :
280 8590 : for(PPG_Count i = 0; i < token->n_children; ++i) {
281 4250 : ppg_token_traverse_tree(token->children[i],
282 : pre_children_visitor,
283 : post_children_visitor,
284 : user_data);
285 : }
286 :
287 4340 : if(post_children_visitor) {
288 868 : post_children_visitor(token, user_data);
289 : }
290 4340 : }
291 :
292 868 : void ppg_token_addresses_to_relative( PPG_Token__ *token,
293 : void *begin_of_buffer
294 : )
295 : {
296 1718 : for(PPG_Count i = 0; i < token->n_children; ++i) {
297 850 : token->children[i] = (PPG_Token__ *)((char*)token->children[i] - (char*)begin_of_buffer);
298 : }
299 :
300 868 : if(token->children) {
301 868 : token->children = (PPG_Token__ **)((char*)token->children - (char*)begin_of_buffer);
302 : }
303 868 : }
304 :
305 434 : void ppg_token_addresses_to_absolute( PPG_Token__ *token,
306 : void *begin_of_buffer
307 : )
308 : {
309 434 : token->children = (PPG_Token__ **)((char*)begin_of_buffer + (uintptr_t)token->children);
310 :
311 859 : for(PPG_Count i = 0; i < token->n_children; ++i) {
312 425 : token->children[i] = (PPG_Token__ *)((char*)begin_of_buffer + (uintptr_t)token->children[i]);
313 : }
314 434 : }
315 :
316 : PPG_Token_Vtable ppg_token_vtable =
317 : {
318 : .match_event
319 : = NULL,
320 : .reset
321 : = (PPG_Token_Reset_Fun) ppg_token_reset_control_state,
322 : .destroy
323 : = (PPG_Token_Destroy_Fun) ppg_token_destroy,
324 : .equals
325 : = NULL,
326 : .dynamic_size
327 : = (PPG_Token_Dynamic_Size_Requirement_Fun)ppg_token_dynamic_size,
328 : .placement_clone
329 : = (PPG_Token_Placement_Clone_Fun)ppg_token_placement_clone,
330 : .register_ptrs_for_compression
331 : = (PPG_Token_Register_Pointers_For_Compression)ppg_token_register_pointers_for_compression,
332 : .addresses_to_relative
333 : = (PPG_Token_Addresses_To_Relative)ppg_token_addresses_to_relative,
334 : .addresses_to_absolute
335 : = (PPG_Token_Addresses_To_Absolute)ppg_token_addresses_to_absolute
336 :
337 : #if PPG_PRINT_SELF_ENABLED
338 : ,
339 : .print_self
340 : = (PPG_Token_Print_Self_Fun) ppg_token_print_self
341 : #endif
342 :
343 : #if PPG_HAVE_DEBUGGING
344 : ,
345 : .check_initialized
346 : = (PPG_Token_Check_Initialized_Fun)ppg_token_check_initialized
347 : #endif
348 : };
349 :
350 1363 : PPG_Token__ *ppg_token_new(PPG_Token__ *token) {
351 :
352 1363 : token->vtable = &ppg_token_vtable;
353 :
354 1363 : token->misc = (PPG_Misc_Bits) {
355 : .state = PPG_Token_Initialized,
356 : .flags = 0,
357 : .action_state = 0,
358 : .action_flags = PPG_Action_Default
359 : };
360 1363 : token->parent = NULL;
361 1363 : token->children = NULL;
362 1363 : token->n_allocated_children = 0;
363 1363 : token->n_children = 0;
364 1363 : token->action.callback.func = NULL;
365 1363 : token->action.callback.user_data = NULL;
366 1363 : token->layer = 0;
367 :
368 1363 : return token;
369 : }
370 :
371 799 : PPG_Token ppg_token_set_action(
372 : PPG_Token token,
373 : PPG_Action action)
374 : {
375 799 : PPG_Token__ *token__ = (PPG_Token__ *)token;
376 :
377 799 : ppg_token_store_action(token__, action);
378 :
379 799 : return token;
380 : }
381 :
382 0 : PPG_Action ppg_token_get_action(PPG_Token token)
383 : {
384 0 : PPG_Token__ *token__ = (PPG_Token__ *)token;
385 :
386 0 : return token__->action;
387 : }
388 :
389 2 : PPG_Token ppg_token_set_action_flags(
390 : PPG_Token token,
391 : PPG_Action_Flags_Type action_flags)
392 : {
393 2 : PPG_Token__ *token__ = (PPG_Token__ *)token;
394 :
395 2 : token__->misc.action_flags = action_flags;
396 :
397 2 : return token;
398 : }
399 :
400 0 : PPG_Action_Flags_Type ppg_token_get_action_flags(PPG_Token token)
401 : {
402 0 : PPG_Token__ *token__ = (PPG_Token__ *)token;
403 :
404 0 : return token__->misc.action_flags;
405 : }
406 :
407 3 : PPG_Token ppg_token_set_flags(
408 : PPG_Token token,
409 : PPG_Count flags)
410 : {
411 3 : PPG_Token__ *token__ = (PPG_Token__ *)token;
412 :
413 3 : token__->misc.flags = flags;
414 :
415 3 : return token;
416 : }
417 :
418 0 : PPG_Count ppg_token_get_flags(PPG_Token token)
419 : {
420 0 : PPG_Token__ *token__ = (PPG_Token__ *)token;
421 :
422 0 : return token__->misc.flags;
423 : }
424 :
425 109 : void ppg_token_list_all_active(void)
426 : {
427 109 : PPG_LOG("T actv:\n");
428 :
429 109 : for(PPG_Count i = 0; i < PPG_GAT.n_tokens; ++i) {
430 0 : PPG_LOG("\t0x%" PRIXPTR "\n", (uintptr_t)PPG_GAT.tokens[i]);
431 : }
432 109 : }
|