diff options
Diffstat (limited to 'engines/glk/tads/tads2/post_compilation.cpp')
-rw-r--r-- | engines/glk/tads/tads2/post_compilation.cpp | 466 |
1 files changed, 466 insertions, 0 deletions
diff --git a/engines/glk/tads/tads2/post_compilation.cpp b/engines/glk/tads/tads2/post_compilation.cpp new file mode 100644 index 0000000000..ca29601190 --- /dev/null +++ b/engines/glk/tads/tads2/post_compilation.cpp @@ -0,0 +1,466 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program 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. + * + * This program 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "glk/tads/tads2/post_compilation.h" +#include "glk/tads/tads2/error.h" +#include "glk/tads/tads2/os.h" + +namespace Glk { +namespace TADS { +namespace TADS2 { + +/* + * Special character sequence description table for TADS language. + * Note that operators that start with common sequences must be grouped + * together, with the shorter sequences preceding the longer sequences. + * For example, ":" and ":=" must be adjacent, and ":" must precede + * ":=". Other than this restriction, the order of tokens doesn't + * matter. + */ +tokldef supsctab[] = +{ + { TOKTCOLON, ":" }, + { TOKTASSIGN, ":=" }, + { TOKTLT, "<" }, + { TOKTLE, "<=" }, + { TOKTSHL, "<<" }, + { TOKTSHLEQ, "<<="}, + { TOKTNE, "<>" }, + { TOKTGT, ">" }, + { TOKTSHR, ">>" }, + { TOKTSHREQ, ">>="}, + { TOKTGE, ">=" }, + { TOKTLPAR, "(" }, + { TOKTRPAR, ")" }, + { TOKTPLUS, "+" }, + { TOKTINC, "++" }, + { TOKTPLEQ, "+=" }, + { TOKTMINUS, "-" }, + { TOKTPOINTER, "->" }, + { TOKTDEC, "--" }, + { TOKTMINEQ, "-=" }, + { TOKTDIV, "/" }, + { TOKTMOD, "%" }, + { TOKTMODEQ, "%=" }, + { TOKTDIVEQ, "/=" }, + { TOKTTIMES, "*" }, + { TOKTTIMEQ, "*=" }, + { TOKTEQ, "=" }, + { TOKTEQEQ, "==" }, + { TOKTLBRACK, "[" }, + { TOKTRBRACK, "]" }, + { TOKTLBRACE, "{" }, + { TOKTRBRACE, "}" }, + { TOKTSEM, ";" }, + { TOKTCOMMA, "," }, + { TOKTDOT, "." }, + { TOKTELLIPSIS,"..." }, + { TOKTPOUND, "#" }, + { TOKTBAND, "&" }, + { TOKTBANDEQ, "&=" }, + { TOKTAND, "&&" }, + { TOKTBOR, "|" }, + { TOKTBOREQ, "|=" }, + { TOKTOR, "||" }, + { TOKTQUESTION,"?" }, + { TOKTDSTRING, "\"" }, + { TOKTSSTRING, "'" }, + { TOKTNOT, "!" }, + { TOKTNE, "!=" }, + { TOKTXOR, "^" }, + { TOKTXOREQ, "^=" }, + { TOKTTILDE, "~" }, + { 0, "" } +}; + +typedef struct supkwdef supkwdef; +struct supkwdef +{ + char *supkwnam; + int supkwtok; +}; + +static supkwdef supkwtab[] = +{ + { "not", TOKTNOT }, + { "if", TOKTIF }, + { "else", TOKTELSE }, + { "while", TOKTWHILE }, + { "break", TOKTBREAK }, + { "continue", TOKTCONTINUE }, + { "exit", TOKTEXIT }, + { "abort", TOKTABORT }, + { "and", TOKTAND }, + { "or", TOKTOR }, + { "function", TOKTFUNCTION }, + { "return", TOKTRETURN }, + { "local", TOKTLOCAL }, + { "object", TOKTOBJECT }, + { "nil", TOKTNIL }, + { "true", TOKTTRUE }, + { "pass", TOKTPASS }, + { "askdo", TOKTASKDO }, + { "askio", TOKTASKIO }, + { "ioSynonym", TOKTIOSYN }, + { "doSynonym", TOKTDOSYN }, + { "external", TOKTEXTERN }, + { "formatstring", TOKTFORMAT }, + { "compoundWord", TOKTCOMPOUND }, + { "specialWords", TOKTSPECIAL }, + { "class", TOKTCLASS }, + + /* new keywords for V2 */ + { "\002", 0 }, /* special flag for start of v2 section */ + { "for", TOKTFOR }, + { "\001", 0 }, /* special flag that "do" is next keyword */ + { "do", TOKTDO }, + { "switch", TOKTSWITCH }, + { "case", TOKTCASE }, + { "default", TOKTDEFAULT }, + { "goto", TOKTGOTO }, + { "replace", TOKTREPLACE }, + { "modify", TOKTMODIFY }, + + { "new", TOKTNEW }, + { "delete", TOKTDELETE }, + { (char *)0, 0 } +}; + +typedef struct supprdef supprdef; +struct supprdef +{ + char *supprnam; + prpnum supprval; +}; + +static supprdef supprtab[] = +{ + { "verb", PRP_VERB }, + { "noun", PRP_NOUN }, + { "adjective", PRP_ADJ }, + { "preposition", PRP_PREP }, + { "article", PRP_ARTICLE }, + { "plural", PRP_PLURAL }, + + /* add some more built-in properties */ + { "doAction", PRP_DOACTION }, + { "ioAction", PRP_IOACTION }, + { "sdesc", PRP_SDESC }, + { "thedesc", PRP_THEDESC }, + { "ioDefault", PRP_IODEFAULT }, + { "doDefault", PRP_DODEFAULT }, + { "location", PRP_LOCATION }, + { "value", PRP_VALUE }, + { "roomAction", PRP_ROOMACTION }, + { "actorAction", PRP_ACTORACTION }, + { "contents", PRP_CONTENTS }, + { "prepDefault", PRP_PREPDEFAULT }, + { "verActor", PRP_VERACTOR }, + { "validDo", PRP_VALIDDO }, + { "validIo", PRP_VALIDIO }, + { "lookAround", PRP_LOOKAROUND }, + { "roomCheck", PRP_ROOMCHECK }, + { "statusLine", PRP_STATUSLINE }, + { "locationOK", PRP_LOCOK }, + { "isVisible", PRP_ISVIS }, + { "cantReach", PRP_NOREACH }, + { "isHim", PRP_ISHIM }, + { "isHer", PRP_ISHER }, + { "action", PRP_ACTION }, + { "validDoList", PRP_VALDOLIST }, + { "validIoList", PRP_VALIOLIST }, + { "dobjGen", PRP_DOBJGEN }, + { "iobjGen", PRP_IOBJGEN }, + { "nilPrep", PRP_NILPREP }, + { "rejectMultiDobj", PRP_REJECTMDO }, + { "moveInto", PRP_MOVEINTO }, + { "construct", PRP_CONSTRUCT }, + { "destruct", PRP_DESTRUCT }, + { "validActor", PRP_VALIDACTOR }, + { "preferredActor", PRP_PREFACTOR }, + { "isEquivalent", PRP_ISEQUIV }, + { "adesc", PRP_ADESC }, + { "multisdesc", PRP_MULTISDESC }, + { "anyvalue", PRP_ANYVALUE }, + { "newNumbered", PRP_NEWNUMOBJ }, + { "parseUnknownDobj", PRP_PARSEUNKNOWNDOBJ }, + { "parseUnknownIobj", PRP_PARSEUNKNOWNIOBJ }, + { "dobjCheck", PRP_DOBJCHECK }, + { "iobjCheck", PRP_IOBJCHECK }, + { "verbAction", PRP_VERBACTION }, + { "disambigDobj", PRP_DISAMBIGDO }, + { "disambigIobj", PRP_DISAMBIGIO }, + { "prefixdesc", PRP_PREFIXDESC }, + { "isThem", PRP_ISTHEM }, + + /* still more - TADS/Graphic properties */ + { "gp_picture", PRP_GP_PIC }, + { "gp_name", PRP_GP_NAME }, + { "gp_defverb", PRP_GP_DEFVERB }, + { "gp_active", PRP_GP_ACTIVE }, + { "gp_hotlist", PRP_GP_HOTLIST }, + { "gp_icon", PRP_GP_ICON }, + { "gp_defverb2", PRP_GP_DEFVERB2 }, + { "gp_defprep", PRP_GP_DEFPREP }, + { "gp_hotid", PRP_GP_HOTID }, + { "gp_overlay", PRP_GP_OVERLAY }, + { "gp_hotx", PRP_GP_HOTX }, + { "gp_hoty", PRP_GP_HOTY }, + + /* flag end of list with null property name */ + { (char *)0, 0 } +}; + +/* define a built-in symbol */ +static void supaddsym(toktdef *tab, char *txt, int styp, int sval, + int casefold) +{ + char buf[40]; + + if (casefold) + { + strcpy(buf, txt); + os_strlwr(buf); + txt = buf; + } + (*tab->toktfadd)(tab, txt, (int)strlen(txt), styp, sval, tokhsh(txt)); +} + +/* add a built-in function to a symbol table */ +static void supaddbi(void (*bif[])(bifcxdef *, int), + toktdef *tab, char *txt, + void (*fn)(bifcxdef *, int), int num, int casefold) +{ + supaddsym(tab, txt, TOKSTBIFN, num, casefold); + bif[num] = fn; +} + +/* set up reserved words: built-in functions and properties, keywords, etc */ +void suprsrv(supcxdef *sup, void (*bif[])(bifcxdef *, int), + toktdef *tab, int max, int v1compat, char *new_do, + int casefold) +{ + supkwdef *kw; + supbidef *p; + int i; + supprdef *pr; + extern supbidef osfar_t supbitab[]; + int do_kw = FALSE; + char *kwname; + char buf[40]; + + /* add built-in functions */ + for (p = supbitab, i = 0 ; p->supbinam ; ++i, ++p) + { + if (i >= max) errsig(sup->supcxerr, ERR_MANYBIF); + supaddbi(bif, tab, p->supbinam, p->supbifn, i, casefold); + } + + /* add keywords */ + for (kw = supkwtab ; kw->supkwnam ; ++kw) + { + if (kw->supkwnam[0] == '\002') + { + if (v1compat) break; /* no v2 keywords - quit now */ + else continue; /* keep going, but skip this flag entry */ + } + + /* if this is the "do" keyword, change to user-supplied value */ + if (do_kw && new_do) + kwname = new_do; + else + kwname = kw->supkwnam; + + if (kw->supkwnam[0] == '\001') + { + do_kw = TRUE; + continue; + } + else + do_kw = FALSE; + + if (casefold) + { + strcpy(buf, kwname); + os_strlwr(buf); + kwname = buf; + } + (*tab->toktfadd)(tab, kwname, (int)strlen(kwname), + TOKSTKW, kw->supkwtok, tokhsh(kwname)); + } + + /* add pseudo-variables */ + supaddsym(tab, "self", TOKSTSELF, 0, casefold); + supaddsym(tab, "inherited", TOKSTINHERIT, 0, casefold); + supaddsym(tab, "argcount", TOKSTARGC, 0, casefold); + + /* add built-in properties */ + for (pr = supprtab ; pr->supprnam ; ++pr) + supaddsym(tab, pr->supprnam, TOKSTPROP, pr->supprval, casefold); +} + +/* get name of an object out of symbol table */ +void supgnam(char *buf, tokthdef *tab, objnum objn) +{ + toksdef sym; + + if (!tab) + { + strcpy(buf, "<NO SYMBOL TABLE>"); + return; + } + + if (tokthfind((toktdef *)tab, TOKSTOBJ, (uint)objn, &sym) + || tokthfind((toktdef *)tab, TOKSTFWDOBJ, (uint)objn, &sym)) + { + memcpy(buf, sym.toksnam, (size_t)sym.tokslen); + buf[sym.tokslen] = '\0'; + return; + } + + strcpy(buf, "<UNKNOWN>"); +} + +/* set up inherited vocabulary */ +void supivoc(supcxdef *ctx) +{ + vocidef ***vpg; + vocidef **v; + voccxdef *voc = ctx->supcxvoc; + int i; + int j; + objnum obj; + + /* delete all existing inherited words */ + vocdelinh(voc); + + for (vpg = voc->voccxinh, i = 0 ; i < VOCINHMAX ; ++vpg, ++i) + { + if (!*vpg) continue; /* no entries on this page */ + for (v = *vpg, obj = (i << 8), j = 0 ; j < 256 ; ++v, ++obj, ++j) + { + /* if it's not a class, inherit vocabulary for the object */ + if (!*v) continue; + if (!((*v)->vociflg & VOCIFCLASS)) + { + (*v)->vociilc = MCMONINV; /* no inherited location yet */ + supivoc1(ctx, ctx->supcxvoc, *v, obj, FALSE, 0); + } + } + } +} + +/* find a single required object, by name */ +static void supfind1(errcxdef *ec, toktdef *tab, char *nam, objnum *objp, + int required, int *errp, int warnlevel, int casefold) +{ + toksdef sym; + int namel = strlen(nam); + char buf[40]; + + if (casefold) + { + strcpy(buf, nam); + os_strlwr(buf); + nam = buf; + } + if ((*tab->toktfsea)(tab, nam, namel, tokhsh(nam), &sym)) + { + *objp = (objnum)sym.toksval; + } + else + { + if (required || warnlevel > 1) + errlog1(ec, (required ? ERR_RQOBJNF : ERR_WRNONF), + ERRTSTR, errstr(ec, nam, namel)); + *objp = MCMONINV; + if (required) *errp = 1; + } +} + +/* find required objects/functions */ +void supfind(errcxdef *ec, tokthdef *htab, voccxdef *voc, + objnum *preinit, int warnlevel, int cf) +{ + int err = 0; + toktdef *tab = &htab->tokthsc; + + /* look up the required and optional symbols */ + supfind1(ec, tab, "Me", &voc->voccxme, TRUE, &err, warnlevel, cf); + supfind1(ec, tab, "takeVerb", &voc->voccxvtk, TRUE, &err, warnlevel, cf); + supfind1(ec, tab, "strObj", &voc->voccxstr, TRUE, &err, warnlevel, cf); + supfind1(ec, tab, "numObj", &voc->voccxnum, TRUE, &err, warnlevel, cf); + supfind1(ec, tab, "pardon", &voc->voccxprd, TRUE, &err, warnlevel, cf); + supfind1(ec, tab, "againVerb", &voc->voccxvag, TRUE, &err, warnlevel, cf); + supfind1(ec, tab, "init", &voc->voccxini, TRUE, &err, warnlevel, cf); + supfind1(ec, tab, "preinit", preinit, FALSE, &err, warnlevel, cf); + supfind1(ec, tab, "preparse", &voc->voccxpre, FALSE, &err, warnlevel, cf); + supfind1(ec, tab, "preparseExt", &voc->voccxpre2, FALSE, &err, + warnlevel, cf); + supfind1(ec, tab, "parseError", &voc->voccxper, FALSE, &err, warnlevel, + cf); + supfind1(ec, tab, "commandPrompt", &voc->voccxprom, FALSE, &err, + warnlevel, cf); + supfind1(ec, tab, "parseDisambig", &voc->voccxpdis, FALSE, &err, + warnlevel, cf); + supfind1(ec, tab, "parseError2", &voc->voccxper2, FALSE, &err, warnlevel, + cf); + supfind1(ec, tab, "parseDefault", &voc->voccxpdef, FALSE, &err, warnlevel, + cf); + supfind1(ec, tab, "parseDefaultExt", &voc->voccxpdef2, FALSE, &err, + warnlevel, cf); + supfind1(ec, tab, "parseAskobj", &voc->voccxpask, FALSE, &err, warnlevel, + cf); + supfind1(ec, tab, "preparseCmd", &voc->voccxppc, FALSE, &err, warnlevel, + cf); + supfind1(ec, tab, "parseAskobjActor", &voc->voccxpask2, FALSE, + &err, warnlevel, cf); + supfind1(ec, tab, "parseAskobjIndirect", &voc->voccxpask3, FALSE, + &err, warnlevel, cf); + supfind1(ec, tab, "parseErrorParam", &voc->voccxperp, FALSE, &err, + warnlevel, cf); + supfind1(ec, tab, "commandAfterRead", &voc->voccxpostprom, FALSE, + &err, warnlevel, cf); + supfind1(ec, tab, "initRestore", &voc->voccxinitrestore, FALSE, + &err, warnlevel, cf); + supfind1(ec, tab, "parseUnknownVerb", &voc->voccxpuv, FALSE, + &err, warnlevel, cf); + supfind1(ec, tab, "parseNounPhrase", &voc->voccxpnp, FALSE, + &err, warnlevel, cf); + supfind1(ec, tab, "postAction", &voc->voccxpostact, FALSE, + &err, warnlevel, cf); + supfind1(ec, tab, "endCommand", &voc->voccxendcmd, FALSE, + &err, warnlevel, cf); + supfind1(ec, tab, "preCommand", &voc->voccxprecmd, FALSE, + &err, warnlevel, cf); + + /* "Me" is always the initial Me object */ + voc->voccxme_init = voc->voccxme; + + /* if we encountered any errors, signal the problem */ + if (err) + errsig(ec, ERR_UNDEF); +} + +} // End of namespace TADS2 +} // End of namespace TADS +} // End of namespace Glk |