/*
Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/
/* configure all options BEFORE including system stuff. */
#include "config.h"
#include "sbuf.h"
#include "mud.h"
/*
WARNING - static stretchy buffers
several static stretchy buffers are allocated and kept here. this is the
only way to do this efficiently. if the allocations fail, there's really
jack-all we can do at this point, so we exit
*/
/* PRIVATE!! search for 'nam' in list 'l' and return a pointer to it */
static char *lstlookup (char *l, char *nam)
{
char *np;
char *bp;
if (l == (char *) 0)
return ((char *) 0);
while (*l != '\0') {
np = nam;
bp = l;
while (*np != '\0') {
if (*l != *np)
break;
l++, np++;
}
/* have we found it ? */
if (*np == '\0' && (*l == '\0' || *l == ';'))
return (bp);
/* no. skip to next semicolon */
while (*l != '\0') {
if (*l++ == ';')
break;
}
}
return ((char *) 0);
}
/* user-level access to listlookup() - denied because i want to keep
people from directly accessing pointers into the contents of a list */
int lstlook (char *l, char *nam)
{
if (lstlookup (l, nam))
return (1);
return (0);
}
/*
add 'nam' to list 'l' and return a pointer to the result.
if 'lp' is not (int *)0, place the length of the result in 'lp.
*/
char *lstadd (char *l, char *nam, int *lp)
{
static Sbuf *sp = (Sbuf *) 0;
char *xp;
if (sp == (Sbuf *) 0 && (sp = sbuf_new ()) == (Sbuf *) 0)
fatal ("cannot get list buffer: ", (char *) -1, "\n", (char *) 0);
sbuf_reset (sp);
xp = l;
while (xp != (char *) 0 && *xp != '\0') {
if (*xp != ';' || *(xp + 1) != ';')
sbuf_put (*xp, sp);
xp++;
}
/* only you can prevent dups */
if (lstlookup (l, nam) == (char *) 0) {
/* special case - if the previous list SHOULD have a ; add */
if (xp != (char *) 0 && xp > l && *(xp - 1) != ';')
sbuf_put (';', sp);
/* copy in new and add a semicolon */
while (*nam != '\0')
sbuf_put (*nam, sp), nam++;
sbuf_put (';', sp);
}
sbuf_put ('\0', sp);
if (lp != (int *) 0)
*lp = sbuf_len (sp);
return (sbuf_buf (sp));
}
/*
return a copy of the next element in list 'l', or null pointer at list end.
buffer given is assumed to be large enough to fit an ID.
WARNING - do not fiddle with the logic of scanning list next elements.
NOTE!!!!! the match code assumes that this routine will "do the right thing"
if given a single object-id as well as a list. if you change that, all hell
will break loose in matching.
*/
char *lstnext (char *l, char *buf, int bs)
{
char *op = buf;
if (l == (char *) 0 || *l == '\0')
return ((char *) 0);
while (*l != '\0') {
if (*l == ';') {
l++;
/* if there is nothing in the buffer, keep going. */
if (op != buf)
break;
else
continue;
}
/* objid too big */
if (--bs <= 0) {
log_printf ("object-id too big\n", (char *) 0);
while (*l != ';' && *l != '\0')
l++;
op = buf;
continue;
}
*op++ = *l++;
}
*op = '\0';
return (l);
}
/*
return a copy of the next element in list 'l', or null pointer at list end.
items are copied out into a stretchy-buf.
*/
char *lstnextsbuf (char *l, Sbuf * sb)
{
if (l == (char *) 0 || *l == '\0')
return ((char *) 0);
sbuf_reset (sb);
while (*l != '\0') {
if (*l == ';') {
l++;
/* >= 'cuz we haven't added the null yet */
if (sbuf_len (sb) >= 0)
break;
else {
sbuf_reset (sb);
continue;
}
}
sbuf_put (*l, sb), l++;
}
sbuf_put ('\0', sb);
return (l);
}
/*
delete 'nam' from list 'l' and return a pointer to the result
if 'lp' is not (int *)0, place the length of the result in 'lp.
*/
char *lstdel (char *l, char *nam, int *lp)
{
static Sbuf *sp = (Sbuf *) 0;
char *p1;
char *p2;
if (sp == (Sbuf *) 0 && (sp = sbuf_new ()) == (Sbuf *) 0)
fatal ("cannot get list buffer: ", (char *) -1, "\n", (char *) 0);
sbuf_reset (sp);
/* heh. already not there, you goob */
if ((p1 = lstlookup (l, nam)) == (char *) 0) {
(void) sbuf_strcpy (l, sp);
goto done;
}
p2 = l;
while (p2 < p1)
sbuf_put (*p2, sp), p2++;
/* skip the infected part */
while (*p2 != '\0') {
/* skip the semicolon if one */
if (*p2 == ';') {
p2++;
break;
}
p2++;
}
/* take the rest */
while (*p2 != '\0')
sbuf_put (*p2, sp), p2++;
sbuf_put ('\0', sp);
done:
if (lp != (int *) 0)
*lp = sbuf_len (sp);
return (sbuf_buf (sp));
}
/* return the number of elements in list 'l' */
int lstcnt (char *l)
{
int ret = 0;
if (l == (char *) 0)
return (0);
while (*l != '\0') {
if (*l == ';')
ret++;
l++;
}
return (ret);
}