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 char *pvindex;
9 
10 #define BGET_FREAD(argp, len, nelem)	\
11 	 bl_read(bstate->bs_fdata,(char*)(argp),(len),(nelem))
12 #define BGET_FGETC() bl_getc(bstate->bs_fdata)
13 
14 /* all this should be made endianness-agnostic */
15 
16 #define BGET_U8(arg)	arg = BGET_FGETC()
17 #define BGET_U16(arg)	\
18 	BGET_FREAD(&arg, sizeof(U16), 1)
19 #define BGET_U32(arg)	\
20 	BGET_FREAD(&arg, sizeof(U32), 1)
21 #define BGET_UV(arg)	\
22 	BGET_FREAD(&arg, sizeof(UV), 1)
23 #define BGET_PADOFFSET(arg)	\
24 	BGET_FREAD(&arg, sizeof(PADOFFSET), 1)
25 #define BGET_long(arg)		\
26 	BGET_FREAD(&arg, sizeof(long), 1)
27 
28 #define BGET_I32(arg)	BGET_U32(arg)
29 #define BGET_IV(arg)	BGET_UV(arg)
30 
31 #define BGET_PV(arg)	STMT_START {					\
32 	BGET_U32(arg);							\
33 	if (arg) {							\
34 	    Newx(bstate->bs_pv.xpv_pv, arg, char);			\
35 	    bl_read(bstate->bs_fdata, bstate->bs_pv.xpv_pv, arg, 1);	\
36 	    bstate->bs_pv.xpv_len = arg;				\
37 	    bstate->bs_pv.xpv_cur = arg - 1;				\
38 	} else {							\
39 	    bstate->bs_pv.xpv_pv = 0;					\
40 	    bstate->bs_pv.xpv_len = 0;					\
41 	    bstate->bs_pv.xpv_cur = 0;					\
42 	}								\
43     } STMT_END
44 
45 #ifdef BYTELOADER_LOG_COMMENTS
46 #  define BGET_comment_t(arg) \
47     STMT_START {							\
48 	char buf[1024];							\
49 	int i = 0;							\
50 	do {								\
51 	    arg = BGET_FGETC();						\
52 	    buf[i++] = (char)arg;					\
53 	} while (arg != '\n' && arg != EOF);				\
54 	buf[i] = '\0';							\
55 	PerlIO_printf(PerlIO_stderr(), "%s", buf);			\
56     } STMT_END
57 #else
58 #  define BGET_comment_t(arg) \
59 	do { arg = BGET_FGETC(); } while (arg != '\n' && arg != EOF)
60 #endif
61 
62 
63 #define BGET_op_tr_array(arg) do {			\
64 	unsigned short *ary, len;			\
65 	BGET_U16(len);					\
66 	Newx(ary, len, unsigned short);		\
67 	BGET_FREAD(ary, sizeof(unsigned short), len);	\
68 	arg = (char *) ary;				\
69     } while (0)
70 
71 #define BGET_pvcontents(arg)	arg = bstate->bs_pv.xpv_pv
72 #define BGET_strconst(arg) STMT_START {	\
73 	for (arg = PL_tokenbuf; (*arg = BGET_FGETC()); arg++) /* nothing */; \
74 	arg = PL_tokenbuf;			\
75     } STMT_END
76 
77 #define BGET_NV(arg) STMT_START {	\
78 	char *str;			\
79 	BGET_strconst(str);		\
80 	arg = Atof(str);		\
81     } STMT_END
82 
83 #define BGET_objindex(arg, type) STMT_START {	\
84 	BGET_U32(ix);				\
85 	arg = (type)bstate->bs_obj_list[ix];	\
86     } STMT_END
87 #define BGET_svindex(arg) BGET_objindex(arg, svindex)
88 #define BGET_opindex(arg) BGET_objindex(arg, opindex)
89 #define BGET_pvindex(arg) STMT_START {			\
90 	BGET_objindex(arg, pvindex);			\
91 	arg = arg ? savepv(arg) : arg;			\
92     } STMT_END
93 
94 #define BSET_ldspecsv(sv, arg) sv = specialsv_list[arg]
95 #define BSET_ldspecsvx(sv, arg) STMT_START {	\
96 	BSET_ldspecsv(sv, arg);			\
97 	BSET_OBJ_STOREX(sv);			\
98     } STMT_END
99 
100 #define BSET_stpv(pv, arg) STMT_START {		\
101 	BSET_OBJ_STORE(pv, arg);		\
102 	SAVEFREEPV(pv);				\
103     } STMT_END
104 
105 #define BSET_sv_refcnt_add(svrefcnt, arg)	svrefcnt += arg
106 #define BSET_gp_refcnt_add(gprefcnt, arg)	gprefcnt += arg
107 #define BSET_gp_share(sv, arg) STMT_START {	\
108 	gp_free((GV*)sv);			\
109 	GvGP(sv) = GvGP(arg);			\
110     } STMT_END
111 
112 #define BSET_gv_fetchpv(sv, arg)	sv = (SV*)gv_fetchpv(arg, TRUE, SVt_PV)
113 #define BSET_gv_fetchpvx(sv, arg) STMT_START {	\
114 	BSET_gv_fetchpv(sv, arg);		\
115 	BSET_OBJ_STOREX(sv);			\
116     } STMT_END
117 
118 #define BSET_gv_stashpv(sv, arg)	sv = (SV*)gv_stashpv(arg, TRUE)
119 #define BSET_gv_stashpvx(sv, arg) STMT_START {	\
120 	BSET_gv_stashpv(sv, arg);		\
121 	BSET_OBJ_STOREX(sv);			\
122     } STMT_END
123 
124 #define BSET_sv_magic(sv, arg)		sv_magic(sv, Nullsv, arg, 0, 0)
125 #define BSET_mg_name(mg, arg)	mg->mg_ptr = arg; mg->mg_len = bstate->bs_pv.xpv_cur
126 #define BSET_mg_namex(mg, arg)			\
127 	(mg->mg_ptr = (char*)SvREFCNT_inc((SV*)arg),	\
128 	 mg->mg_len = HEf_SVKEY)
129 #define BSET_xmg_stash(sv, arg) *(SV**)&(((XPVMG*)SvANY(sv))->xmg_stash) = (arg)
130 #define BSET_sv_upgrade(sv, arg)	(void)SvUPGRADE(sv, arg)
131 #define BSET_xrv(sv, arg) SvRV_set(sv, arg)
132 #define BSET_xpv(sv)	do {	\
133 	SvPV_set(sv, bstate->bs_pv.xpv_pv);	\
134 	SvCUR_set(sv, bstate->bs_pv.xpv_cur);	\
135 	SvLEN_set(sv, bstate->bs_pv.xpv_len);	\
136     } while (0)
137 #define BSET_xpv_cur(sv, arg) SvCUR_set(sv, arg)
138 #define BSET_xpv_len(sv, arg) SvLEN_set(sv, arg)
139 #define BSET_xiv(sv, arg) SvIV_set(sv, arg)
140 #define BSET_xnv(sv, arg) SvNV_set(sv, arg)
141 
142 #define BSET_av_extend(sv, arg)	av_extend((AV*)sv, arg)
143 
144 #define BSET_av_push(sv, arg)	av_push((AV*)sv, arg)
145 #define BSET_av_pushx(sv, arg)	(AvARRAY(sv)[++AvFILLp(sv)] = arg)
146 #define BSET_hv_store(sv, arg)	\
147 	hv_store((HV*)sv, bstate->bs_pv.xpv_pv, bstate->bs_pv.xpv_cur, arg, 0)
148 #define BSET_pv_free(pv)	Safefree(pv.xpv_pv)
149 
150 
151 #ifdef USE_ITHREADS
152 
153 /* copied after the code in newPMOP() */
154 #define BSET_pregcomp(o, arg) \
155     STMT_START { \
156         SV* repointer; \
157 	REGEXP* rx = arg ? \
158 	    CALLREGCOMP(aTHX_ arg, arg + bstate->bs_pv.xpv_cur, cPMOPx(o)) : \
159 	    Null(REGEXP*); \
160         if(av_len((AV*) PL_regex_pad[0]) > -1) { \
161             repointer = av_pop((AV*)PL_regex_pad[0]); \
162             cPMOPx(o)->op_pmoffset = SvIV(repointer); \
163             SvREPADTMP_off(repointer); \
164             sv_setiv(repointer,PTR2IV(rx)); \
165         } else { \
166             repointer = newSViv(PTR2IV(rx)); \
167             av_push(PL_regex_padav,SvREFCNT_inc(repointer)); \
168             cPMOPx(o)->op_pmoffset = av_len(PL_regex_padav); \
169             PL_regex_pad = AvARRAY(PL_regex_padav); \
170         } \
171     } STMT_END
172 
173 #else
174 #define BSET_pregcomp(o, arg) \
175     STMT_START { \
176 	PM_SETRE(((PMOP*)o), (arg ? \
177 	     CALLREGCOMP(aTHX_ arg, arg + bstate->bs_pv.xpv_cur, cPMOPx(o)): \
178 	     Null(REGEXP*))); \
179     } STMT_END
180 
181 #endif /* USE_THREADS */
182 
183 
184 #define BSET_newsv(sv, arg)				\
185 	    switch(arg) {				\
186 	    case SVt_PVAV:				\
187 		sv = (SV*)newAV();			\
188 		break;					\
189 	    case SVt_PVHV:				\
190 		sv = (SV*)newHV();			\
191 		break;					\
192 	    default:					\
193 		sv = NEWSV(0,0);			\
194 		SvUPGRADE(sv, (arg));			\
195 	    }
196 #define BSET_newsvx(sv, arg) STMT_START {		\
197 	    BSET_newsv(sv, arg &  SVTYPEMASK);		\
198 	    SvFLAGS(sv) = arg;				\
199 	    BSET_OBJ_STOREX(sv);			\
200 	} STMT_END
201 
202 #define BSET_newop(o, arg)	NewOpSz(666, o, arg)
203 #define BSET_newopx(o, arg) STMT_START {	\
204 	register int sz = arg & 0x7f;		\
205 	register OP* newop;			\
206 	BSET_newop(newop, sz);			\
207 	/* newop->op_next = o; XXX */		\
208 	o = newop;				\
209 	arg >>=7;				\
210 	BSET_op_type(o, arg);			\
211 	BSET_OBJ_STOREX(o);			\
212     } STMT_END
213 
214 #define BSET_newopn(o, arg) STMT_START {	\
215 	OP *oldop = o;				\
216 	BSET_newop(o, arg);			\
217 	oldop->op_next = o;			\
218     } STMT_END
219 
220 #define BSET_ret(foo) STMT_START {		\
221 	Safefree(bstate->bs_obj_list);		\
222 	return 0;				\
223     } STMT_END
224 
225 #define BSET_op_pmstashpv(op, arg)	PmopSTASHPV_set(op, arg)
226 
227 /*
228  * stolen from toke.c: better if that was a function.
229  * in toke.c there are also #ifdefs for dosish systems and i/o layers
230  */
231 
232 #if defined(HAS_FCNTL) && defined(F_SETFD)
233 #define set_clonex(fp)				\
234 	STMT_START {				\
235 	    int fd = PerlIO_fileno(fp);		\
236 	    fcntl(fd,F_SETFD,fd >= 3);		\
237 	} STMT_END
238 #else
239 #define set_clonex(fp)
240 #endif
241 
242 #define BSET_data(dummy,arg)						\
243     STMT_START {							\
244 	GV *gv;								\
245 	char *pname = "main";						\
246 	if (arg == 'D')							\
247 	    pname = HvNAME(PL_curstash ? PL_curstash : PL_defstash);	\
248 	gv = gv_fetchpv(Perl_form(aTHX_ "%s::DATA", pname), TRUE, SVt_PVIO);\
249 	GvMULTI_on(gv);							\
250 	if (!GvIO(gv))							\
251 	    GvIOp(gv) = newIO();					\
252 	IoIFP(GvIOp(gv)) = PL_rsfp;					\
253 	set_clonex(PL_rsfp);						\
254 	/* Mark this internal pseudo-handle as clean */			\
255 	IoFLAGS(GvIOp(gv)) |= IOf_UNTAINT;				\
256 	if (PL_preprocess)						\
257 	    IoTYPE(GvIOp(gv)) = IoTYPE_PIPE;				\
258 	else if ((PerlIO*)PL_rsfp == PerlIO_stdin())			\
259 	    IoTYPE(GvIOp(gv)) = IoTYPE_STD;				\
260 	else								\
261 	    IoTYPE(GvIOp(gv)) = IoTYPE_RDONLY;				\
262 	Safefree(bstate->bs_obj_list);					\
263 	return 1;							\
264     } STMT_END
265 
266 /* stolen from op.c */
267 #define BSET_load_glob(foo, gv)						\
268     STMT_START {							\
269         GV *glob_gv;							\
270         ENTER;								\
271         Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT,			\
272                 newSVpvn("File::Glob", 10), Nullsv, Nullsv, Nullsv);	\
273         glob_gv = gv_fetchpv("File::Glob::csh_glob", FALSE, SVt_PVCV);	\
274         GvCV(gv) = GvCV(glob_gv);					\
275         SvREFCNT_inc((SV*)GvCV(gv));					\
276         GvIMPORTED_CV_on(gv);						\
277         LEAVE;								\
278     } STMT_END
279 
280 /*
281  * Kludge special-case workaround for OP_MAPSTART
282  * which needs the ppaddr for OP_GREPSTART. Blech.
283  */
284 #define BSET_op_type(o, arg) STMT_START {	\
285 	o->op_type = arg;			\
286 	if (arg == OP_MAPSTART)			\
287 	    arg = OP_GREPSTART;			\
288 	o->op_ppaddr = PL_ppaddr[arg];		\
289     } STMT_END
290 #define BSET_op_ppaddr(o, arg) Perl_croak(aTHX_ "op_ppaddr not yet implemented")
291 #define BSET_curpad(pad, arg) STMT_START {	\
292 	PL_comppad = (AV *)arg;			\
293 	pad = AvARRAY(arg);			\
294     } STMT_END
295 
296 #ifdef USE_ITHREADS
297 #define BSET_cop_file(cop, arg)		CopFILE_set(cop,arg)
298 #define BSET_cop_stashpv(cop, arg)	CopSTASHPV_set(cop,arg)
299 #else
300 /* this works now that Sarathy's changed the CopFILE_set macro to do the SvREFCNT_inc()
301 	-- BKS 6-2-2000 */
302 /* that really meant the actual CopFILEGV_set */
303 #define BSET_cop_filegv(cop, arg)	CopFILEGV_set(cop,arg)
304 #define BSET_cop_stash(cop,arg)		CopSTASH_set(cop,(HV*)arg)
305 #endif
306 
307 /* this is simply stolen from the code in newATTRSUB() */
308 #define BSET_push_begin(ary,cv)				\
309 	STMT_START {					\
310             I32 oldscope = PL_scopestack_ix;		\
311             ENTER;					\
312             SAVECOPFILE(&PL_compiling);			\
313             SAVECOPLINE(&PL_compiling);			\
314             if (!PL_beginav)				\
315                 PL_beginav = newAV();			\
316             av_push(PL_beginav, (SV*)cv);		\
317 	    GvCV(CvGV(cv)) = 0;               /* cv has been hijacked */\
318             call_list(oldscope, PL_beginav);		\
319             PL_curcop = &PL_compiling;			\
320             PL_compiling.op_private = (U8)(PL_hints & HINT_PRIVATE_MASK);\
321             LEAVE;					\
322 	} STMT_END
323 #define BSET_push_init(ary,cv)				\
324 	STMT_START {					\
325 	    av_unshift((PL_initav ? PL_initav : 	\
326 		(PL_initav = newAV(), PL_initav)), 1); 	\
327 	    av_store(PL_initav, 0, cv);			\
328 	} STMT_END
329 #define BSET_push_end(ary,cv)				\
330 	STMT_START {					\
331 	    av_unshift((PL_endav ? PL_endav : 		\
332 	    (PL_endav = newAV(), PL_endav)), 1);	\
333 	    av_store(PL_endav, 0, cv);			\
334 	} STMT_END
335 #define BSET_OBJ_STORE(obj, ix)			\
336 	((I32)ix > bstate->bs_obj_list_fill ?	\
337 	 bset_obj_store(aTHX_ bstate, obj, (I32)ix) : \
338 	 (bstate->bs_obj_list[ix] = obj),	\
339 	 bstate->bs_ix = ix+1)
340 #define BSET_OBJ_STOREX(obj)			\
341 	(bstate->bs_ix > bstate->bs_obj_list_fill ?	\
342 	 bset_obj_store(aTHX_ bstate, obj, bstate->bs_ix) : \
343 	 (bstate->bs_obj_list[bstate->bs_ix] = obj),	\
344 	 bstate->bs_ix++)
345 
346 #define BSET_signal(cv, name)						\
347 	mg_set(*hv_store(GvHV(gv_fetchpv("SIG", TRUE, SVt_PVHV)),	\
348 		name, strlen(name), cv, 0))
349 
350 #define BSET_xhv_name(hv, name)	hv_name_set((HV*)hv, name, strlen(name), 0)
351 
352 /* NOTE: the bytecode header only sanity-checks the bytecode. If a script cares about
353  * what version of Perl it's being called under, it should do a 'use 5.006_001' or
354  * equivalent. However, since the header includes checks requiring an exact match in
355  * ByteLoader versions (we can't guarantee forward compatibility), you don't
356  * need to specify one:
357  * 	use ByteLoader;
358  * is all you need.
359  *	-- BKS, June 2000
360 */
361 
362 #define HEADER_FAIL(f)	\
363 	Perl_croak(aTHX_ "Invalid bytecode for this architecture: " f)
364 #define HEADER_FAIL1(f, arg1)	\
365 	Perl_croak(aTHX_ "Invalid bytecode for this architecture: " f, arg1)
366 #define HEADER_FAIL2(f, arg1, arg2)	\
367 	Perl_croak(aTHX_ "Invalid bytecode for this architecture: " f, arg1, arg2)
368 
369 #define BYTECODE_HEADER_CHECK					\
370 	STMT_START {						\
371 	    U32 sz = 0;						\
372 	    strconst str;					\
373 								\
374 	    BGET_U32(sz); /* Magic: 'PLBC' */			\
375 	    if (sz != 0x43424c50) {				\
376 		HEADER_FAIL1("bad magic (want 0x43424c50, got %#x)", (int)sz);		\
377 	    }							\
378 	    BGET_strconst(str);	/* archname */			\
379 	    if (strNE(str, ARCHNAME)) {				\
380 		HEADER_FAIL2("wrong architecture (want %s, you have %s)",str,ARCHNAME);	\
381 	    }							\
382 	    BGET_strconst(str); /* ByteLoader version */	\
383 	    if (strNE(str, VERSION)) {				\
384 		HEADER_FAIL2("mismatched ByteLoader versions (want %s, you have %s)",	\
385 			str, VERSION);				\
386 	    }							\
387 	    BGET_U32(sz); /* ivsize */				\
388 	    if (sz != IVSIZE) {					\
389 		HEADER_FAIL("different IVSIZE");		\
390 	    }							\
391 	    BGET_U32(sz); /* ptrsize */				\
392 	    if (sz != PTRSIZE) {				\
393 		HEADER_FAIL("different PTRSIZE");		\
394 	    }							\
395 	} STMT_END
396