Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
/*
2
 * MS-DOS SHELL - TSEARCH functions
3
 *
4
 * MS-DOS SHELL - Copyright (c) 1990,4 Data Logic Limited
5
 *
6
 * This code is subject to the following copyright restrictions.  The
7
 * code for the extended (non BASIC) tsearch.3 functions is based on code
8
 * written by Peter Valkenburg & Michiel Huisjes.  The following copyright
9
 * conditions apply:
10
 *
11
 * 1.  Redistribution and use in source and binary forms are permitted
12
 *     provided that the above copyright notice is duplicated in the
13
 *     source form and the copyright notice in file sh6.c is displayed
14
 *     on entry to the program.
15
 *
16
 * 2.  The sources (or parts thereof) or objects generated from the sources
17
 *     (or parts of sources) cannot be sold under any circumstances.
18
 *
19
 *    $Header: /cvsroot/device/DEVL/UTILS/SH/Sh12.c,v 1.1 2002/08/02 06:49:33 adamy Exp $
20
 *
21
 *    $Log: Sh12.c,v $
22
 *    Revision 1.1  2002/08/02 06:49:33  adamy
23
 *    imported (reference only)
24
 *
25
 *    Revision 1.1  2001/07/20 05:55:44  ayoung
26
 *    WIN32 support
27
 *
28
 *    Revision 1.1.1.1  1999/12/02 01:11:12  gordonh
29
 *    UTIL
30
 *
31
 * Revision 2.7  1994/08/25  20:49:11  istewart
32
 * MS Shell 2.3 Release
33
 *
34
 * Revision 2.6  1994/02/01  10:25:20  istewart
35
 * Release 2.3 Beta 2, including first NT port
36
 *
37
 * Revision 2.5  1993/08/25  16:03:57  istewart
38
 * Beta 225 - see Notes file
39
 *
40
 * Revision 2.4  1993/07/02  10:21:35  istewart
41
 * 224 Beta fixes
42
 *
43
 * Revision 2.3  1993/06/02  09:52:35  istewart
44
 * Beta 223 Updates - see Notes file
45
 *
46
 * Revision 2.2  1993/02/16  16:03:15  istewart
47
 * Beta 2.22 Release
48
 *
49
 * Revision 2.1  1993/01/26  18:35:09  istewart
50
 * Release 2.2 beta 0
51
 *
52
 * Revision 2.0  1992/07/10  10:52:48  istewart
53
 * 211 Beta updates
54
 *
55
 *
56
 * Start of original notes for the non-BASIC tsearch functions.
57
 *
58
 * "tsearch.c", Peter Valkenburg & Michiel Huisjes, november '89.
59
 *
60
 * Standard tsearch(3) compatible implementation of AVL height balanced trees.
61
 * Performance is slightly better than SUN OS tsearch(3) for average case
62
 * delete/add operations, but worst case behaviour (i.e. when ordinary trees
63
 * get unbalanced) is much better.  Tsearch/tdelete/tfind run in O(2log(n)),
64
 * twalk in O(n), where n is the size of binary tree.
65
 *
66
 * Entry points:
67
 *
68
 *	_ts_NODE_t *tsearch((void *)key, (_ts_NODE_t **)rootp, int (*compar)());
69
 *	_ts_NODE_t *tdelete((void *)key, (_ts_NODE_t **)rootp, int (*compar)());
70
 *	_ts_NODE_t *tfind((void *)key, (_ts_NODE_t **)rootp, int (*compar)());
71
 *	void twalk((_ts_NODE_t *root), void (*action)());
72
 *
73
 * Here key is a pointer to any datum (to be) held in the tree rooted by *rootp
74
 * or root.  Keys are compared by calling compar, which gets two key arguments
75
 * and should return a value < 0, 0, or > 0, if the first parameter is to be
76
 * considered less than , equal to, or greater than the second, respectively.
77
 * Users can declare type (_ts_NODE_t *) as (char *) and (_ts_NODE_t **) as
78
 * (char **).  The return values of tsearch/tdelete/tfind can be used as
79
 * pointers to the key pointers of their _ts_NODE_t, by casting them to
80
 * (char **).
81
 *
82
 * See manual page tsearch(3) for more extensive user documentation.
83
 */
84
 
85
#include <sys/types.h>
86
#include <sys/stat.h>
87
#include <stdio.h>
88
#include <string.h>
89
#include <setjmp.h>
90
#include <unistd.h>
91
#include <limits.h>
92
#include "sh.h"
93
 
94
/*
95
 * Type for doubly linked AVL tree.
96
 */
97
 
98
#ifndef BASIC
99
typedef struct node_s {
100
    void		*key;		/* ptr to datum			*/
101
    struct node_s	*parent;	/* ptr to parent ancestor	*/
102
    struct node_s	*sibls[2];	/* ptrs to L/R siblings		*/
103
    int			balance;	/* balance value (-1, 0 or +1)	*/
104
} _ts_NODE_t;
105
 
106
typedef int		_SibIndex_t;	/* type for indexing siblings	*/
107
#define	L		((_SibIndex_t) 0)
108
#define	R		((_SibIndex_t) 1)
109
 
110
#define	LEFT		sibls[L]/* left sibling pointer _ts_NODE_t field */
111
#define	RIGHT		sibls[R]/* right sibling pointer _ts_NODE_t field */
112
 
113
/*
114
 * Direction gives direction in which child _ts_NODE_t c is under parent
115
 * _ts_NODE_t p.
116
 */
117
 
118
#define	direction(p, c)	((_SibIndex_t) ((p)->RIGHT == (c)))
119
 
120
/*
121
 * Cmp_dir gives direction corresponding with compare value v (R iff v > 0).
122
 */
123
 
124
#define	cmp_dir(v)	((_SibIndex_t) ((v) > 0))
125
 
126
/*
127
 * Siblingp yields ptr to left (d == L) or right (d == R) child of _ts_NODE_t n.
128
 */
129
 
130
#define	siblingp(n, d)	((n)->sibls + (d))
131
 
132
/*
133
 * Parentp yields ptr to parent's ptr to _ts_NODE_t n, or root ptr r if n is 0.
134
 */
135
 
136
#define	parentp(r, n)	((n)->parent == (_ts_NODE_t *)NULL ? (r) : \
137
			     siblingp((n)->parent, direction((n)->parent, (n))))
138
 
139
/*
140
 * Dir_bal yields balance value corresponding to _SibIndex_t d.
141
 */
142
 
143
#define	dir_bal(d)	((d) == L ? -1 : 1)
144
 
145
static _ts_NODE_t	*balance (_ts_NODE_t **, _ts_NODE_t *, int);
146
static _ts_NODE_t	*single_rotation (_ts_NODE_t **, _ts_NODE_t *,
147
					  _ts_NODE_t *, _SibIndex_t);
148
static _ts_NODE_t	*double_rotation (_ts_NODE_t **, _ts_NODE_t *,
149
					  _ts_NODE_t *, _SibIndex_t);
150
 
151
/*
152
 * Tsearch adds node key to tree rooted by *rootp, using compar for
153
 * comparing elements.  It returns the pointer to the _ts_NODE_t in which
154
 * the (possibly already existing) key pointer resides.
155
 */
156
 
157
void *
158
tsearch(void *key, void **root, int (*compar)(const void *, const void *) )
159
{
160
    register _ts_NODE_t		*parent, *child;
161
    _ts_NODE_t			*nnode;
162
    register _SibIndex_t	d;
163
    register int		cmp = 0;
164
    register _ts_NODE_t		**rootp = (_ts_NODE_t **)root;
165
 
166
    if (rootp == (_ts_NODE_t **)NULL)
167
	return (_ts_NODE_t *)NULL;
168
 
169
    /* find place where key should go */
170
 
171
    parent = (_ts_NODE_t *)NULL;
172
    child = *rootp;
173
 
174
    while (child != (_ts_NODE_t *)NULL)
175
    {
176
	if ((cmp = compar (key, child->key)) == 0)
177
	    return child;
178
 
179
	parent = child;
180
	child = *siblingp (child, cmp_dir (cmp));
181
    }
182
 
183
    /* create new node and set its parent's sibling pointer */
184
 
185
    nnode = (_ts_NODE_t *) GetAllocatedSpace (sizeof (_ts_NODE_t));
186
 
187
    if (nnode == (_ts_NODE_t *)NULL)
188
	return (_ts_NODE_t *)NULL;
189
 
190
    SetMemoryAreaNumber ((void *) nnode, 0);
191
    nnode->key = key;
192
    nnode->balance = 0;
193
    nnode->parent = parent;
194
    nnode->LEFT = nnode->RIGHT = (_ts_NODE_t *)NULL;
195
 
196
    if (parent == (_ts_NODE_t *)NULL)
197
    {
198
	*rootp = nnode;
199
	return nnode;			/* just created tree */
200
    }
201
 
202
    *siblingp (parent, cmp_dir(cmp)) = nnode;
203
    child = nnode;
204
 
205
/*
206
 * Back up until tree is balanced.  This is achieved when either
207
 * the tree is balanced by rotation or a node's balance becomes 0.
208
 */
209
 
210
    do
211
    {
212
	d = direction (parent, child);
213
 
214
	if (parent->balance == dir_bal(d))
215
	{
216
	    (void) balance (rootp, parent, d);
217
	    return nnode;
218
	}
219
 
220
	else if ((parent->balance += dir_bal(d)) == 0)
221
	    return nnode;
222
 
223
	child = parent;
224
	parent = parent->parent;
225
 
226
    } while (parent != (_ts_NODE_t *)NULL);
227
 
228
    return nnode;
229
}
230
 
231
/*
232
 * Tdelete removes key from the tree rooted by *rootp, using compar for
233
 * comparing elements.  It returns the pointer to the _ts_NODE_t that was the
234
 * parent of the _ts_NODE_t that contained the key pointer, 0 if it did not exist.
235
 */
236
 
237
void *
238
tdelete (void *key, void **root, int (*compar)(const void *, const void *))
239
{
240
    register _ts_NODE_t		*parent, *child;
241
    _ts_NODE_t			*dnode, *dparent;
242
    register _SibIndex_t	d;
243
    register int		cont_bal;
244
    register int		cmp;
245
    register _ts_NODE_t		**rootp = (_ts_NODE_t **)root;
246
 
247
    if (rootp == (_ts_NODE_t **)NULL)
248
	return (void *)NULL;
249
 
250
/* find node to delete */
251
 
252
    child = *rootp;
253
 
254
    while (child != (_ts_NODE_t *)NULL)
255
    {
256
	if ((cmp = compar (key, child->key)) == 0)
257
	    break;
258
 
259
	child = *siblingp (child, cmp_dir (cmp));
260
    }
261
 
262
    if (child == (_ts_NODE_t *)NULL)
263
	return (void *)NULL;		/* key not in tree */
264
 
265
/* the node was found; get its successor (if any) to replace it */
266
 
267
    dnode = child;
268
    dparent = dnode->parent;
269
    child = child->RIGHT;
270
 
271
    if (child == (_ts_NODE_t *)NULL)		/* no successor for key */
272
    {
273
	if ((child = dnode->LEFT) != (_ts_NODE_t *)NULL)
274
	    child->parent = dparent;	/* set new parent */
275
 
276
	if (dparent == (_ts_NODE_t *)NULL)
277
	{
278
	    ReleaseMemoryCell ((void *) dnode);
279
	    *rootp = child;
280
	    return (void *)NULL;	/* just deleted the root */
281
	}
282
 
283
	d = direction (dparent, dnode);	/* for back up */
284
	*siblingp(dparent, d) = child;	/* replace by left child */
285
	ReleaseMemoryCell ((void *) dnode);
286
	parent = dparent;
287
    }
288
 
289
    else				/* key's successor exists */
290
    {
291
	while (child->LEFT != (_ts_NODE_t *)NULL)
292
	    child = child->LEFT;
293
 
294
	parent = child->parent;
295
	d = direction(parent, child);		/* for back up */
296
	*siblingp(parent, d) = child->RIGHT;
297
 
298
	if (child->RIGHT != (_ts_NODE_t *)NULL)
299
	    child->RIGHT->parent = parent;	/* set new parent */
300
 
301
	dnode->key = child->key;	/* successor replaces key */
302
	ReleaseMemoryCell ((void *) child);
303
    }
304
 
305
/*
306
 * Back up until tree is balanced.  This is achieved when either the tree is
307
 * balanced by rotation but not made shorter, or a node's balance was 0 before
308
 * deletion.
309
 */
310
 
311
    do
312
    {
313
	if (parent->balance == dir_bal(!d))
314
	{
315
	    cont_bal = ((*siblingp(parent, !d))->balance != 0);
316
	    parent = balance(rootp, parent, !d);
317
	}
318
 
319
	else
320
	{
321
	    cont_bal = (parent->balance != 0);
322
	    parent->balance += dir_bal(!d);
323
	}
324
 
325
	child = parent;
326
 
327
	if ((parent = parent->parent) == (_ts_NODE_t *)NULL)
328
	    return dparent;		/* we reached the root */
329
 
330
	d = direction(parent, child);
331
 
332
    } while (cont_bal);
333
 
334
    return dparent;
335
}
336
 
337
/*
338
 * Balance the subtree rooted at sb that has become to heavy on side d.
339
 * Also adjusts sibling pointer of the parent of sb, or *rootp if sb is
340
 * the top of the entire tree.
341
 */
342
 
343
static _ts_NODE_t *
344
balance(_ts_NODE_t **rootp, _ts_NODE_t *sb, _SibIndex_t	d)
345
{
346
    _ts_NODE_t	*sb_next = *siblingp (sb, d);
347
 
348
    if (sb_next->balance == -dir_bal(d))
349
	return double_rotation (rootp, sb, sb_next, d);
350
 
351
    else
352
	return single_rotation (rootp, sb, sb_next, d);
353
}
354
 
355
/*
356
 * Balance the subtree rooted at sb that has become to heavy on side d
357
 * by single rotation of sb and sb_next.
358
 * Also adjusts sibling pointer of the parent of sb, or *rootp if sb is
359
 * the top of the entire tree.
360
 *
361
 *		sb		sb_next		Single rotation: Adding x or
362
 *	       /  \	       /       \	deleting under 3 caused
363
 *	sb_next	   3	      1		sb	rotation.  Same holds for mirror
364
 *     /       \	      |	       /  \	image.  Single_rotation returns
365
 *    1	        2	==>   x       2    3	top of new balanced tree.
366
 *    |		|		      |
367
 *    x		y		      y
368
 */
369
 
370
static _ts_NODE_t *
371
single_rotation ( 
372
    _ts_NODE_t **rootp,
373
    register _ts_NODE_t *sb, register _ts_NODE_t *sb_next, 
374
    register _SibIndex_t d )
375
{
376
    *siblingp (sb, d)       = *siblingp(sb_next, !d);
377
    *siblingp (sb_next, !d) = sb;
378
    sb->balance             -= sb_next->balance;
379
    sb_next->balance        = -sb->balance;
380
    *parentp (rootp, sb)    = sb_next;
381
    sb_next->parent         = sb->parent;
382
    sb->parent              = sb_next;
383
 
384
    if (*siblingp (sb, d) != (_ts_NODE_t *)NULL)
385
	(*siblingp (sb, d))->parent = sb;
386
 
387
    return sb_next;
388
}
389
 
390
/*
391
 * Balance the subtree rooted at sb that has become to heavy on side d
392
 * by double rotation of sb and sb_next.
393
 * Also adjusts sibling pointer of the parent of sb, or *rootp if sb is
394
 * the top of the entire tree.
395
 *
396
 *		sb		    sb_next2	   Double rotation: Adding x or
397
 *	       /  \	           /	    \	   x', or deleting under 4
398
 *	sb_next    \		sb_next	     sb    caused rotation. Same holds
399
 *     /       \    \	       /       \    /  \   for the mirror image.
400
 *    1   sb_next2   4	 ==>  1		2  3    4  Double_rotation returns top
401
 *       /        \			|  |	   of new balanced tree.
402
 *      2          3			x  x'
403
 *      |  	   |
404
 *      x	   x'
405
 */
406
 
407
static _ts_NODE_t *
408
double_rotation (
409
    _ts_NODE_t	**rootp,
410
    register _ts_NODE_t	*sb, register _ts_NODE_t *sb_next,
411
    register _SibIndex_t d )
412
{
413
    register _ts_NODE_t *sb_next2 = *siblingp(sb_next, !d);
414
 
415
    *siblingp (sb_next, !d)  = *siblingp (sb_next2, d);
416
    *siblingp (sb, d)        = *siblingp (sb_next2, !d);
417
    *siblingp (sb_next2, d)  = sb_next;
418
    *siblingp (sb_next2, !d) = sb;
419
 
420
    if (sb_next2->balance == sb_next->balance)
421
	sb_next->balance = -sb_next->balance;
422
 
423
    else
424
	sb_next->balance = 0;
425
 
426
    if (sb_next2->balance == sb->balance)
427
	sb->balance = -sb->balance;
428
 
429
    else
430
	sb->balance = 0;
431
 
432
    sb_next2->balance    = 0;
433
    *parentp (rootp, sb) = sb_next2;
434
    sb_next2->parent     = sb->parent;
435
    sb->parent           = sb_next->parent = sb_next2;
436
 
437
    if (*siblingp (sb_next, !d) != (_ts_NODE_t *)NULL)
438
	(*siblingp (sb_next, !d))->parent = sb_next;
439
 
440
    if (*siblingp (sb, d) != (_ts_NODE_t *)NULL)
441
	(*siblingp (sb, d))->parent = sb;
442
 
443
    return sb_next2;
444
}
445
 
446
/*
447
 * Tfind searches node key in the tree rooted by *rootp, using compar for
448
 * comparing elements.  It returns the pointer to the _ts_NODE_t in which
449
 * the key pointer resides, or 0 if key is not present.
450
 */
451
 
452
void	*
453
tfind(void *key, void **root, int (*compar)(const void *, const void *))
454
{
455
    register _ts_NODE_t	*node;
456
    _ts_NODE_t		**rootp = (_ts_NODE_t **)root;
457
    register int	cmp;
458
 
459
    if (rootp == (_ts_NODE_t **)NULL)
460
	return (void *)NULL;
461
 
462
    node = *rootp;
463
    while (node != (_ts_NODE_t *)NULL)
464
    {
465
	if ((cmp = compar (key, node->key)) == 0)
466
	    return node;
467
 
468
	node = *siblingp (node, cmp_dir (cmp));
469
    }
470
 
471
    return (void *)NULL;
472
}
473
 
474
/*
475
 * Twalk walks the tree rooted by node, from top to bottom and left to right,
476
 * calling action with the _ts_NODE_t pointer, visit order, and level in the tree
477
 * (0 is root).  Leafs are visited only once and action is then called with
478
 * `leaf' as the second parameter.  For nodes with children action is called
479
 * three times with visit order parameter `preorder' before, `postorder' in
480
 * between, and `endorder' after visiting the nodes children.
481
 */
482
 
483
void		
484
twalk (const void *start, register void	(*action)(const void *, VISIT, int))
485
{
486
    register VISIT	visit;
487
    register int	level;
488
    register _ts_NODE_t	*node = (_ts_NODE_t *)start;
489
 
490
    if ((node == (_ts_NODE_t *)NULL) || (action == 0))
491
	return;
492
 
493
/* run down tree from top to bottom, left to right */
494
 
495
    visit = preorder;
496
    level = 0;
497
 
498
    while (node != (_ts_NODE_t *)NULL)
499
    {
500
	if ((visit == preorder) &&
501
	    (node->LEFT == (_ts_NODE_t *)NULL) &&
502
	    (node->RIGHT == (_ts_NODE_t *)NULL))
503
	    visit = leaf;		/* node turns out to be leaf */
504
 
505
	action (node, visit, level);
506
 
507
	switch (visit)
508
	{
509
	    case preorder:			/* before visiting left child */
510
		if (node->LEFT != (_ts_NODE_t *)NULL)
511
		{
512
		    node = node->LEFT;
513
		    level++;
514
		}
515
 
516
		else
517
		    visit = postorder;
518
 
519
		break;
520
 
521
	    case postorder:		/* between visiting children */
522
		if (node->RIGHT != (_ts_NODE_t *)NULL)
523
		{
524
		    node = node->RIGHT;
525
		    visit = preorder;
526
		    level++;
527
		}
528
 
529
		else
530
		    visit = endorder;
531
 
532
		break;
533
 
534
	    case endorder:		/* after visiting children */
535
	    case leaf:			/* node has no children */
536
		if (node->parent != (_ts_NODE_t *)NULL)
537
		{
538
		    if (direction (node->parent, node) == L)
539
			visit = postorder;
540
 
541
		    else
542
			visit = endorder;
543
		}
544
 
545
		node = node->parent;
546
		level--;
547
 
548
		break;
549
	}
550
    }
551
}
552
#else
553
 
554
/*
555
 * Definition for t.... functions
556
 */
557
 
558
typedef struct _t_node {
559
    char		*key;
560
    struct _t_node	*llink;
561
    struct _t_node	*rlink;
562
} _t_NODE;
563
 
564
static void		_twalk (_t_NODE *,
565
				void (*)(const void *, VISIT, int), int);
566
/*
567
 * Basic Tree Processing Functions
568
 */
569
 
570
/*
571
 * Delete node with key
572
 */
573
 
574
void	*tdelete (key, rootcp, compar)
575
void	*key;
576
void	**rootcp;
577
int	(*compar)(const void *, const void *);
578
{
579
    _t_NODE		*p;		/* Parent of node to be deleted */
580
    register _t_NODE	*q;		/* Successor node		*/
581
    register _t_NODE	*r;		/* Right son node		*/
582
    int			ans;		/* Result of comparison		*/
583
    register _t_NODE	**rootp = (_t_NODE **)rootcp;
584
 
585
    if ((rootp == (_t_NODE **)NULL) || ((p = *rootp) == (_t_NODE *)NULL))
586
	return (void *)NULL;
587
 
588
    while ((ans = (*compar)(key, (*rootp)->key)) != 0)
589
    {
590
	p = *rootp;
591
	rootp = (ans < 0) ? &(*rootp)->llink : &(*rootp)->rlink;
592
 
593
	if (*rootp == (_t_NODE *)NULL)
594
	    return (void *)NULL;
595
    }
596
 
597
    r = (*rootp)->rlink;
598
 
599
    if ((q = (*rootp)->llink) == (_t_NODE *)NULL)
600
	    q = r;
601
 
602
    else if (r != (_t_NODE *)NULL)
603
    {
604
	if (r->llink == (_t_NODE *)NULL)
605
	{
606
	    r->llink = q;
607
	    q = r;
608
	}
609
 
610
	else
611
	{
612
	    for (q = r->llink; q->llink != (_t_NODE *)NULL; q = r->llink)
613
		r = q;
614
 
615
	    r->llink = q->rlink;
616
	    q->llink = (*rootp)->llink;
617
	    q->rlink = (*rootp)->rlink;
618
	}
619
    }
620
 
621
    ReleaseMemoryCell ((char *) *rootp);
622
    *rootp = q;
623
    return (void *)p;
624
}
625
 
626
/*
627
 * Find node with key
628
 */
629
 
630
void	*tfind (key, rootcp, compar)
631
void	*key;			/* Key to be located			*/
632
void	**rootcp;		/* Address of the root of the tree	*/
633
int	(*compar)(const void *, const void *);
634
{
635
    register _t_NODE	**rootp = (_t_NODE **)rootcp;
636
 
637
    if (rootp == (_t_NODE **)NULL)
638
	return (void *)NULL;
639
 
640
    while (*rootp != (_t_NODE *)NULL)
641
    {
642
	int	r = (*compar)(key, (*rootp)->key);
643
 
644
	if (r == 0)
645
	    return (void *)*rootp;
646
 
647
	rootp = (r < 0) ? &(*rootp)->llink : &(*rootp)->rlink;
648
    }
649
 
650
    return (void *)NULL;
651
}
652
 
653
/*
654
 * Search for a node with key key and add it if appropriate
655
 */
656
 
657
void	*tsearch (key, rootcp, compar)
658
void	*key;			/* Key to be located			*/
659
void	**rootcp;		/* Address of the root of the tree	*/
660
int	(*compar)(const void *, const void *);
661
{
662
    register _t_NODE	**rootp = (_t_NODE **)rootcp;
663
    register _t_NODE	*q;	/* New node if key not found */
664
 
665
    if (rootp == (_t_NODE **)NULL)
666
	return (void *)NULL;
667
 
668
    while (*rootp != (_t_NODE *)NULL)
669
    {
670
	int	r = (*compar)(key, (*rootp)->key);
671
 
672
	if (r == 0)
673
	    return (void *)*rootp;
674
 
675
	rootp = (r < 0) ? &(*rootp)->llink : &(*rootp)->rlink;
676
    }
677
 
678
    q = (_t_NODE *) GetAllocatedSpace (sizeof (_t_NODE));
679
 
680
    if (q != (_t_NODE *)NULL)
681
    {
682
        SetMemoryAreaNumber ((void *)q, 0);
683
	*rootp = q;
684
	q->key = key;
685
	q->llink = q->rlink = (_t_NODE *)NULL;
686
    }
687
 
688
    return (void *)q;
689
}
690
 
691
 
692
/* Walk the nodes of a tree */
693
 
694
void		twalk (root, action)
695
const void	*root;			/* Root of the tree to be walked */
696
void		(*action)(const void *, VISIT, int);
697
{
698
    if ((root != (char *)NULL) && (action != NULL))
699
	_twalk (root, action, 0);
700
}
701
 
702
static void		_twalk (root, action, level)
703
register _t_NODE	*root;
704
register void		(*action)(const void *, VISIT, int);
705
register int		level;
706
{
707
    if (root->llink == (_t_NODE *)NULL && root->rlink == NULL)
708
	(*action)(root, leaf, level);
709
 
710
    else
711
    {
712
	(*action)(root, preorder, level);
713
 
714
	if (root->llink != (_t_NODE *)NULL)
715
	    _twalk (root->llink, action, level + 1);
716
 
717
	(*action)(root, postorder, level);
718
 
719
	if (root->rlink != (_t_NODE *)NULL)
720
	    _twalk (root->rlink, action, level + 1);
721
 
722
	(*action)(root, endorder, level);
723
    }
724
}
725
#endif