summaryrefslogtreecommitdiff
path: root/src/luac
diff options
context:
space:
mode:
Diffstat (limited to 'src/luac')
-rw-r--r--src/luac/Makefile6
-rw-r--r--src/luac/README34
-rw-r--r--src/luac/dump.c173
-rw-r--r--src/luac/luac.c252
-rw-r--r--src/luac/luac.h37
-rw-r--r--src/luac/opcode.c102
-rw-r--r--src/luac/opcode.h70
-rw-r--r--src/luac/opt.c326
-rw-r--r--src/luac/print.c252
-rw-r--r--src/luac/print.h55
-rw-r--r--src/luac/stubs.c176
-rw-r--r--src/luac/test.c253
12 files changed, 527 insertions, 1209 deletions
diff --git a/src/luac/Makefile b/src/luac/Makefile
index e2950e60..4517d82b 100644
--- a/src/luac/Makefile
+++ b/src/luac/Makefile
@@ -1,12 +1,12 @@
-# makefile for lua compiler
+# makefile for Lua compiler
LUA= ../..
include $(LUA)/config
INCS= -I$(INC) $(EXTRA_INCS) -I..
-OBJS= dump.o luac.o opcode.o opt.o print.o stubs.o test.o
-SRCS= dump.c luac.c opcode.c opt.c print.c stubs.c test.c luac.h opcode.h
+OBJS= dump.o luac.o opt.o print.o stubs.o
+SRCS= dump.c luac.c opt.c print.c stubs.c luac.h print.h
T= $(BIN)/luac
diff --git a/src/luac/README b/src/luac/README
index 9fba74bb..8d8bb491 100644
--- a/src/luac/README
+++ b/src/luac/README
@@ -1,28 +1,22 @@
+This is luac, the Lua compiler.
+There are man pages for it in both nroff and html in ../../doc.
+
luac translates Lua programs into binary files that can be loaded and executed
with lua_dofile in C or with dofile in Lua.
-The main advantages of pre-compiling chunks are: faster loading,
-protecting source code from user changes, off-line syntax error detection.
+The main advantages of pre-compiling chunks are: faster loading, protecting
+source code from user changes, and off-line syntax error detection.
luac can also be used to learn about the Lua virtual machine.
Here are the options that luac understands:
- -c compile (default)
- -d generate debugging information
- -D name predefine 'name' for conditional compilation
- -l list (default for -u)
- -n save numbers in native format (file may not be portable)
- -o file output file for -c (default is "luac.out")
- -O optimize
- -p parse only
- -q quiet (default for -c)
- -t test code integrity
- -u undump
- -U name undefine 'name' for conditional compilation
- -v show version information
- -V verbose
- - compile "stdin"
+ - process stdin
+ -l list
+ -o file output file (default is "luac.out")
+ -p parse only
+ -s strip debug information
+ -t test code integrity
+ -v show version information
-Finally, luac is an example of how to use the internals of Lua (politely).
-Also, luac does not need the runtime code and stubs.c makes sure it is not
+luac is also an example of how to use the internals of Lua (politely).
+Finally, luac does not need the runtime code, and stubs.c makes sure it is not
linked into luac. This file also shows how to avoid linking the parser.
-
diff --git a/src/luac/dump.c b/src/luac/dump.c
index 479ce5d4..149469ba 100644
--- a/src/luac/dump.c
+++ b/src/luac/dump.c
@@ -1,154 +1,121 @@
/*
-** $Id: dump.c,v 1.20 1999/07/02 19:34:26 lhf Exp $
+** $Id: dump.c,v 1.30 2000/10/31 16:57:23 lhf Exp $
** save bytecodes to file
** See Copyright Notice in lua.h
*/
-#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-#include "luac.h"
+#include <string.h>
-#ifdef OLD_ANSI
-#define strerror(e) "(no error message provided by operating system)"
-#endif
+#include "luac.h"
+#define DumpVector(b,n,size,D) fwrite(b,size,n,D)
#define DumpBlock(b,size,D) fwrite(b,size,1,D)
-#define DumpInt DumpLong
+#define DumpByte fputc
-static void DumpWord(int i, FILE* D)
+static void DumpInt(int x, FILE* D)
{
- int hi= 0x0000FF & (i>>8);
- int lo= 0x0000FF & i;
- fputc(hi,D);
- fputc(lo,D);
+ DumpBlock(&x,sizeof(x),D);
}
-static void DumpLong(long i, FILE* D)
+static void DumpSize(size_t x, FILE* D)
{
- int hi= 0x00FFFF & (i>>16);
- int lo= 0x00FFFF & i;
- DumpWord(hi,D);
- DumpWord(lo,D);
+ DumpBlock(&x,sizeof(x),D);
}
-static void DumpNumber(real x, FILE* D, int native, TProtoFunc* tf)
+static void DumpNumber(Number x, FILE* D)
{
- if (native)
- DumpBlock(&x,sizeof(x),D);
- else
- {
- char b[256];
- int n;
- sprintf(b,NUMBER_FMT"%n",x,&n);
- luaU_str2d(b,tf->source->str); /* help lundump not to fail */
- fputc(n,D);
- DumpBlock(b,n,D);
- }
+ DumpBlock(&x,sizeof(x),D);
}
-static void DumpCode(TProtoFunc* tf, FILE* D)
+static void DumpString(const TString* s, FILE* D)
{
- int size=luaU_codesize(tf);
- DumpLong(size,D);
- DumpBlock(tf->code,size,D);
-}
-
-static void DumpString(char* s, int size, FILE* D)
-{
- if (s==NULL)
- DumpLong(0,D);
+ if (s==NULL || s->str==NULL)
+ DumpSize(0,D);
else
{
- DumpLong(size,D);
- DumpBlock(s,size,D);
+ size_t size=s->len+1; /* include trailing '\0' */
+ DumpSize(size,D);
+ DumpBlock(s->str,size,D);
}
}
-static void DumpTString(TaggedString* s, FILE* D)
+static void DumpCode(const Proto* tf, FILE* D)
{
- if (s==NULL)
- DumpString(NULL,0,D);
- else
- DumpString(s->str,s->u.s.len+1,D);
+ DumpInt(tf->ncode,D);
+ DumpVector(tf->code,tf->ncode,sizeof(*tf->code),D);
}
-static void DumpLocals(TProtoFunc* tf, FILE* D)
+static void DumpLocals(const Proto* tf, FILE* D)
{
- if (tf->locvars==NULL)
- DumpInt(0,D);
- else
+ int i,n=tf->nlocvars;
+ DumpInt(n,D);
+ for (i=0; i<n; i++)
{
- LocVar* v;
- int n=0;
- for (v=tf->locvars; v->line>=0; v++)
- ++n;
- DumpInt(n,D);
- for (v=tf->locvars; v->line>=0; v++)
- {
- DumpInt(v->line,D);
- DumpTString(v->varname,D);
- }
+ DumpString(tf->locvars[i].varname,D);
+ DumpInt(tf->locvars[i].startpc,D);
+ DumpInt(tf->locvars[i].endpc,D);
}
}
-static void DumpFunction(TProtoFunc* tf, FILE* D, int native);
+static void DumpLines(const Proto* tf, FILE* D)
+{
+ DumpInt(tf->nlineinfo,D);
+ DumpVector(tf->lineinfo,tf->nlineinfo,sizeof(*tf->lineinfo),D);
+}
+
+static void DumpFunction(const Proto* tf, FILE* D);
-static void DumpConstants(TProtoFunc* tf, FILE* D, int native)
+static void DumpConstants(const Proto* tf, FILE* D)
{
- int i,n=tf->nconsts;
- DumpInt(n,D);
+ int i,n;
+ DumpInt(n=tf->nkstr,D);
for (i=0; i<n; i++)
- {
- TObject* o=tf->consts+i;
- fputc(-ttype(o),D); /* ttype(o) is negative - ORDER LUA_T */
- switch (ttype(o))
- {
- case LUA_T_NUMBER:
- DumpNumber(nvalue(o),D,native,tf);
- break;
- case LUA_T_STRING:
- DumpTString(tsvalue(o),D);
- break;
- case LUA_T_PROTO:
- DumpFunction(tfvalue(o),D,native);
- break;
- case LUA_T_NIL:
- break;
- default: /* cannot happen */
- luaU_badconstant("dump",i,o,tf);
- break;
- }
- }
+ DumpString(tf->kstr[i],D);
+ DumpInt(tf->nknum,D);
+ DumpVector(tf->knum,tf->nknum,sizeof(*tf->knum),D);
+ DumpInt(n=tf->nkproto,D);
+ for (i=0; i<n; i++)
+ DumpFunction(tf->kproto[i],D);
}
-static void DumpFunction(TProtoFunc* tf, FILE* D, int native)
+static void DumpFunction(const Proto* tf, FILE* D)
{
+ DumpString(tf->source,D);
DumpInt(tf->lineDefined,D);
- DumpTString(tf->source,D);
- DumpCode(tf,D);
+ DumpInt(tf->numparams,D);
+ DumpByte(tf->is_vararg,D);
+ DumpInt(tf->maxstacksize,D);
DumpLocals(tf,D);
- DumpConstants(tf,D,native);
+ DumpLines(tf,D);
+ DumpConstants(tf,D);
+ DumpCode(tf,D);
if (ferror(D))
- luaL_verror("write error" IN ": %s (errno=%d)",INLOC,strerror(errno),errno);
+ {
+ perror("luac: write error");
+ exit(1);
+ }
}
-static void DumpHeader(TProtoFunc* Main, FILE* D, int native)
+static void DumpHeader(FILE* D)
{
- fputc(ID_CHUNK,D);
+ DumpByte(ID_CHUNK,D);
fputs(SIGNATURE,D);
- fputc(VERSION,D);
- if (native)
- {
- fputc(sizeof(real),D);
- DumpNumber(TEST_NUMBER,D,native,Main);
- }
- else
- fputc(0,D);
+ DumpByte(VERSION,D);
+ DumpByte(luaU_endianess(),D);
+ DumpByte(sizeof(int),D);
+ DumpByte(sizeof(size_t),D);
+ DumpByte(sizeof(Instruction),D);
+ DumpByte(SIZE_INSTRUCTION,D);
+ DumpByte(SIZE_OP,D);
+ DumpByte(SIZE_B,D);
+ DumpByte(sizeof(Number),D);
+ DumpNumber(TEST_NUMBER,D);
}
-void luaU_dumpchunk(TProtoFunc* Main, FILE* D, int native)
+void luaU_dumpchunk(const Proto* Main, FILE* D)
{
- DumpHeader(Main,D,native);
- DumpFunction(Main,D,native);
+ DumpHeader(D);
+ DumpFunction(Main,D);
}
diff --git a/src/luac/luac.c b/src/luac/luac.c
index 68af1c76..8832de62 100644
--- a/src/luac/luac.c
+++ b/src/luac/luac.c
@@ -1,5 +1,5 @@
/*
-** $Id: luac.c,v 1.17 1999/07/02 19:34:26 lhf Exp $
+** $Id: luac.c,v 1.28 2000/11/06 20:06:27 lhf Exp $
** lua compiler (saves bytecodes to files; also list binary files)
** See Copyright Notice in lua.h
*/
@@ -7,181 +7,197 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "luac.h"
+
#include "lparser.h"
#include "lstate.h"
#include "lzio.h"
+#include "luac.h"
#define OUTPUT "luac.out" /* default output file */
-static FILE* efopen(char* name, char* mode);
-static void doit(int undump, char* filename);
+static void usage(const char* message, const char* arg);
+static int doargs(int argc, const char* argv[]);
+static Proto* load(const char* filename);
+static FILE* efopen(const char* name, const char* mode);
+static void strip(Proto* tf);
+static Proto* combine(Proto** P, int n);
+
+lua_State* lua_state=NULL; /* lazy! */
static int listing=0; /* list bytecodes? */
-static int debugging=0; /* emit debug information? */
static int dumping=1; /* dump bytecodes? */
-static int undumping=0; /* undump bytecodes? */
-static int optimizing=0; /* optimize? */
-static int parsing=0; /* parse only? */
+static int stripping=0; /* strip debug information? */
static int testing=0; /* test integrity? */
-static int verbose=0; /* tell user what is done */
-static int native=0; /* save numbers in native format? */
-static FILE* D; /* output file */
+static const char* output=OUTPUT; /* output file name */
-static void usage(char* op)
+#define IS(s) (strcmp(argv[i],s)==0)
+
+int main(int argc, const char* argv[])
{
- if (op) fprintf(stderr,"luac: unrecognized option '%s'\n",op);
+ Proto** P,*tf;
+ int i=doargs(argc,argv);
+ argc-=i; argv+=i;
+ if (argc<=0) usage("no input files given",NULL);
+ L=lua_open(0);
+ P=luaM_newvector(L,argc,Proto*);
+ for (i=0; i<argc; i++)
+ P[i]=load(IS("-")? NULL : argv[i]);
+ tf=combine(P,argc);
+ if (dumping) luaU_optchunk(tf);
+ if (listing) luaU_printchunk(tf);
+ if (testing) luaU_testchunk(tf);
+ if (dumping)
+ {
+ if (stripping) strip(tf);
+ luaU_dumpchunk(tf,efopen(output,"wb"));
+ }
+ return 0;
+}
+
+static void usage(const char* message, const char* arg)
+{
+ if (message!=NULL)
+ {
+ fprintf(stderr,"luac: "); fprintf(stderr,message,arg); fprintf(stderr,"\n");
+ }
fprintf(stderr,
"usage: luac [options] [filenames]. Available options are:\n"
- " -c\t\tcompile (default)\n"
- " -d\t\tgenerate debugging information\n"
- " -D name\tpredefine 'name' for conditional compilation\n"
- " -l\t\tlist (default for -u)\n"
- " -n\t\tsave numbers in native format (file may not be portable)\n"
- " -o file\toutput file for -c (default is \"" OUTPUT "\")\n"
- " -O\t\toptimize\n"
- " -p\t\tparse only\n"
- " -q\t\tquiet (default for -c)\n"
- " -t\t\ttest code integrity\n"
- " -u\t\tundump\n"
- " -U name\tundefine 'name' for conditional compilation\n"
- " -v\t\tshow version information\n"
- " -V\t\tverbose\n"
- " -\t\tcompile \"stdin\"\n"
+ " - process stdin\n"
+ " -l list\n"
+ " -o file output file (default is \"" OUTPUT "\")\n"
+ " -p parse only\n"
+ " -s strip debug information\n"
+ " -t test code integrity\n"
+ " -v show version information\n"
);
exit(1);
}
-#define IS(s) (strcmp(argv[i],s)==0)
-
-int main(int argc, char* argv[])
+static int doargs(int argc, const char* argv[])
{
- char* d=OUTPUT; /* output file name */
int i;
- lua_open();
for (i=1; i<argc; i++)
{
- if (argv[i][0]!='-') /* end of options */
+ if (*argv[i]!='-') /* end of options */
break;
else if (IS("-")) /* end of options; use stdin */
- break;
- else if (IS("-c")) /* compile (and dump) */
- {
- dumping=1;
- undumping=0;
- }
- else if (IS("-D")) /* $define */
- {
- TaggedString* s=luaS_new(argv[++i]);
- s->u.s.globalval.ttype=LUA_T_NUMBER;
- s->u.s.globalval.value.n=1;
- }
- else if (IS("-d")) /* debug */
- debugging=1;
+ return i;
else if (IS("-l")) /* list */
listing=1;
- else if (IS("-n")) /* native */
- native=1;
else if (IS("-o")) /* output file */
- d=argv[++i];
- else if (IS("-O")) /* optimize */
- optimizing=1;
- else if (IS("-p")) /* parse only */
{
- dumping=0;
- parsing=1;
+ output=argv[++i];
+ if (output==NULL) usage(NULL,NULL);
}
- else if (IS("-q")) /* quiet */
- listing=0;
+ else if (IS("-p")) /* parse only */
+ dumping=0;
+ else if (IS("-s")) /* strip debug information */
+ stripping=1;
else if (IS("-t")) /* test */
- testing=1;
- else if (IS("-u")) /* undump */
{
+ testing=1;
dumping=0;
- undumping=1;
- listing=1;
- }
- else if (IS("-U")) /* undefine */
- {
- TaggedString* s=luaS_new(argv[++i]);
- s->u.s.globalval.ttype=LUA_T_NIL;
}
else if (IS("-v")) /* show version */
- printf("%s %s\n(written by %s)\n\n",LUA_VERSION,LUA_COPYRIGHT,LUA_AUTHORS);
- else if (IS("-V")) /* verbose */
- verbose=1;
- else /* unknown option */
- usage(argv[i]);
- }
- --i; /* fake new argv[0] */
- argc-=i;
- argv+=i;
- if (dumping || parsing)
- {
- if (argc<2) usage(NULL);
- if (dumping)
{
- for (i=1; i<argc; i++) /* play safe with output file */
- if (IS(d)) luaL_verror("will not overwrite input file \"%s\"",d);
- D=efopen(d,"wb"); /* must open in binary mode */
+ printf("%s %s\n",LUA_VERSION,LUA_COPYRIGHT);
+ if (argc==2) exit(0);
}
- for (i=1; i<argc; i++) doit(0,IS("-")? NULL : argv[i]);
- if (dumping) fclose(D);
+ else /* unknown option */
+ usage("unrecognized option `%s'",argv[i]);
}
- if (undumping)
+ if (i==argc && (listing || testing))
{
- if (argc<2)
- doit(1,OUTPUT);
- else
- for (i=1; i<argc; i++) doit(1,IS("-")? NULL : argv[i]);
+ dumping=0;
+ argv[--i]=OUTPUT;
}
- return 0;
+ return i;
}
-static void do_compile(ZIO* z)
+static Proto* load(const char* filename)
{
- TProtoFunc* Main;
- if (optimizing) L->debug=0;
- if (debugging) L->debug=1;
- Main=luaY_parser(z);
- if (optimizing) luaU_optchunk(Main);
- if (listing) luaU_printchunk(Main);
- if (testing) luaU_testchunk(Main);
- if (dumping) luaU_dumpchunk(Main,D,native);
+ Proto* tf;
+ ZIO z;
+ char source[512];
+ FILE* f;
+ int c,undump;
+ if (filename==NULL)
+ {
+ f=stdin;
+ filename="(stdin)";
+ }
+ else
+ f=efopen(filename,"r");
+ c=ungetc(fgetc(f),f);
+ if (ferror(f))
+ {
+ fprintf(stderr,"luac: cannot read from ");
+ perror(filename);
+ exit(1);
+ }
+ undump=(c==ID_CHUNK);
+ if (undump && f!=stdin)
+ {
+ fclose(f);
+ f=efopen(filename,"rb");
+ }
+ sprintf(source,"@%.*s",Sizeof(source)-2,filename);
+ luaZ_Fopen(&z,f,source);
+ tf = undump ? luaU_undump(L,&z) : luaY_parser(L,&z);
+ if (f!=stdin) fclose(f);
+ return tf;
}
-static void do_undump(ZIO* z)
+static Proto* combine(Proto** P, int n)
{
- for (;;)
+ if (n==1)
+ return P[0];
+ else
{
- TProtoFunc* Main=luaU_undump1(z);
- if (Main==NULL) break;
- if (optimizing) luaU_optchunk(Main);
- if (listing) luaU_printchunk(Main);
- if (testing) luaU_testchunk(Main);
+ int i,pc=0;
+ Proto* tf=luaF_newproto(L);
+ tf->source=luaS_new(L,"=(luac)");
+ tf->maxstacksize=1;
+ tf->kproto=P;
+ tf->nkproto=n;
+ tf->ncode=2*n+1;
+ tf->code=luaM_newvector(L,tf->ncode,Instruction);
+ for (i=0; i<n; i++)
+ {
+ tf->code[pc++]=CREATE_AB(OP_CLOSURE,i,0);
+ tf->code[pc++]=CREATE_AB(OP_CALL,0,0);
+ }
+ tf->code[pc++]=OP_END;
+ return tf;
}
}
-static void doit(int undump, char* filename)
+static void strip(Proto* tf)
{
- FILE* f= (filename==NULL) ? stdin : efopen(filename, undump ? "rb" : "r");
- ZIO z;
- char source[255+2]; /* +2 for '@' and '\0' */
- luaL_filesource(source,filename,sizeof(source));
- zFopen(&z,f,source);
- if (verbose) fprintf(stderr,"%s\n",source+1);
- if (undump) do_undump(&z); else do_compile(&z);
- if (f!=stdin) fclose(f);
+ int i,n=tf->nkproto;
+ tf->lineinfo=NULL;
+ tf->nlineinfo=0;
+ tf->source=luaS_new(L,"=(none)");
+ tf->locvars=NULL;
+ tf->nlocvars=0;
+ for (i=0; i<n; i++) strip(tf->kproto[i]);
}
-static FILE* efopen(char* name, char* mode)
+static FILE* efopen(const char* name, const char* mode)
{
FILE* f=fopen(name,mode);
if (f==NULL)
{
- fprintf(stderr,"luac: cannot open %sput file ",mode[0]=='r' ? "in" : "out");
+ fprintf(stderr,"luac: cannot open %sput file ",*mode=='r' ? "in" : "out");
perror(name);
exit(1);
}
return f;
}
+
+void luaU_testchunk(const Proto* Main)
+{
+ UNUSED(Main);
+ fprintf(stderr,"luac: -t not operational in this version\n");
+ exit(1);
+}
diff --git a/src/luac/luac.h b/src/luac/luac.h
index 1ae5267b..f8987cf2 100644
--- a/src/luac/luac.h
+++ b/src/luac/luac.h
@@ -1,48 +1,31 @@
/*
-** $Id: luac.h,v 1.11 1999/07/02 19:34:26 lhf Exp $
+** $Id: luac.h,v 1.18 2000/10/31 16:57:23 lhf Exp $
** definitions for luac
** See Copyright Notice in lua.h
*/
-#include "lauxlib.h"
+#include "ldebug.h"
#include "lfunc.h"
#include "lmem.h"
#include "lobject.h"
#include "lopcodes.h"
#include "lstring.h"
+#include "ltable.h"
#include "lundump.h"
-typedef struct
-{
- char* name; /* name of opcode */
- int op; /* value of opcode */
- int class; /* class of opcode (byte variant) */
- int args; /* types of arguments (operands) */
- int arg; /* arg #1 */
- int arg2; /* arg #2 */
-} Opcode;
+extern lua_State *lua_state;
+#define L lua_state /* lazy! */
/* from dump.c */
-void luaU_dumpchunk(TProtoFunc* Main, FILE* D, int native);
-
-/* from opcode.c */
-int luaU_opcodeinfo(TProtoFunc* tf, Byte* p, Opcode* I, char* xFILE, int xLINE);
-int luaU_codesize(TProtoFunc* tf);
+void luaU_dumpchunk(const Proto* Main, FILE* D);
/* from opt.c */
-void luaU_optchunk(TProtoFunc* Main);
+void luaU_optchunk(Proto* Main);
/* from print.c */
-void luaU_printchunk(TProtoFunc* Main);
+void luaU_printchunk(const Proto* Main);
/* from test.c */
-void luaU_testchunk(TProtoFunc* Main);
-TObject* luaU_getconstant(TProtoFunc* tf, int i, int at);
-
-#define INFO(tf,p,I) luaU_opcodeinfo(tf,p,I,__FILE__,__LINE__)
+void luaU_testchunk(const Proto* Main);
-/* fake (but convenient) opcodes */
-#define NOP 255
-#define STACK (-1)
-#define ARGS (-2)
-#define VARARGS (-3)
+#define Sizeof(x) ((int)sizeof(x))
diff --git a/src/luac/opcode.c b/src/luac/opcode.c
deleted file mode 100644
index c2d4ae7d..00000000
--- a/src/luac/opcode.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
-** $Id: opcode.c,v 1.9 1999/05/25 19:58:55 lhf Exp $
-** opcode information
-** See Copyright Notice in lua.h
-*/
-
-#include "luac.h"
-
-enum { /* for Opcode.args */
- ARGS_NONE,
- ARGS_B,
- ARGS_W,
- ARGS_BB,
- ARGS_WB
-};
-
-static Opcode Info[]= /* ORDER lopcodes.h */
-{
-#include "opcode.h"
-};
-
-static Opcode Fake[]= /* ORDER luac.h */
-{
-{ "NOP", NOP, NOP, ARGS_NONE, -1, -1 },
-{ "STACK", STACK, STACK, ARGS_B, -1, -1 },
-{ "ARGS", ARGS, ARGS, ARGS_B, -1, -1 },
-{ "VARARGS", VARARGS, VARARGS, ARGS_B, -1, -1 },
-};
-
-#define NOPCODES (sizeof(Info)/sizeof(Info[0]))
-
-int luaU_opcodeinfo(TProtoFunc* tf, Byte* p, Opcode* I, char* xFILE, int xLINE)
-{
- Opcode OP;
- Byte* code=tf->code;
- int op=*p;
- int size=1;
- if (p==code) /* first byte is STACK */
- {
- OP=Fake[-STACK];
- OP.arg=op;
- }
- else if (p==code+1) /* second byte is ARGS or VARARGS */
- {
- if (op<ZEROVARARG)
- {
- OP=Fake[-ARGS];
- OP.arg=op;
- }
- else
- {
- OP=Fake[-VARARGS];
- OP.arg=op-ZEROVARARG;
- }
- }
- else if (op==NOP) /* NOP is fake */
- {
- OP=Fake[0];
- }
- else if (op>=NOPCODES) /* cannot happen */
- {
- luaL_verror("[%s:%d] bad opcode %d at pc=%d" IN,
- xFILE,xLINE,op,(int)(p-code),INLOC);
- return 0;
- }
- else /* ordinary opcode */
- {
- OP=Info[op];
- switch (OP.args)
- {
- case ARGS_NONE: size=1;
- break;
- case ARGS_B: size=2; OP.arg=p[1];
- break;
- case ARGS_W: size=3; OP.arg=(p[1]<<8)+p[2];
- break;
- case ARGS_BB: size=3; OP.arg=p[1]; OP.arg2=p[2];
- break;
- case ARGS_WB: size=4; OP.arg=(p[1]<<8)+p[2]; OP.arg2=p[3];
- break;
- default: /* cannot happen */
- luaL_verror("[%s:%d] bad args %d for %s at pc=%d" IN,
- __FILE__,__LINE__,OP.args,OP.name,(int)(p-code),INLOC);
- break;
- }
- }
- *I=OP;
- return size;
-}
-
-int luaU_codesize(TProtoFunc* tf)
-{
- Byte* code=tf->code;
- Byte* p=code;
- for (;;)
- {
- Opcode OP;
- p+=INFO(tf,p,&OP);
- if (OP.op==ENDCODE) break;
- }
- return p-code;
-}
diff --git a/src/luac/opcode.h b/src/luac/opcode.h
deleted file mode 100644
index 4ae910f5..00000000
--- a/src/luac/opcode.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
-** $Id: opcode.h,v 1.1 1999/03/25 13:43:05 lhf Exp $
-** opcode info to be #included into opcode.c
-** extracted automatically from lopcodes.h by mkopcodeh -- DO NOT EDIT
-** See Copyright Notice in lua.h
-*/
-{ "ENDCODE", ENDCODE, ENDCODE, ARGS_NONE, -1, -1 },
-{ "RETCODE", RETCODE, RETCODE, ARGS_B, -1, -1 },
-{ "CALL", CALL, CALL, ARGS_BB, -1, -1 },
-{ "TAILCALL", TAILCALL, TAILCALL, ARGS_BB, -1, -1 },
-{ "PUSHNIL", PUSHNIL, PUSHNIL, ARGS_B, -1, -1 },
-{ "POP", POP, POP, ARGS_B, -1, -1 },
-{ "PUSHNUMBERW", PUSHNUMBERW, PUSHNUMBER, ARGS_W, -1, -1 },
-{ "PUSHNUMBER", PUSHNUMBER, PUSHNUMBER, ARGS_B, -1, -1 },
-{ "PUSHNUMBERNEGW", PUSHNUMBERNEGW, PUSHNUMBERNEG, ARGS_W, -1, -1 },
-{ "PUSHNUMBERNEG", PUSHNUMBERNEG, PUSHNUMBERNEG, ARGS_B, -1, -1 },
-{ "PUSHCONSTANTW", PUSHCONSTANTW, PUSHCONSTANT, ARGS_W, -1, -1 },
-{ "PUSHCONSTANT", PUSHCONSTANT, PUSHCONSTANT, ARGS_B, -1, -1 },
-{ "PUSHUPVALUE", PUSHUPVALUE, PUSHUPVALUE, ARGS_B, -1, -1 },
-{ "PUSHLOCAL", PUSHLOCAL, PUSHLOCAL, ARGS_B, -1, -1 },
-{ "GETGLOBALW", GETGLOBALW, GETGLOBAL, ARGS_W, -1, -1 },
-{ "GETGLOBAL", GETGLOBAL, GETGLOBAL, ARGS_B, -1, -1 },
-{ "GETTABLE", GETTABLE, GETTABLE, ARGS_NONE, -1, -1 },
-{ "GETDOTTEDW", GETDOTTEDW, GETDOTTED, ARGS_W, -1, -1 },
-{ "GETDOTTED", GETDOTTED, GETDOTTED, ARGS_B, -1, -1 },
-{ "PUSHSELFW", PUSHSELFW, PUSHSELF, ARGS_W, -1, -1 },
-{ "PUSHSELF", PUSHSELF, PUSHSELF, ARGS_B, -1, -1 },
-{ "CREATEARRAYW", CREATEARRAYW, CREATEARRAY, ARGS_W, -1, -1 },
-{ "CREATEARRAY", CREATEARRAY, CREATEARRAY, ARGS_B, -1, -1 },
-{ "SETLOCAL", SETLOCAL, SETLOCAL, ARGS_B, -1, -1 },
-{ "SETGLOBALW", SETGLOBALW, SETGLOBAL, ARGS_W, -1, -1 },
-{ "SETGLOBAL", SETGLOBAL, SETGLOBAL, ARGS_B, -1, -1 },
-{ "SETTABLEPOP", SETTABLEPOP, SETTABLEPOP, ARGS_NONE, -1, -1 },
-{ "SETTABLE", SETTABLE, SETTABLE, ARGS_B, -1, -1 },
-{ "SETLISTW", SETLISTW, SETLIST, ARGS_WB, -1, -1 },
-{ "SETLIST", SETLIST, SETLIST, ARGS_BB, -1, -1 },
-{ "SETMAP", SETMAP, SETMAP, ARGS_B, -1, -1 },
-{ "NEQOP", NEQOP, NEQOP, ARGS_NONE, -1, -1 },
-{ "EQOP", EQOP, EQOP, ARGS_NONE, -1, -1 },
-{ "LTOP", LTOP, LTOP, ARGS_NONE, -1, -1 },
-{ "LEOP", LEOP, LEOP, ARGS_NONE, -1, -1 },
-{ "GTOP", GTOP, GTOP, ARGS_NONE, -1, -1 },
-{ "GEOP", GEOP, GEOP, ARGS_NONE, -1, -1 },
-{ "ADDOP", ADDOP, ADDOP, ARGS_NONE, -1, -1 },
-{ "SUBOP", SUBOP, SUBOP, ARGS_NONE, -1, -1 },
-{ "MULTOP", MULTOP, MULTOP, ARGS_NONE, -1, -1 },
-{ "DIVOP", DIVOP, DIVOP, ARGS_NONE, -1, -1 },
-{ "POWOP", POWOP, POWOP, ARGS_NONE, -1, -1 },
-{ "CONCOP", CONCOP, CONCOP, ARGS_NONE, -1, -1 },
-{ "MINUSOP", MINUSOP, MINUSOP, ARGS_NONE, -1, -1 },
-{ "NOTOP", NOTOP, NOTOP, ARGS_NONE, -1, -1 },
-{ "ONTJMPW", ONTJMPW, ONTJMP, ARGS_W, -1, -1 },
-{ "ONTJMP", ONTJMP, ONTJMP, ARGS_B, -1, -1 },
-{ "ONFJMPW", ONFJMPW, ONFJMP, ARGS_W, -1, -1 },
-{ "ONFJMP", ONFJMP, ONFJMP, ARGS_B, -1, -1 },
-{ "JMPW", JMPW, JMP, ARGS_W, -1, -1 },
-{ "JMP", JMP, JMP, ARGS_B, -1, -1 },
-{ "IFFJMPW", IFFJMPW, IFFJMP, ARGS_W, -1, -1 },
-{ "IFFJMP", IFFJMP, IFFJMP, ARGS_B, -1, -1 },
-{ "IFTUPJMPW", IFTUPJMPW, IFTUPJMP, ARGS_W, -1, -1 },
-{ "IFTUPJMP", IFTUPJMP, IFTUPJMP, ARGS_B, -1, -1 },
-{ "IFFUPJMPW", IFFUPJMPW, IFFUPJMP, ARGS_W, -1, -1 },
-{ "IFFUPJMP", IFFUPJMP, IFFUPJMP, ARGS_B, -1, -1 },
-{ "CLOSUREW", CLOSUREW, CLOSURE, ARGS_WB, -1, -1 },
-{ "CLOSURE", CLOSURE, CLOSURE, ARGS_BB, -1, -1 },
-{ "SETLINEW", SETLINEW, SETLINE, ARGS_W, -1, -1 },
-{ "SETLINE", SETLINE, SETLINE, ARGS_B, -1, -1 },
-{ "LONGARGW", LONGARGW, LONGARG, ARGS_W, -1, -1 },
-{ "LONGARG", LONGARG, LONGARG, ARGS_B, -1, -1 },
-{ "CHECKSTACK", CHECKSTACK, CHECKSTACK, ARGS_B, -1, -1 },
diff --git a/src/luac/opt.c b/src/luac/opt.c
index e2becc2a..e51a0868 100644
--- a/src/luac/opt.c
+++ b/src/luac/opt.c
@@ -1,5 +1,5 @@
/*
-** $Id: opt.c,v 1.12 1999/07/02 19:34:26 lhf Exp $
+** $Id: opt.c,v 1.22 2000/10/31 16:57:23 lhf Exp $
** optimize bytecodes
** See Copyright Notice in lua.h
*/
@@ -7,275 +7,121 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "luac.h"
-static void FixArg(Byte* p, int i, int j, int isconst)
-{
- if (j==i)
- ;
- else if (i<=MAX_BYTE) /* j<i, so j fits where i did */
- p[1]=j;
- else if (i<=MAX_WORD)
- {
- if (isconst && j<=MAX_BYTE) /* may use byte variant instead */
- {
- p[0]++; /* byte variant follows word variant */
- p[1]=j;
- p[2]=NOP;
- }
- else /* stuck with word variant */
- {
- p[1]=j>>8;
- p[2]=j;
- }
- }
- else /* previous instruction must've been LONGARG */
- {
- if (isconst && j<=MAX_WORD) p[-2]=p[-1]=NOP; else p[-1]=j>>16;
- p[1]=j>>8;
- p[2]=j;
- }
-}
+#include "luac.h"
-static void FixConstants(TProtoFunc* tf, int* C)
+static int MapConstant(Hash* t, int j, const TObject* key)
{
- Byte* code=tf->code;
- Byte* p=code;
- int longarg=0;
- for (;;)
+ const TObject* o=luaH_get(L,t,key);
+ if (ttype(o)==LUA_TNUMBER)
+ return (int) nvalue(o);
+ else
{
- Opcode OP;
- int n=INFO(tf,p,&OP);
- int op=OP.class;
- int i=OP.arg+longarg;
- longarg=0;
- if (op==PUSHCONSTANT || op==GETGLOBAL || op==GETDOTTED ||
- op==PUSHSELF || op==SETGLOBAL || op==CLOSURE)
- FixArg(p,i,C[i],1);
- else if (op==LONGARG) longarg=i<<16;
- else if (op==ENDCODE) break;
- p+=n;
+ TObject val;
+ ttype(&val)=LUA_TNUMBER;
+ nvalue(&val)=j;
+ *luaH_set(L,t,key)=val;
+ LUA_ASSERT(j>=0,"MapConstant returns negative!");
+ return j;
}
}
-#define UNREF 1 /* "type" of unused constants */
-#define BIAS 128 /* mark for used constants */
-
-static void NoUnrefs(TProtoFunc* tf)
+static int MapConstants(Proto* tf, Hash* map)
{
- int i,n=tf->nconsts;
- Byte* code=tf->code;
- Byte* p=code;
- int longarg=0;
- for (;;) /* mark all used constants */
- {
- Opcode OP;
- int n=INFO(tf,p,&OP);
- int op=OP.class;
- int i=OP.arg+longarg;
- longarg=0;
- if (op==PUSHCONSTANT || op==GETGLOBAL || op==GETDOTTED ||
- op==PUSHSELF || op==SETGLOBAL || op==CLOSURE)
- {
- TObject* o=tf->consts+i;
- if (ttype(o)<=0) ttype(o)+=BIAS; /* mark as used */
- }
- else if (op==LONGARG) longarg=i<<16;
- else if (op==ENDCODE) break;
- p+=n;
- }
- for (i=0; i<n; i++) /* mark all unused constants */
+ int i,j,k,n,m=0;
+ TObject o;
+ j=0; n=tf->nknum; ttype(&o)=LUA_TNUMBER;
+ for (i=0; i<n; i++)
{
- TObject* o=tf->consts+i;
- if (ttype(o)<=0)
- ttype(o)=UNREF; /* mark as unused */
- else
- ttype(o)-=BIAS; /* unmark used constant */
+ nvalue(&o)=tf->knum[i];
+ k=MapConstant(map,j,&o);
+ if (k==j) j++;
}
-}
-
-#define CMP(oa,ob,f) memcmp(&f(oa),&f(ob),sizeof(f(oa)))
-
-static int compare(TProtoFunc* tf, int ia, int ib)
-{
- TObject* oa=tf->consts+ia;
- TObject* ob=tf->consts+ib;
- int t=ttype(oa)-ttype(ob);
- if (t) return t;
- switch (ttype(oa))
+ m=j;
+ j=0; n=tf->nkstr; ttype(&o)=LUA_TSTRING;
+ for (i=0; i<n; i++)
{
- case LUA_T_NUMBER: return CMP(oa,ob,nvalue);
- case LUA_T_STRING: return CMP(oa,ob,tsvalue);
- case LUA_T_PROTO: return CMP(oa,ob,tfvalue);
- case LUA_T_NIL: return 0;
- case UNREF: return 0;
- default: return ia-ib; /* cannot happen */
+ tsvalue(&o)=tf->kstr[i];
+ k=MapConstant(map,j,&o);
+ if (k==j) j++;
}
+ return m+j;
}
-static TProtoFunc* TF; /* for sort */
-
-static int compare1(const void* a, const void* b)
-{
- int ia=*(int*)a;
- int ib=*(int*)b;
- int t=compare(TF,ia,ib);
- return (t) ? t : ia-ib;
-}
-
-static void OptConstants(TProtoFunc* tf)
+static void PackConstants(Proto* tf, Hash* map)
{
- static int* C=NULL;
- static int* D=NULL;
- int i,k;
- int n=tf->nconsts;
- if (n==0) return;
- luaM_reallocvector(C,n,int);
- luaM_reallocvector(D,n,int);
- NoUnrefs(tf);
- for (i=0; i<n; i++) C[i]=D[i]=i; /* group duplicates */
- TF=tf; qsort(C,n,sizeof(C[0]),compare1);
- k=C[0]; /* build duplicate table */
- for (i=1; i<n; i++)
- {
- int j=C[i];
- if (compare(tf,k,j)==0) D[j]=k; else k=j;
- }
- k=0; /* build rename map & pack constants */
+ int i,j,k,n;
+ TObject o;
+#ifdef DEBUG
+ printf("%p before pack nknum=%d nkstr=%d\n",tf,tf->nknum,tf->nkstr);
+#endif
+ j=0; n=tf->nknum; ttype(&o)=LUA_TNUMBER;
for (i=0; i<n; i++)
{
- if (D[i]==i) /* new value */
- {
- TObject* o=tf->consts+i;
- if (ttype(o)!=UNREF)
- {
- tf->consts[k]=tf->consts[i];
- C[i]=k++;
- }
- }
- else C[i]=C[D[i]];
+ nvalue(&o)=tf->knum[i];
+ k=MapConstant(map,-1,&o);
+ if (k==j) tf->knum[j++]=tf->knum[i];
}
- if (k<n)
+ tf->nknum=j;
+ j=0; n=tf->nkstr; ttype(&o)=LUA_TSTRING;
+ for (i=0; i<n; i++)
{
-printf("\t" SOURCE " reduced constants from %d to %d\n",
- tf->source->str,tf->lineDefined,n,k);
- FixConstants(tf,C);
- tf->nconsts=k;
+ tsvalue(&o)=tf->kstr[i];
+ k=MapConstant(map,-1,&o);
+ if (k==j) tf->kstr[j++]=tf->kstr[i];
}
+ tf->nkstr=j;
+#ifdef DEBUG
+ printf("%p after pack nknum=%d nkstr=%d\n",tf,tf->nknum,tf->nkstr);
+#endif
}
-static int NoDebug(TProtoFunc* tf)
+static void OptConstants(Proto* tf)
{
- Byte* code=tf->code;
- Byte* p=code;
- int lop=NOP; /* last opcode */
- int nop=0;
- for (;;) /* change SETLINE to NOP */
+ Instruction* p;
+ int n=tf->nknum+tf->nkstr;
+ Hash* map=luaH_new(L,n);
+ int m=MapConstants(tf,map);
+#ifdef DEBUG
+ printf("%p n=%d m=%d %s\n",tf,n,m,(m==n)?"nothing to optimize":"yes!");
+#endif
+ if (m==n) return;
+ for (p=tf->code;; p++)
{
- Opcode OP;
- int n=INFO(tf,p,&OP);
- int op=OP.class;
- if (op==NOP) ++nop;
- else if (op==SETLINE)
+ Instruction i=*p;
+ int op=GET_OPCODE(i);
+ switch (op)
{
- int m;
- if (lop==LONGARG) m=2; else if (lop==LONGARGW) m=3; else m=0;
- nop+=n+m; memset(p-m,NOP,n+m);
+ TObject o;
+ int j,k;
+ case OP_PUSHNUM: case OP_PUSHNEGNUM:
+ j=GETARG_U(i);
+ ttype(&o)=LUA_TNUMBER; nvalue(&o)=tf->knum[j];
+ k=MapConstant(map,-1,&o);
+ if (k!=j) *p=CREATE_U(op,k);
+ break;
+ case OP_PUSHSTRING: case OP_GETGLOBAL: case OP_GETDOTTED:
+ case OP_PUSHSELF: case OP_SETGLOBAL:
+ j=GETARG_U(i);
+ ttype(&o)=LUA_TSTRING; tsvalue(&o)=tf->kstr[j];
+ k=MapConstant(map,-1,&o);
+ if (k!=j) *p=CREATE_U(op,k);
+ break;
+ case OP_END:
+ PackConstants(tf,map);
+ luaH_free(L,map);
+ return;
+ default:
+ break;
}
- else if (op==ENDCODE) break;
- lop=OP.op;
- p+=n;
}
- return nop;
}
-static int FixJump(TProtoFunc* tf, Byte* a, Byte* b)
-{
- Byte* p;
- int nop=0;
- for (p=a; p<b; )
- {
- Opcode OP;
- int n=INFO(tf,p,&OP);
- int op=OP.class;
- if (op==NOP) ++nop;
- else if (op==ENDCODE) break;
- p+=n;
- }
- return nop;
-}
+#define OptFunction luaU_optchunk
-static void FixJumps(TProtoFunc* tf)
-{
- Byte* code=tf->code;
- Byte* p=code;
- int longarg=0;
- for (;;)
- {
- Opcode OP;
- int n=INFO(tf,p,&OP);
- int op=OP.class;
- int i=OP.arg+longarg;
- int nop=0;
- longarg=0;
- if (op==ENDCODE) break;
- else if (op==IFTUPJMP || op==IFFUPJMP)
- nop=FixJump(tf,p-i+n,p);
- else if (op==ONTJMP || op==ONFJMP || op==JMP || op==IFFJMP)
- nop=FixJump(tf,p,p+i+n);
- else if (op==LONGARG) longarg=i<<16;
- if (nop>0) FixArg(p,i,i-nop,0);
- p+=n;
- }
-}
-
-static void PackCode(TProtoFunc* tf)
-{
- Byte* code=tf->code;
- Byte* p=code;
- Byte* q=code;
- for (;;)
- {
- Opcode OP;
- int n=INFO(tf,p,&OP);
- int op=OP.class;
- if (op!=NOP) { memcpy(q,p,n); q+=n; }
- p+=n;
- if (op==ENDCODE) break;
- }
-printf("\t" SOURCE " reduced code from %d to %d\n",
- tf->source->str,tf->lineDefined,(int)(p-code),(int)(q-code));
-}
-
-static void OptCode(TProtoFunc* tf)
-{
- if (NoDebug(tf)==0) return; /* cannot improve code */
- FixJumps(tf);
- PackCode(tf);
-}
-
-static void OptFunction(TProtoFunc* tf);
-
-static void OptFunctions(TProtoFunc* tf)
-{
- int i,n=tf->nconsts;
- for (i=0; i<n; i++)
- {
- TObject* o=tf->consts+i;
- if (ttype(o)==LUA_T_PROTO) OptFunction(tfvalue(o));
- }
-}
-
-static void OptFunction(TProtoFunc* tf)
+void OptFunction(Proto* tf)
{
+ int i,n=tf->nkproto;
OptConstants(tf);
- OptCode(tf);
- OptFunctions(tf);
- tf->source=luaS_new("");
- tf->locvars=NULL;
-}
-
-void luaU_optchunk(TProtoFunc* Main)
-{
- OptFunction(Main);
+ for (i=0; i<n; i++) OptFunction(tf->kproto[i]);
}
diff --git a/src/luac/print.c b/src/luac/print.c
index b1ee8934..4ffc8b3d 100644
--- a/src/luac/print.c
+++ b/src/luac/print.c
@@ -1,223 +1,99 @@
/*
-** $Id: print.c,v 1.21 1999/05/25 19:58:55 lhf Exp $
+** $Id: print.c,v 1.32 2000/11/06 20:04:36 lhf Exp $
** print bytecodes
** See Copyright Notice in lua.h
*/
#include <stdio.h>
#include <stdlib.h>
+
#include "luac.h"
-#ifdef DEBUG
-static void PrintConstants(TProtoFunc* tf)
+/* macros used in print.h, included in PrintCode */
+#define P_OP(x) printf("%-11s\t",x)
+#define P_NONE
+#define P_AB printf("%d %d",GETARG_A(i),GETARG_B(i))
+#define P_F printf("%d %d\t; %p",GETARG_A(i),GETARG_B(i),tf->kproto[GETARG_A(i)])
+#define P_J printf("%d\t; to %d",GETARG_S(i),GETARG_S(i)+at+1)
+#define P_Q PrintString(tf,GETARG_U(i))
+#define P_K printf("%d\t; %s",GETARG_U(i),tf->kstr[GETARG_U(i)]->str)
+#define P_L PrintLocal(tf,GETARG_U(i),at-1)
+#define P_N printf("%d\t; " NUMBER_FMT,GETARG_U(i),tf->knum[GETARG_U(i)])
+#define P_S printf("%d",GETARG_S(i))
+#define P_U printf("%u",GETARG_U(i))
+
+static void PrintString(const Proto* tf, int n)
{
- int i,n=tf->nconsts;
- printf("constants (%d) for %p:\n",n,tf);
- for (i=0; i<n; i++)
+ const char* s=tf->kstr[n]->str;
+ printf("%d\t; ",n);
+ putchar('"');
+ for (; *s; s++)
{
- TObject* o=tf->consts+i;
- printf("%6d ",i);
- switch (ttype(o))
+ switch (*s)
{
- case LUA_T_NUMBER:
- printf("N " NUMBER_FMT "\n",(double)nvalue(o));
- break;
- case LUA_T_STRING:
- printf("S %p\t\"%s\"\n",tsvalue(o),svalue(o));
- break;
- case LUA_T_PROTO:
- printf("F %p\n",tfvalue(o));
- break;
- case LUA_T_NIL:
- printf("nil\n");
- break;
- default: /* cannot happen */
- printf("? type=%d\n",ttype(o));
- break;
+ case '"': printf("\\\""); break;
+ case '\a': printf("\\a"); break;
+ case '\b': printf("\\b"); break;
+ case '\f': printf("\\f"); break;
+ case '\n': printf("\\n"); break;
+ case '\r': printf("\\r"); break;
+ case '\t': printf("\\t"); break;
+ case '\v': printf("\\v"); break;
+ default: putchar(*s); break;
}
}
+ putchar('"');
}
-#endif
-static void PrintConstant(TProtoFunc* tf, int i, int at)
+static void PrintLocal(const Proto* tf, int n, int pc)
{
- TObject* o=luaU_getconstant(tf,i,at);
- switch (ttype(o))
- {
- case LUA_T_NUMBER:
- printf(NUMBER_FMT,(double)nvalue(o));
- break;
- case LUA_T_STRING:
- printf("\"%s\"",svalue(o));
- break;
- case LUA_T_PROTO:
- printf("function at %p",(void*)tfvalue(o));
- break;
- case LUA_T_NIL:
- printf("(nil)");
- break;
- default: /* cannot happen */
- luaU_badconstant("print",i,o,tf);
- break;
- }
+ const char* s=luaF_getlocalname(tf,n+1,pc);
+ printf("%u",n);
+ if (s!=NULL) printf("\t; %s",s);
}
-static void PrintCode(TProtoFunc* tf)
+static void PrintCode(const Proto* tf)
{
- Byte* code=tf->code;
- Byte* p=code;
- int line=0;
- int longarg=0;
+ const Instruction* code=tf->code;
+ const Instruction* p=code;
for (;;)
{
- Opcode OP;
- int n=INFO(tf,p,&OP);
- int i=OP.arg+longarg;
- int at=p-code;
- longarg=0;
- printf("%6d ",at);
- {
- Byte* q=p;
- int j=n;
- while (j--) printf("%02X",*q++);
- }
- printf("%*s%-14s ",2*(5-n),"",OP.name);
- if (OP.arg >=0) printf("%d",i);
- if (OP.arg2>=0) printf(" %d",OP.arg2);
-
- switch (OP.class)
- {
-
- case ENDCODE:
- printf("\n");
- return;
-
- case PUSHCONSTANT:
- case GETGLOBAL:
- case SETGLOBAL:
- case GETDOTTED:
- case PUSHSELF:
- case CLOSURE:
- printf("\t; ");
- PrintConstant(tf,i,at);
- break;
-
- case PUSHLOCAL:
- case SETLOCAL:
- {
- char* s=luaF_getlocalname(tf,i+1,line);
- if (s) printf("\t; %s",s);
- break;
- }
-
- case SETLINE:
- printf("\t; " SOURCE,tf->source->str,line=i);
- break;
-
- case LONGARG:
- longarg=i<<16;
- break;
-
-/* suggested by Norman Ramsey <nr@cs.virginia.edu> */
- case ONTJMP:
- case ONFJMP:
- case JMP:
- case IFFJMP:
- printf("\t; to %d",at+i+n);
- break;
- case IFTUPJMP:
- case IFFUPJMP:
- printf("\t; to %d",at-i+n);
- break;
-
- }
- printf("\n");
- p+=n;
- }
-}
-
-static void PrintLocals(TProtoFunc* tf)
-{
- LocVar* v=tf->locvars;
- int n,i;
- if (v==NULL || v->line<0) return;
- n=tf->code[1]; if (n>=ZEROVARARG) n-=ZEROVARARG;
- printf("locals:");
- for (i=0; i<n; v++,i++) /* arguments */
- printf(" %s",v->varname->str);
- for (; v->line>=0; v++)
- {
- if (v->varname==NULL)
- {
- --i; if (i<0) luaL_verror("bad locvars[%d]",v-tf->locvars); else printf(")");
- }
- else
- {
- ++i; printf(" (%s",v->varname->str);
+ int at=p-code+1;
+ Instruction i=*p;
+ int line=luaG_getline(tf->lineinfo,at-1,1,NULL);
+ printf("%6d\t",at);
+ if (line>=0) printf("[%d]\t",line); else printf("[-]\t");
+ switch (GET_OPCODE(i)) {
+#include "print.h"
}
+ printf("\n");
+ if (i==OP_END) break;
+ p++;
}
- i-=n;
- while (i--) printf(")");
- printf("\n");
}
#define IsMain(tf) (tf->lineDefined==0)
-static void PrintHeader(TProtoFunc* tf, TProtoFunc* Main, int at)
-{
- int size=luaU_codesize(tf);
- if (IsMain(tf))
- printf("\nmain " SOURCE " (%d bytes at %p)\n",
- tf->source->str,tf->lineDefined,size,tf);
- else
- {
- printf("\nfunction " SOURCE " (%d bytes at %p); used at ",
- tf->source->str,tf->lineDefined,size,tf);
- if (Main && IsMain(Main))
- printf("main");
- else
- printf("%p",Main);
- printf("+%d\n",at);
- }
-}
-
-static void PrintFunction(TProtoFunc* tf, TProtoFunc* Main, int at);
+#define SS(x) (x==1)?"":"s"
+#define S(x) x,SS(x)
-static void PrintFunctions(TProtoFunc* Main)
+static void PrintHeader(const Proto* tf)
{
- Byte* code=Main->code;
- Byte* p=code;
- int longarg=0;
- for (;;)
- {
- Opcode OP;
- int n=INFO(Main,p,&OP);
- int op=OP.class;
- int i=OP.arg+longarg;
- longarg=0;
- if (op==PUSHCONSTANT || op==CLOSURE)
- {
- TObject* o=Main->consts+i;
- if (ttype(o)==LUA_T_PROTO) PrintFunction(tfvalue(o),Main,(int)(p-code));
- }
- else if (op==LONGARG) longarg=i<<16;
- else if (op==ENDCODE) break;
- p+=n;
- }
+ printf("\n%s " SOURCE_FMT " (%d instruction%s/%d bytes at %p)\n",
+ IsMain(tf)?"main":"function",SOURCE,
+ S(tf->ncode),tf->ncode*Sizeof(Instruction),tf);
+ printf("%d%s param%s, %d stack%s, ",
+ tf->numparams,tf->is_vararg?"+":"",SS(tf->numparams),S(tf->maxstacksize));
+ printf("%d local%s, %d string%s, %d number%s, %d function%s, %d line%s\n",
+ S(tf->nlocvars),S(tf->nkstr),S(tf->nknum),S(tf->nkproto),S(tf->nlineinfo));
}
-static void PrintFunction(TProtoFunc* tf, TProtoFunc* Main, int at)
-{
- PrintHeader(tf,Main,at);
- PrintLocals(tf);
- PrintCode(tf);
-#ifdef DEBUG
- PrintConstants(tf);
-#endif
- PrintFunctions(tf);
-}
+#define PrintFunction luaU_printchunk
-void luaU_printchunk(TProtoFunc* Main)
+void PrintFunction(const Proto* tf)
{
- PrintFunction(Main,0,0);
+ int i,n=tf->nkproto;
+ PrintHeader(tf);
+ PrintCode(tf);
+ for (i=0; i<n; i++) PrintFunction(tf->kproto[i]);
}
diff --git a/src/luac/print.h b/src/luac/print.h
new file mode 100644
index 00000000..5f74e149
--- /dev/null
+++ b/src/luac/print.h
@@ -0,0 +1,55 @@
+/*
+** $Id: print.h,v 1.1 2000/11/06 20:03:12 lhf Exp $
+** extracted automatically from lopcodes.h by mkprint.lua -- DO NOT EDIT
+** See Copyright Notice in lua.h
+*/
+
+ case OP_END: P_OP("END"); P_NONE; break;
+ case OP_RETURN: P_OP("RETURN"); P_U; break;
+ case OP_CALL: P_OP("CALL"); P_AB; break;
+ case OP_TAILCALL: P_OP("TAILCALL"); P_AB; break;
+ case OP_PUSHNIL: P_OP("PUSHNIL"); P_U; break;
+ case OP_POP: P_OP("POP"); P_U; break;
+ case OP_PUSHINT: P_OP("PUSHINT"); P_S; break;
+ case OP_PUSHSTRING: P_OP("PUSHSTRING"); P_Q; break;
+ case OP_PUSHNUM: P_OP("PUSHNUM"); P_N; break;
+ case OP_PUSHNEGNUM: P_OP("PUSHNEGNUM"); P_N; break;
+ case OP_PUSHUPVALUE: P_OP("PUSHUPVALUE"); P_U; break;
+ case OP_GETLOCAL: P_OP("GETLOCAL"); P_L; break;
+ case OP_GETGLOBAL: P_OP("GETGLOBAL"); P_K; break;
+ case OP_GETTABLE: P_OP("GETTABLE"); P_NONE; break;
+ case OP_GETDOTTED: P_OP("GETDOTTED"); P_K; break;
+ case OP_GETINDEXED: P_OP("GETINDEXED"); P_L; break;
+ case OP_PUSHSELF: P_OP("PUSHSELF"); P_K; break;
+ case OP_CREATETABLE: P_OP("CREATETABLE"); P_U; break;
+ case OP_SETLOCAL: P_OP("SETLOCAL"); P_L; break;
+ case OP_SETGLOBAL: P_OP("SETGLOBAL"); P_K; break;
+ case OP_SETTABLE: P_OP("SETTABLE"); P_AB; break;
+ case OP_SETLIST: P_OP("SETLIST"); P_AB; break;
+ case OP_SETMAP: P_OP("SETMAP"); P_U; break;
+ case OP_ADD: P_OP("ADD"); P_NONE; break;
+ case OP_ADDI: P_OP("ADDI"); P_S; break;
+ case OP_SUB: P_OP("SUB"); P_NONE; break;
+ case OP_MULT: P_OP("MULT"); P_NONE; break;
+ case OP_DIV: P_OP("DIV"); P_NONE; break;
+ case OP_POW: P_OP("POW"); P_NONE; break;
+ case OP_CONCAT: P_OP("CONCAT"); P_U; break;
+ case OP_MINUS: P_OP("MINUS"); P_NONE; break;
+ case OP_NOT: P_OP("NOT"); P_NONE; break;
+ case OP_JMPNE: P_OP("JMPNE"); P_J; break;
+ case OP_JMPEQ: P_OP("JMPEQ"); P_J; break;
+ case OP_JMPLT: P_OP("JMPLT"); P_J; break;
+ case OP_JMPLE: P_OP("JMPLE"); P_J; break;
+ case OP_JMPGT: P_OP("JMPGT"); P_J; break;
+ case OP_JMPGE: P_OP("JMPGE"); P_J; break;
+ case OP_JMPT: P_OP("JMPT"); P_J; break;
+ case OP_JMPF: P_OP("JMPF"); P_J; break;
+ case OP_JMPONT: P_OP("JMPONT"); P_J; break;
+ case OP_JMPONF: P_OP("JMPONF"); P_J; break;
+ case OP_JMP: P_OP("JMP"); P_J; break;
+ case OP_PUSHNILJMP: P_OP("PUSHNILJMP"); P_NONE; break;
+ case OP_FORPREP: P_OP("FORPREP"); P_J; break;
+ case OP_FORLOOP: P_OP("FORLOOP"); P_J; break;
+ case OP_LFORPREP: P_OP("LFORPREP"); P_J; break;
+ case OP_LFORLOOP: P_OP("LFORLOOP"); P_J; break;
+ case OP_CLOSURE: P_OP("CLOSURE"); P_F; break;
diff --git a/src/luac/stubs.c b/src/luac/stubs.c
index 5f38940e..74f509eb 100644
--- a/src/luac/stubs.c
+++ b/src/luac/stubs.c
@@ -1,68 +1,109 @@
/*
-** $Id: stubs.c,v 1.11 1999/03/11 17:09:10 lhf Exp $
+** $Id: stubs.c,v 1.20 2000/10/31 16:57:23 lhf Exp $
** avoid runtime modules in luac
** See Copyright Notice in lua.h
*/
-#ifdef NOSTUBS
-
-/* according to gcc, ANSI C forbids an empty source file */
-void luaU_dummy(void);
-void luaU_dummy(void){}
-
-#else
-
-#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
+
+#include "ldo.h"
+#include "llex.h"
#include "luac.h"
+#undef L
+
+#ifndef NOSTUBS
+
+const char luac_ident[] = "$luac: " LUA_VERSION " " LUA_COPYRIGHT " $\n"
+ "$Authors: " LUA_AUTHORS " $";
/*
-* avoid lapi lauxlib lbuiltin ldo lgc ltable ltm lvm
-* use only lbuffer lfunc llex lmem lobject lparser lstate lstring lzio
+* avoid lapi ldebug ldo lgc lstate ltm lvm
+* use only lcode lfunc llex lmem lobject lparser lstring ltable lzio
*/
/* simplified from ldo.c */
-void lua_error(char* s)
-{
- if (s) fprintf(stderr,"luac: %s\n",s);
- exit(1);
+void lua_error (lua_State* L, const char* s) {
+ UNUSED(L);
+ if (s) fprintf(stderr,"luac: %s\n",s);
+ exit(1);
}
-/* copied from lauxlib.c */
-void luaL_verror (char *fmt, ...)
-{
- char buff[500];
- va_list argp;
- va_start(argp, fmt);
- vsprintf(buff, fmt, argp);
- va_end(argp);
- lua_error(buff);
+/* simplified from ldo.c */
+void luaD_breakrun (lua_State *L, int errcode) {
+ UNUSED(errcode);
+ lua_error(L,"memory allocation error");
}
-/* copied from lauxlib.c */
-void luaL_filesource (char *out, char *filename, int len) {
- if (filename == NULL) filename = "(stdin)";
- sprintf(out, "@%.*s", len-2, filename); /* -2 for '@' and '\0' */
+/* simplified from lstate.c */
+lua_State *lua_open (int stacksize) {
+ lua_State *L = luaM_new(NULL, lua_State);
+ if (L == NULL) return NULL; /* memory allocation error */
+ L->stack = NULL;
+ L->strt.size = L->udt.size = 0;
+ L->strt.nuse = L->udt.nuse = 0;
+ L->strt.hash = NULL;
+ L->udt.hash = NULL;
+ L->Mbuffer = NULL;
+ L->Mbuffsize = 0;
+ L->rootproto = NULL;
+ L->rootcl = NULL;
+ L->roottable = NULL;
+ L->TMtable = NULL;
+ L->last_tag = -1;
+ L->refArray = NULL;
+ L->refSize = 0;
+ L->refFree = NONEXT;
+ L->nblocks = sizeof(lua_State);
+ L->GCthreshold = MAX_INT; /* to avoid GC during pre-definitions */
+ L->callhook = NULL;
+ L->linehook = NULL;
+ L->allowhooks = 1;
+ L->errorJmp = NULL;
+ if (stacksize == 0)
+ stacksize = DEFAULT_STACK_SIZE;
+ else
+ stacksize += LUA_MINSTACK;
+ L->gt = luaH_new(L, 10); /* table of globals */
+ luaS_init(L);
+ luaX_init(L);
+ L->GCthreshold = 2*L->nblocks;
+ return L;
}
-/* avoid runtime modules in lstate.c */
-
-#include "lbuiltin.h"
-#include "ldo.h"
-#include "lgc.h"
-#include "ltable.h"
-#include "ltm.h"
-
-void luaB_predefine(void){}
-void luaC_hashcallIM(Hash *l){}
-void luaC_strcallIM(TaggedString *l){}
-void luaD_gcIM(TObject *o){}
-void luaH_free(Hash *frees){}
-void luaT_init(void){}
+/* copied from ldebug.c */
+int luaG_getline (int *lineinfo, int pc, int refline, int *prefi) {
+ int refi;
+ if (lineinfo == NULL || pc == -1)
+ return -1; /* no line info or function is not active */
+ refi = prefi ? *prefi : 0;
+ if (lineinfo[refi] < 0)
+ refline += -lineinfo[refi++];
+ LUA_ASSERT(lineinfo[refi] >= 0, "invalid line info");
+ while (lineinfo[refi] > pc) {
+ refline--;
+ refi--;
+ if (lineinfo[refi] < 0)
+ refline -= -lineinfo[refi--];
+ LUA_ASSERT(lineinfo[refi] >= 0, "invalid line info");
+ }
+ for (;;) {
+ int nextline = refline + 1;
+ int nextref = refi + 1;
+ if (lineinfo[nextref] < 0)
+ nextline += -lineinfo[nextref++];
+ LUA_ASSERT(lineinfo[nextref] >= 0, "invalid line info");
+ if (lineinfo[nextref] > pc)
+ break;
+ refline = nextline;
+ refi = nextref;
+ }
+ if (prefi) *prefi = refi;
+ return refline;
+}
/*
-* the code below avoids the lexer and the parser (llex lparser).
+* the code below avoids the lexer and the parser (llex lparser lcode).
* it is useful if you only want to load binary files.
* this works for interpreters like lua.c too.
*/
@@ -72,49 +113,14 @@ void luaT_init(void){}
#include "llex.h"
#include "lparser.h"
-void luaX_init(void){}
-void luaD_init(void){}
-
-TProtoFunc* luaY_parser(ZIO *z) {
- lua_error("parser not loaded");
- return NULL;
-}
-
-#else
-
-/* copied from lauxlib.c */
-int luaL_findstring (char *name, char *list[]) {
- int i;
- for (i=0; list[i]; i++)
- if (strcmp(list[i], name) == 0)
- return i;
- return -1; /* name not found */
-}
-
-/* copied from lauxlib.c */
-void luaL_chunkid (char *out, char *source, int len) {
- len -= 13; /* 13 = strlen("string ''...\0") */
- if (*source == '@')
- sprintf(out, "file `%.*s'", len, source+1);
- else if (*source == '(')
- strcpy(out, "(C code)");
- else {
- char *b = strchr(source , '\n'); /* stop string at first new line */
- int lim = (b && (b-source)<len) ? b-source : len;
- sprintf(out, "string `%.*s'", lim, source);
- strcpy(out+lim+(13-5), "...'"); /* 5 = strlen("...'\0") */
- }
+void luaX_init(lua_State *L) {
+ UNUSED(L);
}
-void luaD_checkstack(int n){}
-
-#define STACK_UNIT 128
-
-/* copied from ldo.c */
-void luaD_init (void) {
- L->stack.stack = luaM_newvector(STACK_UNIT, TObject);
- L->stack.top = L->stack.stack;
- L->stack.last = L->stack.stack+(STACK_UNIT-1);
+Proto *luaY_parser(lua_State *L, ZIO *z) {
+ UNUSED(z);
+ lua_error(L,"parser not loaded");
+ return NULL;
}
#endif
diff --git a/src/luac/test.c b/src/luac/test.c
deleted file mode 100644
index 78ba4556..00000000
--- a/src/luac/test.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
-** $Id: test.c,v 1.10 1999/07/02 19:34:26 lhf Exp $
-** test integrity
-** See Copyright Notice in lua.h
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "luac.h"
-
-#define AT "pc=%d"
-#define ATLOC 0)
-#define UNSAFE(s) \
- luaL_verror("unsafe code at " AT IN "\n " s,at,INLOC
-
-TObject* luaU_getconstant(TProtoFunc* tf, int i, int at)
-{
- if (i>=tf->nconsts) UNSAFE("bad constant #%d (max=%d)"),i,tf->nconsts-1,ATLOC;
- return tf->consts+i;
-}
-
-static int check(int n, TProtoFunc* tf, int at, int sp, int ss)
-{
- if (n==0) return sp;
- sp+=n;
- if (sp<00) UNSAFE("stack underflow (sp=%d)"),sp,ATLOC;
- if (sp>ss) UNSAFE("stack overflow (sp=%d ss=%d)"),sp,ss,ATLOC;
- return sp;
-}
-
-#define CHECK(before,after) \
- sp=check(-(before),tf,at,sp,ss), sp=check(after,tf,at,sp,ss)
-
-static int jmpok(TProtoFunc* tf, int size, int at, int d)
-{
- int to=at+d;
- if (to<2 || to>=size)
- UNSAFE("invalid jump to %d (valid range is 2..%d)"),to,size-1,ATLOC;
- return to;
-}
-
-static void TestStack(TProtoFunc* tf, int size, int* SP, int* JP)
-{
- Byte* code=tf->code;
- Byte* p=code;
- int longarg=0;
- int ss=0;
- int sp=0;
- for (;;)
- {
- Opcode OP;
- int n=INFO(tf,p,&OP);
- int op=OP.class;
- int i=OP.arg+longarg;
- int at=p-code;
- longarg=0;
- switch (op) /* test sanity of operands */
- {
- case PUSHCONSTANT:
- case GETGLOBAL:
- case GETDOTTED:
- case PUSHSELF:
- case SETGLOBAL:
- case CLOSURE:
- {
- TObject* o=luaU_getconstant(tf,i,at);
- if ((op==CLOSURE && ttype(o)!=LUA_T_PROTO)
- || (op==GETGLOBAL && ttype(o)!=LUA_T_STRING)
- || (op==SETGLOBAL && ttype(o)!=LUA_T_STRING))
- UNSAFE("bad operand to %s"),OP.name,ATLOC;
- break;
- }
- case PUSHLOCAL:
- if (i>=sp) UNSAFE("bad local #%d (max=%d)"),i,sp-1,ATLOC;
- break;
- case SETLOCAL:
- if (i>=(sp-1)) UNSAFE("bad local #%d (max=%d)"),i,sp-2,ATLOC;
- break;
- case ONTJMP:
- case ONFJMP: /* negate to remember ON?JMP */
- JP[at]=-jmpok(tf,size,at,i+n);
- break;
- case JMP: /* remember JMP targets */
- case IFFJMP:
- JP[at]= jmpok(tf,size,at,i+n);
- break;
- case IFTUPJMP:
- case IFFUPJMP:
- JP[at]= jmpok(tf,size,at,-i+n);
- break;
- }
-
- SP[at]=sp; /* remember depth before instruction */
-
- switch (op)
- {
- case STACK: ss=i; break;
- case ARGS: CHECK(0,i); break;
- case VARARGS: break;
- case ENDCODE: return;
- case RETCODE: CHECK(i,0); sp=i; break;
- case CALL: CHECK(OP.arg2+1,i); break;
- case TAILCALL: CHECK(OP.arg2,0); sp=i; break;
- case PUSHNIL: CHECK(0,i+1); break;
- case POP: CHECK(0,-i); break;
- case PUSHNUMBER:
- case PUSHNUMBERNEG:
- case PUSHCONSTANT:
- case PUSHUPVALUE:
- case PUSHLOCAL:
- case GETGLOBAL: CHECK(0,1); break;
- case GETTABLE: CHECK(2,1); break;
- case GETDOTTED: CHECK(1,1); break;
- case PUSHSELF: CHECK(1,2); break;
- case CREATEARRAY: CHECK(0,1); break;
- case SETLOCAL: CHECK(1,0); break;
- case SETGLOBAL: CHECK(1,0); break;
- case SETTABLEPOP: CHECK(3,0); break;
- case SETTABLE: CHECK(i+3,i+2); break;
- case SETLIST: CHECK(OP.arg2+1,1); break;
- case SETMAP: CHECK(2*(i+1)+1,1); break;
- case NEQOP:
- case EQOP:
- case LTOP:
- case LEOP:
- case GTOP:
- case GEOP:
- case ADDOP:
- case SUBOP:
- case MULTOP:
- case DIVOP:
- case POWOP:
- case CONCOP: CHECK(2,1); break;
- case MINUSOP:
- case NOTOP: CHECK(1,1); break;
- case ONTJMP:
- case ONFJMP:
- case IFFJMP:
- case IFTUPJMP:
- case IFFUPJMP: CHECK(1,0); break;
- case JMP: break;
- case CLOSURE: CHECK(OP.arg2,1); break;
- case SETLINE: break;
- case LONGARG:
- longarg=i<<16;
- if (longarg<0) UNSAFE("longarg overflow"),ATLOC;
- break;
- case CHECKSTACK: break;
- default: /* cannot happen */
- UNSAFE("cannot test opcode %d [%s]"),OP.op,OP.name,ATLOC;
- break;
- }
- p+=n;
- }
-}
-
-static void TestJumps(TProtoFunc* tf, int size, int* SP, int* JP)
-{
- int i;
- for (i=0; i<size; i++)
- {
- int to=JP[i];
- if (to!=0)
- {
- int at=i; /* for ATLOC */
- int a,b,j;
- int on=(to<0); /* ON?JMP */
- if (on) to=-to;
- a=SP[to];
- if (a<0)
- UNSAFE("invalid jump to %d (not an instruction)"),to,ATLOC;
- for (j=i; SP[++j]<0; ) /* find next instruction */
- ;
- b=SP[j]+on;
- if (a!=b)
- UNSAFE("stack inconsistency in jump to %d (expected %d, found %d)"),
- to,a,b,ATLOC;
- }
- }
-}
-
-static void TestCode(TProtoFunc* tf)
-{
- static int* SP=NULL;
- static int* JP=NULL;
- int size=luaU_codesize(tf);
- luaM_reallocvector(SP,size,int); memset(SP,-1,size*sizeof(int));
- luaM_reallocvector(JP,size,int); memset(JP, 0,size*sizeof(int));
- TestStack(tf,size,SP,JP);
- TestJumps(tf,size,SP,JP);
-}
-
-#undef AT
-#define AT "locvars[%d]"
-static void TestLocals(TProtoFunc* tf)
-{
- LocVar* v;
- int l=1;
- int d=0;
- if (tf->locvars==NULL) return;
- for (v=tf->locvars; v->line>=0; v++)
- {
- int at=v-tf->locvars; /* for ATLOC */
- if (l>v->line)
- UNSAFE("bad line number %d; expected at least %d"),v->line,l,ATLOC;
- l=v->line;
- if (v->varname==NULL)
- {
- if (--d<0) UNSAFE("no scope to close"),ATLOC;
- }
- else
- ++d;
- }
-}
-
-static void TestFunction(TProtoFunc* tf);
-
-static void TestConstants(TProtoFunc* tf)
-{
- int i,n=tf->nconsts;
- for (i=0; i<n; i++)
- {
- TObject* o=tf->consts+i;
- switch (ttype(o))
- {
- case LUA_T_NUMBER:
- break;
- case LUA_T_STRING:
- break;
- case LUA_T_PROTO:
- TestFunction(tfvalue(o));
- break;
- case LUA_T_NIL:
- break;
- default: /* cannot happen */
- luaU_badconstant("print",i,o,tf);
- break;
- }
- }
-}
-
-static void TestFunction(TProtoFunc* tf)
-{
- TestCode(tf);
- TestLocals(tf);
- TestConstants(tf);
-}
-
-void luaU_testchunk(TProtoFunc* Main)
-{
- TestFunction(Main);
-}