##// END OF EJS Templates
diffhelpers: verify hline was created before using it...
Augie Fackler -
r23959:c8e7fa41 stable
parent child Browse files
Show More
@@ -1,197 +1,199
1 /*
1 /*
2 * diffhelpers.c - helper routines for mpatch
2 * diffhelpers.c - helper routines for mpatch
3 *
3 *
4 * Copyright 2007 Chris Mason <chris.mason@oracle.com>
4 * Copyright 2007 Chris Mason <chris.mason@oracle.com>
5 *
5 *
6 * This software may be used and distributed according to the terms
6 * This software may be used and distributed according to the terms
7 * of the GNU General Public License v2, incorporated herein by reference.
7 * of the GNU General Public License v2, incorporated herein by reference.
8 */
8 */
9
9
10 #include <Python.h>
10 #include <Python.h>
11 #include <stdlib.h>
11 #include <stdlib.h>
12 #include <string.h>
12 #include <string.h>
13
13
14 #include "util.h"
14 #include "util.h"
15
15
16 static char diffhelpers_doc[] = "Efficient diff parsing";
16 static char diffhelpers_doc[] = "Efficient diff parsing";
17 static PyObject *diffhelpers_Error;
17 static PyObject *diffhelpers_Error;
18
18
19
19
20 /* fixup the last lines of a and b when the patch has no newline at eof */
20 /* fixup the last lines of a and b when the patch has no newline at eof */
21 static void _fix_newline(PyObject *hunk, PyObject *a, PyObject *b)
21 static void _fix_newline(PyObject *hunk, PyObject *a, PyObject *b)
22 {
22 {
23 Py_ssize_t hunksz = PyList_Size(hunk);
23 Py_ssize_t hunksz = PyList_Size(hunk);
24 PyObject *s = PyList_GET_ITEM(hunk, hunksz-1);
24 PyObject *s = PyList_GET_ITEM(hunk, hunksz-1);
25 char *l = PyBytes_AsString(s);
25 char *l = PyBytes_AsString(s);
26 Py_ssize_t alen = PyList_Size(a);
26 Py_ssize_t alen = PyList_Size(a);
27 Py_ssize_t blen = PyList_Size(b);
27 Py_ssize_t blen = PyList_Size(b);
28 char c = l[0];
28 char c = l[0];
29 PyObject *hline;
29 PyObject *hline;
30 Py_ssize_t sz = PyBytes_GET_SIZE(s);
30 Py_ssize_t sz = PyBytes_GET_SIZE(s);
31
31
32 if (sz > 1 && l[sz-2] == '\r')
32 if (sz > 1 && l[sz-2] == '\r')
33 /* tolerate CRLF in last line */
33 /* tolerate CRLF in last line */
34 sz -= 1;
34 sz -= 1;
35
35
36 hline = PyBytes_FromStringAndSize(l, sz-1);
36 hline = PyBytes_FromStringAndSize(l, sz-1);
37 if (!hline) {
38 return NULL;
39 }
37
40
38 if (c == ' ' || c == '+') {
41 if (c == ' ' || c == '+') {
39 PyObject *rline = PyBytes_FromStringAndSize(l + 1, sz - 2);
42 PyObject *rline = PyBytes_FromStringAndSize(l + 1, sz - 2);
40 PyList_SetItem(b, blen-1, rline);
43 PyList_SetItem(b, blen-1, rline);
41 }
44 }
42 if (c == ' ' || c == '-') {
45 if (c == ' ' || c == '-') {
43 Py_INCREF(hline);
46 Py_INCREF(hline);
44 PyList_SetItem(a, alen-1, hline);
47 PyList_SetItem(a, alen-1, hline);
45 }
48 }
46 PyList_SetItem(hunk, hunksz-1, hline);
49 PyList_SetItem(hunk, hunksz-1, hline);
47 }
50 }
48
51
49 /* python callable form of _fix_newline */
52 /* python callable form of _fix_newline */
50 static PyObject *
53 static PyObject *
51 fix_newline(PyObject *self, PyObject *args)
54 fix_newline(PyObject *self, PyObject *args)
52 {
55 {
53 PyObject *hunk, *a, *b;
56 PyObject *hunk, *a, *b;
54 if (!PyArg_ParseTuple(args, "OOO", &hunk, &a, &b))
57 if (!PyArg_ParseTuple(args, "OOO", &hunk, &a, &b))
55 return NULL;
58 return NULL;
56 _fix_newline(hunk, a, b);
59 _fix_newline(hunk, a, b);
57 return Py_BuildValue("l", 0);
60 return Py_BuildValue("l", 0);
58 }
61 }
59
62
60 #if (PY_VERSION_HEX < 0x02050000)
63 #if (PY_VERSION_HEX < 0x02050000)
61 static const char *addlines_format = "OOiiOO";
64 static const char *addlines_format = "OOiiOO";
62 #else
65 #else
63 static const char *addlines_format = "OOnnOO";
66 static const char *addlines_format = "OOnnOO";
64 #endif
67 #endif
65
68
66 /*
69 /*
67 * read lines from fp into the hunk. The hunk is parsed into two arrays
70 * read lines from fp into the hunk. The hunk is parsed into two arrays
68 * a and b. a gets the old state of the text, b gets the new state
71 * a and b. a gets the old state of the text, b gets the new state
69 * The control char from the hunk is saved when inserting into a, but not b
72 * The control char from the hunk is saved when inserting into a, but not b
70 * (for performance while deleting files)
73 * (for performance while deleting files)
71 */
74 */
72 static PyObject *
75 static PyObject *
73 addlines(PyObject *self, PyObject *args)
76 addlines(PyObject *self, PyObject *args)
74 {
77 {
75
78
76 PyObject *fp, *hunk, *a, *b, *x;
79 PyObject *fp, *hunk, *a, *b, *x;
77 Py_ssize_t i;
80 Py_ssize_t i;
78 Py_ssize_t lena, lenb;
81 Py_ssize_t lena, lenb;
79 Py_ssize_t num;
82 Py_ssize_t num;
80 Py_ssize_t todoa, todob;
83 Py_ssize_t todoa, todob;
81 char *s, c;
84 char *s, c;
82 PyObject *l;
85 PyObject *l;
83 if (!PyArg_ParseTuple(args, addlines_format,
86 if (!PyArg_ParseTuple(args, addlines_format,
84 &fp, &hunk, &lena, &lenb, &a, &b))
87 &fp, &hunk, &lena, &lenb, &a, &b))
85 return NULL;
88 return NULL;
86
89
87 while (1) {
90 while (1) {
88 todoa = lena - PyList_Size(a);
91 todoa = lena - PyList_Size(a);
89 todob = lenb - PyList_Size(b);
92 todob = lenb - PyList_Size(b);
90 num = todoa > todob ? todoa : todob;
93 num = todoa > todob ? todoa : todob;
91 if (num == 0)
94 if (num == 0)
92 break;
95 break;
93 for (i = 0; i < num; i++) {
96 for (i = 0; i < num; i++) {
94 x = PyFile_GetLine(fp, 0);
97 x = PyFile_GetLine(fp, 0);
95 s = PyBytes_AsString(x);
98 s = PyBytes_AsString(x);
96 c = *s;
99 c = *s;
97 if (strcmp(s, "\\ No newline at end of file\n") == 0) {
100 if (strcmp(s, "\\ No newline at end of file\n") == 0) {
98 _fix_newline(hunk, a, b);
101 _fix_newline(hunk, a, b);
99 continue;
102 continue;
100 }
103 }
101 if (c == '\n') {
104 if (c == '\n') {
102 /* Some patches may be missing the control char
105 /* Some patches may be missing the control char
103 * on empty lines. Supply a leading space. */
106 * on empty lines. Supply a leading space. */
104 Py_DECREF(x);
107 Py_DECREF(x);
105 x = PyBytes_FromString(" \n");
108 x = PyBytes_FromString(" \n");
106 }
109 }
107 PyList_Append(hunk, x);
110 PyList_Append(hunk, x);
108 if (c == '+') {
111 if (c == '+') {
109 l = PyBytes_FromString(s + 1);
112 l = PyBytes_FromString(s + 1);
110 PyList_Append(b, l);
113 PyList_Append(b, l);
111 Py_DECREF(l);
114 Py_DECREF(l);
112 } else if (c == '-') {
115 } else if (c == '-') {
113 PyList_Append(a, x);
116 PyList_Append(a, x);
114 } else {
117 } else {
115 l = PyBytes_FromString(s + 1);
118 l = PyBytes_FromString(s + 1);
116 PyList_Append(b, l);
119 PyList_Append(b, l);
117 Py_DECREF(l);
120 Py_DECREF(l);
118 PyList_Append(a, x);
121 PyList_Append(a, x);
119 }
122 }
120 Py_DECREF(x);
123 Py_DECREF(x);
121 }
124 }
122 }
125 }
123 return Py_BuildValue("l", 0);
126 return Py_BuildValue("l", 0);
124 }
127 }
125
128
126 /*
129 /*
127 * compare the lines in a with the lines in b. a is assumed to have
130 * compare the lines in a with the lines in b. a is assumed to have
128 * a control char at the start of each line, this char is ignored in the
131 * a control char at the start of each line, this char is ignored in the
129 * compare
132 * compare
130 */
133 */
131 static PyObject *
134 static PyObject *
132 testhunk(PyObject *self, PyObject *args)
135 testhunk(PyObject *self, PyObject *args)
133 {
136 {
134
137
135 PyObject *a, *b;
138 PyObject *a, *b;
136 long bstart;
139 long bstart;
137 Py_ssize_t alen, blen;
140 Py_ssize_t alen, blen;
138 Py_ssize_t i;
141 Py_ssize_t i;
139 char *sa, *sb;
142 char *sa, *sb;
140
143
141 if (!PyArg_ParseTuple(args, "OOl", &a, &b, &bstart))
144 if (!PyArg_ParseTuple(args, "OOl", &a, &b, &bstart))
142 return NULL;
145 return NULL;
143 alen = PyList_Size(a);
146 alen = PyList_Size(a);
144 blen = PyList_Size(b);
147 blen = PyList_Size(b);
145 if (alen > blen - bstart || bstart < 0) {
148 if (alen > blen - bstart || bstart < 0) {
146 return Py_BuildValue("l", -1);
149 return Py_BuildValue("l", -1);
147 }
150 }
148 for (i = 0; i < alen; i++) {
151 for (i = 0; i < alen; i++) {
149 sa = PyBytes_AsString(PyList_GET_ITEM(a, i));
152 sa = PyBytes_AsString(PyList_GET_ITEM(a, i));
150 sb = PyBytes_AsString(PyList_GET_ITEM(b, i + bstart));
153 sb = PyBytes_AsString(PyList_GET_ITEM(b, i + bstart));
151 if (strcmp(sa + 1, sb) != 0)
154 if (strcmp(sa + 1, sb) != 0)
152 return Py_BuildValue("l", -1);
155 return Py_BuildValue("l", -1);
153 }
156 }
154 return Py_BuildValue("l", 0);
157 return Py_BuildValue("l", 0);
155 }
158 }
156
159
157 static PyMethodDef methods[] = {
160 static PyMethodDef methods[] = {
158 {"addlines", addlines, METH_VARARGS, "add lines to a hunk\n"},
161 {"addlines", addlines, METH_VARARGS, "add lines to a hunk\n"},
159 {"fix_newline", fix_newline, METH_VARARGS, "fixup newline counters\n"},
162 {"fix_newline", fix_newline, METH_VARARGS, "fixup newline counters\n"},
160 {"testhunk", testhunk, METH_VARARGS, "test lines in a hunk\n"},
163 {"testhunk", testhunk, METH_VARARGS, "test lines in a hunk\n"},
161 {NULL, NULL}
164 {NULL, NULL}
162 };
165 };
163
166
164 #ifdef IS_PY3K
167 #ifdef IS_PY3K
165 static struct PyModuleDef diffhelpers_module = {
168 static struct PyModuleDef diffhelpers_module = {
166 PyModuleDef_HEAD_INIT,
169 PyModuleDef_HEAD_INIT,
167 "diffhelpers",
170 "diffhelpers",
168 diffhelpers_doc,
171 diffhelpers_doc,
169 -1,
172 -1,
170 methods
173 methods
171 };
174 };
172
175
173 PyMODINIT_FUNC PyInit_diffhelpers(void)
176 PyMODINIT_FUNC PyInit_diffhelpers(void)
174 {
177 {
175 PyObject *m;
178 PyObject *m;
176
179
177 m = PyModule_Create(&diffhelpers_module);
180 m = PyModule_Create(&diffhelpers_module);
178 if (m == NULL)
181 if (m == NULL)
179 return NULL;
182 return NULL;
180
183
181 diffhelpers_Error = PyErr_NewException("diffhelpers.diffhelpersError",
184 diffhelpers_Error = PyErr_NewException("diffhelpers.diffhelpersError",
182 NULL, NULL);
185 NULL, NULL);
183 Py_INCREF(diffhelpers_Error);
186 Py_INCREF(diffhelpers_Error);
184 PyModule_AddObject(m, "diffhelpersError", diffhelpers_Error);
187 PyModule_AddObject(m, "diffhelpersError", diffhelpers_Error);
185
188
186 return m;
189 return m;
187 }
190 }
188 #else
191 #else
189 PyMODINIT_FUNC
192 PyMODINIT_FUNC
190 initdiffhelpers(void)
193 initdiffhelpers(void)
191 {
194 {
192 Py_InitModule3("diffhelpers", methods, diffhelpers_doc);
195 Py_InitModule3("diffhelpers", methods, diffhelpers_doc);
193 diffhelpers_Error = PyErr_NewException("diffhelpers.diffhelpersError",
196 diffhelpers_Error = PyErr_NewException("diffhelpers.diffhelpersError",
194 NULL, NULL);
197 NULL, NULL);
195 }
198 }
196 #endif
199 #endif
197
General Comments 0
You need to be logged in to leave comments. Login now