Merge pull request #2593 from Akury83/master
[RRG-proxmark3.git] / client / deps / liblua / luac.c
blob35af873d3132ac2381fae67b517b192cb61495ac
1 /*
2 ** $Id: luac.c $
3 ** Lua compiler (saves bytecodes to files; also lists bytecodes)
4 ** See Copyright Notice in lua.h
5 */
7 #define luac_c
8 #define LUA_CORE
10 #include "lprefix.h"
12 #include <ctype.h>
13 #include <errno.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
18 #include "lua.h"
19 #include "lauxlib.h"
21 #include "ldebug.h"
22 #include "lobject.h"
23 #include "lopcodes.h"
24 #include "lopnames.h"
25 #include "lstate.h"
26 #include "lundump.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);
44 exit(EXIT_FAILURE);
47 static void cannot(const char *what) {
48 fprintf(stderr, "%s: cannot %s %s: %s\n", progname, what, output, strerror(errno));
49 exit(EXIT_FAILURE);
52 static void usage(const char *message) {
53 if (*message == '-')
54 fprintf(stderr, "%s: unrecognized option '%s'\n", progname, message);
55 else
56 fprintf(stderr, "%s: %s\n", progname, message);
57 fprintf(stderr,
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"
62 " -p parse only\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"
67 , progname, Output);
68 exit(EXIT_FAILURE);
71 #define IS(s) (strcmp(argv[i],s)==0)
73 static int doargs(int argc, char *argv[]) {
74 int i;
75 int version = 0;
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 */
79 break;
80 else if (IS("--")) { /* end of options; skip it */
81 ++i;
82 if (version) ++version;
83 break;
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 output = argv[++i];
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 */
94 dumping = 0;
95 else if (IS("-s")) /* strip debug information */
96 stripping = 1;
97 else if (IS("-v")) /* show version */
98 ++version;
99 else /* unknown option */
100 usage(argv[i]);
102 if (i == argc && (listing || !dumping)) {
103 dumping = 0;
104 argv[--i] = Output;
106 if (version) {
107 printf("%s\n", LUA_COPYRIGHT);
108 if (version == argc - 1) exit(EXIT_SUCCESS);
110 return i;
113 #define FUNCTION "(function()end)();\n"
115 static const char *reader(lua_State *L, void *ud, size_t *size) {
116 UNUSED(L);
117 if ((*(int *)ud)--) {
118 *size = sizeof(FUNCTION) - 1;
119 return FUNCTION;
120 } else {
121 *size = 0;
122 return NULL;
126 #define toproto(L,i) getproto(s2v(L->top.p+(i)))
128 static const Proto *combine(lua_State *L, int n) {
129 if (n == 1)
130 return toproto(L, -1);
131 else {
132 Proto *f;
133 int i = n;
134 if (lua_load(L, reader, &i, "=(" PROGNAME ")", NULL) != LUA_OK) fatal(lua_tostring(L, -1));
135 f = toproto(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;
140 return f;
144 static int writer(lua_State *L, const void *p, size_t size, void *u) {
145 UNUSED(L);
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);
152 const Proto *f;
153 int i;
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);
162 if (dumping) {
163 FILE *D = (output == NULL) ? stdout : fopen(output, "wb");
164 if (D == NULL) cannot("open");
165 lua_lock(L);
166 luaU_dump(L, f, writer, D, stripping);
167 lua_unlock(L);
168 if (ferror(D)) cannot("write");
169 if (fclose(D)) cannot("close");
171 return 0;
174 int main(int argc, char *argv[]) {
175 lua_State *L;
176 int i = doargs(argc, argv);
177 argc -= i;
178 argv += i;
179 if (argc <= 0) usage("no input files given");
180 L = luaL_newstate();
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));
186 lua_close(L);
187 return EXIT_SUCCESS;
191 ** print bytecodes
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);
201 printf("\"");
202 for (i = 0; i < n; i++) {
203 int c = (int)(unsigned char)s[i];
204 switch (c) {
205 case '"':
206 printf("\\\"");
207 break;
208 case '\\':
209 printf("\\\\");
210 break;
211 case '\a':
212 printf("\\a");
213 break;
214 case '\b':
215 printf("\\b");
216 break;
217 case '\f':
218 printf("\\f");
219 break;
220 case '\n':
221 printf("\\n");
222 break;
223 case '\r':
224 printf("\\r");
225 break;
226 case '\t':
227 printf("\\t");
228 break;
229 case '\v':
230 printf("\\v");
231 break;
232 default:
233 if (isprint(c)) printf("%c", c);
234 else printf("\\%03d", c);
235 break;
238 printf("\"");
241 static void PrintType(const Proto *f, int i) {
242 const TValue *o = &f->k[i];
243 switch (ttypetag(o)) {
244 case LUA_VNIL:
245 printf("N");
246 break;
247 case LUA_VFALSE:
248 case LUA_VTRUE:
249 printf("B");
250 break;
251 case LUA_VNUMFLT:
252 printf("F");
253 break;
254 case LUA_VNUMINT:
255 printf("I");
256 break;
257 case LUA_VSHRSTR:
258 case LUA_VLNGSTR:
259 printf("S");
260 break;
261 default: /* cannot happen */
262 printf("?%d", ttypetag(o));
263 break;
265 printf("\t");
268 static void PrintConstant(const Proto *f, int i) {
269 const TValue *o = &f->k[i];
270 switch (ttypetag(o)) {
271 case LUA_VNIL:
272 printf("nil");
273 break;
274 case LUA_VFALSE:
275 printf("false");
276 break;
277 case LUA_VTRUE:
278 printf("true");
279 break;
280 case LUA_VNUMFLT: {
281 char buff[100];
282 sprintf(buff, LUA_NUMBER_FMT, fltvalue(o));
283 printf("%s", buff);
284 if (buff[strspn(buff, "-0123456789")] == '\0') printf(".0");
285 break;
287 case LUA_VNUMINT:
288 printf(LUA_INTEGER_FMT, ivalue(o));
289 break;
290 case LUA_VSHRSTR:
291 case LUA_VLNGSTR:
292 PrintString(tsvalue(o));
293 break;
294 default: /* cannot happen */
295 printf("?%d", ttypetag(o));
296 break;
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);
311 int a = GETARG_A(i);
312 int b = GETARG_B(i);
313 int c = GETARG_C(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]);
325 switch (o) {
326 case OP_MOVE:
327 printf("%d %d", a, b);
328 break;
329 case OP_LOADI:
330 printf("%d %d", a, sbx);
331 break;
332 case OP_LOADF:
333 printf("%d %d", a, sbx);
334 break;
335 case OP_LOADK:
336 printf("%d %d", a, bx);
337 printf(COMMENT);
338 PrintConstant(f, bx);
339 break;
340 case OP_LOADKX:
341 printf("%d", a);
342 printf(COMMENT);
343 PrintConstant(f, EXTRAARG);
344 break;
345 case OP_LOADFALSE:
346 printf("%d", a);
347 break;
348 case OP_LFALSESKIP:
349 printf("%d", a);
350 break;
351 case OP_LOADTRUE:
352 printf("%d", a);
353 break;
354 case OP_LOADNIL:
355 printf("%d %d", a, b);
356 printf(COMMENT "%d out", b + 1);
357 break;
358 case OP_GETUPVAL:
359 printf("%d %d", a, b);
360 printf(COMMENT "%s", UPVALNAME(b));
361 break;
362 case OP_SETUPVAL:
363 printf("%d %d", a, b);
364 printf(COMMENT "%s", UPVALNAME(b));
365 break;
366 case OP_GETTABUP:
367 printf("%d %d %d", a, b, c);
368 printf(COMMENT "%s", UPVALNAME(b));
369 printf(" ");
370 PrintConstant(f, c);
371 break;
372 case OP_GETTABLE:
373 printf("%d %d %d", a, b, c);
374 break;
375 case OP_GETI:
376 printf("%d %d %d", a, b, c);
377 break;
378 case OP_GETFIELD:
379 printf("%d %d %d", a, b, c);
380 printf(COMMENT);
381 PrintConstant(f, c);
382 break;
383 case OP_SETTABUP:
384 printf("%d %d %d%s", a, b, c, ISK);
385 printf(COMMENT "%s", UPVALNAME(a));
386 printf(" ");
387 PrintConstant(f, b);
388 if (isk) { printf(" "); PrintConstant(f, c); }
389 break;
390 case OP_SETTABLE:
391 printf("%d %d %d%s", a, b, c, ISK);
392 if (isk) { printf(COMMENT); PrintConstant(f, c); }
393 break;
394 case OP_SETI:
395 printf("%d %d %d%s", a, b, c, ISK);
396 if (isk) { printf(COMMENT); PrintConstant(f, c); }
397 break;
398 case OP_SETFIELD:
399 printf("%d %d %d%s", a, b, c, ISK);
400 printf(COMMENT);
401 PrintConstant(f, b);
402 if (isk) { printf(" "); PrintConstant(f, c); }
403 break;
404 case OP_NEWTABLE:
405 printf("%d %d %d", a, b, c);
406 printf(COMMENT "%d", c + EXTRAARGC);
407 break;
408 case OP_SELF:
409 printf("%d %d %d%s", a, b, c, ISK);
410 if (isk) { printf(COMMENT); PrintConstant(f, c); }
411 break;
412 case OP_ADDI:
413 printf("%d %d %d", a, b, sc);
414 break;
415 case OP_ADDK:
416 printf("%d %d %d", a, b, c);
417 printf(COMMENT);
418 PrintConstant(f, c);
419 break;
420 case OP_SUBK:
421 printf("%d %d %d", a, b, c);
422 printf(COMMENT);
423 PrintConstant(f, c);
424 break;
425 case OP_MULK:
426 printf("%d %d %d", a, b, c);
427 printf(COMMENT);
428 PrintConstant(f, c);
429 break;
430 case OP_MODK:
431 printf("%d %d %d", a, b, c);
432 printf(COMMENT);
433 PrintConstant(f, c);
434 break;
435 case OP_POWK:
436 printf("%d %d %d", a, b, c);
437 printf(COMMENT);
438 PrintConstant(f, c);
439 break;
440 case OP_DIVK:
441 printf("%d %d %d", a, b, c);
442 printf(COMMENT);
443 PrintConstant(f, c);
444 break;
445 case OP_IDIVK:
446 printf("%d %d %d", a, b, c);
447 printf(COMMENT);
448 PrintConstant(f, c);
449 break;
450 case OP_BANDK:
451 printf("%d %d %d", a, b, c);
452 printf(COMMENT);
453 PrintConstant(f, c);
454 break;
455 case OP_BORK:
456 printf("%d %d %d", a, b, c);
457 printf(COMMENT);
458 PrintConstant(f, c);
459 break;
460 case OP_BXORK:
461 printf("%d %d %d", a, b, c);
462 printf(COMMENT);
463 PrintConstant(f, c);
464 break;
465 case OP_SHRI:
466 printf("%d %d %d", a, b, sc);
467 break;
468 case OP_SHLI:
469 printf("%d %d %d", a, b, sc);
470 break;
471 case OP_ADD:
472 printf("%d %d %d", a, b, c);
473 break;
474 case OP_SUB:
475 printf("%d %d %d", a, b, c);
476 break;
477 case OP_MUL:
478 printf("%d %d %d", a, b, c);
479 break;
480 case OP_MOD:
481 printf("%d %d %d", a, b, c);
482 break;
483 case OP_POW:
484 printf("%d %d %d", a, b, c);
485 break;
486 case OP_DIV:
487 printf("%d %d %d", a, b, c);
488 break;
489 case OP_IDIV:
490 printf("%d %d %d", a, b, c);
491 break;
492 case OP_BAND:
493 printf("%d %d %d", a, b, c);
494 break;
495 case OP_BOR:
496 printf("%d %d %d", a, b, c);
497 break;
498 case OP_BXOR:
499 printf("%d %d %d", a, b, c);
500 break;
501 case OP_SHL:
502 printf("%d %d %d", a, b, c);
503 break;
504 case OP_SHR:
505 printf("%d %d %d", a, b, c);
506 break;
507 case OP_MMBIN:
508 printf("%d %d %d", a, b, c);
509 printf(COMMENT "%s", eventname(c));
510 break;
511 case OP_MMBINI:
512 printf("%d %d %d %d", a, sb, c, isk);
513 printf(COMMENT "%s", eventname(c));
514 if (isk) printf(" flip");
515 break;
516 case OP_MMBINK:
517 printf("%d %d %d %d", a, b, c, isk);
518 printf(COMMENT "%s ", eventname(c));
519 PrintConstant(f, b);
520 if (isk) printf(" flip");
521 break;
522 case OP_UNM:
523 printf("%d %d", a, b);
524 break;
525 case OP_BNOT:
526 printf("%d %d", a, b);
527 break;
528 case OP_NOT:
529 printf("%d %d", a, b);
530 break;
531 case OP_LEN:
532 printf("%d %d", a, b);
533 break;
534 case OP_CONCAT:
535 printf("%d %d", a, b);
536 break;
537 case OP_CLOSE:
538 printf("%d", a);
539 break;
540 case OP_TBC:
541 printf("%d", a);
542 break;
543 case OP_JMP:
544 printf("%d", GETARG_sJ(i));
545 printf(COMMENT "to %d", GETARG_sJ(i) + pc + 2);
546 break;
547 case OP_EQ:
548 printf("%d %d %d", a, b, isk);
549 break;
550 case OP_LT:
551 printf("%d %d %d", a, b, isk);
552 break;
553 case OP_LE:
554 printf("%d %d %d", a, b, isk);
555 break;
556 case OP_EQK:
557 printf("%d %d %d", a, b, isk);
558 printf(COMMENT);
559 PrintConstant(f, b);
560 break;
561 case OP_EQI:
562 printf("%d %d %d", a, sb, isk);
563 break;
564 case OP_LTI:
565 printf("%d %d %d", a, sb, isk);
566 break;
567 case OP_LEI:
568 printf("%d %d %d", a, sb, isk);
569 break;
570 case OP_GTI:
571 printf("%d %d %d", a, sb, isk);
572 break;
573 case OP_GEI:
574 printf("%d %d %d", a, sb, isk);
575 break;
576 case OP_TEST:
577 printf("%d %d", a, isk);
578 break;
579 case OP_TESTSET:
580 printf("%d %d %d", a, b, isk);
581 break;
582 case OP_CALL:
583 printf("%d %d %d", a, b, c);
584 printf(COMMENT);
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);
589 break;
590 case OP_TAILCALL:
591 printf("%d %d %d%s", a, b, c, ISK);
592 printf(COMMENT "%d in", b - 1);
593 break;
594 case OP_RETURN:
595 printf("%d %d %d%s", a, b, c, ISK);
596 printf(COMMENT);
597 if (b == 0) printf("all out");
598 else printf("%d out", b - 1);
599 break;
600 case OP_RETURN0:
601 break;
602 case OP_RETURN1:
603 printf("%d", a);
604 break;
605 case OP_FORLOOP:
606 printf("%d %d", a, bx);
607 printf(COMMENT "to %d", pc - bx + 2);
608 break;
609 case OP_FORPREP:
610 printf("%d %d", a, bx);
611 printf(COMMENT "exit to %d", pc + bx + 3);
612 break;
613 case OP_TFORPREP:
614 printf("%d %d", a, bx);
615 printf(COMMENT "to %d", pc + bx + 2);
616 break;
617 case OP_TFORCALL:
618 printf("%d %d", a, c);
619 break;
620 case OP_TFORLOOP:
621 printf("%d %d", a, bx);
622 printf(COMMENT "to %d", pc - bx + 2);
623 break;
624 case OP_SETLIST:
625 printf("%d %d %d", a, b, c);
626 if (isk) printf(COMMENT "%d", c + EXTRAARGC);
627 break;
628 case OP_CLOSURE:
629 printf("%d %d", a, bx);
630 printf(COMMENT "%p", VOID(f->p[bx]));
631 break;
632 case OP_VARARG:
633 printf("%d %d", a, c);
634 printf(COMMENT);
635 if (c == 0) printf("all out");
636 else printf("%d out", c - 1);
637 break;
638 case OP_VARARGPREP:
639 printf("%d", a);
640 break;
641 case OP_EXTRAARG:
642 printf("%d", ax);
643 break;
644 #if 0
645 default:
646 printf("%d %d %d", a, b, c);
647 printf(COMMENT "not handled");
648 break;
649 #endif
651 printf("\n");
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 == '=')
662 s++;
663 else if (*s == LUA_SIGNATURE[0])
664 s = "(bstring)";
665 else
666 s = "(string)";
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) {
679 int i, n;
680 n = f->sizek;
681 printf("constants (%d) for %p:\n", n, VOID(f));
682 for (i = 0; i < n; i++) {
683 printf("\t%d\t", i);
684 PrintType(f, i);
685 PrintConstant(f, i);
686 printf("\n");
688 n = f->sizelocvars;
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);
694 n = f->sizeupvalues;
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) {
703 int i, n = f->sizep;
704 PrintHeader(f);
705 PrintCode(f);
706 if (full) PrintDebug(f);
707 for (i = 0; i < n; i++) PrintFunction(f->p[i], full);