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
|
---|
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
|
---|
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 | } else {
|
---|
49 | *start = '\0'; /* Avoid call to memmove. */
|
---|
50 | }
|
---|
51 | SvCUR_set(data->datasv, len);
|
---|
52 | data->next_out = 0;
|
---|
53 |
|
---|
54 | /* Attempt to read more data. */
|
---|
55 | do {
|
---|
56 | result = FILTER_READ (data->idx + 1, data->datasv, BYTELOADER_BUFFER);
|
---|
57 |
|
---|
58 | start = SvPV (data->datasv, len);
|
---|
59 | } while (result > 0 && len < wanted);
|
---|
60 | /* Loop while not (EOF || error) and short reads */
|
---|
61 |
|
---|
62 | /* If not enough data read, truncate copy */
|
---|
63 | if (wanted > len)
|
---|
64 | wanted = len;
|
---|
65 | }
|
---|
66 |
|
---|
67 | if (wanted > 0) {
|
---|
68 | memcpy (buf, start + data->next_out, wanted);
|
---|
69 | data->next_out += wanted;
|
---|
70 | wanted /= size;
|
---|
71 | }
|
---|
72 | return (int) wanted;
|
---|
73 | }
|
---|
74 |
|
---|
75 | static I32
|
---|
76 | byteloader_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
|
---|
77 | {
|
---|
78 | OP *saveroot = PL_main_root;
|
---|
79 | OP *savestart = PL_main_start;
|
---|
80 | struct byteloader_state bstate;
|
---|
81 | struct byteloader_fdata data;
|
---|
82 | int len;
|
---|
83 | (void)buf_sv;
|
---|
84 | (void)maxlen;
|
---|
85 |
|
---|
86 | data.next_out = 0;
|
---|
87 | data.datasv = FILTER_DATA(idx);
|
---|
88 | data.idx = idx;
|
---|
89 |
|
---|
90 | bstate.bs_fdata = &data;
|
---|
91 | bstate.bs_obj_list = Null(void**);
|
---|
92 | bstate.bs_obj_list_fill = -1;
|
---|
93 | bstate.bs_sv = Nullsv;
|
---|
94 | bstate.bs_iv_overflows = 0;
|
---|
95 |
|
---|
96 | /* KLUDGE */
|
---|
97 | if (byterun(aTHX_ &bstate)
|
---|
98 | && (len = SvCUR(data.datasv) - (STRLEN)data.next_out))
|
---|
99 | {
|
---|
100 | PerlIO_seek(PL_rsfp, -len, SEEK_CUR);
|
---|
101 | PL_rsfp = NULL;
|
---|
102 | }
|
---|
103 | filter_del(byteloader_filter);
|
---|
104 |
|
---|
105 | if (PL_in_eval) {
|
---|
106 | OP *o;
|
---|
107 |
|
---|
108 | PL_eval_start = PL_main_start;
|
---|
109 |
|
---|
110 | o = newSVOP(OP_CONST, 0, newSViv(1));
|
---|
111 | PL_eval_root = newLISTOP(OP_LINESEQ, 0, PL_main_root, o);
|
---|
112 | PL_main_root->op_next = o;
|
---|
113 | PL_eval_root = newUNOP(OP_LEAVEEVAL, 0, PL_eval_root);
|
---|
114 | o->op_next = PL_eval_root;
|
---|
115 |
|
---|
116 | PL_main_root = saveroot;
|
---|
117 | PL_main_start = savestart;
|
---|
118 | }
|
---|
119 |
|
---|
120 | return 0;
|
---|
121 | }
|
---|
122 |
|
---|
123 | MODULE = ByteLoader PACKAGE = ByteLoader
|
---|
124 |
|
---|
125 | PROTOTYPES: ENABLE
|
---|
126 |
|
---|
127 | void
|
---|
128 | import(package="ByteLoader", ...)
|
---|
129 | char *package
|
---|
130 | PREINIT:
|
---|
131 | SV *sv = newSVpvn ("", 0);
|
---|
132 | PPCODE:
|
---|
133 | if (!sv)
|
---|
134 | croak ("Could not allocate ByteLoader buffers");
|
---|
135 | filter_add(byteloader_filter, sv);
|
---|