This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
NOTREACHED goes at/in the unreachable, not after it.
[perl5.git] / regexec.c
index f167fd9..432764b 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -540,7 +540,11 @@ S_isFOO_utf8_lc(pTHX_ const U8 classnum, const U8* character)
                                                below 256 */
     }
 
-    assert(0); /* NOTREACHED */
+    /* NOTREACHED */
+    /* Some compilers/linters detect that this spot cannot be reached
+     * (because all code paths above already did return), while some
+     * others throw a fit unless we have a return at the end. */
+    assert(0);
     return FALSE;
 }
 
@@ -1502,6 +1506,10 @@ STMT_START {
     }                                                                               \
 } STMT_END
 
+#define DUMP_EXEC_POS(li,s,doutf8)                          \
+    dump_exec_pos(li,s,(reginfo->strend),(reginfo->strbeg), \
+                startpos, doutf8)
+
 #define REXEC_FBC_EXACTISH_SCAN(COND)                     \
 STMT_START {                                              \
     while (s <= e) {                                      \
@@ -1529,34 +1537,30 @@ STMT_START {                                          \
     }                                                 \
 } STMT_END
 
-#define REXEC_FBC_UTF8_CLASS_SCAN(COND)               \
-REXEC_FBC_UTF8_SCAN(                                  \
-    if (COND) {                                       \
-       if (tmp && (reginfo->intuit || regtry(reginfo, &s))) \
-           goto got_it;                              \
-       else                                          \
-           tmp = doevery;                            \
-    }                                                 \
-    else                                              \
-       tmp = 1;                                      \
+#define REXEC_FBC_UTF8_CLASS_SCAN(COND)                        \
+REXEC_FBC_UTF8_SCAN( /* Loops while (s < strend) */            \
+    if (COND) {                                                \
+       if (tmp && (reginfo->intuit || regtry(reginfo, &s)))   \
+           goto got_it;                                       \
+       else                                                   \
+           tmp = doevery;                                     \
+    }                                                          \
+    else                                                       \
+       tmp = 1;                                               \
 )
 
-#define REXEC_FBC_CLASS_SCAN(COND)                    \
-REXEC_FBC_SCAN(                                       \
-    if (COND) {                                       \
-       if (tmp && (reginfo->intuit || regtry(reginfo, &s)))  \
-           goto got_it;                              \
-       else                                          \
-           tmp = doevery;                            \
-    }                                                 \
-    else                                              \
-       tmp = 1;                                      \
+#define REXEC_FBC_CLASS_SCAN(COND)                             \
+REXEC_FBC_SCAN( /* Loops while (s < strend) */                 \
+    if (COND) {                                                \
+       if (tmp && (reginfo->intuit || regtry(reginfo, &s)))   \
+           goto got_it;                                       \
+       else                                                   \
+           tmp = doevery;                                     \
+    }                                                          \
+    else                                                       \
+       tmp = 1;                                               \
 )
 
-#define REXEC_FBC_TRYIT                       \
-if ((reginfo->intuit || regtry(reginfo, &s))) \
-    goto got_it
-
 #define REXEC_FBC_CSCAN(CONDUTF8,COND)                         \
     if (utf8_target) {                                         \
        REXEC_FBC_UTF8_CLASS_SCAN(CONDUTF8);                   \
@@ -1564,86 +1568,91 @@ if ((reginfo->intuit || regtry(reginfo, &s))) \
     else {                                                     \
        REXEC_FBC_CLASS_SCAN(COND);                            \
     }
-    
-#define DUMP_EXEC_POS(li,s,doutf8)                          \
-    dump_exec_pos(li,s,(reginfo->strend),(reginfo->strbeg), \
-                startpos, doutf8)
-
-
-#define FBC_UTF8_A(TEST_NON_UTF8, IF_SUCCESS, IF_FAIL)                         \
-       tmp = (s != reginfo->strbeg) ? UCHARAT(s - 1) : '\n';                  \
-       tmp = TEST_NON_UTF8(tmp);                                              \
-       REXEC_FBC_UTF8_SCAN(                                                   \
-           if (tmp == ! TEST_NON_UTF8((U8) *s)) {                             \
-               tmp = !tmp;                                                    \
-               IF_SUCCESS;                                                    \
-           }                                                                  \
-           else {                                                             \
-               IF_FAIL;                                                       \
-           }                                                                  \
-       );                                                                     \
-
-#define FBC_UTF8(TEST_UV, TEST_UTF8, IF_SUCCESS, IF_FAIL)                      \
-       if (s == reginfo->strbeg) {                                            \
-           tmp = '\n';                                                        \
-       }                                                                      \
-       else {                                                                 \
-           U8 * const r = reghop3((U8*)s, -1, (U8*)reginfo->strbeg);          \
-           tmp = utf8n_to_uvchr(r, (U8*) reginfo->strend - r,                 \
-                                                       0, UTF8_ALLOW_DEFAULT); \
-       }                                                                      \
-       tmp = TEST_UV(tmp);                                                    \
-       LOAD_UTF8_CHARCLASS_ALNUM();                                           \
-       REXEC_FBC_UTF8_SCAN(                                                   \
-           if (tmp == ! (TEST_UTF8((U8 *) s))) {                              \
-               tmp = !tmp;                                                    \
-               IF_SUCCESS;                                                    \
-           }                                                                  \
-           else {                                                             \
-               IF_FAIL;                                                       \
-           }                                                                  \
-       );                                                                     \
 
-/* The only difference between the BOUND and NBOUND cases is that
- * REXEC_FBC_TRYIT is called when matched in BOUND, and when non-matched in
- * NBOUND.  This is accomplished by passing it in either the if or else clause,
- * with the other one being empty */
-#define FBC_BOUND(TEST_NON_UTF8, TEST_UV, TEST_UTF8) \
-    FBC_BOUND_COMMON(FBC_UTF8(TEST_UV, TEST_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER), TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER)
-
-#define FBC_BOUND_A(TEST_NON_UTF8, TEST_UV, TEST_UTF8) \
-    FBC_BOUND_COMMON(FBC_UTF8_A(TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER), TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER)
-
-#define FBC_NBOUND(TEST_NON_UTF8, TEST_UV, TEST_UTF8) \
-    FBC_BOUND_COMMON(FBC_UTF8(TEST_UV, TEST_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT), TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT)
-
-#define FBC_NBOUND_A(TEST_NON_UTF8, TEST_UV, TEST_UTF8) \
-    FBC_BOUND_COMMON(FBC_UTF8_A(TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT), TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT)
-
-/* Common to the BOUND and NBOUND cases.  We
- * are looking for the boundary (or non-boundary between a word and non-word
- * character.  The utf8 and non-utf8 cases have the same logic, but the details
- * must be different.  Find the "wordness" of the character just prior to this
- * one, and compare it with the wordness of this one.  If they differ, we have
- * a boundary.  At the beginning of the string, pretend that the previous
+/* The three macros below are slightly different versions of the same logic.
+ *
+ * The first is for /a and /aa when the target string is UTF-8.  This can only
+ * match ascii, but it must advance based on UTF-8.   The other two handle the
+ * non-UTF-8 and the more generic UTF-8 cases.   In all three, we are looking
+ * for the boundary (or non-boundary) between a word and non-word character.
+ * The utf8 and non-utf8 cases have the same logic, but the details must be
+ * different.  Find the "wordness" of the character just prior to this one, and
+ * compare it with the wordness of this one.  If they differ, we have a
+ * boundary.  At the beginning of the string, pretend that the previous
  * character was a new-line.
  *
- * 'tmp' below in the REXEC_FBC_SCAN loop is a loop invariant, a bool giving
- * the return of TEST_NON_UTF8(s-1).  To see this, note that that's what it is
- * defined to be at entry to the loop, and to get to the IF_FAIL branch, tmp
- * must equal TEST_NON_UTF8(s), and in the opposite branch, IF_SUCCESS, tmp is
- * that complement.  But in that branch we complement tmp, meaning that at the
+ * All these macros uncleanly have side-effects with each other and outside
+ * variables.  So far it's been too much trouble to clean-up
+ *
+ * TEST_NON_UTF8 is the macro or function to call to test if its byte input is
+ *               a word character or not.
+ * IF_SUCCESS    is code to do if it finds that we are at a boundary between
+ *               word/non-word
+ * IF_FAIL       is code to do if we aren't at a boundary between word/non-word
+ *
+ * Exactly one of the two IF_FOO parameters is a no-op, depending on whether we
+ * are looking for a boundary or for a non-boundary.  If we are looking for a
+ * boundary, we want IF_FAIL to be the no-op, and for IF_SUCCESS to go out and
+ * see if this tentative match actually works, and if so, to quit the loop
+ * here.  And vice-versa if we are looking for a non-boundary.
+ *
+ * 'tmp' below in the next three macros in the REXEC_FBC_SCAN and
+ * REXEC_FBC_UTF8_SCAN loops is a loop invariant, a bool giving the return of
+ * TEST_NON_UTF8(s-1).  To see this, note that that's what it is defined to be
+ * at entry to the loop, and to get to the IF_FAIL branch, tmp must equal
+ * TEST_NON_UTF8(s), and in the opposite branch, IF_SUCCESS, tmp is that
+ * complement.  But in that branch we complement tmp, meaning that at the
  * bottom of the loop tmp is always going to be equal to TEST_NON_UTF8(s),
  * which means at the top of the loop in the next iteration, it is
  * TEST_NON_UTF8(s-1) */
+#define FBC_UTF8_A(TEST_NON_UTF8, IF_SUCCESS, IF_FAIL)                         \
+    tmp = (s != reginfo->strbeg) ? UCHARAT(s - 1) : '\n';                      \
+    tmp = TEST_NON_UTF8(tmp);                                                  \
+    REXEC_FBC_UTF8_SCAN( /* advances s while s < strend */                     \
+        if (tmp == ! TEST_NON_UTF8((U8) *s)) {                                 \
+            tmp = !tmp;                                                        \
+            IF_SUCCESS; /* Is a boundary if values for s-1 and s differ */     \
+        }                                                                      \
+        else {                                                                 \
+            IF_FAIL;                                                           \
+        }                                                                      \
+    );                                                                         \
+
+/* Like FBC_UTF8_A, but TEST_UV is a macro which takes a UV as its input, and
+ * TEST_UTF8 is a macro that for the same input code points returns identically
+ * to TEST_UV, but takes a pointer to a UTF-8 encoded string instead */
+#define FBC_UTF8(TEST_UV, TEST_UTF8, IF_SUCCESS, IF_FAIL)                      \
+    if (s == reginfo->strbeg) {                                                \
+        tmp = '\n';                                                            \
+    }                                                                          \
+    else { /* Back-up to the start of the previous character */                \
+        U8 * const r = reghop3((U8*)s, -1, (U8*)reginfo->strbeg);              \
+        tmp = utf8n_to_uvchr(r, (U8*) reginfo->strend - r,                     \
+                                                       0, UTF8_ALLOW_DEFAULT); \
+    }                                                                          \
+    tmp = TEST_UV(tmp);                                                        \
+    LOAD_UTF8_CHARCLASS_ALNUM();                                               \
+    REXEC_FBC_UTF8_SCAN( /* advances s while s < strend */                     \
+        if (tmp == ! (TEST_UTF8((U8 *) s))) {                                  \
+            tmp = !tmp;                                                        \
+            IF_SUCCESS;                                                        \
+        }                                                                      \
+        else {                                                                 \
+            IF_FAIL;                                                           \
+        }                                                                      \
+    );
+
+/* Like the above two macros.  UTF8_CODE is the complete code for handling
+ * UTF-8.  Common to the BOUND and NBOUND cases, set-up by the FBC_BOUND, etc
+ * macros below */
 #define FBC_BOUND_COMMON(UTF8_CODE, TEST_NON_UTF8, IF_SUCCESS, IF_FAIL)        \
     if (utf8_target) {                                                         \
-               UTF8_CODE                                                      \
+        UTF8_CODE                                                              \
     }                                                                          \
     else {  /* Not utf8 */                                                     \
        tmp = (s != reginfo->strbeg) ? UCHARAT(s - 1) : '\n';                  \
        tmp = TEST_NON_UTF8(tmp);                                              \
-       REXEC_FBC_SCAN(                                                        \
+       REXEC_FBC_SCAN( /* advances s while s < strend */                      \
            if (tmp == ! TEST_NON_UTF8((U8) *s)) {                             \
                IF_SUCCESS;                                                    \
                tmp = !tmp;                                                    \
@@ -1653,14 +1662,58 @@ if ((reginfo->intuit || regtry(reginfo, &s))) \
            }                                                                  \
        );                                                                     \
     }                                                                          \
-    if ((!prog->minlen && tmp) && (reginfo->intuit || regtry(reginfo, &s)))    \
-       goto got_it;
+    /* Here, things have been set up by the previous code so that tmp is the   \
+     * return of TEST_NON_UTF(s-1) or TEST_UTF8(s-1) (depending on the         \
+     * utf8ness of the target).  We also have to check if this matches against \
+     * the EOS, which we treat as a \n (which is the same value in both UTF-8  \
+     * or non-UTF8, so can use the non-utf8 test condition even for a UTF-8    \
+     * string */                                                               \
+    if (tmp == ! TEST_NON_UTF8('\n')) {                                        \
+        IF_SUCCESS;                                                            \
+    }                                                                          \
+    else {                                                                     \
+        IF_FAIL;                                                               \
+    }
+
+/* This is the macro to use when we want to see if something that looks like it
+ * could match, actually does, and if so exits the loop */
+#define REXEC_FBC_TRYIT                            \
+    if ((reginfo->intuit || regtry(reginfo, &s)))  \
+        goto got_it
+
+/* The only difference between the BOUND and NBOUND cases is that
+ * REXEC_FBC_TRYIT is called when matched in BOUND, and when non-matched in
+ * NBOUND.  This is accomplished by passing it as either the if or else clause,
+ * with the other one being empty (PLACEHOLDER is defined as empty).
+ *
+ * The TEST_FOO parameters are for operating on different forms of input, but
+ * all should be ones that return identically for the same underlying code
+ * points */
+#define FBC_BOUND(TEST_NON_UTF8, TEST_UV, TEST_UTF8)                           \
+    FBC_BOUND_COMMON(                                                          \
+          FBC_UTF8(TEST_UV, TEST_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER),          \
+          TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER)
+
+#define FBC_BOUND_A(TEST_NON_UTF8, TEST_UV, TEST_UTF8)                         \
+    FBC_BOUND_COMMON(                                                          \
+            FBC_UTF8_A(TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER),           \
+            TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER)
+
+#define FBC_NBOUND(TEST_NON_UTF8, TEST_UV, TEST_UTF8)                          \
+    FBC_BOUND_COMMON(                                                          \
+          FBC_UTF8(TEST_UV, TEST_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT),          \
+          TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT)
+
+#define FBC_NBOUND_A(TEST_NON_UTF8, TEST_UV, TEST_UTF8)                        \
+    FBC_BOUND_COMMON(                                                          \
+            FBC_UTF8_A(TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT),           \
+            TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT)
+
 
 /* We know what class REx starts with.  Try to find this position... */
 /* if reginfo->intuit, its a dryrun */
 /* annoyingly all the vars in this routine have different names from their counterparts
    in regmatch. /grrr */
-
 STATIC char *
 S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, 
     const char *strend, regmatch_info *reginfo)
@@ -3587,8 +3640,8 @@ S_setup_EXACTISH_ST_c1_c2(pTHX_ const regnode * const text_node, int *c1p,
 
     const bool utf8_target = reginfo->is_utf8_target;
 
-    UV c1 = CHRTEST_NOT_A_CP_1;
-    UV c2 = CHRTEST_NOT_A_CP_2;
+    UV c1 = (UV)CHRTEST_NOT_A_CP_1;
+    UV c2 = (UV)CHRTEST_NOT_A_CP_2;
     bool use_chrtest_void = FALSE;
     const bool is_utf8_pat = reginfo->is_utf8_pat;
 
@@ -3990,12 +4043,15 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
            st->u.keeper.val = rex->offs[0].start;
            rex->offs[0].start = locinput - reginfo->strbeg;
            PUSH_STATE_GOTO(KEEPS_next, next, locinput);
-           assert(0); /*NOTREACHED*/
+            /* NOTREACHED */
+           assert(0);
+
        case KEEPS_next_fail:
            /* rollback the start point change */
            rex->offs[0].start = st->u.keeper.val;
            sayNO_SILENT;
-           assert(0); /*NOTREACHED*/
+            /* NOTREACHED */
+           assert(0);
 
        case MEOL: /* /..$/m  */
            if (!NEXTCHR_IS_EOS && nextchr != '\n')
@@ -4046,7 +4102,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
                               REPORT_CODE_OFF+depth*2, "", PL_colors[4], PL_colors[5])
                 );
                 sayNO_SILENT;
-                assert(0); /* NOTREACHED */
+                /* NOTREACHED */
+                assert(0);
             }
             /* FALLTHROUGH */
        case TRIE:  /* (ab|cd)  */
@@ -4233,7 +4290,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
                );
                goto trie_first_try; /* jump into the fail handler */
            }}
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case TRIE_next_fail: /* we failed - try next alternative */
         {
@@ -4347,7 +4405,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
 
            if (ST.accepted > 1 || has_cutgroup) {
                PUSH_STATE_GOTO(TRIE_next, scan, (char*)uc);
-               assert(0); /* NOTREACHED */
+                /* NOTREACHED */
+               assert(0);
            }
            /* only one choice left - just continue */
            DEBUG_EXECUTE_r({
@@ -4371,7 +4430,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
 
            locinput = (char*)uc;
            continue; /* execute rest of RE */
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
         }
 #undef  ST
 
@@ -5180,7 +5240,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
             /* and then jump to the code we share with EVAL */
             goto eval_recurse_doit;
 
-            assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+            assert(0);
 
         case EVAL:  /*   /(?{A})B/   /(??{A})B/  and /(?(?{A})X|Y)B/   */        
             if (cur_eval && cur_eval->locinput==locinput) {
@@ -5269,7 +5330,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
                        assert(o->op_targ == OP_LEAVE);
                        o = cUNOPo->op_first;
                        assert(o->op_type == OP_ENTER);
-                       o = o->op_sibling;
+                       o = OP_SIBLING(o);
                    }
 
                    if (o->op_type != OP_STUB) {
@@ -5461,7 +5522,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
                cur_eval = st;
                /* now continue from first node in postoned RE */
                PUSH_YES_STATE_GOTO(EVAL_AB, startpoint, locinput);
-               assert(0); /* NOTREACHED */
+                /* NOTREACHED */
+               assert(0);
        }
 
        case EVAL_AB: /* cleanup after a successful (??{A})B */
@@ -5570,7 +5632,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
                 }
             }
            goto fake_end;
-           /*NOTREACHED*/          
+           /* NOTREACHED */
 
        case GROUPP:  /*  (?(1))  */
            n = ARG(scan);  /* which paren pair */
@@ -5720,19 +5782,22 @@ NULL
            ST.lastloc = NULL;  /* this will be updated by WHILEM */
 
            PUSH_YES_STATE_GOTO(CURLYX_end, PREVOPER(next), locinput);
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
        }
 
        case CURLYX_end: /* just finished matching all of A*B */
            cur_curlyx = ST.prev_curlyx;
            sayYES;
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case CURLYX_end_fail: /* just failed to match all of A*B */
            regcpblow(ST.cp);
            cur_curlyx = ST.prev_curlyx;
            sayNO;
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
 
 #undef ST
@@ -5742,11 +5807,14 @@ NULL
        {
            /* see the discussion above about CURLYX/WHILEM */
            I32 n;
-           int min = ARG1(cur_curlyx->u.curlyx.me);
-           int max = ARG2(cur_curlyx->u.curlyx.me);
-           regnode *A = NEXTOPER(cur_curlyx->u.curlyx.me) + EXTRA_STEP_2ARGS;
+           int min, max;
+           regnode *A;
 
            assert(cur_curlyx); /* keep Coverity happy */
+
+           min = ARG1(cur_curlyx->u.curlyx.me);
+           max = ARG2(cur_curlyx->u.curlyx.me);
+           A = NEXTOPER(cur_curlyx->u.curlyx.me) + EXTRA_STEP_2ARGS;
            n = ++cur_curlyx->u.curlyx.count; /* how many A's matched */
            ST.save_lastloc = cur_curlyx->u.curlyx.lastloc;
            ST.cache_offset = 0;
@@ -5767,7 +5835,8 @@ NULL
                REGCP_SET(ST.lastcp);
 
                PUSH_STATE_GOTO(WHILEM_A_pre, A, locinput);
-               assert(0); /* NOTREACHED */
+                /* NOTREACHED */
+               assert(0);
            }
 
            /* If degenerate A matches "", assume A done. */
@@ -5879,7 +5948,8 @@ NULL
                REGCP_SET(ST.lastcp);
                PUSH_YES_STATE_GOTO(WHILEM_B_min, ST.save_curlyx->u.curlyx.B,
                                     locinput);
-               assert(0); /* NOTREACHED */
+                /* NOTREACHED */
+               assert(0);
            }
 
            /* Prefer A over B for maximal matching. */
@@ -5890,24 +5960,28 @@ NULL
                cur_curlyx->u.curlyx.lastloc = locinput;
                REGCP_SET(ST.lastcp);
                PUSH_STATE_GOTO(WHILEM_A_max, A, locinput);
-               assert(0); /* NOTREACHED */
+                /* NOTREACHED */
+               assert(0);
            }
            goto do_whilem_B_max;
        }
-       assert(0); /* NOTREACHED */
+        /* NOTREACHED */
+       assert(0);
 
        case WHILEM_B_min: /* just matched B in a minimal match */
        case WHILEM_B_max: /* just matched B in a maximal match */
            cur_curlyx = ST.save_curlyx;
            sayYES;
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case WHILEM_B_max_fail: /* just failed to match B in a maximal match */
            cur_curlyx = ST.save_curlyx;
            cur_curlyx->u.curlyx.lastloc = ST.save_lastloc;
            cur_curlyx->u.curlyx.count--;
            CACHEsayNO;
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case WHILEM_A_min_fail: /* just failed to match A in a minimal match */
            /* FALLTHROUGH */
@@ -5917,7 +5991,8 @@ NULL
            cur_curlyx->u.curlyx.lastloc = ST.save_lastloc;
            cur_curlyx->u.curlyx.count--;
            CACHEsayNO;
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case WHILEM_A_max_fail: /* just failed to match A in a maximal match */
            REGCP_UNWIND(ST.lastcp);
@@ -5943,7 +6018,8 @@ NULL
            cur_curlyx = cur_curlyx->u.curlyx.prev_curlyx;
            PUSH_YES_STATE_GOTO(WHILEM_B_max, ST.save_curlyx->u.curlyx.B,
                                 locinput);
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case WHILEM_B_min_fail: /* just failed to match B in a minimal match */
            cur_curlyx = ST.save_curlyx;
@@ -5977,7 +6053,8 @@ NULL
            PUSH_STATE_GOTO(WHILEM_A_min,
                /*A*/ NEXTOPER(ST.save_curlyx->u.curlyx.me) + EXTRA_STEP_2ARGS,
                 locinput);
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
 #undef  ST
 #define ST st->u.branch
@@ -6002,13 +6079,15 @@ NULL
            } else {
                PUSH_STATE_GOTO(BRANCH_next, scan, locinput);
            }
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
         case CUTGROUP:  /*  /(*THEN)/  */
             sv_yes_mark = st->u.mark.mark_name = scan->flags ? NULL :
                 MUTABLE_SV(rexi->data->data[ ARG( scan ) ]);
             PUSH_STATE_GOTO(CUTGROUP_next, next, locinput);
-            assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+            assert(0);
 
         case CUTGROUP_next_fail:
             do_cutgroup = 1;
@@ -6016,11 +6095,13 @@ NULL
             if (st->u.mark.mark_name)
                 sv_commit = st->u.mark.mark_name;
             sayNO;         
-            assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+            assert(0);
 
         case BRANCH_next:
             sayYES;
-            assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+            assert(0);
 
        case BRANCH_next_fail: /* that branch failed; try the next, if any */
            if (do_cutgroup) {
@@ -6042,7 +6123,8 @@ NULL
                sayNO_SILENT;
             }
            continue; /* execute next BRANCH[J] op */
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
     
        case MINMOD: /* next op will be non-greedy, e.g. A*?  */
            minmod = 1;
@@ -6086,7 +6168,8 @@ NULL
 
          curlym_do_A: /* execute the A in /A{m,n}B/  */
            PUSH_YES_STATE_GOTO(CURLYM_A, ST.A, locinput); /* match A */
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case CURLYM_A: /* we've just matched an A */
            ST.count++;
@@ -6136,6 +6219,7 @@ NULL
                /* calculate c1 and c2 for possible match of 1st char
                 * following curly */
                ST.c1 = ST.c2 = CHRTEST_VOID;
+                assert(ST.B);
                if (HAS_TEXT(ST.B) || JUMPABLE(ST.B)) {
                    regnode *text_node = ST.B;
                    if (! HAS_TEXT(text_node))
@@ -6221,7 +6305,8 @@ NULL
            }
            
            PUSH_STATE_GOTO(CURLYM_B, ST.B, locinput); /* match B */
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case CURLYM_B_fail: /* just failed to match a B */
            REGCP_UNWIND(ST.cp);
@@ -6399,8 +6484,8 @@ NULL
                REGCP_SET(ST.cp);
                goto curly_try_B_max;
            }
-           assert(0); /* NOTREACHED */
-
+            /* NOTREACHED */
+           assert(0);
 
        case CURLY_B_min_known_fail:
            /* failed to find B in a non-greedy match where c1,c2 valid */
@@ -6475,8 +6560,8 @@ NULL
                }
                PUSH_STATE_GOTO(CURLY_B_min_known, ST.B, locinput);
            }
-           assert(0); /* NOTREACHED */
-
+            /* NOTREACHED */
+           assert(0);
 
        case CURLY_B_min_fail:
            /* failed to find B in a non-greedy match where c1,c2 invalid */
@@ -6508,8 +6593,8 @@ NULL
                }
            }
             sayNO;
-           assert(0); /* NOTREACHED */
-
+            /* NOTREACHED */
+           assert(0);
 
        curly_try_B_max:
            /* a successful greedy match: now try to match B */
@@ -6539,7 +6624,8 @@ NULL
                 if (ST.c1 == CHRTEST_VOID || could_match) {
                    CURLY_SETPAREN(ST.paren, ST.count);
                    PUSH_STATE_GOTO(CURLY_B_max, ST.B, locinput);
-                   assert(0); /* NOTREACHED */
+                    /* NOTREACHED */
+                   assert(0);
                }
            }
            /* FALLTHROUGH */
@@ -6658,7 +6744,8 @@ NULL
            
            /* execute body of (?...A) */
            PUSH_YES_STATE_GOTO(IFMATCH_A, NEXTOPER(NEXTOPER(scan)), newstart);
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
         }
 
        case IFMATCH_A_fail: /* body of (?...A) failed */
@@ -6698,7 +6785,8 @@ NULL
            if (!scan->flags)
                sv_yes_mark = sv_commit = MUTABLE_SV(rexi->data->data[ ARG( scan ) ]);
            PUSH_STATE_GOTO(COMMIT_next, next, locinput);
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case COMMIT_next_fail:
            no_final = 1;    
@@ -6706,7 +6794,8 @@ NULL
 
        case OPFAIL:   /* (*FAIL)  */
            sayNO;
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
 #define ST st->u.mark
         case MARKPOINT: /*  (*MARK:foo)  */
@@ -6716,12 +6805,14 @@ NULL
             mark_state = st;
             ST.mark_loc = locinput;
             PUSH_YES_STATE_GOTO(MARKPOINT_next, next, locinput);
-            assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+            assert(0);
 
         case MARKPOINT_next:
             mark_state = ST.prev_mark;
             sayYES;
-            assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+            assert(0);
 
         case MARKPOINT_next_fail:
             if (popmark && sv_eq(ST.mark_name,popmark)) 
@@ -6742,7 +6833,8 @@ NULL
             sv_yes_mark = mark_state ? 
                 mark_state->u.mark.mark_name : NULL;
             sayNO;
-            assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+            assert(0);
 
         case SKIP:  /*  (*SKIP)  */
             if (scan->flags) {
@@ -6787,7 +6879,8 @@ NULL
             } 
             no_final = 1; 
             sayNO;
-            assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+            assert(0);
 #undef ST
 
         case LNBREAK: /* \R */
@@ -6821,7 +6914,8 @@ NULL
         /* switch break jumps here */
        scan = next; /* prepare to execute the next op and ... */
        continue;    /* ... jump back to the top, reusing st */
-       assert(0); /* NOTREACHED */
+        /* NOTREACHED */
+       assert(0);
 
       push_yes_state:
        /* push a state that backtracks on success */
@@ -6864,7 +6958,8 @@ NULL
            locinput = pushinput;
            st = newst;
            continue;
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
        }
     }
 
@@ -6873,7 +6968,7 @@ NULL
     * the terminating point.
     */
     Perl_croak(aTHX_ "corrupted regexp pointers");
-    /*NOTREACHED*/
+    /* NOTREACHED */
     sayNO;
 
 yes:
@@ -7500,7 +7595,8 @@ S_regrepeat(pTHX_ regexp *prog, char **startposp, const regnode *p,
 
     default:
         Perl_croak(aTHX_ "panic: regrepeat() called with unrecognized node type %d='%s'", OP(p), PL_reg_name[OP(p)]);
-        assert(0); /* NOTREACHED */
+        /* NOTREACHED */
+        assert(0);
 
     }