NetBSD/usr.sbin/sup/source/stree.c

359 lines
7.2 KiB
C

/* $NetBSD: stree.c,v 1.15 2009/10/17 22:26:13 christos Exp $ */
/*
* Copyright (c) 1992 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
* stree.c -- SUP Tree Routines
*
**********************************************************************
* HISTORY
* Revision 1.4 92/08/11 12:06:32 mrt
* Added copyright. Delinted
* [92/08/10 mrt]
*
*
* Revision 1.3 89/08/15 15:30:57 bww
* Changed code in Tlookup to Tsearch for each subpart of path.
* Added indent formatting code to Tprint.
* From "[89/06/24 gm0w]" at CMU.
* [89/08/15 bww]
*
* 20-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Added code to please lint.
*
* 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Added code to initialize new fields. Added Tfree routine.
*
* 27-Sep-85 Glenn Marcy (gm0w) at Carnegie-Mellon University
* Created.
*
**********************************************************************
*/
#include <sys/param.h>
#include <assert.h>
#include "supcdefs.h"
#include "supextern.h"
#include "libc.h"
#include "c.h"
static TREE *Tmake(const char *);
static TREE *Trotll(TREE *, TREE *);
static TREE *Trotlh(TREE *, TREE *);
static TREE *Trothl(TREE *, TREE *);
static TREE *Trothh(TREE *, TREE *);
static void Tbalance(TREE **);
static TREE *Tinsertavl(TREE **, const char *, int, int *);
static int Tsubprocess(TREE *, int, int (*f) (TREE *, void *), void *);
static int Tprintone(TREE *, void *);
/*************************************************************
*** T R E E P R O C E S S I N G R O U T I N E S ***
*************************************************************/
void
Tfree(TREE ** t)
{
if (*t == NULL)
return;
Tfree(&((*t)->Tlink));
Tfree(&((*t)->Texec));
Tfree(&((*t)->Tlo));
Tfree(&((*t)->Thi));
if ((*t)->Tname)
free((*t)->Tname);
if ((*t)->Tuser)
free((*t)->Tuser);
if ((*t)->Tgroup)
free((*t)->Tgroup);
free(*(char **) t);
*t = NULL;
}
static TREE *
Tmake(const char *p)
{
TREE *t;
t = (TREE *) malloc(sizeof(TREE));
if (t == NULL)
goaway("Cannot allocate memory");
t->Tname = (p == NULL) ? NULL : estrdup(p);
t->Tflags = 0;
t->Tuid = 0;
t->Tgid = 0;
t->Tuser = NULL;
t->Tgroup = NULL;
t->Tmode = 0;
t->Tctime = 0;
t->Tmtime = 0;
t->Tlink = NULL;
t->Texec = NULL;
t->Tbf = 0;
t->Tlo = NULL;
t->Thi = NULL;
return (t);
}
static TREE *
Trotll(TREE * tp, TREE * tl)
{
tp->Tlo = tl->Thi;
tl->Thi = tp;
tp->Tbf = tl->Tbf = 0;
return (tl);
}
static TREE *
Trotlh(TREE * tp, TREE * tl)
{
TREE *th;
th = tl->Thi;
tp->Tlo = th->Thi;
tl->Thi = th->Tlo;
th->Thi = tp;
th->Tlo = tl;
tp->Tbf = tl->Tbf = 0;
if (th->Tbf == 1)
tp->Tbf = -1;
else if (th->Tbf == -1)
tl->Tbf = 1;
th->Tbf = 0;
return (th);
}
static TREE *
Trothl(TREE * tp, TREE * th)
{
TREE *tl;
tl = th->Tlo;
tp->Thi = tl->Tlo;
th->Tlo = tl->Thi;
tl->Tlo = tp;
tl->Thi = th;
tp->Tbf = th->Tbf = 0;
if (tl->Tbf == -1)
tp->Tbf = 1;
else if (tl->Tbf == 1)
th->Tbf = -1;
tl->Tbf = 0;
return (tl);
}
static TREE *
Trothh(TREE * tp, TREE * th)
{
tp->Thi = th->Tlo;
th->Tlo = tp;
tp->Tbf = th->Tbf = 0;
return (th);
}
static void
Tbalance(TREE ** t)
{
if ((*t)->Tbf < 2 && (*t)->Tbf > -2)
return;
if ((*t)->Tbf > 0) {
if ((*t)->Tlo->Tbf > 0)
*t = Trotll(*t, (*t)->Tlo);
else
*t = Trotlh(*t, (*t)->Tlo);
} else {
if ((*t)->Thi->Tbf > 0)
*t = Trothl(*t, (*t)->Thi);
else
*t = Trothh(*t, (*t)->Thi);
}
}
static TREE *
Tinsertavl(TREE ** t, const char *p, int find, int *dh)
{
TREE *newt;
int cmp;
int deltah;
if (*t == NULL) {
*t = Tmake(p);
*dh = 1;
return (*t);
}
if ((cmp = strcmp(p, (*t)->Tname)) == 0) {
if (!find)
return (NULL); /* node already exists */
*dh = 0;
return (*t);
} else if (cmp < 0) {
if ((newt = Tinsertavl(&((*t)->Tlo), p, find, &deltah)) == NULL)
return (NULL);
(*t)->Tbf += deltah;
} else {
if ((newt = Tinsertavl(&((*t)->Thi), p, find, &deltah)) == NULL)
return (NULL);
(*t)->Tbf -= deltah;
}
Tbalance(t);
if ((*t)->Tbf == 0)
deltah = 0;
*dh = deltah;
return (newt);
}
TREE *
Tinsert(TREE ** t, const char *p, int find)
{
int deltah;
if (p != NULL && p[0] == '.' && p[1] == '/') {
p += 2;
while (*p == '/')
p++;
if (*p == 0)
p = ".";
}
return (Tinsertavl(t, p, find, &deltah));
}
TREE *
Tsearch(TREE * t, const char *p)
{
TREE *x;
int cmp;
x = t;
while (x) {
cmp = strcmp(p, x->Tname);
if (cmp == 0)
return (x);
if (cmp < 0)
x = x->Tlo;
else
x = x->Thi;
}
return (NULL);
}
TREE *
Tlookup(TREE * t, const char *p)
{
TREE *x;
char buf[MAXPATHLEN + 1];
char *q;
if (p == NULL)
return (NULL);
if (p[0] == '.' && p[1] == '/') {
p += 2;
while (*p == '/')
p++;
if (*p == 0)
p = ".";
}
if ((x = Tsearch(t, p)) != NULL)
return (x);
if (*p != '/' && (x = Tsearch(t, ".")) != NULL)
return (x);
(void) strncpy(buf, p, sizeof(buf) - 1);
buf[MAXPATHLEN] = '\0';
while ((q = strrchr(buf, '/')) != NULL) {
while (q >= buf && *(q - 1) == '/')
q--;
if (q == buf)
*(q + 1) = '\0';
else
*q = '\0';
if ((x = Tsearch(t, buf)) != NULL)
return (x);
if (q == buf)
break;
}
return (NULL);
}
static int process_level;
static int
Tsubprocess(TREE * t, int reverse, int (*f) (TREE *, void *), void *argp)
{
int x = SCMOK;
process_level++;
if (reverse ? t->Thi : t->Tlo)
x = Tsubprocess(reverse ? t->Thi : t->Tlo,
reverse, f, argp);
if (x == SCMOK) {
x = (*f) (t, argp);
if (x == SCMOK) {
if (reverse ? t->Tlo : t->Thi)
x = Tsubprocess(reverse ? t->Tlo : t->Thi,
reverse, f, argp);
}
}
process_level--;
return (x);
}
/* VARARGS2 */
int
Trprocess(TREE * t, int (*f) (TREE *, void *), void *args)
{
if (t == NULL)
return (SCMOK);
process_level = 0;
return (Tsubprocess(t, TRUE, f, args));
}
/* VARARGS2 */
int
Tprocess(TREE * t, int (*f) (TREE *, void *), void *args)
{
if (t == NULL)
return (SCMOK);
process_level = 0;
return (Tsubprocess(t, FALSE, f, args));
}
static int
/*ARGSUSED*/
Tprintone(TREE * t, void *v __unused)
{
int i;
for (i = 0; i < (process_level * 2); i++)
(void) putchar(' ');
printf("Node at %p name '%s' flags %o hi %p lo %p\n", t, t->Tname, t->Tflags, t->Thi, t->Tlo);
return (SCMOK);
}
void
Tprint(TREE * t, char *p)
{ /* print tree -- for debugging */
printf("%s\n", p);
(void) Tprocess(t, Tprintone, NULL);
printf("End of tree\n");
(void) fflush(stdout);
}