00001
00002
00003
00004
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"
00027 #define OUTPUT PROGNAME ".out"
00028
00029 static int listing=0;
00030 static int dumping=1;
00031 static int stripping=0;
00032 static char Output[]={ OUTPUT };
00033 static const char* output=Output;
00034 static const char* progname=PROGNAME;
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]!='-')
00078 break;
00079 else if (IS("--"))
00080 {
00081 ++i;
00082 if (version) ++version;
00083 break;
00084 }
00085 else if (IS("-"))
00086 break;
00087 else if (IS("-l"))
00088 ++listing;
00089 else if (IS("-o"))
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"))
00096 dumping=0;
00097 else if (IS("-s"))
00098 stripping=1;
00099 else if (IS("-v"))
00100 ++version;
00101 else
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 }