368 lines
7.5 KiB
C
368 lines
7.5 KiB
C
/* $NetBSD: stree.c,v 1.3 1997/06/17 18:56:39 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 <libc.h>
|
|
#include <c.h>
|
|
#include <sys/param.h>
|
|
#include "supcdefs.h"
|
|
#include "supextern.h"
|
|
|
|
#define Static static /* comment for debugging */
|
|
|
|
Static TREE *Tmake __P((char *));
|
|
Static TREE *Trotll __P((TREE *, TREE *));
|
|
Static TREE *Trotlh __P((TREE *, TREE *));
|
|
Static TREE *Trothl __P((TREE *, TREE *));
|
|
Static TREE *Trothh __P((TREE *, TREE *));
|
|
Static void Tbalance __P((TREE **));
|
|
Static TREE *Tinsertavl __P((TREE **, char *, int, int *));
|
|
Static int Tsubprocess __P((TREE *, int, int (*f )(TREE *, void *), void *));
|
|
Static int Tprintone __P((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 (t)
|
|
register 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 (p)
|
|
char *p;
|
|
{
|
|
register TREE *t;
|
|
t = (TREE *) malloc (sizeof (TREE));
|
|
t->Tname = (p == NULL) ? NULL : salloc (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 (tp,tl)
|
|
register TREE *tp,*tl;
|
|
{
|
|
tp->Tlo = tl->Thi;
|
|
tl->Thi = tp;
|
|
tp->Tbf = tl->Tbf = 0;
|
|
return(tl);
|
|
}
|
|
|
|
Static
|
|
TREE *Trotlh (tp,tl)
|
|
register TREE *tp,*tl;
|
|
{
|
|
register 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 (tp,th)
|
|
register TREE *tp,*th;
|
|
{
|
|
register 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 (tp,th)
|
|
register TREE *tp,*th;
|
|
{
|
|
tp->Thi = th->Tlo;
|
|
th->Tlo = tp;
|
|
tp->Tbf = th->Tbf = 0;
|
|
return(th);
|
|
}
|
|
|
|
Static void
|
|
Tbalance (t)
|
|
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 (t,p,find,dh)
|
|
TREE **t;
|
|
char *p;
|
|
int find;
|
|
int *dh;
|
|
{
|
|
register TREE *newt;
|
|
register 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 (t,p,find)
|
|
TREE **t;
|
|
register 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 (t,p)
|
|
TREE *t;
|
|
char *p;
|
|
{
|
|
register TREE *x;
|
|
register 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 (t,p)
|
|
TREE *t;
|
|
char *p;
|
|
{
|
|
register TREE *x;
|
|
char buf[MAXPATHLEN+1];
|
|
|
|
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 ((p = rindex(buf, '/')) != NULL) {
|
|
while (p >= buf && *(p-1) == '/')
|
|
p--;
|
|
if (p == buf)
|
|
*(p+1) = '\0';
|
|
else
|
|
*p = '\0';
|
|
if ((x = Tsearch (t,buf)) != NULL)
|
|
return (x);
|
|
if (p == buf)
|
|
break;
|
|
}
|
|
return (NULL);
|
|
}
|
|
|
|
Static int process_level;
|
|
|
|
Static
|
|
int Tsubprocess (t,reverse,f,argp)
|
|
TREE *t;
|
|
int reverse;
|
|
int (*f) __P((TREE *, void *));
|
|
void *argp;
|
|
{
|
|
register 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 (t,f,args)
|
|
TREE *t;
|
|
int (*f) __P((TREE *, void *));
|
|
void *args;
|
|
{
|
|
if (t == NULL) return (SCMOK);
|
|
process_level = 0;
|
|
return (Tsubprocess (t,TRUE,f,args));
|
|
}
|
|
|
|
/* VARARGS2 */
|
|
int Tprocess (t,f,args)
|
|
TREE *t;
|
|
int (*f) __P((TREE *, void *));
|
|
void *args;
|
|
{
|
|
if (t == NULL) return (SCMOK);
|
|
process_level = 0;
|
|
return (Tsubprocess (t,FALSE,f,args));
|
|
}
|
|
|
|
Static
|
|
int Tprintone (t, v)
|
|
TREE *t;
|
|
void *v;
|
|
{
|
|
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 (t,p) /* print tree -- for debugging */
|
|
TREE *t;
|
|
char *p;
|
|
{
|
|
printf ("%s\n",p);
|
|
(void) Tprocess (t,Tprintone, NULL);
|
|
printf ("End of tree\n");
|
|
(void) fflush (stdout);
|
|
}
|