2 ** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $
3 ** load precompiled Ekto chunks
4 ** See Copyright Notice in ekto.h
14 #include "ekto_debug.h"
16 #include "ekto_func.h"
18 #include "ekto_object.h"
19 #include "ekto_string.h"
20 #include "ekto_undump.h"
30 #ifdef EKTOC_TRUST_BINARIES
34 #define IF(c,s) if (c) error(S,s)
36 static void error(LoadState
* S
, const char* why
)
38 ektoO_pushfstring(S
->L
,"%s: %s in precompiled chunk",S
->name
,why
);
39 ektoD_throw(S
->L
,EKTO_ERRSYNTAX
);
43 #define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size))
44 #define LoadByte(S) (lu_byte)LoadChar(S)
45 #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x))
46 #define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
48 static void LoadBlock(LoadState
* S
, void* b
, uint32_t size
)
50 uint32_t r
=ektoZ_read(S
->Z
,b
,size
);
51 IF (r
!=0, "unexpected end");
54 static int LoadChar(LoadState
* S
)
61 static int LoadInt(LoadState
* S
)
66 #ifdef WORDS_BIGENDIAN
67 uint32_t z
= bswap_32 (*y
);
71 IF (z
<0, "bad integer");
75 static ekto_Number
LoadNumber(LoadState
* S
)
80 #ifdef WORDS_BIGENDIAN
81 uint64_t z
= bswap_64 (*y
);
88 static TString
* LoadString(LoadState
* S
)
96 char* s
=ektoZ_openspace(S
->L
,S
->b
,size
);
98 return ektoS_newlstr(S
->L
,s
,size
-1); /* remove trailing '\0' */
102 static void LoadCode(LoadState
* S
, Proto
* f
)
105 f
->code
=ektoM_newvector(S
->L
,n
,Instruction
);
107 LoadVector(S
,f
->code
,n
,sizeof(Instruction
));
110 static Proto
* LoadFunction(LoadState
* S
, TString
* p
);
112 static void LoadConstants(LoadState
* S
, Proto
* f
)
116 f
->k
=ektoM_newvector(S
->L
,n
,TValue
);
118 for (i
=0; i
<n
; i
++) setnilvalue(&f
->k
[i
]);
129 setbvalue(o
,LoadChar(S
)!=0);
132 setnvalue(o
,LoadNumber(S
));
135 setsvalue2n(S
->L
,o
,LoadString(S
));
138 error(S
,"bad constant");
143 f
->p
=ektoM_newvector(S
->L
,n
,Proto
*);
145 for (i
=0; i
<n
; i
++) f
->p
[i
]=NULL
;
146 for (i
=0; i
<n
; i
++) f
->p
[i
]=LoadFunction(S
,f
->source
);
149 static void LoadDebug(LoadState
* S
, Proto
* f
)
153 f
->lineinfo
=ektoM_newvector(S
->L
,n
,int);
155 LoadVector(S
,f
->lineinfo
,n
,sizeof(int));
157 f
->locvars
=ektoM_newvector(S
->L
,n
,LocVar
);
159 for (i
=0; i
<n
; i
++) f
->locvars
[i
].varname
=NULL
;
162 f
->locvars
[i
].varname
=LoadString(S
);
163 f
->locvars
[i
].startpc
=LoadInt(S
);
164 f
->locvars
[i
].endpc
=LoadInt(S
);
167 f
->upvalues
=ektoM_newvector(S
->L
,n
,TString
*);
169 for (i
=0; i
<n
; i
++) f
->upvalues
[i
]=NULL
;
170 for (i
=0; i
<n
; i
++) f
->upvalues
[i
]=LoadString(S
);
173 static Proto
* LoadFunction(LoadState
* S
, TString
* p
)
176 if (++S
->L
->nCcalls
> EKTOI_MAXCCALLS
) error(S
,"code too deep");
177 f
=ektoF_newproto(S
->L
);
178 setptvalue2s(S
->L
,S
->L
->top
,f
); incr_top(S
->L
);
179 f
->source
=LoadString(S
); if (f
->source
==NULL
) f
->source
=p
;
180 f
->linedefined
=LoadInt(S
);
181 f
->lastlinedefined
=LoadInt(S
);
183 f
->numparams
=LoadByte(S
);
184 f
->is_vararg
=LoadByte(S
);
185 f
->maxstacksize
=LoadByte(S
);
189 IF (!ektoG_checkcode(f
), "bad code");
195 static void LoadHeader(LoadState
* S
)
197 char h
[EKTOC_HEADERSIZE
];
198 char s
[EKTOC_HEADERSIZE
];
200 LoadBlock(S
,s
,EKTOC_HEADERSIZE
);
201 IF (memcmp(h
,s
,EKTOC_HEADERSIZE
)!=0, "bad header");
205 ** load precompiled chunk
207 Proto
* ektoU_undump (ekto_State
* L
, ZIO
* Z
, Mbuffer
* buff
, const char* name
)
210 if (*name
=='@' || *name
=='=')
212 else if (*name
==EKTO_SIGNATURE
[0])
213 S
.name
="binary string";
220 return LoadFunction(&S
,ektoS_newliteral(L
,"=?"));
226 void ektoU_header (char* h
)
229 memcpy(h
,EKTO_SIGNATURE
,sizeof(EKTO_SIGNATURE
)-1);
230 h
+=sizeof(EKTO_SIGNATURE
)-1;
231 *h
++=(char)EKTOC_VERSION
;
232 *h
++=(char)EKTOC_FORMAT
;
233 *h
++=(char)*(char*)&x
; /* endianness */
234 *h
++=(char)sizeof(int);
235 *h
++=(char)sizeof(uint32_t);
236 *h
++=(char)sizeof(Instruction
);
237 *h
++=(char)sizeof(ekto_Number
);
238 *h
++=(char)(((ekto_Number
)0.5)==0); /* is ekto_Number integral? */