/* do not edit automatically generated by mc from nameKey. */ /* nameKey.mod provides a dynamic binary tree name to key. Copyright (C) 2015-2024 Free Software Foundation, Inc. Contributed by Gaius Mulley . 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 . */ #include "config.h" #include "system.h" #include # 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_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__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 (n)); k = lastIndice; } else { Storage_DEALLOCATE (reinterpret_cast (&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_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 (&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 (libc_strlen (a)); Storage_ALLOCATE (reinterpret_cast (&p), higha+1); if (p == NULL) { M2RTS_HALT (-1); /* out of memory error */ __builtin_unreachable (); } else { n = p; pa = static_cast (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_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_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_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_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_keyToCharStar (key1)); pj = static_cast (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[]) { }