lua/luac.c

Go to the documentation of this file.
00001 /*
00002 ** $Id: luac.c,v 1.69 2011/11/29 17:46:33 lhf Exp $
00003 ** Lua compiler (saves bytecodes to files; also list bytecodes)
00004 ** See Copyright Notice in lua.h
00005 */
00006 
00007 #include <errno.h>
00008 #include <stdio.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 
00012 #define luac_c
00013 #define LUA_CORE
00014 
00015 #include "lua.h"
00016 #include "lauxlib.h"
00017 
00018 #include "lobject.h"
00019 #include "lstate.h"
00020 #include "lundump.h"
00021 
00022 static void PrintFunction(const Proto* f, int full);
00023 #define luaU_print  PrintFunction
00024 
00025 #define PROGNAME    "luac"      /* default program name */
00026 #define OUTPUT      PROGNAME ".out" /* default output file */
00027 
00028 static int listing=0;           /* list bytecodes? */
00029 static int dumping=1;           /* dump bytecodes? */
00030 static int stripping=0;         /* strip debug information? */
00031 static char Output[]={ OUTPUT };    /* default output file name */
00032 static const char* output=Output;   /* actual output file name */
00033 static const char* progname=PROGNAME;   /* actual program name */
00034 
00035 static void fatal(const char* message)
00036 {
00037  fprintf(stderr,"%s: %s\n",progname,message);
00038  exit(EXIT_FAILURE);
00039 }
00040 
00041 static void cannot(const char* what)
00042 {
00043  fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno));
00044  exit(EXIT_FAILURE);
00045 }
00046 
00047 static void usage(const char* message)
00048 {
00049  if (*message=='-')
00050   fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message);
00051  else
00052   fprintf(stderr,"%s: %s\n",progname,message);
00053  fprintf(stderr,
00054   "usage: %s [options] [filenames]\n"
00055   "Available options are:\n"
00056   "  -l       list (use -l -l for full listing)\n"
00057   "  -o name  output to file " LUA_QL("name") " (default is \"%s\")\n"
00058   "  -p       parse only\n"
00059   "  -s       strip debug information\n"
00060   "  -v       show version information\n"
00061   "  --       stop handling options\n"
00062   "  -        stop handling options and process stdin\n"
00063   ,progname,Output);
00064  exit(EXIT_FAILURE);
00065 }
00066 
00067 #define IS(s)   (strcmp(argv[i],s)==0)
00068 
00069 static int doargs(int argc, char* argv[])
00070 {
00071  int i;
00072  int version=0;
00073  if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0];
00074  for (i=1; i<argc; i++)
00075  {
00076   if (*argv[i]!='-')            /* end of options; keep it */
00077    break;
00078   else if (IS("--"))            /* end of options; skip it */
00079   {
00080    ++i;
00081    if (version) ++version;
00082    break;
00083   }
00084   else if (IS("-"))         /* end of options; use stdin */
00085    break;
00086   else if (IS("-l"))            /* list */
00087    ++listing;
00088   else if (IS("-o"))            /* output file */
00089   {
00090    output=argv[++i];
00091    if (output==NULL || *output==0 || (*output=='-' && output[1]!=0))
00092     usage(LUA_QL("-o") " needs argument");
00093    if (IS("-")) output=NULL;
00094   }
00095   else if (IS("-p"))            /* parse only */
00096    dumping=0;
00097   else if (IS("-s"))            /* strip debug information */
00098    stripping=1;
00099   else if (IS("-v"))            /* show version */
00100    ++version;
00101   else                  /* unknown option */
00102    usage(argv[i]);
00103  }
00104  if (i==argc && (listing || !dumping))
00105  {
00106   dumping=0;
00107   argv[--i]=Output;
00108  }
00109  if (version)
00110  {
00111   printf("%s\n",LUA_COPYRIGHT);
00112   if (version==argc-1) exit(EXIT_SUCCESS);
00113  }
00114  return i;
00115 }
00116 
00117 #define FUNCTION "(function()end)();"
00118 
00119 static const char* reader(lua_State *L, void *ud, size_t *size)
00120 {
00121  UNUSED(L);
00122  if ((*(int*)ud)--)
00123  {
00124   *size=sizeof(FUNCTION)-1;
00125   return FUNCTION;
00126  }
00127  else
00128  {
00129   *size=0;
00130   return NULL;
00131  }
00132 }
00133 
00134 #define toproto(L,i) getproto(L->top+(i))
00135 
00136 static const Proto* combine(lua_State* L, int n)
00137 {
00138  if (n==1)
00139   return toproto(L,-1);
00140  else
00141  {
00142   Proto* f;
00143   int i=n;
00144   if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1));
00145   f=toproto(L,-1);
00146   for (i=0; i<n; i++)
00147   {
00148    f->p[i]=toproto(L,i-n-1);
00149    if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0;
00150   }
00151   f->sizelineinfo=0;
00152   return f;
00153  }
00154 }
00155 
00156 static int writer(lua_State* L, const void* p, size_t size, void* u)
00157 {
00158  UNUSED(L);
00159  return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);
00160 }
00161 
00162 static int pmain(lua_State* L)
00163 {
00164  int argc=(int)lua_tointeger(L,1);
00165  char** argv=(char**)lua_touserdata(L,2);
00166  const Proto* f;
00167  int i;
00168  if (!lua_checkstack(L,argc)) fatal("too many input files");
00169  for (i=0; i<argc; i++)
00170  {
00171   const char* filename=IS("-") ? NULL : argv[i];
00172   if (luaL_loadfile(L,filename)!=LUA_OK) fatal(lua_tostring(L,-1));
00173  }
00174  f=combine(L,argc);
00175  if (listing) luaU_print(f,listing>1);
00176  if (dumping)
00177  {
00178   FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
00179   if (D==NULL) cannot("open");
00180   lua_lock(L);
00181   luaU_dump(L,f,writer,D,stripping);
00182   lua_unlock(L);
00183   if (ferror(D)) cannot("write");
00184   if (fclose(D)) cannot("close");
00185  }
00186  return 0;
00187 }
00188 
00189 int main(int argc, char* argv[])
00190 {
00191  lua_State* L;
00192  int i=doargs(argc,argv);
00193  argc-=i; argv+=i;
00194  if (argc<=0) usage("no input files given");
00195  L=luaL_newstate();
00196  if (L==NULL) fatal("cannot create state: not enough memory");
00197  lua_pushcfunction(L,&pmain);
00198  lua_pushinteger(L,argc);
00199  lua_pushlightuserdata(L,argv);
00200  if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1));
00201  lua_close(L);
00202  return EXIT_SUCCESS;
00203 }
00204 
00205 /*
00206 ** $Id: print.c,v 1.68 2011/09/30 10:21:20 lhf Exp $
00207 ** print bytecodes
00208 ** See Copyright Notice in lua.h
00209 */
00210 
00211 #include <ctype.h>
00212 #include <stdio.h>
00213 
00214 #define luac_c
00215 #define LUA_CORE
00216 
00217 #include "ldebug.h"
00218 #include "lobject.h"
00219 #include "lopcodes.h"
00220 
00221 #define VOID(p)     ((const void*)(p))
00222 
00223 static void PrintString(const TString* ts)
00224 {
00225  const char* s=getstr(ts);
00226  size_t i,n=ts->tsv.len;
00227  printf("%c",'"');
00228  for (i=0; i<n; i++)
00229  {
00230   int c=(int)(unsigned char)s[i];
00231   switch (c)
00232   {
00233    case '"':  printf("\\\""); break;
00234    case '\\': printf("\\\\"); break;
00235    case '\a': printf("\\a"); break;
00236    case '\b': printf("\\b"); break;
00237    case '\f': printf("\\f"); break;
00238    case '\n': printf("\\n"); break;
00239    case '\r': printf("\\r"); break;
00240    case '\t': printf("\\t"); break;
00241    case '\v': printf("\\v"); break;
00242    default: if (isprint(c))
00243             printf("%c",c);
00244         else
00245             printf("\\%03d",c);
00246   }
00247  }
00248  printf("%c",'"');
00249 }
00250 
00251 static void PrintConstant(const Proto* f, int i)
00252 {
00253  const TValue* o=&f->k[i];
00254  switch (ttype(o))
00255  {
00256   case LUA_TNIL:
00257     printf("nil");
00258     break;
00259   case LUA_TBOOLEAN:
00260     printf(bvalue(o) ? "true" : "false");
00261     break;
00262   case LUA_TNUMBER:
00263     printf(LUA_NUMBER_FMT,nvalue(o));
00264     break;
00265   case LUA_TSTRING:
00266     PrintString(rawtsvalue(o));
00267     break;
00268   default:              /* cannot happen */
00269     printf("? type=%d",ttype(o));
00270     break;
00271  }
00272 }
00273 
00274 #define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-")
00275 #define MYK(x)      (-1-(x))
00276 
00277 static void PrintCode(const Proto* f)
00278 {
00279  const Instruction* code=f->code;
00280  int pc,n=f->sizecode;
00281  for (pc=0; pc<n; pc++)
00282  {
00283   Instruction i=code[pc];
00284   OpCode o=GET_OPCODE(i);
00285   int a=GETARG_A(i);
00286   int b=GETARG_B(i);
00287   int c=GETARG_C(i);
00288   int ax=GETARG_Ax(i);
00289   int bx=GETARG_Bx(i);
00290   int sbx=GETARG_sBx(i);
00291   int line=getfuncline(f,pc);
00292   printf("\t%d\t",pc+1);
00293   if (line>0) printf("[%d]\t",line); else printf("[-]\t");
00294   printf("%-9s\t",luaP_opnames[o]);
00295   switch (getOpMode(o))
00296   {
00297    case iABC:
00298     printf("%d",a);
00299     if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (MYK(INDEXK(b))) : b);
00300     if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c);
00301     break;
00302    case iABx:
00303     printf("%d",a);
00304     if (getBMode(o)==OpArgK) printf(" %d",MYK(bx));
00305     if (getBMode(o)==OpArgU) printf(" %d",bx);
00306     break;
00307    case iAsBx:
00308     printf("%d %d",a,sbx);
00309     break;
00310    case iAx:
00311     printf("%d",MYK(ax));
00312     break;
00313   }
00314   switch (o)
00315   {
00316    case OP_LOADK:
00317     printf("\t; "); PrintConstant(f,bx);
00318     break;
00319    case OP_GETUPVAL:
00320    case OP_SETUPVAL:
00321     printf("\t; %s",UPVALNAME(b));
00322     break;
00323    case OP_GETTABUP:
00324     printf("\t; %s",UPVALNAME(b));
00325     if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); }
00326     break;
00327    case OP_SETTABUP:
00328     printf("\t; %s",UPVALNAME(a));
00329     if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); }
00330     if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); }
00331     break;
00332    case OP_GETTABLE:
00333    case OP_SELF:
00334     if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); }
00335     break;
00336    case OP_SETTABLE:
00337    case OP_ADD:
00338    case OP_SUB:
00339    case OP_MUL:
00340    case OP_DIV:
00341    case OP_POW:
00342    case OP_EQ:
00343    case OP_LT:
00344    case OP_LE:
00345     if (ISK(b) || ISK(c))
00346     {
00347      printf("\t; ");
00348      if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-");
00349      printf(" ");
00350      if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-");
00351     }
00352     break;
00353    case OP_JMP:
00354    case OP_FORLOOP:
00355    case OP_FORPREP:
00356    case OP_TFORLOOP:
00357     printf("\t; to %d",sbx+pc+2);
00358     break;
00359    case OP_CLOSURE:
00360     printf("\t; %p",VOID(f->p[bx]));
00361     break;
00362    case OP_SETLIST:
00363     if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c);
00364     break;
00365    case OP_EXTRAARG:
00366     printf("\t; "); PrintConstant(f,ax);
00367     break;
00368    default:
00369     break;
00370   }
00371   printf("\n");
00372  }
00373 }
00374 
00375 #define SS(x)   ((x==1)?"":"s")
00376 #define S(x)    (int)(x),SS(x)
00377 
00378 static void PrintHeader(const Proto* f)
00379 {
00380  const char* s=f->source ? getstr(f->source) : "=?";
00381  if (*s=='@' || *s=='=')
00382   s++;
00383  else if (*s==LUA_SIGNATURE[0])
00384   s="(bstring)";
00385  else
00386   s="(string)";
00387  printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n",
00388     (f->linedefined==0)?"main":"function",s,
00389     f->linedefined,f->lastlinedefined,
00390     S(f->sizecode),VOID(f));
00391  printf("%d%s param%s, %d slot%s, %d upvalue%s, ",
00392     (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams),
00393     S(f->maxstacksize),S(f->sizeupvalues));
00394  printf("%d local%s, %d constant%s, %d function%s\n",
00395     S(f->sizelocvars),S(f->sizek),S(f->sizep));
00396 }
00397 
00398 static void PrintDebug(const Proto* f)
00399 {
00400  int i,n;
00401  n=f->sizek;
00402  printf("constants (%d) for %p:\n",n,VOID(f));
00403  for (i=0; i<n; i++)
00404  {
00405   printf("\t%d\t",i+1);
00406   PrintConstant(f,i);
00407   printf("\n");
00408  }
00409  n=f->sizelocvars;
00410  printf("locals (%d) for %p:\n",n,VOID(f));
00411  for (i=0; i<n; i++)
00412  {
00413   printf("\t%d\t%s\t%d\t%d\n",
00414   i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);
00415  }
00416  n=f->sizeupvalues;
00417  printf("upvalues (%d) for %p:\n",n,VOID(f));
00418  for (i=0; i<n; i++)
00419  {
00420   printf("\t%d\t%s\t%d\t%d\n",
00421   i,UPVALNAME(i),f->upvalues[i].instack,f->upvalues[i].idx);
00422  }
00423 }
00424 
00425 static void PrintFunction(const Proto* f, int full)
00426 {
00427  int i,n=f->sizep;
00428  PrintHeader(f);
00429  PrintCode(f);
00430  if (full) PrintDebug(f);
00431  for (i=0; i<n; i++) PrintFunction(f->p[i],full);
00432 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:04 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs