lundump.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. ** $Id: lundump.c,v 1.7 1998/03/05 15:45:08 lhf Exp lhf $
  3. ** load bytecodes from files
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <stdio.h>
  7. #include "lauxlib.h"
  8. #include "lfunc.h"
  9. #include "lmem.h"
  10. #include "lstring.h"
  11. #include "lundump.h"
  12. #define LoadBlock(b,size,Z) ezread(Z,b,size)
  13. #define LoadNative(t,D) LoadBlock(&t,sizeof(t),D)
  14. /* LUA_NUMBER */
  15. /* if you change the definition of real, make sure you set ID_NUMBER
  16. * accordingly lundump.h, specially if sizeof(long)!=4.
  17. * for types other than the ones listed below, you'll have to write your own
  18. * dump and undump routines.
  19. */
  20. #if ID_NUMBER==ID_REAL4
  21. #define LoadNumber LoadFloat
  22. #elif ID_NUMBER==ID_REAL8
  23. #define LoadNumber LoadDouble
  24. #elif ID_NUMBER==ID_INT4
  25. #define LoadNumber LoadLong
  26. #elif ID_NUMBER==ID_NATIVE
  27. #define LoadNumber LoadNative
  28. #else
  29. #define LoadNumber LoadWhat
  30. #endif
  31. static void unexpectedEOZ(ZIO* Z)
  32. {
  33. luaL_verror("unexpected end of file in %s",zname(Z));
  34. }
  35. static int ezgetc(ZIO* Z)
  36. {
  37. int c=zgetc(Z);
  38. if (c==EOZ) unexpectedEOZ(Z);
  39. return c;
  40. }
  41. static void ezread(ZIO* Z, void* b, int n)
  42. {
  43. int r=zread(Z,b,n);
  44. if (r!=0) unexpectedEOZ(Z);
  45. }
  46. static unsigned int LoadWord(ZIO* Z)
  47. {
  48. unsigned int hi=ezgetc(Z);
  49. unsigned int lo=ezgetc(Z);
  50. return (hi<<8)|lo;
  51. }
  52. static unsigned long LoadLong(ZIO* Z)
  53. {
  54. unsigned long hi=LoadWord(Z);
  55. unsigned long lo=LoadWord(Z);
  56. return (hi<<16)|lo;
  57. }
  58. /* LUA_NUMBER */
  59. /* assumes sizeof(long)==4 and sizeof(float)==4 (IEEE) */
  60. static float LoadFloat(ZIO* Z)
  61. {
  62. long l=LoadLong(Z);
  63. float f=*(float*)&l;
  64. return f;
  65. }
  66. /* LUA_NUMBER */
  67. /* assumes sizeof(long)==4 and sizeof(double)==8 (IEEE) */
  68. static double LoadDouble(ZIO* Z)
  69. {
  70. long l[2];
  71. double f;
  72. int x=1;
  73. if (*(char*)&x==1) /* little-endian */
  74. {
  75. l[1]=LoadLong(Z);
  76. l[0]=LoadLong(Z);
  77. }
  78. else /* big-endian */
  79. {
  80. l[0]=LoadLong(Z);
  81. l[1]=LoadLong(Z);
  82. }
  83. f=*(double*)l;
  84. return f;
  85. }
  86. static Byte* LoadCode(ZIO* Z)
  87. {
  88. long size=LoadLong(Z);
  89. unsigned int s=size;
  90. void* b;
  91. if (s!=size) luaL_verror("code too long (%ld bytes) in %s",size,zname(Z));
  92. b=luaM_malloc(size);
  93. LoadBlock(b,size,Z);
  94. return b;
  95. }
  96. static TaggedString* LoadTString(ZIO* Z)
  97. {
  98. int size=LoadWord(Z);
  99. if (size==0)
  100. return NULL;
  101. else
  102. {
  103. char* s=luaL_openspace(size);
  104. LoadBlock(s,size,Z);
  105. return luaS_newlstr(s,size-1);
  106. }
  107. }
  108. static void LoadLocals(TProtoFunc* tf, ZIO* Z)
  109. {
  110. int i,n=LoadWord(Z);
  111. if (n==0) return;
  112. tf->locvars=luaM_newvector(n+1,LocVar);
  113. for (i=0; i<n; i++)
  114. {
  115. tf->locvars[i].line=LoadWord(Z);
  116. tf->locvars[i].varname=LoadTString(Z);
  117. }
  118. tf->locvars[i].line=-1; /* flag end of vector */
  119. tf->locvars[i].varname=NULL;
  120. }
  121. static TProtoFunc* LoadFunction(ZIO* Z);
  122. static void LoadConstants(TProtoFunc* tf, ZIO* Z)
  123. {
  124. int i,n=LoadWord(Z);
  125. tf->nconsts=n;
  126. if (n==0) return;
  127. tf->consts=luaM_newvector(n,TObject);
  128. for (i=0; i<n; i++)
  129. {
  130. TObject* o=tf->consts+i;
  131. int c=ezgetc(Z);
  132. switch (c)
  133. {
  134. case ID_NUM:
  135. ttype(o)=LUA_T_NUMBER;
  136. #if ID_NUMBER==ID_NATIVE
  137. LoadNative(nvalue(o),Z)
  138. #else
  139. nvalue(o)=LoadNumber(Z);
  140. #endif
  141. break;
  142. case ID_STR:
  143. ttype(o)=LUA_T_STRING;
  144. tsvalue(o)=LoadTString(Z);
  145. break;
  146. case ID_FUN:
  147. ttype(o)=LUA_T_PROTO;
  148. tfvalue(o)=LoadFunction(Z);
  149. break;
  150. default:
  151. luaL_verror("bad constant #%d in %s: type=%d ('%c')",i,zname(Z),c,c);
  152. break;
  153. }
  154. }
  155. }
  156. static TProtoFunc* LoadFunction(ZIO* Z)
  157. {
  158. TProtoFunc* tf=luaF_newproto();
  159. tf->lineDefined=LoadWord(Z);
  160. tf->fileName=LoadTString(Z);
  161. tf->code=LoadCode(Z);
  162. LoadLocals(tf,Z);
  163. LoadConstants(tf,Z);
  164. return tf;
  165. }
  166. static void LoadSignature(ZIO* Z)
  167. {
  168. char* s=SIGNATURE;
  169. while (*s!=0 && ezgetc(Z)==*s)
  170. ++s;
  171. if (*s!=0) luaL_verror("bad signature in %s",zname(Z));
  172. }
  173. static void LoadHeader(ZIO* Z)
  174. {
  175. int version,id,sizeofR;
  176. real f=-TEST_NUMBER,tf=TEST_NUMBER;
  177. LoadSignature(Z);
  178. version=ezgetc(Z);
  179. if (version>VERSION)
  180. luaL_verror(
  181. "%s too new: version=0x%02x; expected at most 0x%02x",
  182. zname(Z),version,VERSION);
  183. if (version<0x31) /* major change in 3.1 */
  184. luaL_verror(
  185. "%s too old: version=0x%02x; expected at least 0x%02x",
  186. zname(Z),version,0x31);
  187. id=ezgetc(Z); /* test number representation */
  188. sizeofR=ezgetc(Z);
  189. if (id!=ID_NUMBER || sizeofR!=sizeof(real))
  190. {
  191. luaL_verror("unknown number representation in %s: "
  192. "read 0x%02x %d; expected 0x%02x %d",
  193. zname(Z),id,sizeofR,ID_NUMBER,sizeof(real));
  194. }
  195. f=LoadNumber(Z);
  196. if (f!=tf)
  197. luaL_verror("unknown number representation in %s: "
  198. "read %g; expected %g", /* LUA_NUMBER */
  199. zname(Z),(double)f,(double)tf);
  200. }
  201. static TProtoFunc* LoadChunk(ZIO* Z)
  202. {
  203. LoadHeader(Z);
  204. return LoadFunction(Z);
  205. }
  206. /*
  207. ** load one chunk from a file or buffer
  208. ** return main if ok and NULL at EOF
  209. */
  210. TProtoFunc* luaU_undump1(ZIO* Z)
  211. {
  212. int c=zgetc(Z);
  213. if (c==ID_CHUNK)
  214. return LoadChunk(Z);
  215. else if (c!=EOZ)
  216. luaL_verror("%s is not a Lua binary file",zname(Z));
  217. return NULL;
  218. }