lundump.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. ** $Id: lundump.c,v 1.19 1999/04/15 12:30:03 lhf Exp lhf $
  3. ** load bytecodes from files
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include "lauxlib.h"
  9. #include "lfunc.h"
  10. #include "lmem.h"
  11. #include "lopcodes.h"
  12. #include "lstring.h"
  13. #include "lundump.h"
  14. #define LoadBlock(b,size,Z) ezread(Z,b,size)
  15. static void unexpectedEOZ (ZIO* Z)
  16. {
  17. luaL_verror("unexpected end of file in %s",zname(Z));
  18. }
  19. static int ezgetc (ZIO* Z)
  20. {
  21. int c=zgetc(Z);
  22. if (c==EOZ) unexpectedEOZ(Z);
  23. return c;
  24. }
  25. static void ezread (ZIO* Z, void* b, int n)
  26. {
  27. int r=zread(Z,b,n);
  28. if (r!=0) unexpectedEOZ(Z);
  29. }
  30. static unsigned int LoadWord (ZIO* Z)
  31. {
  32. unsigned int hi=ezgetc(Z);
  33. unsigned int lo=ezgetc(Z);
  34. return (hi<<8)|lo;
  35. }
  36. static unsigned long LoadLong (ZIO* Z)
  37. {
  38. unsigned long hi=LoadWord(Z);
  39. unsigned long lo=LoadWord(Z);
  40. return (hi<<16)|lo;
  41. }
  42. static real LoadNumber (ZIO* Z)
  43. {
  44. #ifdef LUAC_NATIVE
  45. real x;
  46. LoadBlock(&x,sizeof(x),Z);
  47. return x;
  48. #else
  49. char b[256];
  50. int size=ezgetc(Z);
  51. LoadBlock(b,size,Z);
  52. b[size]=0;
  53. if (b[0]=='-')
  54. return -luaO_str2d(b+1);
  55. else
  56. return luaO_str2d(b);
  57. #endif
  58. }
  59. static int LoadInt (ZIO* Z, char* message)
  60. {
  61. unsigned long l=LoadLong(Z);
  62. unsigned int i=l;
  63. if (i!=l) luaL_verror(message,l,zname(Z));
  64. return i;
  65. }
  66. #define PAD 5 /* two word operands plus opcode */
  67. static Byte* LoadCode (ZIO* Z)
  68. {
  69. int size=LoadInt(Z,"code too long (%ld bytes) in %s");
  70. Byte* b=luaM_malloc(size+PAD);
  71. LoadBlock(b,size,Z);
  72. if (b[size-1]!=ENDCODE) luaL_verror("bad code in %s",zname(Z));
  73. memset(b+size,ENDCODE,PAD); /* pad code for safety */
  74. return b;
  75. }
  76. static TaggedString* LoadTString (ZIO* Z)
  77. {
  78. long size=LoadLong(Z);
  79. if (size==0)
  80. return NULL;
  81. else
  82. {
  83. char* s=luaL_openspace(size);
  84. LoadBlock(s,size,Z);
  85. return luaS_newlstr(s,size-1);
  86. }
  87. }
  88. static void LoadLocals (TProtoFunc* tf, ZIO* Z)
  89. {
  90. int i,n=LoadInt(Z,"too many locals (%ld) in %s");
  91. if (n==0) return;
  92. tf->locvars=luaM_newvector(n+1,LocVar);
  93. for (i=0; i<n; i++)
  94. {
  95. tf->locvars[i].line=LoadInt(Z,"too many lines (%ld) in %s");
  96. tf->locvars[i].varname=LoadTString(Z);
  97. }
  98. tf->locvars[i].line=-1; /* flag end of vector */
  99. tf->locvars[i].varname=NULL;
  100. }
  101. static TProtoFunc* LoadFunction (ZIO* Z);
  102. static void LoadConstants (TProtoFunc* tf, ZIO* Z)
  103. {
  104. int i,n=LoadInt(Z,"too many constants (%ld) in %s");
  105. tf->nconsts=n;
  106. if (n==0) return;
  107. tf->consts=luaM_newvector(n,TObject);
  108. for (i=0; i<n; i++)
  109. {
  110. TObject* o=tf->consts+i;
  111. ttype(o)=-ezgetc(Z); /* ttype(o) is negative - ORDER LUA_T */
  112. switch (ttype(o))
  113. {
  114. case LUA_T_NUMBER:
  115. nvalue(o)=LoadNumber(Z);
  116. break;
  117. case LUA_T_STRING:
  118. tsvalue(o)=LoadTString(Z);
  119. break;
  120. case LUA_T_PROTO:
  121. tfvalue(o)=LoadFunction(Z);
  122. break;
  123. case LUA_T_NIL:
  124. break;
  125. default: /* cannot happen */
  126. luaU_badconstant("load",i,o,tf);
  127. break;
  128. }
  129. }
  130. }
  131. static TProtoFunc* LoadFunction (ZIO* Z)
  132. {
  133. TProtoFunc* tf=luaF_newproto();
  134. tf->lineDefined=LoadInt(Z,"lineDefined too large (%ld) in %s");
  135. tf->source=LoadTString(Z);
  136. if (tf->source==NULL) tf->source=luaS_new(zname(Z));
  137. tf->code=LoadCode(Z);
  138. LoadLocals(tf,Z);
  139. LoadConstants(tf,Z);
  140. return tf;
  141. }
  142. static void LoadSignature (ZIO* Z)
  143. {
  144. char* s=SIGNATURE;
  145. while (*s!=0 && ezgetc(Z)==*s)
  146. ++s;
  147. if (*s!=0) luaL_verror("bad signature in %s",zname(Z));
  148. }
  149. static void LoadHeader (ZIO* Z)
  150. {
  151. int version,sizeofR;
  152. LoadSignature(Z);
  153. version=ezgetc(Z);
  154. if (version>VERSION)
  155. luaL_verror(
  156. "%s too new: version=0x%02x; expected at most 0x%02x",
  157. zname(Z),version,VERSION);
  158. if (version<VERSION0) /* check last major change */
  159. luaL_verror(
  160. "%s too old: version=0x%02x; expected at least 0x%02x",
  161. zname(Z),version,VERSION0);
  162. sizeofR=ezgetc(Z); /* test number representation */
  163. #ifdef LUAC_NATIVE
  164. if (sizeofR==0)
  165. luaL_verror("cannot read numbers in %s: no support for decimal format",
  166. zname(Z));
  167. if (sizeofR!=sizeof(real))
  168. luaL_verror("unknown number size in %s: read %d; expected %d",
  169. zname(Z),sizeofR,sizeof(real));
  170. else
  171. {
  172. real f=-TEST_NUMBER,tf=TEST_NUMBER;
  173. f=LoadNumber(Z);
  174. if ((long)f!=(long)tf)
  175. luaL_verror("unknown number format in %s: "
  176. "read " NUMBER_FMT "; expected " NUMBER_FMT,
  177. zname(Z),f,tf);
  178. }
  179. #else
  180. if (sizeofR!=0)
  181. luaL_verror("cannot read numbers in %s: no support for native format",
  182. zname(Z));
  183. #endif
  184. }
  185. static TProtoFunc* LoadChunk (ZIO* Z)
  186. {
  187. LoadHeader(Z);
  188. return LoadFunction(Z);
  189. }
  190. /*
  191. ** load one chunk from a file or buffer
  192. ** return main if ok and NULL at EOF
  193. */
  194. TProtoFunc* luaU_undump1 (ZIO* Z)
  195. {
  196. int c=zgetc(Z);
  197. if (c==ID_CHUNK)
  198. return LoadChunk(Z);
  199. else if (c!=EOZ)
  200. luaL_verror("%s is not a Lua binary file",zname(Z));
  201. return NULL;
  202. }
  203. /*
  204. * handle constants that cannot happen
  205. */
  206. void luaU_badconstant (char* s, int i, TObject* o, TProtoFunc* tf)
  207. {
  208. int t=ttype(o);
  209. char* name= (t>0 || t<LUA_T_LINE) ? "?" : luaO_typenames[-t];
  210. luaL_verror("cannot %s constant #%d: type=%d [%s]" IN,s,i,t,name,INLOC);
  211. }