442ea5b5e12c4e29822d5e946aeab7ec5b101b91
[p5sagit/p5-mst-13.2.git] / ext / ByteLoader / bytecode.h
1 typedef char *pvcontents;
2 typedef char *strconst;
3 typedef U32 PV;
4 typedef char *op_tr_array;
5 typedef int comment_t;
6 typedef SV *svindex;
7 typedef OP *opindex;
8 typedef IV IV64;
9
10 #define BGET_FREAD(argp, len, nelem)    \
11          bs.fread((char*)(argp),(len),(nelem),bs.data)
12 #define BGET_FGETC() bs.fgetc(bs.data)
13
14 #define BGET_U32(arg)   \
15         BGET_FREAD(&arg, sizeof(U32), 1); arg = PerlSock_ntohl((U32)arg)
16 #define BGET_I32(arg)   \
17         BGET_FREAD(&arg, sizeof(I32), 1); arg = (I32)PerlSock_ntohl((U32)arg)
18 #define BGET_U16(arg)   \
19         BGET_FREAD(&arg, sizeof(U16), 1); arg = PerlSock_ntohs((U16)arg)
20 #define BGET_U8(arg)    arg = BGET_FGETC()
21
22 #define BGET_PV(arg)    STMT_START {    \
23         BGET_U32(arg);                  \
24         if (arg)                        \
25             bs.freadpv(arg, bs.data, &bytecode_pv);     \
26         else {                          \
27             bytecode_pv.xpv_pv = 0;             \
28             bytecode_pv.xpv_len = 0;            \
29             bytecode_pv.xpv_cur = 0;            \
30         }                               \
31     } STMT_END
32
33 #define BGET_comment_t(arg) \
34         do { arg = BGET_FGETC(); } while (arg != '\n' && arg != EOF)
35
36 /*
37  * In the following, sizeof(IV)*4 is just a way of encoding 32 on 64-bit-IV
38  * machines such that 32-bit machine compilers don't whine about the shift
39  * count being too high even though the code is never reached there.
40  */
41 #define BGET_IV64(arg) STMT_START {                     \
42         U32 hi, lo;                                     \
43         BGET_U32(hi);                                   \
44         BGET_U32(lo);                                   \
45         if (sizeof(IV) == 8)                            \
46             arg = (IV) (hi << (sizeof(IV)*4) | lo);     \
47         else if (((I32)hi == -1 && (I32)lo < 0)         \
48                  || ((I32)hi == 0 && (I32)lo >= 0)) {   \
49             arg = (I32)lo;                              \
50         }                                               \
51         else {                                          \
52             bytecode_iv_overflows++;                            \
53             arg = 0;                                    \
54         }                                               \
55     } STMT_END
56
57 #define BGET_op_tr_array(arg) do {      \
58         unsigned short *ary;            \
59         int i;                          \
60         New(666, ary, 256, unsigned short); \
61         BGET_FREAD(ary, 256, 2);        \
62         for (i = 0; i < 256; i++)       \
63             ary[i] = PerlSock_ntohs(ary[i]);    \
64         arg = (char *) ary;             \
65     } while (0)
66
67 #define BGET_pvcontents(arg)    arg = bytecode_pv.xpv_pv
68 #define BGET_strconst(arg) STMT_START { \
69         for (arg = PL_tokenbuf; (*arg = BGET_FGETC()); arg++) /* nothing */; \
70         arg = PL_tokenbuf;                      \
71     } STMT_END
72
73 #define BGET_double(arg) STMT_START {   \
74         char *str;                      \
75         BGET_strconst(str);             \
76         arg = atof(str);                \
77     } STMT_END
78
79 #define BGET_objindex(arg, type) STMT_START {   \
80         U32 ix;                                 \
81         BGET_U32(ix);                           \
82         arg = (type)bytecode_obj_list[ix];              \
83     } STMT_END
84 #define BGET_svindex(arg) BGET_objindex(arg, svindex)
85 #define BGET_opindex(arg) BGET_objindex(arg, opindex)
86
87 #define BSET_ldspecsv(sv, arg) sv = specialsv_list[arg]
88                                     
89 #define BSET_sv_refcnt_add(svrefcnt, arg)       svrefcnt += arg
90 #define BSET_gp_refcnt_add(gprefcnt, arg)       gprefcnt += arg
91 #define BSET_gp_share(sv, arg) STMT_START {     \
92         gp_free((GV*)sv);                       \
93         GvGP(sv) = GvGP(arg);                   \
94     } STMT_END
95
96 #define BSET_gv_fetchpv(sv, arg)        sv = (SV*)gv_fetchpv(arg, TRUE, SVt_PV)
97 #define BSET_gv_stashpv(sv, arg)        sv = (SV*)gv_stashpv(arg, TRUE)
98 #define BSET_sv_magic(sv, arg)          sv_magic(sv, Nullsv, arg, 0, 0)
99 #define BSET_mg_pv(mg, arg)     mg->mg_ptr = arg; mg->mg_len = bytecode_pv.xpv_cur
100 #define BSET_sv_upgrade(sv, arg)        (void)SvUPGRADE(sv, arg)
101 #define BSET_xpv(sv)    do {    \
102         SvPV_set(sv, bytecode_pv.xpv_pv);       \
103         SvCUR_set(sv, bytecode_pv.xpv_cur);     \
104         SvLEN_set(sv, bytecode_pv.xpv_len);     \
105     } while (0)
106 #define BSET_av_extend(sv, arg) av_extend((AV*)sv, arg)
107
108 #define BSET_av_push(sv, arg)   av_push((AV*)sv, arg)
109 #define BSET_hv_store(sv, arg)  \
110         hv_store((HV*)sv, bytecode_pv.xpv_pv, bytecode_pv.xpv_cur, arg, 0)
111 #define BSET_pv_free(pv)        Safefree(pv.xpv_pv)
112 #define BSET_pregcomp(o, arg) \
113         ((PMOP*)o)->op_pmregexp = arg ? \
114                 CALLREGCOMP(arg, arg + bytecode_pv.xpv_cur, ((PMOP*)o)) : 0
115 #define BSET_newsv(sv, arg)     sv = NEWSV(666,0); SvUPGRADE(sv, arg)
116 #define BSET_newop(o, arg)      o = (OP*)safemalloc(optype_size[arg])
117 #define BSET_newopn(o, arg) STMT_START {        \
118         OP *oldop = o;                          \
119         BSET_newop(o, arg);                     \
120         oldop->op_next = o;                     \
121     } STMT_END
122
123 #define BSET_ret(foo) return
124
125 /*
126  * Kludge special-case workaround for OP_MAPSTART
127  * which needs the ppaddr for OP_GREPSTART. Blech.
128  */
129 #define BSET_op_type(o, arg) STMT_START {       \
130         o->op_type = arg;                       \
131         if (arg == OP_MAPSTART)                 \
132             arg = OP_GREPSTART;                 \
133         o->op_ppaddr = PL_ppaddr[arg];          \
134     } STMT_END
135 #define BSET_op_ppaddr(o, arg) croak("op_ppaddr not yet implemented")
136 #define BSET_curpad(pad, arg) STMT_START {      \
137         PL_comppad = (AV *)arg;                 \
138         pad = AvARRAY(arg);                     \
139     } STMT_END
140
141 #define BSET_OBJ_STORE(obj, ix)         \
142         (I32)ix > bytecode_obj_list_fill ?      \
143         bset_obj_store(obj, (I32)ix) : (bytecode_obj_list[ix] = obj)
144 typedef char *pvcontents;
145 typedef char *strconst;
146 typedef U32 PV;
147 typedef char *op_tr_array;
148 typedef int comment_t;
149 typedef SV *svindex;
150 typedef OP *opindex;
151 typedef IV IV64;
152
153 #define BGET_FREAD(argp, len, nelem)    \
154          bs.fread((char*)(argp),(len),(nelem),bs.data)
155 #define BGET_FGETC() bs.fgetc(bs.data)
156
157 #define BGET_U32(arg)   \
158         BGET_FREAD(&arg, sizeof(U32), 1); arg = PerlSock_ntohl((U32)arg)
159 #define BGET_I32(arg)   \
160         BGET_FREAD(&arg, sizeof(I32), 1); arg = (I32)PerlSock_ntohl((U32)arg)
161 #define BGET_U16(arg)   \
162         BGET_FREAD(&arg, sizeof(U16), 1); arg = PerlSock_ntohs((U16)arg)
163 #define BGET_U8(arg)    arg = BGET_FGETC()
164
165 #define BGET_PV(arg)    STMT_START {    \
166         BGET_U32(arg);                  \
167         if (arg)                        \
168             bs.freadpv(arg, bs.data, &bytecode_pv);     \
169         else {                          \
170             bytecode_pv.xpv_pv = 0;             \
171             bytecode_pv.xpv_len = 0;            \
172             bytecode_pv.xpv_cur = 0;            \
173         }                               \
174     } STMT_END
175
176 #define BGET_comment_t(arg) \
177         do { arg = BGET_FGETC(); } while (arg != '\n' && arg != EOF)
178
179 /*
180  * In the following, sizeof(IV)*4 is just a way of encoding 32 on 64-bit-IV
181  * machines such that 32-bit machine compilers don't whine about the shift
182  * count being too high even though the code is never reached there.
183  */
184 #define BGET_IV64(arg) STMT_START {                     \
185         U32 hi, lo;                                     \
186         BGET_U32(hi);                                   \
187         BGET_U32(lo);                                   \
188         if (sizeof(IV) == 8)                            \
189             arg = (IV) (hi << (sizeof(IV)*4) | lo);     \
190         else if (((I32)hi == -1 && (I32)lo < 0)         \
191                  || ((I32)hi == 0 && (I32)lo >= 0)) {   \
192             arg = (I32)lo;                              \
193         }                                               \
194         else {                                          \
195             bytecode_iv_overflows++;                            \
196             arg = 0;                                    \
197         }                                               \
198     } STMT_END
199
200 #define BGET_op_tr_array(arg) do {      \
201         unsigned short *ary;            \
202         int i;                          \
203         New(666, ary, 256, unsigned short); \
204         BGET_FREAD(ary, 256, 2);        \
205         for (i = 0; i < 256; i++)       \
206             ary[i] = PerlSock_ntohs(ary[i]);    \
207         arg = (char *) ary;             \
208     } while (0)
209
210 #define BGET_pvcontents(arg)    arg = bytecode_pv.xpv_pv
211 #define BGET_strconst(arg) STMT_START { \
212         for (arg = PL_tokenbuf; (*arg = BGET_FGETC()); arg++) /* nothing */; \
213         arg = PL_tokenbuf;                      \
214     } STMT_END
215
216 #define BGET_double(arg) STMT_START {   \
217         char *str;                      \
218         BGET_strconst(str);             \
219         arg = atof(str);                \
220     } STMT_END
221
222 #define BGET_objindex(arg, type) STMT_START {   \
223         U32 ix;                                 \
224         BGET_U32(ix);                           \
225         arg = (type)bytecode_obj_list[ix];              \
226     } STMT_END
227 #define BGET_svindex(arg) BGET_objindex(arg, svindex)
228 #define BGET_opindex(arg) BGET_objindex(arg, opindex)
229
230 #define BSET_ldspecsv(sv, arg) sv = specialsv_list[arg]
231                                     
232 #define BSET_sv_refcnt_add(svrefcnt, arg)       svrefcnt += arg
233 #define BSET_gp_refcnt_add(gprefcnt, arg)       gprefcnt += arg
234 #define BSET_gp_share(sv, arg) STMT_START {     \
235         gp_free((GV*)sv);                       \
236         GvGP(sv) = GvGP(arg);                   \
237     } STMT_END
238
239 #define BSET_gv_fetchpv(sv, arg)        sv = (SV*)gv_fetchpv(arg, TRUE, SVt_PV)
240 #define BSET_gv_stashpv(sv, arg)        sv = (SV*)gv_stashpv(arg, TRUE)
241 #define BSET_sv_magic(sv, arg)          sv_magic(sv, Nullsv, arg, 0, 0)
242 #define BSET_mg_pv(mg, arg)     mg->mg_ptr = arg; mg->mg_len = bytecode_pv.xpv_cur
243 #define BSET_sv_upgrade(sv, arg)        (void)SvUPGRADE(sv, arg)
244 #define BSET_xpv(sv)    do {    \
245         SvPV_set(sv, bytecode_pv.xpv_pv);       \
246         SvCUR_set(sv, bytecode_pv.xpv_cur);     \
247         SvLEN_set(sv, bytecode_pv.xpv_len);     \
248     } while (0)
249 #define BSET_av_extend(sv, arg) av_extend((AV*)sv, arg)
250
251 #define BSET_av_push(sv, arg)   av_push((AV*)sv, arg)
252 #define BSET_hv_store(sv, arg)  \
253         hv_store((HV*)sv, bytecode_pv.xpv_pv, bytecode_pv.xpv_cur, arg, 0)
254 #define BSET_pv_free(pv)        Safefree(pv.xpv_pv)
255 #define BSET_pregcomp(o, arg) \
256         ((PMOP*)o)->op_pmregexp = arg ? \
257                 CALLREGCOMP(arg, arg + bytecode_pv.xpv_cur, ((PMOP*)o)) : 0
258 #define BSET_newsv(sv, arg)     sv = NEWSV(666,0); SvUPGRADE(sv, arg)
259 #define BSET_newop(o, arg)      o = (OP*)safemalloc(optype_size[arg])
260 #define BSET_newopn(o, arg) STMT_START {        \
261         OP *oldop = o;                          \
262         BSET_newop(o, arg);                     \
263         oldop->op_next = o;                     \
264     } STMT_END
265
266 #define BSET_ret(foo) return
267
268 /*
269  * Kludge special-case workaround for OP_MAPSTART
270  * which needs the ppaddr for OP_GREPSTART. Blech.
271  */
272 #define BSET_op_type(o, arg) STMT_START {       \
273         o->op_type = arg;                       \
274         if (arg == OP_MAPSTART)                 \
275             arg = OP_GREPSTART;                 \
276         o->op_ppaddr = PL_ppaddr[arg];          \
277     } STMT_END
278 #define BSET_op_ppaddr(o, arg) croak("op_ppaddr not yet implemented")
279 #define BSET_curpad(pad, arg) STMT_START {      \
280         PL_comppad = (AV *)arg;                 \
281         pad = AvARRAY(arg);                     \
282     } STMT_END
283
284 #define BSET_OBJ_STORE(obj, ix)         \
285         (I32)ix > bytecode_obj_list_fill ?      \
286         bset_obj_store(obj, (I32)ix) : (bytecode_obj_list[ix] = obj)
287 typedef char *pvcontents;
288 typedef char *strconst;
289 typedef U32 PV;
290 typedef char *op_tr_array;
291 typedef int comment_t;
292 typedef SV *svindex;
293 typedef OP *opindex;
294 typedef IV IV64;
295
296 #define BGET_FREAD(argp, len, nelem)    \
297          bs.fread((char*)(argp),(len),(nelem),bs.data)
298 #define BGET_FGETC() bs.fgetc(bs.data)
299
300 #define BGET_U32(arg)   \
301         BGET_FREAD(&arg, sizeof(U32), 1); arg = PerlSock_ntohl((U32)arg)
302 #define BGET_I32(arg)   \
303         BGET_FREAD(&arg, sizeof(I32), 1); arg = (I32)PerlSock_ntohl((U32)arg)
304 #define BGET_U16(arg)   \
305         BGET_FREAD(&arg, sizeof(U16), 1); arg = PerlSock_ntohs((U16)arg)
306 #define BGET_U8(arg)    arg = BGET_FGETC()
307
308 #define BGET_PV(arg)    STMT_START {    \
309         BGET_U32(arg);                  \
310         if (arg)                        \
311             bs.freadpv(arg, bs.data, &bytecode_pv);     \
312         else {                          \
313             bytecode_pv.xpv_pv = 0;             \
314             bytecode_pv.xpv_len = 0;            \
315             bytecode_pv.xpv_cur = 0;            \
316         }                               \
317     } STMT_END
318
319 #define BGET_comment_t(arg) \
320         do { arg = BGET_FGETC(); } while (arg != '\n' && arg != EOF)
321
322 /*
323  * In the following, sizeof(IV)*4 is just a way of encoding 32 on 64-bit-IV
324  * machines such that 32-bit machine compilers don't whine about the shift
325  * count being too high even though the code is never reached there.
326  */
327 #define BGET_IV64(arg) STMT_START {                     \
328         U32 hi, lo;                                     \
329         BGET_U32(hi);                                   \
330         BGET_U32(lo);                                   \
331         if (sizeof(IV) == 8)                            \
332             arg = (IV) (hi << (sizeof(IV)*4) | lo);     \
333         else if (((I32)hi == -1 && (I32)lo < 0)         \
334                  || ((I32)hi == 0 && (I32)lo >= 0)) {   \
335             arg = (I32)lo;                              \
336         }                                               \
337         else {                                          \
338             bytecode_iv_overflows++;                            \
339             arg = 0;                                    \
340         }                                               \
341     } STMT_END
342
343 #define BGET_op_tr_array(arg) do {      \
344         unsigned short *ary;            \
345         int i;                          \
346         New(666, ary, 256, unsigned short); \
347         BGET_FREAD(ary, 256, 2);        \
348         for (i = 0; i < 256; i++)       \
349             ary[i] = PerlSock_ntohs(ary[i]);    \
350         arg = (char *) ary;             \
351     } while (0)
352
353 #define BGET_pvcontents(arg)    arg = bytecode_pv.xpv_pv
354 #define BGET_strconst(arg) STMT_START { \
355         for (arg = PL_tokenbuf; (*arg = BGET_FGETC()); arg++) /* nothing */; \
356         arg = PL_tokenbuf;                      \
357     } STMT_END
358
359 #define BGET_double(arg) STMT_START {   \
360         char *str;                      \
361         BGET_strconst(str);             \
362         arg = atof(str);                \
363     } STMT_END
364
365 #define BGET_objindex(arg, type) STMT_START {   \
366         U32 ix;                                 \
367         BGET_U32(ix);                           \
368         arg = (type)bytecode_obj_list[ix];              \
369     } STMT_END
370 #define BGET_svindex(arg) BGET_objindex(arg, svindex)
371 #define BGET_opindex(arg) BGET_objindex(arg, opindex)
372
373 #define BSET_ldspecsv(sv, arg) sv = specialsv_list[arg]
374                                     
375 #define BSET_sv_refcnt_add(svrefcnt, arg)       svrefcnt += arg
376 #define BSET_gp_refcnt_add(gprefcnt, arg)       gprefcnt += arg
377 #define BSET_gp_share(sv, arg) STMT_START {     \
378         gp_free((GV*)sv);                       \
379         GvGP(sv) = GvGP(arg);                   \
380     } STMT_END
381
382 #define BSET_gv_fetchpv(sv, arg)        sv = (SV*)gv_fetchpv(arg, TRUE, SVt_PV)
383 #define BSET_gv_stashpv(sv, arg)        sv = (SV*)gv_stashpv(arg, TRUE)
384 #define BSET_sv_magic(sv, arg)          sv_magic(sv, Nullsv, arg, 0, 0)
385 #define BSET_mg_pv(mg, arg)     mg->mg_ptr = arg; mg->mg_len = bytecode_pv.xpv_cur
386 #define BSET_sv_upgrade(sv, arg)        (void)SvUPGRADE(sv, arg)
387 #define BSET_xpv(sv)    do {    \
388         SvPV_set(sv, bytecode_pv.xpv_pv);       \
389         SvCUR_set(sv, bytecode_pv.xpv_cur);     \
390         SvLEN_set(sv, bytecode_pv.xpv_len);     \
391     } while (0)
392 #define BSET_av_extend(sv, arg) av_extend((AV*)sv, arg)
393
394 #define BSET_av_push(sv, arg)   av_push((AV*)sv, arg)
395 #define BSET_hv_store(sv, arg)  \
396         hv_store((HV*)sv, bytecode_pv.xpv_pv, bytecode_pv.xpv_cur, arg, 0)
397 #define BSET_pv_free(pv)        Safefree(pv.xpv_pv)
398 #define BSET_pregcomp(o, arg) \
399         ((PMOP*)o)->op_pmregexp = arg ? \
400                 CALLREGCOMP(arg, arg + bytecode_pv.xpv_cur, ((PMOP*)o)) : 0
401 #define BSET_newsv(sv, arg)     sv = NEWSV(666,0); SvUPGRADE(sv, arg)
402 #define BSET_newop(o, arg)      o = (OP*)safemalloc(optype_size[arg])
403 #define BSET_newopn(o, arg) STMT_START {        \
404         OP *oldop = o;                          \
405         BSET_newop(o, arg);                     \
406         oldop->op_next = o;                     \
407     } STMT_END
408
409 #define BSET_ret(foo) return
410
411 /*
412  * Kludge special-case workaround for OP_MAPSTART
413  * which needs the ppaddr for OP_GREPSTART. Blech.
414  */
415 #define BSET_op_type(o, arg) STMT_START {       \
416         o->op_type = arg;                       \
417         if (arg == OP_MAPSTART)                 \
418             arg = OP_GREPSTART;                 \
419         o->op_ppaddr = PL_ppaddr[arg];          \
420     } STMT_END
421 #define BSET_op_ppaddr(o, arg) croak("op_ppaddr not yet implemented")
422 #define BSET_curpad(pad, arg) STMT_START {      \
423         PL_comppad = (AV *)arg;                 \
424         pad = AvARRAY(arg);                     \
425     } STMT_END
426
427 #define BSET_OBJ_STORE(obj, ix)         \
428         (I32)ix > bytecode_obj_list_fill ?      \
429         bset_obj_store(obj, (I32)ix) : (bytecode_obj_list[ix] = obj)