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