1/*
   2** $Id: ltests.c $
   3** Internal Module for Debugging of the Lua Implementation
   4** See Copyright Notice in lua.h
   5*/
   6
   7#define ltests_c
   8#define LUA_CORE
   9
  10#include "lprefix.h"
  11
  12
  13#include <limits.h>
  14#include <setjmp.h>
  15#include <stdio.h>
  16#include <stdlib.h>
  17#include <string.h>
  18
  19#include "lua.h"
  20
  21#include "lapi.h"
  22#include "lauxlib.h"
  23#include "lcode.h"
  24#include "lctype.h"
  25#include "ldebug.h"
  26#include "ldo.h"
  27#include "lfunc.h"
  28#include "lmem.h"
  29#include "lopcodes.h"
  30#include "lopnames.h"
  31#include "lstate.h"
  32#include "lstring.h"
  33#include "ltable.h"
  34#include "lualib.h"
  35
  36
  37
  38/*
  39** The whole module only makes sense with LUA_DEBUG on
  40*/
  41#if defined(LUA_DEBUG)
  42
  43
  44void *l_Trick = 0;
  45
  46
  47#define obj_at(L,k)	s2v(L->ci->func.p + (k))
  48
  49
  50static int runC (lua_State *L, lua_State *L1, const char *pc);
  51
  52
  53static void setnameval (lua_State *L, const char *name, int val) {
  54  lua_pushinteger(L, val);
  55  lua_setfield(L, -2, name);
  56}
  57
  58
  59static void pushobject (lua_State *L, const TValue *o) {
  60  setobj2s(L, L->top.p, o);
  61  api_incr_top(L);
  62}
  63
  64
  65static void badexit (const char *fmt, const char *s1, const char *s2) {
  66  fprintf(stderr, fmt, s1);
  67  if (s2)
  68    fprintf(stderr, "extra info: %s\n", s2);
  69  /* avoid assertion failures when exiting */
  70  l_memcontrol.numblocks = l_memcontrol.total = 0;
  71  exit(EXIT_FAILURE);
  72}
  73
  74
  75static int tpanic (lua_State *L) {
  76  const char *msg = (lua_type(L, -1) == LUA_TSTRING)
  77                  ? lua_tostring(L, -1)
  78                  : "error object is not a string";
  79  return (badexit("PANIC: unprotected error in call to Lua API (%s)\n",
  80                   msg, NULL),
  81          0);  /* do not return to Lua */
  82}
  83
  84
  85/*
  86** Warning function for tests. First, it concatenates all parts of
  87** a warning in buffer 'buff'. Then, it has three modes:
  88** - 0.normal: messages starting with '#' are shown on standard output;
  89** - other messages abort the tests (they represent real warning
  90** conditions; the standard tests should not generate these conditions
  91** unexpectedly);
  92** - 1.allow: all messages are shown;
  93** - 2.store: all warnings go to the global '_WARN';
  94*/
  95static void warnf (void *ud, const char *msg, int tocont) {
  96  lua_State *L = cast(lua_State *, ud);
  97  static char buff[200] = "";  /* should be enough for tests... */
  98  static int onoff = 0;
  99  static int mode = 0;  /* start in normal mode */
 100  static int lasttocont = 0;
 101  if (!lasttocont && !tocont && *msg == '@') {  /* control message? */
 102    if (buff[0] != '\0')
 103      badexit("Control warning during warning: %s\naborting...\n", msg, buff);
 104    if (strcmp(msg, "@off") == 0)
 105      onoff = 0;
 106    else if (strcmp(msg, "@on") == 0)
 107      onoff = 1;
 108    else if (strcmp(msg, "@normal") == 0)
 109      mode = 0;
 110    else if (strcmp(msg, "@allow") == 0)
 111      mode = 1;
 112    else if (strcmp(msg, "@store") == 0)
 113      mode = 2;
 114    else
 115      badexit("Invalid control warning in test mode: %s\naborting...\n",
 116              msg, NULL);
 117    return;
 118  }
 119  lasttocont = tocont;
 120  if (strlen(msg) >= sizeof(buff) - strlen(buff))
 121    badexit("warnf-buffer overflow (%s)\n", msg, buff);
 122  strcat(buff, msg);  /* add new message to current warning */
 123  if (!tocont) {  /* message finished? */
 124    lua_unlock(L);
 125    luaL_checkstack(L, 1, "warn stack space");
 126    lua_getglobal(L, "_WARN");
 127    if (!lua_toboolean(L, -1))
 128      lua_pop(L, 1);  /* ok, no previous unexpected warning */
 129    else {
 130      badexit("Unhandled warning in store mode: %s\naborting...\n",
 131              lua_tostring(L, -1), buff);
 132    }
 133    lua_lock(L);
 134    switch (mode) {
 135      case 0: {  /* normal */
 136        if (buff[0] != '#' && onoff)  /* unexpected warning? */
 137          badexit("Unexpected warning in test mode: %s\naborting...\n",
 138                  buff, NULL);
 139      }  /* FALLTHROUGH */
 140      case 1: {  /* allow */
 141        if (onoff)
 142          fprintf(stderr, "Lua warning: %s\n", buff);  /* print warning */
 143        break;
 144      }
 145      case 2: {  /* store */
 146        lua_unlock(L);
 147        luaL_checkstack(L, 1, "warn stack space");
 148        lua_pushstring(L, buff);
 149        lua_setglobal(L, "_WARN");  /* assign message to global '_WARN' */
 150        lua_lock(L);
 151        break;
 152      }
 153    }
 154    buff[0] = '\0';  /* prepare buffer for next warning */
 155  }
 156}
 157
 158
 159/*
 160** {======================================================================
 161** Controlled version for realloc.
 162** =======================================================================
 163*/
 164
 165#define MARK		0x55  /* 01010101 (a nice pattern) */
 166
 167typedef union Header {
 168  LUAI_MAXALIGN;
 169  struct {
 170    size_t size;
 171    int type;
 172  } d;
 173} Header;
 174
 175
 176#if !defined(EXTERNMEMCHECK)
 177
 178/* full memory check */
 179#define MARKSIZE	16  /* size of marks after each block */
 180#define fillmem(mem,size)	memset(mem, -MARK, size)
 181
 182#else
 183
 184/* external memory check: don't do it twice */
 185#define MARKSIZE	0
 186#define fillmem(mem,size)	/* empty */
 187
 188#endif
 189
 190
 191Memcontrol l_memcontrol =
 192  {0, 0UL, 0UL, 0UL, 0UL, (~0UL),
 193   {0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL}};
 194
 195
 196static void freeblock (Memcontrol *mc, Header *block) {
 197  if (block) {
 198    size_t size = block->d.size;
 199    int i;
 200    for (i = 0; i < MARKSIZE; i++)  /* check marks after block */
 201      lua_assert(*(cast_charp(block + 1) + size + i) == MARK);
 202    mc->objcount[block->d.type]--;
 203    fillmem(block, sizeof(Header) + size + MARKSIZE);  /* erase block */
 204    free(block);  /* actually free block */
 205    mc->numblocks--;  /* update counts */
 206    mc->total -= size;
 207  }
 208}
 209
 210
 211void *debug_realloc (void *ud, void *b, size_t oldsize, size_t size) {
 212  Memcontrol *mc = cast(Memcontrol *, ud);
 213  Header *block = cast(Header *, b);
 214  int type;
 215  if (mc->memlimit == 0) {  /* first time? */
 216    char *limit = getenv("MEMLIMIT");  /* initialize memory limit */
 217    mc->memlimit = limit ? strtoul(limit, NULL, 10) : ULONG_MAX;
 218  }
 219  if (block == NULL) {
 220    type = (oldsize < LUA_NUMTAGS) ? oldsize : 0;
 221    oldsize = 0;
 222  }
 223  else {
 224    block--;  /* go to real header */
 225    type = block->d.type;
 226    lua_assert(oldsize == block->d.size);
 227  }
 228  if (size == 0) {
 229    freeblock(mc, block);
 230    return NULL;
 231  }
 232  if (mc->failnext) {
 233    mc->failnext = 0;
 234    return NULL;  /* fake a single memory allocation error */
 235  }
 236  if (mc->countlimit != ~0UL && size != oldsize) {  /* count limit in use? */
 237    if (mc->countlimit == 0)
 238      return NULL;  /* fake a memory allocation error */
 239    mc->countlimit--;
 240  }
 241  if (size > oldsize && mc->total+size-oldsize > mc->memlimit)
 242    return NULL;  /* fake a memory allocation error */
 243  else {
 244    Header *newblock;
 245    int i;
 246    size_t commonsize = (oldsize < size) ? oldsize : size;
 247    size_t realsize = sizeof(Header) + size + MARKSIZE;
 248    if (realsize < size) return NULL;  /* arithmetic overflow! */
 249    newblock = cast(Header *, malloc(realsize));  /* alloc a new block */
 250    if (newblock == NULL)
 251      return NULL;  /* really out of memory? */
 252    if (block) {
 253      memcpy(newblock + 1, block + 1, commonsize);  /* copy old contents */
 254      freeblock(mc, block);  /* erase (and check) old copy */
 255    }
 256    /* initialize new part of the block with something weird */
 257    fillmem(cast_charp(newblock + 1) + commonsize, size - commonsize);
 258    /* initialize marks after block */
 259    for (i = 0; i < MARKSIZE; i++)
 260      *(cast_charp(newblock + 1) + size + i) = MARK;
 261    newblock->d.size = size;
 262    newblock->d.type = type;
 263    mc->total += size;
 264    if (mc->total > mc->maxmem)
 265      mc->maxmem = mc->total;
 266    mc->numblocks++;
 267    mc->objcount[type]++;
 268    return newblock + 1;
 269  }
 270}
 271
 272
 273/* }====================================================================== */
 274
 275
 276
 277/*
 278** {=====================================================================
 279** Functions to check memory consistency.
 280** Most of these checks are done through asserts, so this code does
 281** not make sense with asserts off. For this reason, it uses 'assert'
 282** directly, instead of 'lua_assert'.
 283** ======================================================================
 284*/
 285
 286#include <assert.h>
 287
 288/*
 289** Check GC invariants. For incremental mode, a black object cannot
 290** point to a white one. For generational mode, really old objects
 291** cannot point to young objects. Both old1 and touched2 objects
 292** cannot point to new objects (but can point to survivals).
 293** (Threads and open upvalues, despite being marked "really old",
 294** continue to be visited in all collections, and therefore can point to
 295** new objects. They, and only they, are old but gray.)
 296*/
 297static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
 298  if (isdead(g,t)) return 0;
 299  if (issweepphase(g))
 300    return 1;  /* no invariants */
 301  else if (g->gckind == KGC_INC)
 302    return !(isblack(f) && iswhite(t));  /* basic incremental invariant */
 303  else {  /* generational mode */
 304    if ((getage(f) == G_OLD && isblack(f)) && !isold(t))
 305      return 0;
 306    if (((getage(f) == G_OLD1 || getage(f) == G_TOUCHED2) && isblack(f)) &&
 307          getage(t) == G_NEW)
 308      return 0;
 309    return 1;
 310  }
 311}
 312
 313
 314static void printobj (global_State *g, GCObject *o) {
 315  printf("||%s(%p)-%c%c(%02X)||",
 316           ttypename(novariant(o->tt)), (void *)o,
 317           isdead(g,o) ? 'd' : isblack(o) ? 'b' : iswhite(o) ? 'w' : 'g',
 318           "ns01oTt"[getage(o)], o->marked);
 319  if (o->tt == LUA_VSHRSTR || o->tt == LUA_VLNGSTR)
 320    printf(" '%s'", getstr(gco2ts(o)));
 321}
 322
 323
 324void lua_printobj (lua_State *L, struct GCObject *o) {
 325  printobj(G(L), o);
 326}
 327
 328static int testobjref (global_State *g, GCObject *f, GCObject *t) {
 329  int r1 = testobjref1(g, f, t);
 330  if (!r1) {
 331    printf("%d(%02X) - ", g->gcstate, g->currentwhite);
 332    printobj(g, f);
 333    printf("  ->  ");
 334    printobj(g, t);
 335    printf("\n");
 336  }
 337  return r1;
 338}
 339
 340
 341static void checkobjref (global_State *g, GCObject *f, GCObject *t) {
 342    assert(testobjref(g, f, t));
 343}
 344
 345
 346/*
 347** Version where 't' can be NULL. In that case, it should not apply the
 348** macro 'obj2gco' over the object. ('t' may have several types, so this
 349** definition must be a macro.)  Most checks need this version, because
 350** the check may run while an object is still being created.
 351*/
 352#define checkobjrefN(g,f,t)	{ if (t) checkobjref(g,f,obj2gco(t)); }
 353
 354
 355static void checkvalref (global_State *g, GCObject *f, const TValue *t) {
 356  assert(!iscollectable(t) || (righttt(t) && testobjref(g, f, gcvalue(t))));
 357}
 358
 359
 360static void checktable (global_State *g, Table *h) {
 361  unsigned int i;
 362  unsigned int asize = luaH_realasize(h);
 363  Node *n, *limit = gnode(h, sizenode(h));
 364  GCObject *hgc = obj2gco(h);
 365  checkobjrefN(g, hgc, h->metatable);
 366  for (i = 0; i < asize; i++)
 367    checkvalref(g, hgc, &h->array[i]);
 368  for (n = gnode(h, 0); n < limit; n++) {
 369    if (!isempty(gval(n))) {
 370      TValue k;
 371      getnodekey(g->mainthread, &k, n);
 372      assert(!keyisnil(n));
 373      checkvalref(g, hgc, &k);
 374      checkvalref(g, hgc, gval(n));
 375    }
 376  }
 377}
 378
 379
 380static void checkudata (global_State *g, Udata *u) {
 381  int i;
 382  GCObject *hgc = obj2gco(u);
 383  checkobjrefN(g, hgc, u->metatable);
 384  for (i = 0; i < u->nuvalue; i++)
 385    checkvalref(g, hgc, &u->uv[i].uv);
 386}
 387
 388
 389static void checkproto (global_State *g, Proto *f) {
 390  int i;
 391  GCObject *fgc = obj2gco(f);
 392  checkobjrefN(g, fgc, f->source);
 393  for (i=0; i<f->sizek; i++) {
 394    if (iscollectable(f->k + i))
 395      checkobjref(g, fgc, gcvalue(f->k + i));
 396  }
 397  for (i=0; i<f->sizeupvalues; i++)
 398    checkobjrefN(g, fgc, f->upvalues[i].name);
 399  for (i=0; i<f->sizep; i++)
 400    checkobjrefN(g, fgc, f->p[i]);
 401  for (i=0; i<f->sizelocvars; i++)
 402    checkobjrefN(g, fgc, f->locvars[i].varname);
 403}
 404
 405
 406static void checkCclosure (global_State *g, CClosure *cl) {
 407  GCObject *clgc = obj2gco(cl);
 408  int i;
 409  for (i = 0; i < cl->nupvalues; i++)
 410    checkvalref(g, clgc, &cl->upvalue[i]);
 411}
 412
 413
 414static void checkLclosure (global_State *g, LClosure *cl) {
 415  GCObject *clgc = obj2gco(cl);
 416  int i;
 417  checkobjrefN(g, clgc, cl->p);
 418  for (i=0; i<cl->nupvalues; i++) {
 419    UpVal *uv = cl->upvals[i];
 420    if (uv) {
 421      checkobjrefN(g, clgc, uv);
 422      if (!upisopen(uv))
 423        checkvalref(g, obj2gco(uv), uv->v.p);
 424    }
 425  }
 426}
 427
 428
 429static int lua_checkpc (CallInfo *ci) {
 430  if (!isLua(ci)) return 1;
 431  else {
 432    StkId f = ci->func.p;
 433    Proto *p = clLvalue(s2v(f))->p;
 434    return p->code <= ci->u.l.savedpc &&
 435           ci->u.l.savedpc <= p->code + p->sizecode;
 436  }
 437}
 438
 439
 440static void checkstack (global_State *g, lua_State *L1) {
 441  StkId o;
 442  CallInfo *ci;
 443  UpVal *uv;
 444  assert(!isdead(g, L1));
 445  if (L1->stack.p == NULL) {  /* incomplete thread? */
 446    assert(L1->openupval == NULL && L1->ci == NULL);
 447    return;
 448  }
 449  for (uv = L1->openupval; uv != NULL; uv = uv->u.open.next)
 450    assert(upisopen(uv));  /* must be open */
 451  assert(L1->top.p <= L1->stack_last.p);
 452  assert(L1->tbclist.p <= L1->top.p);
 453  for (ci = L1->ci; ci != NULL; ci = ci->previous) {
 454    assert(ci->top.p <= L1->stack_last.p);
 455    assert(lua_checkpc(ci));
 456  }
 457  for (o = L1->stack.p; o < L1->stack_last.p; o++)
 458    checkliveness(L1, s2v(o));  /* entire stack must have valid values */
 459}
 460
 461
 462static void checkrefs (global_State *g, GCObject *o) {
 463  switch (o->tt) {
 464    case LUA_VUSERDATA: {
 465      checkudata(g, gco2u(o));
 466      break;
 467    }
 468    case LUA_VUPVAL: {
 469      checkvalref(g, o, gco2upv(o)->v.p);
 470      break;
 471    }
 472    case LUA_VTABLE: {
 473      checktable(g, gco2t(o));
 474      break;
 475    }
 476    case LUA_VTHREAD: {
 477      checkstack(g, gco2th(o));
 478      break;
 479    }
 480    case LUA_VLCL: {
 481      checkLclosure(g, gco2lcl(o));
 482      break;
 483    }
 484    case LUA_VCCL: {
 485      checkCclosure(g, gco2ccl(o));
 486      break;
 487    }
 488    case LUA_VPROTO: {
 489      checkproto(g, gco2p(o));
 490      break;
 491    }
 492    case LUA_VSHRSTR:
 493    case LUA_VLNGSTR: {
 494      assert(!isgray(o));  /* strings are never gray */
 495      break;
 496    }
 497    default: assert(0);
 498  }
 499}
 500
 501
 502/*
 503** Check consistency of an object:
 504** - Dead objects can only happen in the 'allgc' list during a sweep
 505** phase (controlled by the caller through 'maybedead').
 506** - During pause, all objects must be white.
 507** - In generational mode:
 508**   * objects must be old enough for their lists ('listage').
 509**   * old objects cannot be white.
 510**   * old objects must be black, except for 'touched1', 'old0',
 511** threads, and open upvalues.
 512*/
 513static void checkobject (global_State *g, GCObject *o, int maybedead,
 514                         int listage) {
 515  if (isdead(g, o))
 516    assert(maybedead);
 517  else {
 518    assert(g->gcstate != GCSpause || iswhite(o));
 519    if (g->gckind == KGC_GEN) {  /* generational mode? */
 520      assert(getage(o) >= listage);
 521      assert(!iswhite(o) || !isold(o));
 522      if (isold(o)) {
 523        assert(isblack(o) ||
 524        getage(o) == G_TOUCHED1 ||
 525        getage(o) == G_OLD0 ||
 526        o->tt == LUA_VTHREAD ||
 527        (o->tt == LUA_VUPVAL && upisopen(gco2upv(o))));
 528      }
 529    }
 530    checkrefs(g, o);
 531  }
 532}
 533
 534
 535static lu_mem checkgraylist (global_State *g, GCObject *o) {
 536  int total = 0;  /* count number of elements in the list */
 537  cast_void(g);  /* better to keep it if we need to print an object */
 538  while (o) {
 539    assert(!!isgray(o) ^ (getage(o) == G_TOUCHED2));
 540    assert(!testbit(o->marked, TESTBIT));
 541    if (keepinvariant(g))
 542      l_setbit(o->marked, TESTBIT);  /* mark that object is in a gray list */
 543    total++;
 544    switch (o->tt) {
 545      case LUA_VTABLE: o = gco2t(o)->gclist; break;
 546      case LUA_VLCL: o = gco2lcl(o)->gclist; break;
 547      case LUA_VCCL: o = gco2ccl(o)->gclist; break;
 548      case LUA_VTHREAD: o = gco2th(o)->gclist; break;
 549      case LUA_VPROTO: o = gco2p(o)->gclist; break;
 550      case LUA_VUSERDATA:
 551        assert(gco2u(o)->nuvalue > 0);
 552        o = gco2u(o)->gclist;
 553        break;
 554      default: assert(0);  /* other objects cannot be in a gray list */
 555    }
 556  }
 557  return total;
 558}
 559
 560
 561/*
 562** Check objects in gray lists.
 563*/
 564static lu_mem checkgrays (global_State *g) {
 565  int total = 0;  /* count number of elements in all lists */
 566  if (!keepinvariant(g)) return total;
 567  total += checkgraylist(g, g->gray);
 568  total += checkgraylist(g, g->grayagain);
 569  total += checkgraylist(g, g->weak);
 570  total += checkgraylist(g, g->allweak);
 571  total += checkgraylist(g, g->ephemeron);
 572  return total;
 573}
 574
 575
 576/*
 577** Check whether 'o' should be in a gray list. If so, increment
 578** 'count' and check its TESTBIT. (It must have been previously set by
 579** 'checkgraylist'.)
 580*/
 581static void incifingray (global_State *g, GCObject *o, lu_mem *count) {
 582  if (!keepinvariant(g))
 583    return;  /* gray lists not being kept in these phases */
 584  if (o->tt == LUA_VUPVAL) {
 585    /* only open upvalues can be gray */
 586    assert(!isgray(o) || upisopen(gco2upv(o)));
 587    return;  /* upvalues are never in gray lists */
 588  }
 589  /* these are the ones that must be in gray lists */
 590  if (isgray(o) || getage(o) == G_TOUCHED2) {
 591    (*count)++;
 592    assert(testbit(o->marked, TESTBIT));
 593    resetbit(o->marked, TESTBIT);  /* prepare for next cycle */
 594  }
 595}
 596
 597
 598static lu_mem checklist (global_State *g, int maybedead, int tof,
 599  GCObject *newl, GCObject *survival, GCObject *old, GCObject *reallyold) {
 600  GCObject *o;
 601  lu_mem total = 0;  /* number of object that should be in  gray lists */
 602  for (o = newl; o != survival; o = o->next) {
 603    checkobject(g, o, maybedead, G_NEW);
 604    incifingray(g, o, &total);
 605    assert(!tof == !tofinalize(o));
 606  }
 607  for (o = survival; o != old; o = o->next) {
 608    checkobject(g, o, 0, G_SURVIVAL);
 609    incifingray(g, o, &total);
 610    assert(!tof == !tofinalize(o));
 611  }
 612  for (o = old; o != reallyold; o = o->next) {
 613    checkobject(g, o, 0, G_OLD1);
 614    incifingray(g, o, &total);
 615    assert(!tof == !tofinalize(o));
 616  }
 617  for (o = reallyold; o != NULL; o = o->next) {
 618    checkobject(g, o, 0, G_OLD);
 619    incifingray(g, o, &total);
 620    assert(!tof == !tofinalize(o));
 621  }
 622  return total;
 623}
 624
 625
 626int lua_checkmemory (lua_State *L) {
 627  global_State *g = G(L);
 628  GCObject *o;
 629  int maybedead;
 630  lu_mem totalin;  /* total of objects that are in gray lists */
 631  lu_mem totalshould;  /* total of objects that should be in gray lists */
 632  if (keepinvariant(g)) {
 633    assert(!iswhite(g->mainthread));
 634    assert(!iswhite(gcvalue(&g->l_registry)));
 635  }
 636  assert(!isdead(g, gcvalue(&g->l_registry)));
 637  assert(g->sweepgc == NULL || issweepphase(g));
 638  totalin = checkgrays(g);
 639
 640  /* check 'fixedgc' list */
 641  for (o = g->fixedgc; o != NULL; o = o->next) {
 642    assert(o->tt == LUA_VSHRSTR && isgray(o) && getage(o) == G_OLD);
 643  }
 644
 645  /* check 'allgc' list */
 646  maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswpallgc);
 647  totalshould = checklist(g, maybedead, 0, g->allgc,
 648                             g->survival, g->old1, g->reallyold);
 649
 650  /* check 'finobj' list */
 651  totalshould += checklist(g, 0, 1, g->finobj,
 652                              g->finobjsur, g->finobjold1, g->finobjrold);
 653
 654  /* check 'tobefnz' list */
 655  for (o = g->tobefnz; o != NULL; o = o->next) {
 656    checkobject(g, o, 0, G_NEW);
 657    incifingray(g, o, &totalshould);
 658    assert(tofinalize(o));
 659    assert(o->tt == LUA_VUSERDATA || o->tt == LUA_VTABLE);
 660  }
 661  if (keepinvariant(g))
 662    assert(totalin == totalshould);
 663  return 0;
 664}
 665
 666/* }====================================================== */
 667
 668
 669
 670/*
 671** {======================================================
 672** Disassembler
 673** =======================================================
 674*/
 675
 676
 677static char *buildop (Proto *p, int pc, char *buff) {
 678  char *obuff = buff;
 679  Instruction i = p->code[pc];
 680  OpCode o = GET_OPCODE(i);
 681  const char *name = opnames[o];
 682  int line = luaG_getfuncline(p, pc);
 683  int lineinfo = (p->lineinfo != NULL) ? p->lineinfo[pc] : 0;
 684  if (lineinfo == ABSLINEINFO)
 685    buff += sprintf(buff, "(__");
 686  else
 687    buff += sprintf(buff, "(%2d", lineinfo);
 688  buff += sprintf(buff, " - %4d) %4d - ", line, pc);
 689  switch (getOpMode(o)) {
 690    case iABC:
 691      sprintf(buff, "%-12s%4d %4d %4d%s", name,
 692              GETARG_A(i), GETARG_B(i), GETARG_C(i),
 693              GETARG_k(i) ? " (k)" : "");
 694      break;
 695    case iABx:
 696      sprintf(buff, "%-12s%4d %4d", name, GETARG_A(i), GETARG_Bx(i));
 697      break;
 698    case iAsBx:
 699      sprintf(buff, "%-12s%4d %4d", name, GETARG_A(i), GETARG_sBx(i));
 700      break;
 701    case iAx:
 702      sprintf(buff, "%-12s%4d", name, GETARG_Ax(i));
 703      break;
 704    case isJ:
 705      sprintf(buff, "%-12s%4d", name, GETARG_sJ(i));
 706      break;
 707  }
 708  return obuff;
 709}
 710
 711
 712#if 0
 713void luaI_printcode (Proto *pt, int size) {
 714  int pc;
 715  for (pc=0; pc<size; pc++) {
 716    char buff[100];
 717    printf("%s\n", buildop(pt, pc, buff));
 718  }
 719  printf("-------\n");
 720}
 721
 722
 723void luaI_printinst (Proto *pt, int pc) {
 724  char buff[100];
 725  printf("%s\n", buildop(pt, pc, buff));
 726}
 727#endif
 728
 729
 730static int listcode (lua_State *L) {
 731  int pc;
 732  Proto *p;
 733  luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
 734                 1, "Lua function expected");
 735  p = getproto(obj_at(L, 1));
 736  lua_newtable(L);
 737  setnameval(L, "maxstack", p->maxstacksize);
 738  setnameval(L, "numparams", p->numparams);
 739  for (pc=0; pc<p->sizecode; pc++) {
 740    char buff[100];
 741    lua_pushinteger(L, pc+1);
 742    lua_pushstring(L, buildop(p, pc, buff));
 743    lua_settable(L, -3);
 744  }
 745  return 1;
 746}
 747
 748
 749static int printcode (lua_State *L) {
 750  int pc;
 751  Proto *p;
 752  luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
 753                 1, "Lua function expected");
 754  p = getproto(obj_at(L, 1));
 755  printf("maxstack: %d\n", p->maxstacksize);
 756  printf("numparams: %d\n", p->numparams);
 757  for (pc=0; pc<p->sizecode; pc++) {
 758    char buff[100];
 759    printf("%s\n", buildop(p, pc, buff));
 760  }
 761  return 0;
 762}
 763
 764
 765static int listk (lua_State *L) {
 766  Proto *p;
 767  int i;
 768  luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
 769                 1, "Lua function expected");
 770  p = getproto(obj_at(L, 1));
 771  lua_createtable(L, p->sizek, 0);
 772  for (i=0; i<p->sizek; i++) {
 773    pushobject(L, p->k+i);
 774    lua_rawseti(L, -2, i+1);
 775  }
 776  return 1;
 777}
 778
 779
 780static int listabslineinfo (lua_State *L) {
 781  Proto *p;
 782  int i;
 783  luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
 784                 1, "Lua function expected");
 785  p = getproto(obj_at(L, 1));
 786  luaL_argcheck(L, p->abslineinfo != NULL, 1, "function has no debug info");
 787  lua_createtable(L, 2 * p->sizeabslineinfo, 0);
 788  for (i=0; i < p->sizeabslineinfo; i++) {
 789    lua_pushinteger(L, p->abslineinfo[i].pc);
 790    lua_rawseti(L, -2, 2 * i + 1);
 791    lua_pushinteger(L, p->abslineinfo[i].line);
 792    lua_rawseti(L, -2, 2 * i + 2);
 793  }
 794  return 1;
 795}
 796
 797
 798static int listlocals (lua_State *L) {
 799  Proto *p;
 800  int pc = cast_int(luaL_checkinteger(L, 2)) - 1;
 801  int i = 0;
 802  const char *name;
 803  luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
 804                 1, "Lua function expected");
 805  p = getproto(obj_at(L, 1));
 806  while ((name = luaF_getlocalname(p, ++i, pc)) != NULL)
 807    lua_pushstring(L, name);
 808  return i-1;
 809}
 810
 811/* }====================================================== */
 812
 813
 814
 815static void printstack (lua_State *L) {
 816  int i;
 817  int n = lua_gettop(L);
 818  printf("stack: >>\n");
 819  for (i = 1; i <= n; i++) {
 820    printf("%3d: %s\n", i, luaL_tolstring(L, i, NULL));
 821    lua_pop(L, 1);
 822  }
 823  printf("<<\n");
 824}
 825
 826
 827static int get_limits (lua_State *L) {
 828  lua_createtable(L, 0, 6);
 829  setnameval(L, "IS32INT", LUAI_IS32INT);
 830  setnameval(L, "MAXARG_Ax", MAXARG_Ax);
 831  setnameval(L, "MAXARG_Bx", MAXARG_Bx);
 832  setnameval(L, "OFFSET_sBx", OFFSET_sBx);
 833  setnameval(L, "LFPF", LFIELDS_PER_FLUSH);
 834  setnameval(L, "NUM_OPCODES", NUM_OPCODES);
 835  return 1;
 836}
 837
 838
 839static int mem_query (lua_State *L) {
 840  if (lua_isnone(L, 1)) {
 841    lua_pushinteger(L, l_memcontrol.total);
 842    lua_pushinteger(L, l_memcontrol.numblocks);
 843    lua_pushinteger(L, l_memcontrol.maxmem);
 844    return 3;
 845  }
 846  else if (lua_isnumber(L, 1)) {
 847    unsigned long limit = cast(unsigned long, luaL_checkinteger(L, 1));
 848    if (limit == 0) limit = ULONG_MAX;
 849    l_memcontrol.memlimit = limit;
 850    return 0;
 851  }
 852  else {
 853    const char *t = luaL_checkstring(L, 1);
 854    int i;
 855    for (i = LUA_NUMTAGS - 1; i >= 0; i--) {
 856      if (strcmp(t, ttypename(i)) == 0) {
 857        lua_pushinteger(L, l_memcontrol.objcount[i]);
 858        return 1;
 859      }
 860    }
 861    return luaL_error(L, "unknown type '%s'", t);
 862  }
 863}
 864
 865
 866static int alloc_count (lua_State *L) {
 867  if (lua_isnone(L, 1))
 868    l_memcontrol.countlimit = ~0L;
 869  else
 870    l_memcontrol.countlimit = luaL_checkinteger(L, 1);
 871  return 0;
 872}
 873
 874
 875static int alloc_failnext (lua_State *L) {
 876  UNUSED(L);
 877  l_memcontrol.failnext = 1;
 878  return 0;
 879}
 880
 881
 882static int settrick (lua_State *L) {
 883  if (ttisnil(obj_at(L, 1)))
 884    l_Trick = NULL;
 885  else
 886    l_Trick = gcvalue(obj_at(L, 1));
 887  return 0;
 888}
 889
 890
 891static int gc_color (lua_State *L) {
 892  TValue *o;
 893  luaL_checkany(L, 1);
 894  o = obj_at(L, 1);
 895  if (!iscollectable(o))
 896    lua_pushstring(L, "no collectable");
 897  else {
 898    GCObject *obj = gcvalue(o);
 899    lua_pushstring(L, isdead(G(L), obj) ? "dead" :
 900                      iswhite(obj) ? "white" :
 901                      isblack(obj) ? "black" : "gray");
 902  }
 903  return 1;
 904}
 905
 906
 907static int gc_age (lua_State *L) {
 908  TValue *o;
 909  luaL_checkany(L, 1);
 910  o = obj_at(L, 1);
 911  if (!iscollectable(o))
 912    lua_pushstring(L, "no collectable");
 913  else {
 914    static const char *gennames[] = {"new", "survival", "old0", "old1",
 915                                     "old", "touched1", "touched2"};
 916    GCObject *obj = gcvalue(o);
 917    lua_pushstring(L, gennames[getage(obj)]);
 918  }
 919  return 1;
 920}
 921
 922
 923static int gc_printobj (lua_State *L) {
 924  TValue *o;
 925  luaL_checkany(L, 1);
 926  o = obj_at(L, 1);
 927  if (!iscollectable(o))
 928    printf("no collectable\n");
 929  else {
 930    GCObject *obj = gcvalue(o);
 931    printobj(G(L), obj);
 932    printf("\n");
 933  }
 934  return 0;
 935}
 936
 937
 938static int gc_state (lua_State *L) {
 939  static const char *statenames[] = {
 940    "propagate", "atomic", "enteratomic", "sweepallgc", "sweepfinobj",
 941    "sweeptobefnz", "sweepend", "callfin", "pause", ""};
 942  static const int states[] = {
 943    GCSpropagate, GCSenteratomic, GCSatomic, GCSswpallgc, GCSswpfinobj,
 944    GCSswptobefnz, GCSswpend, GCScallfin, GCSpause, -1};
 945  int option = states[luaL_checkoption(L, 1, "", statenames)];
 946  if (option == -1) {
 947    lua_pushstring(L, statenames[G(L)->gcstate]);
 948    return 1;
 949  }
 950  else {
 951    global_State *g = G(L);
 952    if (G(L)->gckind == KGC_GEN)
 953      luaL_error(L, "cannot change states in generational mode");
 954    lua_lock(L);
 955    if (option < g->gcstate) {  /* must cross 'pause'? */
 956      luaC_runtilstate(L, bitmask(GCSpause));  /* run until pause */
 957    }
 958    luaC_runtilstate(L, bitmask(option));
 959    lua_assert(G(L)->gcstate == option);
 960    lua_unlock(L);
 961    return 0;
 962  }
 963}
 964
 965
 966static int hash_query (lua_State *L) {
 967  if (lua_isnone(L, 2)) {
 968    luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected");
 969    lua_pushinteger(L, tsvalue(obj_at(L, 1))->hash);
 970  }
 971  else {
 972    TValue *o = obj_at(L, 1);
 973    Table *t;
 974    luaL_checktype(L, 2, LUA_TTABLE);
 975    t = hvalue(obj_at(L, 2));
 976    lua_pushinteger(L, luaH_mainposition(t, o) - t->node);
 977  }
 978  return 1;
 979}
 980
 981
 982static int stacklevel (lua_State *L) {
 983  unsigned long a = 0;
 984  lua_pushinteger(L, (L->top.p - L->stack.p));
 985  lua_pushinteger(L, stacksize(L));
 986  lua_pushinteger(L, L->nCcalls);
 987  lua_pushinteger(L, L->nci);
 988  lua_pushinteger(L, (unsigned long)&a);
 989  return 5;
 990}
 991
 992
 993static int table_query (lua_State *L) {
 994  const Table *t;
 995  int i = cast_int(luaL_optinteger(L, 2, -1));
 996  unsigned int asize;
 997  luaL_checktype(L, 1, LUA_TTABLE);
 998  t = hvalue(obj_at(L, 1));
 999  asize = luaH_realasize(t);
1000  if (i == -1) {
1001    lua_pushinteger(L, asize);
1002    lua_pushinteger(L, allocsizenode(t));
1003    lua_pushinteger(L, isdummy(t) ? 0 : t->lastfree - t->node);
1004    lua_pushinteger(L, t->alimit);
1005    return 4;
1006  }
1007  else if ((unsigned int)i < asize) {
1008    lua_pushinteger(L, i);
1009    pushobject(L, &t->array[i]);
1010    lua_pushnil(L);
1011  }
1012  else if ((i -= asize) < sizenode(t)) {
1013    TValue k;
1014    getnodekey(L, &k, gnode(t, i));
1015    if (!isempty(gval(gnode(t, i))) ||
1016        ttisnil(&k) ||
1017        ttisnumber(&k)) {
1018      pushobject(L, &k);
1019    }
1020    else
1021      lua_pushliteral(L, "<undef>");
1022    pushobject(L, gval(gnode(t, i)));
1023    if (gnext(&t->node[i]) != 0)
1024      lua_pushinteger(L, gnext(&t->node[i]));
1025    else
1026      lua_pushnil(L);
1027  }
1028  return 3;
1029}
1030
1031
1032static int string_query (lua_State *L) {
1033  stringtable *tb = &G(L)->strt;
1034  int s = cast_int(luaL_optinteger(L, 1, 0)) - 1;
1035  if (s == -1) {
1036    lua_pushinteger(L ,tb->size);
1037    lua_pushinteger(L ,tb->nuse);
1038    return 2;
1039  }
1040  else if (s < tb->size) {
1041    TString *ts;
1042    int n = 0;
1043    for (ts = tb->hash[s]; ts != NULL; ts = ts->u.hnext) {
1044      setsvalue2s(L, L->top.p, ts);
1045      api_incr_top(L);
1046      n++;
1047    }
1048    return n;
1049  }
1050  else return 0;
1051}
1052
1053
1054static int tref (lua_State *L) {
1055  int level = lua_gettop(L);
1056  luaL_checkany(L, 1);
1057  lua_pushvalue(L, 1);
1058  lua_pushinteger(L, luaL_ref(L, LUA_REGISTRYINDEX));
1059  cast_void(level);  /* to avoid warnings */
1060  lua_assert(lua_gettop(L) == level+1);  /* +1 for result */
1061  return 1;
1062}
1063
1064static int getref (lua_State *L) {
1065  int level = lua_gettop(L);
1066  lua_rawgeti(L, LUA_REGISTRYINDEX, luaL_checkinteger(L, 1));
1067  cast_void(level);  /* to avoid warnings */
1068  lua_assert(lua_gettop(L) == level+1);
1069  return 1;
1070}
1071
1072static int unref (lua_State *L) {
1073  int level = lua_gettop(L);
1074  luaL_unref(L, LUA_REGISTRYINDEX, cast_int(luaL_checkinteger(L, 1)));
1075  cast_void(level);  /* to avoid warnings */
1076  lua_assert(lua_gettop(L) == level);
1077  return 0;
1078}
1079
1080
1081static int upvalue (lua_State *L) {
1082  int n = cast_int(luaL_checkinteger(L, 2));
1083  luaL_checktype(L, 1, LUA_TFUNCTION);
1084  if (lua_isnone(L, 3)) {
1085    const char *name = lua_getupvalue(L, 1, n);
1086    if (name == NULL) return 0;
1087    lua_pushstring(L, name);
1088    return 2;
1089  }
1090  else {
1091    const char *name = lua_setupvalue(L, 1, n);
1092    lua_pushstring(L, name);
1093    return 1;
1094  }
1095}
1096
1097
1098static int newuserdata (lua_State *L) {
1099  size_t size = cast_sizet(luaL_optinteger(L, 1, 0));
1100  int nuv = luaL_optinteger(L, 2, 0);
1101  char *p = cast_charp(lua_newuserdatauv(L, size, nuv));
1102  while (size--) *p++ = '\0';
1103  return 1;
1104}
1105
1106
1107static int pushuserdata (lua_State *L) {
1108  lua_Integer u = luaL_checkinteger(L, 1);
1109  lua_pushlightuserdata(L, cast_voidp(cast_sizet(u)));
1110  return 1;
1111}
1112
1113
1114static int udataval (lua_State *L) {
1115  lua_pushinteger(L, cast(long, lua_touserdata(L, 1)));
1116  return 1;
1117}
1118
1119
1120static int doonnewstack (lua_State *L) {
1121  lua_State *L1 = lua_newthread(L);
1122  size_t l;
1123  const char *s = luaL_checklstring(L, 1, &l);
1124  int status = luaL_loadbuffer(L1, s, l, s);
1125  if (status == LUA_OK)
1126    status = lua_pcall(L1, 0, 0, 0);
1127  lua_pushinteger(L, status);
1128  return 1;
1129}
1130
1131
1132static int s2d (lua_State *L) {
1133  lua_pushnumber(L, cast_num(*cast(const double *, luaL_checkstring(L, 1))));
1134  return 1;
1135}
1136
1137
1138static int d2s (lua_State *L) {
1139  double d = cast(double, luaL_checknumber(L, 1));
1140  lua_pushlstring(L, cast_charp(&d), sizeof(d));
1141  return 1;
1142}
1143
1144
1145static int num2int (lua_State *L) {
1146  lua_pushinteger(L, lua_tointeger(L, 1));
1147  return 1;
1148}
1149
1150
1151static int newstate (lua_State *L) {
1152  void *ud;
1153  lua_Alloc f = lua_getallocf(L, &ud);
1154  lua_State *L1 = lua_newstate(f, ud);
1155  if (L1) {
1156    lua_atpanic(L1, tpanic);
1157    lua_pushlightuserdata(L, L1);
1158  }
1159  else
1160    lua_pushnil(L);
1161  return 1;
1162}
1163
1164
1165static lua_State *getstate (lua_State *L) {
1166  lua_State *L1 = cast(lua_State *, lua_touserdata(L, 1));
1167  luaL_argcheck(L, L1 != NULL, 1, "state expected");
1168  return L1;
1169}
1170
1171
1172static int loadlib (lua_State *L) {
1173  static const luaL_Reg libs[] = {
1174    {LUA_GNAME, luaopen_base},
1175    {"coroutine", luaopen_coroutine},
1176    {"debug", luaopen_debug},
1177    {"io", luaopen_io},
1178    {"os", luaopen_os},
1179    {"math", luaopen_math},
1180    {"string", luaopen_string},
1181    {"table", luaopen_table},
1182    {"T", luaB_opentests},
1183    {NULL, NULL}
1184  };
1185  lua_State *L1 = getstate(L);
1186  int i;
1187  luaL_requiref(L1, "package", luaopen_package, 0);
1188  lua_assert(lua_type(L1, -1) == LUA_TTABLE);
1189  /* 'requiref' should not reload module already loaded... */
1190  luaL_requiref(L1, "package", NULL, 1);  /* seg. fault if it reloads */
1191  /* ...but should return the same module */
1192  lua_assert(lua_compare(L1, -1, -2, LUA_OPEQ));
1193  luaL_getsubtable(L1, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE);
1194  for (i = 0; libs[i].name; i++) {
1195    lua_pushcfunction(L1, libs[i].func);
1196    lua_setfield(L1, -2, libs[i].name);
1197  }
1198  return 0;
1199}
1200
1201static int closestate (lua_State *L) {
1202  lua_State *L1 = getstate(L);
1203  lua_close(L1);
1204  return 0;
1205}
1206
1207static int doremote (lua_State *L) {
1208  lua_State *L1 = getstate(L);
1209  size_t lcode;
1210  const char *code = luaL_checklstring(L, 2, &lcode);
1211  int status;
1212  lua_settop(L1, 0);
1213  status = luaL_loadbuffer(L1, code, lcode, code);
1214  if (status == LUA_OK)
1215    status = lua_pcall(L1, 0, LUA_MULTRET, 0);
1216  if (status != LUA_OK) {
1217    lua_pushnil(L);
1218    lua_pushstring(L, lua_tostring(L1, -1));
1219    lua_pushinteger(L, status);
1220    return 3;
1221  }
1222  else {
1223    int i = 0;
1224    while (!lua_isnone(L1, ++i))
1225      lua_pushstring(L, lua_tostring(L1, i));
1226    lua_pop(L1, i-1);
1227    return i-1;
1228  }
1229}
1230
1231
1232static int log2_aux (lua_State *L) {
1233  unsigned int x = (unsigned int)luaL_checkinteger(L, 1);
1234  lua_pushinteger(L, luaO_ceillog2(x));
1235  return 1;
1236}
1237
1238
1239struct Aux { jmp_buf jb; const char *paniccode; lua_State *L; };
1240
1241/*
1242** does a long-jump back to "main program".
1243*/
1244static int panicback (lua_State *L) {
1245  struct Aux *b;
1246  lua_checkstack(L, 1);  /* open space for 'Aux' struct */
1247  lua_getfield(L, LUA_REGISTRYINDEX, "_jmpbuf");  /* get 'Aux' struct */
1248  b = (struct Aux *)lua_touserdata(L, -1);
1249  lua_pop(L, 1);  /* remove 'Aux' struct */
1250  runC(b->L, L, b->paniccode);  /* run optional panic code */
1251  longjmp(b->jb, 1);
1252  return 1;  /* to avoid warnings */
1253}
1254
1255static int checkpanic (lua_State *L) {
1256  struct Aux b;
1257  void *ud;
1258  lua_State *L1;
1259  const char *code = luaL_checkstring(L, 1);
1260  lua_Alloc f = lua_getallocf(L, &ud);
1261  b.paniccode = luaL_optstring(L, 2, "");
1262  b.L = L;
1263  L1 = lua_newstate(f, ud);  /* create new state */
1264  if (L1 == NULL) {  /* error? */
1265    lua_pushnil(L);
1266    return 1;
1267  }
1268  lua_atpanic(L1, panicback);  /* set its panic function */
1269  lua_pushlightuserdata(L1, &b);
1270  lua_setfield(L1, LUA_REGISTRYINDEX, "_jmpbuf");  /* store 'Aux' struct */
1271  if (setjmp(b.jb) == 0) {  /* set jump buffer */
1272    runC(L, L1, code);  /* run code unprotected */
1273    lua_pushliteral(L, "no errors");
1274  }
1275  else {  /* error handling */
1276    /* move error message to original state */
1277    lua_pushstring(L, lua_tostring(L1, -1));
1278  }
1279  lua_close(L1);
1280  return 1;
1281}
1282
1283
1284
1285/*
1286** {====================================================================
1287** function to test the API with C. It interprets a kind of assembler
1288** language with calls to the API, so the test can be driven by Lua code
1289** =====================================================================
1290*/
1291
1292
1293static void sethookaux (lua_State *L, int mask, int count, const char *code);
1294
1295static const char *const delimits = " \t\n,;";
1296
1297static void skip (const char **pc) {
1298  for (;;) {
1299    if (**pc != '\0' && strchr(delimits, **pc)) (*pc)++;
1300    else if (**pc == '#') {  /* comment? */
1301      while (**pc != '\n' && **pc != '\0') (*pc)++;  /* until end-of-line */
1302    }
1303    else break;
1304  }
1305}
1306
1307static int getnum_aux (lua_State *L, lua_State *L1, const char **pc) {
1308  int res = 0;
1309  int sig = 1;
1310  skip(pc);
1311  if (**pc == '.') {
1312    res = cast_int(lua_tointeger(L1, -1));
1313    lua_pop(L1, 1);
1314    (*pc)++;
1315    return res;
1316  }
1317  else if (**pc == '*') {
1318    res = lua_gettop(L1);
1319    (*pc)++;
1320    return res;
1321  }
1322  else if (**pc == '-') {
1323    sig = -1;
1324    (*pc)++;
1325  }
1326  if (!lisdigit(cast_uchar(**pc)))
1327    luaL_error(L, "number expected (%s)", *pc);
1328  while (lisdigit(cast_uchar(**pc))) res = res*10 + (*(*pc)++) - '0';
1329  return sig*res;
1330}
1331
1332static const char *getstring_aux (lua_State *L, char *buff, const char **pc) {
1333  int i = 0;
1334  skip(pc);
1335  if (**pc == '"' || **pc == '\'') {  /* quoted string? */
1336    int quote = *(*pc)++;
1337    while (**pc != quote) {
1338      if (**pc == '\0') luaL_error(L, "unfinished string in C script");
1339      buff[i++] = *(*pc)++;
1340    }
1341    (*pc)++;
1342  }
1343  else {
1344    while (**pc != '\0' && !strchr(delimits, **pc))
1345      buff[i++] = *(*pc)++;
1346  }
1347  buff[i] = '\0';
1348  return buff;
1349}
1350
1351
1352static int getindex_aux (lua_State *L, lua_State *L1, const char **pc) {
1353  skip(pc);
1354  switch (*(*pc)++) {
1355    case 'R': return LUA_REGISTRYINDEX;
1356    case 'G': return luaL_error(L, "deprecated index 'G'");
1357    case 'U': return lua_upvalueindex(getnum_aux(L, L1, pc));
1358    default: (*pc)--; return getnum_aux(L, L1, pc);
1359  }
1360}
1361
1362
1363static const char *const statcodes[] = {"OK", "YIELD", "ERRRUN",
1364    "ERRSYNTAX", MEMERRMSG, "ERRGCMM", "ERRERR"};
1365
1366/*
1367** Avoid these stat codes from being collected, to avoid possible
1368** memory error when pushing them.
1369*/
1370static void regcodes (lua_State *L) {
1371  unsigned int i;
1372  for (i = 0; i < sizeof(statcodes) / sizeof(statcodes[0]); i++) {
1373    lua_pushboolean(L, 1);
1374    lua_setfield(L, LUA_REGISTRYINDEX, statcodes[i]);
1375  }
1376}
1377
1378
1379#define EQ(s1)	(strcmp(s1, inst) == 0)
1380
1381#define getnum		(getnum_aux(L, L1, &pc))
1382#define getstring	(getstring_aux(L, buff, &pc))
1383#define getindex	(getindex_aux(L, L1, &pc))
1384
1385
1386static int testC (lua_State *L);
1387static int Cfunck (lua_State *L, int status, lua_KContext ctx);
1388
1389/*
1390** arithmetic operation encoding for 'arith' instruction
1391** LUA_OPIDIV  -> \
1392** LUA_OPSHL   -> <
1393** LUA_OPSHR   -> >
1394** LUA_OPUNM   -> _
1395** LUA_OPBNOT  -> !
1396*/
1397static const char ops[] = "+-*%^/\\&|~<>_!";
1398
1399static int runC (lua_State *L, lua_State *L1, const char *pc) {
1400  char buff[300];
1401  int status = 0;
1402  if (pc == NULL) return luaL_error(L, "attempt to runC null script");
1403  for (;;) {
1404    const char *inst = getstring;
1405    if EQ("") return 0;
1406    else if EQ("absindex") {
1407      lua_pushnumber(L1, lua_absindex(L1, getindex));
1408    }
1409    else if EQ("append") {
1410      int t = getindex;
1411      int i = lua_rawlen(L1, t);
1412      lua_rawseti(L1, t, i + 1);
1413    }
1414    else if EQ("arith") {
1415      int op;
1416      skip(&pc);
1417      op = strchr(ops, *pc++) - ops;
1418      lua_arith(L1, op);
1419    }
1420    else if EQ("call") {
1421      int narg = getnum;
1422      int nres = getnum;
1423      lua_call(L1, narg, nres);
1424    }
1425    else if EQ("callk") {
1426      int narg = getnum;
1427      int nres = getnum;
1428      int i = getindex;
1429      lua_callk(L1, narg, nres, i, Cfunck);
1430    }
1431    else if EQ("checkstack") {
1432      int sz = getnum;
1433      const char *msg = getstring;
1434      if (*msg == '\0')
1435        msg = NULL;  /* to test 'luaL_checkstack' with no message */
1436      luaL_checkstack(L1, sz, msg);
1437    }
1438    else if EQ("rawcheckstack") {
1439      int sz = getnum;
1440      lua_pushboolean(L1, lua_checkstack(L1, sz));
1441    }
1442    else if EQ("compare") {
1443      const char *opt = getstring;  /* EQ, LT, or LE */
1444      int op = (opt[0] == 'E') ? LUA_OPEQ
1445                               : (opt[1] == 'T') ? LUA_OPLT : LUA_OPLE;
1446      int a = getindex;
1447      int b = getindex;
1448      lua_pushboolean(L1, lua_compare(L1, a, b, op));
1449    }
1450    else if EQ("concat") {
1451      lua_concat(L1, getnum);
1452    }
1453    else if EQ("copy") {
1454      int f = getindex;
1455      lua_copy(L1, f, getindex);
1456    }
1457    else if EQ("func2num") {
1458      lua_CFunction func = lua_tocfunction(L1, getindex);
1459      lua_pushnumber(L1, cast_sizet(func));
1460    }
1461    else if EQ("getfield") {
1462      int t = getindex;
1463      lua_getfield(L1, t, getstring);
1464    }
1465    else if EQ("getglobal") {
1466      lua_getglobal(L1, getstring);
1467    }
1468    else if EQ("getmetatable") {
1469      if (lua_getmetatable(L1, getindex) == 0)
1470        lua_pushnil(L1);
1471    }
1472    else if EQ("gettable") {
1473      lua_gettable(L1, getindex);
1474    }
1475    else if EQ("gettop") {
1476      lua_pushinteger(L1, lua_gettop(L1));
1477    }
1478    else if EQ("gsub") {
1479      int a = getnum; int b = getnum; int c = getnum;
1480      luaL_gsub(L1, lua_tostring(L1, a),
1481                    lua_tostring(L1, b),
1482                    lua_tostring(L1, c));
1483    }
1484    else if EQ("insert") {
1485      lua_insert(L1, getnum);
1486    }
1487    else if EQ("iscfunction") {
1488      lua_pushboolean(L1, lua_iscfunction(L1, getindex));
1489    }
1490    else if EQ("isfunction") {
1491      lua_pushboolean(L1, lua_isfunction(L1, getindex));
1492    }
1493    else if EQ("isnil") {
1494      lua_pushboolean(L1, lua_isnil(L1, getindex));
1495    }
1496    else if EQ("isnull") {
1497      lua_pushboolean(L1, lua_isnone(L1, getindex));
1498    }
1499    else if EQ("isnumber") {
1500      lua_pushboolean(L1, lua_isnumber(L1, getindex));
1501    }
1502    else if EQ("isstring") {
1503      lua_pushboolean(L1, lua_isstring(L1, getindex));
1504    }
1505    else if EQ("istable") {
1506      lua_pushboolean(L1, lua_istable(L1, getindex));
1507    }
1508    else if EQ("isudataval") {
1509      lua_pushboolean(L1, lua_islightuserdata(L1, getindex));
1510    }
1511    else if EQ("isuserdata") {
1512      lua_pushboolean(L1, lua_isuserdata(L1, getindex));
1513    }
1514    else if EQ("len") {
1515      lua_len(L1, getindex);
1516    }
1517    else if EQ("Llen") {
1518      lua_pushinteger(L1, luaL_len(L1, getindex));
1519    }
1520    else if EQ("loadfile") {
1521      luaL_loadfile(L1, luaL_checkstring(L1, getnum));
1522    }
1523    else if EQ("loadstring") {
1524      const char *s = luaL_checkstring(L1, getnum);
1525      luaL_loadstring(L1, s);
1526    }
1527    else if EQ("newmetatable") {
1528      lua_pushboolean(L1, luaL_newmetatable(L1, getstring));
1529    }
1530    else if EQ("newtable") {
1531      lua_newtable(L1);
1532    }
1533    else if EQ("newthread") {
1534      lua_newthread(L1);
1535    }
1536    else if EQ("resetthread") {
1537      lua_pushinteger(L1, lua_resetthread(L1));  /* deprecated */
1538    }
1539    else if EQ("newuserdata") {
1540      lua_newuserdata(L1, getnum);
1541    }
1542    else if EQ("next") {
1543      lua_next(L1, -2);
1544    }
1545    else if EQ("objsize") {
1546      lua_pushinteger(L1, lua_rawlen(L1, getindex));
1547    }
1548    else if EQ("pcall") {
1549      int narg = getnum;
1550      int nres = getnum;
1551      status = lua_pcall(L1, narg, nres, getnum);
1552    }
1553    else if EQ("pcallk") {
1554      int narg = getnum;
1555      int nres = getnum;
1556      int i = getindex;
1557      status = lua_pcallk(L1, narg, nres, 0, i, Cfunck);
1558    }
1559    else if EQ("pop") {
1560      lua_pop(L1, getnum);
1561    }
1562    else if EQ("printstack") {
1563      int n = getnum;
1564      if (n != 0) {
1565        printf("%s\n", luaL_tolstring(L1, n, NULL));
1566        lua_pop(L1, 1);
1567      }
1568      else printstack(L1);
1569    }
1570    else if EQ("print") {
1571      const char *msg = getstring;
1572      printf("%s\n", msg);
1573    }
1574    else if EQ("warningC") {
1575      const char *msg = getstring;
1576      lua_warning(L1, msg, 1);
1577    }
1578    else if EQ("warning") {
1579      const char *msg = getstring;
1580      lua_warning(L1, msg, 0);
1581    }
1582    else if EQ("pushbool") {
1583      lua_pushboolean(L1, getnum);
1584    }
1585    else if EQ("pushcclosure") {
1586      lua_pushcclosure(L1, testC, getnum);
1587    }
1588    else if EQ("pushint") {
1589      lua_pushinteger(L1, getnum);
1590    }
1591    else if EQ("pushnil") {
1592      lua_pushnil(L1);
1593    }
1594    else if EQ("pushnum") {
1595      lua_pushnumber(L1, (lua_Number)getnum);
1596    }
1597    else if EQ("pushstatus") {
1598      lua_pushstring(L1, statcodes[status]);
1599    }
1600    else if EQ("pushstring") {
1601      lua_pushstring(L1, getstring);
1602    }
1603    else if EQ("pushupvalueindex") {
1604      lua_pushinteger(L1, lua_upvalueindex(getnum));
1605    }
1606    else if EQ("pushvalue") {
1607      lua_pushvalue(L1, getindex);
1608    }
1609    else if EQ("pushfstringI") {
1610      lua_pushfstring(L1, lua_tostring(L, -2), (int)lua_tointeger(L, -1));
1611    }
1612    else if EQ("pushfstringS") {
1613      lua_pushfstring(L1, lua_tostring(L, -2), lua_tostring(L, -1));
1614    }
1615    else if EQ("pushfstringP") {
1616      lua_pushfstring(L1, lua_tostring(L, -2), lua_topointer(L, -1));
1617    }
1618    else if EQ("rawget") {
1619      int t = getindex;
1620      lua_rawget(L1, t);
1621    }
1622    else if EQ("rawgeti") {
1623      int t = getindex;
1624      lua_rawgeti(L1, t, getnum);
1625    }
1626    else if EQ("rawgetp") {
1627      int t = getindex;
1628      lua_rawgetp(L1, t, cast_voidp(cast_sizet(getnum)));
1629    }
1630    else if EQ("rawset") {
1631      int t = getindex;
1632      lua_rawset(L1, t);
1633    }
1634    else if EQ("rawseti") {
1635      int t = getindex;
1636      lua_rawseti(L1, t, getnum);
1637    }
1638    else if EQ("rawsetp") {
1639      int t = getindex;
1640      lua_rawsetp(L1, t, cast_voidp(cast_sizet(getnum)));
1641    }
1642    else if EQ("remove") {
1643      lua_remove(L1, getnum);
1644    }
1645    else if EQ("replace") {
1646      lua_replace(L1, getindex);
1647    }
1648    else if EQ("resume") {
1649      int i = getindex;
1650      int nres;
1651      status = lua_resume(lua_tothread(L1, i), L, getnum, &nres);
1652    }
1653    else if EQ("traceback") {
1654      const char *msg = getstring;
1655      int level = getnum;
1656      luaL_traceback(L1, L1, msg, level);
1657    }
1658    else if EQ("return") {
1659      int n = getnum;
1660      if (L1 != L) {
1661        int i;
1662        for (i = 0; i < n; i++) {
1663          int idx = -(n - i);
1664          switch (lua_type(L1, idx)) {
1665            case LUA_TBOOLEAN:
1666              lua_pushboolean(L, lua_toboolean(L1, idx));
1667              break;
1668            default:
1669              lua_pushstring(L, lua_tostring(L1, idx));
1670              break;
1671          }
1672        }
1673      }
1674      return n;
1675    }
1676    else if EQ("rotate") {
1677      int i = getindex;
1678      lua_rotate(L1, i, getnum);
1679    }
1680    else if EQ("setfield") {
1681      int t = getindex;
1682      const char *s = getstring;
1683      lua_setfield(L1, t, s);
1684    }
1685    else if EQ("seti") {
1686      int t = getindex;
1687      lua_seti(L1, t, getnum);
1688    }
1689    else if EQ("setglobal") {
1690      const char *s = getstring;
1691      lua_setglobal(L1, s);
1692    }
1693    else if EQ("sethook") {
1694      int mask = getnum;
1695      int count = getnum;
1696      const char *s = getstring;
1697      sethookaux(L1, mask, count, s);
1698    }
1699    else if EQ("setmetatable") {
1700      int idx = getindex;
1701      lua_setmetatable(L1, idx);
1702    }
1703    else if EQ("settable") {
1704      lua_settable(L1, getindex);
1705    }
1706    else if EQ("settop") {
1707      lua_settop(L1, getnum);
1708    }
1709    else if EQ("testudata") {
1710      int i = getindex;
1711      lua_pushboolean(L1, luaL_testudata(L1, i, getstring) != NULL);
1712    }
1713    else if EQ("error") {
1714      lua_error(L1);
1715    }
1716    else if EQ("abort") {
1717      abort();
1718    }
1719    else if EQ("throw") {
1720#if defined(__cplusplus)
1721static struct X { int x; } x;
1722      throw x;
1723#else
1724      luaL_error(L1, "C++");
1725#endif
1726      break;
1727    }
1728    else if EQ("tobool") {
1729      lua_pushboolean(L1, lua_toboolean(L1, getindex));
1730    }
1731    else if EQ("tocfunction") {
1732      lua_pushcfunction(L1, lua_tocfunction(L1, getindex));
1733    }
1734    else if EQ("tointeger") {
1735      lua_pushinteger(L1, lua_tointeger(L1, getindex));
1736    }
1737    else if EQ("tonumber") {
1738      lua_pushnumber(L1, lua_tonumber(L1, getindex));
1739    }
1740    else if EQ("topointer") {
1741      lua_pushlightuserdata(L1, cast_voidp(lua_topointer(L1, getindex)));
1742    }
1743    else if EQ("touserdata") {
1744      lua_pushlightuserdata(L1, lua_touserdata(L1, getindex));
1745    }
1746    else if EQ("tostring") {
1747      const char *s = lua_tostring(L1, getindex);
1748      const char *s1 = lua_pushstring(L1, s);
1749      cast_void(s1);  /* to avoid warnings */
1750      lua_longassert((s == NULL && s1 == NULL) || strcmp(s, s1) == 0);
1751    }
1752    else if EQ("Ltolstring") {
1753      luaL_tolstring(L1, getindex, NULL);
1754    }
1755    else if EQ("type") {
1756      lua_pushstring(L1, luaL_typename(L1, getnum));
1757    }
1758    else if EQ("xmove") {
1759      int f = getindex;
1760      int t = getindex;
1761      lua_State *fs = (f == 0) ? L1 : lua_tothread(L1, f);
1762      lua_State *ts = (t == 0) ? L1 : lua_tothread(L1, t);
1763      int n = getnum;
1764      if (n == 0) n = lua_gettop(fs);
1765      lua_xmove(fs, ts, n);
1766    }
1767    else if EQ("isyieldable") {
1768      lua_pushboolean(L1, lua_isyieldable(lua_tothread(L1, getindex)));
1769    }
1770    else if EQ("yield") {
1771      return lua_yield(L1, getnum);
1772    }
1773    else if EQ("yieldk") {
1774      int nres = getnum;
1775      int i = getindex;
1776      return lua_yieldk(L1, nres, i, Cfunck);
1777    }
1778    else if EQ("toclose") {
1779      lua_toclose(L1, getnum);
1780    }
1781    else if EQ("closeslot") {
1782      lua_closeslot(L1, getnum);
1783    }
1784    else luaL_error(L, "unknown instruction %s", buff);
1785  }
1786  return 0;
1787}
1788
1789
1790static int testC (lua_State *L) {
1791  lua_State *L1;
1792  const char *pc;
1793  if (lua_isuserdata(L, 1)) {
1794    L1 = getstate(L);
1795    pc = luaL_checkstring(L, 2);
1796  }
1797  else if (lua_isthread(L, 1)) {
1798    L1 = lua_tothread(L, 1);
1799    pc = luaL_checkstring(L, 2);
1800  }
1801  else {
1802    L1 = L;
1803    pc = luaL_checkstring(L, 1);
1804  }
1805  return runC(L, L1, pc);
1806}
1807
1808
1809static int Cfunc (lua_State *L) {
1810  return runC(L, L, lua_tostring(L, lua_upvalueindex(1)));
1811}
1812
1813
1814static int Cfunck (lua_State *L, int status, lua_KContext ctx) {
1815  lua_pushstring(L, statcodes[status]);
1816  lua_setglobal(L, "status");
1817  lua_pushinteger(L, ctx);
1818  lua_setglobal(L, "ctx");
1819  return runC(L, L, lua_tostring(L, ctx));
1820}
1821
1822
1823static int makeCfunc (lua_State *L) {
1824  luaL_checkstring(L, 1);
1825  lua_pushcclosure(L, Cfunc, lua_gettop(L));
1826  return 1;
1827}
1828
1829
1830/* }====================================================== */
1831
1832
1833/*
1834** {======================================================
1835** tests for C hooks
1836** =======================================================
1837*/
1838
1839/*
1840** C hook that runs the C script stored in registry.C_HOOK[L]
1841*/
1842static void Chook (lua_State *L, lua_Debug *ar) {
1843  const char *scpt;
1844  const char *const events [] = {"call", "ret", "line", "count", "tailcall"};
1845  lua_getfield(L, LUA_REGISTRYINDEX, "C_HOOK");
1846  lua_pushlightuserdata(L, L);
1847  lua_gettable(L, -2);  /* get C_HOOK[L] (script saved by sethookaux) */
1848  scpt = lua_tostring(L, -1);  /* not very religious (string will be popped) */
1849  lua_pop(L, 2);  /* remove C_HOOK and script */
1850  lua_pushstring(L, events[ar->event]);  /* may be used by script */
1851  lua_pushinteger(L, ar->currentline);  /* may be used by script */
1852  runC(L, L, scpt);  /* run script from C_HOOK[L] */
1853}
1854
1855
1856/*
1857** sets 'registry.C_HOOK[L] = scpt' and sets 'Chook' as a hook
1858*/
1859static void sethookaux (lua_State *L, int mask, int count, const char *scpt) {
1860  if (*scpt == '\0') {  /* no script? */
1861    lua_sethook(L, NULL, 0, 0);  /* turn off hooks */
1862    return;
1863  }
1864  lua_getfield(L, LUA_REGISTRYINDEX, "C_HOOK");  /* get C_HOOK table */
1865  if (!lua_istable(L, -1)) {  /* no hook table? */
1866    lua_pop(L, 1);  /* remove previous value */
1867    lua_newtable(L);  /* create new C_HOOK table */
1868    lua_pushvalue(L, -1);
1869    lua_setfield(L, LUA_REGISTRYINDEX, "C_HOOK");  /* register it */
1870  }
1871  lua_pushlightuserdata(L, L);
1872  lua_pushstring(L, scpt);
1873  lua_settable(L, -3);  /* C_HOOK[L] = script */
1874  lua_sethook(L, Chook, mask, count);
1875}
1876
1877
1878static int sethook (lua_State *L) {
1879  if (lua_isnoneornil(L, 1))
1880    lua_sethook(L, NULL, 0, 0);  /* turn off hooks */
1881  else {
1882    const char *scpt = luaL_checkstring(L, 1);
1883    const char *smask = luaL_checkstring(L, 2);
1884    int count = cast_int(luaL_optinteger(L, 3, 0));
1885    int mask = 0;
1886    if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
1887    if (strchr(smask, 'r')) mask |= LUA_MASKRET;
1888    if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
1889    if (count > 0) mask |= LUA_MASKCOUNT;
1890    sethookaux(L, mask, count, scpt);
1891  }
1892  return 0;
1893}
1894
1895
1896static int coresume (lua_State *L) {
1897  int status, nres;
1898  lua_State *co = lua_tothread(L, 1);
1899  luaL_argcheck(L, co, 1, "coroutine expected");
1900  status = lua_resume(co, L, 0, &nres);
1901  if (status != LUA_OK && status != LUA_YIELD) {
1902    lua_pushboolean(L, 0);
1903    lua_insert(L, -2);
1904    return 2;  /* return false + error message */
1905  }
1906  else {
1907    lua_pushboolean(L, 1);
1908    return 1;
1909  }
1910}
1911
1912/* }====================================================== */
1913
1914
1915
1916static const struct luaL_Reg tests_funcs[] = {
1917  {"checkmemory", lua_checkmemory},
1918  {"closestate", closestate},
1919  {"d2s", d2s},
1920  {"doonnewstack", doonnewstack},
1921  {"doremote", doremote},
1922  {"gccolor", gc_color},
1923  {"gcage", gc_age},
1924  {"gcstate", gc_state},
1925  {"pobj", gc_printobj},
1926  {"getref", getref},
1927  {"hash", hash_query},
1928  {"log2", log2_aux},
1929  {"limits", get_limits},
1930  {"listcode", listcode},
1931  {"printcode", printcode},
1932  {"listk", listk},
1933  {"listabslineinfo", listabslineinfo},
1934  {"listlocals", listlocals},
1935  {"loadlib", loadlib},
1936  {"checkpanic", checkpanic},
1937  {"newstate", newstate},
1938  {"newuserdata", newuserdata},
1939  {"num2int", num2int},
1940  {"pushuserdata", pushuserdata},
1941  {"querystr", string_query},
1942  {"querytab", table_query},
1943  {"ref", tref},
1944  {"resume", coresume},
1945  {"s2d", s2d},
1946  {"sethook", sethook},
1947  {"stacklevel", stacklevel},
1948  {"testC", testC},
1949  {"makeCfunc", makeCfunc},
1950  {"totalmem", mem_query},
1951  {"alloccount", alloc_count},
1952  {"allocfailnext", alloc_failnext},
1953  {"trick", settrick},
1954  {"udataval", udataval},
1955  {"unref", unref},
1956  {"upvalue", upvalue},
1957  {NULL, NULL}
1958};
1959
1960
1961static void checkfinalmem (void) {
1962  lua_assert(l_memcontrol.numblocks == 0);
1963  lua_assert(l_memcontrol.total == 0);
1964}
1965
1966
1967int luaB_opentests (lua_State *L) {
1968  void *ud;
1969  lua_Alloc f = lua_getallocf(L, &ud);
1970  lua_atpanic(L, &tpanic);
1971  lua_setwarnf(L, &warnf, L);
1972  lua_pushboolean(L, 0);
1973  lua_setglobal(L, "_WARN");  /* _WARN = false */
1974  regcodes(L);
1975  atexit(checkfinalmem);
1976  lua_assert(f == debug_realloc && ud == cast_voidp(&l_memcontrol));
1977  lua_setallocf(L, f, ud);  /* exercise this function */
1978  luaL_newlib(L, tests_funcs);
1979  return 1;
1980}
1981
1982#endif
1983