|
@@ -15,8 +15,8 @@
|
|
|
with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
#include <system.h>
|
|
|
-#include <ctype.h>
|
|
|
#include <regex.h>
|
|
|
+#include <mcel.h>
|
|
|
#include "common.h"
|
|
|
|
|
|
enum transform_type
|
|
@@ -417,51 +417,44 @@ set_transform_expr (const char *expr)
|
|
|
expr = parse_transform_expr (expr);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+static struct obstack stk;
|
|
|
+static bool stk_init;
|
|
|
+
|
|
|
/* Run case conversion specified by CASE_CTL on array PTR of SIZE
|
|
|
- characters. Returns pointer to statically allocated storage. */
|
|
|
-static char *
|
|
|
+ characters. Append the result to STK. */
|
|
|
+static void
|
|
|
run_case_conv (enum case_ctl_type case_ctl, char *ptr, size_t size)
|
|
|
{
|
|
|
- static char *case_ctl_buffer;
|
|
|
- static size_t case_ctl_bufsize;
|
|
|
- char *p;
|
|
|
-
|
|
|
- if (case_ctl_bufsize < size)
|
|
|
+ char const *p = ptr, *plim = ptr + size;
|
|
|
+ mbstate_t mbs; mbszero (&mbs);
|
|
|
+ while (p < plim)
|
|
|
{
|
|
|
- case_ctl_bufsize = size;
|
|
|
- case_ctl_buffer = xrealloc (case_ctl_buffer, case_ctl_bufsize);
|
|
|
+ mcel_t g = mcel_scan (p, plim);
|
|
|
+ char32_t ch;
|
|
|
+ switch (case_ctl)
|
|
|
+ {
|
|
|
+ case ctl_upcase: case ctl_upcase_next: ch = c32toupper (g.ch); break;
|
|
|
+ case ctl_locase: case ctl_locase_next: ch = c32tolower (g.ch); break;
|
|
|
+ default: ch = g.ch; break;
|
|
|
+ }
|
|
|
+ if (ch == g.ch)
|
|
|
+ obstack_grow (&stk, p, g.len);
|
|
|
+ else
|
|
|
+ {
|
|
|
+ obstack_make_room (&stk, MB_LEN_MAX);
|
|
|
+ mbstate_t ombs; mbszero (&ombs);
|
|
|
+ size_t outbytes = c32rtomb (obstack_next_free (&stk), ch, &ombs);
|
|
|
+ obstack_blank_fast (&stk, outbytes);
|
|
|
+ }
|
|
|
+ p += g.len;
|
|
|
+ if (case_ctl != ctl_upcase && case_ctl != ctl_locase)
|
|
|
+ break;
|
|
|
}
|
|
|
- memcpy (case_ctl_buffer, ptr, size);
|
|
|
- switch (case_ctl)
|
|
|
- {
|
|
|
- case ctl_upcase_next:
|
|
|
- case_ctl_buffer[0] = toupper ((unsigned char) case_ctl_buffer[0]);
|
|
|
- break;
|
|
|
-
|
|
|
- case ctl_locase_next:
|
|
|
- case_ctl_buffer[0] = tolower ((unsigned char) case_ctl_buffer[0]);
|
|
|
- break;
|
|
|
|
|
|
- case ctl_upcase:
|
|
|
- for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
|
|
|
- *p = toupper ((unsigned char) *p);
|
|
|
- break;
|
|
|
-
|
|
|
- case ctl_locase:
|
|
|
- for (p = case_ctl_buffer; p < case_ctl_buffer + size; p++)
|
|
|
- *p = tolower ((unsigned char) *p);
|
|
|
- break;
|
|
|
-
|
|
|
- case ctl_stop:
|
|
|
- break;
|
|
|
- }
|
|
|
- return case_ctl_buffer;
|
|
|
+ obstack_grow (&stk, p, plim - p);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-static struct obstack stk;
|
|
|
-static bool stk_init;
|
|
|
-
|
|
|
static void
|
|
|
_single_transform_name_to_obstack (struct transform *tf, char *input)
|
|
|
{
|
|
@@ -484,7 +477,6 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
|
|
|
while (*input)
|
|
|
{
|
|
|
size_t disp;
|
|
|
- char *ptr;
|
|
|
|
|
|
rc = regexec (&tf->regex, input, tf->regex.re_nsub + 1, rmp, 0);
|
|
|
|
|
@@ -510,16 +502,10 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
|
|
|
switch (segm->type)
|
|
|
{
|
|
|
case segm_literal: /* Literal segment */
|
|
|
- if (case_ctl == ctl_stop)
|
|
|
- ptr = segm->v.literal.ptr;
|
|
|
- else
|
|
|
- {
|
|
|
- ptr = run_case_conv (case_ctl,
|
|
|
- segm->v.literal.ptr,
|
|
|
- segm->v.literal.size);
|
|
|
- CASE_CTL_RESET();
|
|
|
- }
|
|
|
- obstack_grow (&stk, ptr, segm->v.literal.size);
|
|
|
+ run_case_conv (case_ctl,
|
|
|
+ segm->v.literal.ptr,
|
|
|
+ segm->v.literal.size);
|
|
|
+ CASE_CTL_RESET ();
|
|
|
break;
|
|
|
|
|
|
case segm_backref: /* Back-reference segment */
|
|
@@ -528,14 +514,9 @@ _single_transform_name_to_obstack (struct transform *tf, char *input)
|
|
|
{
|
|
|
size_t size = rmp[segm->v.ref].rm_eo
|
|
|
- rmp[segm->v.ref].rm_so;
|
|
|
- ptr = input + rmp[segm->v.ref].rm_so;
|
|
|
- if (case_ctl != ctl_stop)
|
|
|
- {
|
|
|
- ptr = run_case_conv (case_ctl, ptr, size);
|
|
|
- CASE_CTL_RESET();
|
|
|
- }
|
|
|
-
|
|
|
- obstack_grow (&stk, ptr, size);
|
|
|
+ run_case_conv (case_ctl,
|
|
|
+ input + rmp[segm->v.ref].rm_so, size);
|
|
|
+ CASE_CTL_RESET ();
|
|
|
}
|
|
|
break;
|
|
|
|