Lua 5.1.4: luac.c


This is the Lua compiler front-end (luac). Note: Comments based on Lua 5.2.0-alpha.
L0001 /* L0002 ** $Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp $ L0003 ** Lua compiler (saves bytecodes to files; also list bytecodes) L0004 ** See Copyright Notice in lua.h L0005 */ L0006 L0007 #include <errno.h> L0008 #include <stdio.h> L0009 #include <stdlib.h> L0010 #include <string.h> L0011 L0012 #define luac_c L0013 #define LUA_CORE L0014 L0015 #include "lua.h" L0016 #include "lauxlib.h" L0017 L0018 #include "ldo.h" L0019 #include "lfunc.h" L0020 #include "lmem.h" L0021 #include "lobject.h" L0022 #include "lopcodes.h" L0023 #include "lstring.h" L0024 #include "lundump.h" L0025 L0026 #define PROGNAME "luac" /* default program name */ L0027 #define OUTPUT PROGNAME ".out" /* default output file */ L0028 L0029 static int listing=0; /* list bytecodes? */ L0030 static int dumping=1; /* dump bytecodes? */ L0031 static int stripping=0; /* strip debug information? */ L0032 static char Output[]={ OUTPUT }; /* default output file name */ L0033 static const char* output=Output; /* actual output file name */ L0034 static const char* progname=PROGNAME; /* actual program name */ L0035 L0036 static void fatal(const char* message)
Utility function to display fatal error message and exit (without cleanup).
L0037 { L0038 fprintf(stderr,"%s: %s\n",progname,message); L0039 exit(EXIT_FAILURE); L0040 } L0041 L0042 static void cannot(const char* what)
Utility function display fatal I/O error and exit (without cleanup).
L0043 { L0044 fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); L0045 exit(EXIT_FAILURE); L0046 } L0047 L0048 static void usage(const char* message)
Writes command-line help to standard error and exit (without cleanup)
L0049 { L0050 if (*message=='-') L0051 fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message); L0052 else L0053 fprintf(stderr,"%s: %s\n",progname,message); L0054 fprintf(stderr, L0055 "usage: %s [options] [filenames].\n" L0056 "Available options are:\n" L0057 " - process stdin\n" L0058 " -l list\n" L0059 " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" L0060 " -p parse only\n" L0061 " -s strip debug information\n" L0062 " -v show version information\n" L0063 " -- stop handling options\n", L0064 progname,Output); L0065 exit(EXIT_FAILURE); L0066 } L0067 L0068 #define IS(s) (strcmp(argv[i],s)==0) L0069 L0070 static int doargs(int argc, char* argv[])
Parse main's command line arguments. May exit without cleanup.
L0071 { L0072 int i; L0073 int version=0; L0074 if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; L0075 for (i=1; i<argc; i++) L0076 { L0077 if (*argv[i]!='-') /* end of options; keep it */ L0078 break; L0079 else if (IS("--")) /* end of options; skip it */ L0080 { L0081 ++i; L0082 if (version) ++version; L0083 break; L0084 } L0085 else if (IS("-")) /* end of options; use stdin */ L0086 break; L0087 else if (IS("-l")) /* list */ L0088 ++listing; L0089 else if (IS("-o")) /* output file */ L0090 { L0091 output=argv[++i]; L0092 if (output==NULL || *output==0) usage(LUA_QL("-o") " needs argument"); L0093 if (IS("-")) output=NULL; L0094 } L0095 else if (IS("-p")) /* parse only */ L0096 dumping=0; L0097 else if (IS("-s")) /* strip debug information */ L0098 stripping=1; L0099 else if (IS("-v")) /* show version */ L0100 ++version; L0101 else /* unknown option */ L0102 usage(argv[i]); L0103 } L0104 if (i==argc && (listing || !dumping)) L0105 { L0106 dumping=0; L0107 argv[--i]=Output; L0108 } L0109 if (version) L0110 { L0111 printf("%s %s\n",LUA_RELEASE,LUA_COPYRIGHT); L0112 if (version==argc-1) exit(EXIT_SUCCESS); L0113 } L0114 return i; L0115 } L0116 L0117 #define toproto(L,i) (clvalue(L->top+(i))->l.p) L0118 L0119 static const Proto* combine(lua_State* L, int n)
On exit, the top of the stack will contain a function that calls the previous top-most n values (functions) on the stack. This is used to generate the initial bytecode needed by luac when compiling multiple files (chunks) together.
L0120 { L0121 if (n==1) L0122 return toproto(L,-1); L0123 else L0124 { L0125 int i,pc; L0126 Proto* f=luaF_newproto(L); L0127 setptvalue2s(L,L->top,f); incr_top(L); L0128 f->source=luaS_newliteral(L,"=(" PROGNAME ")"); L0129 f->maxstacksize=1; L0130 pc=2*n+1; L0131 f->code=luaM_newvector(L,pc,Instruction); L0132 f->sizecode=pc; L0133 f->p=luaM_newvector(L,n,Proto*); L0134 f->sizep=n; L0135 pc=0; L0136 for (i=0; i<n; i++) L0137 { L0138 f->p[i]=toproto(L,i-n-1); L0139 f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i); L0140 f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1); L0141 } L0142 f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0); L0143 return f; L0144 } L0145 } L0146 L0147 static int writer(lua_State* L, const void* p, size_t size, void* u) L0148 { L0149 UNUSED(L); L0150 return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); L0151 } L0152 L0153 struct Smain { L0154 int argc; L0155 char** argv; L0156 }; L0157 L0158 static int pmain(lua_State* L) L0159 { L0160 struct Smain* s = (struct Smain*)lua_touserdata(L, 1); L0161 int argc=s->argc; L0162 char** argv=s->argv; L0163 const Proto* f; L0164 int i; L0165 if (!lua_checkstack(L,argc)) fatal("too many input files"); L0166 for (i=0; i<argc; i++) L0167 { L0168 const char* filename=IS("-") ? NULL : argv[i]; L0169 if (luaL_loadfile(L,filename)!=0) fatal(lua_tostring(L,-1)); L0170 } L0171 f=combine(L,argc); L0172 if (listing) luaU_print(f,listing>1); L0173 if (dumping) L0174 { L0175 FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); L0176 if (D==NULL) cannot("open"); L0177 lua_lock(L); L0178 luaU_dump(L,f,writer,D,stripping); L0179 lua_unlock(L); L0180 if (ferror(D)) cannot("write"); L0181 if (fclose(D)) cannot("close"); L0182 } L0183 return 0; L0184 } L0185 L0186 int main(int argc, char* argv[]) L0187 { L0188 lua_State* L; L0189 struct Smain s; L0190 int i=doargs(argc,argv); L0191 argc-=i; argv+=i; L0192 if (argc<=0) usage("no input files given"); L0193 L=lua_open(); L0194 if (L==NULL) fatal("not enough memory for state"); L0195 s.argc=argc; L0196 s.argv=argv; L0197 if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1)); L0198 lua_close(L); L0199 return EXIT_SUCCESS; L0200 }

Generated by pretty.lua