luac.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /*
  2. ** $Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp $
  3. ** Lua compiler (saves bytecodes to files; also list bytecodes)
  4. ** See Copyright Notice in lua.h
  5. */
  6. #define LUAC_CROSS_FILE
  7. #include "luac_cross.h"
  8. #include C_HEADER_ERRNO
  9. #include C_HEADER_STDIO
  10. #include C_HEADER_STDLIB
  11. #include C_HEADER_STRING
  12. #define luac_c
  13. #define LUA_CORE
  14. #include "lua.h"
  15. #include "lauxlib.h"
  16. #include "ldo.h"
  17. #include "lfunc.h"
  18. #include "lmem.h"
  19. #include "lobject.h"
  20. #include "lopcodes.h"
  21. #include "lstring.h"
  22. #include "lundump.h"
  23. #define PROGNAME "luac" /* default program name */
  24. #define OUTPUT PROGNAME ".out" /* default output file */
  25. static int listing=0; /* list bytecodes? */
  26. static int dumping=1; /* dump bytecodes? */
  27. static int stripping=0; /* strip debug information? */
  28. static char Output[]={ OUTPUT }; /* default output file name */
  29. static const char* output=Output; /* actual output file name */
  30. static const char* progname=PROGNAME; /* actual program name */
  31. static DumpTargetInfo target;
  32. static void fatal(const char* message)
  33. {
  34. fprintf(stderr,"%s: %s\n",progname,message);
  35. exit(EXIT_FAILURE);
  36. }
  37. static void cannot(const char* what)
  38. {
  39. fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno));
  40. exit(EXIT_FAILURE);
  41. }
  42. static void usage(const char* message)
  43. {
  44. if (*message=='-')
  45. fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message);
  46. else
  47. fprintf(stderr,"%s: %s\n",progname,message);
  48. fprintf(stderr,
  49. "usage: %s [options] [filenames].\n"
  50. "Available options are:\n"
  51. " - process stdin\n"
  52. " -l list\n"
  53. " -o name output to file " LUA_QL("name") " (default is \"%s\")\n"
  54. " -p parse only\n"
  55. " -s strip debug information\n"
  56. " -v show version information\n"
  57. " -cci bits cross-compile with given integer size\n"
  58. " -ccn type bits cross-compile with given lua_Number type and size\n"
  59. " -cce endian cross-compile with given endianness ('big' or 'little')\n"
  60. " -- stop handling options\n",
  61. progname,Output);
  62. exit(EXIT_FAILURE);
  63. }
  64. #define IS(s) (strcmp(argv[i],s)==0)
  65. static int doargs(int argc, char* argv[])
  66. {
  67. int i;
  68. int version=0;
  69. if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0];
  70. for (i=1; i<argc; i++)
  71. {
  72. if (*argv[i]!='-') /* end of options; keep it */
  73. break;
  74. else if (IS("--")) /* end of options; skip it */
  75. {
  76. ++i;
  77. if (version) ++version;
  78. break;
  79. }
  80. else if (IS("-")) /* end of options; use stdin */
  81. break;
  82. else if (IS("-l")) /* list */
  83. ++listing;
  84. else if (IS("-o")) /* output file */
  85. {
  86. output=argv[++i];
  87. if (output==NULL || *output==0) usage(LUA_QL("-o") " needs argument");
  88. if (IS("-")) output=NULL;
  89. }
  90. else if (IS("-p")) /* parse only */
  91. dumping=0;
  92. else if (IS("-s")) /* strip debug information */
  93. stripping=1;
  94. else if (IS("-v")) /* show version */
  95. ++version;
  96. else if (IS("-cci")) /* target integer size */
  97. {
  98. int s = target.sizeof_int = atoi(argv[++i])/8;
  99. if (!(s==1 || s==2 || s==4)) fatal(LUA_QL("-cci") " must be 8, 16 or 32");
  100. }
  101. else if (IS("-ccn")) /* target lua_Number type and size */
  102. {
  103. const char *type=argv[++i];
  104. if (strcmp(type,"int")==0) target.lua_Number_integral=1;
  105. else if (strcmp(type,"float")==0) target.lua_Number_integral=0;
  106. else if (strcmp(type,"float_arm")==0)
  107. {
  108. target.lua_Number_integral=0;
  109. target.is_arm_fpa=1;
  110. }
  111. else fatal(LUA_QL("-ccn") " type must be " LUA_QL("int") " or " LUA_QL("float") " or " LUA_QL("float_arm"));
  112. int s = target.sizeof_lua_Number = atoi(argv[++i])/8;
  113. if (target.lua_Number_integral && !(s==1 || s==2 || s==4)) fatal(LUA_QL("-ccn") " size must be 8, 16, or 32 for int");
  114. if (!target.lua_Number_integral && !(s==4 || s==8)) fatal(LUA_QL("-ccn") " size must be 32 or 64 for float");
  115. }
  116. else if (IS("-cce")) /* target endianness */
  117. {
  118. const char *val=argv[++i];
  119. if (strcmp(val,"big")==0) target.little_endian=0;
  120. else if (strcmp(val,"little")==0) target.little_endian=1;
  121. else fatal(LUA_QL("-cce") " must be " LUA_QL("big") " or " LUA_QL("little"));
  122. }
  123. else /* unknown option */
  124. usage(argv[i]);
  125. }
  126. if (i==argc && (listing || !dumping))
  127. {
  128. dumping=0;
  129. argv[--i]=Output;
  130. }
  131. if (version)
  132. {
  133. printf("%s %s\n",LUA_RELEASE,LUA_COPYRIGHT);
  134. if (version==argc-1) exit(EXIT_SUCCESS);
  135. }
  136. return i;
  137. }
  138. #define toproto(L,i) (clvalue(L->top+(i))->l.p)
  139. static const Proto* combine(lua_State* L, int n)
  140. {
  141. if (n==1)
  142. return toproto(L,-1);
  143. else
  144. {
  145. int i,pc;
  146. Proto* f=luaF_newproto(L);
  147. setptvalue2s(L,L->top,f); incr_top(L);
  148. f->source=luaS_newliteral(L,"=(" PROGNAME ")");
  149. f->maxstacksize=1;
  150. pc=2*n+1;
  151. f->code=luaM_newvector(L,pc,Instruction);
  152. f->sizecode=pc;
  153. f->p=luaM_newvector(L,n,Proto*);
  154. f->sizep=n;
  155. pc=0;
  156. for (i=0; i<n; i++)
  157. {
  158. f->p[i]=toproto(L,i-n-1);
  159. f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i);
  160. f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1);
  161. }
  162. f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0);
  163. return f;
  164. }
  165. }
  166. static int writer(lua_State* L, const void* p, size_t size, void* u)
  167. {
  168. UNUSED(L);
  169. return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);
  170. }
  171. struct Smain {
  172. int argc;
  173. char** argv;
  174. };
  175. static int pmain(lua_State* L)
  176. {
  177. struct Smain* s = (struct Smain*)lua_touserdata(L, 1);
  178. int argc=s->argc;
  179. char** argv=s->argv;
  180. const Proto* f;
  181. int i;
  182. if (!lua_checkstack(L,argc)) fatal("too many input files");
  183. for (i=0; i<argc; i++)
  184. {
  185. const char* filename=IS("-") ? NULL : argv[i];
  186. if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1));
  187. }
  188. f=combine(L,argc);
  189. if (listing) luaU_print(f,listing>1);
  190. if (dumping)
  191. {
  192. FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
  193. if (D==NULL) cannot("open");
  194. lua_lock(L);
  195. int result=luaU_dump_crosscompile(L,f,writer,D,stripping,target);
  196. lua_unlock(L);
  197. if (result==LUA_ERR_CC_INTOVERFLOW) fatal("value too big or small for target integer type");
  198. if (result==LUA_ERR_CC_NOTINTEGER) fatal("target lua_Number is integral but fractional value found");
  199. if (ferror(D)) cannot("write");
  200. if (fclose(D)) cannot("close");
  201. }
  202. return 0;
  203. }
  204. int main(int argc, char* argv[])
  205. {
  206. lua_State* L;
  207. struct Smain s;
  208. int test=1;
  209. target.little_endian=*(char*)&test;
  210. target.sizeof_int=sizeof(int);
  211. target.sizeof_strsize_t=sizeof(strsize_t);
  212. target.sizeof_lua_Number=sizeof(lua_Number);
  213. target.lua_Number_integral=(((lua_Number)0.5)==0);
  214. target.is_arm_fpa=0;
  215. int i=doargs(argc,argv);
  216. argc-=i; argv+=i;
  217. if (argc<=0) usage("no input files given");
  218. L=lua_open();
  219. if (L==NULL) fatal("not enough memory for state");
  220. s.argc=argc;
  221. s.argv=argv;
  222. if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1));
  223. lua_close(L);
  224. return EXIT_SUCCESS;
  225. }