示例#1
0
/* Forms new line with highlights of matcher of the re regular expression using
 * escape sequences that invert colors.  Returns NULL when no match found or
 * memory allocation error occured. */
static char *
add_pattern_highlights(const char line[], size_t len, const char no_esc[],
                       const int offsets[], const regex_t *re)
{
    regmatch_t match;
    char *next = NULL;
    char *processed;
    int shift = 0;
    int overhead = 0;

    if(regexec(re, no_esc, 1, &match, 0) != 0)
    {
        return NULL;
    }
    if((processed = malloc(len + 1)) == NULL)
    {
        return NULL;
    }

    /* Before the first match. */
    strncpy(processed, line, offsets[match.rm_so]);
    next = processed + offsets[match.rm_so];

    /* All matches. */
    do
    {
        size_t match_len;
        size_t new_overhead;
        int so_offset;
        void *ptr;
        const int empty_match = (match.rm_so == match.rm_eo);

        match.rm_so += shift;
        match.rm_eo += shift;

        so_offset = offsets[match.rm_so];

        if(empty_match)
        {
            if(no_esc[match.rm_eo] == '\0')
            {
                shift = match.rm_eo;
                break;
            }
        }

        /* Between matches. */
        if(shift != 0)
        {
            const int corrected = correct_offset(line, offsets, shift);
            strncpy(next, line + corrected, so_offset - corrected);
        }

        if(empty_match)
        {
            const int corrected = (shift == 0)
                                  ? (size_t)(next - processed)
                                  : correct_offset(line, offsets, shift);
            const int len = offsets[match.rm_so + 1] - corrected;
            strncpy(next, line + corrected, len);
            next += len;
            ++shift;
        }
        else
        {
            new_overhead = INV_OVERHEAD*count_substr_chars(no_esc, &match);
            len += new_overhead;
            if((ptr = realloc(processed, len + 1)) == NULL)
            {
                free(processed);
                return NULL;
            }
            processed = ptr;

            match_len = correct_offset(line, offsets, match.rm_eo) - so_offset;
            next = processed + so_offset + overhead;
            next = add_highlighted_substr(line + so_offset, match_len, next);

            shift = match.rm_eo;
            overhead += new_overhead;
        }
    }
    while(regexec(re, no_esc + shift, 1, &match, 0) == 0);

    /* Abort if there were no non-empty matches. */
    if(next == NULL)
    {
        free(processed);
        return 0;
    }

    /* After the last match. */
    strcpy(next, line + (shift == 0 ? 0 : correct_offset(line, offsets, shift)));

    return processed;
}
示例#2
0
/* Forms new line with highlights of matcher of the re regular expression using
 * escape sequences that invert colors.  Returns NULL when no match found or
 * memory allocation error occurred. */
static char *
add_pattern_highlights(const char line[], size_t len, const char no_esc[],
		const int offsets[], const regex_t *re)
{
	/* XXX: this might benefit from a rewrite, logic of when escape sequences are
	 *      copied is unclear (sometimes along with first matched character,
	 *      sometimes before the match). */

	regmatch_t match;
	char *next;
	char *processed;
	int no_esc_pos = 0;
	int overhead = 0;
	int offset;

	if(regexec(re, no_esc, 1, &match, 0) != 0)
	{
		return NULL;
	}
	if((processed = malloc(len + 1)) == NULL)
	{
		return NULL;
	}

	/* Before the first match. */
	if(match.rm_so != 0 && no_esc[match.rm_so] == '\0')
	{
		/* This is needed to handle possibility of immediate break from the loop
		 * below. */
		offset = correct_offset(line, offsets, match.rm_so);
	}
	else
	{
		offset = offsets[match.rm_so];
	}
	strncpy(processed, line, offset);
	next = processed + offset;

	/* All matches. */
	do
	{
		int so_offset;
		void *ptr;
		const int empty_match = (match.rm_so == match.rm_eo);

		match.rm_so += no_esc_pos;
		match.rm_eo += no_esc_pos;

		so_offset = offsets[match.rm_so];

		if(empty_match)
		{
			if(no_esc[match.rm_eo] == '\0')
			{
				no_esc_pos = match.rm_eo;
				break;
			}
		}

		/* Between matches. */
		if(no_esc_pos != 0)
		{
			const int corrected = correct_offset(line, offsets, no_esc_pos);
			strncpy(next, line + corrected, so_offset - corrected);
		}

		if(empty_match)
		{
			/* Copy single character after the match to advance forward. */

			/* Position inside the line string. */
			const int esc_pos = (no_esc_pos == 0)
			                  ? (size_t)(next - processed)
			                  : correct_offset(line, offsets, no_esc_pos);
			/* Number of characters to copy from the line string. */
			const int len = (match.rm_so == 0)
			              ? utf8_chrw(no_esc)
			              : correct_offset(line, offsets, match.rm_so + 1) - esc_pos;
			strncpy(next, line + esc_pos, len);
			next += len;
			no_esc_pos += utf8_chrw(&no_esc[no_esc_pos]);
		}
		else
		{
			size_t new_overhead;
			size_t match_len;

			new_overhead = INV_OVERHEAD*count_substr_chars(no_esc, &match);
			len += new_overhead;
			if((ptr = realloc(processed, len + 1)) == NULL)
			{
				free(processed);
				return NULL;
			}
			processed = ptr;

			match_len = correct_offset(line, offsets, match.rm_eo) - so_offset;
			next = processed + so_offset + overhead;
			next = add_highlighted_substr(line + so_offset, match_len, next);

			no_esc_pos = match.rm_eo;
			overhead += new_overhead;
		}
	}
	while(regexec(re, no_esc + no_esc_pos, 1, &match, 0) == 0);

	/* Abort if there were no non-empty matches. */
	if(overhead == 0)
	{
		free(processed);
		return 0;
	}

	/* After the last match. */
	strcpy(next, line +
			(no_esc_pos == 0 ? (size_t)(next - processed) :
			 correct_offset(line, offsets, no_esc_pos)));

	return processed;
}