static const Proto* combine(lua_State* L, int n) { if (n==1) return toproto(L,-1); else { int i,pc; Proto* f=luaF_newproto(L); setptvalue2s(L,L->top,f); incr_top(L); f->source=luaS_newliteral(L,"=(" PROGNAME ")"); f->maxstacksize=1; pc=2*n+1; f->code=luaM_newvector(L,pc,Instruction); f->sizecode=pc; f->p=luaM_newvector(L,n,Proto*); f->sizep=n; pc=0; for (i=0; i<n; i++) { f->p[i]=toproto(L,i-n-1); f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i); f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1); } f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0); return f; } }
int main(int argc, char* argv[]) { const char *input_luac, *opcodes_def; int i; lua_State* L; Proto* f; FILE* D; gargc = argc; gargv = argv; i = doargs(argc,argv); argc -= i; argv += i; if (argc < 1) { usage("need 1 arguments at least", NULL); } L = lua_open(); glstate = L; //luaB_opentests(L); input_luac = argv[0]; if (luaL_loadfile(L, input_luac) != 0) { fatal(lua_tostring(L, -1)); } f = toproto(L, -1); if (cmp_gen_lua || cmp_gen_luac) { Proto* input_proto = f; Proto* allopcodes_proto; const char* buff = cmp_gen_lua ? allopcodes_lua : allopcodes_luac; int bufflen = cmp_gen_lua ? allopcodes_lua_len : allopcodes_luac_len; if (luaL_loadbuffer(L, buff, bufflen, "allopcodes.lua") != 0) { fatal(lua_tostring(L, -1)); } allopcodes_proto = toproto(L, -1); CompareAndGenOpcodes(input_proto, allopcodes_proto); } else { opcodes_def = (argv[1]) ? (argv[1]) : OPCODES_TXT; if (!generateOp2op(opcodes_def)) { fprintf(stderr, "opcodes.txt file: %s format error!", opcodes_def); return EXIT_FAILURE; } swapOpCode(f); D = (output == NULL) ? stdout : fopen(output, "wb"); if (D == NULL) cannot("open", output); lua_lock(L); luaU_dump(L, f, writer, D, 0); lua_unlock(L); if (ferror(D)) cannot("write", output); if (fclose(D)) cannot("close", output); printf("%s generated!\n", output); } lua_close(L); return EXIT_SUCCESS; }
static const Proto* combine(lua_State* L, int n) { if (n==1) return toproto(L,-1); else { Proto* f; int i=n; if (lua_load(L,reader,&i,"=(" PROGNAME ")")!=LUA_OK) fatal(lua_tostring(L,-1)); f=toproto(L,-1); for (i=0; i<n; i++) f->p[i]=toproto(L,i-n-1); f->sizelineinfo=0; f->sizeupvalues=0; return f; } }
// Lua: compile(filename) -- compile lua file into lua bytecode, and save to .lc static int node_compile( lua_State* L ) { Proto* f; int file_fd = FS_OPEN_OK - 1; size_t len; const char *fname = luaL_checklstring( L, 1, &len ); if ( len > FS_NAME_MAX_LENGTH ) return luaL_error(L, "filename too long"); char output[FS_NAME_MAX_LENGTH]; c_strcpy(output, fname); // check here that filename end with ".lua". if (len < 4 || (c_strcmp( output + len - 4, ".lua") != 0) ) return luaL_error(L, "not a .lua file"); output[c_strlen(output) - 2] = 'c'; output[c_strlen(output) - 1] = '\0'; NODE_DBG(output); NODE_DBG("\n"); if (luaL_loadfsfile(L, fname) != 0) { return luaL_error(L, lua_tostring(L, -1)); } f = toproto(L, -1); int stripping = 1; /* strip debug information? */ file_fd = fs_open(output, fs_mode2flag("w+")); if (file_fd < FS_OPEN_OK) { return luaL_error(L, "cannot open/write to file"); } lua_lock(L); int result = luaU_dump(L, f, writer, &file_fd, stripping); lua_unlock(L); if (fs_flush(file_fd) < 0) { // result codes aren't propagated by flash_fs.h // overwrite Lua error, like writer() does in case of a file io error result = 1; } fs_close(file_fd); file_fd = FS_OPEN_OK - 1; if (result == LUA_ERR_CC_INTOVERFLOW) { return luaL_error(L, "value too big or small for target integer type"); } if (result == LUA_ERR_CC_NOTINTEGER) { return luaL_error(L, "target lua_Number is integral but fractional value found"); } if (result == 1) { // result status generated by writer() or fs_flush() fail return luaL_error(L, "writing to file failed"); } return 0; }
static Proto* combine(lua_State* L, int n) { if (n==1) { int i; Proto* f = toproto(L,-1); if (LDS2) { Inject(f,0); for (i=0; i<f->sizep; i++) { Inject(f->p[i],i+1); } } return f; } else { int i,pc=0; Proto* f=luaF_newproto(L); f->source=luaS_newliteral(L,"=(" PROGNAME ")"); f->maxstacksize=1; f->p=luaM_newvector(L,n,Proto*); f->sizep=n; f->sizecode=2*n+1; f->code=luaM_newvector(L,f->sizecode,Instruction); for (i=0; i<n; i++) { f->p[i]=toproto(L,i-n); f->code[pc++]=CREATE_ABx(HKS_OPCODE_CLOSURE,0,i); f->code[pc++]=CREATE_ABC(HKS_OPCODE_CALL,0,1,1); } f->code[pc++]=CREATE_ABC(HKS_OPCODE_RETURN,0,1,0); if (LDS2) { Inject(f,0); for (i=0; i<n; i++) { Inject(f->p[i],i+1); } } return f; } }
static const Proto* combine(lua_State* L, int n) { Proto* f; char buf[4096]; int i=n; if (n==1) return toproto(L,-1); memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf)-1, "=(%s)", process_name); if (sexe_load(L, reader, &i, buf, NULL)!=LUA_OK) fatal(lua_tostring(L,-1)); f=toproto(L,-1); for (i=0; i<n; i++) { f->p[i]=toproto(L,i-n-1); if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; } f->sizelineinfo=0; return f; }
static int file_compile( lua_State* L ) { Proto* f; int file_fd = FILE_NOT_OPENED; size_t len; const char *fname = luaL_checklstring( L, 1, &len ); if ( len > SPIFFS_OBJ_NAME_LEN ) return luaL_error(L, "filename too long"); char output[SPIFFS_OBJ_NAME_LEN]; strcpy(output, fname); // check here that filename end with ".lua". if (len < 4 || (strcmp( output + len - 4, ".lua") != 0) ) return luaL_error(L, "not a .lua file"); output[strlen(output) - 2] = 'c'; output[strlen(output) - 1] = '\0'; if (luaL_loadfile(L, fname) != 0) { return luaL_error(L, lua_tostring(L, -1)); } f = toproto(L, -1); int stripping = 1; /* strip debug information? */ file_fd = SPIFFS_open(&fs,(char*)output,mode2flag("w+"),0); if (file_fd < FILE_NOT_OPENED) { return luaL_error(L, "cannot open/write to file"); } lua_lock(L); int result = luaU_dump(L, f, writer, &file_fd, stripping); lua_unlock(L); SPIFFS_fflush(&fs,file_fd); SPIFFS_close(&fs,file_fd); file_fd =FILE_NOT_OPENED; if (result == LUA_ERR_CC_INTOVERFLOW) { return luaL_error(L, "value too big or small for target integer type"); } if (result == LUA_ERR_CC_NOTINTEGER) { return luaL_error(L, "target lua_Number is integral but fractional value found"); } return 0; }
static void persistproto(PersistInfo *pi) { /* perms reftbl ... proto */ Proto *p = toproto(pi->L, -1); lua_checkstack(pi->L, 2); /* Persist constant refs */ { int i; pi->writer(pi->L, &p->sizek, sizeof(int), pi->ud); for(i=0; i<p->sizek; i++) { LIF(A,pushobject)(pi->L, &p->k[i]); /* perms reftbl ... proto const */ persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... proto */ } } /* perms reftbl ... proto */ /* serialize inner Proto refs */ { int i; pi->writer(pi->L, &p->sizep, sizeof(int), pi->ud); for(i=0; i<p->sizep; i++) { pushproto(pi->L, p->p[i]); /* perms reftbl ... proto subproto */ persist(pi); lua_pop(pi->L, 1); /* perms reftbl ... proto */ } } /* perms reftbl ... proto */ /* Serialize code */ { pi->writer(pi->L, &p->sizecode, sizeof(int), pi->ud); pi->writer(pi->L, p->code, sizeof(Instruction) * p->sizecode, pi->ud); } /* Serialize misc values */ { pi->writer(pi->L, &p->nups, sizeof(lu_byte), pi->ud); pi->writer(pi->L, &p->numparams, sizeof(lu_byte), pi->ud); pi->writer(pi->L, &p->is_vararg, sizeof(lu_byte), pi->ud); pi->writer(pi->L, &p->maxstacksize, sizeof(lu_byte), pi->ud); } /* We do not currently persist upvalue names, local variable names, * variable lifetimes, line info, or source code. */ }
static void unpersistfunction(int ref, UnpersistInfo *upi) { /* perms reftbl ... */ LClosure *lcl; int i; lu_byte nupvalues; verify(luaZ_read(&upi->zio, &nupvalues, sizeof(lu_byte)) == 0); lcl = (LClosure*)luaF_newLclosure(upi->L, nupvalues, &upi->L->_gt); pushclosure(upi->L, (Closure*)lcl); /* perms reftbl ... func */ /* Put *some* proto in the closure, before the GC can find it */ lcl->p = makefakeproto(upi->L, nupvalues); /* Also, we need to temporarily fill the upvalues */ lua_pushnil(upi->L); /* perms reftbl ... func nil */ for(i=0; i<nupvalues; i++) { lcl->upvals[i] = makeupval(upi->L, -1); } lua_pop(upi->L, 1); /* perms reftbl ... func */ /* I can't see offhand how a function would ever get to be self- * referential, but just in case let's register it early */ registerobject(ref, upi); /* Now that it's safe, we can get the real proto */ unpersist(upi); /* perms reftbl ... func proto? */ lua_assert(lua_type(upi->L, -1) == LUA_TPROTO); /* perms reftbl ... func proto */ lcl->p = toproto(upi->L, -1); lua_pop(upi->L, 1); /* perms reftbl ... func */ for(i=0; i<nupvalues; i++) { /* perms reftbl ... func */ unpersist(upi); /* perms reftbl ... func func2 */ unboxupval(upi->L); /* perms reftbl ... func upval */ lcl->upvals[i] = toupval(upi->L, -1); lua_pop(upi->L, 1); /* perms reftbl ... func */ } /* perms reftbl ... func */ /* Finally, the fenv */ unpersist(upi); /* perms reftbl ... func fenv/nil? */ lua_assert(lua_type(upi->L, -1) == LUA_TNIL || lua_type(upi->L, -1) == LUA_TTABLE); /* perms reftbl ... func fenv/nil */ if(!lua_isnil(upi->L, -1)) { /* perms reftbl ... func fenv */ lua_setfenv(upi->L, -2); /* perms reftbl ... func */ } else { /* perms reftbl ... func nil */ lua_pop(upi->L, 1); /* perms reftbl ... func */ } /* perms reftbl ... func */ }
static void unpersistproto(int ref, UnpersistInfo *upi) { /* perms reftbl ... */ Proto *p; int i; int sizep, sizek; /* We have to be careful. The GC expects a lot out of protos. In * particular, we need to give the function a valid string for its * source, and valid code, even before we actually read in the real * code. */ TString *source = luaS_newlstr(upi->L, "", 0); p = luaF_newproto(upi->L); p->source = source; p->sizecode=1; p->code = luaM_newvector(upi->L, 1, Instruction); p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0); p->maxstacksize = 2; p->sizek = 0; p->sizep = 0; pushproto(upi->L, p); /* perms reftbl ... proto */ /* We don't need to register early, since protos can never ever be * involved in cyclic references */ /* Read in constant references */ { verify(luaZ_read(&upi->zio, &sizek, sizeof(int)) == 0); luaM_reallocvector(upi->L, p->k, 0, sizek, TObject); for(i=0; i<sizek; i++) { /* perms reftbl ... proto */ unpersist(upi); /* perms reftbl ... proto k */ setobj2s(&p->k[i], getobject(upi->L, -1)); p->sizek++; lua_pop(upi->L, 1); /* perms reftbl ... proto */ } /* perms reftbl ... proto */ } /* Read in sub-proto references */ { verify(luaZ_read(&upi->zio, &sizep, sizeof(int)) == 0); luaM_reallocvector(upi->L, p->p, 0, sizep, Proto*); for(i=0; i<sizep; i++) { /* perms reftbl ... proto */ unpersist(upi); /* perms reftbl ... proto subproto */ p->p[i] = toproto(upi->L, -1); p->sizep++; lua_pop(upi->L, 1); /* perms reftbl ... proto */ } /* perms reftbl ... proto */ } /* Read in code */ { verify(luaZ_read(&upi->zio, &p->sizecode, sizeof(int)) == 0); luaM_reallocvector(upi->L, p->code, 1, p->sizecode, Instruction); verify(luaZ_read(&upi->zio, p->code, sizeof(Instruction) * p->sizecode) == 0); } /* Read in misc values */ { verify(luaZ_read(&upi->zio, &p->nups, sizeof(lu_byte)) == 0); verify(luaZ_read(&upi->zio, &p->numparams, sizeof(lu_byte)) == 0); verify(luaZ_read(&upi->zio, &p->is_vararg, sizeof(lu_byte)) == 0); verify(luaZ_read(&upi->zio, &p->maxstacksize, sizeof(lu_byte)) == 0); } }
static Proto* combine(lua_State* L, int scripts) { if (scripts==1 && preloads==0) return toproto(L,-1); else { TString *s; TValue *k; int i,pc,n; Proto* f=luaF_newproto(L); setptvalue2s(L,L->top,f); incr_top(L); f->source=luaS_newliteral(L,"=(" PROGNAME ")"); f->maxstacksize=1; pc=(2*scripts) + 1; if(preloads > 0) { pc+=(2*preloads) + 2; } f->code=luaM_newvector(L,pc,Instruction); f->sizecode=pc; n=(scripts + preloads); f->p=luaM_newvector(L,n,Proto*); f->sizep=n; pc=0; n=0; /* preload libraries. */ if (preloads > 0) { /* create constants array. */ f->k=luaM_newvector(L, (preloads + 2),TValue); f->sizek=(preloads + 2); /* make room for "local t" variable. */ f->maxstacksize=2; /* add "package" & "preload" constants. */ k=&(f->k[0]); s=luaS_newliteral(L, "package"); setsvalue2n(L,k,s); k=&(f->k[1]); s=luaS_newliteral(L, "preload"); setsvalue2n(L,k,s); /* code: local t = package.preload */ f->code[pc++]=CREATE_ABx(OP_GETGLOBAL,0,0); f->code[pc++]=CREATE_ABC(OP_GETTABLE,0,0,RKASK(1)); } /* add preload libraries to "package.preload" */ for (i=0; i < preloads; i++) { /* create constant for library name. */ k=&(f->k[i+2]); s=luaS_new(L, preload_libs[i]); setsvalue2n(L,k,s); /* code: t['name'] = function() --[[ lib code ]] end */ f->code[pc++]=CREATE_ABx(OP_CLOSURE,1,n); f->code[pc++]=CREATE_ABC(OP_SETTABLE,0,RKASK(i+2),1); f->p[n++]=toproto(L,i-preloads-1); } /* call scripts. */ for (i=0; i < scripts; i++) { /* code: (function() --[[ script code ]] end)() */ f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,n); f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1); f->p[n++]=toproto(L,i-scripts-1-preloads); } f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0); return f; } }
int main(int argc, char* argv[]) { lua_State* L; const char *destfile, *destnum, *srcfile, *srcnum; Proto *fdestroot, *fsrcroot, *fparent, *fdest, *fsrc; int cdest, csrc; char *realdestnum = NULL, *realsrcnum = NULL; FILE* D; int diff, i; gargc = argc; gargv = argv; i = doargs(argc,argv); argc -= i; argv += i; if (printfuncnum && argc < 1) { usage("need 1 arguments for -pn at least", NULL); } if (argc < 4) { usage("need 4 arguments at least", NULL); } L = lua_open(); glstate = L; luaB_opentests(L); destfile = argv[0]; destnum = argv[1]; if (luaL_loadfile(L, destfile) != 0) { fatal(lua_tostring(L, -1)); } fdestroot = toproto(L, -1); if (printfuncnum) { printf("%d\n",0); printFuncStructure(fdestroot, " 0_"); lua_close(L); return EXIT_SUCCESS; } realdestnum = (char*)calloc(strlen(destnum)+1, sizeof(char)); fparent = findParentFunction(fdestroot, destnum, &cdest, realdestnum); if (cdest < 0) { if (realdestnum) { free(realdestnum); realdestnum = NULL; } fatal("cannot find dest function"); } if (fparent == NULL) { fdest = fdestroot; } else { fdest = fparent->p[cdest]; } srcfile = argv[2]; srcnum = argv[3]; if (luaL_loadfile(L, srcfile) != 0) { fatal(lua_tostring(L, -1)); } fsrcroot = toproto(L, -1); realsrcnum = (char*)calloc(strlen(srcnum)+1, sizeof(char)); fsrc = findParentFunction(fsrcroot, srcnum, &csrc, realsrcnum); if (csrc < 0) { if (realdestnum) { free(realdestnum); realdestnum = NULL; } if (realsrcnum) { free(realsrcnum); realsrcnum = NULL; } fatal("cannot find src function"); } if (fsrc == NULL) { fsrc = fsrcroot; } else { fsrc = fsrc->p[csrc]; } if (!replace_sub){ if (fparent == NULL) { if (realdestnum) { free(realdestnum); realdestnum = NULL; } if (realsrcnum) { free(realsrcnum); realsrcnum = NULL; } fatal("cannot use root as dest function"); } fprintf(stderr, "Replacing %s %s with %s %s ...\n", destfile, realdestnum, srcfile, realsrcnum); diff = replaceFunction(fparent, cdest, fsrc); fprintf(stderr, "1 function replaced ok.\n"); } else { fprintf(stderr, "Replacing sub functions of %s %s with those of %s %s ...\n", destfile, realdestnum, srcfile, realsrcnum); diff = replaceSubFunctions(fdest, fsrc); fprintf(stderr, "%d function replaced ok.", MIN(fdest->sizep, fsrc->sizep)); if (fdest->sizep != fsrc->sizep) { fprintf(stderr, " The dest has %d sub functions, but the src has %d . Please have a check.\n", fdest->sizep, fsrc->sizep); } else { fprintf(stderr, "\n"); } } if (realdestnum) { free(realdestnum); realdestnum = NULL; } if (realsrcnum) { free(realsrcnum); realsrcnum = NULL; } if (strict == 1 && diff > 0){ fatal("strip mode on and incompatible functions found, stop writing output."); } D = (output == NULL) ? stdout : fopen(output, "wb"); if (D == NULL) cannot("open"); lua_lock(L); luaU_dump(L, fdestroot, writer, D, 0); lua_unlock(L); if (ferror(D)) cannot("write"); if (fclose(D)) cannot("close"); printf("%s generated!\n", output); lua_close(L); return EXIT_SUCCESS; }
/* * If the luac command line includes multiple files or has the -f option * then luac generates a main function to reference all sub-main prototypes. * This is one of two types: * Type 0 The standard luac combination main * Type 1 A lookup wrapper that facilitates indexing into the generated protos */ static const Proto* combine(lua_State* L, int n, int type) { if (n==1 && type == 0) return toproto(L,-1); else { int i; Instruction *pc; Proto* f=luaF_newproto(L); setptvalue2s(L,L->top,f); incr_top(L); f->source=luaS_newliteral(L,"=(" PROGNAME ")"); f->p=luaM_newvector(L,n,Proto*); f->sizep=n; for (i=0; i<n; i++) f->p[i]=toproto(L,i-n-1); pc=0; if (type == 0) { /* * Type 0 is as per the standard luac, which is just a main routine which * invokes all of the compiled functions sequentially. This is fine if * they are self registering modules, but useless otherwise. */ f->numparams = 0; f->maxstacksize = 1; f->sizecode = 2*n + 1 ; f->sizek = 0; f->code = luaM_newvector(L, f->sizecode , Instruction); f->k = luaM_newvector(L,f->sizek,TValue); for (i=0, pc = f->code; i<n; i++) { *pc++ = CREATE_ABx(OP_CLOSURE,0,i); *pc++ = CREATE_ABC(OP_CALL,0,1,1); } *pc++ = CREATE_ABC(OP_RETURN,0,1,0); } else { /* * The Type 1 main() is a lookup which takes a single argument, the name to * be resolved. If this matches root name of one of the compiled files then * a closure to this file main is returned. Otherwise the Unixtime of the * compile and the list of root names is returned. */ if (n > LFIELDS_PER_FLUSH) { #define NO_MOD_ERR_(n) ": Number of modules > " #n #define NO_MOD_ERR(n) NO_MOD_ERR_(n) usage(LUA_QL("-f") NO_MOD_ERR(LFIELDS_PER_FLUSH)); } f->numparams = 1; f->maxstacksize = n + 3; f->sizecode = 5*n + 5 ; f->sizek = n + 1; f->sizelocvars = 0; f->code = luaM_newvector(L, f->sizecode , Instruction); f->k = luaM_newvector(L,f->sizek,TValue); for (i=0, pc = f->code; i<n; i++) { /* if arg1 == FnameA then return function (...) -- funcA -- end end */ setsvalue2n(L,f->k+i,corename(L, f->p[i]->source)); *pc++ = CREATE_ABC(OP_EQ,0,0,RKASK(i)); *pc++ = CREATE_ABx(OP_JMP,0,MAXARG_sBx+2); *pc++ = CREATE_ABx(OP_CLOSURE,1,i); *pc++ = CREATE_ABC(OP_RETURN,1,2,0); } setnvalue(f->k+n, (lua_Number) time(NULL)); *pc++ = CREATE_ABx(OP_LOADK,1,n); *pc++ = CREATE_ABC(OP_NEWTABLE,2,luaO_int2fb(i),0); for (i=0; i<n; i++) *pc++ = CREATE_ABx(OP_LOADK,i+3,i); *pc++ = CREATE_ABC(OP_SETLIST,2,i,1); *pc++ = CREATE_ABC(OP_RETURN,1,3,0); *pc++ = CREATE_ABC(OP_RETURN,0,1,0); } lua_assert((pc-f->code) == f->sizecode); return f; } }
void ravi_dump_function(lua_State *L) { Proto* f; f = toproto(L, -1); ravi_print_function(f, 1); }