#include <stdio.h> #include <stdlib.h> #include <string.h> #include "struct.h" /* * Allocator.c: Version 1.11 * Author: Alan Cox * Last Changed: 14/12/90 * * Purpose: * Provides basic low level functions for memory allocation in * the system, and also maintains and allocates entries in the item * arrays. * * Bugs & Limits * * Functions Provided: * NObs,emalloc,estralloc,TrashItem,AddObject,AddRoom,AddPlayer, * SetName,SetIOH,SetLong,SetState,SetMaxState,SetDesc. * * Functions Used: * None. */ struct Object **ItemArray; static tag max_Object=0; static tag next_Object=0; /* * Return the number of items in the game */ tag NObs() { return(next_Object); } /* * Allocate a block of memory and zero its contents */ char *emalloc(x) int x; { char *t=(char *)malloc(x); if(!t) { fprintf(stderr,"[SYSTEM ERROR] : emalloc out of memory\n"); exit(1); } bzero(t,x); return(t); } /* * Allocate a copy of a given string. * Currently allocating NULL gives you a null string. This is a hack * until the parser is tidied up properly. */ char *estralloc(x) char *x; { char *y; if(x==NULL) x=""; y=emalloc(strlen(x)+1); strcpy(y,x); return(y); } /* * Item number allocation */ /* * Private types for maintaining free item stack */ typedef struct freestack FSTACK; struct freestack { FSTACK *Next; tag Number; }; static FSTACK *FreeStack=NULL; extern void FreeSlot(tag); extern tag NextSlot(void); static void FreeSlot(n) tag n; { FSTACK *f=(FSTACK *)malloc(sizeof(FSTACK)); if(f==NULL) { fprintf(stderr,"FreeSlot: Out Of Memory\n"); exit(0); } f->Number=n; f->Next=FreeStack; FreeStack=f; } static tag NextSlot() { /* * See if we have any free item slots stacked. Such item slots * already exist but are NULL ptrs for items. */ if(FreeStack) { tag i=FreeStack->Number; FSTACK *f=FreeStack; FreeStack=FreeStack->Next; free(f); return(i); } if(next_Object==max_Object) { if(max_Object) { max_Object+=100; ItemArray=(struct Object **)realloc(ItemArray,max_Object*sizeof(char *)); if(ItemArray==NULL) { fprintf(stderr,"PANIC! No memory\n"); exit(1); } return(next_Object++); } else { max_Object=100; ItemArray=(struct Object **)malloc(100*sizeof(char *)); return(next_Object++); } } return(next_Object++); } void TrashItem(i) tag i; { int ct; switch(TYPE(i)) { case FL_PLAYER:free(PLAYER(i)->pl_IOH[0]); free(PLAYER(i)->pl_IOH[1]); free(PLAYER(i)->pl_IOH[2]); break; case FL_OBJECT:ct=0; while(ct<MAXSTATE(i)) { free(OBJECT(i)->ob_Desc[ct]); ct++; } break; case FL_ROOM: free(ROOM(i)->rm_Long); break; default:fprintf(stderr,"Panic: Item '%s' not valid class\n",NAME(i)); } free(NAME(i)); free(ItemArray[VAL(i)]); ItemArray[VAL(i)]=NULL; FreeSlot(VAL(i)); } tag AddObject() { tag n=NextSlot(); ItemArray[n]=(struct Object *)emalloc(sizeof(struct Object)); n=ISOBJ(n); LOC(n)=ISOBJ(-1); FLAGS(n)=FL_OBJECT; OBJECT(n)->ob_Name=estralloc("null"); OBJECT(n)->ob_Data[2]=0x00; OBJECT(n)->ob_Desc=(char **)emalloc(sizeof(char *)); SETSIZE(n,0); SETWEIGHT(n,0); CLASS(n)=0; return(n); } tag AddRoom() { ITEM n=NextSlot(); ItemArray[n]=(struct Object *)emalloc(sizeof(struct Room)); n=ISOBJ(n); FLAGS(n)=FL_ROOM; ROOM(n)->rm_Name=estralloc("null"); ROOM(n)->rm_Long=estralloc("null"); /* if(EXIT(n,0)!=0||EXIT(n,1)!=0) { fprintf(stderr,"Allocation botched up!\n"); exit(0); }*/ return(n); } tag AddPlayer() { tag n=NextSlot(); ItemArray[n]=(struct Object *)emalloc(sizeof(struct Player)); n=ISOBJ(n); /* if(IFOBJ(n)==0) printf("IFOBJ/ISOBJ wrong\n"); */ PLAYER(n)->pl_Name=estralloc("null"); FLAGS(n)=FL_PLAYER; LOC(n)=ISOBJ(-1); PLAYER(n)->pl_IOH[0]=estralloc("is here"); PLAYER(n)->pl_IOH[1]=estralloc("leaves"); PLAYER(n)->pl_IOH[2]=estralloc("arrives"); return(n); } void SetName(n,x) tag n; char *x; { free(OBJECT(n)->ob_Name); OBJECT(n)->ob_Name=estralloc(x); } void SetIOH(n,s,x) tag n; int s; char *x; { if(TYPE(n)!=FL_PLAYER) { log_error("[ERROR]: SetIOH, not a player.\n",NULL); panic(); } free(PLAYER(n)->pl_IOH[s]); PLAYER(n)->pl_IOH[s]=estralloc(x); } void SetLong(n,x) tag n; char *x; { if(TYPE(n)!=FL_ROOM) { log_error("[ERROR]: SetLong, not a room.\n",NULL); panic(); } free(ROOM(n)->rm_Long); ROOM(n)->rm_Long=estralloc(x); } void SetState(n,m) tag n; int m; { if(m<0||m>=MAXSTATE(n)) { log_error("[ERROR]: SetState, state out of range\n",NULL); panic(); } if(TYPE(n)!=FL_OBJECT) { log_error("[ERROR]: SetState, not an object.\n",NULL); panic(); } OBJECT(n)->ob_Data[2]&=~15; OBJECT(n)->ob_Data[2]|=m; MoveItem(n,-2); } void SetMaxState(n,f) tag n; int f; { int l; if(f<1||f>16) { log_error("[ERROR]: MaxState must range from 1-16.\n",NULL); panic(); } if(TYPE(n)!=FL_OBJECT) { log_error("[ERROR]: SetMaxState, not an object.\n",NULL); panic(); } l=MAXSTATE(n); OBJECT(n)->ob_Desc=(char **)realloc(OBJECT(n)->ob_Desc, sizeof(char *)*f); while(l<f) { OBJECT(n)->ob_Desc[l]=estralloc("(unset)"); l++; } if(STATE(n)>=f) SetState(n,0); OBJECT(n)->ob_Data[2]=(f<<4)+STATE(n); } void SetDesc(n,m,x) tag n; int m; char *x; { if(TYPE(n)!=FL_OBJECT) { log_error("[ERROR]: SetDec, not an object.\n",NULL); panic(); } if(m<0||m>=MAXSTATE(n)) { log_error("SetDesc: State invalid for %s\n",NAME(n)); panic(); } free(OBJECT(n)->ob_Desc[m]); OBJECT(n)->ob_Desc[m]=estralloc(x); }