1 /* 2 ** $Id: luac.c $ 3 ** Lua compiler (saves bytecodes to files; also lists bytecodes) 4 ** See Copyright Notice in lua.h 5 */ 6 7 #define luac_c 8 #define LUA_CORE 9 10 #include "lprefix.h" 11 12 #include <ctype.h> 13 #include <errno.h> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 18 #include "lua.h" 19 #include "lauxlib.h" 20 21 #include "ldebug.h" 22 #include "lobject.h" 23 #include "lopcodes.h" 24 #include "lopnames.h" 25 #include "lstate.h" 26 #include "lundump.h" 27 28 static void PrintFunction(const Proto* f, int full); 29 #define luaU_print PrintFunction 30 31 #define PROGNAME "luac" /* default program name */ 32 #define OUTPUT PROGNAME ".out" /* default output file */ 33 34 static int listing=0; /* list bytecodes? */ 35 static int dumping=1; /* dump bytecodes? */ 36 static int stripping=0; /* strip debug information? */ 37 static char Output[]={ OUTPUT }; /* default output file name */ 38 static const char* output=Output; /* actual output file name */ 39 static const char* progname=PROGNAME; /* actual program name */ 40 static TString **tmname; 41 42 static void fatal(const char* message) 43 { 44 fprintf(stderr,"%s: %s\n",progname,message); 45 exit(EXIT_FAILURE); 46 } 47 48 static void cannot(const char* what) 49 { 50 fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); 51 exit(EXIT_FAILURE); 52 } 53 54 static void usage(const char* message) 55 { 56 if (*message=='-') 57 fprintf(stderr,"%s: unrecognized option '%s'\n",progname,message); 58 else 59 fprintf(stderr,"%s: %s\n",progname,message); 60 fprintf(stderr, 61 "usage: %s [options] [filenames]\n" 62 "Available options are:\n" 63 " -l list (use -l -l for full listing)\n" 64 " -o name output to file 'name' (default is \"%s\")\n" 65 " -p parse only\n" 66 " -s strip debug information\n" 67 " -v show version information\n" 68 " -- stop handling options\n" 69 " - stop handling options and process stdin\n" 70 ,progname,Output); 71 exit(EXIT_FAILURE); 72 } 73 74 #define IS(s) (strcmp(argv[i],s)==0) 75 76 static int doargs(int argc, char* argv[]) 77 { 78 int i; 79 int version=0; 80 if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; 81 for (i=1; i<argc; i++) 82 { 83 if (*argv[i]!='-') /* end of options; keep it */ 84 break; 85 else if (IS("--")) /* end of options; skip it */ 86 { 87 ++i; 88 if (version) ++version; 89 break; 90 } 91 else if (IS("-")) /* end of options; use stdin */ 92 break; 93 else if (IS("-l")) /* list */ 94 ++listing; 95 else if (IS("-o")) /* output file */ 96 { 97 output=argv[++i]; 98 if (output==NULL || *output==0 || (*output=='-' && output[1]!=0)) 99 usage("'-o' needs argument"); 100 if (IS("-")) output=NULL; 101 } 102 else if (IS("-p")) /* parse only */ 103 dumping=0; 104 else if (IS("-s")) /* strip debug information */ 105 stripping=1; 106 else if (IS("-v")) /* show version */ 107 ++version; 108 else /* unknown option */ 109 usage(argv[i]); 110 } 111 if (i==argc && (listing || !dumping)) 112 { 113 dumping=0; 114 argv[--i]=Output; 115 } 116 if (version) 117 { 118 printf("%s\n",LUA_COPYRIGHT); 119 if (version==argc-1) exit(EXIT_SUCCESS); 120 } 121 return i; 122 } 123 124 #define FUNCTION "(function()end)();\n" 125 126 static const char* reader(lua_State* L, void* ud, size_t* size) 127 { 128 UNUSED(L); 129 if ((*(int*)ud)--) 130 { 131 *size=sizeof(FUNCTION)-1; 132 return FUNCTION; 133 } 134 else 135 { 136 *size=0; 137 return NULL; 138 } 139 } 140 141 #define toproto(L,i) getproto(s2v(L->top.p+(i))) 142 143 static const Proto* combine(lua_State* L, int n) 144 { 145 if (n==1) 146 return toproto(L,-1); 147 else 148 { 149 Proto* f; 150 int i=n; 151 if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1)); 152 f=toproto(L,-1); 153 for (i=0; i<n; i++) 154 { 155 f->p[i]=toproto(L,i-n-1); 156 if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; 157 } 158 return f; 159 } 160 } 161 162 static int writer(lua_State* L, const void* p, size_t size, void* u) 163 { 164 UNUSED(L); 165 return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); 166 } 167 168 static int pmain(lua_State* L) 169 { 170 int argc=(int)lua_tointeger(L,1); 171 char** argv=(char**)lua_touserdata(L,2); 172 const Proto* f; 173 int i; 174 tmname=G(L)->tmname; 175 if (!lua_checkstack(L,argc)) fatal("too many input files"); 176 for (i=0; i<argc; i++) 177 { 178 const char* filename=IS("-") ? NULL : argv[i]; 179 if (luaL_loadfile(L,filename)!=LUA_OK) fatal(lua_tostring(L,-1)); 180 } 181 f=combine(L,argc); 182 if (listing) luaU_print(f,listing>1); 183 if (dumping) 184 { 185 FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); 186 if (D==NULL) cannot("open"); 187 lua_lock(L); 188 luaU_dump(L,f,writer,D,stripping); 189 lua_unlock(L); 190 if (ferror(D)) cannot("write"); 191 if (fclose(D)) cannot("close"); 192 } 193 return 0; 194 } 195 196 int main(int argc, char* argv[]) 197 { 198 lua_State* L; 199 int i=doargs(argc,argv); 200 argc-=i; argv+=i; 201 if (argc<=0) usage("no input files given"); 202 L=luaL_newstate(); 203 if (L==NULL) fatal("cannot create state: not enough memory"); 204 lua_pushcfunction(L,&pmain); 205 lua_pushinteger(L,argc); 206 lua_pushlightuserdata(L,argv); 207 if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1)); 208 lua_close(L); 209 return EXIT_SUCCESS; 210 } 211 212 /* 213 ** print bytecodes 214 */ 215 216 #define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") 217 #define VOID(p) ((const void*)(p)) 218 #define eventname(i) (getstr(tmname[i])) 219 220 static void PrintString(const TString* ts) 221 { 222 const char* s=getstr(ts); 223 size_t i,n=tsslen(ts); 224 printf("\""); 225 for (i=0; i<n; i++) 226 { 227 int c=(int)(unsigned char)s[i]; 228 switch (c) 229 { 230 case '"': 231 printf("\\\""); 232 break; 233 case '\\': 234 printf("\\\\"); 235 break; 236 case '\a': 237 printf("\\a"); 238 break; 239 case '\b': 240 printf("\\b"); 241 break; 242 case '\f': 243 printf("\\f"); 244 break; 245 case '\n': 246 printf("\\n"); 247 break; 248 case '\r': 249 printf("\\r"); 250 break; 251 case '\t': 252 printf("\\t"); 253 break; 254 case '\v': 255 printf("\\v"); 256 break; 257 default: 258 if (isprint(c)) printf("%c",c); else printf("\\%03d",c); 259 break; 260 } 261 } 262 printf("\""); 263 } 264 265 static void PrintType(const Proto* f, int i) 266 { 267 const TValue* o=&f->k[i]; 268 switch (ttypetag(o)) 269 { 270 case LUA_VNIL: 271 printf("N"); 272 break; 273 case LUA_VFALSE: 274 case LUA_VTRUE: 275 printf("B"); 276 break; 277 case LUA_VNUMFLT: 278 printf("F"); 279 break; 280 case LUA_VNUMINT: 281 printf("I"); 282 break; 283 case LUA_VSHRSTR: 284 case LUA_VLNGSTR: 285 printf("S"); 286 break; 287 default: /* cannot happen */ 288 printf("?%d",ttypetag(o)); 289 break; 290 } 291 printf("\t"); 292 } 293 294 static void PrintConstant(const Proto* f, int i) 295 { 296 const TValue* o=&f->k[i]; 297 switch (ttypetag(o)) 298 { 299 case LUA_VNIL: 300 printf("nil"); 301 break; 302 case LUA_VFALSE: 303 printf("false"); 304 break; 305 case LUA_VTRUE: 306 printf("true"); 307 break; 308 case LUA_VNUMFLT: 309 { 310 char buff[100]; 311 sprintf(buff,LUA_NUMBER_FMT,fltvalue(o)); 312 printf("%s",buff); 313 if (buff[strspn(buff,"-0123456789")]=='\0') printf(".0"); 314 break; 315 } 316 case LUA_VNUMINT: 317 printf(LUA_INTEGER_FMT,ivalue(o)); 318 break; 319 case LUA_VSHRSTR: 320 case LUA_VLNGSTR: 321 PrintString(tsvalue(o)); 322 break; 323 default: /* cannot happen */ 324 printf("?%d",ttypetag(o)); 325 break; 326 } 327 } 328 329 #define COMMENT "\t; " 330 #define EXTRAARG GETARG_Ax(code[pc+1]) 331 #define EXTRAARGC (EXTRAARG*(MAXARG_C+1)) 332 #define ISK (isk ? "k" : "") 333 334 static void PrintCode(const Proto* f) 335 { 336 const Instruction* code=f->code; 337 int pc,n=f->sizecode; 338 for (pc=0; pc<n; pc++) 339 { 340 Instruction i=code[pc]; 341 OpCode o=GET_OPCODE(i); 342 int a=GETARG_A(i); 343 int b=GETARG_B(i); 344 int c=GETARG_C(i); 345 int ax=GETARG_Ax(i); 346 int bx=GETARG_Bx(i); 347 int sb=GETARG_sB(i); 348 int sc=GETARG_sC(i); 349 int sbx=GETARG_sBx(i); 350 int isk=GETARG_k(i); 351 int line=luaG_getfuncline(f,pc); 352 printf("\t%d\t",pc+1); 353 if (line>0) printf("[%d]\t",line); else printf("[-]\t"); 354 printf("%-9s\t",opnames[o]); 355 switch (o) 356 { 357 case OP_MOVE: 358 printf("%d %d",a,b); 359 break; 360 case OP_LOADI: 361 printf("%d %d",a,sbx); 362 break; 363 case OP_LOADF: 364 printf("%d %d",a,sbx); 365 break; 366 case OP_LOADK: 367 printf("%d %d",a,bx); 368 printf(COMMENT); PrintConstant(f,bx); 369 break; 370 case OP_LOADKX: 371 printf("%d",a); 372 printf(COMMENT); PrintConstant(f,EXTRAARG); 373 break; 374 case OP_LOADFALSE: 375 printf("%d",a); 376 break; 377 case OP_LFALSESKIP: 378 printf("%d",a); 379 break; 380 case OP_LOADTRUE: 381 printf("%d",a); 382 break; 383 case OP_LOADNIL: 384 printf("%d %d",a,b); 385 printf(COMMENT "%d out",b+1); 386 break; 387 case OP_GETUPVAL: 388 printf("%d %d",a,b); 389 printf(COMMENT "%s",UPVALNAME(b)); 390 break; 391 case OP_SETUPVAL: 392 printf("%d %d",a,b); 393 printf(COMMENT "%s",UPVALNAME(b)); 394 break; 395 case OP_GETTABUP: 396 printf("%d %d %d",a,b,c); 397 printf(COMMENT "%s",UPVALNAME(b)); 398 printf(" "); PrintConstant(f,c); 399 break; 400 case OP_GETTABLE: 401 printf("%d %d %d",a,b,c); 402 break; 403 case OP_GETI: 404 printf("%d %d %d",a,b,c); 405 break; 406 case OP_GETFIELD: 407 printf("%d %d %d",a,b,c); 408 printf(COMMENT); PrintConstant(f,c); 409 break; 410 case OP_SETTABUP: 411 printf("%d %d %d%s",a,b,c,ISK); 412 printf(COMMENT "%s",UPVALNAME(a)); 413 printf(" "); PrintConstant(f,b); 414 if (isk) { printf(" "); PrintConstant(f,c); } 415 break; 416 case OP_SETTABLE: 417 printf("%d %d %d%s",a,b,c,ISK); 418 if (isk) { printf(COMMENT); PrintConstant(f,c); } 419 break; 420 case OP_SETI: 421 printf("%d %d %d%s",a,b,c,ISK); 422 if (isk) { printf(COMMENT); PrintConstant(f,c); } 423 break; 424 case OP_SETFIELD: 425 printf("%d %d %d%s",a,b,c,ISK); 426 printf(COMMENT); PrintConstant(f,b); 427 if (isk) { printf(" "); PrintConstant(f,c); } 428 break; 429 case OP_NEWTABLE: 430 printf("%d %d %d",a,b,c); 431 printf(COMMENT "%d",c+EXTRAARGC); 432 break; 433 case OP_SELF: 434 printf("%d %d %d%s",a,b,c,ISK); 435 if (isk) { printf(COMMENT); PrintConstant(f,c); } 436 break; 437 case OP_ADDI: 438 printf("%d %d %d",a,b,sc); 439 break; 440 case OP_ADDK: 441 printf("%d %d %d",a,b,c); 442 printf(COMMENT); PrintConstant(f,c); 443 break; 444 case OP_SUBK: 445 printf("%d %d %d",a,b,c); 446 printf(COMMENT); PrintConstant(f,c); 447 break; 448 case OP_MULK: 449 printf("%d %d %d",a,b,c); 450 printf(COMMENT); PrintConstant(f,c); 451 break; 452 case OP_MODK: 453 printf("%d %d %d",a,b,c); 454 printf(COMMENT); PrintConstant(f,c); 455 break; 456 case OP_POWK: 457 printf("%d %d %d",a,b,c); 458 printf(COMMENT); PrintConstant(f,c); 459 break; 460 case OP_DIVK: 461 printf("%d %d %d",a,b,c); 462 printf(COMMENT); PrintConstant(f,c); 463 break; 464 case OP_IDIVK: 465 printf("%d %d %d",a,b,c); 466 printf(COMMENT); PrintConstant(f,c); 467 break; 468 case OP_BANDK: 469 printf("%d %d %d",a,b,c); 470 printf(COMMENT); PrintConstant(f,c); 471 break; 472 case OP_BORK: 473 printf("%d %d %d",a,b,c); 474 printf(COMMENT); PrintConstant(f,c); 475 break; 476 case OP_BXORK: 477 printf("%d %d %d",a,b,c); 478 printf(COMMENT); PrintConstant(f,c); 479 break; 480 case OP_SHRI: 481 printf("%d %d %d",a,b,sc); 482 break; 483 case OP_SHLI: 484 printf("%d %d %d",a,b,sc); 485 break; 486 case OP_ADD: 487 printf("%d %d %d",a,b,c); 488 break; 489 case OP_SUB: 490 printf("%d %d %d",a,b,c); 491 break; 492 case OP_MUL: 493 printf("%d %d %d",a,b,c); 494 break; 495 case OP_MOD: 496 printf("%d %d %d",a,b,c); 497 break; 498 case OP_POW: 499 printf("%d %d %d",a,b,c); 500 break; 501 case OP_DIV: 502 printf("%d %d %d",a,b,c); 503 break; 504 case OP_IDIV: 505 printf("%d %d %d",a,b,c); 506 break; 507 case OP_BAND: 508 printf("%d %d %d",a,b,c); 509 break; 510 case OP_BOR: 511 printf("%d %d %d",a,b,c); 512 break; 513 case OP_BXOR: 514 printf("%d %d %d",a,b,c); 515 break; 516 case OP_SHL: 517 printf("%d %d %d",a,b,c); 518 break; 519 case OP_SHR: 520 printf("%d %d %d",a,b,c); 521 break; 522 case OP_MMBIN: 523 printf("%d %d %d",a,b,c); 524 printf(COMMENT "%s",eventname(c)); 525 break; 526 case OP_MMBINI: 527 printf("%d %d %d %d",a,sb,c,isk); 528 printf(COMMENT "%s",eventname(c)); 529 if (isk) printf(" flip"); 530 break; 531 case OP_MMBINK: 532 printf("%d %d %d %d",a,b,c,isk); 533 printf(COMMENT "%s ",eventname(c)); PrintConstant(f,b); 534 if (isk) printf(" flip"); 535 break; 536 case OP_UNM: 537 printf("%d %d",a,b); 538 break; 539 case OP_BNOT: 540 printf("%d %d",a,b); 541 break; 542 case OP_NOT: 543 printf("%d %d",a,b); 544 break; 545 case OP_LEN: 546 printf("%d %d",a,b); 547 break; 548 case OP_CONCAT: 549 printf("%d %d",a,b); 550 break; 551 case OP_CLOSE: 552 printf("%d",a); 553 break; 554 case OP_TBC: 555 printf("%d",a); 556 break; 557 case OP_JMP: 558 printf("%d",GETARG_sJ(i)); 559 printf(COMMENT "to %d",GETARG_sJ(i)+pc+2); 560 break; 561 case OP_EQ: 562 printf("%d %d %d",a,b,isk); 563 break; 564 case OP_LT: 565 printf("%d %d %d",a,b,isk); 566 break; 567 case OP_LE: 568 printf("%d %d %d",a,b,isk); 569 break; 570 case OP_EQK: 571 printf("%d %d %d",a,b,isk); 572 printf(COMMENT); PrintConstant(f,b); 573 break; 574 case OP_EQI: 575 printf("%d %d %d",a,sb,isk); 576 break; 577 case OP_LTI: 578 printf("%d %d %d",a,sb,isk); 579 break; 580 case OP_LEI: 581 printf("%d %d %d",a,sb,isk); 582 break; 583 case OP_GTI: 584 printf("%d %d %d",a,sb,isk); 585 break; 586 case OP_GEI: 587 printf("%d %d %d",a,sb,isk); 588 break; 589 case OP_TEST: 590 printf("%d %d",a,isk); 591 break; 592 case OP_TESTSET: 593 printf("%d %d %d",a,b,isk); 594 break; 595 case OP_CALL: 596 printf("%d %d %d",a,b,c); 597 printf(COMMENT); 598 if (b==0) printf("all in "); else printf("%d in ",b-1); 599 if (c==0) printf("all out"); else printf("%d out",c-1); 600 break; 601 case OP_TAILCALL: 602 printf("%d %d %d%s",a,b,c,ISK); 603 printf(COMMENT "%d in",b-1); 604 break; 605 case OP_RETURN: 606 printf("%d %d %d%s",a,b,c,ISK); 607 printf(COMMENT); 608 if (b==0) printf("all out"); else printf("%d out",b-1); 609 break; 610 case OP_RETURN0: 611 break; 612 case OP_RETURN1: 613 printf("%d",a); 614 break; 615 case OP_FORLOOP: 616 printf("%d %d",a,bx); 617 printf(COMMENT "to %d",pc-bx+2); 618 break; 619 case OP_FORPREP: 620 printf("%d %d",a,bx); 621 printf(COMMENT "exit to %d",pc+bx+3); 622 break; 623 case OP_TFORPREP: 624 printf("%d %d",a,bx); 625 printf(COMMENT "to %d",pc+bx+2); 626 break; 627 case OP_TFORCALL: 628 printf("%d %d",a,c); 629 break; 630 case OP_TFORLOOP: 631 printf("%d %d",a,bx); 632 printf(COMMENT "to %d",pc-bx+2); 633 break; 634 case OP_SETLIST: 635 printf("%d %d %d",a,b,c); 636 if (isk) printf(COMMENT "%d",c+EXTRAARGC); 637 break; 638 case OP_CLOSURE: 639 printf("%d %d",a,bx); 640 printf(COMMENT "%p",VOID(f->p[bx])); 641 break; 642 case OP_VARARG: 643 printf("%d %d",a,c); 644 printf(COMMENT); 645 if (c==0) printf("all out"); else printf("%d out",c-1); 646 break; 647 case OP_VARARGPREP: 648 printf("%d",a); 649 break; 650 case OP_EXTRAARG: 651 printf("%d",ax); 652 break; 653 #if 0 654 default: 655 printf("%d %d %d",a,b,c); 656 printf(COMMENT "not handled"); 657 break; 658 #endif 659 } 660 printf("\n"); 661 } 662 } 663 664 665 #define SS(x) ((x==1)?"":"s") 666 #define S(x) (int)(x),SS(x) 667 668 static void PrintHeader(const Proto* f) 669 { 670 const char* s=f->source ? getstr(f->source) : "=?"; 671 if (*s=='@' || *s=='=') 672 s++; 673 else if (*s==LUA_SIGNATURE[0]) 674 s="(bstring)"; 675 else 676 s="(string)"; 677 printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n", 678 (f->linedefined==0)?"main":"function",s, 679 f->linedefined,f->lastlinedefined, 680 S(f->sizecode),VOID(f)); 681 printf("%d%s param%s, %d slot%s, %d upvalue%s, ", 682 (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), 683 S(f->maxstacksize),S(f->sizeupvalues)); 684 printf("%d local%s, %d constant%s, %d function%s\n", 685 S(f->sizelocvars),S(f->sizek),S(f->sizep)); 686 } 687 688 static void PrintDebug(const Proto* f) 689 { 690 int i,n; 691 n=f->sizek; 692 printf("constants (%d) for %p:\n",n,VOID(f)); 693 for (i=0; i<n; i++) 694 { 695 printf("\t%d\t",i); 696 PrintType(f,i); 697 PrintConstant(f,i); 698 printf("\n"); 699 } 700 n=f->sizelocvars; 701 printf("locals (%d) for %p:\n",n,VOID(f)); 702 for (i=0; i<n; i++) 703 { 704 printf("\t%d\t%s\t%d\t%d\n", 705 i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); 706 } 707 n=f->sizeupvalues; 708 printf("upvalues (%d) for %p:\n",n,VOID(f)); 709 for (i=0; i<n; i++) 710 { 711 printf("\t%d\t%s\t%d\t%d\n", 712 i,UPVALNAME(i),f->upvalues[i].instack,f->upvalues[i].idx); 713 } 714 } 715 716 static void PrintFunction(const Proto* f, int full) 717 { 718 int i,n=f->sizep; 719 PrintHeader(f); 720 PrintCode(f); 721 if (full) PrintDebug(f); 722 for (i=0; i<n; i++) PrintFunction(f->p[i],full); 723 } 724