| 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);
|
|---|