/* $Id: tree.c,v 2.1 2005/10/09 03:52:38 ksb Exp $ */ #include #include #include #include #include "machine.h" #include "tree.h" static TREE *pThead = NULL; static TREE * pTnewNode(pcName) char *pcName; { register TREE *pTnew; pTnew = (TREE *) malloc(sizeof(TREE)); pTnew->pcName = pcName ? strdup(pcName) : NULL; pTnew->pTparent = NULL; pTnew->pTsib = NULL; pTnew->pTchild = NULL; pTnew->fMark = 0; return pTnew; } static TREE * pTaddChild(pTnode, pcName) TREE *pTnode; char *pcName; { register TREE *pTnew = pTnewNode(pcName); pTnew->pTparent = pTnode; pTnew->pTsib = pTnode->pTchild; pTnode->pTchild = pTnew; return pTnew; } static TREE * pTfindChild(pTnode, pcName) TREE *pTnode; char *pcName; { for (pTnode = pTnode->pTchild; pTnode; pTnode = pTnode->pTsib) { if (!strcmp(pcName, pTnode->pcName)) return pTnode; } return NULL; } /* generate the elements of the path in the current filename * in our representation of the directory tree. */ TREE * pTfindDirTree(pcName) char *pcName; { register char *s = pcName, *t; register TREE *pTnode, *pTnext; if (!pThead) { /* initialize */ pThead = pTnewNode(NULL); } if (0 == strncmp(s, "./", 2)) s += 2; pTnode = pThead; for (;;) { t = strchr(s, '/'); if (!t) { return pTnode; } *t = '\000'; if ((TREE *)0 == (pTnext = pTfindChild(pTnode, s))) pTnode = pTaddChild(pTnode, s); else pTnode = pTnext; *t = '/'; s = t + 1; } /* NOT REACHED */ } /* mark all the elements of the path you found with pTfindDirTree */ void MarkDirTree(pTnode) TREE *pTnode; { for (; pTnode; pTnode = pTnode->pTparent) pTnode->fMark = 1; } /* do something with all the elements you marked with MarkDirTree. * I did this in a tricky nonrecursive way first, but it wasn't really * better than the recursion. */ static void _UseDirMarks(CFunc, pTnode, pcPath) void (*CFunc)(); TREE *pTnode; char *pcPath; { char acBuf[MAXPATHLEN+1]; TREE *pTloop; if ((TREE *)0 == pTnode || !pTnode->fMark) { return; } /* do self then children (preorder traversal) */ if (pTnode->pcName) { sprintf(acBuf, "%s%s", pcPath, pTnode->pcName); (*CFunc)(acBuf); strcat(acBuf, "/"); } else { acBuf[0] = '\000'; } for (pTloop = pTnode->pTchild; pTloop; pTloop = pTloop->pTsib) { _UseDirMarks(CFunc, pTloop, acBuf); } } void UseDirMarks(CFunc) void (*CFunc)(); { _UseDirMarks(CFunc, pThead, ""); } #ifdef TEST extern puts(); main(ac, av) int ac; char **av; { while (*av) { MarkDirTree(pTfindDirTree(*av)); av++; } UseDirMarks(puts); } #endif