aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/tads/tads2/post_compilation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/glk/tads/tads2/post_compilation.cpp')
-rw-r--r--engines/glk/tads/tads2/post_compilation.cpp466
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