- /* 
- ** $Id: luac.c $ 
- ** Lua compiler (saves bytecodes to files; also lists bytecodes) 
- ** See Copyright Notice in lua.h 
- */ 
-   
- #define luac_c 
- #define LUA_CORE 
-   
- #include "lprefix.h" 
-   
- #include <ctype.h> 
- #include <errno.h> 
- #include <stdio.h> 
- #include <stdlib.h> 
- #include <string.h> 
-   
- #include "lua.h" 
- #include "lauxlib.h" 
-   
- #include "ldebug.h" 
- #include "lobject.h" 
- #include "lopcodes.h" 
- #include "lopnames.h" 
- #include "lstate.h" 
- #include "lundump.h" 
-   
- static void PrintFunction(const Proto* f, int full); 
- #define luaU_print      PrintFunction 
-   
- #define PROGNAME        "luac"          /* default program name */ 
- #define OUTPUT          PROGNAME ".out" /* default output file */ 
-   
- static int listing=0;                   /* list bytecodes? */ 
- static int dumping=1;                   /* dump bytecodes? */ 
- static int stripping=0;                 /* strip debug information? */ 
- static char Output[]={ OUTPUT };        /* default output file name */ 
- static const char* output=Output;       /* actual output file name */ 
- static const char* progname=PROGNAME;   /* actual program name */ 
- static TString **tmname; 
-   
- static void fatal(const char* message) 
- { 
-  fprintf(- stderr ,"%s: %s\n",- progname ,- message );
 
- } 
-   
- static void cannot(const char* what) 
- { 
-  fprintf(- stderr ,"%s: cannot %s %s: %s\n",- progname ,- what ,- output ,strerror(- errno ));
 
- } 
-   
- static void usage(const char* message) 
- { 
-  if (*message=='-') 
-   fprintf(- stderr ,"%s: unrecognized option '%s'\n",- progname ,- message );
 
-  else 
-   fprintf(- stderr ,"%s: %s\n",- progname ,- message );
 
-   "usage: %s [options] [filenames]\n" 
-   "Available options are:\n" 
-   "  -l       list (use -l -l for full listing)\n" 
-   "  -o name  output to file 'name' (default is \"%s\")\n" 
-   "  -p       parse only\n" 
-   "  -s       strip debug information\n" 
-   "  -v       show version information\n" 
-   "  --       stop handling options\n" 
-   "  -        stop handling options and process stdin\n" 
-   ,progname,Output); 
- } 
-   
- #define IS(s)   (strcmp(argv[i],s)==0) 
-   
- static int doargs(int argc, char* argv[]) 
- { 
-  int i; 
-  int version=0; 
-  if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; 
-  for (i=1; i<argc; i++) 
-  { 
-   if (*argv[i]!='-')                    /* end of options; keep it */ 
-    break; 
-   else if (IS("--"))                    /* end of options; skip it */ 
-   { 
-    ++i; 
-    if (version) ++version; 
-    break; 
-   } 
-   else if (IS("-"))                     /* end of options; use stdin */ 
-    break; 
-   else if (IS("-l"))                    /* list */ 
-    ++listing; 
-   else if (IS("-o"))                    /* output file */ 
-   { 
-    output=argv[++i]; 
-    if (output==NULL || *output==0 || (*output=='-' && output[1]!=0)) 
-     usage("'-o' needs argument"); 
-    if (IS("-")) output=NULL; 
-   } 
-   else if (IS("-p"))                    /* parse only */ 
-    dumping=0; 
-   else if (IS("-s"))                    /* strip debug information */ 
-    stripping=1; 
-   else if (IS("-v"))                    /* show version */ 
-    ++version; 
-   else                                  /* unknown option */ 
-    usage(argv[i]); 
-  } 
-  if (i==argc && (listing || !dumping)) 
-  { 
-   dumping=0; 
-   argv[--i]=Output; 
-  } 
-  if (version) 
-  { 
-   if (- version ==- argc -1) exit(- EXIT_SUCCESS );
 
-  } 
-  return i; 
- } 
-   
- #define FUNCTION "(function()end)();" 
-   
- static const char* reader(lua_State* L, void* ud, size_t* size) 
- { 
-  UNUSED(L); 
-  if ((*(int*)ud)--) 
-  { 
-   *size=sizeof(FUNCTION)-1; 
-   return FUNCTION; 
-  } 
-  else 
-  { 
-   *size=0; 
-   return NULL; 
-  } 
- } 
-   
- #define toproto(L,i) getproto(s2v(L->top+(i))) 
-   
- static const Proto* combine(lua_State* L, int n) 
- { 
-  if (n==1) 
-   return toproto(L,-1); 
-  else 
-  { 
-   Proto* f; 
-   int i=n; 
-   if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1)); 
-   f=toproto(L,-1); 
-   for (i=0; i<n; i++) 
-   { 
-    f->p[i]=toproto(L,i-n-1); 
-    if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; 
-   } 
-   luaM_freearray(L,f->lineinfo,f->sizelineinfo); 
-   f->sizelineinfo=0; 
-   return f; 
-  } 
- } 
-   
- static int writer(lua_State* L, const void* p, size_t size, void* u) 
- { 
-  UNUSED(L); 
-  return (fwrite(- p ,- size ,1,(- FILE *)- u )!=1) && (- size !=0);
 
- } 
-   
- static int pmain(lua_State* L) 
- { 
-  int argc=(int)lua_tointeger(L,1); 
-  char** argv=(char**)lua_touserdata(L,2); 
-  const Proto* f; 
-  int i; 
-  tmname=G(L)->tmname; 
-  if (!lua_checkstack(L,argc)) fatal("too many input files"); 
-  for (i=0; i<argc; i++) 
-  { 
-   const char* filename=IS("-") ? NULL : argv[i]; 
-   if (luaL_loadfile(L,filename)!=LUA_OK) fatal(lua_tostring(L,-1)); 
-  } 
-  f=combine(L,argc); 
-  if (listing) luaU_print(f,listing>1); 
-  if (dumping) 
-  { 
-   FILE *-  D = (- output ==- NULL ) ?-  stdout  : fopen(- output ,"wb");
-   if (D==NULL) cannot("open"); 
-   lua_lock(L); 
-   luaU_dump(L,f,writer,D,stripping); 
-   lua_unlock(L); 
-   if (ferror(- D ))-  cannot ("write");
 
-   if (fclose(- D ))-  cannot ("close");
 
-  } 
-  return 0; 
- } 
-   
- int main(int argc, char* argv[]) 
- { 
-  lua_State* L; 
-  int i=doargs(argc,argv); 
-  argc-=i; argv+=i; 
-  if (argc<=0) usage("no input files given"); 
-  L=luaL_newstate(); 
-  if (L==NULL) fatal("cannot create state: not enough memory"); 
-  lua_pushcfunction(L,&pmain); 
-  lua_pushinteger(L,argc); 
-  lua_pushlightuserdata(L,argv); 
-  if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1)); 
-  lua_close(L); 
-  return EXIT_SUCCESS; 
- } 
-   
- /* 
- ** print bytecodes 
- */ 
-   
- #define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") 
- #define VOID(p) ((const void*)(p)) 
- #define eventname(i) (getstr(tmname[i])) 
-   
- static void PrintString(const TString* ts) 
- { 
-  const char* s=getstr(ts); 
-  size_t i,n=tsslen(ts); 
-  for (i=0; i<n; i++) 
-  { 
-   int c=(int)(unsigned char)s[i]; 
-   switch (c) 
-   { 
-    case '"': 
-         break; 
-    case '\\': 
-         break; 
-    case '\a': 
-         break; 
-    case '\b': 
-         break; 
-    case '\f': 
-         break; 
-    case '\n': 
-         break; 
-    case '\r': 
-         break; 
-    case '\t': 
-         break; 
-    case '\v': 
-         break; 
-    default: 
-         break; 
-   } 
-  } 
- } 
-   
- static void PrintType(const Proto* f, int i) 
- { 
-  const TValue* o=&f->k[i]; 
-  switch (ttypetag(o)) 
-  { 
-   case LUA_VNIL: 
-         break; 
-   case LUA_VFALSE: 
-   case LUA_VTRUE: 
-         break; 
-   case LUA_VNUMFLT: 
-         break; 
-   case LUA_VNUMINT: 
-         break; 
-   case LUA_VSHRSTR: 
-   case LUA_VLNGSTR: 
-         break; 
-   default:                              /* cannot happen */ 
-         break; 
-  } 
- } 
-   
- static void PrintConstant(const Proto* f, int i) 
- { 
-  const TValue* o=&f->k[i]; 
-  switch (ttypetag(o)) 
-  { 
-   case LUA_VNIL: 
-         break; 
-   case LUA_VFALSE: 
-         break; 
-   case LUA_VTRUE: 
-         break; 
-   case LUA_VNUMFLT: 
-         { 
-         char buff[100]; 
-         sprintf(- buff ,- LUA_NUMBER_FMT ,- fltvalue (- o ));
 
-         break; 
-         } 
-   case LUA_VNUMINT: 
-         printf(- LUA_INTEGER_FMT ,- ivalue (- o ));
 
-         break; 
-   case LUA_VSHRSTR: 
-   case LUA_VLNGSTR: 
-         PrintString(tsvalue(o)); 
-         break; 
-   default:                              /* cannot happen */ 
-         break; 
-  } 
- } 
-   
- #define COMMENT         "\t; " 
- #define EXTRAARG        GETARG_Ax(code[pc+1]) 
- #define EXTRAARGC       (EXTRAARG*(MAXARG_C+1)) 
- #define ISK             (isk ? "k" : "") 
-   
- static void PrintCode(const Proto* f) 
- { 
-  const Instruction* code=f->code; 
-  int pc,n=f->sizecode; 
-  for (pc=0; pc<n; pc++) 
-  { 
-   Instruction i=code[pc]; 
-   OpCode o=GET_OPCODE(i); 
-   int a=GETARG_A(i); 
-   int b=GETARG_B(i); 
-   int c=GETARG_C(i); 
-   int ax=GETARG_Ax(i); 
-   int bx=GETARG_Bx(i); 
-   int sb=GETARG_sB(i); 
-   int sc=GETARG_sC(i); 
-   int sbx=GETARG_sBx(i); 
-   int isk=GETARG_k(i); 
-   int line=luaG_getfuncline(f,pc); 
-   switch (o) 
-   { 
-    case OP_MOVE: 
-         break; 
-    case OP_LOADI: 
-         break; 
-    case OP_LOADF: 
-         break; 
-    case OP_LOADK: 
-         printf(- COMMENT );-  PrintConstant (- f ,- bx );
 
-         break; 
-    case OP_LOADKX: 
-         printf(- COMMENT );-  PrintConstant (- f ,- EXTRAARG );
 
-         break; 
-    case OP_LOADFALSE: 
-         break; 
-    case OP_LFALSESKIP: 
-         break; 
-    case OP_LOADTRUE: 
-         break; 
-    case OP_LOADNIL: 
-         break; 
-    case OP_GETUPVAL: 
-         printf(- COMMENT  "%s",- UPVALNAME (- b ));
 
-         break; 
-    case OP_SETUPVAL: 
-         printf(- COMMENT  "%s",- UPVALNAME (- b ));
 
-         break; 
-    case OP_GETTABUP: 
-         printf(- COMMENT  "%s",- UPVALNAME (- b ));
 
-         printf(" ");-  PrintConstant (- f ,- c );
 
-         break; 
-    case OP_GETTABLE: 
-         break; 
-    case OP_GETI: 
-         break; 
-    case OP_GETFIELD: 
-         printf(- COMMENT );-  PrintConstant (- f ,- c );
 
-         break; 
-    case OP_SETTABUP: 
-         printf("%d %d %d%s",- a ,- b ,- c ,- ISK );
 
-         printf(- COMMENT  "%s",- UPVALNAME (- a ));
 
-         printf(" ");-  PrintConstant (- f ,- b );
 
-         if (- isk ) { printf(" ");-  PrintConstant (- f ,- c ); }
 
-         break; 
-    case OP_SETTABLE: 
-         printf("%d %d %d%s",- a ,- b ,- c ,- ISK );
 
-         if (- isk ) { printf(- COMMENT );-  PrintConstant (- f ,- c ); }
 
-         break; 
-    case OP_SETI: 
-         printf("%d %d %d%s",- a ,- b ,- c ,- ISK );
 
-         if (- isk ) { printf(- COMMENT );-  PrintConstant (- f ,- c ); }
 
-         break; 
-    case OP_SETFIELD: 
-         printf("%d %d %d%s",- a ,- b ,- c ,- ISK );
 
-         printf(- COMMENT );-  PrintConstant (- f ,- b );
 
-         if (- isk ) { printf(" ");-  PrintConstant (- f ,- c ); }
 
-         break; 
-    case OP_NEWTABLE: 
-         printf(- COMMENT  "%d",- c +- EXTRAARGC );
 
-         break; 
-    case OP_SELF: 
-         printf("%d %d %d%s",- a ,- b ,- c ,- ISK );
 
-         if (- isk ) { printf(- COMMENT );-  PrintConstant (- f ,- c ); }
 
-         break; 
-    case OP_ADDI: 
-         break; 
-    case OP_ADDK: 
-         printf(- COMMENT );-  PrintConstant (- f ,- c );
 
-         break; 
-    case OP_SUBK: 
-         printf(- COMMENT );-  PrintConstant (- f ,- c );
 
-         break; 
-    case OP_MULK: 
-         printf(- COMMENT );-  PrintConstant (- f ,- c );
 
-         break; 
-    case OP_MODK: 
-         printf(- COMMENT );-  PrintConstant (- f ,- c );
 
-         break; 
-    case OP_POWK: 
-         printf(- COMMENT );-  PrintConstant (- f ,- c );
 
-         break; 
-    case OP_DIVK: 
-         printf(- COMMENT );-  PrintConstant (- f ,- c );
 
-         break; 
-    case OP_IDIVK: 
-         printf(- COMMENT );-  PrintConstant (- f ,- c );
 
-         break; 
-    case OP_BANDK: 
-         printf(- COMMENT );-  PrintConstant (- f ,- c );
 
-         break; 
-    case OP_BORK: 
-         printf(- COMMENT );-  PrintConstant (- f ,- c );
 
-         break; 
-    case OP_BXORK: 
-         printf(- COMMENT );-  PrintConstant (- f ,- c );
 
-         break; 
-    case OP_SHRI: 
-         break; 
-    case OP_SHLI: 
-         break; 
-    case OP_ADD: 
-         break; 
-    case OP_SUB: 
-         break; 
-    case OP_MUL: 
-         break; 
-    case OP_MOD: 
-         break; 
-    case OP_POW: 
-         break; 
-    case OP_DIV: 
-         break; 
-    case OP_IDIV: 
-         break; 
-    case OP_BAND: 
-         break; 
-    case OP_BOR: 
-         break; 
-    case OP_BXOR: 
-         break; 
-    case OP_SHL: 
-         break; 
-    case OP_SHR: 
-         break; 
-    case OP_MMBIN: 
-         printf(- COMMENT  "%s",- eventname (- c ));
 
-         break; 
-    case OP_MMBINI: 
-         printf("%d %d %d %d",- a ,- sb ,- c ,- isk );
 
-         printf(- COMMENT  "%s",- eventname (- c ));
 
-         break; 
-    case OP_MMBINK: 
-         printf("%d %d %d %d",- a ,- b ,- c ,- isk );
 
-         printf(- COMMENT  "%s ",- eventname (- c ));-  PrintConstant (- f ,- b );
 
-         break; 
-    case OP_UNM: 
-         break; 
-    case OP_BNOT: 
-         break; 
-    case OP_NOT: 
-         break; 
-    case OP_LEN: 
-         break; 
-    case OP_CONCAT: 
-         break; 
-    case OP_CLOSE: 
-         break; 
-    case OP_TBC: 
-         break; 
-    case OP_JMP: 
-         printf(- COMMENT  "to %d",- GETARG_sJ (- i )+- pc +2);
 
-         break; 
-    case OP_EQ: 
-         break; 
-    case OP_LT: 
-         break; 
-    case OP_LE: 
-         break; 
-    case OP_EQK: 
-         printf(- COMMENT );-  PrintConstant (- f ,- b );
 
-         break; 
-    case OP_EQI: 
-         break; 
-    case OP_LTI: 
-         break; 
-    case OP_LEI: 
-         break; 
-    case OP_GTI: 
-         break; 
-    case OP_GEI: 
-         break; 
-    case OP_TEST: 
-         break; 
-    case OP_TESTSET: 
-         break; 
-    case OP_CALL: 
-         break; 
-    case OP_TAILCALL: 
-         printf("%d %d %d%s",- a ,- b ,- c ,- ISK );
 
-         break; 
-    case OP_RETURN: 
-         printf("%d %d %d%s",- a ,- b ,- c ,- ISK );
 
-         break; 
-    case OP_RETURN0: 
-         break; 
-    case OP_RETURN1: 
-         break; 
-    case OP_FORLOOP: 
-         printf(- COMMENT  "to %d",- pc -- bx +2);
 
-         break; 
-    case OP_FORPREP: 
-         printf(- COMMENT  "exit to %d",- pc +- bx +3);
 
-         break; 
-    case OP_TFORPREP: 
-         printf(- COMMENT  "to %d",- pc +- bx +2);
 
-         break; 
-    case OP_TFORCALL: 
-         break; 
-    case OP_TFORLOOP: 
-         printf(- COMMENT  "to %d",- pc -- bx +2);
 
-         break; 
-    case OP_SETLIST: 
-         if (- isk ) printf(- COMMENT  "%d",- c +- EXTRAARGC );
 
-         break; 
-    case OP_CLOSURE: 
-         printf(- COMMENT  "%p",- VOID (- f ->- p [- bx ]));
 
-         break; 
-    case OP_VARARG: 
-         break; 
-    case OP_VARARGPREP: 
-         break; 
-    case OP_EXTRAARG: 
-         break; 
- #if 0 
-    default: 
-         printf(- COMMENT  "not handled");
 
-         break; 
- #endif 
-   } 
-  } 
- } 
-   
-   
- #define SS(x)   ((x==1)?"":"s") 
- #define S(x)    (int)(x),SS(x) 
-   
- static void PrintHeader(const Proto* f) 
- { 
-  const char* s=f->source ? getstr(f->source) : "=?"; 
-  if (*s=='@' || *s=='=') 
-   s++; 
-  else if (*s==LUA_SIGNATURE[0]) 
-   s="(bstring)"; 
-  else 
-   s="(string)"; 
-  printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n", 
-         (f->linedefined==0)?"main":"function",s, 
-         f->linedefined,f->lastlinedefined, 
-         S(f->sizecode),VOID(f)); 
-  printf("%d%s param%s, %d slot%s, %d upvalue%s, ", 
-         (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), 
-         S(f->maxstacksize),S(f->sizeupvalues)); 
-  printf("%d local%s, %d constant%s, %d function%s\n", 
-         S(f->sizelocvars),S(f->sizek),S(f->sizep)); 
- } 
-   
- static void PrintDebug(const Proto* f) 
- { 
-  int i,n; 
-  n=f->sizek; 
-  printf("constants (%d) for %p:\n",- n ,- VOID (- f ));
 
-  for (i=0; i<n; i++) 
-  { 
-   PrintType(f,i); 
-   PrintConstant(f,i); 
-  } 
-  n=f->sizelocvars; 
-  printf("locals (%d) for %p:\n",- n ,- VOID (- f ));
 
-  for (i=0; i<n; i++) 
-  { 
-   i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); 
-  } 
-  n=f->sizeupvalues; 
-  printf("upvalues (%d) for %p:\n",- n ,- VOID (- f ));
 
-  for (i=0; i<n; i++) 
-  { 
-   i,UPVALNAME(i),f->upvalues[i].instack,f->upvalues[i].idx); 
-  } 
- } 
-   
- static void PrintFunction(const Proto* f, int full) 
- { 
-  int i,n=f->sizep; 
-  PrintHeader(f); 
-  PrintCode(f); 
-  if (full) PrintDebug(f); 
-  for (i=0; i<n; i++) PrintFunction(f->p[i],full); 
- } 
-