Line data Source code
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 :
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 "ldo.h"
19 : #include "lfunc.h"
20 : #include "lmem.h"
21 : #include "lobject.h"
22 : #include "lopcodes.h"
23 : #include "lstring.h"
24 : #include "lundump.h"
25 :
26 : #define PROGNAME "luac" /* default program name */
27 : #define OUTPUT PROGNAME ".out" /* default output file */
28 :
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 :
36 1 : static void fatal(const char* message)
37 : {
38 1 : fprintf(stderr,"%s: %s\n",progname,message);
39 1 : exit(EXIT_FAILURE);
40 : }
41 :
42 0 : static void cannot(const char* what)
43 : {
44 0 : fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno));
45 0 : exit(EXIT_FAILURE);
46 : }
47 :
48 0 : static void usage(const char* message)
49 : {
50 0 : if (*message=='-')
51 0 : fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message);
52 : else
53 0 : fprintf(stderr,"%s: %s\n",progname,message);
54 0 : fprintf(stderr,
55 : "usage: %s [options] [filenames].\n"
56 : "Available options are:\n"
57 : " - process stdin\n"
58 : " -l list\n"
59 : " -o name output to file " LUA_QL("name") " (default is \"%s\")\n"
60 : " -p parse only\n"
61 : " -s strip debug information\n"
62 : " -v show version information\n"
63 : " -- stop handling options\n",
64 : progname,Output);
65 0 : exit(EXIT_FAILURE);
66 : }
67 :
68 : #define IS(s) (strcmp(argv[i],s)==0)
69 :
70 14 : static int doargs(int argc, char* argv[])
71 : {
72 : int i;
73 14 : int version=0;
74 14 : if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0];
75 33 : for (i=1; i<argc; i++)
76 : {
77 31 : if (*argv[i]!='-') /* end of options; keep it */
78 9 : break;
79 22 : else if (IS("--")) /* end of options; skip it */
80 : {
81 1 : ++i;
82 1 : if (version) ++version;
83 1 : break;
84 : }
85 21 : else if (IS("-")) /* end of options; use stdin */
86 2 : break;
87 19 : else if (IS("-l")) /* list */
88 8 : ++listing;
89 11 : else if (IS("-o")) /* output file */
90 : {
91 3 : output=argv[++i];
92 3 : if (output==NULL || *output==0) usage(LUA_QL("-o") " needs argument");
93 3 : if (IS("-")) output=NULL;
94 : }
95 8 : else if (IS("-p")) /* parse only */
96 3 : dumping=0;
97 5 : else if (IS("-s")) /* strip debug information */
98 2 : stripping=1;
99 3 : else if (IS("-v")) /* show version */
100 3 : ++version;
101 : else /* unknown option */
102 0 : usage(argv[i]);
103 : }
104 14 : if (i==argc && (listing || !dumping))
105 : {
106 1 : dumping=0;
107 1 : argv[--i]=Output;
108 : }
109 14 : if (version)
110 : {
111 3 : printf("%s %s\n",LUA_RELEASE,LUA_COPYRIGHT);
112 3 : if (version==argc-1) exit(EXIT_SUCCESS);
113 : }
114 12 : return i;
115 : }
116 :
117 : #define toproto(L,i) (clvalue(L->top+(i))->l.p)
118 :
119 11 : static const Proto* combine(lua_State* L, int n)
120 : {
121 11 : if (n==1)
122 10 : return toproto(L,-1);
123 : else
124 : {
125 : int i,pc;
126 1 : Proto* f=luaF_newproto(L);
127 1 : setptvalue2s(L,L->top,f); incr_top(L);
128 1 : f->source=luaS_newliteral(L,"=(" PROGNAME ")");
129 1 : f->maxstacksize=1;
130 1 : pc=2*n+1;
131 1 : f->code=luaM_newvector(L,pc,Instruction);
132 1 : f->sizecode=pc;
133 1 : f->p=luaM_newvector(L,n,Proto*);
134 1 : f->sizep=n;
135 1 : pc=0;
136 3 : for (i=0; i<n; i++)
137 : {
138 2 : f->p[i]=toproto(L,i-n-1);
139 2 : f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i);
140 2 : f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1);
141 : }
142 1 : f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0);
143 1 : return f;
144 : }
145 : }
146 :
147 476 : static int writer(lua_State* L, const void* p, size_t size, void* u)
148 : {
149 : UNUSED(L);
150 476 : return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);
151 : }
152 :
153 : struct Smain {
154 : int argc;
155 : char** argv;
156 : };
157 :
158 12 : static int pmain(lua_State* L)
159 : {
160 12 : struct Smain* s = (struct Smain*)lua_touserdata(L, 1);
161 12 : int argc=s->argc;
162 12 : char** argv=s->argv;
163 : const Proto* f;
164 : int i;
165 12 : if (!lua_checkstack(L,argc)) fatal("too many input files");
166 24 : for (i=0; i<argc; i++)
167 : {
168 13 : const char* filename=IS("-") ? NULL : argv[i];
169 13 : if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1));
170 : }
171 11 : f=combine(L,argc);
172 11 : if (listing) luaU_print(f,listing>1);
173 11 : if (dumping)
174 : {
175 8 : FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
176 8 : if (D==NULL) cannot("open");
177 : lua_lock(L);
178 8 : luaU_dump(L,f,writer,D,stripping);
179 : lua_unlock(L);
180 8 : if (ferror(D)) cannot("write");
181 8 : if (fclose(D)) cannot("close");
182 : }
183 11 : return 0;
184 : }
185 :
186 14 : int main(int argc, char* argv[])
187 : {
188 : lua_State* L;
189 : struct Smain s;
190 14 : int i=doargs(argc,argv);
191 12 : argc-=i; argv+=i;
192 12 : if (argc<=0) usage("no input files given");
193 12 : L=lua_open();
194 12 : if (L==NULL) fatal("not enough memory for state");
195 12 : s.argc=argc;
196 12 : s.argv=argv;
197 12 : if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1));
198 11 : lua_close(L);
199 11 : return EXIT_SUCCESS;
200 : }
|