| | 1 | #ifdef RCSID |
| | 2 | static char RCSid[] = |
| | 3 | "$Header: d:/cvsroot/tads/TADS2/SUPRUN.C,v 1.3 1999/07/11 00:46:30 MJRoberts Exp $"; |
| | 4 | #endif |
| | 5 | |
| | 6 | /* |
| | 7 | * Copyright (c) 1992, 2002 Michael J. Roberts. All Rights Reserved. |
| | 8 | * |
| | 9 | * Please see the accompanying license file, LICENSE.TXT, for information |
| | 10 | * on using and copying this software. |
| | 11 | */ |
| | 12 | /* |
| | 13 | Name |
| | 14 | suprun.c - setup functions for run-time |
| | 15 | Function |
| | 16 | This module implements the set-up functions needed at run-time |
| | 17 | Notes |
| | 18 | Separated from sup.c to avoid having to link functions needed only |
| | 19 | in the compiler into the runtime. |
| | 20 | Modified |
| | 21 | 12/16/92 MJRoberts - add TADS/Graphic extensions |
| | 22 | 04/11/92 MJRoberts - creation |
| | 23 | */ |
| | 24 | |
| | 25 | #include <stdlib.h> |
| | 26 | #include <string.h> |
| | 27 | #include <assert.h> |
| | 28 | |
| | 29 | #include "os.h" |
| | 30 | #include "std.h" |
| | 31 | #include "obj.h" |
| | 32 | #include "prp.h" |
| | 33 | #include "dat.h" |
| | 34 | #include "tok.h" |
| | 35 | #include "mcm.h" |
| | 36 | #include "mch.h" |
| | 37 | #include "sup.h" |
| | 38 | #include "bif.h" |
| | 39 | |
| | 40 | supbidef osfar_t supbitab[] = |
| | 41 | { |
| | 42 | { "say", bifsay }, |
| | 43 | { "car", bifcar }, |
| | 44 | { "cdr", bifcdr }, |
| | 45 | { "length", biflen }, |
| | 46 | { "randomize", bifsrn }, |
| | 47 | { "rand", bifrnd }, |
| | 48 | { "substr", bifsub }, |
| | 49 | { "cvtstr", bifcvs }, |
| | 50 | { "cvtnum", bifcvn }, |
| | 51 | { "upper", bifupr }, |
| | 52 | { "lower", biflwr }, |
| | 53 | { "caps", bifcap }, |
| | 54 | { "find", biffnd }, |
| | 55 | { "getarg", bifarg }, |
| | 56 | { "datatype", biftyp }, |
| | 57 | { "setdaemon", bifsdm }, |
| | 58 | { "setfuse", bifsfs }, |
| | 59 | { "setversion", bifsvn }, |
| | 60 | { "notify", bifnfy }, |
| | 61 | { "unnotify", bifunn }, |
| | 62 | { "yorn", bifyon }, |
| | 63 | { "remfuse", bifrfs }, |
| | 64 | { "remdaemon", bifrdm }, |
| | 65 | { "incturn", bifinc }, |
| | 66 | { "quit", bifqui }, |
| | 67 | { "save", bifsav }, |
| | 68 | { "restore", bifrso }, |
| | 69 | { "logging", biflog }, |
| | 70 | { "input", bifinp }, |
| | 71 | { "setit", bifsit }, |
| | 72 | { "askfile", bifask }, |
| | 73 | { "setscore", bifssc }, |
| | 74 | { "firstobj", biffob }, |
| | 75 | { "nextobj", bifnob }, |
| | 76 | { "isclass", bifisc }, |
| | 77 | { "restart", bifres }, |
| | 78 | { "debugTrace", biftrc }, |
| | 79 | { "undo", bifund }, |
| | 80 | { "defined", bifdef }, |
| | 81 | { "proptype", bifpty }, |
| | 82 | { "outhide", bifoph }, |
| | 83 | { "runfuses", bifruf }, |
| | 84 | { "rundaemons", bifrud }, |
| | 85 | { "gettime", biftim }, |
| | 86 | { "getfuse", bifgfu }, |
| | 87 | { "intersect", bifsct }, |
| | 88 | { "inputkey", bifink }, |
| | 89 | { "objwords", bifwrd }, |
| | 90 | { "addword", bifadw }, |
| | 91 | { "delword", bifdlw }, |
| | 92 | { "getwords", bifgtw }, |
| | 93 | { "nocaps", bifnoc }, |
| | 94 | { "skipturn", bifskt }, |
| | 95 | { "clearscreen", bifcls }, |
| | 96 | { "firstsc", bif1sc }, |
| | 97 | { "verbinfo", bifvin }, |
| | 98 | { "fopen", biffopen }, |
| | 99 | { "fclose", biffclose }, |
| | 100 | { "fwrite", biffwrite }, |
| | 101 | { "fread", biffread }, |
| | 102 | { "fseek", biffseek }, |
| | 103 | { "fseekeof", biffseekeof }, |
| | 104 | { "ftell", bifftell }, |
| | 105 | { "outcapture", bifcapture }, |
| | 106 | |
| | 107 | { "systemInfo", bifsysinfo }, |
| | 108 | { "morePrompt", bifmore }, |
| | 109 | { "parserSetMe", bifsetme }, |
| | 110 | { "parserGetMe", bifgetme }, |
| | 111 | |
| | 112 | { "reSearch", bifresearch }, |
| | 113 | { "reGetGroup", bifregroup }, |
| | 114 | { "inputevent", bifinpevt }, |
| | 115 | { "timeDelay", bifdelay }, |
| | 116 | { "setOutputFilter", bifsetoutfilter }, |
| | 117 | { "execCommand", bifexec }, |
| | 118 | { "parserGetObj", bifgetobj }, |
| | 119 | { "parseNounList", bifparsenl }, |
| | 120 | { "parserTokenize", bifprstok }, |
| | 121 | { "parserGetTokTypes", bifprstoktyp }, |
| | 122 | { "parserDictLookup", bifprsdict }, |
| | 123 | { "parserResolveObjects", bifprsrslv }, |
| | 124 | { "parserReplaceCommand", bifprsrplcmd }, |
| | 125 | { "exitobj", bifexitobj }, |
| | 126 | { "inputdialog", bifinpdlg }, |
| | 127 | { "resourceExists", bifresexists }, |
| | 128 | |
| | 129 | /* |
| | 130 | * To accommodate systemInfo, we've removed g_readpic. This has been |
| | 131 | * present for a while and didn't do anything, since tads/g was never |
| | 132 | * released. We can therefore use its function slot without requiring |
| | 133 | * a format change. |
| | 134 | */ |
| | 135 | /* { "g_readpic", bifgrp }, */ |
| | 136 | |
| | 137 | /* likewise these */ |
| | 138 | /* { "g_showpic", bifgsp }, */ |
| | 139 | /* { "g_sethot", bifgsh }, */ |
| | 140 | /* { "g_inventory", bifgin }, */ |
| | 141 | |
| | 142 | /* |
| | 143 | * more tads/g functions - these are kept around mostly as |
| | 144 | * placeholders in case we want to use these slots in the future |
| | 145 | */ |
| | 146 | /* { "g_compass", bifgco }, - removed for reSearch */ |
| | 147 | /* { "g_overlay", bifgov }, - removed for reGetGroup */ |
| | 148 | /* { "g_mode", bifgmd }, - removed for inputevent */ |
| | 149 | /* { "g_music", bifgmu }, - removed for timeDelay */ |
| | 150 | /* { "g_pause", bifgpa }, - removed for setOutputFilter */ |
| | 151 | /* { "g_effect", bifgef }, - removed for execCommand */ |
| | 152 | /* { "g_sound", bifgsn }, - removed for parserGetObj */ |
| | 153 | |
| | 154 | /* a few more placeholder slots for future expansion */ |
| | 155 | /* { "__reserved_func_0", bifgsn }, - removed for parseNounList */ |
| | 156 | /* { "__reserved_func_2", bifgsn }, - removed for parserTokenize */ |
| | 157 | /* { "__reserved_func_3", bifgsn }, - removed for parserGetTokTypes */ |
| | 158 | /* { "__reserved_func_4", bifgsn }, - removed for parserDictLookup */ |
| | 159 | /* { "__reserved_func_5", bifgsn }, - removed for parserResolveObjects */ |
| | 160 | /* { "__reserved_func_6", bifgsn }, - removed for parserReplaceCommand */ |
| | 161 | /* { "__reserved_func_7", bifgsn }, - removed for exitobj */ |
| | 162 | /* { "__reserved_func_8", bifgsn }, - removed for inputdialog */ |
| | 163 | /* { "__reserved_func_9", bifgsn }, - removed for resourceExists */ |
| | 164 | |
| | 165 | /* more slots added in 2.3.1 */ |
| | 166 | { "__reserved_func_10", bifgsn }, |
| | 167 | { "__reserved_func_11", bifgsn }, |
| | 168 | { "__reserved_func_12", bifgsn }, |
| | 169 | { "__reserved_func_13", bifgsn }, |
| | 170 | { "__reserved_func_14", bifgsn }, |
| | 171 | { "__reserved_func_15", bifgsn }, |
| | 172 | { "__reserved_func_16", bifgsn }, |
| | 173 | { "__reserved_func_17", bifgsn }, |
| | 174 | { "__reserved_func_18", bifgsn }, |
| | 175 | { "__reserved_func_19", bifgsn }, |
| | 176 | |
| | 177 | |
| | 178 | { 0, 0 } |
| | 179 | }; |
| | 180 | |
| | 181 | /* set up built-in functions array without symbol table (for run-time) */ |
| | 182 | void supbif(supcxdef *sup, void (*bif[])(bifcxdef*, int), int bifsiz) |
| | 183 | { |
| | 184 | supbidef *p; |
| | 185 | int i; |
| | 186 | |
| | 187 | for (p = supbitab, i = 0 ; p->supbinam ; ++i, ++p) |
| | 188 | { |
| | 189 | if (i >= bifsiz) errsig(sup->supcxerr, ERR_MANYBIF); |
| | 190 | bif[i] = p->supbifn; |
| | 191 | } |
| | 192 | } |
| | 193 | |
| | 194 | /* set up contents property for load-on-demand */ |
| | 195 | void supcont(void *ctx0, objnum obj, prpnum prp) |
| | 196 | { |
| | 197 | supcxdef *ctx = (supcxdef *)ctx0; |
| | 198 | vocidef ***vpg; |
| | 199 | vocidef **v; |
| | 200 | voccxdef *voc = ctx->supcxvoc; |
| | 201 | int i; |
| | 202 | int j; |
| | 203 | int len = 2; |
| | 204 | objnum chi; |
| | 205 | objnum loc; |
| | 206 | |
| | 207 | /* be sure the buffer is allocated */ |
| | 208 | if (!ctx->supcxbuf) |
| | 209 | { |
| | 210 | ctx->supcxlen = 512; |
| | 211 | ctx->supcxbuf = mchalo(ctx->supcxerr, (ushort)ctx->supcxlen, |
| | 212 | "supcont"); |
| | 213 | } |
| | 214 | |
| | 215 | assert(prp == PRP_CONTENTS); /* the only thing that makes sense */ |
| | 216 | for (vpg = voc->voccxinh, i = 0 ; i < VOCINHMAX ; ++vpg, ++i) |
| | 217 | { |
| | 218 | if (!*vpg) continue; /* no entries on this page */ |
| | 219 | for (v = *vpg, chi = (i << 8), j = 0 ; j < 256 ; ++v, ++chi, ++j) |
| | 220 | { |
| | 221 | /* if there's no record at this location, skip it */ |
| | 222 | if (!*v) continue; |
| | 223 | |
| | 224 | /* inherit the location if it hasn't been set to any value */ |
| | 225 | if ((*v)->vociloc == MCMONINV |
| | 226 | && !((*v)->vociflg & VOCIFLOCNIL)) |
| | 227 | loc = (*v)->vociilc; |
| | 228 | else |
| | 229 | loc = (*v)->vociloc; |
| | 230 | |
| | 231 | /* if this object is in the indicated location, add it */ |
| | 232 | if (loc == obj && !((*v)->vociflg & VOCIFCLASS)) |
| | 233 | { |
| | 234 | /* see if we have room in list buffer; expand buffer if not */ |
| | 235 | if (len + 3 > ctx->supcxlen) |
| | 236 | { |
| | 237 | uchar *newbuf; |
| | 238 | |
| | 239 | /* allocate a new buffer */ |
| | 240 | newbuf = mchalo(ctx->supcxerr, |
| | 241 | (ushort)(len + 512), "supcont"); |
| | 242 | |
| | 243 | /* copy the old buffer's contents into the new buffer */ |
| | 244 | memcpy(newbuf, ctx->supcxbuf, ctx->supcxlen); |
| | 245 | |
| | 246 | /* remember the new buffer length */ |
| | 247 | ctx->supcxlen = len + 512; |
| | 248 | |
| | 249 | /* free the old buffer */ |
| | 250 | mchfre(ctx->supcxbuf); |
| | 251 | |
| | 252 | /* remember the new buffer */ |
| | 253 | ctx->supcxbuf = newbuf; |
| | 254 | |
| | 255 | /* sanity check for integer overflow */ |
| | 256 | if (len + 3 > ctx->supcxlen) |
| | 257 | errsig(ctx->supcxmem->mcmcxgl->mcmcxerr, ERR_SUPOVF); |
| | 258 | } |
| | 259 | ctx->supcxbuf[len] = DAT_OBJECT; |
| | 260 | oswp2(ctx->supcxbuf + len + 1, chi); |
| | 261 | len += 3; |
| | 262 | } |
| | 263 | } |
| | 264 | } |
| | 265 | |
| | 266 | oswp2(ctx->supcxbuf, len); |
| | 267 | objsetp(ctx->supcxmem, obj, prp, DAT_LIST, ctx->supcxbuf, |
| | 268 | ctx->supcxrun->runcxundo); |
| | 269 | } |
| | 270 | |
| | 271 | static void supiwrds(voccxdef *ctx, objnum sc, objnum target, int flags) |
| | 272 | { |
| | 273 | int i; |
| | 274 | vocdef *v; |
| | 275 | vocdef **vp; |
| | 276 | vocwdef *vw; |
| | 277 | |
| | 278 | /* go through each hash value looking for superclass object */ |
| | 279 | for (i = VOCHASHSIZ, vp = ctx->voccxhsh ; i != 0 ; ++vp, --i) |
| | 280 | { |
| | 281 | /* go through all words in this hash chain */ |
| | 282 | for (v = *vp ; v != 0 ; v = v->vocnxt) |
| | 283 | { |
| | 284 | /* go through all vocwdef's defined for this word */ |
| | 285 | for (vw = vocwget(ctx, v->vocwlst) ; vw ; |
| | 286 | vw = vocwget(ctx, vw->vocwnxt)) |
| | 287 | { |
| | 288 | /* add word to target if it's defined for this superclass */ |
| | 289 | if (vw->vocwobj == sc) |
| | 290 | vocadd2(ctx, vw->vocwtyp, target, VOCFINH + flags, |
| | 291 | v->voctxt, v->voclen, |
| | 292 | (v->vocln2 ? v->voctxt + v->voclen : (uchar *)0), |
| | 293 | v->vocln2); |
| | 294 | } |
| | 295 | } |
| | 296 | } |
| | 297 | } |
| | 298 | |
| | 299 | /* set up inherited vocabulary for a particular object */ |
| | 300 | void supivoc1(supcxdef *sup, voccxdef *ctx, vocidef *v, objnum target, |
| | 301 | int inh_from_obj, int flags) |
| | 302 | { |
| | 303 | objnum *sc; |
| | 304 | int numsc; |
| | 305 | vocidef *scv; |
| | 306 | |
| | 307 | for (numsc = v->vocinsc, sc = v->vocisc ; numsc ; ++sc, --numsc) |
| | 308 | { |
| | 309 | scv = vocinh(ctx, *sc); |
| | 310 | if (scv) |
| | 311 | { |
| | 312 | /* inherit from its superclasses first */ |
| | 313 | supivoc1(sup, ctx, scv, target, FALSE, flags); |
| | 314 | |
| | 315 | /* if it's a class object, we can inherit from it */ |
| | 316 | if (scv->vociflg & VOCIFCLASS) |
| | 317 | { |
| | 318 | /* inherit location, if we haven't already done so */ |
| | 319 | if (v->vociilc == MCMONINV) |
| | 320 | { |
| | 321 | if (scv->vociloc == MCMONINV) |
| | 322 | v->vociilc = scv->vociilc; |
| | 323 | else |
| | 324 | v->vociilc = scv->vociloc; |
| | 325 | } |
| | 326 | } |
| | 327 | |
| | 328 | /* |
| | 329 | * inherit from superclass if it's a class, or if we're |
| | 330 | * supposed to inherit from any object |
| | 331 | */ |
| | 332 | if (inh_from_obj || (scv->vociflg & VOCIFCLASS)) |
| | 333 | { |
| | 334 | /* inherit vocabulary if this superclass has any words */ |
| | 335 | if (scv->vociflg & VOCIFVOC) |
| | 336 | supiwrds(ctx, *sc, target, flags); |
| | 337 | } |
| | 338 | } |
| | 339 | else |
| | 340 | { |
| | 341 | char buf[TOKNAMMAX + 1]; |
| | 342 | |
| | 343 | /* get the symbol's name */ |
| | 344 | supgnam(buf, sup->supcxtab, *sc); |
| | 345 | |
| | 346 | /* log an error with the symbol's name and location of first use */ |
| | 347 | sup_log_undefobj(ctx->voccxmem, ctx->voccxerr, ERR_UNDFOBJ, |
| | 348 | buf, (int)strlen(buf), *sc); |
| | 349 | } |
| | 350 | } |
| | 351 | } |
| | 352 | |
| | 353 | void sup_log_undefobj(mcmcxdef *mctx, errcxdef *ec, int err, |
| | 354 | char *nm, int nmlen, objnum objn) |
| | 355 | { |
| | 356 | uchar *p; |
| | 357 | size_t len; |
| | 358 | |
| | 359 | /* |
| | 360 | * if the object has any superclasses defined, what must have |
| | 361 | * happened is that we encountered an error in the course of |
| | 362 | * defining the object; the object is partially defined, hence it |
| | 363 | * won't show up in our records of defined objects, yet it really |
| | 364 | * shouldn't count as an undefined object; simply suppress the |
| | 365 | * message in this case |
| | 366 | */ |
| | 367 | if (objget1sc(mctx, objn) != MCMONINV) |
| | 368 | return; |
| | 369 | |
| | 370 | /* get the object - it contains the location where it was defined */ |
| | 371 | p = mcmlck(mctx, (mcmon)objn); |
| | 372 | |
| | 373 | /* skip the object header */ |
| | 374 | p += OBJDEFSIZ; |
| | 375 | |
| | 376 | /* get the length of the name */ |
| | 377 | len = strlen((char *)p); |
| | 378 | |
| | 379 | #ifdef OS_ERRLINE |
| | 380 | len += strlen((char *)p + len + 1); |
| | 381 | #endif |
| | 382 | |
| | 383 | /* log the error */ |
| | 384 | errlog2(ec, err, ERRTSTR, errstr(ec, nm, nmlen), |
| | 385 | ERRTSTR, errstr(ec, (char *)p, len)); |
| | 386 | |
| | 387 | /* done with the object */ |
| | 388 | mcmunlck(mctx, (mcmon)objn); |
| | 389 | } |
| | 390 | |