3 ** Lua compiler (saves bytecodes to files; also lists bytecodes)
4 ** See Copyright Notice in lua.h
28 static void PrintFunction(const Proto
*f
, int full
);
29 #define luaU_print PrintFunction
31 #define PROGNAME "luac" /* default program name */
32 #define OUTPUT PROGNAME ".out" /* default output file */
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
;
42 static void fatal(const char *message
) {
43 fprintf(stderr
, "%s: %s\n", progname
, message
);
47 static void cannot(const char *what
) {
48 fprintf(stderr
, "%s: cannot %s %s: %s\n", progname
, what
, output
, strerror(errno
));
52 static void usage(const char *message
) {
54 fprintf(stderr
, "%s: unrecognized option '%s'\n", progname
, message
);
56 fprintf(stderr
, "%s: %s\n", progname
, message
);
58 "usage: %s [options] [filenames]\n"
59 "Available options are:\n"
60 " -l list (use -l -l for full listing)\n"
61 " -o name output to file 'name' (default is \"%s\")\n"
63 " -s strip debug information\n"
64 " -v show version information\n"
65 " -- stop handling options\n"
66 " - stop handling options and process stdin\n"
71 #define IS(s) (strcmp(argv[i],s)==0)
73 static int doargs(int argc
, char *argv
[]) {
76 if (argv
[0] != NULL
&& *argv
[0] != 0) progname
= argv
[0];
77 for (i
= 1; i
< argc
; i
++) {
78 if (*argv
[i
] != '-') /* end of options; keep it */
80 else if (IS("--")) { /* end of options; skip it */
82 if (version
) ++version
;
84 } else if (IS("-")) /* end of options; use stdin */
86 else if (IS("-l")) /* list */
88 else if (IS("-o")) { /* output file */
90 if (output
== NULL
|| *output
== 0 || (*output
== '-' && output
[1] != 0))
91 usage("'-o' needs argument");
92 if (IS("-")) output
= NULL
;
93 } else if (IS("-p")) /* parse only */
95 else if (IS("-s")) /* strip debug information */
97 else if (IS("-v")) /* show version */
99 else /* unknown option */
102 if (i
== argc
&& (listing
|| !dumping
)) {
107 printf("%s\n", LUA_COPYRIGHT
);
108 if (version
== argc
- 1) exit(EXIT_SUCCESS
);
113 #define FUNCTION "(function()end)();\n"
115 static const char *reader(lua_State
*L
, void *ud
, size_t *size
) {
117 if ((*(int *)ud
)--) {
118 *size
= sizeof(FUNCTION
) - 1;
126 #define toproto(L,i) getproto(s2v(L->top.p+(i)))
128 static const Proto
*combine(lua_State
*L
, int n
) {
130 return toproto(L
, -1);
134 if (lua_load(L
, reader
, &i
, "=(" PROGNAME
")", NULL
) != LUA_OK
) fatal(lua_tostring(L
, -1));
136 for (i
= 0; i
< n
; i
++) {
137 f
->p
[i
] = toproto(L
, i
- n
- 1);
138 if (f
->p
[i
]->sizeupvalues
> 0) f
->p
[i
]->upvalues
[0].instack
= 0;
144 static int writer(lua_State
*L
, const void *p
, size_t size
, void *u
) {
146 return (fwrite(p
, size
, 1, (FILE *)u
) != 1) && (size
!= 0);
149 static int pmain(lua_State
*L
) {
150 int argc
= (int)lua_tointeger(L
, 1);
151 char **argv
= (char **)lua_touserdata(L
, 2);
154 tmname
= G(L
)->tmname
;
155 if (!lua_checkstack(L
, argc
)) fatal("too many input files");
156 for (i
= 0; i
< argc
; i
++) {
157 const char *filename
= IS("-") ? NULL
: argv
[i
];
158 if (luaL_loadfile(L
, filename
) != LUA_OK
) fatal(lua_tostring(L
, -1));
160 f
= combine(L
, argc
);
161 if (listing
) luaU_print(f
, listing
> 1);
163 FILE *D
= (output
== NULL
) ? stdout
: fopen(output
, "wb");
164 if (D
== NULL
) cannot("open");
166 luaU_dump(L
, f
, writer
, D
, stripping
);
168 if (ferror(D
)) cannot("write");
169 if (fclose(D
)) cannot("close");
174 int main(int argc
, char *argv
[]) {
176 int i
= doargs(argc
, argv
);
179 if (argc
<= 0) usage("no input files given");
181 if (L
== NULL
) fatal("cannot create state: not enough memory");
182 lua_pushcfunction(L
, &pmain
);
183 lua_pushinteger(L
, argc
);
184 lua_pushlightuserdata(L
, argv
);
185 if (lua_pcall(L
, 2, 0, 0) != LUA_OK
) fatal(lua_tostring(L
, -1));
194 #define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-")
195 #define VOID(p) ((const void*)(p))
196 #define eventname(i) (getstr(tmname[i]))
198 static void PrintString(const TString
*ts
) {
199 const char *s
= getstr(ts
);
200 size_t i
, n
= tsslen(ts
);
202 for (i
= 0; i
< n
; i
++) {
203 int c
= (int)(unsigned char)s
[i
];
233 if (isprint(c
)) printf("%c", c
);
234 else printf("\\%03d", c
);
241 static void PrintType(const Proto
*f
, int i
) {
242 const TValue
*o
= &f
->k
[i
];
243 switch (ttypetag(o
)) {
261 default: /* cannot happen */
262 printf("?%d", ttypetag(o
));
268 static void PrintConstant(const Proto
*f
, int i
) {
269 const TValue
*o
= &f
->k
[i
];
270 switch (ttypetag(o
)) {
282 sprintf(buff
, LUA_NUMBER_FMT
, fltvalue(o
));
284 if (buff
[strspn(buff
, "-0123456789")] == '\0') printf(".0");
288 printf(LUA_INTEGER_FMT
, ivalue(o
));
292 PrintString(tsvalue(o
));
294 default: /* cannot happen */
295 printf("?%d", ttypetag(o
));
300 #define COMMENT "\t; "
301 #define EXTRAARG GETARG_Ax(code[pc+1])
302 #define EXTRAARGC (EXTRAARG*(MAXARG_C+1))
303 #define ISK (isk ? "k" : "")
305 static void PrintCode(const Proto
*f
) {
306 const Instruction
*code
= f
->code
;
307 int pc
, n
= f
->sizecode
;
308 for (pc
= 0; pc
< n
; pc
++) {
309 Instruction i
= code
[pc
];
310 OpCode o
= GET_OPCODE(i
);
314 int ax
= GETARG_Ax(i
);
315 int bx
= GETARG_Bx(i
);
316 int sb
= GETARG_sB(i
);
317 int sc
= GETARG_sC(i
);
318 int sbx
= GETARG_sBx(i
);
319 int isk
= GETARG_k(i
);
320 int line
= luaG_getfuncline(f
, pc
);
321 printf("\t%d\t", pc
+ 1);
322 if (line
> 0) printf("[%d]\t", line
);
323 else printf("[-]\t");
324 printf("%-9s\t", opnames
[o
]);
327 printf("%d %d", a
, b
);
330 printf("%d %d", a
, sbx
);
333 printf("%d %d", a
, sbx
);
336 printf("%d %d", a
, bx
);
338 PrintConstant(f
, bx
);
343 PrintConstant(f
, EXTRAARG
);
355 printf("%d %d", a
, b
);
356 printf(COMMENT
"%d out", b
+ 1);
359 printf("%d %d", a
, b
);
360 printf(COMMENT
"%s", UPVALNAME(b
));
363 printf("%d %d", a
, b
);
364 printf(COMMENT
"%s", UPVALNAME(b
));
367 printf("%d %d %d", a
, b
, c
);
368 printf(COMMENT
"%s", UPVALNAME(b
));
373 printf("%d %d %d", a
, b
, c
);
376 printf("%d %d %d", a
, b
, c
);
379 printf("%d %d %d", a
, b
, c
);
384 printf("%d %d %d%s", a
, b
, c
, ISK
);
385 printf(COMMENT
"%s", UPVALNAME(a
));
388 if (isk
) { printf(" "); PrintConstant(f
, c
); }
391 printf("%d %d %d%s", a
, b
, c
, ISK
);
392 if (isk
) { printf(COMMENT
); PrintConstant(f
, c
); }
395 printf("%d %d %d%s", a
, b
, c
, ISK
);
396 if (isk
) { printf(COMMENT
); PrintConstant(f
, c
); }
399 printf("%d %d %d%s", a
, b
, c
, ISK
);
402 if (isk
) { printf(" "); PrintConstant(f
, c
); }
405 printf("%d %d %d", a
, b
, c
);
406 printf(COMMENT
"%d", c
+ EXTRAARGC
);
409 printf("%d %d %d%s", a
, b
, c
, ISK
);
410 if (isk
) { printf(COMMENT
); PrintConstant(f
, c
); }
413 printf("%d %d %d", a
, b
, sc
);
416 printf("%d %d %d", a
, b
, c
);
421 printf("%d %d %d", a
, b
, c
);
426 printf("%d %d %d", a
, b
, c
);
431 printf("%d %d %d", a
, b
, c
);
436 printf("%d %d %d", a
, b
, c
);
441 printf("%d %d %d", a
, b
, c
);
446 printf("%d %d %d", a
, b
, c
);
451 printf("%d %d %d", a
, b
, c
);
456 printf("%d %d %d", a
, b
, c
);
461 printf("%d %d %d", a
, b
, c
);
466 printf("%d %d %d", a
, b
, sc
);
469 printf("%d %d %d", a
, b
, sc
);
472 printf("%d %d %d", a
, b
, c
);
475 printf("%d %d %d", a
, b
, c
);
478 printf("%d %d %d", a
, b
, c
);
481 printf("%d %d %d", a
, b
, c
);
484 printf("%d %d %d", a
, b
, c
);
487 printf("%d %d %d", a
, b
, c
);
490 printf("%d %d %d", a
, b
, c
);
493 printf("%d %d %d", a
, b
, c
);
496 printf("%d %d %d", a
, b
, c
);
499 printf("%d %d %d", a
, b
, c
);
502 printf("%d %d %d", a
, b
, c
);
505 printf("%d %d %d", a
, b
, c
);
508 printf("%d %d %d", a
, b
, c
);
509 printf(COMMENT
"%s", eventname(c
));
512 printf("%d %d %d %d", a
, sb
, c
, isk
);
513 printf(COMMENT
"%s", eventname(c
));
514 if (isk
) printf(" flip");
517 printf("%d %d %d %d", a
, b
, c
, isk
);
518 printf(COMMENT
"%s ", eventname(c
));
520 if (isk
) printf(" flip");
523 printf("%d %d", a
, b
);
526 printf("%d %d", a
, b
);
529 printf("%d %d", a
, b
);
532 printf("%d %d", a
, b
);
535 printf("%d %d", a
, b
);
544 printf("%d", GETARG_sJ(i
));
545 printf(COMMENT
"to %d", GETARG_sJ(i
) + pc
+ 2);
548 printf("%d %d %d", a
, b
, isk
);
551 printf("%d %d %d", a
, b
, isk
);
554 printf("%d %d %d", a
, b
, isk
);
557 printf("%d %d %d", a
, b
, isk
);
562 printf("%d %d %d", a
, sb
, isk
);
565 printf("%d %d %d", a
, sb
, isk
);
568 printf("%d %d %d", a
, sb
, isk
);
571 printf("%d %d %d", a
, sb
, isk
);
574 printf("%d %d %d", a
, sb
, isk
);
577 printf("%d %d", a
, isk
);
580 printf("%d %d %d", a
, b
, isk
);
583 printf("%d %d %d", a
, b
, c
);
585 if (b
== 0) printf("all in ");
586 else printf("%d in ", b
- 1);
587 if (c
== 0) printf("all out");
588 else printf("%d out", c
- 1);
591 printf("%d %d %d%s", a
, b
, c
, ISK
);
592 printf(COMMENT
"%d in", b
- 1);
595 printf("%d %d %d%s", a
, b
, c
, ISK
);
597 if (b
== 0) printf("all out");
598 else printf("%d out", b
- 1);
606 printf("%d %d", a
, bx
);
607 printf(COMMENT
"to %d", pc
- bx
+ 2);
610 printf("%d %d", a
, bx
);
611 printf(COMMENT
"exit to %d", pc
+ bx
+ 3);
614 printf("%d %d", a
, bx
);
615 printf(COMMENT
"to %d", pc
+ bx
+ 2);
618 printf("%d %d", a
, c
);
621 printf("%d %d", a
, bx
);
622 printf(COMMENT
"to %d", pc
- bx
+ 2);
625 printf("%d %d %d", a
, b
, c
);
626 if (isk
) printf(COMMENT
"%d", c
+ EXTRAARGC
);
629 printf("%d %d", a
, bx
);
630 printf(COMMENT
"%p", VOID(f
->p
[bx
]));
633 printf("%d %d", a
, c
);
635 if (c
== 0) printf("all out");
636 else printf("%d out", c
- 1);
646 printf("%d %d %d", a
, b
, c
);
647 printf(COMMENT
"not handled");
656 #define SS(x) ((x==1)?"":"s")
657 #define S(x) (int)(x),SS(x)
659 static void PrintHeader(const Proto
*f
) {
660 const char *s
= f
->source
? getstr(f
->source
) : "=?";
661 if (*s
== '@' || *s
== '=')
663 else if (*s
== LUA_SIGNATURE
[0])
667 printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n",
668 (f
->linedefined
== 0) ? "main" : "function", s
,
669 f
->linedefined
, f
->lastlinedefined
,
670 S(f
->sizecode
), VOID(f
));
671 printf("%d%s param%s, %d slot%s, %d upvalue%s, ",
672 (int)(f
->numparams
), f
->is_vararg
? "+" : "", SS(f
->numparams
),
673 S(f
->maxstacksize
), S(f
->sizeupvalues
));
674 printf("%d local%s, %d constant%s, %d function%s\n",
675 S(f
->sizelocvars
), S(f
->sizek
), S(f
->sizep
));
678 static void PrintDebug(const Proto
*f
) {
681 printf("constants (%d) for %p:\n", n
, VOID(f
));
682 for (i
= 0; i
< n
; i
++) {
689 printf("locals (%d) for %p:\n", n
, VOID(f
));
690 for (i
= 0; i
< n
; i
++) {
691 printf("\t%d\t%s\t%d\t%d\n",
692 i
, getstr(f
->locvars
[i
].varname
), f
->locvars
[i
].startpc
+ 1, f
->locvars
[i
].endpc
+ 1);
695 printf("upvalues (%d) for %p:\n", n
, VOID(f
));
696 for (i
= 0; i
< n
; i
++) {
697 printf("\t%d\t%s\t%d\t%d\n",
698 i
, UPVALNAME(i
), f
->upvalues
[i
].instack
, f
->upvalues
[i
].idx
);
702 static void PrintFunction(const Proto
*f
, int full
) {
706 if (full
) PrintDebug(f
);
707 for (i
= 0; i
< n
; i
++) PrintFunction(f
->p
[i
], full
);