blob: 5df940d8dd26268233acc59d9479ad7f26d5d8da [file] [log] [blame]
/* do not edit automatically generated by mc from NameKey. */
/* NameKey.mod provides a dynamic binary tree name to key.
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 (TRUE)
# define TRUE (1==1)
# endif
# if !defined (FALSE)
# define FALSE (1==0)
# endif
#include <stddef.h>
#include <string.h>
#include <limits.h>
# include "GStorage.h"
# include "Gmcrts.h"
#if defined(__cplusplus)
# undef NULL
# define NULL 0
#endif
#define _NameKey_H
#define _NameKey_C
# include "GSYSTEM.h"
# include "GStorage.h"
# include "GIndexing.h"
# include "GStrIO.h"
# include "GStdIO.h"
# include "GNumberIO.h"
# include "GStrLib.h"
# include "Glibc.h"
# include "GASCII.h"
# include "GM2RTS.h"
# define NameKey_NulName 0
typedef unsigned int NameKey_Name;
typedef struct NameKey_Node_r NameKey_Node;
typedef char *NameKey_PtrToChar;
typedef NameKey_Node *NameKey_NameNode;
typedef enum {NameKey_less, NameKey_equal, NameKey_greater} NameKey_Comparison;
struct NameKey_Node_r {
NameKey_PtrToChar Data;
NameKey_Name Key;
NameKey_NameNode Left;
NameKey_NameNode Right;
};
static NameKey_NameNode BinaryTree;
static Indexing_Index KeyIndex;
static unsigned int LastIndice;
/*
MakeKey - returns the Key of the symbol, a. If a is not in the
name table then it is added, otherwise the Key of a is returned
directly. Note that the name table has no scope - it merely
presents a more convienient way of expressing strings. By a Key.
*/
extern "C" NameKey_Name NameKey_MakeKey (const char *a_, unsigned int _a_high);
/*
makekey - returns the Key of the symbol, a. If a is not in the
name table then it is added, otherwise the Key of a is returned
directly. Note that the name table has no scope - it merely
presents a more convienient way of expressing strings. By a Key.
These keys last for the duration of compilation.
*/
extern "C" NameKey_Name NameKey_makekey (void * a);
/*
GetKey - returns the name, a, of the key, Key.
*/
extern "C" void NameKey_GetKey (NameKey_Name key, char *a, unsigned int _a_high);
/*
LengthKey - returns the StrLen of Key.
*/
extern "C" unsigned int NameKey_LengthKey (NameKey_Name Key);
/*
IsKey - returns TRUE if string, a, is currently a key.
We dont use the Compare function, we inline it and avoid
converting, a, into a String, for speed.
*/
extern "C" bool NameKey_IsKey (const char *a_, unsigned int _a_high);
/*
KeyToCharStar - returns the C char * string equivalent for, key.
*/
extern "C" void NameKey_WriteKey (NameKey_Name key);
/*
IsSameExcludingCase - returns TRUE if key1 and key2 are
the same. It is case insensitive.
This function deliberately inlines CAP for speed.
*/
extern "C" bool NameKey_IsSameExcludingCase (NameKey_Name key1, NameKey_Name key2);
/*
KeyToCharStar - returns the C char * string equivalent for, key.
*/
extern "C" void * NameKey_KeyToCharStar (NameKey_Name key);
/*
CharKey - returns the key[i] character.
*/
extern "C" char NameKey_CharKey (NameKey_Name key, unsigned int i);
/*
DoMakeKey - finds the name, n, in the tree or else create a name.
If a name is found then the string, n, is deallocated.
*/
static NameKey_Name DoMakeKey (NameKey_PtrToChar n, unsigned int higha);
/*
Compare - return the result of Names[i] with Names[j]
*/
static NameKey_Comparison Compare (NameKey_PtrToChar pi, NameKey_Name j);
/*
FindNodeAndParentInTree - search BinaryTree for a name.
If this name is found in the BinaryTree then
child is set to this name and father is set to the node above.
A comparison is returned to assist adding entries into this tree.
*/
static NameKey_Comparison FindNodeAndParentInTree (NameKey_PtrToChar n, NameKey_NameNode *child, NameKey_NameNode *father);
/*
DoMakeKey - finds the name, n, in the tree or else create a name.
If a name is found then the string, n, is deallocated.
*/
static NameKey_Name DoMakeKey (NameKey_PtrToChar n, unsigned int higha)
{
NameKey_Comparison result;
NameKey_NameNode father;
NameKey_NameNode child;
NameKey_Name k;
result = FindNodeAndParentInTree (n, &child, &father);
if (child == NULL)
{
if (result == NameKey_less)
{
Storage_ALLOCATE ((void **) &child, sizeof (NameKey_Node));
father->Left = child;
}
else if (result == NameKey_greater)
{
/* avoid dangling else. */
Storage_ALLOCATE ((void **) &child, sizeof (NameKey_Node));
father->Right = child;
}
child->Right = NULL;
child->Left = NULL;
LastIndice += 1;
child->Key = LastIndice;
child->Data = n;
Indexing_PutIndice (KeyIndex, child->Key, reinterpret_cast<void *> (n));
k = LastIndice;
}
else
{
Storage_DEALLOCATE (reinterpret_cast<void **> (&n), higha+1);
k = child->Key;
}
return k;
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
Compare - return the result of Names[i] with Names[j]
*/
static NameKey_Comparison Compare (NameKey_PtrToChar pi, NameKey_Name j)
{
NameKey_PtrToChar pj;
char c1;
char c2;
pj = static_cast<NameKey_PtrToChar> (NameKey_KeyToCharStar (j));
c1 = (*pi);
c2 = (*pj);
while ((c1 != ASCII_nul) || (c2 != ASCII_nul))
{
if (c1 < c2)
{
return NameKey_less;
}
else if (c1 > c2)
{
/* avoid dangling else. */
return NameKey_greater;
}
else
{
/* avoid dangling else. */
pi += 1;
pj += 1;
c1 = (*pi);
c2 = (*pj);
}
}
return NameKey_equal;
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
FindNodeAndParentInTree - search BinaryTree for a name.
If this name is found in the BinaryTree then
child is set to this name and father is set to the node above.
A comparison is returned to assist adding entries into this tree.
*/
static NameKey_Comparison FindNodeAndParentInTree (NameKey_PtrToChar n, NameKey_NameNode *child, NameKey_NameNode *father)
{
NameKey_Comparison result;
/* firstly set up the initial values of child and father, using sentinal node */
(*father) = BinaryTree;
(*child) = BinaryTree->Left;
if ((*child) == NULL)
{
return NameKey_less;
}
else
{
do {
result = Compare (n, (*child)->Key);
if (result == NameKey_less)
{
(*father) = (*child);
(*child) = (*child)->Left;
}
else if (result == NameKey_greater)
{
/* avoid dangling else. */
(*father) = (*child);
(*child) = (*child)->Right;
}
} while (! (((*child) == NULL) || (result == NameKey_equal)));
return result;
}
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
MakeKey - returns the Key of the symbol, a. If a is not in the
name table then it is added, otherwise the Key of a is returned
directly. Note that the name table has no scope - it merely
presents a more convienient way of expressing strings. By a Key.
*/
extern "C" NameKey_Name NameKey_MakeKey (const char *a_, unsigned int _a_high)
{
NameKey_PtrToChar n;
NameKey_PtrToChar p;
unsigned int i;
unsigned int higha;
char a[_a_high+1];
/* make a local copy of each unbounded array. */
memcpy (a, a_, _a_high+1);
higha = StrLib_StrLen ((const char *) a, _a_high);
Storage_ALLOCATE (reinterpret_cast<void **> (&p), higha+1);
if (p == NULL)
{
M2RTS_HALT (-1); /* out of memory error */
__builtin_unreachable ();
}
else
{
n = p;
i = 0;
while (i < higha)
{
(*p) = a[i];
i += 1;
p += 1;
}
(*p) = ASCII_nul;
return DoMakeKey (n, higha);
}
ReturnException ("../../gcc-read-write/gcc/m2/gm2-compiler/NameKey.def", 20, 1);
__builtin_unreachable ();
}
/*
makekey - returns the Key of the symbol, a. If a is not in the
name table then it is added, otherwise the Key of a is returned
directly. Note that the name table has no scope - it merely
presents a more convienient way of expressing strings. By a Key.
These keys last for the duration of compilation.
*/
extern "C" NameKey_Name NameKey_makekey (void * a)
{
NameKey_PtrToChar n;
NameKey_PtrToChar p;
NameKey_PtrToChar pa;
unsigned int i;
unsigned int higha;
if (a == NULL)
{
return NameKey_NulName;
}
else
{
higha = static_cast<unsigned int> (libc_strlen (a));
Storage_ALLOCATE (reinterpret_cast<void **> (&p), higha+1);
if (p == NULL)
{
M2RTS_HALT (-1); /* out of memory error */
__builtin_unreachable ();
}
else
{
n = p;
pa = static_cast<NameKey_PtrToChar> (a);
i = 0;
while (i < higha)
{
(*p) = (*pa);
i += 1;
p += 1;
pa += 1;
}
(*p) = ASCII_nul;
return DoMakeKey (n, higha);
}
}
ReturnException ("../../gcc-read-write/gcc/m2/gm2-compiler/NameKey.def", 20, 1);
__builtin_unreachable ();
}
/*
GetKey - returns the name, a, of the key, Key.
*/
extern "C" void NameKey_GetKey (NameKey_Name key, char *a, unsigned int _a_high)
{
NameKey_PtrToChar p;
unsigned int i;
unsigned int higha;
p = static_cast<NameKey_PtrToChar> (NameKey_KeyToCharStar (key));
i = 0;
higha = _a_high;
while (((p != NULL) && (i <= higha)) && ((*p) != ASCII_nul))
{
a[i] = (*p);
p += 1;
i += 1;
}
if (i <= higha)
{
a[i] = ASCII_nul;
}
}
/*
LengthKey - returns the StrLen of Key.
*/
extern "C" unsigned int NameKey_LengthKey (NameKey_Name Key)
{
unsigned int i;
NameKey_PtrToChar p;
p = static_cast<NameKey_PtrToChar> (NameKey_KeyToCharStar (Key));
i = 0;
while ((*p) != ASCII_nul)
{
i += 1;
p += 1;
}
return i;
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
IsKey - returns TRUE if string, a, is currently a key.
We dont use the Compare function, we inline it and avoid
converting, a, into a String, for speed.
*/
extern "C" bool NameKey_IsKey (const char *a_, unsigned int _a_high)
{
NameKey_NameNode child;
NameKey_PtrToChar p;
unsigned int i;
unsigned int higha;
char a[_a_high+1];
/* make a local copy of each unbounded array. */
memcpy (a, a_, _a_high+1);
/* firstly set up the initial values of child, using sentinal node */
child = BinaryTree->Left;
if (child != NULL)
{
do {
i = 0;
higha = _a_high;
p = static_cast<NameKey_PtrToChar> (NameKey_KeyToCharStar (child->Key));
while ((i <= higha) && (a[i] != ASCII_nul))
{
if (a[i] < (*p))
{
child = child->Left;
i = higha;
}
else if (a[i] > (*p))
{
/* avoid dangling else. */
child = child->Right;
i = higha;
}
else
{
/* avoid dangling else. */
if ((a[i] == ASCII_nul) || (i == higha))
{
/* avoid gcc warning by using compound statement even if not strictly necessary. */
if ((*p) == ASCII_nul)
{
return true;
}
else
{
child = child->Left;
}
}
p += 1;
}
i += 1;
}
} while (! (child == NULL));
}
return false;
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
KeyToCharStar - returns the C char * string equivalent for, key.
*/
extern "C" void NameKey_WriteKey (NameKey_Name key)
{
NameKey_PtrToChar s;
s = static_cast<NameKey_PtrToChar> (NameKey_KeyToCharStar (key));
while ((s != NULL) && ((*s) != ASCII_nul))
{
StdIO_Write ((*s));
s += 1;
}
}
/*
IsSameExcludingCase - returns TRUE if key1 and key2 are
the same. It is case insensitive.
This function deliberately inlines CAP for speed.
*/
extern "C" bool NameKey_IsSameExcludingCase (NameKey_Name key1, NameKey_Name key2)
{
NameKey_PtrToChar pi;
NameKey_PtrToChar pj;
char c1;
char c2;
if (key1 == key2)
{
return true;
}
else
{
pi = static_cast<NameKey_PtrToChar> (NameKey_KeyToCharStar (key1));
pj = static_cast<NameKey_PtrToChar> (NameKey_KeyToCharStar (key2));
c1 = (*pi);
c2 = (*pj);
while ((c1 != ASCII_nul) && (c2 != ASCII_nul))
{
if (((c1 == c2) || (((c1 >= 'A') && (c1 <= 'Z')) && (c2 == ((char) (( ((unsigned int) (c1))- ((unsigned int) ('A')))+ ((unsigned int) ('a'))))))) || (((c2 >= 'A') && (c2 <= 'Z')) && (c1 == ((char) (( ((unsigned int) (c2))- ((unsigned int) ('A')))+ ((unsigned int) ('a')))))))
{
pi += 1;
pj += 1;
c1 = (*pi);
c2 = (*pj);
}
else
{
/* difference found */
return false;
}
}
return c1 == c2;
}
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
KeyToCharStar - returns the C char * string equivalent for, key.
*/
extern "C" void * NameKey_KeyToCharStar (NameKey_Name key)
{
if ((key == NameKey_NulName) || (! (Indexing_InBounds (KeyIndex, key))))
{
return NULL;
}
else
{
return Indexing_GetIndice (KeyIndex, key);
}
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
/*
CharKey - returns the key[i] character.
*/
extern "C" char NameKey_CharKey (NameKey_Name key, unsigned int i)
{
NameKey_PtrToChar p;
if (i >= (NameKey_LengthKey (key)))
{
M2RTS_HALT (-1);
__builtin_unreachable ();
}
p = static_cast<NameKey_PtrToChar> (NameKey_KeyToCharStar (key));
p += i;
return (*p);
/* static analysis guarentees a RETURN statement will be used before here. */
__builtin_unreachable ();
}
extern "C" void _M2_NameKey_init (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
{
LastIndice = 0;
KeyIndex = Indexing_InitIndex (1);
Storage_ALLOCATE ((void **) &BinaryTree, sizeof (NameKey_Node));
BinaryTree->Left = NULL;
}
extern "C" void _M2_NameKey_fini (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[])
{
}