]>
Commit | Line | Data |
---|---|---|
1eee94d3 GM |
1 | /* do not edit automatically generated by mc from nameKey. */ |
2 | /* nameKey.mod provides a dynamic binary tree name to key. | |
3 | ||
83ffe9cd | 4 | Copyright (C) 2015-2023 Free Software Foundation, Inc. |
1eee94d3 GM |
5 | Contributed by Gaius Mulley <gaius@glam.ac.uk>. |
6 | ||
7 | This file is part of GNU Modula-2. | |
8 | ||
9 | GNU Modula-2 is free software; you can redistribute it and/or modify | |
10 | it under the terms of the GNU General Public License as published by | |
11 | the Free Software Foundation; either version 3, or (at your option) | |
12 | any later version. | |
13 | ||
14 | GNU Modula-2 is distributed in the hope that it will be useful, but | |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | General Public License for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
20 | along with GNU Modula-2; see the file COPYING3. If not see | |
21 | <http://www.gnu.org/licenses/>. */ | |
22 | ||
23 | #include "config.h" | |
24 | #include "system.h" | |
25 | # if !defined (PROC_D) | |
26 | # define PROC_D | |
27 | typedef void (*PROC_t) (void); | |
28 | typedef struct { PROC_t proc; } PROC; | |
29 | # endif | |
30 | ||
31 | # if !defined (TRUE) | |
32 | # define TRUE (1==1) | |
33 | # endif | |
34 | ||
35 | # if !defined (FALSE) | |
36 | # define FALSE (1==0) | |
37 | # endif | |
38 | ||
39 | # include "GStorage.h" | |
40 | # include "Gmcrts.h" | |
41 | #if defined(__cplusplus) | |
42 | # undef NULL | |
43 | # define NULL 0 | |
44 | #endif | |
45 | #define _nameKey_H | |
46 | #define _nameKey_C | |
47 | ||
48 | # include "GSYSTEM.h" | |
49 | # include "GStorage.h" | |
50 | # include "GIndexing.h" | |
51 | # include "GStrIO.h" | |
52 | # include "GStdIO.h" | |
53 | # include "GNumberIO.h" | |
54 | # include "GStrLib.h" | |
55 | # include "Glibc.h" | |
56 | # include "GASCII.h" | |
57 | # include "GM2RTS.h" | |
58 | ||
59 | # define nameKey_NulName 0 | |
60 | typedef unsigned int nameKey_Name; | |
61 | ||
62 | typedef struct nameKey__T1_r nameKey__T1; | |
63 | ||
64 | typedef char *nameKey_ptrToChar; | |
65 | ||
66 | typedef nameKey__T1 *nameKey_nameNode; | |
67 | ||
68 | typedef enum {nameKey_less, nameKey_equal, nameKey_greater} nameKey_comparison; | |
69 | ||
70 | struct nameKey__T1_r { | |
71 | nameKey_ptrToChar data; | |
72 | nameKey_Name key; | |
73 | nameKey_nameNode left; | |
74 | nameKey_nameNode right; | |
75 | }; | |
76 | ||
77 | static nameKey_nameNode binaryTree; | |
78 | static Indexing_Index keyIndex; | |
79 | static unsigned int lastIndice; | |
80 | ||
81 | /* | |
82 | makeKey - returns the Key of the symbol, a. If a is not in the | |
83 | name table then it is added, otherwise the Key of a is returned | |
84 | directly. Note that the name table has no scope - it merely | |
85 | presents a more convienient way of expressing strings. By a Key. | |
86 | */ | |
87 | ||
88 | extern "C" nameKey_Name nameKey_makeKey (const char *a_, unsigned int _a_high); | |
89 | ||
90 | /* | |
91 | makekey - returns the Key of the symbol, a. If a is not in the | |
92 | name table then it is added, otherwise the Key of a is returned | |
93 | directly. Note that the name table has no scope - it merely | |
94 | presents a more convienient way of expressing strings. By a Key. | |
95 | These keys last for the duration of compilation. | |
96 | */ | |
97 | ||
98 | extern "C" nameKey_Name nameKey_makekey (void * a); | |
99 | ||
100 | /* | |
101 | getKey - returns the name, a, of the key, Key. | |
102 | */ | |
103 | ||
104 | extern "C" void nameKey_getKey (nameKey_Name key, char *a, unsigned int _a_high); | |
105 | ||
106 | /* | |
107 | lengthKey - returns the StrLen of Key. | |
108 | */ | |
109 | ||
110 | extern "C" unsigned int nameKey_lengthKey (nameKey_Name key); | |
111 | ||
112 | /* | |
113 | isKey - returns TRUE if string, a, is currently a key. | |
114 | We dont use the Compare function, we inline it and avoid | |
115 | converting, a, into a String, for speed. | |
116 | */ | |
117 | ||
118 | extern "C" unsigned int nameKey_isKey (const char *a_, unsigned int _a_high); | |
119 | ||
120 | /* | |
121 | keyToCharStar - returns the C char * string equivalent for, key. | |
122 | */ | |
123 | ||
124 | extern "C" void nameKey_writeKey (nameKey_Name key); | |
125 | ||
126 | /* | |
127 | isSameExcludingCase - returns TRUE if key1 and key2 are | |
128 | the same. It is case insensitive. | |
129 | This function deliberately inlines CAP for speed. | |
130 | */ | |
131 | ||
132 | extern "C" unsigned int nameKey_isSameExcludingCase (nameKey_Name key1, nameKey_Name key2); | |
133 | ||
134 | /* | |
135 | keyToCharStar - returns the C char * string equivalent for, key. | |
136 | */ | |
137 | ||
138 | extern "C" void * nameKey_keyToCharStar (nameKey_Name key); | |
139 | ||
140 | /* | |
141 | doMakeKey - finds the name, n, in the tree or else create a name. | |
142 | If a name is found then the string, n, is deallocated. | |
143 | */ | |
144 | ||
145 | static nameKey_Name doMakeKey (nameKey_ptrToChar n, unsigned int higha); | |
146 | ||
147 | /* | |
148 | compare - return the result of Names[i] with Names[j] | |
149 | */ | |
150 | ||
151 | static nameKey_comparison compare (nameKey_ptrToChar pi, nameKey_Name j); | |
152 | ||
153 | /* | |
154 | findNodeAndParentInTree - search BinaryTree for a name. | |
155 | If this name is found in the BinaryTree then | |
156 | child is set to this name and father is set to the node above. | |
157 | A comparison is returned to assist adding entries into this tree. | |
158 | */ | |
159 | ||
160 | static nameKey_comparison findNodeAndParentInTree (nameKey_ptrToChar n, nameKey_nameNode *child, nameKey_nameNode *father); | |
161 | ||
162 | ||
163 | /* | |
164 | doMakeKey - finds the name, n, in the tree or else create a name. | |
165 | If a name is found then the string, n, is deallocated. | |
166 | */ | |
167 | ||
168 | static nameKey_Name doMakeKey (nameKey_ptrToChar n, unsigned int higha) | |
169 | { | |
170 | nameKey_comparison result; | |
171 | nameKey_nameNode father; | |
172 | nameKey_nameNode child; | |
173 | nameKey_Name k; | |
174 | ||
175 | result = findNodeAndParentInTree (n, &child, &father); | |
176 | if (child == NULL) | |
177 | { | |
178 | if (result == nameKey_less) | |
179 | { | |
180 | Storage_ALLOCATE ((void **) &child, sizeof (nameKey__T1)); | |
181 | father->left = child; | |
182 | } | |
183 | else if (result == nameKey_greater) | |
184 | { | |
185 | /* avoid dangling else. */ | |
186 | Storage_ALLOCATE ((void **) &child, sizeof (nameKey__T1)); | |
187 | father->right = child; | |
188 | } | |
189 | child->right = NULL; | |
190 | child->left = NULL; | |
191 | lastIndice += 1; | |
192 | child->key = lastIndice; | |
193 | child->data = n; | |
194 | Indexing_PutIndice (keyIndex, child->key, reinterpret_cast<void *> (n)); | |
195 | k = lastIndice; | |
196 | } | |
197 | else | |
198 | { | |
199 | Storage_DEALLOCATE (reinterpret_cast<void **> (&n), higha+1); | |
200 | k = child->key; | |
201 | } | |
202 | return k; | |
203 | /* static analysis guarentees a RETURN statement will be used before here. */ | |
204 | __builtin_unreachable (); | |
205 | } | |
206 | ||
207 | ||
208 | /* | |
209 | compare - return the result of Names[i] with Names[j] | |
210 | */ | |
211 | ||
212 | static nameKey_comparison compare (nameKey_ptrToChar pi, nameKey_Name j) | |
213 | { | |
214 | nameKey_ptrToChar pj; | |
215 | char c1; | |
216 | char c2; | |
217 | ||
218 | pj = static_cast<nameKey_ptrToChar> (nameKey_keyToCharStar (j)); | |
219 | c1 = (*pi); | |
220 | c2 = (*pj); | |
221 | while ((c1 != ASCII_nul) || (c2 != ASCII_nul)) | |
222 | { | |
223 | if (c1 < c2) | |
224 | { | |
225 | return nameKey_less; | |
226 | } | |
227 | else if (c1 > c2) | |
228 | { | |
229 | /* avoid dangling else. */ | |
230 | return nameKey_greater; | |
231 | } | |
232 | else | |
233 | { | |
234 | /* avoid dangling else. */ | |
235 | pi += 1; | |
236 | pj += 1; | |
237 | c1 = (*pi); | |
238 | c2 = (*pj); | |
239 | } | |
240 | } | |
241 | return nameKey_equal; | |
242 | /* static analysis guarentees a RETURN statement will be used before here. */ | |
243 | __builtin_unreachable (); | |
244 | } | |
245 | ||
246 | ||
247 | /* | |
248 | findNodeAndParentInTree - search BinaryTree for a name. | |
249 | If this name is found in the BinaryTree then | |
250 | child is set to this name and father is set to the node above. | |
251 | A comparison is returned to assist adding entries into this tree. | |
252 | */ | |
253 | ||
254 | static nameKey_comparison findNodeAndParentInTree (nameKey_ptrToChar n, nameKey_nameNode *child, nameKey_nameNode *father) | |
255 | { | |
256 | nameKey_comparison result; | |
257 | ||
258 | /* firstly set up the initial values of child and father, using sentinal node */ | |
259 | (*father) = binaryTree; | |
260 | (*child) = binaryTree->left; | |
261 | if ((*child) == NULL) | |
262 | { | |
263 | return nameKey_less; | |
264 | } | |
265 | else | |
266 | { | |
267 | do { | |
268 | result = compare (n, (*child)->key); | |
269 | if (result == nameKey_less) | |
270 | { | |
271 | (*father) = (*child); | |
272 | (*child) = (*child)->left; | |
273 | } | |
274 | else if (result == nameKey_greater) | |
275 | { | |
276 | /* avoid dangling else. */ | |
277 | (*father) = (*child); | |
278 | (*child) = (*child)->right; | |
279 | } | |
280 | } while (! (((*child) == NULL) || (result == nameKey_equal))); | |
281 | return result; | |
282 | } | |
283 | /* static analysis guarentees a RETURN statement will be used before here. */ | |
284 | __builtin_unreachable (); | |
285 | } | |
286 | ||
287 | ||
288 | /* | |
289 | makeKey - returns the Key of the symbol, a. If a is not in the | |
290 | name table then it is added, otherwise the Key of a is returned | |
291 | directly. Note that the name table has no scope - it merely | |
292 | presents a more convienient way of expressing strings. By a Key. | |
293 | */ | |
294 | ||
295 | extern "C" nameKey_Name nameKey_makeKey (const char *a_, unsigned int _a_high) | |
296 | { | |
297 | nameKey_ptrToChar n; | |
298 | nameKey_ptrToChar p; | |
299 | unsigned int i; | |
300 | unsigned int higha; | |
301 | char a[_a_high+1]; | |
302 | ||
303 | /* make a local copy of each unbounded array. */ | |
304 | memcpy (a, a_, _a_high+1); | |
305 | ||
306 | higha = StrLib_StrLen ((const char *) a, _a_high); | |
307 | Storage_ALLOCATE (reinterpret_cast<void **> (&p), higha+1); | |
308 | if (p == NULL) | |
309 | { | |
310 | M2RTS_HALT (-1); /* out of memory error */ | |
311 | __builtin_unreachable (); | |
312 | } | |
313 | else | |
314 | { | |
315 | n = p; | |
316 | i = 0; | |
317 | while (i < higha) | |
318 | { | |
319 | (*p) = a[i]; | |
320 | i += 1; | |
321 | p += 1; | |
322 | } | |
323 | (*p) = ASCII_nul; | |
324 | return doMakeKey (n, higha); | |
325 | } | |
326 | ReturnException ("../../gcc-git-devel-modula2/gcc/m2/mc/nameKey.def", 20, 1); | |
327 | __builtin_unreachable (); | |
328 | } | |
329 | ||
330 | ||
331 | /* | |
332 | makekey - returns the Key of the symbol, a. If a is not in the | |
333 | name table then it is added, otherwise the Key of a is returned | |
334 | directly. Note that the name table has no scope - it merely | |
335 | presents a more convienient way of expressing strings. By a Key. | |
336 | These keys last for the duration of compilation. | |
337 | */ | |
338 | ||
339 | extern "C" nameKey_Name nameKey_makekey (void * a) | |
340 | { | |
341 | nameKey_ptrToChar n; | |
342 | nameKey_ptrToChar p; | |
343 | nameKey_ptrToChar pa; | |
344 | unsigned int i; | |
345 | unsigned int higha; | |
346 | ||
347 | if (a == NULL) | |
348 | { | |
349 | return nameKey_NulName; | |
350 | } | |
351 | else | |
352 | { | |
353 | higha = static_cast<unsigned int> (libc_strlen (a)); | |
354 | Storage_ALLOCATE (reinterpret_cast<void **> (&p), higha+1); | |
355 | if (p == NULL) | |
356 | { | |
357 | M2RTS_HALT (-1); /* out of memory error */ | |
358 | __builtin_unreachable (); | |
359 | } | |
360 | else | |
361 | { | |
362 | n = p; | |
363 | pa = static_cast<nameKey_ptrToChar> (a); | |
364 | i = 0; | |
365 | while (i < higha) | |
366 | { | |
367 | (*p) = (*pa); | |
368 | i += 1; | |
369 | p += 1; | |
370 | pa += 1; | |
371 | } | |
372 | (*p) = ASCII_nul; | |
373 | return doMakeKey (n, higha); | |
374 | } | |
375 | } | |
376 | ReturnException ("../../gcc-git-devel-modula2/gcc/m2/mc/nameKey.def", 20, 1); | |
377 | __builtin_unreachable (); | |
378 | } | |
379 | ||
380 | ||
381 | /* | |
382 | getKey - returns the name, a, of the key, Key. | |
383 | */ | |
384 | ||
385 | extern "C" void nameKey_getKey (nameKey_Name key, char *a, unsigned int _a_high) | |
386 | { | |
387 | nameKey_ptrToChar p; | |
388 | unsigned int i; | |
389 | unsigned int higha; | |
390 | ||
391 | p = static_cast<nameKey_ptrToChar> (nameKey_keyToCharStar (key)); | |
392 | i = 0; | |
393 | higha = _a_high; | |
394 | while (((p != NULL) && (i <= higha)) && ((*p) != ASCII_nul)) | |
395 | { | |
396 | a[i] = (*p); | |
397 | p += 1; | |
398 | i += 1; | |
399 | } | |
400 | if (i <= higha) | |
401 | { | |
402 | a[i] = ASCII_nul; | |
403 | } | |
404 | } | |
405 | ||
406 | ||
407 | /* | |
408 | lengthKey - returns the StrLen of Key. | |
409 | */ | |
410 | ||
411 | extern "C" unsigned int nameKey_lengthKey (nameKey_Name key) | |
412 | { | |
413 | unsigned int i; | |
414 | nameKey_ptrToChar p; | |
415 | ||
416 | p = static_cast<nameKey_ptrToChar> (nameKey_keyToCharStar (key)); | |
417 | i = 0; | |
418 | while ((*p) != ASCII_nul) | |
419 | { | |
420 | i += 1; | |
421 | p += 1; | |
422 | } | |
423 | return i; | |
424 | /* static analysis guarentees a RETURN statement will be used before here. */ | |
425 | __builtin_unreachable (); | |
426 | } | |
427 | ||
428 | ||
429 | /* | |
430 | isKey - returns TRUE if string, a, is currently a key. | |
431 | We dont use the Compare function, we inline it and avoid | |
432 | converting, a, into a String, for speed. | |
433 | */ | |
434 | ||
435 | extern "C" unsigned int nameKey_isKey (const char *a_, unsigned int _a_high) | |
436 | { | |
437 | nameKey_nameNode child; | |
438 | nameKey_ptrToChar p; | |
439 | unsigned int i; | |
440 | unsigned int higha; | |
441 | char a[_a_high+1]; | |
442 | ||
443 | /* make a local copy of each unbounded array. */ | |
444 | memcpy (a, a_, _a_high+1); | |
445 | ||
446 | /* firstly set up the initial values of child, using sentinal node */ | |
447 | child = binaryTree->left; | |
448 | if (child != NULL) | |
449 | { | |
450 | do { | |
451 | i = 0; | |
452 | higha = _a_high; | |
453 | p = static_cast<nameKey_ptrToChar> (nameKey_keyToCharStar (child->key)); | |
454 | while ((i <= higha) && (a[i] != ASCII_nul)) | |
455 | { | |
456 | if (a[i] < (*p)) | |
457 | { | |
458 | child = child->left; | |
459 | i = higha; | |
460 | } | |
461 | else if (a[i] > (*p)) | |
462 | { | |
463 | /* avoid dangling else. */ | |
464 | child = child->right; | |
465 | i = higha; | |
466 | } | |
467 | else | |
468 | { | |
469 | /* avoid dangling else. */ | |
470 | if ((a[i] == ASCII_nul) || (i == higha)) | |
471 | { | |
472 | /* avoid gcc warning by using compound statement even if not strictly necessary. */ | |
473 | if ((*p) == ASCII_nul) | |
474 | { | |
475 | return TRUE; | |
476 | } | |
477 | else | |
478 | { | |
479 | child = child->left; | |
480 | } | |
481 | } | |
482 | p += 1; | |
483 | } | |
484 | i += 1; | |
485 | } | |
486 | } while (! (child == NULL)); | |
487 | } | |
488 | return FALSE; | |
489 | /* static analysis guarentees a RETURN statement will be used before here. */ | |
490 | __builtin_unreachable (); | |
491 | } | |
492 | ||
493 | ||
494 | /* | |
495 | keyToCharStar - returns the C char * string equivalent for, key. | |
496 | */ | |
497 | ||
498 | extern "C" void nameKey_writeKey (nameKey_Name key) | |
499 | { | |
500 | nameKey_ptrToChar s; | |
501 | ||
502 | s = static_cast<nameKey_ptrToChar> (nameKey_keyToCharStar (key)); | |
503 | while ((s != NULL) && ((*s) != ASCII_nul)) | |
504 | { | |
505 | StdIO_Write ((*s)); | |
506 | s += 1; | |
507 | } | |
508 | } | |
509 | ||
510 | ||
511 | /* | |
512 | isSameExcludingCase - returns TRUE if key1 and key2 are | |
513 | the same. It is case insensitive. | |
514 | This function deliberately inlines CAP for speed. | |
515 | */ | |
516 | ||
517 | extern "C" unsigned int nameKey_isSameExcludingCase (nameKey_Name key1, nameKey_Name key2) | |
518 | { | |
519 | nameKey_ptrToChar pi; | |
520 | nameKey_ptrToChar pj; | |
521 | char c1; | |
522 | char c2; | |
523 | ||
524 | if (key1 == key2) | |
525 | { | |
526 | return TRUE; | |
527 | } | |
528 | else | |
529 | { | |
530 | pi = static_cast<nameKey_ptrToChar> (nameKey_keyToCharStar (key1)); | |
531 | pj = static_cast<nameKey_ptrToChar> (nameKey_keyToCharStar (key2)); | |
532 | c1 = (*pi); | |
533 | c2 = (*pj); | |
534 | while ((c1 != ASCII_nul) && (c2 != ASCII_nul)) | |
535 | { | |
536 | 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'))))))) | |
537 | { | |
538 | pi += 1; | |
539 | pj += 1; | |
540 | c1 = (*pi); | |
541 | c2 = (*pj); | |
542 | } | |
543 | else | |
544 | { | |
545 | /* difference found */ | |
546 | return FALSE; | |
547 | } | |
548 | } | |
549 | return c1 == c2; | |
550 | } | |
551 | /* static analysis guarentees a RETURN statement will be used before here. */ | |
552 | __builtin_unreachable (); | |
553 | } | |
554 | ||
555 | ||
556 | /* | |
557 | keyToCharStar - returns the C char * string equivalent for, key. | |
558 | */ | |
559 | ||
560 | extern "C" void * nameKey_keyToCharStar (nameKey_Name key) | |
561 | { | |
562 | if ((key == nameKey_NulName) || (! (Indexing_InBounds (keyIndex, key)))) | |
563 | { | |
564 | return NULL; | |
565 | } | |
566 | else | |
567 | { | |
568 | return Indexing_GetIndice (keyIndex, key); | |
569 | } | |
570 | /* static analysis guarentees a RETURN statement will be used before here. */ | |
571 | __builtin_unreachable (); | |
572 | } | |
573 | ||
574 | extern "C" void _M2_nameKey_init (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[]) | |
575 | { | |
576 | lastIndice = 0; | |
577 | keyIndex = Indexing_InitIndex (1); | |
578 | Storage_ALLOCATE ((void **) &binaryTree, sizeof (nameKey__T1)); | |
579 | binaryTree->left = NULL; | |
580 | } | |
581 | ||
582 | extern "C" void _M2_nameKey_finish (__attribute__((unused)) int argc,__attribute__((unused)) char *argv[],__attribute__((unused)) char *envp[]) | |
583 | { | |
584 | } |