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