home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload
/
ShartewareOverload.cdr
/
games
/
advsys.zip
/
ADVFCN.C
< prev
next >
Wrap
Text File
|
1987-06-28
|
14KB
|
585 lines
/* advfcn.c - functions for the adventure compiler */
/*
Copyright (c) 1986, by David Michael Betz
All rights reserved
*/
#include "advcom.h"
#include "advdbs.h"
/* external variables */
extern char aname[]; /* adventure name */
extern int aversion; /* adventure version number */
extern int cptr; /* code space pointer */
extern int objbuf[]; /* object staging buffer */
extern int nprops; /* number of properties in current object */
extern int t_value; /* token value */
extern char t_token[]; /* token string */
extern char *t_names[]; /* token names */
extern int otable[]; /* object table */
extern int curobj; /* current object number */
extern int curact; /* current action offset */
extern int atable[],acnt; /* action table and count */
extern ARGUMENT *arguments; /* function argument list */
extern ARGUMENT *temporaries; /* function temporary variable list */
extern int def_flag; /* default action flag value */
extern int def_mask; /* default action mask value */
/* external routines */
extern char *malloc();
extern char *save();
/* do_adventure - handle the <ADVENTURE name version-number> statement */
do_adventure()
{
/* get the adventure name */
frequire(T_IDENTIFIER);
strncpy(aname,t_token,18);
aname[18] = 0;
/* get the adventure version number */
frequire(T_NUMBER);
aversion = t_value;
/* check for the closing paren */
frequire(T_CLOSE);
}
/* do_word - enter words of a particular type */
do_word(type)
{
int tkn;
while ((tkn = token()) == T_IDENTIFIER)
add_word(t_token,type);
require(tkn,T_CLOSE);
}
/* do_synonym - handle the <SYNONYMS ... > statement */
do_synonym()
{
int tkn,wrd;
frequire(T_IDENTIFIER);
wrd = add_word(t_token,WT_UNKNOWN);
while ((tkn = token()) == T_IDENTIFIER)
add_synonym(t_token,wrd);
require(tkn,T_CLOSE);
}
/* do_define - handle the <DEFINE ... > statement */
do_define()
{
char name[TKNSIZE+1];
int tkn;
if ((tkn = token()) == T_OPEN)
return (do_function());
stoken(tkn);
while ((tkn = token()) == T_IDENTIFIER) {
strcpy(name,t_token);
center(name,getvalue());
}
require(tkn,T_CLOSE);
}
/* do_variable - handle the <VARIABLE ... > statement */
do_variable()
{
int tkn;
while ((tkn = token()) == T_IDENTIFIER)
venter(t_token);
require(tkn,T_CLOSE);
}
/* do_defproperty - handle the <PROPERTY ... > statement */
do_defproperty()
{
int tkn;
while ((tkn = token()) == T_IDENTIFIER)
penter(t_token);
require(tkn,T_CLOSE);
}
/* do_default - handle the <DEFAULT ... > statement */
do_default()
{
int tkn;
/* process statements until end of file */
while ((tkn = token()) == T_OPEN) {
frequire(T_IDENTIFIER);
if (match("actor"))
do_dflag(A_ACTOR);
else if (match("direct-object"))
do_dflag(A_DOBJECT);
else if (match("indirect-object"))
do_dflag(A_IOBJECT);
else
error("Unknown default definition statement type");
}
require(tkn,T_CLOSE);
}
/* do_dflag - handle ACTOR, DIRECT-OBJECT, and INDIRECT-OBJECT statements */
do_dflag(flag)
int flag;
{
int tkn;
if ((tkn = token()) == T_IDENTIFIER) {
if (match("required")) {
def_flag |= flag;
def_mask &= ~flag;
}
else if (match("forbidden")) {
def_flag &= ~flag;
def_mask &= ~flag;
}
else if (match("optional"))
def_mask |= flag;
else
error("Expecting: REQUIRED, FORBIDDEN or OPTIONAL");
tkn = token();
}
else {
def_flag |= flag;
def_mask &= ~flag;
}
require(tkn,T_CLOSE);
}
/* do_object - handle object (LOCATION,OBJECT,ACTOR) definitions */
int do_object(cname,class)
char *cname; int class;
{
int tkn,obj,obase,osize,i,p;
printf("[ %s: ",cname);
frequire(T_IDENTIFIER);
printf("%s ]\n",t_token);
obj = curobj = oenter(t_token);
/* initialize the object */
objbuf[O_CLASS/2] = class;
objbuf[O_NOUNS/2] = NIL;
objbuf[O_ADJECTIVES/2] = NIL;
objbuf[O_NPROPERTIES/2] = nprops = 0;
/* copy the property list of the class object */
if (class) {
obase = otable[class];
osize = getword(obase+O_NPROPERTIES);
for (i = p = 0; i < osize; i++, p += 4)
if ((getword(obase+O_PROPERTIES+p) & P_CLASS) == 0)
addprop(getword(obase+O_PROPERTIES+p),0,
getword(obase+O_PROPERTIES+p+2));
}
/* process statements until end of file */
while ((tkn = token()) == T_OPEN) {
frequire(T_IDENTIFIER);
if (match("noun"))
do_noun();
else if (match("adjective"))
do_adjective();
else if (match("property"))
do_property(0);
else if (match("class-property"))
do_property(P_CLASS);
else if (match("method"))
do_method();
else
error("Unknown object definition statement type");
}
require(tkn,T_CLOSE);
/* copy the object to data memory */
osize = O_SIZE/2 + nprops*2;
obase = dalloc(osize*2);
for (i = p = 0; i < osize; i++, p += 2)
putword(obase+p,objbuf[i]);
otable[obj] = obase;
curobj = NIL;
/* return the object number */
return (obj);
}
/* do_noun - handle the <NOUN ... > statement */
do_noun()
{
int tkn,new;
while ((tkn = token()) == T_IDENTIFIER) {
new = dalloc(L_SIZE);
putword(new+L_DATA,add_word(t_token,WT_NOUN));
putword(new+L_NEXT,objbuf[O_NOUNS/2]);
objbuf[O_NOUNS/2] = new;
}
require(tkn,T_CLOSE);
}
/* do_adjective - handle the <ADJECTIVE ... > statement */
do_adjective()
{
int tkn,new;
while ((tkn = token()) == T_IDENTIFIER) {
new = dalloc(L_SIZE);
putword(new+L_DATA,add_word(t_token,WT_ADJECTIVE));
putword(new+L_NEXT,objbuf[O_ADJECTIVES/2]);
objbuf[O_ADJECTIVES/2] = new;
}
require(tkn,T_CLOSE);
}
/* do_property - handle the <PROPERTY ... > statement */
do_property(flags)
int flags;
{
int tkn,name,value;
while ((tkn = token()) == T_IDENTIFIER || tkn == T_NUMBER) {
name = (tkn == T_IDENTIFIER ? penter(t_token) : t_value);
value = getvalue();
setprop(name,flags,value);
}
require(tkn,T_CLOSE);
}
/* do_method - handle <METHOD (FUN ...) ... > statement */
do_method()
{
int tkn,name,tcnt;
/* get the property name */
frequire(T_OPEN);
frequire(T_IDENTIFIER);
printf("[ method: %s ]\n",t_token);
/* create a new property */
name = penter(t_token);
/* allocate a new (anonymous) action */
if (acnt < AMAX)
++acnt;
else
error("too many actions");
/* store the action as the value of the property */
setprop(name,P_CLASS,acnt);
/* initialize the action */
curact = atable[acnt] = dalloc(A_SIZE);
putword(curact+A_VERBS,NIL);
putword(curact+A_PREPOSITIONS,NIL);
arguments = temporaries = NULL;
tcnt = 0;
/* enter the "self" argument */
addargument(&arguments,"self");
addargument(&arguments,"(dummy)");
/* get the argument list */
while ((tkn = token()) != T_CLOSE) {
require(tkn,T_IDENTIFIER);
if (match("&aux"))
break;
addargument(&arguments,t_token);
}
/* check for temporary variable definitions */
if (tkn == T_IDENTIFIER)
while ((tkn = token()) != T_CLOSE) {
require(tkn,T_IDENTIFIER);
addargument(&temporaries,t_token);
tcnt++;
}
/* store the code address */
putword(curact+A_CODE,cptr);
/* allocate space for temporaries */
if (temporaries) {
putcbyte(OP_TSPACE);
putcbyte(tcnt);
}
/* compile the code */
do_code(NULL);
/* free the argument and temporary variable symbol tables */
freelist(arguments);
freelist(temporaries);
arguments = temporaries = NULL;
}
/* setprop - set the value of a property */
setprop(prop,flags,value)
int prop,flags,value;
{
int i;
/* look for the property */
for (i = 0; i < nprops; i++)
if ((objbuf[O_PROPERTIES/2 + i*2] & ~P_CLASS) == prop) {
objbuf[O_PROPERTIES/2 + i*2 + 1] = value;
return;
}
addprop(prop,flags,value);
}
/* addprop - add a property to the current object's property list */
addprop(prop,flags,value)
int prop,flags,value;
{
if (nprops >= OPMAX) {
printf("too many properties for this object\n");
return;
}
objbuf[O_PROPERTIES/2 + nprops*2] = prop|flags;
objbuf[O_PROPERTIES/2 + nprops*2 + 1] = value;
objbuf[O_NPROPERTIES/2] = ++nprops;
}
/* do_code - compile code for an expression */
int do_code(type)
char *type;
{
int adr,tkn;
if (type) printf("[ compiling %s code ]\n",type);
adr = putcbyte(OP_PUSH);
while ((tkn = token()) != T_CLOSE) {
stoken(tkn);
do_expr();
}
putcbyte(OP_RETURN);
return (adr);
}
/* do_action - handle <ACTION ... > statement */
do_action()
{
int tkn,act;
/* get the action name */
frequire(T_IDENTIFIER);
printf("[ action: %s ]\n",t_token);
/* create a new action */
act = aenter(t_token);
curact = atable[act] = dalloc(A_SIZE);
putword(curact+A_VERBS,NIL);
putword(curact+A_PREPOSITIONS,NIL);
putbyte(curact+A_FLAG,def_flag);
putbyte(curact+A_MASK,def_mask);
putword(curact+A_CODE,NIL);
/* process statements until end of file */
while ((tkn = token()) == T_OPEN) {
frequire(T_IDENTIFIER);
if (match("actor"))
do_flag(A_ACTOR);
else if (match("verb"))
do_verb();
else if (match("direct-object"))
do_flag(A_DOBJECT);
else if (match("preposition"))
do_preposition();
else if (match("indirect-object"))
do_flag(A_IOBJECT);
else if (match("code"))
putword(curact+A_CODE,do_code(NULL));
else
error("Unknown action definition statement type");
}
require(tkn,T_CLOSE);
}
/* do_flag - handle ACTOR, DIRECT-OBJECT, and INDIRECT-OBJECT statements */
do_flag(flag)
int flag;
{
int tkn;
if ((tkn = token()) == T_IDENTIFIER) {
if (match("required")) {
putbyte(curact+A_FLAG,getbyte(curact+A_FLAG) | flag);
putbyte(curact+A_MASK,getbyte(curact+A_MASK) & ~flag);
}
else if (match("forbidden")) {
putbyte(curact+A_FLAG,getbyte(curact+A_FLAG) & ~flag);
putbyte(curact+A_MASK,getbyte(curact+A_MASK) & ~flag);
}
else if (match("optional"))
putbyte(curact+A_MASK,getbyte(curact+A_MASK) | flag);
else
error("Expecting: REQUIRED, FORBIDDEN or OPTIONAL");
tkn = token();
}
else {
putbyte(curact+A_FLAG,getbyte(curact+A_FLAG) | flag);
putbyte(curact+A_MASK,getbyte(curact+A_MASK) & ~flag);
}
require(tkn,T_CLOSE);
}
/* do_verb - handle the <VERB ... > statement */
do_verb()
{
int tkn,new,lst;
while ((tkn = token()) == T_IDENTIFIER || tkn == T_OPEN) {
new = dalloc(L_SIZE);
putword(new+L_NEXT,getword(curact+A_VERBS));
putword(curact+A_VERBS,new);
lst = dalloc(L_SIZE);
putword(lst+L_NEXT,NIL);
putword(new+L_DATA,lst);
if (tkn == T_IDENTIFIER)
putword(lst+L_DATA,add_word(t_token,WT_VERB));
else {
if ((tkn = token()) == T_IDENTIFIER)
putword(lst+L_DATA,add_word(t_token,WT_VERB));
else
error("Expecting verb");
while ((tkn = token()) == T_IDENTIFIER) {
new = dalloc(L_SIZE);
putword(new+L_DATA,add_word(t_token,WT_UNKNOWN));
putword(new+L_NEXT,NIL);
putword(lst+L_NEXT,new);
lst = new;
}
require(tkn,T_CLOSE);
}
}
require(tkn,T_CLOSE);
}
/* do_preposition - handle the <PREPOSITION ... > statement */
do_preposition()
{
int tkn,new;
while ((tkn = token()) == T_IDENTIFIER) {
new = dalloc(L_SIZE);
putword(new+L_DATA,add_word(t_token,WT_PREPOSITION));
putword(new+L_NEXT,getword(curact+A_PREPOSITIONS));
putword(curact+A_PREPOSITIONS,new);
}
require(tkn,T_CLOSE);
}
/* do_function - handle <DEFINE (FUN ...) ... > statement */
do_function()
{
int tkn,act,tcnt;
/* get the function name */
frequire(T_IDENTIFIER);
printf("[ function: %s ]\n",t_token);
/* create a new action */
act = aenter(t_token);
/* initialize the action */
curact = atable[act] = dalloc(A_SIZE);
putword(curact+A_VERBS,NIL);
putword(curact+A_PREPOSITIONS,NIL);
arguments = temporaries = NULL;
tcnt = 0;
/* get the argument list */
while ((tkn = token()) != T_CLOSE) {
require(tkn,T_IDENTIFIER);
if (match("&aux"))
break;
addargument(&arguments,t_token);
}
/* check for temporary variable definitions */
if (tkn == T_IDENTIFIER)
while ((tkn = token()) != T_CLOSE) {
require(tkn,T_IDENTIFIER);
addargument(&temporaries,t_token);
tcnt++;
}
/* store the code address */
putword(curact+A_CODE,cptr);
/* allocate space for temporaries */
if (temporaries) {
putcbyte(OP_TSPACE);
putcbyte(tcnt);
}
/* compile the code */
do_code(NULL);
/* free the argument and temporary variable symbol tables */
freelist(arguments);
freelist(temporaries);
arguments = temporaries = NULL;
}
/* addargument - add a formal argument */
addargument(list,name)
ARGUMENT **list; char *name;
{
ARGUMENT *arg;
if ((arg = (ARGUMENT *)malloc(sizeof(ARGUMENT))) == NULL)
advfatal("out of memory");
arg->arg_name = save(name);
arg->arg_next = *list;
*list = arg;
}
/* freelist - free a list of arguments or temporaries */
freelist(arg)
ARGUMENT *arg;
{
ARGUMENT *nxt;
while (arg) {
nxt = arg->arg_next;
free(arg->arg_name);
free(arg);
arg = nxt;
}
}
/* findarg - find an argument offset */
int findarg(name)
char *name;
{
ARGUMENT *arg;
int n;
for (n = 0, arg = arguments; arg; n++, arg = arg->arg_next)
if (strcmp(name,arg->arg_name) == 0)
return (n);
return (-1);
}
/* findtmp - find a temporary variable offset */
int findtmp(name)
char *name;
{
ARGUMENT *tmp;
int n;
for (n = 0, tmp = temporaries; tmp; n++, tmp = tmp->arg_next)
if (strcmp(name,tmp->arg_name) == 0)
return (n);
return (-1);
}