1 (* nameKey.mod provides a dynamic binary tree name to key.
3 Copyright (C) 2015-2022 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius@glam.ac.uk>.
6 This file is part of GNU Modula-2.
8 GNU Modula-2 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GNU Modula-2 is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Modula-2; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. *)
22 IMPLEMENTATION MODULE nameKey ;
25 FROM SYSTEM IMPORT ADR ;
26 FROM Storage IMPORT ALLOCATE, DEALLOCATE ;
27 FROM Indexing IMPORT Index, InitIndex, GetIndice, PutIndice, InBounds ;
28 FROM StrIO IMPORT WriteString, WriteLn ;
29 FROM StdIO IMPORT Write ;
30 FROM NumberIO IMPORT WriteCard ;
31 FROM StrLib IMPORT StrLen ;
32 FROM libc IMPORT strlen ;
33 FROM ASCII IMPORT nul ;
37 ptrToChar = POINTER TO CHAR ;
39 nameNode = POINTER TO RECORD
46 comparison = (less, equal, greater) ;
49 binaryTree: nameNode ;
51 lastIndice: CARDINAL ;
55 getKey - returns the name, a, of the key, Key.
58 PROCEDURE getKey (key: Name; VAR a: ARRAY OF CHAR) ;
63 p := keyToCharStar (key) ;
66 WHILE (p#NIL) AND (i<=higha) AND (p^#nul) DO
79 isKey - returns TRUE if string, a, is currently a key.
80 We dont use the Compare function, we inline it and avoid
81 converting, a, into a String, for speed.
84 PROCEDURE isKey (a: ARRAY OF CHAR) : BOOLEAN ;
91 (* firstly set up the initial values of child, using sentinal node *)
92 child := binaryTree^.left ;
98 p := keyToCharStar (child^.key) ;
99 WHILE (i<=higha) AND (a[i]#nul) DO
102 child := child^.left ;
106 child := child^.right ;
109 IF (a[i]=nul) OR (i=higha)
129 doMakeKey - finds the name, n, in the tree or else create a name.
130 If a name is found then the string, n, is deallocated.
133 PROCEDURE doMakeKey (n: ptrToChar; higha: CARDINAL) : Name ;
140 result := findNodeAndParentInTree (n, child, father) ;
146 father^.left := child
150 father^.right := child
158 PutIndice (keyIndex, key, n)
162 DEALLOCATE (n, higha+1) ;
170 makeKey - returns the Key of the symbol, a. If a is not in the
171 name table then it is added, otherwise the Key of a is returned
172 directly. Note that the name table has no scope - it merely
173 presents a more convienient way of expressing strings. By a Key.
176 PROCEDURE makeKey (a: ARRAY OF CHAR) : Name ;
183 ALLOCATE (p, higha+1) ;
186 HALT (* out of memory error *)
197 RETURN doMakeKey (n, higha)
203 makekey - returns the Key of the symbol, a. If a is not in the
204 name table then it is added, otherwise the Key of a is returned
205 directly. Note that the name table has no scope - it merely
206 presents a more convienient way of expressing strings. By a Key.
207 These keys last for the duration of compilation.
210 PROCEDURE makekey (a: ADDRESS) : Name ;
221 higha := strlen (a) ;
222 ALLOCATE (p, higha+1) ;
225 HALT (* out of memory error *)
238 RETURN doMakeKey (n, higha)
245 lengthKey - returns the StrLen of Key.
248 PROCEDURE lengthKey (key: Name) : CARDINAL ;
253 p := keyToCharStar (key) ;
264 compare - return the result of Names[i] with Names[j]
267 PROCEDURE compare (pi: ptrToChar; j: Name) : comparison ;
272 pj := keyToCharStar(j) ;
275 WHILE (c1#nul) OR (c2#nul) DO
294 findNodeAndParentInTree - search BinaryTree for a name.
295 If this name is found in the BinaryTree then
296 child is set to this name and father is set to the node above.
297 A comparison is returned to assist adding entries into this tree.
300 PROCEDURE findNodeAndParentInTree (n: ptrToChar; VAR child, father: nameNode) : comparison ;
304 (* firstly set up the initial values of child and father, using sentinal node *)
305 father := binaryTree ;
306 child := binaryTree^.left ;
312 result := compare (n, child^.key) ;
320 child := child^.right
322 UNTIL (child=NIL) OR (result=equal) ;
325 END findNodeAndParentInTree ;
329 isSameExcludingCase - returns TRUE if key1 and key2 are
330 the same. It is case insensitive.
331 This function deliberately inlines CAP for speed.
334 PROCEDURE isSameExcludingCase (key1, key2: Name) : BOOLEAN ;
343 pi := keyToCharStar(key1) ;
344 pj := keyToCharStar(key2) ;
347 WHILE (c1#nul) AND (c2#nul) DO
349 (((c1>='A') AND (c1<='Z')) AND (c2=CHR(ORD(c1)-ORD('A')+ORD('a')))) OR
350 (((c2>='A') AND (c2<='Z')) AND (c1=CHR(ORD(c2)-ORD('A')+ORD('a'))))
357 (* difference found *)
363 END isSameExcludingCase ;
367 keyToCharStar - returns the C char * string equivalent for, key.
370 PROCEDURE keyToCharStar (key: Name) : ADDRESS ;
372 IF (key=NulName) OR (NOT InBounds (keyIndex, key))
376 RETURN GetIndice (keyIndex, key)
381 PROCEDURE writeKey (key: Name) ;
385 s := keyToCharStar (key) ;
386 WHILE (s#NIL) AND (s^#nul) DO
395 keyIndex := InitIndex(1) ;
397 binaryTree^.left := NIL