1 /* $NetBSD: luac.c,v 1.4 2015/10/08 13:21:00 mbalmer Exp $ */
4 ** Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp
5 ** Lua compiler (saves bytecodes to files; also lists bytecodes)
6 ** See Copyright Notice in lua.h
27 static void PrintFunction(const Proto
* f
, int full
);
28 #define luaU_print PrintFunction
30 #define PROGNAME "luac" /* default program name */
31 #define OUTPUT PROGNAME ".out" /* default output file */
33 static int listing
=0; /* list bytecodes? */
34 static int dumping
=1; /* dump bytecodes? */
35 static int stripping
=0; /* strip debug information? */
36 static char Output
[]={ OUTPUT
}; /* default output file name */
37 static const char* output
=Output
; /* actual output file name */
38 static const char* progname
=PROGNAME
; /* actual program name */
40 static void fatal(const char* message
)
42 fprintf(stderr
,"%s: %s\n",progname
,message
);
46 static void cannot(const char* what
)
48 fprintf(stderr
,"%s: cannot %s %s: %s\n",progname
,what
,output
,strerror(errno
));
52 static void usage(const char* message
)
55 fprintf(stderr
,"%s: unrecognized option '%s'\n",progname
,message
);
57 fprintf(stderr
,"%s: %s\n",progname
,message
);
59 "usage: %s [options] [filenames]\n"
60 "Available options are:\n"
61 " -l list (use -l -l for full listing)\n"
62 " -o name output to file 'name' (default is \"%s\")\n"
64 " -s strip debug information\n"
65 " -v show version information\n"
66 " -- stop handling options\n"
67 " - stop handling options and process stdin\n"
72 #define IS(s) (strcmp(argv[i],s)==0)
74 static int doargs(int argc
, char* argv
[])
78 if (argv
[0]!=NULL
&& *argv
[0]!=0) progname
=argv
[0];
79 for (i
=1; i
<argc
; i
++)
81 if (*argv
[i
]!='-') /* end of options; keep it */
83 else if (IS("--")) /* end of options; skip it */
86 if (version
) ++version
;
89 else if (IS("-")) /* end of options; use stdin */
91 else if (IS("-l")) /* list */
93 else if (IS("-o")) /* output file */
96 if (output
==NULL
|| *output
==0 || (*output
=='-' && output
[1]!=0))
97 usage("'-o' needs argument");
98 if (IS("-")) output
=NULL
;
100 else if (IS("-p")) /* parse only */
102 else if (IS("-s")) /* strip debug information */
104 else if (IS("-v")) /* show version */
106 else /* unknown option */
109 if (i
==argc
&& (listing
|| !dumping
))
116 printf("%s\n",LUA_COPYRIGHT
);
117 if (version
==argc
-1) exit(EXIT_SUCCESS
);
122 #define FUNCTION "(function()end)();"
124 static const char* reader(lua_State
*L
, void *ud
, size_t *size
)
129 *size
=sizeof(FUNCTION
)-1;
139 #define toproto(L,i) getproto(L->top+(i))
141 static const Proto
* combine(lua_State
* L
, int n
)
144 return toproto(L
,-1);
149 if (lua_load(L
,reader
,&i
,"=(" PROGNAME
")",NULL
)!=LUA_OK
) fatal(lua_tostring(L
,-1));
153 f
->p
[i
]=toproto(L
,i
-n
-1);
154 if (f
->p
[i
]->sizeupvalues
>0) f
->p
[i
]->upvalues
[0].instack
=0;
161 static int writer(lua_State
* L
, const void* p
, size_t size
, void* u
)
164 return (fwrite(p
,size
,1,(FILE*)u
)!=1) && (size
!=0);
167 static int pmain(lua_State
* L
)
169 int argc
=(int)lua_tointeger(L
,1);
170 char** argv
=(char**)lua_touserdata(L
,2);
173 if (!lua_checkstack(L
,argc
)) fatal("too many input files");
174 for (i
=0; i
<argc
; i
++)
176 const char* filename
=IS("-") ? NULL
: argv
[i
];
177 if (luaL_loadfile(L
,filename
)!=LUA_OK
) fatal(lua_tostring(L
,-1));
180 if (listing
) luaU_print(f
,listing
>1);
183 FILE* D
= (output
==NULL
) ? stdout
: fopen(output
,"wb");
184 if (D
==NULL
) cannot("open");
186 luaU_dump(L
,f
,writer
,D
,stripping
);
188 if (ferror(D
)) cannot("write");
189 if (fclose(D
)) cannot("close");
194 int main(int argc
, char* argv
[])
197 int i
=doargs(argc
,argv
);
199 if (argc
<=0) usage("no input files given");
201 if (L
==NULL
) fatal("cannot create state: not enough memory");
202 lua_pushcfunction(L
,&pmain
);
203 lua_pushinteger(L
,argc
);
204 lua_pushlightuserdata(L
,argv
);
205 if (lua_pcall(L
,2,0,0)!=LUA_OK
) fatal(lua_tostring(L
,-1));
211 ** Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp
213 ** See Copyright Notice in lua.h
224 #include "lopcodes.h"
226 #define VOID(p) ((const void*)(p))
228 static void PrintString(const TString
* ts
)
230 const char* s
=getstr(ts
);
231 size_t i
,n
=tsslen(ts
);
235 int c
=(int)(unsigned char)s
[i
];
238 case '"': printf("\\\""); break;
239 case '\\': printf("\\\\"); break;
240 case '\a': printf("\\a"); break;
241 case '\b': printf("\\b"); break;
242 case '\f': printf("\\f"); break;
243 case '\n': printf("\\n"); break;
244 case '\r': printf("\\r"); break;
245 case '\t': printf("\\t"); break;
246 case '\v': printf("\\v"); break;
247 default: if (isprint(c
))
256 static void PrintConstant(const Proto
* f
, int i
)
258 const TValue
* o
=&f
->k
[i
];
265 printf(bvalue(o
) ? "true" : "false");
270 sprintf(buff
,LUA_NUMBER_FMT
,fltvalue(o
));
272 if (buff
[strspn(buff
,"-0123456789")]=='\0') printf(".0");
276 printf(LUA_INTEGER_FMT
,ivalue(o
));
278 case LUA_TSHRSTR
: case LUA_TLNGSTR
:
279 PrintString(tsvalue(o
));
281 default: /* cannot happen */
282 printf("? type=%d",ttype(o
));
287 #define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-")
288 #define MYK(x) (-1-(x))
290 static void PrintCode(const Proto
* f
)
292 const Instruction
* code
=f
->code
;
293 int pc
,n
=f
->sizecode
;
294 for (pc
=0; pc
<n
; pc
++)
296 Instruction i
=code
[pc
];
297 OpCode o
=GET_OPCODE(i
);
303 int sbx
=GETARG_sBx(i
);
304 int line
=getfuncline(f
,pc
);
305 printf("\t%d\t",pc
+1);
306 if (line
>0) printf("[%d]\t",line
); else printf("[-]\t");
307 printf("%-9s\t",luaP_opnames
[o
]);
308 switch (getOpMode(o
))
312 if (getBMode(o
)!=OpArgN
) printf(" %d",ISK(b
) ? (MYK(INDEXK(b
))) : b
);
313 if (getCMode(o
)!=OpArgN
) printf(" %d",ISK(c
) ? (MYK(INDEXK(c
))) : c
);
317 if (getBMode(o
)==OpArgK
) printf(" %d",MYK(bx
));
318 if (getBMode(o
)==OpArgU
) printf(" %d",bx
);
321 printf("%d %d",a
,sbx
);
324 printf("%d",MYK(ax
));
330 printf("\t; "); PrintConstant(f
,bx
);
334 printf("\t; %s",UPVALNAME(b
));
337 printf("\t; %s",UPVALNAME(b
));
338 if (ISK(c
)) { printf(" "); PrintConstant(f
,INDEXK(c
)); }
341 printf("\t; %s",UPVALNAME(a
));
342 if (ISK(b
)) { printf(" "); PrintConstant(f
,INDEXK(b
)); }
343 if (ISK(c
)) { printf(" "); PrintConstant(f
,INDEXK(c
)); }
347 if (ISK(c
)) { printf("\t; "); PrintConstant(f
,INDEXK(c
)); }
364 if (ISK(b
) || ISK(c
))
367 if (ISK(b
)) PrintConstant(f
,INDEXK(b
)); else printf("-");
369 if (ISK(c
)) PrintConstant(f
,INDEXK(c
)); else printf("-");
376 printf("\t; to %d",sbx
+pc
+2);
379 printf("\t; %p",VOID(f
->p
[bx
]));
382 if (c
==0) printf("\t; %d",(int)code
[++pc
]); else printf("\t; %d",c
);
385 printf("\t; "); PrintConstant(f
,ax
);
394 #define SS(x) ((x==1)?"":"s")
395 #define S(x) (int)(x),SS(x)
397 static void PrintHeader(const Proto
* f
)
399 const char* s
=f
->source
? getstr(f
->source
) : "=?";
400 if (*s
=='@' || *s
=='=')
402 else if (*s
==LUA_SIGNATURE
[0])
406 printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n",
407 (f
->linedefined
==0)?"main":"function",s
,
408 f
->linedefined
,f
->lastlinedefined
,
409 S(f
->sizecode
),VOID(f
));
410 printf("%d%s param%s, %d slot%s, %d upvalue%s, ",
411 (int)(f
->numparams
),f
->is_vararg
?"+":"",SS(f
->numparams
),
412 S(f
->maxstacksize
),S(f
->sizeupvalues
));
413 printf("%d local%s, %d constant%s, %d function%s\n",
414 S(f
->sizelocvars
),S(f
->sizek
),S(f
->sizep
));
417 static void PrintDebug(const Proto
* f
)
421 printf("constants (%d) for %p:\n",n
,VOID(f
));
424 printf("\t%d\t",i
+1);
429 printf("locals (%d) for %p:\n",n
,VOID(f
));
432 printf("\t%d\t%s\t%d\t%d\n",
433 i
,getstr(f
->locvars
[i
].varname
),f
->locvars
[i
].startpc
+1,f
->locvars
[i
].endpc
+1);
436 printf("upvalues (%d) for %p:\n",n
,VOID(f
));
439 printf("\t%d\t%s\t%d\t%d\n",
440 i
,UPVALNAME(i
),f
->upvalues
[i
].instack
,f
->upvalues
[i
].idx
);
444 static void PrintFunction(const Proto
* f
, int full
)
449 if (full
) PrintDebug(f
);
450 for (i
=0; i
<n
; i
++) PrintFunction(f
->p
[i
],full
);