blob: ea52ccbc3fe39cd0342a386a3ea21d05f04776e5 [file] [log] [blame]
/* do not edit automatically generated by mc from nameKey. */
/* nameKey.mod provides a dynamic binary tree name to key.
Copyright (C) 2015-2025 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius@glam.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 "config.h"
#include "system.h"
#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 "GStorage.h"
# include "Gmcrts.h"
#if defined(__cplusplus)
# undef NULL
# define NULL 0
#endif
#define _nameKey_C
#include "GnameKey.h"
# 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__T1_r nameKey__T1;
typedef char *nameKey_ptrToChar;
typedef nameKey__T1 *nameKey_nameNode;
typedef enum {nameKey_less, nameKey_equal, nameKey_greater} nameKey_comparison;
struct nameKey__T1_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);
/*
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__T1));
father->left = child;
}
else if (result == nameKey_greater)
{
/* avoid dangling else. */
Storage_ALLOCATE ((void **) &child, sizeof (nameKey__T1));
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/m2/mc/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/m2/mc/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))
{
const_cast<char *>(a)[i] = (*p);
p += 1;
i += 1;
}
if (i <= higha)
{
const_cast<char *>(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 ();
}
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__T1));
binaryTree->left = NULL;
}
extern "C" void _M2_nameKey_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
{
}