#include "copyright.h"
#include "config.h"
#include "params.h"
#include "db.h"
#include "tune.h"
#include "props.h"
#include "externs.h"
#include "interface.h"
/* propdirs.c -- handles propdirs property creation, deletion, and finding. */
/* WARNING: These routines all hack up the path string passed to them. */
/* USES:
PropPtr locate_prop(PropPtr root, char *name)
if root is NULL, return NULL.
PropPtr new_prop(PropPtr *root, char *name)
if *root is NULL, create a new propdir, then insert the prop
PropPtr delete_prop(PropPtr *root, char *name)
when last prop in dir is deleted, destroy propdir & change *root to NULL
PropPtr first_node(PropPtr root)
if root is NULL, return NULL
PropPtr next_node(PropPtr root)
if root is NULL, return NULL
*/
/*
* returns pointer to the new property node. Returns a pointer to an
* existing elem of the given name, if one already exists. Returns
* NULL if the name given is bad.
* root is the pointer to the root propdir node. This is updated in this
* routine to point to the new root node of the structure.
* path is the name of the property to insert
*/
PropPtr
propdir_new_elem(PropPtr * root, char *path)
{
PropPtr p;
char *n;
while (*path && *path == PROPDIR_DELIMITER)
path++;
if (!*path)
return (NULL);
n = index(path, PROPDIR_DELIMITER);
while (n && *n == PROPDIR_DELIMITER)
*(n++) = '\0';
if (n && *n) {
/* just another propdir in the path */
p = new_prop(root, path);
return (propdir_new_elem(&PropDir(p), n));
} else {
/* aha, we are finally to the property itself. */
p = new_prop(root, path);
return (p);
}
}
/* returns pointer to the updated propdir structure's root node */
/* root is the pointer to the root propdir node */
/* path is the name of the property to delete */
PropPtr
propdir_delete_elem(PropPtr root, char *path)
{
PropPtr p;
char *n;
if (!root)
return (NULL);
while (*path && *path == PROPDIR_DELIMITER)
path++;
if (!*path)
return (root);
n = index(path, PROPDIR_DELIMITER);
while (n && *n == PROPDIR_DELIMITER)
*(n++) = '\0';
if (n && *n) {
/* just another propdir in the path */
p = locate_prop(root, path);
if (p && PropDir(p)) {
/* yup, found the propdir */
SetPDir(p, propdir_delete_elem(PropDir(p), n));
if (!PropDir(p) && PropType(p) == PROP_DIRTYP) {
root = delete_prop(&root, PropName(p));
}
}
/* return the updated root pntr */
return (root);
} else {
/* aha, we are finally to the property itself. */
p = locate_prop(root, path);
if (p && PropDir(p)) {
delete_proplist(PropDir(p));
}
(void) delete_prop(&root, path);
return (root);
}
}
/* returns pointer to given property */
/* root is the pointer to the root propdir node */
/* path is the name of the property to find */
PropPtr
propdir_get_elem(PropPtr root, char *path)
{
PropPtr p;
char *n;
if (!root)
return (NULL);
while (*path && *path == PROPDIR_DELIMITER)
path++;
if (!*path)
return (NULL);
n = index(path, PROPDIR_DELIMITER);
while (n && *n == PROPDIR_DELIMITER)
*(n++) = '\0';
if (n && *n) {
/* just another propdir in the path */
p = locate_prop(root, path);
if (p && PropDir(p)) {
/* yup, found the propdir */
return (propdir_get_elem(PropDir(p), n));
}
return (NULL);
} else {
/* aha, we are finally to the property subname itself. */
if ((p = locate_prop(root, path))) {
/* found the property! */
return (p);
}
return (NULL); /* nope, doesn't exist */
}
}
/* returns pointer to first property in the given propdir */
/* root is the pointer to the root propdir node */
/* path is the name of the propdir to find the first node of */
PropPtr
propdir_first_elem(PropPtr root, char *path)
{
PropPtr p;
while (*path && *path == PROPDIR_DELIMITER)
path++;
if (!*path)
return (first_node(root));
p = propdir_get_elem(root, path);
if (p && PropDir(p)) {
return (first_node(PropDir(p))); /* found the property! */
}
return (NULL); /* nope, doesn't exist */
}
/* returns pointer to next property after the given one in the propdir */
/* root is the pointer to the root propdir node */
/* path is the name of the property to find the next node after */
/* Note: Finds the next alphabetical property, regardless of the existence
of the original property given. */
PropPtr
propdir_next_elem(PropPtr root, char *path)
{
PropPtr p;
char *n;
if (!root)
return (NULL);
while (*path && *path == PROPDIR_DELIMITER)
path++;
if (!*path)
return (NULL);
n = index(path, PROPDIR_DELIMITER);
while (n && *n == PROPDIR_DELIMITER)
*(n++) = '\0';
if (n && *n) {
/* just another propdir in the path */
p = locate_prop(root, path);
if (p && PropDir(p)) {
/* yup, found the propdir */
return (propdir_next_elem(PropDir(p), n));
}
return (NULL);
} else {
/* aha, we are finally to the property subname itself. */
return (next_node(root, path));
}
}
/* return true if a property contains a propdir */
int
propdir_check(PropPtr root, char *path)
{
PropPtr p;
if ((p = propdir_get_elem(root, path)))
return (PropDir(p) != NULL);
return (0);
}
const char *
propdir_name(const char *name)
{
static char pnbuf[BUFFER_LEN];
const char *i;
char *o;
i = name;
o = pnbuf;
while (*i) {
while (*i == PROPDIR_DELIMITER)
i++;
*o++ = PROPDIR_DELIMITER;
while (*i && *i != PROPDIR_DELIMITER)
*o++ = *i++;
}
*o = '\0';
while (*o != PROPDIR_DELIMITER)
*o-- = '\0';
return pnbuf;
}
/* returns path of first unloaded propdir in given path */
/* returns NULL if all propdirs to path are loaded */
/* root is the pointer to the root propdir node */
/* path is the name of the propdir to find */
const char *
propdir_unloaded(PropPtr root, const char *path)
{
PropPtr p;
const char *n;
char *o, *l;
static char buf[BUFFER_LEN];
if (!root)
return NULL;
n = path;
o = buf;
while (*n == PROPDIR_DELIMITER)
n++;
if (!*n)
return NULL;
while (*n) {
*o++ = '/';
l = o;
while (*n && *n != PROPDIR_DELIMITER)
*o++ = *n++;
while (*n == PROPDIR_DELIMITER)
n++;
*o = '\0';
p = locate_prop(root, l);
if (!p) {
return NULL;
}
if (PropFlags(p) & PROP_DIRUNLOADED) {
SetPFlags(p, (PropFlags(p) & ~PROP_DIRUNLOADED));
return buf + 1;
}
root = PropDir(p);
}
return NULL;
}