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 "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"
00026 #define OUTPUT PROGNAME ".out"
00027
00028 static int listing=0;
00029 static int dumping=1;
00030 static int stripping=0;
00031 static char Output[]={ OUTPUT };
00032 static const char* output=Output;
00033 static const char* progname=PROGNAME;
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]!='-')
00077 break;
00078 else if (IS("--"))
00079 {
00080 ++i;
00081 if (version) ++version;
00082 break;
00083 }
00084 else if (IS("-"))
00085 break;
00086 else if (IS("-l"))
00087 ++listing;
00088 else if (IS("-o"))
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"))
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\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
00207
00208
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:
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 }