This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Re: [perl #25270] 5.8.3 - POSIX::ctermid() on Solaris
[perl5.git] / ext / ByteLoader / ByteLoader.xs
CommitLineData
b295d113
TH
1#include "EXTERN.h"
2#include "perl.h"
3#include "XSUB.h"
e8edd1e6 4#include "byterun.h"
b295d113 5
059a8bb7
JH
6/* Something arbitary for a buffer size */
7#define BYTELOADER_BUFFER 8096
33c2a728 8
059a8bb7
JH
9int
10bl_getc(struct byteloader_fdata *data)
33c2a728
GS
11{
12 dTHX;
7c436af3 13 if (SvCUR(data->datasv) <= (STRLEN)data->next_out) {
059a8bb7
JH
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
1df34986 29 return *((U8 *) SvPV_nolen (data->datasv) + data->next_out++);
33c2a728 30}
d8ab9aa2 31
059a8bb7
JH
32int
33bl_read(struct byteloader_fdata *data, char *buf, size_t size, size_t n)
e8edd1e6 34{
c5be433b 35 dTHX;
059a8bb7
JH
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;
e8edd1e6 74}
b295d113
TH
75
76static I32
acfe0abc 77byteloader_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
b295d113
TH
78{
79 OP *saveroot = PL_main_root;
80 OP *savestart = PL_main_start;
059a8bb7
JH
81 struct byteloader_state bstate;
82 struct byteloader_fdata data;
1df34986 83 int len;
059a8bb7
JH
84
85 data.next_out = 0;
86 data.datasv = FILTER_DATA(idx);
87 data.idx = idx;
b295d113 88
059a8bb7
JH
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;
e8edd1e6 94
1df34986
AE
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);
b295d113
TH
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
122MODULE = ByteLoader PACKAGE = ByteLoader
123
124PROTOTYPES: ENABLE
125
126void
c6c619a9
DM
127import(package="ByteLoader", ...)
128 char *package
059a8bb7
JH
129 PREINIT:
130 SV *sv = newSVpvn ("", 0);
b295d113 131 PPCODE:
059a8bb7
JH
132 if (!sv)
133 croak ("Could not allocate ByteLoader buffers");
134 filter_add(byteloader_filter, sv);