11.7Sabs/*	$NetBSD: tsearch.c,v 1.7 2012/06/25 22:32:45 abs Exp $	*/
21.1Schristos
31.1Schristos/*
41.1Schristos * Tree search generalized from Knuth (6.2.2) Algorithm T just like
51.1Schristos * the AT&T man page says.
61.1Schristos *
71.1Schristos * The node_t structure is for internal use only, lint doesn't grok it.
81.1Schristos *
91.1Schristos * Written by reading the System V Interface Definition, not the code.
101.1Schristos *
111.1Schristos * Totally public domain.
121.1Schristos */
131.1Schristos
141.1Schristos#include <sys/cdefs.h>
151.1Schristos#if defined(LIBC_SCCS) && !defined(lint)
161.7Sabs__RCSID("$NetBSD: tsearch.c,v 1.7 2012/06/25 22:32:45 abs Exp $");
171.1Schristos#endif /* LIBC_SCCS and not lint */
181.1Schristos
191.3Slukem#include <assert.h>
201.1Schristos#define _SEARCH_PRIVATE
211.1Schristos#include <search.h>
221.1Schristos#include <stdlib.h>
231.1Schristos
241.1Schristos/* find or insert datum into search tree */
251.1Schristosvoid *
261.7Sabstsearch(const void *vkey, void **vrootp,
271.7Sabs    int (*compar)(const void *, const void *))
281.1Schristos{
291.1Schristos	node_t *q;
301.1Schristos	node_t **rootp = (node_t **)vrootp;
311.3Slukem
321.3Slukem	_DIAGASSERT(vkey != NULL);
331.3Slukem	_DIAGASSERT(compar != NULL);
341.1Schristos
351.1Schristos	if (rootp == NULL)
361.1Schristos		return NULL;
371.1Schristos
381.1Schristos	while (*rootp != NULL) {	/* Knuth's T1: */
391.1Schristos		int r;
401.1Schristos
411.1Schristos		if ((r = (*compar)(vkey, (*rootp)->key)) == 0)	/* T2: */
421.1Schristos			return *rootp;		/* we found it! */
431.1Schristos
441.1Schristos		rootp = (r < 0) ?
451.1Schristos		    &(*rootp)->llink :		/* T3: follow left branch */
461.1Schristos		    &(*rootp)->rlink;		/* T4: follow right branch */
471.1Schristos	}
481.1Schristos
491.1Schristos	q = malloc(sizeof(node_t));		/* T5: key not found */
501.1Schristos	if (q != 0) {				/* make new node */
511.1Schristos		*rootp = q;			/* link new node to old */
521.5Schristos		q->key = __UNCONST(vkey);	/* initialize new node */
531.1Schristos		q->llink = q->rlink = NULL;
541.1Schristos	}
551.1Schristos	return q;
561.1Schristos}
57