?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2. ** $Id: lundump.c $
  3. ** load precompiled Lua chunks
  4. ** See Copyright Notice in lua.h
  5. */
  6.  
  7. #define lundump_c
  8. #define LUA_CORE
  9.  
  10. #include "lprefix.h"
  11.  
  12.  
  13. #include <limits.h>
  14. #include <string.h>
  15.  
  16. #include "lua.h"
  17.  
  18. #include "ldebug.h"
  19. #include "ldo.h"
  20. #include "lfunc.h"
  21. #include "lmem.h"
  22. #include "lobject.h"
  23. #include "lstring.h"
  24. #include "lundump.h"
  25. #include "lzio.h"
  26.  
  27.  
  28. #if !defined(luai_verifycode)
  29. #define luai_verifycode(L,f)  /* empty */
  30. #endif
  31.  
  32.  
  33. typedef struct {
  34.   lua_State *L;
  35.   ZIO *Z;
  36.   const char *name;
  37. } LoadState;
  38.  
  39.  
  40. static l_noret error (LoadState *S, const char *why) {
  41.   luaO_pushfstring(S->L, "%s: bad binary format (%s)", S->name, why);
  42.   luaD_throw(S->L, LUA_ERRSYNTAX);
  43. }
  44.  
  45.  
  46. /*
  47. ** All high-level loads go through loadVector; you can change it to
  48. ** adapt to the endianness of the input
  49. */
  50. #define loadVector(S,b,n)       loadBlock(S,b,(n)*sizeof((b)[0]))
  51.  
  52. static void loadBlock (LoadState *S, void *b, size_t size) {
  53.   if (luaZ_read(S->Z, b, size) != 0)
  54.     error(S, "truncated chunk");
  55. }
  56.  
  57.  
  58. #define loadVar(S,x)            loadVector(S,&x,1)
  59.  
  60.  
  61. static lu_byte loadByte (LoadState *S) {
  62.   int b = zgetc(S->Z);
  63.   if (b == EOZ)
  64.     error(S, "truncated chunk");
  65.   return cast_byte(b);
  66. }
  67.  
  68.  
  69. static size_t loadUnsigned (LoadState *S, size_t limit) {
  70.   size_t x = 0;
  71.   int b;
  72.   limit >>= 7;
  73.   do {
  74.     b = loadByte(S);
  75.     if (x >= limit)
  76.       error(S, "integer overflow");
  77.     x = (x << 7) | (b & 0x7f);
  78.   } while ((b & 0x80) == 0);
  79.   return x;
  80. }
  81.  
  82.  
  83. static size_t loadSize (LoadState *S) {
  84.   return loadUnsigned(S, ~(size_t)0);
  85. }
  86.  
  87.  
  88. static int loadInt (LoadState *S) {
  89.   return cast_int(loadUnsigned(S, INT_MAX));
  90. }
  91.  
  92.  
  93. static lua_Number loadNumber (LoadState *S) {
  94.   lua_Number x;
  95.   loadVar(S, x);
  96.   return x;
  97. }
  98.  
  99.  
  100. static lua_Integer loadInteger (LoadState *S) {
  101.   lua_Integer x;
  102.   loadVar(S, x);
  103.   return x;
  104. }
  105.  
  106.  
  107. /*
  108. ** Load a nullable string into prototype 'p'.
  109. */
  110. static TString *loadStringN (LoadState *S, Proto *p) {
  111.   lua_State *L = S->L;
  112.   TString *ts;
  113.   size_t size = loadSize(S);
  114.   if (size == 0)  /* no string? */
  115.     return NULL;
  116.   else if (--size <= LUAI_MAXSHORTLEN) {  /* short string? */
  117.     char buff[LUAI_MAXSHORTLEN];
  118.     loadVector(S, buff, size);  /* load string into buffer */
  119.     ts = luaS_newlstr(L, buff, size);  /* create string */
  120.   }
  121.   else {  /* long string */
  122.     ts = luaS_createlngstrobj(L, size);  /* create string */
  123.     setsvalue2s(L, L->top, ts);  /* anchor it ('loadVector' can GC) */
  124.     luaD_inctop(L);
  125.     loadVector(S, getstr(ts), size);  /* load directly in final place */
  126.     L->top--;  /* pop string */
  127.   }
  128.   luaC_objbarrier(L, p, ts);
  129.   return ts;
  130. }
  131.  
  132.  
  133. /*
  134. ** Load a non-nullable string into prototype 'p'.
  135. */
  136. static TString *loadString (LoadState *S, Proto *p) {
  137.   TString *st = loadStringN(S, p);
  138.   if (st == NULL)
  139.     error(S, "bad format for constant string");
  140.   return st;
  141. }
  142.  
  143.  
  144. static void loadCode (LoadState *S, Proto *f) {
  145.   int n = loadInt(S);
  146.   f->code = luaM_newvectorchecked(S->L, n, Instruction);
  147.   f->sizecode = n;
  148.   loadVector(S, f->code, n);
  149. }
  150.  
  151.  
  152. static void loadFunction(LoadState *S, Proto *f, TString *psource);
  153.  
  154.  
  155. static void loadConstants (LoadState *S, Proto *f) {
  156.   int i;
  157.   int n = loadInt(S);
  158.   f->k = luaM_newvectorchecked(S->L, n, TValue);
  159.   f->sizek = n;
  160.   for (i = 0; i < n; i++)
  161.     setnilvalue(&f->k[i]);
  162.   for (i = 0; i < n; i++) {
  163.     TValue *o = &f->k[i];
  164.     int t = loadByte(S);
  165.     switch (t) {
  166.       case LUA_VNIL:
  167.         setnilvalue(o);
  168.         break;
  169.       case LUA_VFALSE:
  170.         setbfvalue(o);
  171.         break;
  172.       case LUA_VTRUE:
  173.         setbtvalue(o);
  174.         break;
  175.       case LUA_VNUMFLT:
  176.         setfltvalue(o, loadNumber(S));
  177.         break;
  178.       case LUA_VNUMINT:
  179.         setivalue(o, loadInteger(S));
  180.         break;
  181.       case LUA_VSHRSTR:
  182.       case LUA_VLNGSTR:
  183.         setsvalue2n(S->L, o, loadString(S, f));
  184.         break;
  185.       default: lua_assert(0);
  186.     }
  187.   }
  188. }
  189.  
  190.  
  191. static void loadProtos (LoadState *S, Proto *f) {
  192.   int i;
  193.   int n = loadInt(S);
  194.   f->p = luaM_newvectorchecked(S->L, n, Proto *);
  195.   f->sizep = n;
  196.   for (i = 0; i < n; i++)
  197.     f->p[i] = NULL;
  198.   for (i = 0; i < n; i++) {
  199.     f->p[i] = luaF_newproto(S->L);
  200.     luaC_objbarrier(S->L, f, f->p[i]);
  201.     loadFunction(S, f->p[i], f->source);
  202.   }
  203. }
  204.  
  205.  
  206. /*
  207. ** Load the upvalues for a function. The names must be filled first,
  208. ** because the filling of the other fields can raise read errors and
  209. ** the creation of the error message can call an emergency collection;
  210. ** in that case all prototypes must be consistent for the GC.
  211. */
  212. static void loadUpvalues (LoadState *S, Proto *f) {
  213.   int i, n;
  214.   n = loadInt(S);
  215.   f->upvalues = luaM_newvectorchecked(S->L, n, Upvaldesc);
  216.   f->sizeupvalues = n;
  217.   for (i = 0; i < n; i++)  /* make array valid for GC */
  218.     f->upvalues[i].name = NULL;
  219.   for (i = 0; i < n; i++) {  /* following calls can raise errors */
  220.     f->upvalues[i].instack = loadByte(S);
  221.     f->upvalues[i].idx = loadByte(S);
  222.     f->upvalues[i].kind = loadByte(S);
  223.   }
  224. }
  225.  
  226.  
  227. static void loadDebug (LoadState *S, Proto *f) {
  228.   int i, n;
  229.   n = loadInt(S);
  230.   f->lineinfo = luaM_newvectorchecked(S->L, n, ls_byte);
  231.   f->sizelineinfo = n;
  232.   loadVector(S, f->lineinfo, n);
  233.   n = loadInt(S);
  234.   f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo);
  235.   f->sizeabslineinfo = n;
  236.   for (i = 0; i < n; i++) {
  237.     f->abslineinfo[i].pc = loadInt(S);
  238.     f->abslineinfo[i].line = loadInt(S);
  239.   }
  240.   n = loadInt(S);
  241.   f->locvars = luaM_newvectorchecked(S->L, n, LocVar);
  242.   f->sizelocvars = n;
  243.   for (i = 0; i < n; i++)
  244.     f->locvars[i].varname = NULL;
  245.   for (i = 0; i < n; i++) {
  246.     f->locvars[i].varname = loadStringN(S, f);
  247.     f->locvars[i].startpc = loadInt(S);
  248.     f->locvars[i].endpc = loadInt(S);
  249.   }
  250.   n = loadInt(S);
  251.   for (i = 0; i < n; i++)
  252.     f->upvalues[i].name = loadStringN(S, f);
  253. }
  254.  
  255.  
  256. static void loadFunction (LoadState *S, Proto *f, TString *psource) {
  257.   f->source = loadStringN(S, f);
  258.   if (f->source == NULL)  /* no source in dump? */
  259.     f->source = psource;  /* reuse parent's source */
  260.   f->linedefined = loadInt(S);
  261.   f->lastlinedefined = loadInt(S);
  262.   f->numparams = loadByte(S);
  263.   f->is_vararg = loadByte(S);
  264.   f->maxstacksize = loadByte(S);
  265.   loadCode(S, f);
  266.   loadConstants(S, f);
  267.   loadUpvalues(S, f);
  268.   loadProtos(S, f);
  269.   loadDebug(S, f);
  270. }
  271.  
  272.  
  273. static void checkliteral (LoadState *S, const char *s, const char *msg) {
  274.   char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */
  275.   size_t len = strlen(s);
  276.   loadVector(S, buff, len);
  277.   if (memcmp(s, buff, len) != 0)
  278.     error(S, msg);
  279. }
  280.  
  281.  
  282. static void fchecksize (LoadState *S, size_t size, const char *tname) {
  283.   if (loadByte(S) != size)
  284.     error(S, luaO_pushfstring(S->L, "%s size mismatch", tname));
  285. }
  286.  
  287.  
  288. #define checksize(S,t)  fchecksize(S,sizeof(t),#t)
  289.  
  290. static void checkHeader (LoadState *S) {
  291.   /* skip 1st char (already read and checked) */
  292.   checkliteral(S, &LUA_SIGNATURE[1], "not a binary chunk");
  293.   if (loadByte(S) != LUAC_VERSION)
  294.     error(S, "version mismatch");
  295.   if (loadByte(S) != LUAC_FORMAT)
  296.     error(S, "format mismatch");
  297.   checkliteral(S, LUAC_DATA, "corrupted chunk");
  298.   checksize(S, Instruction);
  299.   checksize(S, lua_Integer);
  300.   checksize(S, lua_Number);
  301.   if (loadInteger(S) != LUAC_INT)
  302.     error(S, "integer format mismatch");
  303.   if (loadNumber(S) != LUAC_NUM)
  304.     error(S, "float format mismatch");
  305. }
  306.  
  307.  
  308. /*
  309. ** Load precompiled chunk.
  310. */
  311. LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) {
  312.   LoadState S;
  313.   LClosure *cl;
  314.   if (*name == '@' || *name == '=')
  315.     S.name = name + 1;
  316.   else if (*name == LUA_SIGNATURE[0])
  317.     S.name = "binary string";
  318.   else
  319.     S.name = name;
  320.   S.L = L;
  321.   S.Z = Z;
  322.   checkHeader(&S);
  323.   cl = luaF_newLclosure(L, loadByte(&S));
  324.   setclLvalue2s(L, L->top, cl);
  325.   luaD_inctop(L);
  326.   cl->p = luaF_newproto(L);
  327.   luaC_objbarrier(L, cl, cl->p);
  328.   loadFunction(&S, cl->p, NULL);
  329.   lua_assert(cl->nupvalues == cl->p->sizeupvalues);
  330.   luai_verifycode(L, cl->p);
  331.   return cl;
  332. }
  333.  
  334.