1 /* do not edit automatically generated by mc from symbolKey. */
2 /* symbolKey.mod provides binary tree operations for storing symbols.
4 Copyright (C) 2015-2022 Free Software Foundation, Inc.
5 Contributed by Gaius Mulley <gaius@glam.ac.uk>.
7 This file is part of GNU Modula-2.
9 GNU Modula-2 is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
14 GNU Modula-2 is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Modula-2; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
25 # if !defined (PROC_D)
27 typedef void (*PROC_t
) (void);
28 typedef struct { PROC_t proc
; } PROC
;
35 # include "GStorage.h"
36 #if defined(__cplusplus)
43 # include "GStorage.h"
45 # include "GNumberIO.h"
47 # include "GnameKey.h"
49 # define symbolKey_NulKey NULL
50 typedef struct symbolKey_isSymbol_p symbolKey_isSymbol
;
52 typedef struct symbolKey_performOperation_p symbolKey_performOperation
;
54 typedef struct _T1_r _T1
;
56 typedef _T1
*symbolKey_symbolTree
;
58 typedef unsigned int (*symbolKey_isSymbol_t
) (void *);
59 struct symbolKey_isSymbol_p
{ symbolKey_isSymbol_t proc
; };
61 typedef void (*symbolKey_performOperation_t
) (void *);
62 struct symbolKey_performOperation_p
{ symbolKey_performOperation_t proc
; };
67 symbolKey_symbolTree left
;
68 symbolKey_symbolTree right
;
71 extern "C" symbolKey_symbolTree
symbolKey_initTree (void);
72 extern "C" void symbolKey_killTree (symbolKey_symbolTree
*t
);
73 extern "C" void * symbolKey_getSymKey (symbolKey_symbolTree t
, nameKey_Name name
);
74 extern "C" void symbolKey_putSymKey (symbolKey_symbolTree t
, nameKey_Name name
, void * key
);
77 delSymKey - deletes an entry in the binary tree.
79 NB in order for this to work we must ensure that the InitTree sets
80 both left and right to NIL.
83 extern "C" void symbolKey_delSymKey (symbolKey_symbolTree t
, nameKey_Name name
);
86 isEmptyTree - returns true if symbolTree, t, is empty.
89 extern "C" unsigned int symbolKey_isEmptyTree (symbolKey_symbolTree t
);
92 doesTreeContainAny - returns true if symbolTree, t, contains any
93 symbols which in turn return true when procedure,
94 p, is called with a symbol as its parameter.
95 The symbolTree root is empty apart from the field,
96 left, hence we need two procedures.
99 extern "C" unsigned int symbolKey_doesTreeContainAny (symbolKey_symbolTree t
, symbolKey_isSymbol p
);
102 foreachNodeDo - for each node in symbolTree, t, a procedure, p,
103 is called with the node symbol as its parameter.
104 The tree root node only contains a legal left pointer,
105 therefore we need two procedures to examine this tree.
108 extern "C" void symbolKey_foreachNodeDo (symbolKey_symbolTree t
, symbolKey_performOperation p
);
111 findNodeAndParentInTree - find a node, child, in a binary tree, t, with name equal to n.
112 if an entry is found, father is set to the node above child.
115 static void findNodeAndParentInTree (symbolKey_symbolTree t
, nameKey_Name n
, symbolKey_symbolTree
*child
, symbolKey_symbolTree
*father
);
118 searchForAny - performs the search required for doesTreeContainAny.
119 The root node always contains a nul data value,
120 therefore we must skip over it.
123 static unsigned int searchForAny (symbolKey_symbolTree t
, symbolKey_isSymbol p
);
126 searchAndDo - searches all the nodes in symbolTree, t, and
127 calls procedure, p, with a node as its parameter.
128 It traverse the tree in order.
131 static void searchAndDo (symbolKey_symbolTree t
, symbolKey_performOperation p
);
135 findNodeAndParentInTree - find a node, child, in a binary tree, t, with name equal to n.
136 if an entry is found, father is set to the node above child.
139 static void findNodeAndParentInTree (symbolKey_symbolTree t
, nameKey_Name n
, symbolKey_symbolTree
*child
, symbolKey_symbolTree
*father
)
141 /* remember to skip the sentinal value and assign father and child */
145 Debug_Halt ((const char *) "parameter t should never be NIL", 31, 203, (const char *) "../../gcc-git-devel-modula2/gcc/m2/mc/symbolKey.mod", 51);
148 if ((*child
) != NULL
)
151 if (n
< (*child
)->name
)
153 (*father
) = (*child
);
154 (*child
) = (*child
)->left
;
156 else if (n
> (*child
)->name
)
158 /* avoid dangling else. */
159 (*father
) = (*child
);
160 (*child
) = (*child
)->right
;
162 } while (! (((*child
) == NULL
) || (n
== (*child
)->name
)));
168 searchForAny - performs the search required for doesTreeContainAny.
169 The root node always contains a nul data value,
170 therefore we must skip over it.
173 static unsigned int searchForAny (symbolKey_symbolTree t
, symbolKey_isSymbol p
)
181 return (((*p
.proc
) (t
->key
)) || (searchForAny (t
->left
, p
))) || (searchForAny (t
->right
, p
));
183 /* static analysis guarentees a RETURN statement will be used before here. */
184 __builtin_unreachable ();
189 searchAndDo - searches all the nodes in symbolTree, t, and
190 calls procedure, p, with a node as its parameter.
191 It traverse the tree in order.
194 static void searchAndDo (symbolKey_symbolTree t
, symbolKey_performOperation p
)
198 searchAndDo (t
->right
, p
);
200 searchAndDo (t
->left
, p
);
204 extern "C" symbolKey_symbolTree
symbolKey_initTree (void)
206 symbolKey_symbolTree t
;
208 Storage_ALLOCATE ((void **) &t
, sizeof (_T1
)); /* The value entity */
212 /* static analysis guarentees a RETURN statement will be used before here. */
213 __builtin_unreachable ();
216 extern "C" void symbolKey_killTree (symbolKey_symbolTree
*t
)
220 symbolKey_killTree (&(*t
)->left
);
221 symbolKey_killTree (&(*t
)->right
);
222 Storage_DEALLOCATE ((void **) &(*t
), sizeof (_T1
));
227 extern "C" void * symbolKey_getSymKey (symbolKey_symbolTree t
, nameKey_Name name
)
229 symbolKey_symbolTree father
;
230 symbolKey_symbolTree child
;
234 return symbolKey_NulKey
;
238 findNodeAndParentInTree (t
, name
, &child
, &father
);
241 return symbolKey_NulKey
;
248 /* static analysis guarentees a RETURN statement will be used before here. */
249 __builtin_unreachable ();
252 extern "C" void symbolKey_putSymKey (symbolKey_symbolTree t
, nameKey_Name name
, void * key
)
254 symbolKey_symbolTree father
;
255 symbolKey_symbolTree child
;
257 findNodeAndParentInTree (t
, name
, &child
, &father
);
260 /* no child found, now is name less than father or greater? */
263 /* empty tree, add it to the left branch of t */
264 Storage_ALLOCATE ((void **) &child
, sizeof (_T1
));
265 father
->left
= child
;
269 if (name
< father
->name
)
271 Storage_ALLOCATE ((void **) &child
, sizeof (_T1
));
272 father
->left
= child
;
274 else if (name
> father
->name
)
276 /* avoid dangling else. */
277 Storage_ALLOCATE ((void **) &child
, sizeof (_T1
));
278 father
->right
= child
;
288 Debug_Halt ((const char *) "symbol already stored", 21, 119, (const char *) "../../gcc-git-devel-modula2/gcc/m2/mc/symbolKey.mod", 51);
294 delSymKey - deletes an entry in the binary tree.
296 NB in order for this to work we must ensure that the InitTree sets
297 both left and right to NIL.
300 extern "C" void symbolKey_delSymKey (symbolKey_symbolTree t
, nameKey_Name name
)
302 symbolKey_symbolTree i
;
303 symbolKey_symbolTree child
;
304 symbolKey_symbolTree father
;
306 findNodeAndParentInTree (t
, name
, &child
, &father
); /* find father and child of the node */
307 if ((child
!= NULL
) && (child
->name
== name
))
309 /* Have found the node to be deleted */
310 if (father
->right
== child
)
312 /* most branch of child^.left. */
313 if (child
->left
!= NULL
)
315 /* Scan for right most node of child^.left */
317 while (i
->right
!= NULL
)
321 i
->right
= child
->right
;
322 father
->right
= child
->left
;
326 /* (as in a single linked list) to child^.right */
327 father
->right
= child
->right
;
329 Storage_DEALLOCATE ((void **) &child
, sizeof (_T1
));
333 /* branch of child^.right */
334 if (child
->right
!= NULL
)
336 /* Scan for left most node of child^.right */
338 while (i
->left
!= NULL
)
342 i
->left
= child
->left
;
343 father
->left
= child
->right
;
347 /* (as in a single linked list) to child^.left. */
348 father
->left
= child
->left
;
350 Storage_DEALLOCATE ((void **) &child
, sizeof (_T1
));
355 Debug_Halt ((const char *) "trying to delete a symbol that is not in the tree - the compiler never expects this to occur", 92, 186, (const char *) "../../gcc-git-devel-modula2/gcc/m2/mc/symbolKey.mod", 51);
361 isEmptyTree - returns true if symbolTree, t, is empty.
364 extern "C" unsigned int symbolKey_isEmptyTree (symbolKey_symbolTree t
)
366 return t
->left
== NULL
;
367 /* static analysis guarentees a RETURN statement will be used before here. */
368 __builtin_unreachable ();
373 doesTreeContainAny - returns true if symbolTree, t, contains any
374 symbols which in turn return true when procedure,
375 p, is called with a symbol as its parameter.
376 The symbolTree root is empty apart from the field,
377 left, hence we need two procedures.
380 extern "C" unsigned int symbolKey_doesTreeContainAny (symbolKey_symbolTree t
, symbolKey_isSymbol p
)
382 return searchForAny (t
->left
, p
);
383 /* static analysis guarentees a RETURN statement will be used before here. */
384 __builtin_unreachable ();
389 foreachNodeDo - for each node in symbolTree, t, a procedure, p,
390 is called with the node symbol as its parameter.
391 The tree root node only contains a legal left pointer,
392 therefore we need two procedures to examine this tree.
395 extern "C" void symbolKey_foreachNodeDo (symbolKey_symbolTree t
, symbolKey_performOperation p
)
397 searchAndDo (t
->left
, p
);
400 extern "C" void _M2_symbolKey_init (__attribute__((unused
)) int argc
,__attribute__((unused
)) char *argv
[],__attribute__((unused
)) char *envp
[])
404 extern "C" void _M2_symbolKey_finish (__attribute__((unused
)) int argc
,__attribute__((unused
)) char *argv
[],__attribute__((unused
)) char *envp
[])