1139749Simp/* $NetBSD$ */ 2193640Sariff 3193640Sariff/* 464881Scg** Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp 564881Scg** Lua compiler (saves bytecodes to files; also list bytecodes) 664881Scg** See Copyright Notice in lua.h 764881Scg*/ 864881Scg 964881Scg#include <errno.h> 1064881Scg#include <stdio.h> 1164881Scg#include <stdlib.h> 1264881Scg#include <string.h> 1364881Scg 1464881Scg#define luac_c 1564881Scg#define LUA_CORE 1664881Scg 1764881Scg#include "lua.h" 1864881Scg#include "lauxlib.h" 1964881Scg 2064881Scg#include "ldo.h" 2164881Scg#include "lfunc.h" 2264881Scg#include "lmem.h" 2364881Scg#include "lobject.h" 2464881Scg#include "lopcodes.h" 2564881Scg#include "lstring.h" 2664881Scg#include "lundump.h" 2764881Scg 2864881Scg#define PROGNAME "luac" /* default program name */ 2964881Scg#define OUTPUT PROGNAME ".out" /* default output file */ 3074763Scg 3174763Scgstatic int listing=0; /* list bytecodes? */ 3274763Scgstatic int dumping=1; /* dump bytecodes? */ 3374763Scgstatic int stripping=0; /* strip debug information? */ 3474763Scgstatic char Output[]={ OUTPUT }; /* default output file name */ 3574763Scgstatic const char* output=Output; /* actual output file name */ 3674763Scgstatic const char* progname=PROGNAME; /* actual program name */ 3775319Scg 3875319Scgstatic void fatal(const char* message) 3974763Scg{ 4074763Scg fprintf(stderr,"%s: %s\n",progname,message); 4174763Scg exit(EXIT_FAILURE); 4274763Scg} 4375319Scg 4475319Scgstatic void cannot(const char* what) 4570134Scg{ 4689834Scg fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); 4770134Scg exit(EXIT_FAILURE); 4875319Scg} 4989686Scg 5089834Scgstatic void usage(const char* message) 5170134Scg{ 5270134Scg if (*message=='-') 5364881Scg fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message); 5470134Scg else 5564881Scg fprintf(stderr,"%s: %s\n",progname,message); 56193640Sariff fprintf(stderr, 57193640Sariff "usage: %s [options] [filenames].\n" 58193640Sariff "Available options are:\n" 59193640Sariff " - process stdin\n" 60193640Sariff " -l list\n" 61193640Sariff " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" 62193640Sariff " -p parse only\n" 6374763Scg " -s strip debug information\n" 6474763Scg " -v show version information\n" 65117307Scg " -- stop handling options\n", 66193640Sariff progname,Output); 6764881Scg exit(EXIT_FAILURE); 68193640Sariff} 69193640Sariff 70193640Sariff#define IS(s) (strcmp(argv[i],s)==0) 71193640Sariff 72193640Sariffstatic int doargs(int argc, char* argv[]) 73193640Sariff{ 74193640Sariff int i; 75193640Sariff int version=0; 76193640Sariff if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; 77193640Sariff for (i=1; i<argc; i++) 7864881Scg { 79193640Sariff if (*argv[i]!='-') /* end of options; keep it */ 80193640Sariff break; 81193640Sariff else if (IS("--")) /* end of options; skip it */ 82193640Sariff { 83193640Sariff ++i; 84193640Sariff if (version) ++version; 85193640Sariff break; 86193640Sariff } 87193640Sariff else if (IS("-")) /* end of options; use stdin */ 88193640Sariff break; 8966308Scg else if (IS("-l")) /* list */ 90193640Sariff ++listing; 91193640Sariff else if (IS("-o")) /* output file */ 92193640Sariff { 93193640Sariff output=argv[++i]; 9466308Scg if (output==NULL || *output==0) usage(LUA_QL("-o") " needs argument"); 95193640Sariff if (IS("-")) output=NULL; 96193640Sariff } 97193640Sariff else if (IS("-p")) /* parse only */ 98193640Sariff dumping=0; 99193640Sariff else if (IS("-s")) /* strip debug information */ 100193640Sariff stripping=1; 101193640Sariff else if (IS("-v")) /* show version */ 102193640Sariff ++version; 103193640Sariff else /* unknown option */ 104193640Sariff usage(argv[i]); 105193640Sariff } 106193640Sariff if (i==argc && (listing || !dumping)) 107193640Sariff { 108164614Sariff dumping=0; 109193640Sariff argv[--i]=Output; 110164614Sariff } 111164614Sariff if (version) 112164614Sariff { 113164614Sariff printf("%s %s\n",LUA_RELEASE,LUA_COPYRIGHT); 114164614Sariff if (version==argc-1) exit(EXIT_SUCCESS); 115164614Sariff } 116193640Sariff return i; 117193640Sariff} 118193640Sariff 119193640Sariff#define toproto(L,i) (clvalue(L->top+(i))->l.p) 120193640Sariff 121193640Sariffstatic const Proto* combine(lua_State* L, int n) 122193640Sariff{ 123193640Sariff if (n==1) 124193640Sariff return toproto(L,-1); 125193640Sariff else 126193640Sariff { 127193640Sariff int i,pc; 128193640Sariff Proto* f=luaF_newproto(L); 129193640Sariff setptvalue2s(L,L->top,f); incr_top(L); 130193640Sariff f->source=luaS_newliteral(L,"=(" PROGNAME ")"); 131193640Sariff f->maxstacksize=1; 132193640Sariff pc=2*n+1; 133193640Sariff f->code=luaM_newvector(L,pc,Instruction); 134193640Sariff f->sizecode=pc; 135193640Sariff f->p=luaM_newvector(L,n,Proto*); 136193640Sariff f->sizep=n; 137193640Sariff pc=0; 138193640Sariff for (i=0; i<n; i++) 139193640Sariff { 140193640Sariff f->p[i]=toproto(L,i-n-1); 141193640Sariff f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i); 142193640Sariff f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1); 143193640Sariff } 144193640Sariff f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0); 145193640Sariff return f; 146193640Sariff } 147193640Sariff} 148193640Sariff 149193640Sariffstatic int writer(lua_State* L, const void* p, size_t size, void* u) 150193640Sariff{ 151193640Sariff UNUSED(L); 152193640Sariff return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); 153193640Sariff} 154193640Sariff 155193640Sariffstruct Smain { 156193640Sariff int argc; 157193640Sariff char** argv; 158193640Sariff}; 159193640Sariff 160193640Sariffstatic int pmain(lua_State* L) 161193640Sariff{ 162193640Sariff struct Smain* s = (struct Smain*)lua_touserdata(L, 1); 163193640Sariff int argc=s->argc; 164193640Sariff char** argv=s->argv; 165193640Sariff const Proto* f; 166193640Sariff int i; 167193640Sariff if (!lua_checkstack(L,argc)) fatal("too many input files"); 168193640Sariff for (i=0; i<argc; i++) 169193640Sariff { 170193640Sariff const char* filename=IS("-") ? NULL : argv[i]; 171193640Sariff if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1)); 172193640Sariff } 173193640Sariff f=combine(L,argc); 174193640Sariff if (listing) luaU_print(f,listing>1); 175193640Sariff if (dumping) 176193640Sariff { 177193640Sariff FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); 178193640Sariff if (D==NULL) cannot("open"); 179193640Sariff lua_lock(L); 180193640Sariff luaU_dump(L,f,writer,D,stripping); 181193640Sariff lua_unlock(L); 182193640Sariff if (ferror(D)) cannot("write"); 183193640Sariff if (fclose(D)) cannot("close"); 184193640Sariff } 185193640Sariff return 0; 186193640Sariff} 187193640Sariff 188193640Sariffint main(int argc, char* argv[]) 189193640Sariff{ 190193640Sariff lua_State* L; 191193640Sariff struct Smain s; 192193640Sariff int i=doargs(argc,argv); 193193640Sariff argc-=i; argv+=i; 194193640Sariff if (argc<=0) usage("no input files given"); 195193640Sariff L=lua_open(); 196164614Sariff if (L==NULL) fatal("not enough memory for state"); 197193640Sariff s.argc=argc; 198193640Sariff s.argv=argv; 199193640Sariff if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1)); 200193640Sariff lua_close(L); 201193640Sariff return EXIT_SUCCESS; 202164614Sariff} 203193640Sariff