From 43a2ee6ea1b7825c1892de614cb38a3fe487a19f Mon Sep 17 00:00:00 2001
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Tue, 16 Sep 1997 16:25:59 -0300
Subject: Stack and Call structure of Lua

---
 ldo.c | 415 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 415 insertions(+)
 create mode 100644 ldo.c

(limited to 'ldo.c')

diff --git a/ldo.c b/ldo.c
new file mode 100644
index 00000000..b272b819
--- /dev/null
+++ b/ldo.c
@@ -0,0 +1,415 @@
+/*
+** $Id: $
+** Stack and Call structure of Lua
+** See Copyright Notice in lua.h
+*/
+
+
+#include <setjmp.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ldo.h"
+#include "lgc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lparser.h"
+#include "ltm.h"
+#include "lua.h"
+#include "luadebug.h"
+#include "lundump.h"
+#include "lvm.h"
+#include "lzio.h"
+
+
+
+#ifndef STACK_LIMIT
+#define STACK_LIMIT     6000
+#endif
+
+
+static TObject initial_stack;
+
+struct Stack luaD_stack = {&initial_stack+1, &initial_stack, &initial_stack};
+
+
+struct C_Lua_Stack luaD_Cstack = {0, 0, 0};
+
+static  jmp_buf *errorJmp = NULL; /* current error recover point */
+
+
+
+
+
+#define STACK_EXTRA 	32
+
+static void initstack (int n)
+{
+  int maxstack = STACK_EXTRA+n;
+  luaD_stack.stack = luaM_newvector(maxstack, TObject);
+  luaD_stack.last = luaD_stack.stack+(maxstack-1);
+  luaD_stack.top = luaD_stack.stack;
+  *(luaD_stack.top++) = initial_stack;
+}
+
+
+void luaD_checkstack (int n)
+{
+  if (luaD_stack.stack == &initial_stack)
+    initstack(n);
+  else if (luaD_stack.last-luaD_stack.top <= n) {
+    static int limit = STACK_LIMIT;
+    StkId top = luaD_stack.top-luaD_stack.stack;
+    int stacksize = (luaD_stack.last-luaD_stack.stack)+1+STACK_EXTRA+n;
+    luaD_stack.stack = luaM_reallocvector(luaD_stack.stack, stacksize,TObject);
+    luaD_stack.last = luaD_stack.stack+(stacksize-1);
+    luaD_stack.top = luaD_stack.stack + top;
+    if (stacksize >= limit) {
+      limit = stacksize+STACK_EXTRA;  /* extra space to run error handler */
+      if (lua_stackedfunction(100) == LUA_NOOBJECT) {
+        /* less than 100 functions on the stack: cannot be recursive loop */
+        lua_error("Lua2C - C2Lua overflow");
+      }
+      else
+        lua_error(stackEM);
+    }
+  }
+}
+
+
+
+/*
+** Adjust stack. Set top to the given value, pushing NILs if needed.
+*/
+void luaD_adjusttop (StkId newtop)
+{
+  int diff = newtop-(luaD_stack.top-luaD_stack.stack);
+  if (diff <= 0)
+    luaD_stack.top += diff;
+  else {
+    luaD_checkstack(diff);
+    while (diff--)
+      ttype(luaD_stack.top++) = LUA_T_NIL;
+  }
+}
+
+
+/*
+** Open a hole below "nelems" from the luaD_stack.top.
+*/
+void luaD_openstack (int nelems)
+{
+  int i;
+  for (i=0; i<nelems; i++)
+    *(luaD_stack.top-i) = *(luaD_stack.top-i-1);
+  incr_top;
+}
+
+
+void luaD_lineHook (int line)
+{
+  struct C_Lua_Stack oldCLS = luaD_Cstack;
+  StkId old_top = luaD_Cstack.lua2C = luaD_Cstack.base = luaD_stack.top-luaD_stack.stack;
+  luaD_Cstack.num = 0;
+  (*lua_linehook)(line);
+  luaD_stack.top = luaD_stack.stack+old_top;
+  luaD_Cstack = oldCLS;
+}
+
+
+void luaD_callHook (StkId base, lua_Type type, int isreturn)
+{
+  struct C_Lua_Stack oldCLS = luaD_Cstack;
+  StkId old_top = luaD_Cstack.lua2C = luaD_Cstack.base = luaD_stack.top-luaD_stack.stack;
+  luaD_Cstack.num = 0;
+  if (isreturn)
+    (*lua_callhook)(LUA_NOOBJECT, "(return)", 0);
+  else {
+    TObject *f = luaD_stack.stack+base-1;
+    if (type == LUA_T_MARK)
+      (*lua_callhook)(Ref(f), f->value.tf->fileName->str,
+                      f->value.tf->lineDefined);
+    else
+      (*lua_callhook)(Ref(f), "(C)", -1);
+  }
+  luaD_stack.top = luaD_stack.stack+old_top;
+  luaD_Cstack = oldCLS;
+}
+
+
+/*
+** Call a C function. luaD_Cstack.base will point to the luaD_stack.top of the luaD_stack.stack,
+** and luaD_Cstack.num is the number of parameters. Returns an index
+** to the first result from C.
+*/
+static StkId callC (lua_CFunction func, StkId base)
+{
+  struct C_Lua_Stack oldCLS = luaD_Cstack;
+  StkId firstResult;
+  luaD_Cstack.num = (luaD_stack.top-luaD_stack.stack) - base;
+  /* incorporate parameters on the luaD_stack.stack */
+  luaD_Cstack.lua2C = base;
+  luaD_Cstack.base = base+luaD_Cstack.num;  /* == luaD_stack.top-luaD_stack.stack */
+  if (lua_callhook)
+    luaD_callHook(base, LUA_T_CMARK, 0);
+  (*func)();
+  if (lua_callhook)  /* func may have changed lua_callhook */
+    luaD_callHook(base, LUA_T_CMARK, 1);
+  firstResult = luaD_Cstack.base;
+  luaD_Cstack = oldCLS;
+  return firstResult;
+}
+
+
+void luaD_callTM (TObject *f, int nParams, int nResults)
+{
+  luaD_openstack(nParams);
+  *(luaD_stack.top-nParams-1) = *f;
+  luaD_call((luaD_stack.top-luaD_stack.stack)-nParams, nResults);
+}
+
+
+/*
+** Call a function (C or Lua). The parameters must be on the luaD_stack.stack,
+** between [luaD_stack.stack+base,luaD_stack.top). The function to be called is at luaD_stack.stack+base-1.
+** When returns, the results are on the luaD_stack.stack, between [luaD_stack.stack+base-1,luaD_stack.top).
+** The number of results is nResults, unless nResults=MULT_RET.
+*/
+void luaD_call (StkId base, int nResults)
+{
+  StkId firstResult;
+  TObject *func = luaD_stack.stack+base-1;
+  int i;
+  if (ttype(func) == LUA_T_CFUNCTION) {
+    ttype(func) = LUA_T_CMARK;
+    firstResult = callC(fvalue(func), base);
+  }
+  else if (ttype(func) == LUA_T_FUNCTION) {
+    ttype(func) = LUA_T_MARK;
+    firstResult = luaV_execute(func->value.cl, base);
+  }
+  else { /* func is not a function */
+    /* Check the tag method for invalid functions */
+    TObject *im = luaT_getimbyObj(func, IM_FUNCTION);
+    if (ttype(im) == LUA_T_NIL)
+      lua_error("call expression not a function");
+    luaD_callTM(im, (luaD_stack.top-luaD_stack.stack)-(base-1), nResults);
+    return;
+  }
+  /* adjust the number of results */
+  if (nResults != MULT_RET)
+    luaD_adjusttop(firstResult+nResults);
+  /* move results to base-1 (to erase parameters and function) */
+  base--;
+  nResults = luaD_stack.top - (luaD_stack.stack+firstResult);  /* actual number of results */
+  for (i=0; i<nResults; i++)
+    *(luaD_stack.stack+base+i) = *(luaD_stack.stack+firstResult+i);
+  luaD_stack.top -= firstResult-base;
+}
+
+
+
+/*
+** Traverse all objects on luaD_stack.stack
+*/
+void luaD_travstack (int (*fn)(TObject *))
+{
+  StkId i;
+  for (i = (luaD_stack.top-1)-luaD_stack.stack; i>=0; i--)
+    fn (luaD_stack.stack+i);
+}
+
+
+/*
+** Error messages
+*/
+
+static void auxerrorim (char *form)
+{
+  lua_Object s = lua_getparam(1);
+  if (lua_isstring(s))
+    fprintf(stderr, form, lua_getstring(s));
+}
+
+
+static void emergencyerrorf (void)
+{
+  auxerrorim("THERE WAS AN ERROR INSIDE AN ERROR METHOD:\n%s\n");
+}
+
+
+static void stderrorim (void)
+{
+  auxerrorim("lua: %s\n");
+}
+
+
+TObject luaD_errorim = {LUA_T_CFUNCTION, {stderrorim}};
+
+
+static void message (char *s)
+{
+  TObject im = luaD_errorim;
+  if (ttype(&im) != LUA_T_NIL) {
+    luaD_errorim.ttype = LUA_T_CFUNCTION;
+    luaD_errorim.value.f = emergencyerrorf;
+    lua_pushstring(s);
+    luaD_callTM(&im, 1, 0);
+    luaD_errorim = im;
+  }
+}
+
+/*
+** Reports an error, and jumps up to the available recover label
+*/
+void lua_error (char *s)
+{
+  if (s) message(s);
+  if (errorJmp)
+    longjmp(*errorJmp, 1);
+  else {
+    fprintf (stderr, "lua: exit(1). Unable to recover\n");
+    exit(1);
+  }
+}
+
+/*
+** Call the function at luaD_Cstack.base, and incorporate results on
+** the Lua2C structure.
+*/
+static void do_callinc (int nResults)
+{
+  StkId base = luaD_Cstack.base;
+  luaD_call(base+1, nResults);
+  luaD_Cstack.lua2C = base;  /* position of the luaM_new results */
+  luaD_Cstack.num = (luaD_stack.top-luaD_stack.stack) - base;  /* number of results */
+  luaD_Cstack.base = base + luaD_Cstack.num;  /* incorporate results on luaD_stack.stack */
+}
+
+
+/*
+** Execute a protected call. Assumes that function is at luaD_Cstack.base and
+** parameters are on luaD_stack.top of it. Leave nResults on the luaD_stack.stack.
+*/
+int luaD_protectedrun (int nResults)
+{
+  jmp_buf myErrorJmp;
+  int status;
+  struct C_Lua_Stack oldCLS = luaD_Cstack;
+  jmp_buf *oldErr = errorJmp;
+  errorJmp = &myErrorJmp;
+  if (setjmp(myErrorJmp) == 0) {
+    do_callinc(nResults);
+    status = 0;
+  }
+  else { /* an error occurred: restore luaD_Cstack and luaD_stack.top */
+    luaD_Cstack = oldCLS;
+    luaD_stack.top = luaD_stack.stack+luaD_Cstack.base;
+    status = 1;
+  }
+  errorJmp = oldErr;
+  return status;
+}
+
+
+/*
+** returns 0 = chunk loaded; 1 = error; 2 = no more chunks to load
+*/
+static int protectedparser (ZIO *z, char *chunkname, int bin)
+{
+  int status;
+  TProtoFunc *tf;
+  jmp_buf myErrorJmp;
+  jmp_buf *oldErr = errorJmp;
+  errorJmp = &myErrorJmp;
+  if (setjmp(myErrorJmp) == 0) {
+    tf = bin ? luaU_undump1(z, chunkname) : luaY_parser(z, chunkname);
+    status = 0;
+  }
+  else {
+    tf = NULL;
+    status = 1;
+  }
+  errorJmp = oldErr;
+  if (status) return 1;  /* error code */
+  if (tf == NULL) return 2;  /* 'natural' end */
+  luaD_adjusttop(luaD_Cstack.base+1);  /* one slot for the pseudo-function */
+  luaD_stack.stack[luaD_Cstack.base].ttype = LUA_T_PROTO;
+  luaD_stack.stack[luaD_Cstack.base].value.tf = tf;
+  luaV_closure();
+  return 0;
+}
+
+
+static int do_main (ZIO *z, char *chunkname, int bin)
+{
+  int status;
+  do {
+    long old_entities = (luaC_checkGC(), luaO_nentities);
+    status = protectedparser(z, chunkname, bin);
+    if (status == 1) return 1;  /* error */
+    else if (status == 2) return 0;  /* 'natural' end */
+    else {
+      long newelems2 = 2*(luaO_nentities-old_entities);
+      luaC_threshold += newelems2;
+      status = luaD_protectedrun(MULT_RET);
+      luaC_threshold -= newelems2;
+    }
+  } while (bin && status == 0);
+  return status;
+}
+
+
+void luaD_gcIM (TObject *o)
+{
+  TObject *im = luaT_getimbyObj(o, IM_GC);
+  if (ttype(im) != LUA_T_NIL) {
+    *luaD_stack.top = *o;
+    incr_top;
+    luaD_callTM(im, 1, 0);
+  }
+}
+
+
+int lua_dofile (char *filename)
+{
+  ZIO z;
+  int status;
+  int c;
+  int bin;
+  FILE *f = (filename == NULL) ? stdin : fopen(filename, "r");
+  if (f == NULL)
+    return 2;
+  if (filename == NULL)
+    filename = "(stdin)";
+  c = fgetc(f);
+  ungetc(c, f);
+  bin = (c == ID_CHUNK);
+  if (bin)
+    f = freopen(filename, "rb", f);  /* set binary mode */
+  luaZ_Fopen(&z, f);
+  status = do_main(&z, filename, bin);
+  if (f != stdin)
+    fclose(f);
+  return status;
+}
+
+
+#define SIZE_PREF 20  /* size of string prefix to appear in error messages */
+
+
+int lua_dostring (char *str)
+{
+  int status;
+  char buff[SIZE_PREF+25];
+  char *temp;
+  ZIO z;
+  if (str == NULL) return 1;
+  sprintf(buff, "(dostring) >> %.20s", str);
+  temp = strchr(buff, '\n');
+  if (temp) *temp = 0;  /* end string after first line */
+  luaZ_sopen(&z, str);
+  status = do_main(&z, buff, 0);
+  return status;
+}
+
-- 
cgit v1.2.3-55-g6feb