diff options
| author | Mattias Andrée <maandree@kth.se> | 2024-01-09 22:04:24 +0100 | 
|---|---|---|
| committer | Mattias Andrée <maandree@kth.se> | 2024-01-09 22:04:24 +0100 | 
| commit | ae850b1ac755f471beac4dbfef4654fe3fbaaae9 (patch) | |
| tree | 319e7f7f1b99cd1ee75e100f0a29b0f7c827ccea /libpatch_parse_copied_patch.c | |
| download | libpatch-ae850b1ac755f471beac4dbfef4654fe3fbaaae9.tar.gz libpatch-ae850b1ac755f471beac4dbfef4654fe3fbaaae9.tar.bz2 libpatch-ae850b1ac755f471beac4dbfef4654fe3fbaaae9.tar.xz | |
First commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
| -rw-r--r-- | libpatch_parse_copied_patch.c | 153 | 
1 files changed, 153 insertions, 0 deletions
| diff --git a/libpatch_parse_copied_patch.c b/libpatch_parse_copied_patch.c new file mode 100644 index 0000000..b6849b8 --- /dev/null +++ b/libpatch_parse_copied_patch.c @@ -0,0 +1,153 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +static size_t +hunk_head(const char *text, size_t len, const char *suffix, size_t *first, size_t *last) +{ +	size_t off = 4, r; +	off += r = libpatch_get_zu__(&text[off], len - off, first); +	if (!r) +		return 0; +	if (off < len && text[off] == ',') { +		off += 1; +		off += r = libpatch_get_zu__(&text[off], len - off, last); +		if (!r) +			return 0; +	} else { +		*last = *first; +	} +	if (5 < len - off && strncmp(&text[off], suffix, 5)) +		return 0; +	off += 5; +	return off; +} + + +int +libpatch_parse_copied_patch(const char *text, size_t textlen, size_t *textend, +                            struct libpatch_patch **patch, size_t *patchlen) +{ +	const char *patchtext = text; +	size_t len = 0, size = 0, off, lineno, last, count; +	int need_hunk = 0, in_hunk = 0, type, has_patch = 0; + +	*patch = NULL; +	*patchlen = 0; + +	while ((len = libpatch_next_line__(&text, &textlen, len))) { +		if (len >= 5 && !strncmp(text, "diff ", 5)) { +			if (has_patch && textend) +				break; +			APPEND_STRING(5, LIBPATCH_PATCH_DIFF_LINE); +			need_hunk = 0; +			in_hunk = 0; + +		} else if (len >= 15 && !strncmp(text, "***************", 15)) { +			APPEND_OPTSTRING(15, LIBPATCH_PATCH_HUNK); +			need_hunk = 1; +			in_hunk = 0; +			has_patch = 1; + +		} else if (len >= 3 && !strncmp(text, "***", 3)) { +			if (!need_hunk) { +				APPEND_OPTSTRING(3, LIBPATCH_PATCH_FILE1_LABEL); +				(*patch)[*patchlen - 1].lf_terminated = 0; +			} else if (need_hunk == 1 && len > 9 && text[3] == ' ') { +				off = hunk_head(text, len, " ****", &lineno, &last); +				if (!off) +					goto garbage; +				APPEND_OPTSTRING(off, LIBPATCH_PATCH_HUNK_FILE1); +				if (!lineno && last) +					goto garbage; +				else if (!lineno) +					count = 0; +				else if (last < lineno) +					goto garbage; +				else +					count = last - lineno + 1; +				need_hunk = 2; +				in_hunk = lineno > 0 ? 1 : 0; +			} else { +				goto garbage; +			} + +		} else if (len >= 3 && !strncmp(text, "---", 3)) { +			if (!need_hunk) { +				APPEND_OPTSTRING(3, LIBPATCH_PATCH_FILE2_LABEL); +				(*patch)[*patchlen - 1].lf_terminated = 0; +				has_patch = 1; +			} else if (need_hunk == 2 && len > 9 && text[3] == ' ') { +				off = hunk_head(text, len, " ----", &lineno, &last); +				if (!off) +					goto garbage; +				APPEND_OPTSTRING(off, LIBPATCH_PATCH_HUNK_FILE2); +				count = 0; +				if (!lineno && last) +					goto garbage; +				else if (!lineno) +					count = 0; +				else if (last < lineno) +					goto garbage; +				else +					count = last - lineno + 1; +				need_hunk = 0; +				in_hunk = lineno > 0 ? 2 : 0; +			} else { +				goto garbage; +			} + +		} else if (len >= 2 && in_hunk == 1 && !strncmp(text, "- ", 2)) { +			type = LIBPATCH_PATCH_FILE1_ONLY; +			goto file1_line; +		} else if (len >= 2 && in_hunk == 1 && !strncmp(text, "! ", 2)) { +			type = LIBPATCH_PATCH_PRECHANGE; +			goto file1_line; +		} else if (len >= 2 && in_hunk == 1 && !strncmp(text, "  ", 2)) { +			type = LIBPATCH_PATCH_FILE1_CONTEXT; +		file1_line: +			APPEND_OPTSTRING(2, type); +			if (!--count) +				in_hunk = 0; +			(*patch)[*patchlen - 1].file1_lineno = lineno++; + +		} else if (len >= 2 && in_hunk == 2 && !strncmp(text, "+ ", 2)) { +			type = LIBPATCH_PATCH_FILE2_ONLY; +			goto file2_line; +		} else if (len >= 2 && in_hunk == 2 && !strncmp(text, "! ", 2)) { +			type = LIBPATCH_PATCH_POSTCHANGE; +			goto file2_line; +		} else if (len >= 2 && in_hunk == 2 && !strncmp(text, "  ", 2)) { +			type = LIBPATCH_PATCH_FILE2_CONTEXT; +		file2_line: +			APPEND_OPTSTRING(2, type); +			if (!--count) +				in_hunk = 0; +			(*patch)[*patchlen - 1].file2_lineno = lineno++; + +		} else if (len >= 1 && !strncmp(text, "\\", 1) && *patchlen) { +			if (IS_LINE((*patch)[*patchlen - 1].type) || +			    !(*patch)[*patchlen - 1].lf_terminated) +				goto garbage; +			(*patch)[*patchlen - 1].lf_terminated = 0; +			APPEND_NO_TEXT(LIBPATCH_PATCH_SYNTACTICAL); + +		} else { +		garbage: +			APPEND_STRING(0, LIBPATCH_PATCH_GARBAGE); +			if (len == textlen) +				(*patch)[*patchlen - 1].lf_terminated = 0; +		} +	} + +	if (textend) +		*textend = (size_t)(text - patchtext); + +	return 0; + +fail: +	free(*patch); +	*patch = NULL; +	*patchlen = 0; +	return -1; +} | 
