|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T a
Length: 14821 (0x39e5) Types: TextFile Names: »advcom.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/Advsys/advcom.c«
/* advcom.c - a compiler for adventure games */ /* Copyright (c) 1986, by David Michael Betz All rights reserved */ #include "advcom.h" #include "advavl.h" #include "advdbs.h" /* symbol tables */ SYMBOL *symbols; ARGUMENT *arguments; ARGUMENT *temporaries; /* adventure id information */ char aname[19]; int aversion; /* word table */ int wtable[WMAX+1],wcnt; /* object table */ int otable[OMAX+1],ocnt; /* action table */ int atable[AMAX+1],acnt; /* constant, variable and property symbol counts */ int ccnt,vcnt,pcnt; /* data and code space */ char *data,*code; int dptr,cptr; /* buffer for building an object */ int objbuf[OSIZE]; int nprops; /* global variables */ char ifile[FMAX]; /* input file name */ char ofile[FMAX]; /* output file name */ FILE *ifp; /* input file pointer */ unsigned int msgoff; /* message section offset */ TREE *words; /* word tree */ int curwrd; /* current word number */ int curobj; /* current object */ int curact; /* current action */ int def_flag; /* default action flag value */ int def_mask; /* default action mask value */ /* header information variables */ int h_init; /* initialization code */ int h_update; /* update code */ int h_before; /* before handler code */ int h_after; /* after handler code */ int h_error; /* error handling code */ /* external routines */ extern char *malloc(); extern char *calloc(); extern TREE *tnew(); /* external variables */ extern int errcount; /* error count */ extern int t_value; /* token value */ extern char t_token[]; /* token string */ extern char *t_names[]; /* token names */ extern long ad_foff; /* data file offset */ /* forward declarations */ SYMBOL *sfind(); SYMBOL *senter(); char *save(); /* main - the main routine */ main(argc,argv) int argc; char *argv[]; { int tkn,obj,i; /* initialize */ #ifdef MAC macinit(ifile,ofile); #else printf("ADVCOM v1.2 - Copyright (c) 1986, by David Betz\n"); #endif wcnt = ocnt = acnt = ccnt = vcnt = pcnt = msgoff = 0; symbols = NULL; arguments = temporaries = NULL; h_init = h_update = h_before = h_after = h_error = NIL; def_flag = def_mask = 0; aname[0] = 0; sinit(); /* setup the code and data space */ if ((data = calloc(1,DMAX)) == 0) fail("insufficient memory"); if ((code = calloc(1,CMAX)) == 0) fail("insufficient memory"); dptr = cptr = 1; /* make sure nothing has a zero offset */ /* get the file name */ #ifndef MAC if (argc < 2) fail("usage: advcom <file> [ <ofile> ]"); strcpy(ifile,argv[1]); strcat(ifile,".adv"); strcpy(ofile,(argc < 3 ? argv[1] : argv[2])); strcat(ofile,".dat"); #endif /* open the input file */ if ((ifp = fopen(ifile,"r")) == NULL) fail("can't open input file"); /* create and initialize the output file */ ad_create(ofile); for (i = 0; i++ < 512; ad_putc('\0')) ; /* create the word tree */ words = tnew(); /* enter builtin constants */ center("t",-1); center("nil",0); /* enter the builtin variables */ venter("$actor"); venter("$action"); venter("$dobject"); venter("$ndobjects"); venter("$iobject"); venter("$ocount"); /* enter the preposition "to" */ add_word("to",WT_PREPOSITION); /* process statements until end of file */ while ((tkn = token()) == T_OPEN) { frequire(T_IDENTIFIER); /* identification statement */ if (match("adventure")) do_adventure(); /* vocabulary statements */ else if (match("adjective")) do_word(WT_ADJECTIVE); else if (match("preposition")) do_word(WT_PREPOSITION); else if (match("conjunction")) do_word(WT_CONJUNCTION); else if (match("article")) do_word(WT_ARTICLE); else if (match("synonym")) do_synonym(); /* constant, variable, function and default definition statements */ else if (match("define")) do_define(); else if (match("variable")) do_variable(); else if (match("default")) do_default(); /* property definition statement */ else if (match("property")) do_defproperty(); /* handle the init, before and after code statements */ else if (match("init")) h_init = do_code(t_token); else if (match("update")) h_update = do_code(t_token); else if (match("before")) h_before = do_code(t_token); else if (match("after")) h_after = do_code(t_token); else if (match("error")) h_error = do_code(t_token); /* action definition statement */ else if (match("action")) do_action(); /* object definition statements */ else if (match("object")) do_object(t_token,NIL); /* object instance definition statements */ else if (obj = ofind(t_token)) do_object(t_token,obj); /* error, unknown statement */ else error("Unknown statement type"); } require(tkn,T_EOF); /* close the input file */ fclose(ifp); /* output the data structures */ output(); /* close the output file */ ad_close(); } /* getvalue - get a value */ int getvalue() { SYMBOL *sym; switch (token()) { case T_IDENTIFIER: if (sym = sfind(t_token)) return (sym->s_value); return (oenter(t_token)); case T_NUMBER: return (t_value); case T_STRING: return (t_value); default: error("Expecting identifier, number or string"); return (0); } } /* dalloc - allocate data space */ int dalloc(size) int size; { if ((dptr += size) > DMAX) fail("out of data space"); return (dptr - size); } /* add_word - add a word to the dictionary */ int add_word(str,type) char *str; int type; { if ((curwrd = tfind(words,str)) == NIL) { if (wcnt < WMAX) { curwrd = ++wcnt; wtable[curwrd] = type; tenter(words,str); } else { error("too many words"); curwrd = 0; } } else if (wtable[curwrd] == WT_UNKNOWN) wtable[curwrd] = type; else if (type != WT_UNKNOWN && type != wtable[curwrd]) error("Ambiguous word type"); return (curwrd); } /* add_synonym - add a synonym to a word */ int add_synonym(str,wrd) char *str; int wrd; { curwrd = wrd; return (tenter(words,str)); } /* getword - get a word from an object field */ int getword(off) int off; { return ((data[off] & 0xFF) | (data[off+1] << 8)); } /* putword - put a word into an object field */ putword(off,dat) int off,dat; { data[off] = dat; data[off+1] = dat >> 8; } /* getbyte - get a byte from an object field */ int getbyte(off) int off; { return (data[off]); } /* putbyte - put a byte into an object field */ putbyte(off,dat) int off,dat; { data[off] = dat; } /* output - output the binary data structures */ output() { int woff,wsize; /* word table offset and size */ int ooff,osize; /* object table offset and size */ int aoff,asize; /* action table offset and size */ int toff,tsize; /* word type table offset and size */ int voff,vsize; /* variable table offset and size */ int soff,ssize; /* save area offset and size */ int dsize; /* data size without dictionary */ int dbase,cbase,size,mblk,dblk,i; /* make sure the adventure id information is present */ if (aname[0] == 0) { xerror("no adventure identification information"); strcpy(aname,"ADVENTURE"); aversion = 0; } /* pad the remainder of this message block */ while (msgoff & 0x007F) { ad_putc('\0'); ad_putc('\0'); ad_putc('\0'); ad_putc('\0'); msgoff++; } /* save the size of the data area before the dictionary */ dsize = dptr; /* insert the vocabulary into the data array */ woutput(words->tr_root); /* compute table offsets */ woff = 0; wsize = tentries(words) * 2 + 2; toff = woff + wsize; tsize = wcnt; ooff = toff + tsize; osize = ocnt * 2 + 2; aoff = ooff + osize; asize = acnt * 2 + 2; voff = aoff + asize; vsize = vcnt * 2 + 2; dbase = voff + vsize; cbase = dbase + dptr; /* compute the resident structure size */ size = wsize+tsize+osize+asize+vsize+dptr+cptr; /* set the save area parameters */ soff = voff; ssize = vsize + dsize; /* compute the first block for message text */ mblk = 1; dblk = (int)(ad_foff >> 9); /* output the word table */ word_out(tentries(words)); wtoutput(words->tr_root); /* output the word type table */ for (i = 1; i <= wcnt; i++) byte_out(wtable[i]); /* output the object table */ word_out(ocnt); for (i = 1; i <= ocnt; i++) { if (otable[i] == NIL) undef_object(i); word_out(otable[i]); } /* output the action table */ word_out(acnt); for (i = 1; i <= acnt; i++) word_out(atable[i]); /* beginning of saveable data */ /* output the variable table */ word_out(vcnt); for (i = 1; i <= vcnt; i++) word_out(NIL); /* output the data space */ for (i = 0; i < dptr; ) byte_out(data[i++]); /* end of saveable data */ /* output the code space */ for (i = 0; i < cptr; ) byte_out(code[i++]); /* output the file header */ ad_seek(0L); word_out(size); /* resident structure size */ str_out("ADVSYS",6);/* magic information */ word_out(VERSION); /* data structure version number */ str_out(aname,18); /* adventure name */ word_out(aversion); /* adventure version number */ word_out(woff); /* word table offset */ word_out(toff); /* word type table offset */ word_out(ooff); /* object table offset */ word_out(aoff); /* action table offset */ word_out(voff); /* variable table offset */ word_out(dbase); /* base of data */ word_out(cbase); /* base of code */ word_out(dblk); /* first data block */ word_out(mblk); /* first message text block */ word_out(h_init); /* initialization code */ word_out(h_update); /* update code */ word_out(h_before); /* before handler code */ word_out(h_after); /* after handler code */ word_out(h_error); /* error handling code */ word_out(soff); /* save area offset */ word_out(ssize); /* save area size */ /* show statistics */ printf("[ words: %d ]\n",tentries(words)); printf("[ word types: %d ]\n",wcnt); printf("[ objects: %d ]\n",ocnt); printf("[ actions: %d ]\n",acnt); printf("[ variables: %d ]\n",vcnt); printf("[ data: %d ]\n",dsize); printf("[ code: %d ]\n",cptr); printf("[ dictionary: %d ]\n",dptr-dsize); printf("[ text: %ld ]\n",(long) msgoff * 4L); printf("[ save area: %d ]\n",ssize); printf("[ errors: %d ]\n",errcount); #ifdef MAC macpause(); #endif } /* woutput - output the word data */ woutput(node) TNODE *node; { int wnum,wrd; if (node) { woutput(LLINK(node)); wnum = WORD(node); wrd = WORD(node) = dalloc(strlen(KEY(node))+3); putword(wrd,wnum); strcpy(data+wrd+2,KEY(node)); if (wtable[wnum] == WT_UNKNOWN) printf("Type of word %s is unknown\n",KEY(node)); woutput(RLINK(node)); } } /* wtoutput - output the word table */ wtoutput(node) TNODE *node; { if (node) { wtoutput(LLINK(node)); word_out(WORD(node)); wtoutput(RLINK(node)); } } /* undef_object - complain about an undefined object */ undef_object(n) int n; { char msg[100]; SYMBOL *sym; for (sym = symbols; sym != NULL; sym = sym->s_next) if (sym->s_type == ST_OBJECT && n == sym->s_value) { sprintf(msg,"Object %s is undefined",sym->s_name); xerror(msg); break; } } /* str_out - output a string */ str_out(str,len) char *str; int len; { while (len--) byte_out(*str++); } /* word_out - output a word */ word_out(dat) int dat; { byte_out(dat); byte_out(dat >> 8); } /* byte_out - output a byte */ byte_out(dat) int dat; { ad_putc((~dat - 30) & 0xFF); } /* oenter - enter an object into the symbol table */ int oenter(name) char *name; { SYMBOL *sym; if (sym = sfind(name)) { if (sym->s_type != ST_OBJECT) error("Not an object"); return (sym->s_value); } if (ocnt < OMAX) { senter(name,ST_OBJECT,++ocnt); otable[ocnt] = NIL; } else error("too many objects"); return (ocnt); } /* ofind - find an object in the symbol table */ int ofind(name) char *name; { SYMBOL *sym; if (sym = sfind(name)) { if (sym->s_type != ST_OBJECT) return (NIL); return (sym->s_value); } return (NIL); } /* aenter - enter an action into the symbol table */ int aenter(name) char *name; { SYMBOL *sym; if (sym = sfind(name)) { if (sym->s_type != ST_ACTION) error("Not an action"); return (sym->s_value); } if (acnt < AMAX) { senter(name,ST_ACTION,++acnt); atable[acnt] = NIL; } else error("too many actions"); return (acnt); } /* venter - enter a variable into the symbol table */ int venter(name) char *name; { SYMBOL *sym; if (sym = sfind(name)) { if (sym->s_type != ST_VARIABLE) error("Not a variable"); return (sym->s_value); } senter(name,ST_VARIABLE,++vcnt); return (vcnt); } /* penter - enter a property into the symbol table */ int penter(name) char *name; { SYMBOL *sym; if (sym = sfind(name)) { if (sym->s_type != ST_PROPERTY) error("Not a property"); return (sym->s_value); } senter(name,ST_PROPERTY,++pcnt); return (pcnt); } /* center - enter a constant into the symbol table */ center(name,value) char *name; int value; { if (sfind(name)) { error("Already defined"); return; } senter(name,ST_CONSTANT,value); } /* sfind - find a symbol in the symbol table */ SYMBOL *sfind(name) char *name; { SYMBOL *sym; for (sym = symbols; sym != NULL; sym = sym->s_next) if (strcmp(name,sym->s_name) == 0) break; return (sym); } /* senter - enter a symbol into the symbol table */ SYMBOL *senter(name,type,value) char *name; int type,value; { SYMBOL *sym; if ((sym = (SYMBOL *)malloc(sizeof(SYMBOL))) == NULL) fail("out of memory"); sym->s_name = save(name); sym->s_type = type; sym->s_value = value; sym->s_next = symbols; symbols = sym; return (sym); } /* frequire - fetch a token and check it */ frequire(rtkn) int rtkn; { require(token(),rtkn); } /* require - check for a required token */ require(tkn,rtkn) int tkn,rtkn; { char msg[100]; if (tkn != rtkn) { sprintf(msg,"Expecting %s",t_names[rtkn]); error(msg); } } /* save - allocate memory for a string */ char *save(str) char *str; { char *new; if ((new = malloc(strlen(str)+1)) == NULL) fail("out of memory"); strcpy(new,str); return (new); } /* match - compare a string with the current token */ int match(str) char *str; { return (strcmp(str,t_token) == 0); } /* fail - print an error message and exit */ fail(msg) char *msg; { printf("%s\n",msg); #ifdef MAC macpause(); #endif exit(); }