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