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_note_detail.h"
18 : #include "ppg_debug.h"
19 : #include "detail/ppg_context_detail.h"
20 : #include "detail/ppg_input_detail.h"
21 : #include "detail/ppg_token_detail.h"
22 : #include "detail/ppg_token_precedence_detail.h"
23 : #include "detail/ppg_malloc_detail.h"
24 :
25 : #include <stdlib.h>
26 :
27 614 : static bool ppg_note_match_event(
28 : PPG_Note *note,
29 : PPG_Event *event,
30 : bool modify_only_if_consuming
31 : )
32 : {
33 614 : PPG_LOG("Nt 0x%" PRIXPTR ", input 0x%d, ppg_note_match_event\n", (uintptr_t)note, note->input);
34 :
35 614 : PPG_Count note_flags
36 614 : = note->super.misc.flags;
37 :
38 : // Assert that the note requires either activation or deactivation
39 : //
40 614 : PPG_ASSERT(note_flags != 0);
41 :
42 614 : switch(note_flags & ( PPG_Note_Flag_Match_Activation
43 : | PPG_Note_Flag_Match_Deactivation)) {
44 :
45 : case (PPG_Note_Flag_Match_Activation
46 : | PPG_Note_Flag_Match_Deactivation):
47 :
48 580 : if(note->input != event->input) {
49 166 : if( (note_flags & PPG_Token_Flags_Pedantic)
50 166 : || (event->flags & PPG_Event_Active)) {
51 :
52 42 : if(!modify_only_if_consuming) {
53 42 : note->super.misc.state = PPG_Token_Invalid;
54 : }
55 : }
56 :
57 166 : return false;
58 : }
59 :
60 414 : if(event->flags & PPG_Event_Active) {
61 :
62 196 : PPG_LOG("I act\n");
63 :
64 : // Mark the note as active
65 : //
66 196 : note->super.misc.flags |= PPG_Note_Type_Active;
67 :
68 196 : PPG_LOG("Nt 0x%" PRIXPTR " fin\n", (uintptr_t)note);
69 :
70 196 : if(note_flags & PPG_Token_Flags_Pedantic) {
71 0 : note->super.misc.state = PPG_Token_Activation_In_Progress;
72 : }
73 : else {
74 196 : note->super.misc.state = PPG_Token_Matches;
75 : }
76 : }
77 : else {
78 :
79 218 : if(note_flags & PPG_Note_Type_Active) {
80 186 : PPG_LOG("I deact\n");
81 :
82 186 : if(note_flags & PPG_Token_Flags_Pedantic) {
83 0 : PPG_LOG("Nt fin\n");
84 : // PPG_LOG("N");
85 0 : note->super.misc.state = PPG_Token_Matches;
86 : }
87 : else {
88 186 : note->super.misc.state = PPG_Token_Finalized;
89 : }
90 : }
91 : else {
92 :
93 : // The input is not active but this is a deactivation
94 : // event. Thus, we ignore it as it belongs
95 : // to the activation of another token.
96 :
97 : // Note: Even the deactivation of the associated input must
98 : // be ignored here.
99 : //
100 32 : return false;
101 : }
102 : }
103 382 : break;
104 :
105 : case PPG_Note_Flag_Match_Activation:
106 :
107 24 : PPG_LOG("Only act\n");
108 24 : if( (note->input == event->input)
109 14 : && (event->flags & PPG_Event_Active)) {
110 12 : PPG_LOG("I mtch\n");
111 12 : note->super.misc.state = PPG_Token_Matches;
112 12 : note->super.misc.flags |= PPG_Token_Flags_Done;
113 12 : return true;
114 : }
115 :
116 12 : PPG_LOG("I inact\n");
117 12 : if(!modify_only_if_consuming) {
118 12 : note->super.misc.state = PPG_Token_Invalid;
119 : }
120 :
121 12 : return false;
122 :
123 : case PPG_Note_Flag_Match_Deactivation:
124 :
125 10 : if( (note->input == event->input)
126 8 : && ((event->flags & PPG_Event_Active) == 0)) {
127 8 : note->super.misc.state = PPG_Token_Finalized;
128 :
129 8 : note->super.misc.flags |= PPG_Token_Flags_Done;
130 8 : return true;
131 : }
132 :
133 2 : if(!modify_only_if_consuming) {
134 2 : note->super.misc.state = PPG_Token_Invalid;
135 : }
136 :
137 2 : return false;
138 : }
139 :
140 382 : return true;
141 : }
142 :
143 283 : static void ppg_note_reset(PPG_Note *note)
144 : {
145 283 : ppg_token_reset_control_state((PPG_Token__*)note);
146 :
147 : // Notes that only match deactivation start in matching state
148 : //
149 566 : if((note->super.misc.flags
150 283 : & PPG_Note_Flag_Match_Activation) == 0) {
151 10 : note->super.misc.state = PPG_Token_Matches;
152 : }
153 :
154 : // Clear the activation state
155 : //
156 : note->super.misc.flags
157 283 : &= (PPG_Count)~PPG_Note_Type_Active;
158 283 : }
159 :
160 6744 : static bool ppg_note_equals(PPG_Note *n1, PPG_Note *n2)
161 : {
162 6744 : return n1->input == n2->input;
163 : }
164 :
165 280 : static PPG_Count ppg_note_token_precedence(PPG_Token__ *token)
166 : {
167 280 : PPG_Note *note = (PPG_Note *)token;
168 :
169 280 : PPG_Count note_flags = note->super.misc.flags;
170 :
171 280 : if( (note_flags & PPG_Note_Flag_Match_Activation)
172 280 : && (note_flags & PPG_Note_Flag_Match_Deactivation)) {
173 280 : return PPG_Token_Precedence_Note;
174 : }
175 :
176 0 : return PPG_Token_Precedence_Explicit_Note;
177 : }
178 :
179 826 : static size_t ppg_note_dynamic_size(PPG_Token__ *token)
180 : {
181 826 : return sizeof(PPG_Note)
182 826 : + ppg_token_dynamic_member_size(token);
183 : }
184 :
185 826 : static char *ppg_note_placement_clone(PPG_Token__ *token, char *buffer)
186 : {
187 826 : PPG_Note *note = (PPG_Note *)token;
188 :
189 826 : *((PPG_Note *)buffer) = *note;
190 :
191 826 : PPG_Token__ *clone = (PPG_Token__ *)buffer;
192 :
193 : // printf("Replacing children pointer %p with %p\n", clone->children, (PPG_Token__ **)(buffer + sizeof(PPG_Note)));
194 :
195 826 : clone->children = (PPG_Token__ **)(buffer + sizeof(PPG_Note));
196 :
197 826 : return ppg_token_copy_dynamic_members(token, buffer + sizeof(PPG_Note));
198 : }
199 :
200 : #if PPG_PRINT_SELF_ENABLED
201 1668 : static void ppg_note_print_self(PPG_Note *p, PPG_Count indent, bool recurse)
202 : {
203 1668 : PPG_I PPG_LOG("<*** nt (0x%" PRIXPTR ") ***>\n", (uintptr_t)p);
204 1668 : ppg_token_print_self_start((PPG_Token__*)p, indent);
205 1668 : PPG_I PPG_LOG("\tI: 0x%" PRIXPTR "\n", (uintptr_t)p->input);
206 1668 : PPG_I PPG_LOG("\tA: %d\n", (p->super.misc.flags & PPG_Note_Type_Active));
207 1668 : PPG_I PPG_LOG("\tm a: %d\n", (bool)(p->super.misc.flags & PPG_Note_Flag_Match_Activation));
208 1668 : PPG_I PPG_LOG("\tm d: %d\n", (bool)(p->super.misc.flags & PPG_Note_Flag_Match_Deactivation));
209 1668 : ppg_token_print_self_end((PPG_Token__*)p, indent, recurse);
210 1668 : }
211 : #endif
212 :
213 : #if PPG_HAVE_DEBUGGING
214 0 : static bool ppg_note_check_initialized(PPG_Token__ *token)
215 : {
216 0 : PPG_Note *note = (PPG_Note *)token;
217 :
218 0 : bool assertion_failed = false;
219 :
220 : // Skip the parent call as we need a specialized check
221 : // assertion_failed |= ppg_token_check_initialized(token);
222 :
223 0 : if((note->super.misc.flags
224 0 : & PPG_Note_Flag_Match_Activation) == 0) {
225 0 : PPG_ASSERT_WARN(note->super.misc.state == PPG_Token_Matches);
226 : }
227 : else {
228 0 : PPG_ASSERT_WARN(note->super.misc.state == PPG_Token_Initialized);
229 : }
230 :
231 0 : PPG_ASSERT_WARN(token->misc.action_state == PPG_Action_Disabled);
232 :
233 0 : PPG_ASSERT_WARN(
234 : (note->super.misc.flags
235 : & PPG_Note_Type_Active) == 0);
236 :
237 0 : return assertion_failed;
238 : }
239 : #endif
240 :
241 : PPG_Token_Vtable ppg_note_vtable =
242 : {
243 : .match_event
244 : = (PPG_Token_Match_Event_Fun) ppg_note_match_event,
245 : .reset
246 : = (PPG_Token_Reset_Fun) ppg_note_reset,
247 : .destroy
248 : = (PPG_Token_Destroy_Fun) ppg_token_destroy,
249 : .equals
250 : = (PPG_Token_Equals_Fun) ppg_note_equals,
251 : .token_precedence
252 : = (PPG_Token_Precedence_Fun)ppg_note_token_precedence,
253 : .dynamic_size
254 : = (PPG_Token_Dynamic_Size_Requirement_Fun)ppg_note_dynamic_size,
255 : .placement_clone
256 : = (PPG_Token_Placement_Clone_Fun)ppg_note_placement_clone,
257 : .register_ptrs_for_compression
258 : = (PPG_Token_Register_Pointers_For_Compression)ppg_token_register_pointers_for_compression,
259 : .addresses_to_relative
260 : = (PPG_Token_Addresses_To_Relative)ppg_token_addresses_to_relative,
261 : .addresses_to_absolute
262 : = (PPG_Token_Addresses_To_Absolute)ppg_token_addresses_to_absolute
263 : #if PPG_PRINT_SELF_ENABLED
264 : ,
265 : .print_self
266 : = (PPG_Token_Print_Self_Fun) ppg_note_print_self
267 : #endif
268 :
269 : #if PPG_HAVE_DEBUGGING
270 : ,
271 : .check_initialized
272 : = (PPG_Token_Check_Initialized_Fun)ppg_note_check_initialized
273 : #endif
274 : };
275 :
276 1284 : PPG_Note *ppg_note_new(PPG_Note *note)
277 : {
278 : /* Explict call to parent constructor
279 : */
280 1284 : ppg_token_new((PPG_Token__*)note);
281 :
282 1284 : note->super.vtable = &ppg_note_vtable;
283 :
284 1284 : note->super.misc.flags = PPG_Token_Flags_Empty;
285 :
286 1284 : ppg_global_init_input(¬e->input);
287 :
288 1284 : return note;
289 : }
290 :
291 1284 : PPG_Note *ppg_note_alloc(void) {
292 1284 : return (PPG_Note*)PPG_MALLOC(sizeof(PPG_Note));
293 : }
|