Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

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