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