1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 /* 24 * Defines TADS vocabulary (player command parser) functionality 25 */ 26 27 #ifndef GLK_TADS_TADS2_VOCABULARY 28 #define GLK_TADS_TADS2_VOCABULARY 29 30 #include "common/util.h" 31 #include "glk/tads/tads2/lib.h" 32 #include "glk/tads/tads2/object.h" 33 #include "glk/tads/tads2/property.h" 34 #include "glk/tads/tads2/run.h" 35 36 namespace Glk { 37 namespace TADS { 38 namespace TADS2 { 39 40 /* 41 * Cover macro for parser errors. Any parser error should be covered 42 * with this macro for documentation and search purposes. (The macro 43 * doesn't do anything - this is just something to search for when we're 44 * trying to enumerate parser error codes.) 45 */ 46 #define VOCERR(errcode) errcode 47 48 /* maximum number of objects matching an ambiguous word */ 49 #define VOCMAXAMBIG 200 50 51 /* size of input buffer */ 52 #define VOCBUFSIZ 128 53 54 /* 55 * Vocabulary relation structure - this structure relates a vocabulary 56 * word to an object and part of speech. A list of these structures is 57 * attached to each vocabulary word structure to provide the word's 58 * meanings. 59 */ 60 struct vocwdef { 61 uint vocwnxt; /* index of next vocwdef attached to the same word */ 62 objnum vocwobj; /* object associated with the word */ 63 uchar vocwtyp; /* property associated with the word (part of speech) */ 64 uchar vocwflg; /* flags for the word */ 65 #define VOCFCLASS 1 /* word is for a class object */ 66 #define VOCFINH 2 /* word is inherited from a superclass */ 67 #define VOCFNEW 4 /* word was added at run-time */ 68 #define VOCFDEL 8 /* word has been deleted */ 69 }; 70 71 /* vocabulary word structure */ 72 struct vocdef { 73 vocdef *vocnxt; /* next word at same hash value */ 74 uchar voclen; /* length of the word */ 75 uchar vocln2; /* length of second word (0 if no second word) */ 76 uint vocwlst; /* head of list of vocwdef's attached to the word */ 77 uchar voctxt[1]; /* text of the word */ 78 }; 79 80 /* vocabulary inheritance cell */ 81 struct vocidef { 82 uchar vocinsc; /* # of superclasses (gives size of record) */ 83 union { 84 struct { 85 uchar vociusflg; /* flags for entry */ 86 #define VOCIFCLASS 1 /* entry refers to a class object (loc records only) */ 87 #define VOCIFVOC 2 /* entry has vocabulary words defined */ 88 #define VOCIFXLAT 4 /* superclasses must be translated from portable fmt */ 89 #define VOCIFLOCNIL 8 /* location is explicitly set to nil */ 90 #define VOCIFNEW 16 /* object was allocated at run-time with "new" */ 91 objnum vociusloc; /* location of the object */ 92 objnum vociusilc; /* inherited location */ 93 objnum vociussc[1]; /* array of superclasses */ 94 } vocius; 95 vocidef *vociunxt; 96 } vociu; 97 #define vociflg vociu.vocius.vociusflg 98 #define vociloc vociu.vocius.vociusloc 99 #define vociilc vociu.vocius.vociusilc 100 #define vocisc vociu.vocius.vociussc 101 #define vocinxt vociu.vociunxt 102 }; 103 104 /* size of a page in a vocabulary pool */ 105 #define VOCPGSIZ 8192 106 107 /* number of bytes in an inheritance cell page */ 108 #define VOCISIZ 8192 109 110 /* maximum number of inheritance pages */ 111 #define VOCIPGMAX 32 112 113 /* maximum number of inheritance pages (256 objects per page) */ 114 #define VOCINHMAX 128 115 116 /* size of vocabulary hash table */ 117 #define VOCHASHSIZ 256 118 119 /* size of a template structure */ 120 #define VOCTPLSIZ 10 121 122 /* new-style template structure */ 123 #define VOCTPL2SIZ 16 124 125 126 /* 127 * vocwdef's are fixed in size. They're allocated in a set of arrays 128 * (the voccxwp member of the voc context has the list of arrays). Each 129 * array is of a fixed number of vocwdef entries; a maximum number of 130 * vocwdef arrays is possible. 131 */ 132 #define VOCWPGSIZ 2000 /* number of vocwdef's per array */ 133 #define VOCWPGMAX 16 /* maximum number of vocwdef arrays */ 134 135 /* 136 * To find a vocwdef entry given its index, divide the index by the 137 * number of entries per array to find the array number, and use the 138 * remainder to find the index within that array. 139 */ 140 /*#define VOCW_IN_CACHE*/ 141 #ifdef VOCW_IN_CACHE 142 vocwdef *vocwget(struct voccxdef *ctx, uint idx); 143 #else 144 #define vocwget(ctx, idx) \ 145 ((idx) == VOCCXW_NONE ? (vocwdef *)0 : \ 146 ((ctx)->voccxwp[(idx)/VOCWPGSIZ] + ((idx) % VOCWPGSIZ))) 147 #endif 148 149 /* 150 * Special values for vocdtim - these values indicate that the daemon 151 * does not have a normal turn-based expiration time. 152 */ 153 #define VOCDTIM_EACH_TURN 0xffff /* the daemon fires every turn */ 154 155 /* daemon/fuse/alarm slot */ 156 struct vocddef { 157 objnum vocdfn; /* object number of function to be invoked */ 158 runsdef vocdarg; /* argument for daemon/fuse function */ 159 prpnum vocdprp; /* property number (used only for alarms) */ 160 uint vocdtim; /* time for fuses/alarms (0xffff -> each-turn alarm) */ 161 }; 162 163 /* vocabulary object list entry */ 164 struct vocoldef { 165 objnum vocolobj; /* object matching the word */ 166 const char *vocolfst; /* first word in cmd[] that identified object */ 167 const char *vocollst; /* last word in cmd[] that identified object */ 168 char *vocolhlst; /* hypothetical last word, if we trimmed a prep */ 169 int vocolflg; /* special flags (ALL, etc) */ 170 }; 171 172 /* vocabulary context */ 173 struct voccxdef { 174 errcxdef *voccxerr; /* error handling context */ 175 tiocxdef *voccxtio; /* text i/o context */ 176 runcxdef *voccxrun; /* execution context */ 177 mcmcxdef *voccxmem; /* memory manager context */ 178 objucxdef *voccxundo; /* undo context */ 179 uchar *voccxpool; /* next free byte in vocdef pool */ 180 vocdef *voccxfre; /* head of vocdef free list */ 181 char *voccxcpp; /* pointer to compound word area */ 182 int voccxcpl; /* length of compound word area */ 183 char *voccxspp; /* pointer to special word area */ 184 int voccxspl; /* length of special word area */ 185 uint voccxrem; /* number of bytes remaining in vocdef pool */ 186 vocidef **voccxinh[VOCINHMAX]; /* vocidef page table: 256 per page */ 187 uchar *voccxip[VOCIPGMAX]; /* inheritance cell pool */ 188 vocidef *voccxifr; /* head of inheritance cell free list */ 189 uint voccxiplst; /* last inheritance cell page allocated */ 190 uint voccxilst; /* next unused byte in last inheritance page */ 191 int voccxredo; /* flag: redo command in buffer */ 192 193 /* 194 * redo buffer - if voccxredo is set, and this buffer is not empty, 195 * we'll redo the command in this buffer rather than the one in our 196 * internal stack buffer 197 */ 198 char voccxredobuf[VOCBUFSIZ]; 199 200 /* 201 * "again" buffer - when we save the last command for repeating via 202 * the "again" command, we'll save the direct and indirect object 203 * words here, so that they can be recovered if "again" is used 204 */ 205 char voccxagainbuf[VOCBUFSIZ]; 206 207 vocdef *voccxhsh[VOCHASHSIZ]; /* hash table */ 208 209 #ifdef VOCW_IN_CACHE 210 mcmon voccxwp[VOCWPGMAX]; /* list of pages of vocab records */ 211 mcmon voccxwplck; /* locked page of vocab records */ 212 vocwdef *voccxwpgptr; /* pointer to currently locked page */ 213 #else 214 vocwdef *voccxwp[VOCWPGMAX]; /* vocabulary word pool */ 215 #endif 216 217 uint voccxwalocnt; /* number of vocwdef's used so far */ 218 uint voccxwfre; /* index of first vocwdef in free list */ 219 #define VOCCXW_NONE ((uint)(-1)) /* index value indicating end of list */ 220 221 vocddef *voccxdmn; /* array of daemon slots */ 222 uint voccxdmc; /* number of slots in daemon array */ 223 vocddef *voccxfus; /* array of fuse slots */ 224 uint voccxfuc; /* number of slots in fuse array */ 225 vocddef *voccxalm; /* array of alarm slots */ 226 uint voccxalc; /* number of slots in alarm array */ 227 char voccxtim[26]; /* game's timestamp (asctime value) */ 228 229 objnum voccxvtk; /* object number of "take" deepverb */ 230 objnum voccxme; /* object number of "Me" actor */ 231 objnum voccxme_init; /* initial setting of "Me" */ 232 objnum voccxstr; /* object number of "strObj" */ 233 objnum voccxnum; /* object number of "numObj" */ 234 objnum voccxit; /* last "it" value */ 235 objnum voccxhim; /* last "him" value */ 236 objnum voccxher; /* last "her" value */ 237 objnum voccxthc; /* count of items in "them" list */ 238 objnum voccxthm[VOCMAXAMBIG]; /* list of items in "them" */ 239 objnum voccxprd; /* "pardon" function object number */ 240 objnum voccxpre; /* "preparse" function object number */ 241 objnum voccxppc; /* "preparseCmd" function object number */ 242 objnum voccxpre2; /* "preparseExt" function object number */ 243 objnum voccxvag; /* "again" verb object */ 244 objnum voccxini; /* "init" function */ 245 objnum voccxper; /* "parseError" function object number */ 246 objnum voccxprom; /* "cmdPrompt" function object number */ 247 objnum voccxpostprom; /* "cmdPostPrompt" function object number */ 248 objnum voccxpdis; /* parseDisambig function */ 249 objnum voccxper2; /* parseError2 function */ 250 objnum voccxperp; /* parseErrorParam function */ 251 objnum voccxpdef; /* parseDefault function */ 252 objnum voccxpdef2; /* parseDefaultExt function */ 253 objnum voccxpask; /* parseAskobj function */ 254 objnum voccxpask2; /* parseAskobjActor function */ 255 objnum voccxpask3; /* parseAskobjIndirect function */ 256 objnum voccxinitrestore; /* "initRestore" function object number */ 257 objnum voccxpuv; /* parseUnknownVerb function object number */ 258 objnum voccxpnp; /* parseNounPhrase function object number */ 259 objnum voccxpostact; /* postAction function object number */ 260 objnum voccxprecmd; /* preCommand function object number */ 261 objnum voccxendcmd; /* endCommand function object number */ 262 263 /* current command word list values */ 264 vocoldef *voccxdobj; /* current direct object word list */ 265 vocoldef *voccxiobj; /* current indirect object word list */ 266 267 /* current command objects */ 268 objnum voccxactor; /* current actor */ 269 objnum voccxverb; /* current command deepverb */ 270 objnum voccxprep; /* current command preposition */ 271 272 /* previous command values - used by "again" */ 273 objnum voccxlsa; /* previous actor */ 274 objnum voccxlsv; /* previous verb */ 275 vocoldef voccxlsd; /* previous direct object */ 276 vocoldef voccxlsi; /* previous indirect object */ 277 objnum voccxlsp; /* preposition */ 278 int voccxlssty; /* style (new/old) of last template */ 279 uchar voccxlst[VOCTPL2SIZ]; /* template */ 280 281 objnum voccxpreinit; /* preinit function */ 282 283 /* special flags */ 284 uchar voccxflg; 285 #define VOCCXFCLEAR 1 /* ignore remainder of command line (restore) */ 286 #define VOCCXFVWARN 2 /* generate redundant verb warnings */ 287 #define VOCCXFDBG 4 /* debug mode: show parsing information */ 288 #define VOCCXAGAINDEL 8 /* "again" lost due to object deletion */ 289 290 /* number of remaining unresolved unknown words in the command */ 291 int voccxunknown; 292 293 /* total number of unresolved words in the last command */ 294 int voccxlastunk; 295 296 /* parser stack area */ 297 uchar *voc_stk_ptr; 298 uchar *voc_stk_cur; 299 uchar *voc_stk_end; 300 }; 301 302 /* allocate and push a list, returning a pointer to the list's memory */ 303 uchar *voc_push_list_siz(voccxdef *ctx, uint lstsiz); 304 305 /* push a list of objects from a vocoldef array */ 306 void voc_push_vocoldef_list(voccxdef *ctx, vocoldef *objlist, int cnt); 307 308 /* push a list of objects from an objnum array */ 309 void voc_push_objlist(voccxdef *ctx, objnum objlist[], int cnt); 310 311 /* change the player character ("Me") object */ 312 void voc_set_me(voccxdef *ctx, objnum new_me); 313 314 /* add a vocabulary word */ 315 void vocadd(voccxdef *ctx, prpnum p, objnum objn, 316 int classflag, char *wrdval); 317 318 /* internal addword - must already be split into two words and lengths */ 319 void vocadd2(voccxdef *ctx, prpnum p, objnum objn, int classflg, 320 uchar *wrd1, int len1, uchar *wrd2, int len2); 321 322 /* delete vocabulary for a given object */ 323 void vocdel(voccxdef *ctx, objnum objn); 324 325 /* lower-level vocabulary deletion routine */ 326 void vocdel1(voccxdef *ctx, objnum objn, char *wrd, prpnum prp, 327 int really_delete, int revert, int keep_undo); 328 329 /* delete all inherited vocabulary */ 330 void vocdelinh(voccxdef *ctx); 331 332 /* allocate space for an inheritance record if needed */ 333 void vocialo(voccxdef *ctx, objnum obj); 334 335 /* add an inheritance/location record */ 336 void vociadd(voccxdef *ctx, objnum obj, objnum loc, 337 int numsc, objnum *sc, int flags); 338 339 /* delete inheritance records for an object */ 340 void vocidel(voccxdef *ctx, objnum chi); 341 342 /* renumber an object's inheritance records - used for 'modify' */ 343 void vociren(voccxdef *ctx, objnum oldnum, objnum newnum); 344 345 /* caller-provided context structure for vocffw/vocfnw searches */ 346 struct vocseadef { 347 vocdef *v; 348 vocwdef *vw; 349 const uchar *wrd1; 350 int len1; 351 const uchar *wrd2; 352 int len2; 353 }; 354 355 /* find first word matching a given word */ 356 vocwdef *vocffw(voccxdef *ctx, const char *wrd, int len, const char *wrd2, int len2, 357 int p, vocseadef *search_ctx); 358 359 /* find next word */ 360 vocwdef *vocfnw(voccxdef *voccx, vocseadef *search_ctx); 361 362 /* read a line of input text */ 363 int vocread(voccxdef *ctx, objnum actor, objnum verb, 364 char *buf, int bufl, int type); 365 #define VOCREAD_OK 0 366 #define VOCREAD_REDO 1 367 368 /* compute size of a vocoldef list */ 369 int voclistlen(vocoldef *lst); 370 371 /* tokenize an input buffer */ 372 int voctok(voccxdef *ctx, char *cmd, char *outbuf, 373 char **wrd, int lower, int cvt_ones, int show_errors); 374 375 /* get types for a word list */ 376 int vocgtyp(voccxdef *ctx, char **cmd, int *types, char *orgbuf); 377 378 /* execute a player command */ 379 int voccmd(voccxdef *ctx, char *cmd, uint cmdlen); 380 381 /* disambiguator */ 382 int vocdisambig(voccxdef *ctx, vocoldef *outlist, vocoldef *inlist, 383 prpnum defprop, prpnum accprop, prpnum verprop, 384 char *cmd[], objnum otherobj, objnum cmdActor, 385 objnum cmdVerb, objnum cmdPrep, char *cmdbuf, 386 int silent); 387 388 /* display a multiple-object prefix */ 389 void voc_multi_prefix(voccxdef *ctx, objnum objn, 390 int show_prefix, int multi_flags, 391 int cur_index, int count); 392 393 /* low-level executor */ 394 int execmd(voccxdef *ctx, objnum actor, objnum prep, 395 char *vverb, char *vprep, vocoldef *dolist, vocoldef *iolist, 396 char **cmd, int *typelist, 397 char *cmdbuf, int wrdcnt, uchar **preparse_list, int *next_start); 398 399 /* recursive command execution */ 400 int execmd_recurs(voccxdef *ctx, objnum actor, objnum verb, 401 objnum dobj, objnum prep, objnum iobj, 402 int validate_dobj, int validate_iobj); 403 404 /* try running preparseCmd user function */ 405 int try_preparse_cmd(voccxdef *ctx, char **cmd, int wrdcnt, 406 uchar **preparse_list); 407 408 /* 409 * Handle an unknown verb or sentence structure. We'll call this when 410 * we encounter a sentence where we don't know the verb word, or we 411 * don't know the combination of verb and verb preposition, or we don't 412 * recognize the sentence structure (for example, an indirect object is 413 * present, but we don't have a template defined using an indirect 414 * object for the verb). 415 * 416 * 'wrdcnt' is the number of words in the cmd[] array. If wrdcnt is 417 * zero, we'll automatically count the array entries, with the end of 418 * the array indicated by a null pointer entry. 419 * 420 * If do_fuses is true, we'll execute the fuses and daemons if the 421 * function exists and doesn't throw an ABORT error, or any other 422 * run-time error other than EXIT. 423 * 424 * This function calls the game-defined function parseUnknownVerb, if it 425 * exists. If the function doesn't exist, we'll simply display the 426 * given error message, using the normal parseError mechanism. The 427 * function should use "abort" or "exit" if it wants to cancel further 428 * processing of the command. 429 * 430 * We'll return true if the function exists and executes successfully, 431 * in which case normal processing should continue with any remaining 432 * command on the command line. We'll return false if the function 433 * doesn't exist or throws an error other than EXIT, in which case the 434 * remainder of the command should be aborted. 435 */ 436 int try_unknown_verb(voccxdef *ctx, objnum actor, 437 char **cmd, int *typelist, int wrdcnt, int *next_start, 438 int do_fuses, int err, const char *msg, ...); 439 440 /* find a template */ 441 int voctplfnd(voccxdef *ctx, objnum verb_in, objnum prep, 442 uchar *tplout, int *newstyle); 443 444 /* build a printable name for an object from the words in a command list */ 445 void voc_make_obj_name(voccxdef *ctx, char *namebuf, char *cmd[], 446 int firstwrd, int lastwrd); 447 void voc_make_obj_name_from_list(voccxdef *ctx, char *namebuf, 448 char *cmd[], const char *firstwrd, const char *lastwrd); 449 450 /* 451 * check noun - determines whether the next set of words is a valid noun 452 * phrase. No complaint is issued if not; this check is generally made 453 * to figure out what type of sentence we're dealing with. This is 454 * simple; we just call vocgobj() with the complaint flag turned off. 455 */ 456 /* int vocchknoun(voccxdef *ctx, char **cmd, int *typelist, int cur, 457 int *next, vocoldef *nounlist, int chkact); */ 458 #define vocchknoun(ctx, cmd, typelist, cur, next, nounlist, chkact) \ 459 vocgobj(ctx, cmd, typelist, cur, next, FALSE, nounlist, TRUE, chkact, 0) 460 #define vocchknoun2(ctx, cmd, typlst, cur, next, nounlist, chkact, nomatch) \ 461 vocgobj(ctx, cmd, typlst, cur, next, FALSE, nounlist, TRUE, chkact, nomatch) 462 463 /* 464 * get noun - reads an object list. We simply call vocgobj() with the 465 * complaint and multiple-noun flags turned on. 466 */ 467 /* int vocgetnoun(voccxdef *ctx, char **cmd, int *typelist, int cur, 468 int *next, vocoldef *nounlist); */ 469 #define vocgetnoun(ctx, cmd, typelist, cur, next, nounlist) \ 470 vocgobj(ctx, cmd, typelist, cur, next, TRUE, nounlist, TRUE, FALSE, 0) 471 472 /* get object */ 473 int vocgobj(voccxdef *ctx, char **cmd, int *typelist, int cur, 474 int *next, int complain, vocoldef *nounlist, 475 int multi, int chkact, int *nomatch); 476 477 /* tokenize a string - TADS program code interface */ 478 void voc_parse_tok(voccxdef *ctx); 479 480 /* get token types - TADS program code interface */ 481 void voc_parse_types(voccxdef *ctx); 482 483 /* get objects matching all of the given words - TADS program code interface */ 484 void voc_parse_dict_lookup(voccxdef *ctx); 485 486 /* parse a noun list - TADS program code interface */ 487 void voc_parse_np(voccxdef *ctx); 488 489 /* disambiguate a noun list - TADS program code interface */ 490 void voc_parse_disambig(voccxdef *ctx); 491 492 /* replace the current command - TADS program code interface */ 493 void voc_parse_replace_cmd(voccxdef *ctx); 494 495 /* check access to an object */ 496 int vocchkaccess(voccxdef *ctx, objnum obj, prpnum verprop, 497 int seqno, objnum actor, objnum verb); 498 499 /* check to see if an object is visible */ 500 int vocchkvis(voccxdef *ctx, objnum obj, objnum cmdActor); 501 502 /* display an appropriate message for an unreachable object */ 503 void vocnoreach(voccxdef *ctx, objnum *list1, int cnt, 504 objnum actor, objnum verb, objnum prep, prpnum defprop, 505 int show_multi_prefix, int multi_flags, 506 int multi_base_index, int multi_total_count); 507 508 /* set {numObj | strObj}.value, as appropriate */ 509 void vocsetobj(voccxdef *ctx, objnum obj, dattyp typ, const void *val, 510 vocoldef *inobj, vocoldef *outobj); 511 512 /* macros to read values out of templates */ 513 #define voctplpr(tpl) ((objnum)osrp2(((uchar *)tpl))) /* preposition */ 514 #define voctplvi(tpl) ((prpnum)osrp2(((uchar *)tpl) + 2)) /* verIoVerb */ 515 #define voctplio(tpl) ((prpnum)osrp2(((uchar *)tpl) + 4)) /* ioVerb */ 516 #define voctplvd(tpl) ((prpnum)osrp2(((uchar *)tpl) + 6)) /* verDoVerb */ 517 #define voctpldo(tpl) ((prpnum)osrp2(((uchar *)tpl) + 8)) /* doVerb */ 518 #define voctplflg(tpl) (*(((uchar *)tpl) + 10)) /* flags */ 519 520 /* flag values for the voctplflg */ 521 #define VOCTPLFLG_DOBJ_FIRST 0x01 /* disambiguate direct object first */ 522 523 524 /* word type flags */ 525 #define VOCT_ARTICLE 1 526 #define VOCT_ADJ 2 527 #define VOCT_NOUN 4 528 #define VOCT_PREP 8 529 #define VOCT_VERB 16 530 #define VOCT_SPEC 32 /* special words - "of", ",", ".", etc. */ 531 #define VOCT_PLURAL 64 532 #define VOCT_UNKNOWN 128 /* word is unknown */ 533 534 /* special type flags */ 535 #define VOCS_ALL 1 /* "all" */ 536 #define VOCS_EXCEPT 2 /* "except" */ 537 #define VOCS_IT 4 /* "it" */ 538 #define VOCS_THEM 8 /* "them" */ 539 #define VOCS_NUM 16 /* a number */ 540 #define VOCS_COUNT 32 /* a number being used as a count */ 541 #define VOCS_PLURAL 64 /* plural */ 542 #define VOCS_ANY 128 /* "any" */ 543 #define VOCS_HIM 256 /* "him" */ 544 #define VOCS_HER 512 /* "her" */ 545 #define VOCS_STR 1024 /* a quoted string */ 546 #define VOCS_UNKNOWN 2048 /* noun phrase contains an unknown word */ 547 #define VOCS_ENDADJ 4096 /* word matched adjective at end of phrase */ 548 #define VOCS_TRUNC 8192 /* truncated match - word is leading substring */ 549 #define VOCS_TRIMPREP 16384 /* trimmed prep phrase: assumed it was for verb */ 550 551 /* special internally-defined one-character word flags */ 552 #define VOCW_AND ',' 553 #define VOCW_THEN '.' 554 #define VOCW_OF 'O' 555 #define VOCW_ALL 'A' 556 #define VOCW_BOTH 'B' 557 #define VOCW_IT 'I' 558 #define VOCW_HIM 'M' 559 #define VOCW_ONE 'N' 560 #define VOCW_ONES 'P' 561 #define VOCW_HER 'R' 562 #define VOCW_THEM 'T' 563 #define VOCW_BUT 'X' 564 #define VOCW_ANY 'Y' 565 566 /* structure for special internal word table */ 567 struct vocspdef { 568 const char *vocspin; 569 char vocspout; 570 }; 571 572 /* check if a word is a special word - true if word is given special word */ 573 /* int vocspec(char *wordptr, int speccode); */ 574 #define vocspec(w, s) (*(w) == (s)) 575 576 /* 577 * Set a fuse/daemon/notifier. 578 */ 579 void vocsetfd(voccxdef *ctx, vocddef *what, objnum func, prpnum prop, 580 uint tm, runsdef *val, int err); 581 582 /* remove a fuse/daemon/notifier */ 583 void vocremfd(voccxdef *ctx, vocddef *what, objnum func, prpnum prop, 584 runsdef *val, int err); 585 586 /* count a turn (down all fuse/notifier timers) */ 587 void vocturn(voccxdef *ctx, int turncnt, int do_fuses); 588 589 /* initialize voc context */ 590 void vocini(voccxdef *vocctx, errcxdef *errctx, mcmcxdef *memctx, 591 runcxdef *runctx, objucxdef *undoctx, int fuses, 592 int daemons, int notifiers); 593 594 /* clean up the voc context - frees memory allocated by vocini() */ 595 void vocterm(voccxdef *vocctx); 596 597 /* allocate/free fuse/daemon/notifier array for voc ctx initialization */ 598 void vocinialo(voccxdef *ctx, vocddef **what, int cnt); 599 void voctermfree(vocddef *what); 600 601 /* get a vocidef given an object number */ 602 /* vocidef *vocinh(voccxdef *ctx, objnum obj); */ 603 #define vocinh(ctx, obj) ((ctx)->voccxinh[(obj) >> 8][(obj) & 255]) 604 605 /* revert all objects back to original state, using inheritance records */ 606 void vocrevert(voccxdef *ctx); 607 608 /* clear all fuses/daemons/notifiers (useful for restarting) */ 609 void vocdmnclr(voccxdef *ctx); 610 611 /* display a parser error message */ 612 void vocerr(voccxdef *ctx, int err, const char *f, ...); 613 614 /* 615 * display a parser informational error message - this will display the 616 * message whether or not we're suppressing messages due to unknown 617 * words, and should be used when providing information, such as objects 618 * we're assuming by default 619 */ 620 void vocerr_info(voccxdef *ctx, int err, const char *f, ...); 621 622 /* client undo callback - undoes a daemon/fuse/notifier */ 623 void vocdundo(void *ctx, uchar *data); 624 625 /* client undo size figuring callback - return size of client undo record */ 626 ushort OS_LOADDS vocdusz(void *ctx, uchar *data); 627 628 /* save undo for object creation */ 629 void vocdusave_newobj(voccxdef *ctx, objnum objn); 630 631 /* save undo for adding a word */ 632 void vocdusave_addwrd(voccxdef *ctx, objnum objn, prpnum typ, int flags, 633 char *wrd); 634 635 /* save undo for deleting a word */ 636 void vocdusave_delwrd(voccxdef *ctx, objnum objn, prpnum typ, int flags, 637 char *wrd); 638 639 /* save undo for object deletion */ 640 void vocdusave_delobj(voccxdef *ctx, objnum objn); 641 642 /* save undo for changing the "Me" object */ 643 void vocdusave_me(voccxdef *ctx, objnum old_me); 644 645 /* compute vocabulary word hash value */ 646 uint vochsh(const uchar *t, int len); 647 648 /* TADS versions of isalpha, isspace, isdigit, etc */ 649 #define vocisupper(c) ((uchar)(c) <= 127 && Common::isUpper((uchar)(c))) 650 #define vocislower(c) ((uchar)(c) <= 127 && Common::isLower((uchar)(c))) 651 #define vocisalpha(c) ((uchar)(c) > 127 || Common::isAlpha((uchar)(c))) 652 #define vocisspace(c) ((uchar)(c) <= 127 && Common::isSpace((uchar)(c))) 653 #define vocisdigit(c) ((uchar)(c) <= 127 && Common::isDigit((uchar)(c))) 654 655 656 /* 657 * Undo types for voc subsystem 658 */ 659 #define VOC_UNDO_DAEMON 1 /* fuse/daemon status change */ 660 #define VOC_UNDO_NEWOBJ 2 /* object creation */ 661 #define VOC_UNDO_DELOBJ 3 /* object deletion */ 662 #define VOC_UNDO_ADDVOC 4 /* add vocabulary to an object */ 663 #define VOC_UNDO_DELVOC 5 /* delete vocabulary from an object */ 664 #define VOC_UNDO_SETME 6 /* set the "Me" object */ 665 666 667 /* 668 * Our own stack. We need to allocate some fairly large structures 669 * (for the disambiguation lists, mostly) in a stack-like fashion, and 670 * we don't want to consume vast quantities of the real stack, because 671 * some machines have relatively restrictive limitations on stack usage. 672 * To provide some elbow room, we'll use a stack-like structure of our 673 * own: we'll allocate out of this structure as needed, and whenever we 674 * leave a C stack frame, we'll also leave our own stack frame. 675 */ 676 677 /* re-initialize the stack, allocating space for it if needed */ 678 void voc_stk_ini(voccxdef *ctx, uint siz); 679 680 /* enter a stack frame, marking our current position */ 681 #define voc_enter(ctx, marker) (*(marker) = (ctx)->voc_stk_cur) 682 683 /* leave a stack frame, restoring the entry position */ 684 #define voc_leave(ctx, marker) ((ctx)->voc_stk_cur = marker) 685 686 /* return a value */ 687 #define VOC_RETVAL(ctx, marker, retval) \ 688 voc_leave(ctx, marker); return retval 689 690 /* allocate space from the stack */ 691 void *voc_stk_alo(voccxdef *ctx, uint siz); 692 693 /* allocation cover macros */ 694 #define VOC_STK_ARRAY(ctx, typ, var, cnt) \ 695 (var = (typ *)voc_stk_alo(ctx, (uint)((cnt) * sizeof(typ)))) 696 697 #define VOC_MAX_ARRAY(ctx, typ, var) \ 698 VOC_STK_ARRAY(ctx, typ, var, VOCMAXAMBIG) 699 700 /* 701 * Stack size for the vocab stack. We'll scale our stack needs based 702 * on the size of the vocoldef structure, since this is the most common 703 * item to be allocated on the vocab stack. We'll also scale based on 704 * the defined VOCMAXAMBIG parameter, since it is the number of elements 705 * usually allocated. The actual amount of space needed depends on how 706 * the functions in vocab.c and execmd.c work, so this parameter may 707 * need to be adjusted for changes to the player command parser. 708 */ 709 #define VOC_STACK_SIZE (16 * VOCMAXAMBIG * sizeof(vocoldef)) 710 711 /* 712 * Execute all fuses and daemons, then execute the endCommand user 713 * function. Returns zero on success, or ERR_ABORT if 'abort' was 714 * thrown during execution. This is a convenient cover single function 715 * to do all end-of-turn processing; this calls exefuse() and exedaem() 716 * as needed, trapping any 'abort' or 'exit' errors that occur. 717 * 718 * If 'do_fuses' is true, we'll run fuses and daemons. Otherwise, 719 */ 720 int exe_fuses_and_daemons(voccxdef *ctx, int err, int do_fuses, 721 objnum actor, objnum verb, 722 vocoldef *dobj_list, int do_cnt, 723 objnum prep, objnum iobj); 724 725 /* 726 * Execute any pending fuses. Return TRUE if any fuses were executed, 727 * FALSE otherwise. 728 */ 729 int exefuse(voccxdef *ctx, int do_run); 730 731 /* 732 * Execute daemons 733 */ 734 void exedaem(voccxdef *ctx); 735 736 /* 737 * Get the number and size of words defined for an object. The size 738 * returns the total byte count from all the words involved. Do not 739 * include deleted words in the count. 740 */ 741 void voc_count(voccxdef *ctx, objnum objn, prpnum prp, int *cnt, int *siz); 742 743 /* 744 * Iterate through all words for a particular object, calling a 745 * function with each vocwdef found. If objn == MCMONINV, we'll call 746 * the callback for every word. 747 */ 748 void voc_iterate(voccxdef *ctx, objnum objn, 749 void (*fn)(void *, vocdef *, vocwdef *), void *fnctx); 750 751 /* ------------------------------------------------------------------------ */ 752 /* 753 * disambiguation status codes - used for disambigDobj and disambigIobj 754 * methods in the deepverb 755 */ 756 757 /* continue with disambiguation process (using possibly updated list) */ 758 #define VOC_DISAMBIG_CONT 1 759 760 /* done - the list is fully resolved; return with (possibly updated) list */ 761 #define VOC_DISAMBIG_DONE 2 762 763 /* error - abort the command */ 764 #define VOC_DISAMBIG_ERROR 3 765 766 /* parse string returned in second element of list as interactive response */ 767 #define VOC_DISAMBIG_PARSE_RESP 4 768 769 /* already asked for an interactive response, but didn't read it yet */ 770 #define VOC_DISAMBIG_PROMPTED 5 771 772 773 /* ------------------------------------------------------------------------ */ 774 /* 775 * parseNounPhrase status codes 776 */ 777 778 /* parse error occurred */ 779 #define VOC_PNP_ERROR 1 780 781 /* use built-in default parser */ 782 #define VOC_PNP_DEFAULT 2 783 784 /* successful parse */ 785 #define VOC_PNP_SUCCESS 3 786 787 788 /* ------------------------------------------------------------------------ */ 789 /* 790 * parserResolveObjects usage codes 791 */ 792 #define VOC_PRO_RESOLVE_DOBJ 1 /* direct object */ 793 #define VOC_PRO_RESOLVE_IOBJ 2 /* indirect object */ 794 #define VOC_PRO_RESOLVE_ACTOR 3 /* actor */ 795 796 } // End of namespace TADS2 797 } // End of namespace TADS 798 } // End of namespace Glk 799 800 #endif 801