regcomp: Allow freeing up bit in ANYOF flags
authorKarl Williamson <public@khwilliamson.com>
Wed, 8 Dec 2010 00:04:02 +0000 (17:04 -0700)
committerKarl Williamson <public@khwilliamson.com>
Sat, 11 Dec 2010 22:58:01 +0000 (15:58 -0700)
The flags field is fully used, and until the ANYOF node is split later
in development, the CLASS bit will need to be freed up to give the space
for other uses.  This patch allows for this to easily be toggled.

regcomp.c
regcomp.h
regexec.c

index 50634d2..1303ef4 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -3609,8 +3609,7 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp,
                        goto do_default;
                    if (flags & SCF_DO_STCLASS_OR) { /* Everything but \n */
                        value = (ANYOF_BITMAP_TEST(data->start_class,'\n')
-                                || ((data->start_class->flags & ANYOF_CLASS)
-                                     && ANYOF_CLASS_TEST_ANY_SET(data->start_class)));
+                                || ANYOF_CLASS_TEST_ANY_SET(data->start_class));
                        cl_anything(pRExC_state, data->start_class);
                    }
                    if (flags & SCF_DO_STCLASS_AND || !value)
@@ -8377,12 +8376,21 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, U32 depth)
 
     if (SIZE_ONLY) {
        RExC_size += ANYOF_SKIP;
+#ifdef ANYOF_ADD_LOC_SKIP
+       if (LOC) {
+           RExC_size += ANYOF_ADD_LOC_SKIP;
+       }
+#endif
        listsv = &PL_sv_undef; /* For code scanners: listsv always non-NULL. */
     }
     else {
        RExC_emit += ANYOF_SKIP;
-       if (LOC)
+       if (LOC) {
            ANYOF_FLAGS(ret) |= ANYOF_LOCALE;
+#ifdef ANYOF_ADD_LOC_SKIP
+           RExC_emit += ANYOF_ADD_LOC_SKIP;
+#endif
+       }
        ANYOF_BITMAP_ZERO(ret);
        listsv = newSVpvs("# comment\n");
     }
@@ -8596,10 +8604,14 @@ parseit:
            if (LOC && namedclass < ANYOF_MAX && ! need_class) {
                need_class = 1;
                if (SIZE_ONLY) {
+#ifdef ANYOF_CLASS_ADD_SKIP
                    RExC_size += ANYOF_CLASS_ADD_SKIP;
+#endif
                }
                else {
+#ifdef ANYOF_CLASS_ADD_SKIP
                    RExC_emit += ANYOF_CLASS_ADD_SKIP;
+#endif
                    ANYOF_CLASS_ZERO(ret);
                }
                ANYOF_FLAGS(ret) |= ANYOF_CLASS;
@@ -9700,8 +9712,8 @@ Perl_regprop(pTHX_ const regexp *prog, SV *sv, const regnode *o)
        }
         
         EMIT_ANYOF_TEST_SEPARATOR(do_sep,sv,flags);
-        /* output any special charclass tests (used mostly under use locale) */
-       if (o->flags & ANYOF_CLASS && ANYOF_CLASS_TEST_ANY_SET(o))
+        /* output any special charclass tests (used entirely under use locale) */
+       if (ANYOF_CLASS_TEST_ANY_SET(o))
            for (i = 0; i < (int)(sizeof(anyofs)/sizeof(char*)); i++)
                if (ANYOF_CLASS_TEST(o,i)) {
                    sv_catpv(sv, anyofs[i]);
index 6dc05f5..c140089 100644 (file)
--- a/regcomp.h
+++ b/regcomp.h
@@ -406,12 +406,6 @@ struct regnode_charclass_class {
 #define ANYOF_CLASS_CLEAR(p, c)        (ANYOF_CLASS_BYTE(p, c) &= ~ANYOF_BIT(c))
 #define ANYOF_CLASS_TEST(p, c) (ANYOF_CLASS_BYTE(p, c) &   ANYOF_BIT(c))
 
-/* Quicker way to see if there are actually any tests.  This is because
- * currently the set of tests can be empty even when the class bitmap is
- * allocated */
-#define ANYOF_CLASS_TEST_ANY_SET(p)    /* assumes sizeof(p) = 4 */       \
-       memNE (((struct regnode_charclass_class*)(p))->classflags, "0000", ANYOF_CLASS_SIZE)
-
 #define ANYOF_CLASS_ZERO(ret)  Zero(((struct regnode_charclass_class*)(ret))->classflags, ANYOF_CLASSBITMAP_SIZE, char)
 #define ANYOF_BITMAP_ZERO(ret) Zero(((struct regnode_charclass*)(ret))->bitmap, ANYOF_BITMAP_SIZE, char)
 
@@ -431,7 +425,29 @@ struct regnode_charclass_class {
 
 #define ANYOF_SKIP             ((ANYOF_SIZE - 1)/sizeof(regnode))
 #define ANYOF_CLASS_SKIP       ((ANYOF_CLASS_SIZE - 1)/sizeof(regnode))
-#define ANYOF_CLASS_ADD_SKIP   (ANYOF_CLASS_SKIP - ANYOF_SKIP)
+
+/* The class bit can be set to the locale one if necessary to save bits at the
+ * expense of having locale ANYOF nodes always have a class bit map, and hence
+ * take up extra space.  This allows convenient changing it as development
+ * proceeds on this */
+#if ANYOF_CLASS == ANYOF_LOCALE
+#   undef ANYOF_CLASS_ADD_SKIP
+#   define ANYOF_ADD_LOC_SKIP  (ANYOF_CLASS_SKIP - ANYOF_SKIP)
+
+    /* Quicker way to see if there are actually any tests.  This is because
+     * currently the set of tests can be empty even when the class bitmap is
+     * allocated */
+#   if ANYOF_CLASSBITMAP_SIZE != 4
+#      error ANYOF_CLASSBITMAP_SIZE is expected to be 4
+#   endif
+#   define ANYOF_CLASS_TEST_ANY_SET(p) /* assumes sizeof(p) = 4 */       \
+       memNE (((struct regnode_charclass_class*)(p))->classflags,        \
+               "\0\0\0\0", ANYOF_CLASSBITMAP_SIZE)
+#else
+#   define ANYOF_CLASS_ADD_SKIP        (ANYOF_CLASS_SKIP - ANYOF_SKIP)
+#   undef ANYOF_ADD_LOC_SKIP
+#   define ANYOF_CLASS_TEST_ANY_SET(p) (ANYOF_FLAGS(p) & ANYOF_CLASS)
+#endif
 
 
 /*
index c1f1ae2..f2723e4 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -6356,8 +6356,8 @@ S_reginclass(pTHX_ const regexp * const prog, register const regnode * const n,
                match = TRUE;
        }
        
-       if (!match && (flags & ANYOF_CLASS) && ANYOF_CLASS_TEST_ANY_SET(n)) {
-           PL_reg_flags |= RF_tainted;
+       if (!match && ANYOF_CLASS_TEST_ANY_SET(n)) {
+           PL_reg_flags |= RF_tainted;     /* CLASS implies LOCALE */
            if (
                (ANYOF_CLASS_TEST(n, ANYOF_ALNUM)   &&  isALNUM_LC(c))  ||
                (ANYOF_CLASS_TEST(n, ANYOF_NALNUM)  && !isALNUM_LC(c))  ||