blob: 14c644e20246e64155fd66a3065906185f327576 [file] [log] [blame]
/* do not edit automatically generated by mc from SymbolKey. */
/* SymbolKey.mod binary tree operations for storing symbols.
Copyright (C) 2001-2023 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
This file is part of GNU Modula-2.
GNU Modula-2 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Modula-2 is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Modula-2; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include <stdbool.h>
# if !defined (PROC_D)
# define PROC_D
typedef void (*PROC_t) (void);
typedef struct { PROC_t proc; } PROC;
# endif
# if !defined (FALSE)
# define FALSE (1==0)
# endif
#include <stddef.h>
# include "GStorage.h"
#if defined(__cplusplus)
# undef NULL
# define NULL 0
#endif
#define _SymbolKey_H
#define _SymbolKey_C
# include "GStorage.h"
# include "GStrIO.h"
# include "GNumberIO.h"
# include "GNameKey.h"
# include "GAssertion.h"
# include "GDebug.h"
# define SymbolKey_NulKey 0
typedef struct SymbolKey_IsSymbol_p SymbolKey_IsSymbol;
typedef struct SymbolKey_PerformOperation_p SymbolKey_PerformOperation;
typedef struct SymbolKey_Node_r SymbolKey_Node;
typedef SymbolKey_Node *SymbolKey_SymbolTree;
typedef bool (*SymbolKey_IsSymbol_t) (unsigned int);
struct SymbolKey_IsSymbol_p { SymbolKey_IsSymbol_t proc; };
typedef void (*SymbolKey_PerformOperation_t) (unsigned int);
struct SymbolKey_PerformOperation_p { SymbolKey_PerformOperation_t proc; };
struct SymbolKey_Node_r {
NameKey_Name KeyName;
unsigned int KeySym;
SymbolKey_SymbolTree Left;
SymbolKey_SymbolTree Right;
};
extern "C" void SymbolKey_InitTree (SymbolKey_SymbolTree *t);
extern "C" void SymbolKey_KillTree (SymbolKey_SymbolTree *t);
/*
ContainsSymKey - return TRUE if tree, t, contains an entry for, NameKey.
*/
extern "C" unsigned int SymbolKey_GetSymKey (SymbolKey_SymbolTree t, NameKey_Name NameKey);
/*
ContainsSymKey - return TRUE if tree, t, contains an entry for, NameKey.
*/
extern "C" void SymbolKey_PutSymKey (SymbolKey_SymbolTree t, NameKey_Name NameKey, unsigned int SymKey);
/*
DelSymKey - deletes an entry in the binary tree.
NB in order for this to work we must ensure that the InitTree sets
both Left and Right to NIL.
*/
extern "C" void SymbolKey_DelSymKey (SymbolKey_SymbolTree t, NameKey_Name NameKey);
/*
IsEmptyTree - returns true if SymbolTree, t, is empty.
*/
extern "C" bool SymbolKey_IsEmptyTree (SymbolKey_SymbolTree t);
/*
DoesTreeContainAny - returns true if SymbolTree, t, contains any
symbols which in turn return true when procedure,
P, is called with a symbol as its parameter.
The SymbolTree root is empty apart from the field,
Left, hence we need two procedures.
*/
extern "C" bool SymbolKey_DoesTreeContainAny (SymbolKey_SymbolTree t, SymbolKey_IsSymbol P);
/*
ForeachNodeDo - for each node in SymbolTree, t, a procedure, P,
is called with the node symbol as its parameter.
The tree root node only contains a legal Left pointer,
therefore we need two procedures to examine this tree.
*/
extern "C" void SymbolKey_ForeachNodeDo (SymbolKey_SymbolTree t, SymbolKey_PerformOperation P);
/*
ContainsSymKey - return TRUE if tree, t, contains an entry for, NameKey.
*/
extern "C" bool SymbolKey_ContainsSymKey (SymbolKey_SymbolTree t, NameKey_Name NameKey);
/*
NoOfNodes - returns the number of nodes in the tree t.
*/
extern "C" unsigned int SymbolKey_NoOfNodes (SymbolKey_SymbolTree t, SymbolKey_IsSymbol condition);
/*
ForeachNodeConditionDo - traverse the tree t and for any node which satisfied
condition call P.
*/
extern "C" void SymbolKey_ForeachNodeConditionDo (SymbolKey_SymbolTree t, SymbolKey_IsSymbol condition, SymbolKey_PerformOperation P);
/*
FindNodeParentInTree - find a node, child, in a binary tree, t, with name equal to n.
if an entry is found, parent is set to the node above child.
*/
static void FindNodeParentInTree (SymbolKey_SymbolTree t, NameKey_Name n, SymbolKey_SymbolTree *child, SymbolKey_SymbolTree *parent);
/*
SearchForAny - performs the search required for DoesTreeContainAny.
The root node always contains a nul data value,
therefore we must skip over it.
*/
static bool SearchForAny (SymbolKey_SymbolTree t, SymbolKey_IsSymbol P);
/*
SearchAndDo - searches all the nodes in SymbolTree, t, and
calls procedure, P, with a node as its parameter.
It traverse the tree in order.
*/
static void SearchAndDo (SymbolKey_SymbolTree t, SymbolKey_PerformOperation P);
/*
CountNodes - wrapper for NoOfNodes.
*/
static unsigned int CountNodes (SymbolKey_SymbolTree t, SymbolKey_IsSymbol condition, unsigned int count);
/*
SearchConditional - wrapper for ForeachNodeConditionDo.
*/
static void SearchConditional (SymbolKey_SymbolTree t, SymbolKey_IsSymbol condition, SymbolKey_PerformOperation P);
/*
FindNodeParentInTree - find a node, child, in a binary tree, t, with name equal to n.
if an entry is found, parent is set to the node above child.
*/
static void FindNodeParentInTree (SymbolKey_SymbolTree t, NameKey_Name n, SymbolKey_SymbolTree *child, SymbolKey_SymbolTree *parent)
{
/* remember to skip the sentinal value and assign parent and child */
(*parent) = t;
if (t == NULL)
{
Debug_Halt ((const char *) "parameter t should never be NIL", 31, (const char *) "../../gcc-read-write/gcc/m2/gm2-compiler/SymbolKey.mod", 54, (const char *) "FindNodeParentInTree", 20, 241);
}
Assertion_Assert (t->Right == NULL);
(*child) = t->Left;
if ((*child) != NULL)
{
do {
if (n < (*child)->KeyName)
{
(*parent) = (*child);
(*child) = (*child)->Left;
}
else if (n > (*child)->KeyName)
{
/* avoid dangling else. */
(*parent) = (*child);
(*child) = (*child)->Right;
}
} while (! (((*child) == NULL) || (n == (*child)->KeyName)));
}
}
/*
SearchForAny - performs the search required for DoesTreeContainAny.
The root node always contains a nul data value,
therefore we must skip over it.
*/
static bool SearchForAny (SymbolKey_SymbolTree t, SymbolKey_IsSymbol P)
{
if (t == NULL)
{
return false;
}
else
{
return (((*P.proc) (t->KeySym)) || (SearchForAny (t->Left, P))) || (SearchForAny (t->Right, P));
}
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
SearchAndDo - searches all the nodes in SymbolTree, t, and
calls procedure, P, with a node as its parameter.
It traverse the tree in order.
*/
static void SearchAndDo (SymbolKey_SymbolTree t, SymbolKey_PerformOperation P)
{
if (t != NULL)
{
SearchAndDo (t->Right, P);
(*P.proc) (t->KeySym);
SearchAndDo (t->Left, P);
}
}
/*
CountNodes - wrapper for NoOfNodes.
*/
static unsigned int CountNodes (SymbolKey_SymbolTree t, SymbolKey_IsSymbol condition, unsigned int count)
{
if (t != NULL)
{
if ((*condition.proc) (t->KeySym))
{
count += 1;
}
count = CountNodes (t->Left, condition, count);
count = CountNodes (t->Right, condition, count);
}
return count;
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
SearchConditional - wrapper for ForeachNodeConditionDo.
*/
static void SearchConditional (SymbolKey_SymbolTree t, SymbolKey_IsSymbol condition, SymbolKey_PerformOperation P)
{
if (t != NULL)
{
SearchConditional (t->Right, condition, P);
if ((t->KeySym != 0) && ((*condition.proc) (t->KeySym)))
{
(*P.proc) (t->KeySym);
}
SearchConditional (t->Left, condition, P);
}
}
extern "C" void SymbolKey_InitTree (SymbolKey_SymbolTree *t)
{
Storage_ALLOCATE ((void **) &(*t), sizeof (SymbolKey_Node)); /* The value entity */
(*t)->Left = NULL;
(*t)->Right = NULL;
}
extern "C" void SymbolKey_KillTree (SymbolKey_SymbolTree *t)
{
/*
we used to get problems compiling KillTree below - so it was split
into the two procedures below.
PROCEDURE KillTree (VAR t: SymbolTree) ;
BEGIN
IF t#NIL
THEN
Kill(t) ; Would like to place Kill in here but the compiler
gives a type incompatible error... so i've split
the procedure into two. - Problem i think with
VAR t at the top?
t := NIL
END
END KillTree ;
PROCEDURE Kill (t: SymbolTree) ;
BEGIN
IF t#NIL
THEN
Kill(t^.Left) ;
Kill(t^.Right) ;
DISPOSE(t)
END
END Kill ;
*/
if ((*t) != NULL)
{
SymbolKey_KillTree (&(*t)->Left);
SymbolKey_KillTree (&(*t)->Right);
Storage_DEALLOCATE ((void **) &(*t), sizeof (SymbolKey_Node));
(*t) = NULL;
}
}
/*
ContainsSymKey - return TRUE if tree, t, contains an entry for, NameKey.
*/
extern "C" unsigned int SymbolKey_GetSymKey (SymbolKey_SymbolTree t, NameKey_Name NameKey)
{
SymbolKey_SymbolTree father;
SymbolKey_SymbolTree child;
FindNodeParentInTree (t, NameKey, &child, &father);
if (child == NULL)
{
return static_cast<unsigned int> (SymbolKey_NulKey);
}
else
{
return child->KeySym;
}
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
ContainsSymKey - return TRUE if tree, t, contains an entry for, NameKey.
*/
extern "C" void SymbolKey_PutSymKey (SymbolKey_SymbolTree t, NameKey_Name NameKey, unsigned int SymKey)
{
SymbolKey_SymbolTree father;
SymbolKey_SymbolTree child;
FindNodeParentInTree (t, NameKey, &child, &father);
if (child == NULL)
{
/* no child found, now is NameKey less than father or greater? */
if (father == t)
{
/* empty tree, add it to the left branch of t */
Storage_ALLOCATE ((void **) &child, sizeof (SymbolKey_Node));
father->Left = child;
}
else
{
if (NameKey < father->KeyName)
{
Storage_ALLOCATE ((void **) &child, sizeof (SymbolKey_Node));
father->Left = child;
}
else if (NameKey > father->KeyName)
{
/* avoid dangling else. */
Storage_ALLOCATE ((void **) &child, sizeof (SymbolKey_Node));
father->Right = child;
}
}
child->Right = NULL;
child->Left = NULL;
child->KeySym = SymKey;
child->KeyName = NameKey;
}
else
{
Debug_Halt ((const char *) "symbol already stored", 21, (const char *) "../../gcc-read-write/gcc/m2/gm2-compiler/SymbolKey.mod", 54, (const char *) "PutSymKey", 9, 156);
}
}
/*
DelSymKey - deletes an entry in the binary tree.
NB in order for this to work we must ensure that the InitTree sets
both Left and Right to NIL.
*/
extern "C" void SymbolKey_DelSymKey (SymbolKey_SymbolTree t, NameKey_Name NameKey)
{
SymbolKey_SymbolTree i;
SymbolKey_SymbolTree child;
SymbolKey_SymbolTree father;
FindNodeParentInTree (t, NameKey, &child, &father); /* find father and child of the node */
if ((child != NULL) && (child->KeyName == NameKey))
{
/* Have found the node to be deleted */
if (father->Right == child)
{
/* most branch of child^.Left. */
if (child->Left != NULL)
{
/* Scan for Right most node of child^.Left */
i = child->Left;
while (i->Right != NULL)
{
i = i->Right;
}
i->Right = child->Right;
father->Right = child->Left;
}
else
{
/* (as in a single linked list) to child^.Right */
father->Right = child->Right;
}
Storage_DEALLOCATE ((void **) &child, sizeof (SymbolKey_Node));
}
else
{
/* branch of child^.Right */
if (child->Right != NULL)
{
/* Scan for Left most node of child^.Right */
i = child->Right;
while (i->Left != NULL)
{
i = i->Left;
}
i->Left = child->Left;
father->Left = child->Right;
}
else
{
/* (as in a single linked list) to child^.Left. */
father->Left = child->Left;
}
Storage_DEALLOCATE ((void **) &child, sizeof (SymbolKey_Node));
}
}
else
{
Debug_Halt ((const char *) "trying to delete a symbol that is not in the tree - the compiler never expects this to occur", 92, (const char *) "../../gcc-read-write/gcc/m2/gm2-compiler/SymbolKey.mod", 54, (const char *) "DelSymKey", 9, 223);
}
}
/*
IsEmptyTree - returns true if SymbolTree, t, is empty.
*/
extern "C" bool SymbolKey_IsEmptyTree (SymbolKey_SymbolTree t)
{
return t->Left == NULL;
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
DoesTreeContainAny - returns true if SymbolTree, t, contains any
symbols which in turn return true when procedure,
P, is called with a symbol as its parameter.
The SymbolTree root is empty apart from the field,
Left, hence we need two procedures.
*/
extern "C" bool SymbolKey_DoesTreeContainAny (SymbolKey_SymbolTree t, SymbolKey_IsSymbol P)
{
return SearchForAny (t->Left, P);
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
ForeachNodeDo - for each node in SymbolTree, t, a procedure, P,
is called with the node symbol as its parameter.
The tree root node only contains a legal Left pointer,
therefore we need two procedures to examine this tree.
*/
extern "C" void SymbolKey_ForeachNodeDo (SymbolKey_SymbolTree t, SymbolKey_PerformOperation P)
{
SearchAndDo (t->Left, P);
}
/*
ContainsSymKey - return TRUE if tree, t, contains an entry for, NameKey.
*/
extern "C" bool SymbolKey_ContainsSymKey (SymbolKey_SymbolTree t, NameKey_Name NameKey)
{
SymbolKey_SymbolTree father;
SymbolKey_SymbolTree child;
FindNodeParentInTree (t, NameKey, &child, &father);
return child != NULL;
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
NoOfNodes - returns the number of nodes in the tree t.
*/
extern "C" unsigned int SymbolKey_NoOfNodes (SymbolKey_SymbolTree t, SymbolKey_IsSymbol condition)
{
return CountNodes (t->Left, condition, 0);
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
ForeachNodeConditionDo - traverse the tree t and for any node which satisfied
condition call P.
*/
extern "C" void SymbolKey_ForeachNodeConditionDo (SymbolKey_SymbolTree t, SymbolKey_IsSymbol condition, SymbolKey_PerformOperation P)
{
if (t != NULL)
{
Assertion_Assert (t->Right == NULL);
SearchConditional (t->Left, condition, P);
}
}
extern "C" void _M2_SymbolKey_init (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
{
}
extern "C" void _M2_SymbolKey_fini (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
{
}