luac.c

Go to the documentation of this file.
00001 /*
00002 ** $Id: luac.c,v 1.54 2006/06/02 17:37:11 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 "ldo.h"
00019 #include "lfunc.h"
00020 #include "lmem.h"
00021 #include "lobject.h"
00022 #include "lopcodes.h"
00023 #include "lstring.h"
00024 #include "lundump.h"
00025 
00026 #define PROGNAME  "luac"    /* default program name */
00027 #define OUTPUT    PROGNAME ".out" /* default output file */
00028 
00029 static int listing=0;     /* list bytecodes? */
00030 static int dumping=1;     /* dump bytecodes? */
00031 static int stripping=0;     /* strip debug information? */
00032 static char Output[]={ OUTPUT };  /* default output file name */
00033 static const char* output=Output; /* actual output file name */
00034 static const char* progname=PROGNAME; /* actual program name */
00035 
00036 static void fatal(const char* message)
00037 {
00038  fprintf(stderr,"%s: %s\n",progname,message);
00039  exit(EXIT_FAILURE);
00040 }
00041 
00042 static void cannot(const char* what)
00043 {
00044  fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno));
00045  exit(EXIT_FAILURE);
00046 }
00047 
00048 static void usage(const char* message)
00049 {
00050  if (*message=='-')
00051   fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message);
00052  else
00053   fprintf(stderr,"%s: %s\n",progname,message);
00054  fprintf(stderr,
00055  "usage: %s [options] [filenames].\n"
00056  "Available options are:\n"
00057  "  -        process stdin\n"
00058  "  -l       list\n"
00059  "  -o name  output to file " LUA_QL("name") " (default is \"%s\")\n"
00060  "  -p       parse only\n"
00061  "  -s       strip debug information\n"
00062  "  -v       show version information\n"
00063  "  --       stop handling options\n",
00064  progname,Output);
00065  exit(EXIT_FAILURE);
00066 }
00067 
00068 #define IS(s) (strcmp(argv[i],s)==0)
00069 
00070 static int doargs(int argc, char* argv[])
00071 {
00072  int i;
00073  int version=0;
00074  if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0];
00075  for (i=1; i<argc; i++)
00076  {
00077   if (*argv[i]!='-')      /* end of options; keep it */
00078    break;
00079   else if (IS("--"))      /* end of options; skip it */
00080   {
00081    ++i;
00082    if (version) ++version;
00083    break;
00084   }
00085   else if (IS("-"))     /* end of options; use stdin */
00086    break;
00087   else if (IS("-l"))      /* list */
00088    ++listing;
00089   else if (IS("-o"))      /* output file */
00090   {
00091    output=argv[++i];
00092    if (output==NULL || *output==0) 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  %s\n",LUA_RELEASE,LUA_COPYRIGHT);
00112   if (version==argc-1) exit(EXIT_SUCCESS);
00113  }
00114  return i;
00115 }
00116 
00117 #define toproto(L,i) (clvalue(L->top+(i))->l.p)
00118 
00119 static const Proto* combine(lua_State* L, int n)
00120 {
00121  if (n==1)
00122   return toproto(L,-1);
00123  else
00124  {
00125   int i,pc;
00126   Proto* f=luaF_newproto(L);
00127   setptvalue2s(L,L->top,f); incr_top(L);
00128   f->source=luaS_newliteral(L,"=(" PROGNAME ")");
00129   f->maxstacksize=1;
00130   pc=2*n+1;
00131   f->code=luaM_newvector(L,pc,Instruction);
00132   f->sizecode=pc;
00133   f->p=luaM_newvector(L,n,Proto*);
00134   f->sizep=n;
00135   pc=0;
00136   for (i=0; i<n; i++)
00137   {
00138    f->p[i]=toproto(L,i-n-1);
00139    f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i);
00140    f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1);
00141   }
00142   f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0);
00143   return f;
00144  }
00145 }
00146 
00147 static int writer(lua_State* L, const void* p, size_t size, void* u)
00148 {
00149  UNUSED(L);
00150  return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);
00151 }
00152 
00153 struct Smain {
00154  int argc;
00155  char** argv;
00156 };
00157 
00158 static int pmain(lua_State* L)
00159 {
00160  struct Smain* s = (struct Smain*)lua_touserdata(L, 1);
00161  int argc=s->argc;
00162  char** argv=s->argv;
00163  const Proto* f;
00164  int i;
00165  if (!lua_checkstack(L,argc)) fatal("too many input files");
00166  for (i=0; i<argc; i++)
00167  {
00168   const char* filename=IS("-") ? NULL : argv[i];
00169   if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1));
00170  }
00171  f=combine(L,argc);
00172  if (listing) luaU_print(f,listing>1);
00173  if (dumping)
00174  {
00175   FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
00176   if (D==NULL) cannot("open");
00177   lua_lock(L);
00178   luaU_dump(L,f,writer,D,stripping);
00179   lua_unlock(L);
00180   if (ferror(D)) cannot("write");
00181   if (fclose(D)) cannot("close");
00182  }
00183  return 0;
00184 }
00185 
00186 int main(int argc, char* argv[])
00187 {
00188  lua_State* L;
00189  struct Smain s;
00190  int i=doargs(argc,argv);
00191  argc-=i; argv+=i;
00192  if (argc<=0) usage("no input files given");
00193  L=lua_open();
00194  if (L==NULL) fatal("not enough memory for state");
00195  s.argc=argc;
00196  s.argv=argv;
00197  if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1));
00198  lua_close(L);
00199  return EXIT_SUCCESS;
00200 }

ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:55 2011 by Doxygen 1.6.1