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