| /* 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[]) |
| { |
| } |