Ticket #1882: mc-4.7.0.1-regex-replace-escape-sequences.diff

File mc-4.7.0.1-regex-replace-escape-sequences.diff, 9.3 KB (added by vitalif, 9 years ago)

New version of patch

  • src/search/regex.c

    old new static int 
    348348mc_search_regex__process_replace_str (const GString * replace_str, const gsize current_pos, 
    349349                                      gsize * skip_len, replace_transform_type_t * replace_flags) 
    350350{ 
    351     int ret = -1; 
     351    int ret = -1; /* nothing special */ 
    352352    char *tmp_str; 
    353353    const char *curr_str = &(replace_str->str[current_pos]); 
    354354 
    mc_search_regex__process_replace_str (co 
    360360    if (*curr_str == '$' && *(curr_str + 1) == '{' && (*(curr_str + 2) & (char) 0xf0) == 0x30) { 
    361361        if (strutils_is_char_escaped (replace_str->str, curr_str)) { 
    362362            *skip_len = 1; 
    363             return -1; 
     363            return -1; /* nothing special */ 
    364364        } 
    365365 
    366366        for (*skip_len = 0; 
    mc_search_regex__process_replace_str (co 
    368368             && (*(curr_str + 2 + *skip_len) & (char) 0xf0) == 0x30; (*skip_len)++); 
    369369 
    370370        if (*(curr_str + 2 + *skip_len) != '}') 
    371             return -1; 
     371            return -1; /* nothing special */ 
    372372 
    373373        tmp_str = g_strndup (curr_str + 2, *skip_len); 
    374374        if (tmp_str == NULL) 
    375             return -1; 
     375            return -1; /* nothing special */ 
    376376 
    377377        ret = atoi (tmp_str); 
    378378        g_free (tmp_str); 
    379379 
    380380        *skip_len += 3;         /* ${} */ 
    381         return ret; 
     381        return ret; /* capture buffer index >= 0 */ 
    382382    } 
    383383 
    384384    if (*curr_str == '\\') { 
     385        char next_char; 
    385386        if (strutils_is_char_escaped (replace_str->str, curr_str)) { 
    386387            *skip_len = 1; 
    387             return -1; 
     388            return -1; /* nothing special */ 
    388389        } 
    389390 
    390         if ((*(curr_str + 1) & (char) 0xf0) == 0x30) { 
    391             ret = *(curr_str + 1) - '0'; 
     391        next_char = *(curr_str + 1); 
     392        if ((next_char & (char) 0xf0) == 0x30) { 
     393            ret = next_char - '0'; /* capture buffer index >= 0 */ 
    392394            *skip_len = 2;      /* \\ and one digit */ 
    393395            return ret; 
    394396        } 
    395         ret = -2; 
     397 
     398        if (next_char == '{') 
     399        { 
     400            for (*skip_len = 2; /* \{ */ 
     401                 current_pos + *skip_len < replace_str->len 
     402                 && (*(curr_str + *skip_len)) != '}'; (*skip_len)++); 
     403            if (current_pos + *skip_len < replace_str->len) 
     404                (*skip_len)++; 
     405            return -3; /* escape sequence */ 
     406        } 
     407 
     408        if (next_char == 'x') 
     409        { 
     410            *skip_len = 2; /* \x */ 
     411            next_char = *(curr_str + 2); 
     412            if (next_char == '{') 
     413            { 
     414                for (*skip_len = 3; /* \x{ */ 
     415                     current_pos + *skip_len < replace_str->len 
     416                     && (*(curr_str + *skip_len)) != '}'; (*skip_len)++); 
     417                if (current_pos + *skip_len < replace_str->len) 
     418                    (*skip_len)++; 
     419                return -3; /* escape sequence */ 
     420            } 
     421            else if ((next_char < '0' || next_char > '9') && 
     422                (next_char < 'a' || next_char > 'f') && 
     423                (next_char < 'A' || next_char > 'F')) 
     424            { 
     425                *skip_len = 2; /* \x without number behind */ 
     426                return -1; /* nothing special */ 
     427            } 
     428            else 
     429            { 
     430                next_char = *(curr_str + 3); 
     431                if ((next_char < '0' || next_char > '9') && 
     432                    (next_char < 'a' || next_char > 'f') && 
     433                    (next_char < 'A' || next_char > 'F')) 
     434                    *skip_len = 3; /* \xH */ 
     435                else 
     436                    *skip_len = 4; /* \xHH */ 
     437                return -3; /* escape sequence */ 
     438            } 
     439        } 
     440 
     441        if (next_char == 'n' || next_char == 't' || 
     442            next_char == 'v' || next_char == 'b' || 
     443            next_char == 'r' || next_char == 'f' || 
     444            next_char == 'a') 
     445        { 
     446            *skip_len = 2; 
     447            return -3; /* escape sequence */ 
     448        } 
     449 
     450        ret = -2; /* replace flag */ 
    396451        *skip_len += 2; 
    397         switch (*(curr_str + 1)) { 
     452        switch (next_char) { 
    398453        case 'U': 
    399454            *replace_flags |= REPLACE_T_UPP_TRANSFORM; 
    400455            *replace_flags &= ~REPLACE_T_LOW_TRANSFORM; 
    mc_search_regex__process_replace_str (co 
    413468            *replace_flags = REPLACE_T_NO_TRANSFORM; 
    414469            break; 
    415470        default: 
    416             ret = -1; 
     471            ret = -1; /* nothing special */ 
    417472            break; 
    418473        } 
    419474    } 
    mc_search_regex__process_append_str (GSt 
    469524 
    470525} 
    471526 
     527static void 
     528mc_search_regex__process_escape_sequence (GString * dest_str, const char *from, gsize len, 
     529                                          replace_transform_type_t * replace_flags) 
     530{ 
     531    gsize i = 0; 
     532    char c = 0; 
     533    if (len == (gsize) -1) 
     534        len = strlen (from); 
     535    if (len <= 0) 
     536        return; 
     537    if (from[i] == '{') 
     538        i++; 
     539    if (i >= len) 
     540        return; 
     541    if (from[i] == 'x') 
     542    { 
     543        i++; 
     544        if (i < len && from[i] == '{') 
     545            i++; 
     546        for (; i < len; i++) 
     547        { 
     548            if (from[i] >= '0' && from[i] <= '9') 
     549                c = c*16 + from[i] - '0'; 
     550            else if (from[i] >= 'a' && from[i] <= 'f') 
     551                c = c*16 + 10 + from[i] - 'a'; 
     552            else if (from[i] >= 'A' && from[i] <= 'F') 
     553                c = c*16 + 10 + from[i] - 'A'; 
     554            else 
     555                break; 
     556        } 
     557    } 
     558    else if (from[i] >= '0' && from[i] <= '9') 
     559        for (; i < len && from[i] >= '0' && from[i] <= '7'; i++) 
     560            c = c*8 + from[i] - '0'; 
     561    else 
     562    { 
     563        switch (from[i]) 
     564        { 
     565            case 'n': c = '\n'; break; 
     566            case 't': c = '\t'; break; 
     567            case 'v': c = '\v'; break; 
     568            case 'b': c = '\b'; break; 
     569            case 'r': c = '\r'; break; 
     570            case 'f': c = '\f'; break; 
     571            case 'a': c = '\a'; break; 
     572            default: 
     573                mc_search_regex__process_append_str(dest_str, from, len, replace_flags); 
     574                return; 
     575        } 
     576    } 
     577    g_string_append_len (dest_str, &c, 1); 
     578} 
     579 
    472580/*** public functions ****************************************************************************/ 
    473581 
    474582void 
    475583mc_search__cond_struct_new_init_regex (const char *charset, mc_search_t * lc_mc_search, 
    476584                                       mc_search_cond_t * mc_search_cond) 
    477585{ 
    478     GString *tmp = NULL; 
     586    int utf8 = 0; 
    479587#ifdef SEARCH_TYPE_GLIB 
    480588    GError *error = NULL; 
    481589#else /* SEARCH_TYPE_GLIB */ 
    mc_search__cond_struct_new_init_regex (c 
    483591    int erroffset; 
    484592#endif /* SEARCH_TYPE_GLIB */ 
    485593 
     594#ifdef SEARCH_TYPE_GLIB 
    486595    if (!lc_mc_search->is_case_sentitive) { 
    487         tmp = g_string_new_len (mc_search_cond->str->str, mc_search_cond->str->len); 
     596        GString *tmp = g_string_new_len (mc_search_cond->str->str, mc_search_cond->str->len); 
    488597        g_string_free (mc_search_cond->str, TRUE); 
    489598        mc_search_cond->str = mc_search__cond_struct_new_regex_ci_str (charset, tmp->str, tmp->len); 
    490599        g_string_free (tmp, TRUE); 
    491600    } 
    492 #ifdef SEARCH_TYPE_GLIB 
    493601    mc_search_cond->regex_handle = 
    494602        g_regex_new (mc_search_cond->str->str, G_REGEX_OPTIMIZE | G_REGEX_RAW | G_REGEX_DOTALL, 0, 
    495603                     &error); 
    mc_search__cond_struct_new_init_regex (c 
    501609        return; 
    502610    } 
    503611#else /* SEARCH_TYPE_GLIB */ 
     612    if (charset && !strncasecmp(charset, "utf-8", 6)) 
     613        utf8 = 1; 
    504614    mc_search_cond->regex_handle = 
    505         pcre_compile (mc_search_cond->str->str, PCRE_EXTRA, &error, &erroffset, NULL); 
     615        pcre_compile (mc_search_cond->str->str, (!mc_search->is_case_sentitive ? PCRE_CASELESS : 0) | PCRE_MULTILINE | (utf8 ? PCRE_UTF8 : 0) | PCRE_EXTRA, &error, &erroffset, NULL); 
    506616    if (mc_search_cond->regex_handle == NULL) { 
    507617        lc_mc_search->error = MC_SEARCH_E_REGEX_COMPILE; 
    508618        lc_mc_search->error_str = g_strdup (error); 
    mc_search_regex_prepare_replace_str (mc_ 
    635745    for (loop = 0; loop < replace_str->len - 1; loop++) { 
    636746        lc_index = mc_search_regex__process_replace_str (replace_str, loop, &len, &replace_flags); 
    637747 
     748        /* nothing special */ 
    638749        if (lc_index == -1) { 
    639750            if (len != 0) { 
    640751                mc_search_regex__process_append_str (ret, prev_str, 
    mc_search_regex_prepare_replace_str (mc_ 
    648759            continue; 
    649760        } 
    650761 
     762        /* replace flag (transform) */ 
    651763        if (lc_index == -2) { 
    652764            if (loop) 
    653765                mc_search_regex__process_append_str (ret, prev_str, 
    mc_search_regex_prepare_replace_str (mc_ 
    658770            continue; 
    659771        } 
    660772 
     773        /* escape sequence */ 
     774        if (lc_index == -3) { 
     775            mc_search_regex__process_append_str (ret, prev_str, 
     776                                                 replace_str->str - prev_str + loop, 
     777                                                 &replace_flags); 
     778            mc_search_regex__process_escape_sequence (ret, replace_str->str - loop + 1, len - 1, 
     779                                                      &replace_flags); 
     780            prev_str = replace_str->str + loop + len; 
     781            loop += len - 1; 
     782            continue; 
     783        } 
     784 
    661785        if (lc_index > lc_mc_search->num_rezults) { 
    662786            g_string_free (ret, TRUE); 
    663787            lc_mc_search->error = MC_SEARCH_E_REGEX_REPLACE;