1*0Sstevel@tonic-gate #include "EXTERN.h"
2*0Sstevel@tonic-gate #include "perl.h"
3*0Sstevel@tonic-gate #include "XSUB.h"
4*0Sstevel@tonic-gate #include "byterun.h"
5*0Sstevel@tonic-gate 
6*0Sstevel@tonic-gate /* Something arbitary for a buffer size */
7*0Sstevel@tonic-gate #define BYTELOADER_BUFFER 8096
8*0Sstevel@tonic-gate 
9*0Sstevel@tonic-gate int
bl_getc(struct byteloader_fdata * data)10*0Sstevel@tonic-gate bl_getc(struct byteloader_fdata *data)
11*0Sstevel@tonic-gate {
12*0Sstevel@tonic-gate     dTHX;
13*0Sstevel@tonic-gate     if (SvCUR(data->datasv) <= (STRLEN)data->next_out) {
14*0Sstevel@tonic-gate       int result;
15*0Sstevel@tonic-gate       /* Run out of buffered data, so attempt to read some more */
16*0Sstevel@tonic-gate       *(SvPV_nolen (data->datasv)) = '\0';
17*0Sstevel@tonic-gate       SvCUR_set (data->datasv, 0);
18*0Sstevel@tonic-gate       data->next_out = 0;
19*0Sstevel@tonic-gate       result = FILTER_READ (data->idx + 1, data->datasv, BYTELOADER_BUFFER);
20*0Sstevel@tonic-gate 
21*0Sstevel@tonic-gate       /* Filter returned error, or we got EOF and no data, then return EOF.
22*0Sstevel@tonic-gate 	 Not sure if filter is allowed to return EOF and add data simultaneously
23*0Sstevel@tonic-gate 	 Think not, but will bullet proof against it. */
24*0Sstevel@tonic-gate       if (result < 0 || SvCUR(data->datasv) == 0)
25*0Sstevel@tonic-gate 	return EOF;
26*0Sstevel@tonic-gate       /* Else there must be at least one byte present, which is good enough */
27*0Sstevel@tonic-gate     }
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate     return *((U8 *) SvPV_nolen (data->datasv) + data->next_out++);
30*0Sstevel@tonic-gate }
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate int
bl_read(struct byteloader_fdata * data,char * buf,size_t size,size_t n)33*0Sstevel@tonic-gate bl_read(struct byteloader_fdata *data, char *buf, size_t size, size_t n)
34*0Sstevel@tonic-gate {
35*0Sstevel@tonic-gate     dTHX;
36*0Sstevel@tonic-gate     char *start;
37*0Sstevel@tonic-gate     STRLEN len;
38*0Sstevel@tonic-gate     size_t wanted = size * n;
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate     start = SvPV (data->datasv, len);
41*0Sstevel@tonic-gate     if (len < (data->next_out + wanted)) {
42*0Sstevel@tonic-gate       int result;
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate       /* Shuffle data to start of buffer */
45*0Sstevel@tonic-gate       len -= data->next_out;
46*0Sstevel@tonic-gate       if (len) {
47*0Sstevel@tonic-gate 	memmove (start, start + data->next_out, len + 1);
48*0Sstevel@tonic-gate 	SvCUR_set (data->datasv, len);
49*0Sstevel@tonic-gate       } else {
50*0Sstevel@tonic-gate 	*start = '\0';	/* Avoid call to memmove. */
51*0Sstevel@tonic-gate 	SvCUR_set (data->datasv, 0);
52*0Sstevel@tonic-gate       }
53*0Sstevel@tonic-gate       data->next_out = 0;
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate       /* Attempt to read more data. */
56*0Sstevel@tonic-gate       do {
57*0Sstevel@tonic-gate 	result = FILTER_READ (data->idx + 1, data->datasv, BYTELOADER_BUFFER);
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate 	start = SvPV (data->datasv, len);
60*0Sstevel@tonic-gate       } while (result > 0 && len < wanted);
61*0Sstevel@tonic-gate       /* Loop while not (EOF || error) and short reads */
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate       /* If not enough data read, truncate copy */
64*0Sstevel@tonic-gate       if (wanted > len)
65*0Sstevel@tonic-gate 	wanted = len;
66*0Sstevel@tonic-gate     }
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate     if (wanted > 0) {
69*0Sstevel@tonic-gate       memcpy (buf, start + data->next_out, wanted);
70*0Sstevel@tonic-gate 	data->next_out += wanted;
71*0Sstevel@tonic-gate       wanted /= size;
72*0Sstevel@tonic-gate     }
73*0Sstevel@tonic-gate     return (int) wanted;
74*0Sstevel@tonic-gate }
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate static I32
byteloader_filter(pTHX_ int idx,SV * buf_sv,int maxlen)77*0Sstevel@tonic-gate byteloader_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
78*0Sstevel@tonic-gate {
79*0Sstevel@tonic-gate     OP *saveroot = PL_main_root;
80*0Sstevel@tonic-gate     OP *savestart = PL_main_start;
81*0Sstevel@tonic-gate     struct byteloader_state bstate;
82*0Sstevel@tonic-gate     struct byteloader_fdata data;
83*0Sstevel@tonic-gate     int len;
84*0Sstevel@tonic-gate 
85*0Sstevel@tonic-gate     data.next_out = 0;
86*0Sstevel@tonic-gate     data.datasv = FILTER_DATA(idx);
87*0Sstevel@tonic-gate     data.idx = idx;
88*0Sstevel@tonic-gate 
89*0Sstevel@tonic-gate     bstate.bs_fdata = &data;
90*0Sstevel@tonic-gate     bstate.bs_obj_list = Null(void**);
91*0Sstevel@tonic-gate     bstate.bs_obj_list_fill = -1;
92*0Sstevel@tonic-gate     bstate.bs_sv = Nullsv;
93*0Sstevel@tonic-gate     bstate.bs_iv_overflows = 0;
94*0Sstevel@tonic-gate 
95*0Sstevel@tonic-gate /* KLUDGE */
96*0Sstevel@tonic-gate     if (byterun(aTHX_ &bstate)
97*0Sstevel@tonic-gate 	    && (len = SvCUR(data.datasv) - (STRLEN)data.next_out))
98*0Sstevel@tonic-gate     {
99*0Sstevel@tonic-gate 	PerlIO_seek(PL_rsfp, -len, SEEK_CUR);
100*0Sstevel@tonic-gate 	PL_rsfp = NULL;
101*0Sstevel@tonic-gate     }
102*0Sstevel@tonic-gate     filter_del(byteloader_filter);
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate     if (PL_in_eval) {
105*0Sstevel@tonic-gate         OP *o;
106*0Sstevel@tonic-gate 
107*0Sstevel@tonic-gate         PL_eval_start = PL_main_start;
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate         o = newSVOP(OP_CONST, 0, newSViv(1));
110*0Sstevel@tonic-gate         PL_eval_root = newLISTOP(OP_LINESEQ, 0, PL_main_root, o);
111*0Sstevel@tonic-gate         PL_main_root->op_next = o;
112*0Sstevel@tonic-gate         PL_eval_root = newUNOP(OP_LEAVEEVAL, 0, PL_eval_root);
113*0Sstevel@tonic-gate         o->op_next = PL_eval_root;
114*0Sstevel@tonic-gate 
115*0Sstevel@tonic-gate         PL_main_root = saveroot;
116*0Sstevel@tonic-gate         PL_main_start = savestart;
117*0Sstevel@tonic-gate     }
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate     return 0;
120*0Sstevel@tonic-gate }
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate MODULE = ByteLoader		PACKAGE = ByteLoader
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate PROTOTYPES:	ENABLE
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate void
127*0Sstevel@tonic-gate import(package="ByteLoader", ...)
128*0Sstevel@tonic-gate   char *package
129*0Sstevel@tonic-gate   PREINIT:
130*0Sstevel@tonic-gate     SV *sv = newSVpvn ("", 0);
131*0Sstevel@tonic-gate   PPCODE:
132*0Sstevel@tonic-gate     if (!sv)
133*0Sstevel@tonic-gate       croak ("Could not allocate ByteLoader buffers");
134*0Sstevel@tonic-gate     filter_add(byteloader_filter, sv);
135