lundump.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*
  2. ** $Id: lundump.c,v 1.4 1998/01/13 20:05:24 lhf Exp $
  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. typedef struct {
  13. ZIO* Z;
  14. int SwapNumber;
  15. int LoadFloat;
  16. } Sundump;
  17. static void unexpectedEOZ(ZIO* Z)
  18. {
  19. luaL_verror("unexpected end of binary file %s",Z->name);
  20. }
  21. static int ezgetc(ZIO* Z)
  22. {
  23. int c=zgetc(Z);
  24. if (c==EOZ) unexpectedEOZ(Z);
  25. return c;
  26. }
  27. static int ezread(ZIO* Z, void* b, int n)
  28. {
  29. int r=zread(Z,b,n);
  30. if (r!=0) unexpectedEOZ(Z);
  31. return r;
  32. }
  33. static int LoadWord(ZIO* Z)
  34. {
  35. int hi=ezgetc(Z);
  36. int lo=ezgetc(Z);
  37. return (hi<<8)|lo;
  38. }
  39. static void* LoadBlock(int size, ZIO* Z)
  40. {
  41. void* b=luaM_malloc(size);
  42. ezread(Z,b,size);
  43. return b;
  44. }
  45. static int LoadSize(ZIO* Z)
  46. {
  47. int hi=LoadWord(Z);
  48. int lo=LoadWord(Z);
  49. int s=(hi<<16)|lo;
  50. if (hi!=0 && s==lo)
  51. luaL_verror("code too long (%ld bytes)",(hi<<16)|(long)lo);
  52. return s;
  53. }
  54. static char* LoadString(ZIO* Z)
  55. {
  56. int size=LoadWord(Z);
  57. if (size==0)
  58. return NULL;
  59. else
  60. {
  61. char* b=luaL_openspace(size);
  62. ezread(Z,b,size);
  63. return b;
  64. }
  65. }
  66. static TaggedString* LoadTString(ZIO* Z)
  67. {
  68. char* s=LoadString(Z);
  69. return (s==NULL) ? NULL : luaS_new(s);
  70. }
  71. static void SwapFloat(float* f)
  72. {
  73. Byte* p=(Byte*)f;
  74. Byte* q=p+sizeof(float)-1;
  75. Byte t;
  76. t=*p; *p++=*q; *q--=t;
  77. t=*p; *p++=*q; *q--=t;
  78. }
  79. static void SwapDouble(double* f)
  80. {
  81. Byte* p=(Byte*)f;
  82. Byte* q=p+sizeof(double)-1;
  83. Byte t;
  84. t=*p; *p++=*q; *q--=t;
  85. t=*p; *p++=*q; *q--=t;
  86. t=*p; *p++=*q; *q--=t;
  87. t=*p; *p++=*q; *q--=t;
  88. }
  89. static real LoadNumber(Sundump* S)
  90. {
  91. if (S->LoadFloat)
  92. {
  93. float f;
  94. ezread(S->Z,&f,sizeof(f));
  95. if (S->SwapNumber) SwapFloat(&f);
  96. return f;
  97. }
  98. else
  99. {
  100. double f;
  101. ezread(S->Z,&f,sizeof(f));
  102. if (S->SwapNumber) SwapDouble(&f);
  103. return f;
  104. }
  105. }
  106. static void LoadLocals(TProtoFunc* tf, ZIO* Z)
  107. {
  108. int i,n=LoadWord(Z);
  109. if (n==0) return;
  110. tf->locvars=luaM_newvector(n+1,LocVar);
  111. for (i=0; i<n; i++)
  112. {
  113. tf->locvars[i].line=LoadWord(Z);
  114. tf->locvars[i].varname=LoadTString(Z);
  115. }
  116. tf->locvars[i].line=-1; /* flag end of vector */
  117. tf->locvars[i].varname=NULL;
  118. }
  119. static void LoadConstants(TProtoFunc* tf, Sundump* S)
  120. {
  121. int i,n=LoadWord(S->Z);
  122. tf->nconsts=n;
  123. if (n==0) return;
  124. tf->consts=luaM_newvector(n,TObject);
  125. for (i=0; i<n; i++)
  126. {
  127. TObject* o=tf->consts+i;
  128. int c=ezgetc(S->Z);
  129. switch (c)
  130. {
  131. case ID_NUM:
  132. ttype(o)=LUA_T_NUMBER;
  133. nvalue(o)=LoadNumber(S);
  134. break;
  135. case ID_STR:
  136. ttype(o)=LUA_T_STRING;
  137. tsvalue(o)=LoadTString(S->Z);
  138. break;
  139. case ID_FUN:
  140. ttype(o)=LUA_T_PROTO;
  141. tfvalue(o)=NULL;
  142. break;
  143. #ifdef DEBUG
  144. default: /* cannot happen */
  145. luaL_verror("internal error in LoadConstants: "
  146. "bad constant #%d type=%d ('%c')\n",i,c,c);
  147. break;
  148. #endif
  149. }
  150. }
  151. }
  152. static TProtoFunc* LoadFunction(Sundump* S);
  153. static void LoadFunctions(TProtoFunc* tf, Sundump* S)
  154. {
  155. while (zgetc(S->Z)==ID_FUNCTION)
  156. {
  157. int i=LoadWord(S->Z);
  158. TProtoFunc* t=LoadFunction(S);
  159. TObject* o=tf->consts+i;
  160. tfvalue(o)=t;
  161. }
  162. }
  163. static TProtoFunc* LoadFunction(Sundump* S)
  164. {
  165. ZIO* Z=S->Z;
  166. TProtoFunc* tf=luaF_newproto();
  167. tf->lineDefined=LoadWord(Z);
  168. tf->fileName=LoadTString(Z);
  169. tf->code=LoadBlock(LoadSize(Z),Z);
  170. LoadConstants(tf,S);
  171. LoadLocals(tf,Z);
  172. LoadFunctions(tf,S);
  173. return tf;
  174. }
  175. static void LoadSignature(ZIO* Z)
  176. {
  177. char* s=SIGNATURE;
  178. while (*s!=0 && ezgetc(Z)==*s)
  179. ++s;
  180. if (*s!=0) luaL_verror("bad signature in binary file %s",Z->name);
  181. }
  182. static void LoadHeader(Sundump* S)
  183. {
  184. ZIO* Z=S->Z;
  185. int version,sizeofR;
  186. LoadSignature(Z);
  187. version=ezgetc(Z);
  188. if (version>VERSION)
  189. luaL_verror(
  190. "binary file %s too new: version=0x%02x; expected at most 0x%02x",
  191. Z->name,version,VERSION);
  192. if (version<0x31) /* major change in 3.1 */
  193. luaL_verror(
  194. "binary file %s too old: version=0x%02x; expected at least 0x%02x",
  195. Z->name,version,0x31);
  196. sizeofR=ezgetc(Z); /* test float representation */
  197. if (sizeofR==sizeof(float))
  198. {
  199. float f,tf=TEST_FLOAT;
  200. ezread(Z,&f,sizeof(f));
  201. if (f!=tf)
  202. {
  203. SwapFloat(&f);
  204. if (f!=tf)
  205. luaL_verror("unknown float representation in binary file %s",Z->name);
  206. S->SwapNumber=1;
  207. }
  208. S->LoadFloat=1;
  209. }
  210. else if (sizeofR==sizeof(double))
  211. {
  212. double f,tf=TEST_FLOAT;
  213. ezread(Z,&f,sizeof(f));
  214. if (f!=tf)
  215. {
  216. SwapDouble(&f);
  217. if (f!=tf)
  218. luaL_verror("unknown float representation in binary file %s",Z->name);
  219. S->SwapNumber=1;
  220. }
  221. S->LoadFloat=0;
  222. }
  223. else
  224. luaL_verror(
  225. "floats in binary file %s have %d bytes; "
  226. "expected %d (float) or %d (double)",
  227. Z->name,sizeofR,sizeof(float),sizeof(double));
  228. }
  229. static TProtoFunc* LoadChunk(Sundump* S)
  230. {
  231. LoadHeader(S);
  232. return LoadFunction(S);
  233. }
  234. /*
  235. ** load one chunk from a file or buffer
  236. ** return main if ok and NULL at EOF
  237. */
  238. TProtoFunc* luaU_undump1(ZIO* Z)
  239. {
  240. int c=zgetc(Z);
  241. Sundump S;
  242. S.Z=Z;
  243. S.SwapNumber=0;
  244. S.LoadFloat=1;
  245. if (c==ID_CHUNK)
  246. return LoadChunk(&S);
  247. else if (c!=EOZ)
  248. luaL_verror("%s is not a lua binary file",Z->name);
  249. return NULL;
  250. }