/* attributes.c */ #include "config.h" /* * This file is part of TeenyMUD II. * Copyright(C) 1993, 1994, 1995 by Jason Downs. * All rights reserved. * * TeenyMUD II is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * TeenyMUD II is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (see the file 'COPYING'); if not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * */ #include <stdio.h> #include <sys/types.h> #ifdef HAVE_STRING_H #include <string.h> #else #include <strings.h> #endif /* HAVE_STRING_H */ #include <ctype.h> #include "conf.h" #include "teeny.h" #include "teenydb.h" #include "externs.h" /* user def'd attributes */ /* hash routine for attribute names */ int attr_hash(str) char *str; { register unsigned int i = 0; if((str == (char *)NULL) || (str[0] == '\0')) return(0); while(str[0] != '\0') { i = (i * 10) + (to_lower(str[0]) - '0'); str++; } return((i*1103515245 + 12345) % ATTR_WIDTH); } int attr_set(obj, name, flags) int obj; char *name; int flags; { struct attr *attrs; struct obj_data *dat; if (!_exists_object(obj)) return (-1); if ((dat = lookup_obj(obj)) == (struct obj_data *) NULL) return (-1); for (attrs = dat->attributes[attr_hash(name)]; attrs != (struct attr *)NULL; attrs = attrs->next) { if (!strcasecmp(attrs->name, name)) { attrs->flags = flags; DSC_FLAG2(main_index[dat->objnum]) |= DIRTY; return (0); } } return (-2); } int attr_addlock(obj, name, data, flags) int obj; char *name; struct boolexp *data; int flags; { register struct attr *curr, *new; struct obj_data *dat; int hashval; if (!_exists_object(obj)) return (-1); if ((dat = lookup_obj(obj)) == (struct obj_data *) NULL) return (-1); hashval = attr_hash(name); for (curr = dat->attributes[hashval]; curr != (struct attr *)NULL; curr = curr->next) { if (!strcasecmp(curr->name, name)) { if(curr->type != ATTR_LOCK) { ty_free((VOID *)(curr->dat).str); curr->type = ATTR_LOCK; } else boolexp_free((curr->dat).lock); (curr->dat).lock = data; strcpy(curr->name, name); if(islower(name[0])) (curr->name)[0] = to_upper((curr->name)[0]); curr->flags = flags; DSC_FLAG2(main_index[dat->objnum]) |= DIRTY; return (0); } } new = (struct attr *)ty_malloc(sizeof(struct attr), "attr_add.new"); new->name = (char *) ty_strdup(name, "attr_add.name"); if(islower(name[0])) (new->name)[0] = to_upper((new->name)[0]); (new->dat).lock = data; new->flags = flags; new->type = ATTR_LOCK; /* link it in, new style */ new->next = dat->attributes[hashval]; if(dat->attributes[hashval] == (struct attr *) NULL) new->prev = new; else { new->prev = (dat->attributes[hashval])->prev; (dat->attributes[hashval])->prev = new; } dat->attributes[hashval] = new; dat->attr_total++; DSC_FLAG2(main_index[dat->objnum]) |= DIRTY; DSC_SIZE(main_index[dat->objnum]) += strlen(name) + 1; mudstat.cache_usage += strlen(name) + 1; return (0); } int attr_add(obj, name, data, flags) int obj; char *name, *data; int flags; { register struct attr *curr, *new; struct obj_data *dat; int oldsize, hashval; if (!_exists_object(obj)) return (-1); if ((dat = lookup_obj(obj)) == (struct obj_data *) NULL) return (-1); hashval = attr_hash(name); for (curr = dat->attributes[hashval]; curr != (struct attr *)NULL; curr = curr->next) { if (!strcasecmp(curr->name, name)) { if(curr->type != ATTR_STRING) { oldsize = 0; boolexp_free((curr->dat).lock); curr->type = ATTR_STRING; } else { oldsize = strlen((curr->dat).str) + 1; ty_free((VOID *) (curr->dat).str); } (curr->dat).str = (char *) ty_strdup(data, "attr_add.data"); strcpy(curr->name, name); if(islower(name[0])) (curr->name)[0] = to_upper((curr->name)[0]); curr->flags = flags; DSC_FLAG2(main_index[dat->objnum]) |= DIRTY; DSC_SIZE(main_index[dat->objnum]) = (DSC_SIZE(main_index[dat->objnum]) - oldsize) + strlen(data) + 1; mudstat.cache_usage = (mudstat.cache_usage - oldsize) + strlen(data) + 1; return (0); } } new = (struct attr *)ty_malloc(sizeof(struct attr), "attr_add.new"); new->name = (char *) ty_strdup(name, "attr_add.name"); if(islower(name[0])) (new->name)[0] = to_upper((new->name)[0]); (new->dat).str = (char *) ty_strdup(data, "attr_add.data"); new->flags = flags; new->type = ATTR_STRING; /* link it in, new style */ new->next = dat->attributes[hashval]; if(dat->attributes[hashval] == (struct attr *) NULL) new->prev = new; else { new->prev = (dat->attributes[hashval])->prev; (dat->attributes[hashval])->prev = new; } dat->attributes[hashval] = new; dat->attr_total++; DSC_FLAG2(main_index[dat->objnum]) |= DIRTY; DSC_SIZE(main_index[dat->objnum]) += strlen(name) + strlen(data) + 2; mudstat.cache_usage += strlen(name) + strlen(data) + 2; return (0); } int attr_delete(obj, name) int obj; char *name; { register struct attr *curr; struct obj_data *dat; int oldsize, hashval; if (!_exists_object(obj)) return (-1); if ((dat = lookup_obj(obj)) == (struct obj_data *) NULL) return (-1); hashval = attr_hash(name); for (curr = dat->attributes[hashval]; curr != (struct attr *)NULL; curr = curr->next) { if (!strcasecmp(curr->name, name)) { oldsize = strlen(curr->name) + 1; if (curr == dat->attributes[hashval]) { dat->attributes[hashval] = curr->next; if (dat->attributes[hashval] != (struct attr *)NULL) (dat->attributes[hashval])->prev = dat->attributes[hashval]; } else { (curr->prev)->next = curr->next; } if (curr->next != (struct attr *)NULL) { (curr->next)->prev = curr->prev; } else if (dat->attributes[hashval] != (struct attr *)NULL) { /* last thing in the list */ (dat->attributes[hashval])->prev = curr->prev; } ty_free((VOID *) curr->name); switch(curr->type) { case ATTR_STRING: oldsize += strlen((curr->dat).str) + 1; ty_free((VOID *) (curr->dat).str); break; case ATTR_LOCK: boolexp_free((curr->dat).lock); break; } dat->attr_total--; ty_free((VOID *)curr); DSC_FLAG2(main_index[dat->objnum]) |= DIRTY; DSC_SIZE(main_index[dat->objnum]) -= oldsize; mudstat.cache_usage -= oldsize; break; } } return (0); } int attr_source(obj, name) int obj; char *name; { register struct attr *attrs; struct obj_data *dat; int parent, depth, hashval; depth = 0; parent = obj; hashval = attr_hash(name); do { if (!_exists_object(parent)) return (-1); if ((dat = lookup_obj(parent)) == (struct obj_data *) NULL) return (-1); for (attrs = dat->attributes[hashval]; attrs != (struct attr *)NULL; attrs = attrs->next) { if ((attrs->flags & A_PRIVATE) && (parent != obj)) continue; if ((attrs->flags & A_PICKY) && (DSC_TYPE(main_index[parent]) != DSC_TYPE(main_index[obj]))) continue; if ((DSC_FLAG2(main_index[parent]) & PICKY) && (DSC_TYPE(main_index[parent]) != DSC_TYPE(main_index[obj]))) continue; if (!strcasecmp(attrs->name, name)) return (parent); } parent = DSC_PARENT(main_index[dat->objnum]); depth++; } while ((parent != -1) && (depth <= mudconf.parent_depth)); return(-1); } int attr_getlock_parent(obj, name, ret, flags, source) int obj; char *name; struct boolexp **ret; int *flags, *source; { register struct attr *attrs; struct obj_data *dat; int parent, depth, hashval; depth = 0; parent = obj; hashval = attr_hash(name); do { if (!_exists_object(parent)) return (-1); if ((dat = lookup_obj(parent)) == (struct obj_data *)NULL) return (-1); for (attrs = dat->attributes[hashval]; attrs != (struct attr *)NULL; attrs = attrs->next) { if ((attrs->flags & A_PRIVATE) && (parent != obj)) continue; if ((attrs->flags & A_PICKY) && (DSC_TYPE(main_index[parent]) != DSC_TYPE(main_index[obj]))) continue; if ((DSC_FLAG2(main_index[parent]) & PICKY) && (DSC_TYPE(main_index[parent]) != DSC_TYPE(main_index[obj]))) continue; if (!strcasecmp(attrs->name, name)) { if(attrs->type != ATTR_LOCK) { *ret = (struct boolexp *)NULL; *flags = -1; *source = -1; } else { *ret = (attrs->dat).lock; *flags = attrs->flags; *source = parent; } return (0); } } parent = DSC_PARENT(main_index[dat->objnum]); depth++; } while ((parent != -1) && (depth <= mudconf.parent_depth)); *ret = (struct boolexp *) NULL; *flags = -1; *source = -1; return (0); } int attr_get_parent(obj, name, ret, flags, source) int obj; char *name, **ret; int *flags, *source; { register struct attr *attrs; struct obj_data *dat; int parent, depth, hashval; depth = 0; parent = obj; hashval = attr_hash(name); do { if (!_exists_object(parent)) return (-1); if ((dat = lookup_obj(parent)) == (struct obj_data *) NULL) return (-1); for (attrs = dat->attributes[hashval]; attrs != (struct attr *)NULL; attrs = attrs->next) { if ((attrs->flags & A_PRIVATE) && (parent != obj)) continue; if ((attrs->flags & A_PICKY) && (DSC_TYPE(main_index[parent]) != DSC_TYPE(main_index[obj]))) continue; if ((DSC_FLAG2(main_index[parent]) & PICKY) && (DSC_TYPE(main_index[parent]) != DSC_TYPE(main_index[obj]))) continue; if (!strcasecmp(attrs->name, name)) { if(attrs->type != ATTR_STRING) { *ret = (char *)NULL; *flags = -1; *source = -1; } else { *ret = (attrs->dat).str; *flags = attrs->flags; *source = parent; } return (0); } } parent = DSC_PARENT(main_index[dat->objnum]); depth++; } while ((parent != -1) && (depth <= mudconf.parent_depth)); *ret = (char *) NULL; *flags = -1; *source = -1; return (0); } int attr_getlock(obj, name, ret, flags) int obj; char *name; struct boolexp **ret; int *flags; { register struct attr *attrs; struct obj_data *dat; if (!_exists_object(obj)) return (-1); if ((dat = lookup_obj(obj)) == (struct obj_data *)NULL) return (-1); for (attrs = dat->attributes[attr_hash(name)]; attrs != (struct attr *)NULL; attrs = attrs->next) { if(!strcasecmp(attrs->name, name)) { if(attrs->type != ATTR_LOCK) { *ret = (struct boolexp *)NULL; *flags = -1; } else { *ret = (attrs->dat).lock; *flags = attrs->flags; } return (0); } } *ret = (struct boolexp *)NULL; *flags = -1; return(0); } int attr_get(obj, name, ret, flags) int obj; char *name, **ret; int *flags; { register struct attr *attrs; struct obj_data *dat; if (!_exists_object(obj)) return (-1); if ((dat = lookup_obj(obj)) == (struct obj_data *) NULL) return (-1); for (attrs = dat->attributes[attr_hash(name)]; attrs != (struct attr *)NULL; attrs = attrs->next) { if (!strcasecmp(attrs->name, name)) { if(attrs->type != ATTR_STRING) { *ret = (char *)NULL; *flags = -1; } else { *ret = (attrs->dat).str; *flags = attrs->flags; } return (0); } } *ret = (char *) NULL; *flags = -1; return (0); } /* attribute search routines */ struct attr *attr_first(obj, search) int obj; struct asearch *search; { struct obj_data *dat; register int idx; if(!_exists_object(obj)) return((struct attr *)NULL); if((dat = lookup_obj(obj)) == (struct obj_data *)NULL) return((struct attr *)NULL); /* loop through the table, looking for the first attribute */ for(idx = 0; idx < ATTR_WIDTH; idx++) { if(dat->attributes[idx] != (struct attr *)NULL) { search->elem = idx; search->curr = dat->attributes[idx]; return(dat->attributes[idx]); } } return((struct attr *)NULL); } struct attr *attr_next(obj, search) int obj; struct asearch *search; { struct obj_data *dat; if(!_exists_object(obj)) return((struct attr *)NULL); if((dat = lookup_obj(obj)) == (struct obj_data *)NULL) return((struct attr *)NULL); /* find the next attribute */ if(search->curr != (struct attr *)NULL) { if((search->curr)->next != (struct attr *)NULL) { /* elem is still correct */ search->curr = (search->curr)->next; return(search->curr); } /* the current bucket is empty. find the next one. */ while(search->elem < (ATTR_WIDTH-1)) { (search->elem)++; if(dat->attributes[search->elem] != (struct attr *)NULL) { search->curr = dat->attributes[search->elem]; return(search->curr); } } } return((struct attr *)NULL); } /* attributes and list allocation */ void free_attributes(attrs) struct attr *attrs[]; { register struct attr *curr, *next; register int idx; for(idx = 0; idx < ATTR_WIDTH; idx++) { for(curr = attrs[idx]; curr != (struct attr *)NULL; curr = next) { next = curr->next; ty_free((VOID *)curr->name); switch(curr->type) { case ATTR_STRING: ty_free((VOID *)(curr->dat).str); break; case ATTR_LOCK: boolexp_free((curr->dat).lock); break; } ty_free((VOID *)curr); } } }