libc: Add the missing tsearch functions
authorAlan Cox <alan@linux.intel.com>
Sat, 30 Sep 2017 19:41:49 +0000 (20:41 +0100)
committerAlan Cox <alan@linux.intel.com>
Sat, 30 Sep 2017 19:41:49 +0000 (20:41 +0100)
This leaves the hash tables (hsearch etc) and ftw/nftw as the only big APIs
we are missing.

Library/include/search.h
Library/libs/API.list
Library/libs/Makefile.z80
Library/libs/tfind.c [new file with mode: 0644]
Library/libs/tsearch.c [new file with mode: 0644]

index 6eadb9c..159dd17 100644 (file)
@@ -15,7 +15,9 @@ typedef int (*__compar_fn_t)(__ptr_t, __ptr_t);
 typedef struct entry { char *key; char *data; } ENTRY;
 typedef enum { FIND, ENTER } ACTION;
 
-extern ENTRY * hsearch(ENTRY __item, ACTION __action);
+/* Some of our compilers can't do struct arguments at all */
+extern ENTRY * __hsearch(ENTRY __item, ACTION __action);
+#define hsearch(a,b,c) __hsearch(&(a),(b),(c))
 extern int     hcreate(unsigned __nel);
 extern void    hdestroy(void);
 
index abaeb9d..0695ba2 100644 (file)
@@ -263,9 +263,9 @@ tan                 CODE
 tanf                   CODE | Z80
 tanh                   CODE
 tanhf                  CODE
-tdelete                        MISSING
+tdelete                        CODE
 tempnam                        OBSOLETE
-tfind                  MISSING
+tfind                  CODE
 time                   CODE
 times                  CODE
 tmpfile                        CODE
@@ -275,9 +275,9 @@ tolower                     CODE
 _tolower               CODE
 toupper                        CODE
 _toupper               CODE
-tsearch                        MISSING
+tsearch                        CODE
 ttyname                        CODE
-twalk                  MISSING
+twalk                  CODE
 tzset                  CODE
 ulimit                 OBSOLETE (need to get rlimit into L2 kernel)
 umask                  CODE
index 83a4672..8fc30bd 100644 (file)
@@ -49,7 +49,8 @@ SRC_C += setlocale.c setvbuf.c settimeofday.c sgetl.c sleep.c sprintf.c
 SRC_C += sputl.c stat.c stdio0.c stime.c
 SRC_C += strcasecmp.c strcasestr.c strdup.c stricmp.c strlcpy.c strncasecmp.c
 SRC_C += strnlen.c strnicmp.c strsep.c strxfrm.c strcoll.c strsignal.c
-SRC_C += strtod.c strtol.c swab.c system.c telldir.c time.c tmpfile.c tmpnam.c ttyname.c
+SRC_C += strtod.c strtol.c swab.c system.c telldir.c
+SRC_C += tfind.c time.c tmpfile.c tmpnam.c tsearch.c ttyname.c
 SRC_C += tzset.c ungetc.c usleep.c utent.c utimes.c utsname.c
 SRC_C += vfprintf.c vprintf.c wait.c xitoa.c pathconf.c
 SRC_C += gethostname.c sysconf.c confstr.c memccpy.c getpass.c
diff --git a/Library/libs/tfind.c b/Library/libs/tfind.c
new file mode 100644 (file)
index 0000000..d3dd5c1
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Tree search generalized from Knuth (6.2.2) Algorithm T just like
+ * the AT&T man page says.
+ *
+ * The node_t structure is for internal use only, lint doesn't grok it.
+ *
+ * Written by reading the System V Interface Definition, not the code.
+ *
+ * Totally public domain.
+ *
+ * From unix-pc.sources, August 1989
+ */
+
+#include <search.h>
+
+typedef struct node_t
+{
+       char      *key;
+       struct node_t *llink, *rlink;
+} node;
+
+void *tfind(void *key, void **_rootp, __compar_fn_t compar)
+/* find a node, or return 0 */
+{
+    node **rootp = _rootp;
+    if (rootp == NULL)
+       return NULL;
+    while (*rootp != NULL)     /* T1: */
+    {
+       int r;
+       if ((r = (*compar)(key, (*rootp)->key)) == 0)   /* T2: */
+           return (*rootp);            /* key found */
+       rootp = (r < 0) ?
+           &(*rootp)->llink :          /* T3: follow left branch */
+           &(*rootp)->rlink;           /* T4: follow right branch */
+    }
+    return NULL;
+}
+
diff --git a/Library/libs/tsearch.c b/Library/libs/tsearch.c
new file mode 100644 (file)
index 0000000..5ebf37a
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Tree search generalized from Knuth (6.2.2) Algorithm T just like
+ * the AT&T man page says.
+ *
+ * The node_t structure is for internal use only, lint doesn't grok it.
+ *
+ * Written by reading the System V Interface Definition, not the code.
+ *
+ * Totally public domain.
+ *
+ * From unix-pc.sources August 1989
+ */
+
+#include <stdlib.h>
+#include <search.h>
+
+typedef struct node_t
+{
+    char         *key;
+    struct node_t *left, *right;
+}
+node;
+
+void *tsearch(void *key, void **_rootp, __compar_fn_t compar)
+/* find or insert datum into search tree */
+{
+node **rootp = _rootp;
+    node *q;
+
+    if (rootp == NULL)
+       return NULL;
+    while (*rootp != NULL)     /* Knuth's T1: */
+    {
+       int r;
+
+       if ((r = (*compar)(key, (*rootp)->key)) == 0)   /* T2: */
+           return (*rootp);            /* we found it! */
+       rootp = (r < 0) ?
+           &(*rootp)->left :           /* T3: follow left branch */
+           &(*rootp)->right;           /* T4: follow right branch */
+    }
+    q = (node *) malloc(sizeof(node)); /* T5: key not found */
+    if (q != NULL)                     /* make new node */
+    {
+       *rootp = q;                     /* link new node to old */
+       q->key = key;                   /* initialize new node */
+       q->left = q->right = (struct node_t *)0;
+    }
+    return (q);
+}
+
+void *tdelete(void *key, void **_rootp, __compar_fn_t compar)
+/* delete node with given key */
+{
+node **rootp = _rootp;
+    node *p;
+    node *q;
+    node *r;
+    int cmp;
+
+    if (rootp == NULL || (p = *rootp) == NULL)
+       return NULL;
+    while ((cmp = (*compar)(key, (*rootp)->key)) != 0)
+    {
+       p = *rootp;
+       rootp = (cmp < 0) ?
+           &(*rootp)->left :           /* follow left branch */
+           &(*rootp)->right;           /* follow right branch */
+       if (*rootp == NULL)
+           return NULL;                /* key not found */
+    }
+    r = (*rootp)->right;                       /* D1: */
+    if ((q = (*rootp)->left) == NULL)  /* Left (struct node_t *)0? */
+       q = r;
+    else if (r != NULL)                /* Right link is null? */
+    {
+       if (r->left == NULL) {  /* D2: Find successor */
+           r->left = q;
+           q = r;
+       } else {                        /* D3: Find (struct node_t *)0 link */
+           for (q = r->left; q->left != NULL; q = r->left)
+               r = q;
+           r->left = q->right;
+           q->left = (*rootp)->left;
+           q->right = (*rootp)->right;
+       }
+    }
+    free((struct node_t *) *rootp);    /* D4: Free node */
+    *rootp = q;                                /* link parent to new node */
+    return(p);
+}
+
+static void trecurse(node *root, __action_fn_t action, int level)
+/* Walk the nodes of a tree */
+{
+    if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
+       (*action)(root, leaf, level);
+    else
+    {
+       (*action)(root, preorder, level);
+       if (root->left != NULL)
+           trecurse(root->left, action, level + 1);
+       (*action)(root, postorder, level);
+       if (root->right != NULL)
+           trecurse(root->right, action, level + 1);
+       (*action)(root, endorder, level);
+    }
+}
+
+void twalk(void *root, __action_fn_t action)   /* Walk the nodes of a tree */
+{
+    if (root != NULL && action != NULL)
+       trecurse(root, action, 0);
+}
+