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