1/* 2** $Id: luac.c,v 1.69 2011/11/29 17:46:33 lhf Exp $ 3** Lua compiler (saves bytecodes to files; also list bytecodes) 4** See Copyright Notice in lua.h 5*/ 6 7#include <errno.h> 8#include <stdio.h> 9#include <stdlib.h> 10#include <string.h> 11 12#define luac_c 13#define LUA_CORE 14 15#include "lua.h" 16#include "lauxlib.h" 17 18#include "lobject.h" 19#include "lstate.h" 20#include "lundump.h" 21 22static void PrintFunction(const Proto* f, int full); 23#define luaU_print PrintFunction 24 25#define PROGNAME "luac" /* default program name */ 26#define OUTPUT PROGNAME ".out" /* default output file */ 27 28static int listing=0; /* list bytecodes? */ 29static int dumping=1; /* dump bytecodes? */ 30static int stripping=0; /* strip debug information? */ 31static char Output[]={ OUTPUT }; /* default output file name */ 32static const char* output=Output; /* actual output file name */ 33static const char* progname=PROGNAME; /* actual program name */ 34 35static void fatal(const char* message) 36{ 37 fprintf(stderr,"%s: %s\n",progname,message); 38 exit(EXIT_FAILURE); 39} 40 41static void cannot(const char* what) 42{ 43 fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); 44 exit(EXIT_FAILURE); 45} 46 47static void usage(const char* message) 48{ 49 if (*message=='-') 50 fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message); 51 else 52 fprintf(stderr,"%s: %s\n",progname,message); 53 fprintf(stderr, 54 "usage: %s [options] [filenames]\n" 55 "Available options are:\n" 56 " -l list (use -l -l for full listing)\n" 57 " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" 58 " -p parse only\n" 59 " -s strip debug information\n" 60 " -v show version information\n" 61 " -- stop handling options\n" 62 " - stop handling options and process stdin\n" 63 ,progname,Output); 64 exit(EXIT_FAILURE); 65} 66 67#define IS(s) (strcmp(argv[i],s)==0) 68 69static int doargs(int argc, char* argv[]) 70{ 71 int i; 72 int version=0; 73 if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; 74 for (i=1; i<argc; i++) 75 { 76 if (*argv[i]!='-') /* end of options; keep it */ 77 break; 78 else if (IS("--")) /* end of options; skip it */ 79 { 80 ++i; 81 if (version) ++version; 82 break; 83 } 84 else if (IS("-")) /* end of options; use stdin */ 85 break; 86 else if (IS("-l")) /* list */ 87 ++listing; 88 else if (IS("-o")) /* output file */ 89 { 90 output=argv[++i]; 91 if (output==NULL || *output==0 || (*output=='-' && output[1]!=0)) 92 usage(LUA_QL("-o") " needs argument"); 93 if (IS("-")) output=NULL; 94 } 95 else if (IS("-p")) /* parse only */ 96 dumping=0; 97 else if (IS("-s")) /* strip debug information */ 98 stripping=1; 99 else if (IS("-v")) /* show version */ 100 ++version; 101 else /* unknown option */ 102 usage(argv[i]); 103 } 104 if (i==argc && (listing || !dumping)) 105 { 106 dumping=0; 107 argv[--i]=Output; 108 } 109 if (version) 110 { 111 printf("%s\n",LUA_COPYRIGHT); 112 if (version==argc-1) exit(EXIT_SUCCESS); 113 } 114 return i; 115} 116 117#define FUNCTION "(function()end)();" 118 119static const char* reader(lua_State *L, void *ud, size_t *size) 120{ 121 UNUSED(L); 122 if ((*(int*)ud)--) 123 { 124 *size=sizeof(FUNCTION)-1; 125 return FUNCTION; 126 } 127 else 128 { 129 *size=0; 130 return NULL; 131 } 132} 133 134#define toproto(L,i) getproto(L->top+(i)) 135 136static const Proto* combine(lua_State* L, int n) 137{ 138 if (n==1) 139 return toproto(L,-1); 140 else 141 { 142 Proto* f; 143 int i=n; 144 if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1)); 145 f=toproto(L,-1); 146 for (i=0; i<n; i++) 147 { 148 f->p[i]=toproto(L,i-n-1); 149 if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; 150 } 151 f->sizelineinfo=0; 152 return f; 153 } 154} 155 156static int writer(lua_State* L, const void* p, size_t size, void* u) 157{ 158 UNUSED(L); 159 return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); 160} 161 162static int pmain(lua_State* L) 163{ 164 int argc=(int)lua_tointeger(L,1); 165 char** argv=(char**)lua_touserdata(L,2); 166 const Proto* f; 167 int i; 168 if (!lua_checkstack(L,argc)) fatal("too many input files"); 169 for (i=0; i<argc; i++) 170 { 171 const char* filename=IS("-") ? NULL : argv[i]; 172 if (luaL_loadfile(L,filename)!=LUA_OK) fatal(lua_tostring(L,-1)); 173 } 174 f=combine(L,argc); 175 if (listing) luaU_print(f,listing>1); 176 if (dumping) 177 { 178 FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); 179 if (D==NULL) cannot("open"); 180 lua_lock(L); 181 luaU_dump(L,f,writer,D,stripping); 182 lua_unlock(L); 183 if (ferror(D)) cannot("write"); 184 if (fclose(D)) cannot("close"); 185 } 186 return 0; 187} 188 189int main(int argc, char* argv[]) 190{ 191 lua_State* L; 192 int i=doargs(argc,argv); 193 argc-=i; argv+=i; 194 if (argc<=0) usage("no input files given"); 195 L=luaL_newstate(); 196 if (L==NULL) fatal("cannot create state: not enough memory"); 197 lua_pushcfunction(L,&pmain); 198 lua_pushinteger(L,argc); 199 lua_pushlightuserdata(L,argv); 200 if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1)); 201 lua_close(L); 202 return EXIT_SUCCESS; 203} 204 205/* 206** $Id: print.c,v 1.69 2013/07/04 01:03:46 lhf Exp $ 207** print bytecodes 208** See Copyright Notice in lua.h 209*/ 210 211#include <ctype.h> 212#include <stdio.h> 213 214#define luac_c 215#define LUA_CORE 216 217#include "ldebug.h" 218#include "lobject.h" 219#include "lopcodes.h" 220 221#define VOID(p) ((const void*)(p)) 222 223static void PrintString(const TString* ts) 224{ 225 const char* s=getstr(ts); 226 size_t i,n=ts->tsv.len; 227 printf("%c",'"'); 228 for (i=0; i<n; i++) 229 { 230 int c=(int)(unsigned char)s[i]; 231 switch (c) 232 { 233 case '"': printf("\\\""); break; 234 case '\\': printf("\\\\"); break; 235 case '\a': printf("\\a"); break; 236 case '\b': printf("\\b"); break; 237 case '\f': printf("\\f"); break; 238 case '\n': printf("\\n"); break; 239 case '\r': printf("\\r"); break; 240 case '\t': printf("\\t"); break; 241 case '\v': printf("\\v"); break; 242 default: if (isprint(c)) 243 printf("%c",c); 244 else 245 printf("\\%03d",c); 246 } 247 } 248 printf("%c",'"'); 249} 250 251static void PrintConstant(const Proto* f, int i) 252{ 253 const TValue* o=&f->k[i]; 254 switch (ttypenv(o)) 255 { 256 case LUA_TNIL: 257 printf("nil"); 258 break; 259 case LUA_TBOOLEAN: 260 printf(bvalue(o) ? "true" : "false"); 261 break; 262 case LUA_TNUMBER: 263 printf(LUA_NUMBER_FMT,nvalue(o)); 264 break; 265 case LUA_TSTRING: 266 PrintString(rawtsvalue(o)); 267 break; 268 default: /* cannot happen */ 269 printf("? type=%d",ttype(o)); 270 break; 271 } 272} 273 274#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") 275#define MYK(x) (-1-(x)) 276 277static void PrintCode(const Proto* f) 278{ 279 const Instruction* code=f->code; 280 int pc,n=f->sizecode; 281 for (pc=0; pc<n; pc++) 282 { 283 Instruction i=code[pc]; 284 OpCode o=GET_OPCODE(i); 285 int a=GETARG_A(i); 286 int b=GETARG_B(i); 287 int c=GETARG_C(i); 288 int ax=GETARG_Ax(i); 289 int bx=GETARG_Bx(i); 290 int sbx=GETARG_sBx(i); 291 int line=getfuncline(f,pc); 292 printf("\t%d\t",pc+1); 293 if (line>0) printf("[%d]\t",line); else printf("[-]\t"); 294 printf("%-9s\t",luaP_opnames[o]); 295 switch (getOpMode(o)) 296 { 297 case iABC: 298 printf("%d",a); 299 if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (MYK(INDEXK(b))) : b); 300 if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c); 301 break; 302 case iABx: 303 printf("%d",a); 304 if (getBMode(o)==OpArgK) printf(" %d",MYK(bx)); 305 if (getBMode(o)==OpArgU) printf(" %d",bx); 306 break; 307 case iAsBx: 308 printf("%d %d",a,sbx); 309 break; 310 case iAx: 311 printf("%d",MYK(ax)); 312 break; 313 } 314 switch (o) 315 { 316 case OP_LOADK: 317 printf("\t; "); PrintConstant(f,bx); 318 break; 319 case OP_GETUPVAL: 320 case OP_SETUPVAL: 321 printf("\t; %s",UPVALNAME(b)); 322 break; 323 case OP_GETTABUP: 324 printf("\t; %s",UPVALNAME(b)); 325 if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } 326 break; 327 case OP_SETTABUP: 328 printf("\t; %s",UPVALNAME(a)); 329 if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); } 330 if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } 331 break; 332 case OP_GETTABLE: 333 case OP_SELF: 334 if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } 335 break; 336 case OP_SETTABLE: 337 case OP_ADD: 338 case OP_SUB: 339 case OP_MUL: 340 case OP_DIV: 341 case OP_POW: 342 case OP_EQ: 343 case OP_LT: 344 case OP_LE: 345 if (ISK(b) || ISK(c)) 346 { 347 printf("\t; "); 348 if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); 349 printf(" "); 350 if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); 351 } 352 break; 353 case OP_JMP: 354 case OP_FORLOOP: 355 case OP_FORPREP: 356 case OP_TFORLOOP: 357 printf("\t; to %d",sbx+pc+2); 358 break; 359 case OP_CLOSURE: 360 printf("\t; %p",VOID(f->p[bx])); 361 break; 362 case OP_SETLIST: 363 if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c); 364 break; 365 case OP_EXTRAARG: 366 printf("\t; "); PrintConstant(f,ax); 367 break; 368 default: 369 break; 370 } 371 printf("\n"); 372 } 373} 374 375#define SS(x) ((x==1)?"":"s") 376#define S(x) (int)(x),SS(x) 377 378static void PrintHeader(const Proto* f) 379{ 380 const char* s=f->source ? getstr(f->source) : "=?"; 381 if (*s=='@' || *s=='=') 382 s++; 383 else if (*s==LUA_SIGNATURE[0]) 384 s="(bstring)"; 385 else 386 s="(string)"; 387 printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n", 388 (f->linedefined==0)?"main":"function",s, 389 f->linedefined,f->lastlinedefined, 390 S(f->sizecode),VOID(f)); 391 printf("%d%s param%s, %d slot%s, %d upvalue%s, ", 392 (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), 393 S(f->maxstacksize),S(f->sizeupvalues)); 394 printf("%d local%s, %d constant%s, %d function%s\n", 395 S(f->sizelocvars),S(f->sizek),S(f->sizep)); 396} 397 398static void PrintDebug(const Proto* f) 399{ 400 int i,n; 401 n=f->sizek; 402 printf("constants (%d) for %p:\n",n,VOID(f)); 403 for (i=0; i<n; i++) 404 { 405 printf("\t%d\t",i+1); 406 PrintConstant(f,i); 407 printf("\n"); 408 } 409 n=f->sizelocvars; 410 printf("locals (%d) for %p:\n",n,VOID(f)); 411 for (i=0; i<n; i++) 412 { 413 printf("\t%d\t%s\t%d\t%d\n", 414 i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); 415 } 416 n=f->sizeupvalues; 417 printf("upvalues (%d) for %p:\n",n,VOID(f)); 418 for (i=0; i<n; i++) 419 { 420 printf("\t%d\t%s\t%d\t%d\n", 421 i,UPVALNAME(i),f->upvalues[i].instack,f->upvalues[i].idx); 422 } 423} 424 425static void PrintFunction(const Proto* f, int full) 426{ 427 int i,n=f->sizep; 428 PrintHeader(f); 429 PrintCode(f); 430 if (full) PrintDebug(f); 431 for (i=0; i<n; i++) PrintFunction(f->p[i],full); 432} 433