}
+/*
+ * Just saw a single line in a fragment. If it is a part of this hunk
+ * that is a context " ", an added "+", or a removed "-" line, it may
+ * be followed by "\\ No newline..." to signal that the last "\n" on
+ * this line needs to be dropped. Depending on locale settings when
+ * the patch was produced we don't know what this line would exactly
+ * say. The only thing we do know is that it begins with "\ ".
+ * Checking for 12 is just for sanity check; "\ No newline..." would
+ * be at least that long in any l10n.
+ *
+ * Return 0 if the line we saw is not followed by "\ No newline...",
+ * or length of that line. The caller will use it to skip over the
+ * "\ No newline..." line.
+ */
+static int adjust_incomplete(const char *line, int len,
+ unsigned long size)
+{
+ int nextlen;
+
+ if (*line != '\n' && *line != ' ' && *line != '+' && *line != '-')
+ return 0;
+ if (size - len < 12 || memcmp(line + len, "\\ ", 2))
+ return 0;
+ nextlen = linelen(line + len, size - len);
+ if (nextlen < 12)
+ return 0;
+ return nextlen;
+}
+
/*
* Parse a unified diff. Note that this really needs to parse each
* fragment separately, since the only way to know the difference
{
int added, deleted;
int len = linelen(line, size), offset;
+ int skip_len = 0;
unsigned long oldlines, newlines;
unsigned long leading, trailing;
len = linelen(line, size);
if (!len || line[len-1] != '\n')
return -1;
+
+ /*
+ * For an incomplete line, skip_len counts the bytes
+ * on "\\ No newline..." marker line that comes next
+ * to the current line.
+ *
+ * Reduce "len" to drop the newline at the end of
+ * line[], but add one to "skip_len", which will be
+ * added back to "len" for the next iteration, to
+ * compensate.
+ */
+ skip_len = adjust_incomplete(line, len, size);
+ if (skip_len) {
+ len--;
+ skip_len++;
+ }
switch (*line) {
default:
return -1;
newlines--;
trailing = 0;
break;
-
- /*
- * We allow "\ No newline at end of file". Depending
- * on locale settings when the patch was produced we
- * don't know what this line looks like. The only
- * thing we do know is that it begins with "\ ".
- * Checking for 12 is just for sanity check -- any
- * l10n of "\ No newline..." is at least that long.
- */
- case '\\':
- if (len < 12 || memcmp(line, "\\ ", 2))
- return -1;
- break;
}
+
+ /* eat the "\\ No newline..." as well, if exists */
+ len += skip_len;
}
if (oldlines || newlines)
return -1;
fragment->leading = leading;
fragment->trailing = trailing;
- /*
- * If a fragment ends with an incomplete line, we failed to include
- * it in the above loop because we hit oldlines == newlines == 0
- * before seeing it.
- */
- if (12 < size && !memcmp(line, "\\ ", 2))
- offset += linelen(line, size);
-
patch->lines_added += added;
patch->lines_deleted += deleted;