xref: /netbsd-src/external/mit/lua/dist/src/luac.c (revision bdda0531de537df87feb2bf576711ab1be9b3675)
1*bdda0531Snikita /*	$NetBSD: luac.c,v 1.12 2023/06/08 21:12:08 nikita Exp $	*/
2bee09862Smbalmer 
3dbec5304Smbalmer /*
4f0dad708Snikita ** Id: luac.c
573008250Slneto ** Lua compiler (saves bytecodes to files; also lists bytecodes)
6dbec5304Smbalmer ** See Copyright Notice in lua.h
7dbec5304Smbalmer */
8dbec5304Smbalmer 
973008250Slneto #define luac_c
1073008250Slneto #define LUA_CORE
1173008250Slneto 
1273008250Slneto #include "lprefix.h"
1373008250Slneto 
1473008250Slneto #include <ctype.h>
15dbec5304Smbalmer #include <errno.h>
16dbec5304Smbalmer #include <stdio.h>
17dbec5304Smbalmer #include <stdlib.h>
18dbec5304Smbalmer #include <string.h>
19dbec5304Smbalmer 
20dbec5304Smbalmer #include "lua.h"
21dbec5304Smbalmer #include "lauxlib.h"
22dbec5304Smbalmer 
23f0dad708Snikita #include "ldebug.h"
24dbec5304Smbalmer #include "lobject.h"
25f0dad708Snikita #include "lopcodes.h"
26f0dad708Snikita #include "lopnames.h"
274ab4902eSlneto #include "lstate.h"
28dbec5304Smbalmer #include "lundump.h"
29dbec5304Smbalmer 
304ab4902eSlneto static void PrintFunction(const Proto* f, int full);
314ab4902eSlneto #define luaU_print	PrintFunction
324ab4902eSlneto 
33dbec5304Smbalmer #define PROGNAME	"luac"		/* default program name */
34dbec5304Smbalmer #define OUTPUT		PROGNAME ".out"	/* default output file */
35dbec5304Smbalmer 
36dbec5304Smbalmer static int listing=0;			/* list bytecodes? */
37dbec5304Smbalmer static int dumping=1;			/* dump bytecodes? */
38dbec5304Smbalmer static int stripping=0;			/* strip debug information? */
39dbec5304Smbalmer static char Output[]={ OUTPUT };	/* default output file name */
40dbec5304Smbalmer static const char* output=Output;	/* actual output file name */
41dbec5304Smbalmer static const char* progname=PROGNAME;	/* actual program name */
42f0dad708Snikita static TString **tmname;
43dbec5304Smbalmer 
fatal(const char * message)44dbec5304Smbalmer static void fatal(const char* message)
45dbec5304Smbalmer {
46dbec5304Smbalmer  fprintf(stderr,"%s: %s\n",progname,message);
47dbec5304Smbalmer  exit(EXIT_FAILURE);
48dbec5304Smbalmer }
49dbec5304Smbalmer 
cannot(const char * what)50dbec5304Smbalmer static void cannot(const char* what)
51dbec5304Smbalmer {
52dbec5304Smbalmer  fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno));
53dbec5304Smbalmer  exit(EXIT_FAILURE);
54dbec5304Smbalmer }
55dbec5304Smbalmer 
usage(const char * message)56dbec5304Smbalmer static void usage(const char* message)
57dbec5304Smbalmer {
58dbec5304Smbalmer  if (*message=='-')
5973008250Slneto   fprintf(stderr,"%s: unrecognized option '%s'\n",progname,message);
60dbec5304Smbalmer  else
61dbec5304Smbalmer   fprintf(stderr,"%s: %s\n",progname,message);
62dbec5304Smbalmer  fprintf(stderr,
634ab4902eSlneto   "usage: %s [options] [filenames]\n"
64dbec5304Smbalmer   "Available options are:\n"
654ab4902eSlneto   "  -l       list (use -l -l for full listing)\n"
6673008250Slneto   "  -o name  output to file 'name' (default is \"%s\")\n"
67dbec5304Smbalmer   "  -p       parse only\n"
68dbec5304Smbalmer   "  -s       strip debug information\n"
69dbec5304Smbalmer   "  -v       show version information\n"
704ab4902eSlneto   "  --       stop handling options\n"
714ab4902eSlneto   "  -        stop handling options and process stdin\n"
724ab4902eSlneto   ,progname,Output);
73dbec5304Smbalmer  exit(EXIT_FAILURE);
74dbec5304Smbalmer }
75dbec5304Smbalmer 
76dbec5304Smbalmer #define IS(s)	(strcmp(argv[i],s)==0)
77dbec5304Smbalmer 
doargs(int argc,char * argv[])78dbec5304Smbalmer static int doargs(int argc, char* argv[])
79dbec5304Smbalmer {
80dbec5304Smbalmer  int i;
81dbec5304Smbalmer  int version=0;
82dbec5304Smbalmer  if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0];
83dbec5304Smbalmer  for (i=1; i<argc; i++)
84dbec5304Smbalmer  {
85dbec5304Smbalmer   if (*argv[i]!='-')			/* end of options; keep it */
86dbec5304Smbalmer    break;
87dbec5304Smbalmer   else if (IS("--"))			/* end of options; skip it */
88dbec5304Smbalmer   {
89dbec5304Smbalmer    ++i;
90dbec5304Smbalmer    if (version) ++version;
91dbec5304Smbalmer    break;
92dbec5304Smbalmer   }
93dbec5304Smbalmer   else if (IS("-"))			/* end of options; use stdin */
94dbec5304Smbalmer    break;
95dbec5304Smbalmer   else if (IS("-l"))			/* list */
96dbec5304Smbalmer    ++listing;
97dbec5304Smbalmer   else if (IS("-o"))			/* output file */
98dbec5304Smbalmer   {
99dbec5304Smbalmer    output=argv[++i];
1004ab4902eSlneto    if (output==NULL || *output==0 || (*output=='-' && output[1]!=0))
10173008250Slneto     usage("'-o' needs argument");
102dbec5304Smbalmer    if (IS("-")) output=NULL;
103dbec5304Smbalmer   }
104dbec5304Smbalmer   else if (IS("-p"))			/* parse only */
105dbec5304Smbalmer    dumping=0;
106dbec5304Smbalmer   else if (IS("-s"))			/* strip debug information */
107dbec5304Smbalmer    stripping=1;
108dbec5304Smbalmer   else if (IS("-v"))			/* show version */
109dbec5304Smbalmer    ++version;
110dbec5304Smbalmer   else					/* unknown option */
111dbec5304Smbalmer    usage(argv[i]);
112dbec5304Smbalmer  }
113dbec5304Smbalmer  if (i==argc && (listing || !dumping))
114dbec5304Smbalmer  {
115dbec5304Smbalmer   dumping=0;
116dbec5304Smbalmer   argv[--i]=Output;
117dbec5304Smbalmer  }
118dbec5304Smbalmer  if (version)
119dbec5304Smbalmer  {
1204ab4902eSlneto   printf("%s\n",LUA_COPYRIGHT);
121dbec5304Smbalmer   if (version==argc-1) exit(EXIT_SUCCESS);
122dbec5304Smbalmer  }
123dbec5304Smbalmer  return i;
124dbec5304Smbalmer }
125dbec5304Smbalmer 
126*bdda0531Snikita #define FUNCTION "(function()end)();\n"
1274ab4902eSlneto 
reader(lua_State * L,void * ud,size_t * size)1284ab4902eSlneto static const char* reader(lua_State* L, void* ud, size_t* size)
1294ab4902eSlneto {
1304ab4902eSlneto  UNUSED(L);
1314ab4902eSlneto  if ((*(int*)ud)--)
1324ab4902eSlneto  {
1334ab4902eSlneto   *size=sizeof(FUNCTION)-1;
1344ab4902eSlneto   return FUNCTION;
1354ab4902eSlneto  }
1364ab4902eSlneto  else
1374ab4902eSlneto  {
1384ab4902eSlneto   *size=0;
1394ab4902eSlneto   return NULL;
1404ab4902eSlneto  }
1414ab4902eSlneto }
1424ab4902eSlneto 
143*bdda0531Snikita #define toproto(L,i) getproto(s2v(L->top.p+(i)))
144dbec5304Smbalmer 
combine(lua_State * L,int n)145dbec5304Smbalmer static const Proto* combine(lua_State* L, int n)
146dbec5304Smbalmer {
147dbec5304Smbalmer  if (n==1)
148dbec5304Smbalmer   return toproto(L,-1);
149dbec5304Smbalmer  else
150dbec5304Smbalmer  {
1514ab4902eSlneto   Proto* f;
1524ab4902eSlneto   int i=n;
1534ab4902eSlneto   if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1));
1544ab4902eSlneto   f=toproto(L,-1);
155dbec5304Smbalmer   for (i=0; i<n; i++)
156dbec5304Smbalmer   {
157dbec5304Smbalmer    f->p[i]=toproto(L,i-n-1);
1584ab4902eSlneto    if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0;
159dbec5304Smbalmer   }
160dbec5304Smbalmer   return f;
161dbec5304Smbalmer  }
162dbec5304Smbalmer }
163dbec5304Smbalmer 
writer(lua_State * L,const void * p,size_t size,void * u)164dbec5304Smbalmer static int writer(lua_State* L, const void* p, size_t size, void* u)
165dbec5304Smbalmer {
166dbec5304Smbalmer  UNUSED(L);
167dbec5304Smbalmer  return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);
168dbec5304Smbalmer }
169dbec5304Smbalmer 
pmain(lua_State * L)170dbec5304Smbalmer static int pmain(lua_State* L)
171dbec5304Smbalmer {
1724ab4902eSlneto  int argc=(int)lua_tointeger(L,1);
1734ab4902eSlneto  char** argv=(char**)lua_touserdata(L,2);
174dbec5304Smbalmer  const Proto* f;
175dbec5304Smbalmer  int i;
176f0dad708Snikita  tmname=G(L)->tmname;
177dbec5304Smbalmer  if (!lua_checkstack(L,argc)) fatal("too many input files");
178dbec5304Smbalmer  for (i=0; i<argc; i++)
179dbec5304Smbalmer  {
180dbec5304Smbalmer   const char* filename=IS("-") ? NULL : argv[i];
1814ab4902eSlneto   if (luaL_loadfile(L,filename)!=LUA_OK) fatal(lua_tostring(L,-1));
182dbec5304Smbalmer  }
183dbec5304Smbalmer  f=combine(L,argc);
184dbec5304Smbalmer  if (listing) luaU_print(f,listing>1);
185dbec5304Smbalmer  if (dumping)
186dbec5304Smbalmer  {
187dbec5304Smbalmer   FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
188dbec5304Smbalmer   if (D==NULL) cannot("open");
189dbec5304Smbalmer   lua_lock(L);
190dbec5304Smbalmer   luaU_dump(L,f,writer,D,stripping);
191dbec5304Smbalmer   lua_unlock(L);
192dbec5304Smbalmer   if (ferror(D)) cannot("write");
193dbec5304Smbalmer   if (fclose(D)) cannot("close");
194dbec5304Smbalmer  }
195dbec5304Smbalmer  return 0;
196dbec5304Smbalmer }
197dbec5304Smbalmer 
main(int argc,char * argv[])198dbec5304Smbalmer int main(int argc, char* argv[])
199dbec5304Smbalmer {
200dbec5304Smbalmer  lua_State* L;
201dbec5304Smbalmer  int i=doargs(argc,argv);
202dbec5304Smbalmer  argc-=i; argv+=i;
203dbec5304Smbalmer  if (argc<=0) usage("no input files given");
2044ab4902eSlneto  L=luaL_newstate();
2054ab4902eSlneto  if (L==NULL) fatal("cannot create state: not enough memory");
2064ab4902eSlneto  lua_pushcfunction(L,&pmain);
2074ab4902eSlneto  lua_pushinteger(L,argc);
2084ab4902eSlneto  lua_pushlightuserdata(L,argv);
2094ab4902eSlneto  if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1));
210dbec5304Smbalmer  lua_close(L);
211dbec5304Smbalmer  return EXIT_SUCCESS;
212dbec5304Smbalmer }
2134ab4902eSlneto 
2144ab4902eSlneto /*
2154ab4902eSlneto ** print bytecodes
2164ab4902eSlneto */
2174ab4902eSlneto 
218f0dad708Snikita #define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-")
2194ab4902eSlneto #define VOID(p) ((const void*)(p))
220f0dad708Snikita #define eventname(i) (getstr(tmname[i]))
2214ab4902eSlneto 
PrintString(const TString * ts)2224ab4902eSlneto static void PrintString(const TString* ts)
2234ab4902eSlneto {
2244ab4902eSlneto  const char* s=getstr(ts);
225bee09862Smbalmer  size_t i,n=tsslen(ts);
226f0dad708Snikita  printf("\"");
2274ab4902eSlneto  for (i=0; i<n; i++)
2284ab4902eSlneto  {
2294ab4902eSlneto   int c=(int)(unsigned char)s[i];
2304ab4902eSlneto   switch (c)
2314ab4902eSlneto   {
232f0dad708Snikita    case '"':
233f0dad708Snikita 	printf("\\\"");
234f0dad708Snikita 	break;
235f0dad708Snikita    case '\\':
236f0dad708Snikita 	printf("\\\\");
237f0dad708Snikita 	break;
238f0dad708Snikita    case '\a':
239f0dad708Snikita 	printf("\\a");
240f0dad708Snikita 	break;
241f0dad708Snikita    case '\b':
242f0dad708Snikita 	printf("\\b");
243f0dad708Snikita 	break;
244f0dad708Snikita    case '\f':
245f0dad708Snikita 	printf("\\f");
246f0dad708Snikita 	break;
247f0dad708Snikita    case '\n':
248f0dad708Snikita 	printf("\\n");
249f0dad708Snikita 	break;
250f0dad708Snikita    case '\r':
251f0dad708Snikita 	printf("\\r");
252f0dad708Snikita 	break;
253f0dad708Snikita    case '\t':
254f0dad708Snikita 	printf("\\t");
255f0dad708Snikita 	break;
256f0dad708Snikita    case '\v':
257f0dad708Snikita 	printf("\\v");
258f0dad708Snikita 	break;
259f0dad708Snikita    default:
260f0dad708Snikita 	if (isprint(c)) printf("%c",c); else printf("\\%03d",c);
261f0dad708Snikita 	break;
2624ab4902eSlneto   }
2634ab4902eSlneto  }
264f0dad708Snikita  printf("\"");
265f0dad708Snikita }
266f0dad708Snikita 
PrintType(const Proto * f,int i)267f0dad708Snikita static void PrintType(const Proto* f, int i)
268f0dad708Snikita {
269f0dad708Snikita  const TValue* o=&f->k[i];
270f0dad708Snikita  switch (ttypetag(o))
271f0dad708Snikita  {
272f0dad708Snikita   case LUA_VNIL:
273f0dad708Snikita 	printf("N");
274f0dad708Snikita 	break;
275f0dad708Snikita   case LUA_VFALSE:
276f0dad708Snikita   case LUA_VTRUE:
277f0dad708Snikita 	printf("B");
278f0dad708Snikita 	break;
279f0dad708Snikita   case LUA_VNUMFLT:
280f0dad708Snikita 	printf("F");
281f0dad708Snikita 	break;
282f0dad708Snikita   case LUA_VNUMINT:
283f0dad708Snikita 	printf("I");
284f0dad708Snikita 	break;
285f0dad708Snikita   case LUA_VSHRSTR:
286f0dad708Snikita   case LUA_VLNGSTR:
287f0dad708Snikita 	printf("S");
288f0dad708Snikita 	break;
289f0dad708Snikita   default:				/* cannot happen */
290f0dad708Snikita 	printf("?%d",ttypetag(o));
291f0dad708Snikita 	break;
292f0dad708Snikita  }
293f0dad708Snikita  printf("\t");
2944ab4902eSlneto }
2954ab4902eSlneto 
PrintConstant(const Proto * f,int i)2964ab4902eSlneto static void PrintConstant(const Proto* f, int i)
2974ab4902eSlneto {
2984ab4902eSlneto  const TValue* o=&f->k[i];
299f0dad708Snikita  switch (ttypetag(o))
3004ab4902eSlneto  {
301f0dad708Snikita   case LUA_VNIL:
3024ab4902eSlneto 	printf("nil");
3034ab4902eSlneto 	break;
304f0dad708Snikita   case LUA_VFALSE:
305f0dad708Snikita 	printf("false");
3064ab4902eSlneto 	break;
307f0dad708Snikita   case LUA_VTRUE:
308f0dad708Snikita 	printf("true");
309f0dad708Snikita 	break;
310f0dad708Snikita   case LUA_VNUMFLT:
31173008250Slneto 	{
31273008250Slneto 	char buff[100];
3132d6cb6c2Slneto #ifndef __NetBSD__
3142d6cb6c2Slneto 	sprintf(buff,LUA_NUMBER_FMT,fltvalue(o));
3152d6cb6c2Slneto #else /* __NetBSD__ */
3162d6cb6c2Slneto 	l_sprintf(buff, sizeof(buff), LUA_NUMBER_FMT,fltvalue(o));
3172d6cb6c2Slneto #endif /* __NetBSD__ */
31873008250Slneto 	printf("%s",buff);
31973008250Slneto 	if (buff[strspn(buff,"-0123456789")]=='\0') printf(".0");
3204ab4902eSlneto 	break;
32173008250Slneto 	}
322f0dad708Snikita   case LUA_VNUMINT:
3234ab4902eSlneto 	printf(LUA_INTEGER_FMT,ivalue(o));
3244ab4902eSlneto 	break;
325f0dad708Snikita   case LUA_VSHRSTR:
326f0dad708Snikita   case LUA_VLNGSTR:
32773008250Slneto 	PrintString(tsvalue(o));
3284ab4902eSlneto 	break;
3294ab4902eSlneto   default:				/* cannot happen */
330f0dad708Snikita 	printf("?%d",ttypetag(o));
3314ab4902eSlneto 	break;
3324ab4902eSlneto  }
3334ab4902eSlneto }
3344ab4902eSlneto 
335f0dad708Snikita #define COMMENT		"\t; "
336f0dad708Snikita #define EXTRAARG	GETARG_Ax(code[pc+1])
337f0dad708Snikita #define EXTRAARGC	(EXTRAARG*(MAXARG_C+1))
338f0dad708Snikita #define ISK		(isk ? "k" : "")
3394ab4902eSlneto 
PrintCode(const Proto * f)3404ab4902eSlneto static void PrintCode(const Proto* f)
3414ab4902eSlneto {
3424ab4902eSlneto  const Instruction* code=f->code;
3434ab4902eSlneto  int pc,n=f->sizecode;
3444ab4902eSlneto  for (pc=0; pc<n; pc++)
3454ab4902eSlneto  {
3464ab4902eSlneto   Instruction i=code[pc];
3474ab4902eSlneto   OpCode o=GET_OPCODE(i);
3484ab4902eSlneto   int a=GETARG_A(i);
3494ab4902eSlneto   int b=GETARG_B(i);
3504ab4902eSlneto   int c=GETARG_C(i);
3514ab4902eSlneto   int ax=GETARG_Ax(i);
3524ab4902eSlneto   int bx=GETARG_Bx(i);
353f0dad708Snikita   int sb=GETARG_sB(i);
354f0dad708Snikita   int sc=GETARG_sC(i);
3554ab4902eSlneto   int sbx=GETARG_sBx(i);
356f0dad708Snikita   int isk=GETARG_k(i);
357f0dad708Snikita   int line=luaG_getfuncline(f,pc);
3584ab4902eSlneto   printf("\t%d\t",pc+1);
3594ab4902eSlneto   if (line>0) printf("[%d]\t",line); else printf("[-]\t");
360f0dad708Snikita   printf("%-9s\t",opnames[o]);
3614ab4902eSlneto   switch (o)
3624ab4902eSlneto   {
363f0dad708Snikita    case OP_MOVE:
364f0dad708Snikita 	printf("%d %d",a,b);
365f0dad708Snikita 	break;
366f0dad708Snikita    case OP_LOADI:
367f0dad708Snikita 	printf("%d %d",a,sbx);
368f0dad708Snikita 	break;
369f0dad708Snikita    case OP_LOADF:
370f0dad708Snikita 	printf("%d %d",a,sbx);
371f0dad708Snikita 	break;
3724ab4902eSlneto    case OP_LOADK:
373f0dad708Snikita 	printf("%d %d",a,bx);
374f0dad708Snikita 	printf(COMMENT); PrintConstant(f,bx);
375f0dad708Snikita 	break;
376f0dad708Snikita    case OP_LOADKX:
377f0dad708Snikita 	printf("%d",a);
378f0dad708Snikita 	printf(COMMENT); PrintConstant(f,EXTRAARG);
379f0dad708Snikita 	break;
380f0dad708Snikita    case OP_LOADFALSE:
381f0dad708Snikita 	printf("%d",a);
382f0dad708Snikita 	break;
383f0dad708Snikita    case OP_LFALSESKIP:
384f0dad708Snikita 	printf("%d",a);
385f0dad708Snikita 	break;
386f0dad708Snikita    case OP_LOADTRUE:
387f0dad708Snikita 	printf("%d",a);
388f0dad708Snikita 	break;
389f0dad708Snikita    case OP_LOADNIL:
390f0dad708Snikita 	printf("%d %d",a,b);
391f0dad708Snikita 	printf(COMMENT "%d out",b+1);
3924ab4902eSlneto 	break;
3934ab4902eSlneto    case OP_GETUPVAL:
394f0dad708Snikita 	printf("%d %d",a,b);
395f0dad708Snikita 	printf(COMMENT "%s",UPVALNAME(b));
396f0dad708Snikita 	break;
3974ab4902eSlneto    case OP_SETUPVAL:
398f0dad708Snikita 	printf("%d %d",a,b);
399f0dad708Snikita 	printf(COMMENT "%s",UPVALNAME(b));
4004ab4902eSlneto 	break;
4014ab4902eSlneto    case OP_GETTABUP:
402f0dad708Snikita 	printf("%d %d %d",a,b,c);
403f0dad708Snikita 	printf(COMMENT "%s",UPVALNAME(b));
404f0dad708Snikita 	printf(" "); PrintConstant(f,c);
4054ab4902eSlneto 	break;
4064ab4902eSlneto    case OP_GETTABLE:
407f0dad708Snikita 	printf("%d %d %d",a,b,c);
408f0dad708Snikita 	break;
409f0dad708Snikita    case OP_GETI:
410f0dad708Snikita 	printf("%d %d %d",a,b,c);
411f0dad708Snikita 	break;
412f0dad708Snikita    case OP_GETFIELD:
413f0dad708Snikita 	printf("%d %d %d",a,b,c);
414f0dad708Snikita 	printf(COMMENT); PrintConstant(f,c);
415f0dad708Snikita 	break;
416f0dad708Snikita    case OP_SETTABUP:
417f0dad708Snikita 	printf("%d %d %d%s",a,b,c,ISK);
418f0dad708Snikita 	printf(COMMENT "%s",UPVALNAME(a));
419f0dad708Snikita 	printf(" "); PrintConstant(f,b);
420f0dad708Snikita 	if (isk) { printf(" "); PrintConstant(f,c); }
4214ab4902eSlneto 	break;
4224ab4902eSlneto    case OP_SETTABLE:
423f0dad708Snikita 	printf("%d %d %d%s",a,b,c,ISK);
424f0dad708Snikita 	if (isk) { printf(COMMENT); PrintConstant(f,c); }
425f0dad708Snikita 	break;
426f0dad708Snikita    case OP_SETI:
427f0dad708Snikita 	printf("%d %d %d%s",a,b,c,ISK);
428f0dad708Snikita 	if (isk) { printf(COMMENT); PrintConstant(f,c); }
429f0dad708Snikita 	break;
430f0dad708Snikita    case OP_SETFIELD:
431f0dad708Snikita 	printf("%d %d %d%s",a,b,c,ISK);
432f0dad708Snikita 	printf(COMMENT); PrintConstant(f,b);
433f0dad708Snikita 	if (isk) { printf(" "); PrintConstant(f,c); }
434f0dad708Snikita 	break;
435f0dad708Snikita    case OP_NEWTABLE:
436f0dad708Snikita 	printf("%d %d %d",a,b,c);
437f0dad708Snikita 	printf(COMMENT "%d",c+EXTRAARGC);
438f0dad708Snikita 	break;
439f0dad708Snikita    case OP_SELF:
440f0dad708Snikita 	printf("%d %d %d%s",a,b,c,ISK);
441f0dad708Snikita 	if (isk) { printf(COMMENT); PrintConstant(f,c); }
442f0dad708Snikita 	break;
443f0dad708Snikita    case OP_ADDI:
444f0dad708Snikita 	printf("%d %d %d",a,b,sc);
445f0dad708Snikita 	break;
446f0dad708Snikita    case OP_ADDK:
447f0dad708Snikita 	printf("%d %d %d",a,b,c);
448f0dad708Snikita 	printf(COMMENT); PrintConstant(f,c);
449f0dad708Snikita 	break;
450f0dad708Snikita    case OP_SUBK:
451f0dad708Snikita 	printf("%d %d %d",a,b,c);
452f0dad708Snikita 	printf(COMMENT); PrintConstant(f,c);
453f0dad708Snikita 	break;
454f0dad708Snikita    case OP_MULK:
455f0dad708Snikita 	printf("%d %d %d",a,b,c);
456f0dad708Snikita 	printf(COMMENT); PrintConstant(f,c);
457f0dad708Snikita 	break;
458f0dad708Snikita    case OP_MODK:
459f0dad708Snikita 	printf("%d %d %d",a,b,c);
460f0dad708Snikita 	printf(COMMENT); PrintConstant(f,c);
461f0dad708Snikita 	break;
462f0dad708Snikita    case OP_POWK:
463f0dad708Snikita 	printf("%d %d %d",a,b,c);
464f0dad708Snikita 	printf(COMMENT); PrintConstant(f,c);
465f0dad708Snikita 	break;
466f0dad708Snikita    case OP_DIVK:
467f0dad708Snikita 	printf("%d %d %d",a,b,c);
468f0dad708Snikita 	printf(COMMENT); PrintConstant(f,c);
469f0dad708Snikita 	break;
470f0dad708Snikita    case OP_IDIVK:
471f0dad708Snikita 	printf("%d %d %d",a,b,c);
472f0dad708Snikita 	printf(COMMENT); PrintConstant(f,c);
473f0dad708Snikita 	break;
474f0dad708Snikita    case OP_BANDK:
475f0dad708Snikita 	printf("%d %d %d",a,b,c);
476f0dad708Snikita 	printf(COMMENT); PrintConstant(f,c);
477f0dad708Snikita 	break;
478f0dad708Snikita    case OP_BORK:
479f0dad708Snikita 	printf("%d %d %d",a,b,c);
480f0dad708Snikita 	printf(COMMENT); PrintConstant(f,c);
481f0dad708Snikita 	break;
482f0dad708Snikita    case OP_BXORK:
483f0dad708Snikita 	printf("%d %d %d",a,b,c);
484f0dad708Snikita 	printf(COMMENT); PrintConstant(f,c);
485f0dad708Snikita 	break;
486f0dad708Snikita    case OP_SHRI:
487f0dad708Snikita 	printf("%d %d %d",a,b,sc);
488f0dad708Snikita 	break;
489f0dad708Snikita    case OP_SHLI:
490f0dad708Snikita 	printf("%d %d %d",a,b,sc);
491f0dad708Snikita 	break;
4924ab4902eSlneto    case OP_ADD:
493f0dad708Snikita 	printf("%d %d %d",a,b,c);
494f0dad708Snikita 	break;
4954ab4902eSlneto    case OP_SUB:
496f0dad708Snikita 	printf("%d %d %d",a,b,c);
497f0dad708Snikita 	break;
4984ab4902eSlneto    case OP_MUL:
499f0dad708Snikita 	printf("%d %d %d",a,b,c);
500f0dad708Snikita 	break;
5012bf4ff61Salnsn    case OP_MOD:
502f0dad708Snikita 	printf("%d %d %d",a,b,c);
503f0dad708Snikita 	break;
5044ab4902eSlneto    case OP_POW:
505f0dad708Snikita 	printf("%d %d %d",a,b,c);
506f0dad708Snikita 	break;
5074ab4902eSlneto    case OP_DIV:
508f0dad708Snikita 	printf("%d %d %d",a,b,c);
509f0dad708Snikita 	break;
5104ab4902eSlneto    case OP_IDIV:
511f0dad708Snikita 	printf("%d %d %d",a,b,c);
512f0dad708Snikita 	break;
5134ab4902eSlneto    case OP_BAND:
514f0dad708Snikita 	printf("%d %d %d",a,b,c);
515f0dad708Snikita 	break;
5164ab4902eSlneto    case OP_BOR:
517f0dad708Snikita 	printf("%d %d %d",a,b,c);
518f0dad708Snikita 	break;
5194ab4902eSlneto    case OP_BXOR:
520f0dad708Snikita 	printf("%d %d %d",a,b,c);
521f0dad708Snikita 	break;
5224ab4902eSlneto    case OP_SHL:
523f0dad708Snikita 	printf("%d %d %d",a,b,c);
524f0dad708Snikita 	break;
5254ab4902eSlneto    case OP_SHR:
526f0dad708Snikita 	printf("%d %d %d",a,b,c);
527f0dad708Snikita 	break;
528f0dad708Snikita    case OP_MMBIN:
529f0dad708Snikita 	printf("%d %d %d",a,b,c);
530f0dad708Snikita 	printf(COMMENT "%s",eventname(c));
531f0dad708Snikita 	break;
532f0dad708Snikita    case OP_MMBINI:
533f0dad708Snikita 	printf("%d %d %d %d",a,sb,c,isk);
534f0dad708Snikita 	printf(COMMENT "%s",eventname(c));
535f0dad708Snikita 	if (isk) printf(" flip");
536f0dad708Snikita 	break;
537f0dad708Snikita    case OP_MMBINK:
538f0dad708Snikita 	printf("%d %d %d %d",a,b,c,isk);
539f0dad708Snikita 	printf(COMMENT "%s ",eventname(c)); PrintConstant(f,b);
540f0dad708Snikita 	if (isk) printf(" flip");
541f0dad708Snikita 	break;
542f0dad708Snikita    case OP_UNM:
543f0dad708Snikita 	printf("%d %d",a,b);
544f0dad708Snikita 	break;
545f0dad708Snikita    case OP_BNOT:
546f0dad708Snikita 	printf("%d %d",a,b);
547f0dad708Snikita 	break;
548f0dad708Snikita    case OP_NOT:
549f0dad708Snikita 	printf("%d %d",a,b);
550f0dad708Snikita 	break;
551f0dad708Snikita    case OP_LEN:
552f0dad708Snikita 	printf("%d %d",a,b);
553f0dad708Snikita 	break;
554f0dad708Snikita    case OP_CONCAT:
555f0dad708Snikita 	printf("%d %d",a,b);
556f0dad708Snikita 	break;
557f0dad708Snikita    case OP_CLOSE:
558f0dad708Snikita 	printf("%d",a);
559f0dad708Snikita 	break;
560f0dad708Snikita    case OP_TBC:
561f0dad708Snikita 	printf("%d",a);
5624ab4902eSlneto 	break;
5634ab4902eSlneto    case OP_JMP:
564f0dad708Snikita 	printf("%d",GETARG_sJ(i));
565f0dad708Snikita 	printf(COMMENT "to %d",GETARG_sJ(i)+pc+2);
5664ab4902eSlneto 	break;
567f0dad708Snikita    case OP_EQ:
568f0dad708Snikita 	printf("%d %d %d",a,b,isk);
569f0dad708Snikita 	break;
570f0dad708Snikita    case OP_LT:
571f0dad708Snikita 	printf("%d %d %d",a,b,isk);
572f0dad708Snikita 	break;
573f0dad708Snikita    case OP_LE:
574f0dad708Snikita 	printf("%d %d %d",a,b,isk);
575f0dad708Snikita 	break;
576f0dad708Snikita    case OP_EQK:
577f0dad708Snikita 	printf("%d %d %d",a,b,isk);
578f0dad708Snikita 	printf(COMMENT); PrintConstant(f,b);
579f0dad708Snikita 	break;
580f0dad708Snikita    case OP_EQI:
581f0dad708Snikita 	printf("%d %d %d",a,sb,isk);
582f0dad708Snikita 	break;
583f0dad708Snikita    case OP_LTI:
584f0dad708Snikita 	printf("%d %d %d",a,sb,isk);
585f0dad708Snikita 	break;
586f0dad708Snikita    case OP_LEI:
587f0dad708Snikita 	printf("%d %d %d",a,sb,isk);
588f0dad708Snikita 	break;
589f0dad708Snikita    case OP_GTI:
590f0dad708Snikita 	printf("%d %d %d",a,sb,isk);
591f0dad708Snikita 	break;
592f0dad708Snikita    case OP_GEI:
593f0dad708Snikita 	printf("%d %d %d",a,sb,isk);
594f0dad708Snikita 	break;
595f0dad708Snikita    case OP_TEST:
596f0dad708Snikita 	printf("%d %d",a,isk);
597f0dad708Snikita 	break;
598f0dad708Snikita    case OP_TESTSET:
599f0dad708Snikita 	printf("%d %d %d",a,b,isk);
600f0dad708Snikita 	break;
601f0dad708Snikita    case OP_CALL:
602f0dad708Snikita 	printf("%d %d %d",a,b,c);
603f0dad708Snikita 	printf(COMMENT);
604f0dad708Snikita 	if (b==0) printf("all in "); else printf("%d in ",b-1);
605f0dad708Snikita 	if (c==0) printf("all out"); else printf("%d out",c-1);
606f0dad708Snikita 	break;
607f0dad708Snikita    case OP_TAILCALL:
608f0dad708Snikita 	printf("%d %d %d%s",a,b,c,ISK);
609f0dad708Snikita 	printf(COMMENT "%d in",b-1);
610f0dad708Snikita 	break;
611f0dad708Snikita    case OP_RETURN:
612f0dad708Snikita 	printf("%d %d %d%s",a,b,c,ISK);
613f0dad708Snikita 	printf(COMMENT);
614f0dad708Snikita 	if (b==0) printf("all out"); else printf("%d out",b-1);
615f0dad708Snikita 	break;
616f0dad708Snikita    case OP_RETURN0:
617f0dad708Snikita 	break;
618f0dad708Snikita    case OP_RETURN1:
619f0dad708Snikita 	printf("%d",a);
620f0dad708Snikita 	break;
621f0dad708Snikita    case OP_FORLOOP:
622f0dad708Snikita 	printf("%d %d",a,bx);
623f0dad708Snikita 	printf(COMMENT "to %d",pc-bx+2);
624f0dad708Snikita 	break;
625f0dad708Snikita    case OP_FORPREP:
626f0dad708Snikita 	printf("%d %d",a,bx);
627f0dad708Snikita 	printf(COMMENT "exit to %d",pc+bx+3);
628f0dad708Snikita 	break;
629f0dad708Snikita    case OP_TFORPREP:
630f0dad708Snikita 	printf("%d %d",a,bx);
631f0dad708Snikita 	printf(COMMENT "to %d",pc+bx+2);
632f0dad708Snikita 	break;
633f0dad708Snikita    case OP_TFORCALL:
634f0dad708Snikita 	printf("%d %d",a,c);
635f0dad708Snikita 	break;
636f0dad708Snikita    case OP_TFORLOOP:
637f0dad708Snikita 	printf("%d %d",a,bx);
638f0dad708Snikita 	printf(COMMENT "to %d",pc-bx+2);
6394ab4902eSlneto 	break;
6404ab4902eSlneto    case OP_SETLIST:
641f0dad708Snikita 	printf("%d %d %d",a,b,c);
642f0dad708Snikita 	if (isk) printf(COMMENT "%d",c+EXTRAARGC);
643f0dad708Snikita 	break;
644f0dad708Snikita    case OP_CLOSURE:
645f0dad708Snikita 	printf("%d %d",a,bx);
646f0dad708Snikita 	printf(COMMENT "%p",VOID(f->p[bx]));
647f0dad708Snikita 	break;
648f0dad708Snikita    case OP_VARARG:
649f0dad708Snikita 	printf("%d %d",a,c);
650f0dad708Snikita 	printf(COMMENT);
651f0dad708Snikita 	if (c==0) printf("all out"); else printf("%d out",c-1);
652f0dad708Snikita 	break;
653f0dad708Snikita    case OP_VARARGPREP:
654f0dad708Snikita 	printf("%d",a);
6554ab4902eSlneto 	break;
6564ab4902eSlneto    case OP_EXTRAARG:
657f0dad708Snikita 	printf("%d",ax);
6584ab4902eSlneto 	break;
659f0dad708Snikita #if 0
6604ab4902eSlneto    default:
661f0dad708Snikita 	printf("%d %d %d",a,b,c);
662f0dad708Snikita 	printf(COMMENT "not handled");
6634ab4902eSlneto 	break;
664f0dad708Snikita #endif
6654ab4902eSlneto   }
6664ab4902eSlneto   printf("\n");
6674ab4902eSlneto  }
6684ab4902eSlneto }
6694ab4902eSlneto 
670f0dad708Snikita 
6714ab4902eSlneto #define SS(x)	((x==1)?"":"s")
6724ab4902eSlneto #define S(x)	(int)(x),SS(x)
6734ab4902eSlneto 
PrintHeader(const Proto * f)6744ab4902eSlneto static void PrintHeader(const Proto* f)
6754ab4902eSlneto {
6764ab4902eSlneto  const char* s=f->source ? getstr(f->source) : "=?";
6774ab4902eSlneto  if (*s=='@' || *s=='=')
6784ab4902eSlneto   s++;
6794ab4902eSlneto  else if (*s==LUA_SIGNATURE[0])
6804ab4902eSlneto   s="(bstring)";
6814ab4902eSlneto  else
6824ab4902eSlneto   s="(string)";
6834ab4902eSlneto  printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n",
6844ab4902eSlneto 	(f->linedefined==0)?"main":"function",s,
6854ab4902eSlneto 	f->linedefined,f->lastlinedefined,
6864ab4902eSlneto 	S(f->sizecode),VOID(f));
6874ab4902eSlneto  printf("%d%s param%s, %d slot%s, %d upvalue%s, ",
6884ab4902eSlneto 	(int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams),
6894ab4902eSlneto 	S(f->maxstacksize),S(f->sizeupvalues));
6904ab4902eSlneto  printf("%d local%s, %d constant%s, %d function%s\n",
6914ab4902eSlneto 	S(f->sizelocvars),S(f->sizek),S(f->sizep));
6924ab4902eSlneto }
6934ab4902eSlneto 
PrintDebug(const Proto * f)6944ab4902eSlneto static void PrintDebug(const Proto* f)
6954ab4902eSlneto {
6964ab4902eSlneto  int i,n;
6974ab4902eSlneto  n=f->sizek;
6984ab4902eSlneto  printf("constants (%d) for %p:\n",n,VOID(f));
6994ab4902eSlneto  for (i=0; i<n; i++)
7004ab4902eSlneto  {
701f0dad708Snikita   printf("\t%d\t",i);
702f0dad708Snikita   PrintType(f,i);
7034ab4902eSlneto   PrintConstant(f,i);
7044ab4902eSlneto   printf("\n");
7054ab4902eSlneto  }
7064ab4902eSlneto  n=f->sizelocvars;
7074ab4902eSlneto  printf("locals (%d) for %p:\n",n,VOID(f));
7084ab4902eSlneto  for (i=0; i<n; i++)
7094ab4902eSlneto  {
7104ab4902eSlneto   printf("\t%d\t%s\t%d\t%d\n",
7114ab4902eSlneto   i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);
7124ab4902eSlneto  }
7134ab4902eSlneto  n=f->sizeupvalues;
7144ab4902eSlneto  printf("upvalues (%d) for %p:\n",n,VOID(f));
7154ab4902eSlneto  for (i=0; i<n; i++)
7164ab4902eSlneto  {
7174ab4902eSlneto   printf("\t%d\t%s\t%d\t%d\n",
7184ab4902eSlneto   i,UPVALNAME(i),f->upvalues[i].instack,f->upvalues[i].idx);
7194ab4902eSlneto  }
7204ab4902eSlneto }
7214ab4902eSlneto 
PrintFunction(const Proto * f,int full)7224ab4902eSlneto static void PrintFunction(const Proto* f, int full)
7234ab4902eSlneto {
7244ab4902eSlneto  int i,n=f->sizep;
7254ab4902eSlneto  PrintHeader(f);
7264ab4902eSlneto  PrintCode(f);
7274ab4902eSlneto  if (full) PrintDebug(f);
7284ab4902eSlneto  for (i=0; i<n; i++) PrintFunction(f->p[i],full);
7294ab4902eSlneto }
730