Browse Source

debug interface functions to manipulated local variables:
"lua_getlocal" and "lua_setlocal".

Roberto Ierusalimschy 29 years ago
parent
commit
5a3a1fe458
5 changed files with 157 additions and 17 deletions
  1. 82 0
      func.c
  2. 15 1
      func.h
  3. 19 11
      lua.stx
  4. 7 2
      luadebug.h
  5. 34 3
      opcode.c

+ 82 - 0
func.c

@@ -6,9 +6,24 @@
 #include "func.h"
 #include "opcode.h"
 
+#define LOCALVARINITSIZE 10
+
 static TFunc *function_root = NULL;
+static LocVar *currvars = NULL;
+static int numcurrvars = 0;
+static int maxcurrvars = 0;
 
 
+/*
+** Initialize TFunc struct
+*/
+void luaI_initTFunc (TFunc *f)
+{
+  f->code = NULL;
+  f->lineDefined = 0;
+  f->locvars = NULL;
+}
+
 /*
 ** Insert function in list for GC
 */
@@ -77,3 +92,70 @@ void lua_funcinfo (lua_Object func, char **filename, int *linedefined)
   }
 }
 
+/*
+** Stores information to know that variable has been declared in given line
+*/
+void luaI_registerlocalvar (TreeNode *varname, int line)
+{
+  if (numcurrvars >= maxcurrvars)
+    if (currvars == NULL)
+    {
+      maxcurrvars = LOCALVARINITSIZE;
+      currvars = newvector (maxcurrvars, LocVar);
+    }
+    else
+    {
+      maxcurrvars *= 2;
+      currvars = growvector (currvars, maxcurrvars, LocVar);
+    }
+  currvars[numcurrvars].varname = varname;
+  currvars[numcurrvars].line = line;
+  numcurrvars++;
+}
+
+/*
+** Stores information to know that variable has been out of scope in given line
+*/
+void luaI_unregisterlocalvar (int line)
+{
+  luaI_registerlocalvar(NULL, line);
+}
+
+/*
+** Copies "currvars" into a new area and store it in function header.
+** The values (varname = NULL, line = -1) signal the end of vector.
+*/
+void luaI_closelocalvars (TFunc *func)
+{
+  func->locvars = newvector (numcurrvars+1, LocVar);
+  memcpy (func->locvars, currvars, numcurrvars*sizeof(LocVar));
+  func->locvars[numcurrvars].varname = NULL;
+  func->locvars[numcurrvars].line = -1;
+  numcurrvars = 0;  /* prepares for next function */
+}
+
+/*
+** Look for n-esim local variable at line "line" in function "func".
+** Returns NULL if not found.
+*/
+char *luaI_getlocalname (TFunc *func, int local_number, int line)
+{
+  int count = 0;
+  char *varname = NULL;
+  LocVar *lv = func->locvars;
+  if (lv == NULL)
+    return NULL;
+  for (; lv->line != -1 && lv->line < line; lv++)
+  {
+    if (lv->varname)               /* register */
+    {
+      if (++count == local_number)
+        varname = lv->varname->ts.str;
+    }
+    else                           /* unregister */
+      if (--count < local_number)
+        varname = NULL;
+  }
+  return varname;
+}
+

+ 15 - 1
func.h

@@ -4,8 +4,15 @@
 #include "types.h"
 #include "lua.h"
 
+typedef struct LocVar
+{
+  TreeNode  *varname;           /* NULL signals end of scope */
+  int       line;
+} LocVar;
+
+
 /*
-** Header para funcoes.
+** Function Headers
 */
 typedef struct TFunc
 {
@@ -15,10 +22,17 @@ typedef struct TFunc
   Byte		*code;
   int		lineDefined;
   char		*fileName;
+  LocVar        *locvars;
 } TFunc;
 
 Long luaI_funccollector (void);
 void luaI_insertfunction (TFunc *f);
 
+void luaI_initTFunc (TFunc *f);
+
+void luaI_registerlocalvar (TreeNode *varname, int line);
+void luaI_unregisterlocalvar (int line);
+void luaI_closelocalvars (TFunc *func);
+char *luaI_getlocalname (TFunc *func, int local_number, int line);
 
 #endif

+ 19 - 11
lua.stx

@@ -1,11 +1,12 @@
 %{
 
-char *rcs_luastx = "$Id: lua.stx,v 3.27 1996/01/23 17:50:29 roberto Exp $";
+char *rcs_luastx = "$Id: lua.stx,v 3.28 1996/02/05 13:26:01 roberto Exp roberto $";
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+#include "luadebug.h"
 #include "mem.h"
 #include "opcode.h"
 #include "hash.h"
@@ -51,6 +52,7 @@ static int     nlocalvar=0;	     /* number of local variables */
 static Word    fields[MAXFIELDS];     /* fieldnames to be flushed */
 static int     nfields=0;
 
+int lua_debug = 0;
 
 /* Internal functions */
 
@@ -149,20 +151,20 @@ static void flush_list (int m, int n)
   code_byte(n);
 }
 
-static void add_localvar (TreeNode *name)
-{
- if (nlocalvar < MAXLOCALS)
-  localvar[nlocalvar++] = name;
- else
-  yyerror ("too many local variables");
-}
-
 static void store_localvar (TreeNode *name, int n)
 {
  if (nlocalvar+n < MAXLOCALS)
   localvar[nlocalvar+n] = name;
  else
   yyerror ("too many local variables");
+ if (lua_debug)
+   luaI_registerlocalvar(name, lua_linenumber);
+}
+
+static void add_localvar (TreeNode *name)
+{
+  store_localvar(name, 0);
+  nlocalvar++;
 }
 
 static void add_varbuffer (Long var)
@@ -391,7 +393,6 @@ static void codeIf (Long thenAdd, Long elseAdd)
 */
 void lua_parse (TFunc *tf)
 {
- lua_debug = 0;
  initcode = &(tf->code);
  *initcode = newvector(CODE_BLOCK, Byte);
  maincode = 0; 
@@ -492,11 +493,14 @@ body :  '(' parlist ')' block END
 	{
           codereturn();
 	  $$ = new(TFunc);
+          luaI_initTFunc($$);
 	  $$->size = pc;
 	  $$->code = newvector(pc, Byte);
 	  $$->fileName = lua_parsedfile;
 	  $$->lineDefined = $2;
 	  memcpy($$->code, basepc, pc*sizeof(Byte));
+          if (lua_debug)
+            luaI_closelocalvars($$);
 	  /* save func values */
 	  funcCode = basepc; maxcode=maxcurr;
 #if LISTING
@@ -557,7 +561,11 @@ block    : {$<vInt>$ = nlocalvar;} statlist ret
          {
 	  if (nlocalvar != $<vInt>1)
 	  {
-           nlocalvar = $<vInt>1;
+           if (lua_debug)
+             for (; nlocalvar > $<vInt>1; nlocalvar--)
+               luaI_unregisterlocalvar(lua_linenumber);
+           else
+             nlocalvar = $<vInt>1;
 	   lua_codeadjust (0);
 	  }
          }

+ 7 - 2
luadebug.h

@@ -2,7 +2,7 @@
 ** LUA - Linguagem para Usuarios de Aplicacao
 ** Grupo de Tecnologia em Computacao Grafica
 ** TeCGraf - PUC-Rio
-** $Id: luadebug.h,v 1.2 1995/10/26 14:21:56 roberto Exp $
+** $Id: luadebug.h,v 1.3 1996/01/09 20:22:44 roberto Exp roberto $
 */
 
 
@@ -14,11 +14,16 @@
 typedef void (*lua_LHFunction) (int line);
 typedef void (*lua_CHFunction) (lua_Object func, char *file, int line);
 
-lua_Object lua_stackedfunction(int level);
+lua_Object lua_stackedfunction (int level);
 void lua_funcinfo (lua_Object func, char **filename, int *linedefined);
 int lua_currentline (lua_Object func);
 char *lua_getobjname (lua_Object o, char **name);
 lua_LHFunction lua_setlinehook (lua_LHFunction hook);
 lua_CHFunction lua_setcallhook (lua_CHFunction hook);
 
+lua_Object lua_getlocal (lua_Object func, int local_number, char **name);
+int lua_setlocal (lua_Object func, int local_number);
+
+extern int lua_debug;
+
 #endif

+ 34 - 3
opcode.c

@@ -3,7 +3,7 @@
 ** TecCGraf - PUC-Rio
 */
 
-char *rcs_opcode="$Id: opcode.c,v 3.53 1996/01/23 18:43:07 roberto Exp roberto $";
+char *rcs_opcode="$Id: opcode.c,v 3.54 1996/01/30 15:25:23 roberto Exp roberto $";
 
 #include <setjmp.h>
 #include <stdlib.h>
@@ -441,6 +441,38 @@ int lua_currentline (lua_Object func)
 }
 
 
+lua_Object lua_getlocal (lua_Object func, int local_number, char **name)
+{
+  Object *f = luaI_Address(func);
+  *name = luaI_getlocalname(f->value.tf, local_number, lua_currentline(func));
+  if (*name)
+  {
+    /* if "*name", there must be a LUA_T_LINE */
+    /* therefore, f+2 points to function base */
+    return Ref((f+2)+(local_number-1));
+  }
+  else
+    return LUA_NOOBJECT;
+}
+
+int lua_setlocal (lua_Object func, int local_number)
+{
+  Object *f = Address(func);
+  char *name = luaI_getlocalname(f->value.tf, local_number, lua_currentline(func));
+  adjustC(1);
+  --top;
+  if (name)
+  {
+    /* if "name", there must be a LUA_T_LINE */
+    /* therefore, f+2 points to function base */
+    *((f+2)+(local_number-1)) = *top;
+    return 1;
+  }
+  else
+    return 0;
+}
+
+
 /*
 ** Execute a protected call. Assumes that function is at CBase and
 ** parameters are on top of it. Leave nResults on the stack. 
@@ -480,9 +512,8 @@ static int do_protectedmain (void)
   adjustC(1);  /* one slot for the pseudo-function */
   stack[CBase].tag = LUA_T_FUNCTION;
   stack[CBase].value.tf = &tf;
-  tf.lineDefined = 0;
+  luaI_initTFunc(&tf);
   tf.fileName = lua_parsedfile;
-  tf.code = NULL;
   if (setjmp(myErrorJmp) == 0)
   {
     lua_parse(&tf);