luac.c 15 KB

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