/* Copyright (C) 1991, Marcus J. Ranum. All rights reserved. */ #ifndef lint static char RCSid[] = "$Header: /usr/users/mjr/hacks/umud/RCS/list.c,v 1.1 91/07/04 17:32:27 mjr Rel $"; #endif /* 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(l,nam) 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(l,nam) 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(l,nam,lp) 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(l,buf) char *l; char *buf; { char *op = buf; if(l == (char *)0) return(l); while(*l != '\0') { if(*l == ';') { l++; break; } *op++ = *l++; } *op = '\0'; if(op == buf) return((char *)0); 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(l,nam,lp) 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(l) char *l; { char *cp; int ret = 0; if((cp = l) == (char *)0) return(0); while(*cp != '\0') { if(*cp == ';') ret++; l++; } return(ret); }