#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);
}