diff options
author | David Mitchell <davem@iabyn.com> | 2018-01-12 12:00:30 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2018-01-19 13:45:20 +0000 |
commit | c1048fcffff9a2b16ece33136c56febc7e5e4396 (patch) | |
tree | 14410bc416f113a61d6621f51978f53c363482b9 /op.c | |
parent | 5f63644886c09045a5d86d169abdfea9e804bce7 (diff) | |
download | perl-c1048fcffff9a2b16ece33136c56febc7e5e4396.tar.gz |
add two structs for OP_TRANS
Originally, the op_pv of an OP_TRANS op pointed to a 256-slot array of
shorts, which contained the translations. However, in the presence of
tr///c, extra information needs to be stored to handle utf8 strings.
The 256 slot array was extended, with slot 0x100 holding a length,
and slots 0x101 holding some extra chars.
This has made things a bit messy, so this commit adds two structs,
one being an array of 256 shorts, and the other being the same but with
some extra fields. So for example tbl->[0x100] has been replaced with
tbl->excess_len.
This commit should make no functional difference, but will allow us
shortly to fix a bug by changing the type of the excess_len field from
short to something bigger, for example.
Diffstat (limited to 'op.c')
-rw-r--r-- | op.c | 45 |
1 files changed, 22 insertions, 23 deletions
@@ -6343,7 +6343,7 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) I32 i; I32 j; I32 grows = 0; - short *tbl; + OPtrans_map *tbl; const I32 complement = o->op_private & OPpTRANS_COMPLEMENT; const I32 squash = o->op_private & OPpTRANS_SQUASH; @@ -6629,11 +6629,9 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) * The toker will have already expanded char ranges in t and r. */ - tbl = (short*)PerlMemShared_calloc( - /* one slot for 'extra len' count and one slot - * for storing of last replacement char */ - complement ? 258 : 256, - sizeof(short)); + tbl = (OPtrans_map*)PerlMemShared_calloc( + complement ? sizeof(OPtrans_map_ex) : sizeof(OPtrans_map), + sizeof(char)); cPVOPo->op_pv = (char*)tbl; if (complement) { @@ -6641,21 +6639,21 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) * with a search char) replacement chars (so j <= rlen always) */ for (i = 0; i < (I32)tlen; i++) - tbl[t[i]] = -1; + tbl->map[t[i]] = -1; for (i = 0, j = 0; i < 256; i++) { - if (!tbl[i]) { + if (!tbl->map[i]) { if (j == (I32)rlen) { if (del) - tbl[i] = -2; + tbl->map[i] = -2; else if (rlen) - tbl[i] = r[j-1]; + tbl->map[i] = r[j-1]; else - tbl[i] = (short)i; + tbl->map[i] = (short)i; } else { if (UVCHR_IS_INVARIANT(i) && ! UVCHR_IS_INVARIANT(r[j])) grows = 1; - tbl[i] = r[j++]; + tbl->map[i] = r[j++]; } } } @@ -6676,17 +6674,18 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) */ short repeat_char; SSize_t excess = rlen - (SSize_t)j; + OPtrans_map_ex *extbl = (OPtrans_map_ex*)tbl; if (excess) { /* More replacement chars than search chars: * store excess replacement chars at end of main table. */ - tbl = (short *) PerlMemShared_realloc(tbl, - (0x102+excess) * sizeof(short)); - cPVOPo->op_pv = (char*)tbl; + extbl = (OPtrans_map_ex *) PerlMemShared_realloc(extbl, + sizeof(OPtrans_map_ex) + excess * sizeof(short)); + cPVOPo->op_pv = (char*)extbl; for (i = 0; i < (I32)excess; i++) - tbl[0x102+i] = r[j+i]; + extbl->map_ex[i] = r[j+i]; repeat_char = r[rlen-1]; } else { @@ -6703,8 +6702,8 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) o->op_private |= OPpTRANS_IDENTICAL; } } - tbl[0x100] = (short)excess; /* excess char count */ - tbl[0x101] = (short)repeat_char; /* repeated replace char */ + extbl->excess_len = (short)excess; /* excess char count */ + extbl->repeat_char = (short)repeat_char; /* repeated replace char */ } } else { @@ -6717,21 +6716,21 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) o->op_private |= OPpTRANS_IDENTICAL; } for (i = 0; i < 256; i++) - tbl[i] = -1; + tbl->map[i] = -1; for (i = 0, j = 0; i < (I32)tlen; i++,j++) { if (j >= (I32)rlen) { if (del) { - if (tbl[t[i]] == -1) - tbl[t[i]] = -2; + if (tbl->map[t[i]] == -1) + tbl->map[t[i]] = -2; continue; } --j; } - if (tbl[t[i]] == -1) { + if (tbl->map[t[i]] == -1) { if ( UVCHR_IS_INVARIANT(t[i]) && ! UVCHR_IS_INVARIANT(r[j])) grows = 1; - tbl[t[i]] = r[j]; + tbl->map[t[i]] = r[j]; } } } |