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