1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
/* See LICENSE file for copyright and license details. */
#include "common.h"
static int
is_unsigned(const char *text, size_t textlen, size_t *off)
{
if (*off == textlen || !isdigit(text[*off]))
return 0;
while (isdigit(++*off));
return 1;
}
enum libpatch_style
libpatch_guess_format(const char *text, size_t textlen, size_t *offset)
{
enum libpatch_style guess = LIBPATCH_STYLE_GARBAGE;
size_t off = offset ? *offset : 0;
size_t two_nums;
while (off < textlen) {
if (text[off] == '+') {
if (textlen - off < 3 || strncmp(&text[off], "+++", 3))
goto skip_line;
goto unified;
} else if (text[off] == '*') {
if (textlen - off < 3 || strncmp(&text[off], "***", 3))
goto skip_line;
goto copied;
} else if (text[off] == '@') {
if (textlen - off < 3 || strncmp(&text[off], "@@ ", 3))
goto skip_line;
goto unified;
} else if (text[off] == 'a') {
off++;
if (!is_unsigned(text, textlen, &off))
goto skip_line;
if (off != textlen && text[off] == ' ')
off++;
if (is_unsigned(text, textlen, &off))
goto rcs;
else
goto ed_alternative;
} else if (text[off] == 'd') {
off++;
if (!is_unsigned(text, textlen, &off))
goto skip_line;
if (off != textlen && text[off] == ' ')
off++;
if (!is_unsigned(text, textlen, &off))
goto ed_alternative;
guess = LIBPATCH_STYLE_RCS;
/* could also be LIBPATCH_STYLE_ED_ALTERNATIVE,
* whould cannot be parsed so LIBPATCH_STYLE_RCS
* is preferred if the patch happens to be valid
* in both */
goto skip_line;
} else if (text[off] == 'c') {
off++;
if (!is_unsigned(text, textlen, &off))
goto skip_line;
goto ed_alternative;
} else if (isdigit(text[off])) {
if (!is_unsigned(text, textlen, &off))
goto skip_line;
two_nums = (off != textlen && text[off] == ',');
if (two_nums) {
off += 1;
if (!is_unsigned(text, textlen, &off))
goto skip_line;
}
switch (text[off]) {
case 'i':
goto ed;
case 'a':
if (two_nums)
goto normal;
/* fall through */
case 'c':
case 'd':
off++;
if (off == textlen || text[off] == '\n')
goto ed;
else if (isdigit(text[off]))
goto normal;
/* fall through */
default:
goto skip_line;
}
} else {
skip_line:
while (off != textlen && text[off] != '\n')
off++;
off += (off != textlen);
}
}
*offset = off;
return guess;
determined:
while (off != textlen && text[off] != '\n')
off++;
*offset = off += (off != textlen);
return guess;
normal: guess = LIBPATCH_STYLE_NORMAL; goto determined;
copied: guess = LIBPATCH_STYLE_COPIED; goto determined;
unified: guess = LIBPATCH_STYLE_UNIFIED; goto determined;
ed: guess = LIBPATCH_STYLE_ED; goto determined;
ed_alternative: guess = LIBPATCH_STYLE_ED_ALTERNATIVE; goto determined;
rcs: guess = LIBPATCH_STYLE_RCS; goto determined;
}
|