##// END OF EJS Templates
parsers.c: fix comment
Benoit Boissinot -
r13263:c45b5faa default
parent child Browse files
Show More
@@ -1,418 +1,418
1 /*
1 /*
2 parsers.c - efficient content parsing
2 parsers.c - efficient content parsing
3
3
4 Copyright 2008 Matt Mackall <mpm@selenic.com> and others
4 Copyright 2008 Matt Mackall <mpm@selenic.com> and others
5
5
6 This software may be used and distributed according to the terms of
6 This software may be used and distributed according to the terms of
7 the GNU General Public License, incorporated herein by reference.
7 the GNU General Public License, incorporated herein by reference.
8 */
8 */
9
9
10 #include <Python.h>
10 #include <Python.h>
11 #include <ctype.h>
11 #include <ctype.h>
12 #include <string.h>
12 #include <string.h>
13
13
14 #include "util.h"
14 #include "util.h"
15
15
16 static int hexdigit(char c)
16 static int hexdigit(char c)
17 {
17 {
18 if (c >= '0' && c <= '9')
18 if (c >= '0' && c <= '9')
19 return c - '0';
19 return c - '0';
20 if (c >= 'a' && c <= 'f')
20 if (c >= 'a' && c <= 'f')
21 return c - 'a' + 10;
21 return c - 'a' + 10;
22 if (c >= 'A' && c <= 'F')
22 if (c >= 'A' && c <= 'F')
23 return c - 'A' + 10;
23 return c - 'A' + 10;
24
24
25 PyErr_SetString(PyExc_ValueError, "input contains non-hex character");
25 PyErr_SetString(PyExc_ValueError, "input contains non-hex character");
26 return 0;
26 return 0;
27 }
27 }
28
28
29 /*
29 /*
30 * Turn a hex-encoded string into binary.
30 * Turn a hex-encoded string into binary.
31 */
31 */
32 static PyObject *unhexlify(const char *str, int len)
32 static PyObject *unhexlify(const char *str, int len)
33 {
33 {
34 PyObject *ret;
34 PyObject *ret;
35 const char *c;
35 const char *c;
36 char *d;
36 char *d;
37
37
38 ret = PyBytes_FromStringAndSize(NULL, len / 2);
38 ret = PyBytes_FromStringAndSize(NULL, len / 2);
39
39
40 if (!ret)
40 if (!ret)
41 return NULL;
41 return NULL;
42
42
43 d = PyBytes_AsString(ret);
43 d = PyBytes_AsString(ret);
44
44
45 for (c = str; c < str + len;) {
45 for (c = str; c < str + len;) {
46 int hi = hexdigit(*c++);
46 int hi = hexdigit(*c++);
47 int lo = hexdigit(*c++);
47 int lo = hexdigit(*c++);
48 *d++ = (hi << 4) | lo;
48 *d++ = (hi << 4) | lo;
49 }
49 }
50
50
51 return ret;
51 return ret;
52 }
52 }
53
53
54 /*
54 /*
55 * This code assumes that a manifest is stitched together with newline
55 * This code assumes that a manifest is stitched together with newline
56 * ('\n') characters.
56 * ('\n') characters.
57 */
57 */
58 static PyObject *parse_manifest(PyObject *self, PyObject *args)
58 static PyObject *parse_manifest(PyObject *self, PyObject *args)
59 {
59 {
60 PyObject *mfdict, *fdict;
60 PyObject *mfdict, *fdict;
61 char *str, *cur, *start, *zero;
61 char *str, *cur, *start, *zero;
62 int len;
62 int len;
63
63
64 if (!PyArg_ParseTuple(args, "O!O!s#:parse_manifest",
64 if (!PyArg_ParseTuple(args, "O!O!s#:parse_manifest",
65 &PyDict_Type, &mfdict,
65 &PyDict_Type, &mfdict,
66 &PyDict_Type, &fdict,
66 &PyDict_Type, &fdict,
67 &str, &len))
67 &str, &len))
68 goto quit;
68 goto quit;
69
69
70 for (start = cur = str, zero = NULL; cur < str + len; cur++) {
70 for (start = cur = str, zero = NULL; cur < str + len; cur++) {
71 PyObject *file = NULL, *node = NULL;
71 PyObject *file = NULL, *node = NULL;
72 PyObject *flags = NULL;
72 PyObject *flags = NULL;
73 int nlen;
73 int nlen;
74
74
75 if (!*cur) {
75 if (!*cur) {
76 zero = cur;
76 zero = cur;
77 continue;
77 continue;
78 }
78 }
79 else if (*cur != '\n')
79 else if (*cur != '\n')
80 continue;
80 continue;
81
81
82 if (!zero) {
82 if (!zero) {
83 PyErr_SetString(PyExc_ValueError,
83 PyErr_SetString(PyExc_ValueError,
84 "manifest entry has no separator");
84 "manifest entry has no separator");
85 goto quit;
85 goto quit;
86 }
86 }
87
87
88 file = PyBytes_FromStringAndSize(start, zero - start);
88 file = PyBytes_FromStringAndSize(start, zero - start);
89
89
90 if (!file)
90 if (!file)
91 goto bail;
91 goto bail;
92
92
93 nlen = cur - zero - 1;
93 nlen = cur - zero - 1;
94
94
95 node = unhexlify(zero + 1, nlen > 40 ? 40 : nlen);
95 node = unhexlify(zero + 1, nlen > 40 ? 40 : nlen);
96 if (!node)
96 if (!node)
97 goto bail;
97 goto bail;
98
98
99 if (nlen > 40) {
99 if (nlen > 40) {
100 flags = PyBytes_FromStringAndSize(zero + 41,
100 flags = PyBytes_FromStringAndSize(zero + 41,
101 nlen - 40);
101 nlen - 40);
102 if (!flags)
102 if (!flags)
103 goto bail;
103 goto bail;
104
104
105 if (PyDict_SetItem(fdict, file, flags) == -1)
105 if (PyDict_SetItem(fdict, file, flags) == -1)
106 goto bail;
106 goto bail;
107 }
107 }
108
108
109 if (PyDict_SetItem(mfdict, file, node) == -1)
109 if (PyDict_SetItem(mfdict, file, node) == -1)
110 goto bail;
110 goto bail;
111
111
112 start = cur + 1;
112 start = cur + 1;
113 zero = NULL;
113 zero = NULL;
114
114
115 Py_XDECREF(flags);
115 Py_XDECREF(flags);
116 Py_XDECREF(node);
116 Py_XDECREF(node);
117 Py_XDECREF(file);
117 Py_XDECREF(file);
118 continue;
118 continue;
119 bail:
119 bail:
120 Py_XDECREF(flags);
120 Py_XDECREF(flags);
121 Py_XDECREF(node);
121 Py_XDECREF(node);
122 Py_XDECREF(file);
122 Py_XDECREF(file);
123 goto quit;
123 goto quit;
124 }
124 }
125
125
126 if (len > 0 && *(cur - 1) != '\n') {
126 if (len > 0 && *(cur - 1) != '\n') {
127 PyErr_SetString(PyExc_ValueError,
127 PyErr_SetString(PyExc_ValueError,
128 "manifest contains trailing garbage");
128 "manifest contains trailing garbage");
129 goto quit;
129 goto quit;
130 }
130 }
131
131
132 Py_INCREF(Py_None);
132 Py_INCREF(Py_None);
133 return Py_None;
133 return Py_None;
134 quit:
134 quit:
135 return NULL;
135 return NULL;
136 }
136 }
137
137
138 #ifdef _WIN32
138 #ifdef _WIN32
139 #ifdef _MSC_VER
139 #ifdef _MSC_VER
140 /* msvc 6.0 has problems */
140 /* msvc 6.0 has problems */
141 #define inline __inline
141 #define inline __inline
142 typedef unsigned long uint32_t;
142 typedef unsigned long uint32_t;
143 typedef unsigned __int64 uint64_t;
143 typedef unsigned __int64 uint64_t;
144 #else
144 #else
145 #include <stdint.h>
145 #include <stdint.h>
146 #endif
146 #endif
147 static uint32_t ntohl(uint32_t x)
147 static uint32_t ntohl(uint32_t x)
148 {
148 {
149 return ((x & 0x000000ffUL) << 24) |
149 return ((x & 0x000000ffUL) << 24) |
150 ((x & 0x0000ff00UL) << 8) |
150 ((x & 0x0000ff00UL) << 8) |
151 ((x & 0x00ff0000UL) >> 8) |
151 ((x & 0x00ff0000UL) >> 8) |
152 ((x & 0xff000000UL) >> 24);
152 ((x & 0xff000000UL) >> 24);
153 }
153 }
154 #else
154 #else
155 /* not windows */
155 /* not windows */
156 #include <sys/types.h>
156 #include <sys/types.h>
157 #if defined __BEOS__ && !defined __HAIKU__
157 #if defined __BEOS__ && !defined __HAIKU__
158 #include <ByteOrder.h>
158 #include <ByteOrder.h>
159 #else
159 #else
160 #include <arpa/inet.h>
160 #include <arpa/inet.h>
161 #endif
161 #endif
162 #include <inttypes.h>
162 #include <inttypes.h>
163 #endif
163 #endif
164
164
165 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
165 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
166 {
166 {
167 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
167 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
168 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
168 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
169 char *str, *cur, *end, *cpos;
169 char *str, *cur, *end, *cpos;
170 int state, mode, size, mtime;
170 int state, mode, size, mtime;
171 unsigned int flen;
171 unsigned int flen;
172 int len;
172 int len;
173 char decode[16]; /* for alignment */
173 char decode[16]; /* for alignment */
174
174
175 if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate",
175 if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate",
176 &PyDict_Type, &dmap,
176 &PyDict_Type, &dmap,
177 &PyDict_Type, &cmap,
177 &PyDict_Type, &cmap,
178 &str, &len))
178 &str, &len))
179 goto quit;
179 goto quit;
180
180
181 /* read parents */
181 /* read parents */
182 if (len < 40)
182 if (len < 40)
183 goto quit;
183 goto quit;
184
184
185 parents = Py_BuildValue("s#s#", str, 20, str + 20, 20);
185 parents = Py_BuildValue("s#s#", str, 20, str + 20, 20);
186 if (!parents)
186 if (!parents)
187 goto quit;
187 goto quit;
188
188
189 /* read filenames */
189 /* read filenames */
190 cur = str + 40;
190 cur = str + 40;
191 end = str + len;
191 end = str + len;
192
192
193 while (cur < end - 17) {
193 while (cur < end - 17) {
194 /* unpack header */
194 /* unpack header */
195 state = *cur;
195 state = *cur;
196 memcpy(decode, cur + 1, 16);
196 memcpy(decode, cur + 1, 16);
197 mode = ntohl(*(uint32_t *)(decode));
197 mode = ntohl(*(uint32_t *)(decode));
198 size = ntohl(*(uint32_t *)(decode + 4));
198 size = ntohl(*(uint32_t *)(decode + 4));
199 mtime = ntohl(*(uint32_t *)(decode + 8));
199 mtime = ntohl(*(uint32_t *)(decode + 8));
200 flen = ntohl(*(uint32_t *)(decode + 12));
200 flen = ntohl(*(uint32_t *)(decode + 12));
201 cur += 17;
201 cur += 17;
202 if (cur + flen > end || cur + flen < cur) {
202 if (cur + flen > end || cur + flen < cur) {
203 PyErr_SetString(PyExc_ValueError, "overflow in dirstate");
203 PyErr_SetString(PyExc_ValueError, "overflow in dirstate");
204 goto quit;
204 goto quit;
205 }
205 }
206
206
207 entry = Py_BuildValue("ciii", state, mode, size, mtime);
207 entry = Py_BuildValue("ciii", state, mode, size, mtime);
208 if (!entry)
208 if (!entry)
209 goto quit;
209 goto quit;
210 PyObject_GC_UnTrack(entry); /* don't waste time with this */
210 PyObject_GC_UnTrack(entry); /* don't waste time with this */
211
211
212 cpos = memchr(cur, 0, flen);
212 cpos = memchr(cur, 0, flen);
213 if (cpos) {
213 if (cpos) {
214 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
214 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
215 cname = PyBytes_FromStringAndSize(cpos + 1,
215 cname = PyBytes_FromStringAndSize(cpos + 1,
216 flen - (cpos - cur) - 1);
216 flen - (cpos - cur) - 1);
217 if (!fname || !cname ||
217 if (!fname || !cname ||
218 PyDict_SetItem(cmap, fname, cname) == -1 ||
218 PyDict_SetItem(cmap, fname, cname) == -1 ||
219 PyDict_SetItem(dmap, fname, entry) == -1)
219 PyDict_SetItem(dmap, fname, entry) == -1)
220 goto quit;
220 goto quit;
221 Py_DECREF(cname);
221 Py_DECREF(cname);
222 } else {
222 } else {
223 fname = PyBytes_FromStringAndSize(cur, flen);
223 fname = PyBytes_FromStringAndSize(cur, flen);
224 if (!fname ||
224 if (!fname ||
225 PyDict_SetItem(dmap, fname, entry) == -1)
225 PyDict_SetItem(dmap, fname, entry) == -1)
226 goto quit;
226 goto quit;
227 }
227 }
228 cur += flen;
228 cur += flen;
229 Py_DECREF(fname);
229 Py_DECREF(fname);
230 Py_DECREF(entry);
230 Py_DECREF(entry);
231 fname = cname = entry = NULL;
231 fname = cname = entry = NULL;
232 }
232 }
233
233
234 ret = parents;
234 ret = parents;
235 Py_INCREF(ret);
235 Py_INCREF(ret);
236 quit:
236 quit:
237 Py_XDECREF(fname);
237 Py_XDECREF(fname);
238 Py_XDECREF(cname);
238 Py_XDECREF(cname);
239 Py_XDECREF(entry);
239 Py_XDECREF(entry);
240 Py_XDECREF(parents);
240 Py_XDECREF(parents);
241 return ret;
241 return ret;
242 }
242 }
243
243
244 const char nullid[20];
244 const char nullid[20];
245 const int nullrev = -1;
245 const int nullrev = -1;
246
246
247 /* RevlogNG format (all in big endian, data may be inlined):
247 /* RevlogNG format (all in big endian, data may be inlined):
248 * 6 bytes: offset
248 * 6 bytes: offset
249 * 2 bytes: flags
249 * 2 bytes: flags
250 * 4 bytes: compressed length
250 * 4 bytes: compressed length
251 * 4 bytes: uncompressed length
251 * 4 bytes: uncompressed length
252 * 4 bytes: base revision
252 * 4 bytes: base revision
253 * 4 bytes: link revision
253 * 4 bytes: link revision
254 * 4 bytes: parent 1 revision
254 * 4 bytes: parent 1 revision
255 * 4 bytes: parent 2 revision
255 * 4 bytes: parent 2 revision
256 * 32 bytes: nodeid (only 20 bytes used)
256 * 32 bytes: nodeid (only 20 bytes used)
257 */
257 */
258 static int _parse_index_ng(const char *data, int size, int inlined,
258 static int _parse_index_ng(const char *data, int size, int inlined,
259 PyObject *index)
259 PyObject *index)
260 {
260 {
261 PyObject *entry;
261 PyObject *entry;
262 int n = 0, err;
262 int n = 0, err;
263 uint64_t offset_flags;
263 uint64_t offset_flags;
264 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
264 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
265 const char *c_node_id;
265 const char *c_node_id;
266 const char *end = data + size;
266 const char *end = data + size;
267 char decode[64]; /* to enforce alignment with inline data */
267 char decode[64]; /* to enforce alignment with inline data */
268
268
269 while (data < end) {
269 while (data < end) {
270 unsigned int step;
270 unsigned int step;
271
271
272 memcpy(decode, data, 64);
272 memcpy(decode, data, 64);
273 offset_flags = ntohl(*((uint32_t *) (decode + 4)));
273 offset_flags = ntohl(*((uint32_t *) (decode + 4)));
274 if (n == 0) /* mask out version number for the first entry */
274 if (n == 0) /* mask out version number for the first entry */
275 offset_flags &= 0xFFFF;
275 offset_flags &= 0xFFFF;
276 else {
276 else {
277 uint32_t offset_high = ntohl(*((uint32_t *)decode));
277 uint32_t offset_high = ntohl(*((uint32_t *)decode));
278 offset_flags |= ((uint64_t)offset_high) << 32;
278 offset_flags |= ((uint64_t)offset_high) << 32;
279 }
279 }
280
280
281 comp_len = ntohl(*((uint32_t *)(decode + 8)));
281 comp_len = ntohl(*((uint32_t *)(decode + 8)));
282 uncomp_len = ntohl(*((uint32_t *)(decode + 12)));
282 uncomp_len = ntohl(*((uint32_t *)(decode + 12)));
283 base_rev = ntohl(*((uint32_t *)(decode + 16)));
283 base_rev = ntohl(*((uint32_t *)(decode + 16)));
284 link_rev = ntohl(*((uint32_t *)(decode + 20)));
284 link_rev = ntohl(*((uint32_t *)(decode + 20)));
285 parent_1 = ntohl(*((uint32_t *)(decode + 24)));
285 parent_1 = ntohl(*((uint32_t *)(decode + 24)));
286 parent_2 = ntohl(*((uint32_t *)(decode + 28)));
286 parent_2 = ntohl(*((uint32_t *)(decode + 28)));
287 c_node_id = decode + 32;
287 c_node_id = decode + 32;
288
288
289 entry = Py_BuildValue("Liiiiiis#", offset_flags, comp_len,
289 entry = Py_BuildValue("Liiiiiis#", offset_flags, comp_len,
290 uncomp_len, base_rev, link_rev,
290 uncomp_len, base_rev, link_rev,
291 parent_1, parent_2, c_node_id, 20);
291 parent_1, parent_2, c_node_id, 20);
292
292
293 if (!entry)
293 if (!entry)
294 return 0;
294 return 0;
295
295
296 PyObject_GC_UnTrack(entry); /* don't waste time with this */
296 PyObject_GC_UnTrack(entry); /* don't waste time with this */
297
297
298 if (inlined) {
298 if (inlined) {
299 err = PyList_Append(index, entry);
299 err = PyList_Append(index, entry);
300 Py_DECREF(entry);
300 Py_DECREF(entry);
301 if (err)
301 if (err)
302 return 0;
302 return 0;
303 } else
303 } else
304 PyList_SET_ITEM(index, n, entry); /* steals reference */
304 PyList_SET_ITEM(index, n, entry); /* steals reference */
305
305
306 n++;
306 n++;
307 step = 64 + (inlined ? comp_len : 0);
307 step = 64 + (inlined ? comp_len : 0);
308 if (data + step > end || data + step < data)
308 if (data + step > end || data + step < data)
309 break;
309 break;
310 data += step;
310 data += step;
311 }
311 }
312 if (data != end) {
312 if (data != end) {
313 if (!PyErr_Occurred())
313 if (!PyErr_Occurred())
314 PyErr_SetString(PyExc_ValueError, "corrupt index file");
314 PyErr_SetString(PyExc_ValueError, "corrupt index file");
315 return 0;
315 return 0;
316 }
316 }
317
317
318 /* create the magic nullid entry in the index at [-1] */
318 /* create the magic nullid entry in the index at [-1] */
319 entry = Py_BuildValue("Liiiiiis#", (uint64_t)0, 0, 0, -1, -1, -1, -1, nullid, 20);
319 entry = Py_BuildValue("Liiiiiis#", (uint64_t)0, 0, 0, -1, -1, -1, -1, nullid, 20);
320
320
321 if (!entry)
321 if (!entry)
322 return 0;
322 return 0;
323
323
324 PyObject_GC_UnTrack(entry); /* don't waste time with this */
324 PyObject_GC_UnTrack(entry); /* don't waste time with this */
325
325
326 if (inlined) {
326 if (inlined) {
327 err = PyList_Append(index, entry);
327 err = PyList_Append(index, entry);
328 Py_DECREF(entry);
328 Py_DECREF(entry);
329 if (err)
329 if (err)
330 return 0;
330 return 0;
331 } else
331 } else
332 PyList_SET_ITEM(index, n, entry); /* steals reference */
332 PyList_SET_ITEM(index, n, entry); /* steals reference */
333
333
334 return 1;
334 return 1;
335 }
335 }
336
336
337 /* This function parses a index file and returns a Python tuple of the
337 /* This function parses a index file and returns a Python tuple of the
338 * following format: (index, cache)
338 * following format: (index, cache)
339 *
339 *
340 * index: a list of tuples containing the RevlogNG records
340 * index: a list of tuples containing the RevlogNG records
341 * cache: if data is inlined, a tuple (index_file_content, 0) else None
341 * cache: if data is inlined, a tuple (index_file_content, 0) else None
342 */
342 */
343 static PyObject *parse_index2(PyObject *self, PyObject *args)
343 static PyObject *parse_index2(PyObject *self, PyObject *args)
344 {
344 {
345 const char *data;
345 const char *data;
346 int size, inlined;
346 int size, inlined;
347 PyObject *rval = NULL, *index = NULL, *cache = NULL;
347 PyObject *rval = NULL, *index = NULL, *cache = NULL;
348 PyObject *data_obj = NULL, *inlined_obj;
348 PyObject *data_obj = NULL, *inlined_obj;
349
349
350 if (!PyArg_ParseTuple(args, "s#O", &data, &size, &inlined_obj))
350 if (!PyArg_ParseTuple(args, "s#O", &data, &size, &inlined_obj))
351 return NULL;
351 return NULL;
352 inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
352 inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
353
353
354 /* If no data is inlined, we know the size of the index list in
354 /* If no data is inlined, we know the size of the index list in
355 * advance: size divided by size of one one revlog record (64 bytes)
355 * advance: size divided by the size of one revlog record (64 bytes)
356 * plus one for the nullid */
356 * plus one for nullid */
357 index = inlined ? PyList_New(0) : PyList_New(size / 64 + 1);
357 index = inlined ? PyList_New(0) : PyList_New(size / 64 + 1);
358 if (!index)
358 if (!index)
359 goto quit;
359 goto quit;
360
360
361 /* set up the cache return value */
361 /* set up the cache return value */
362 if (inlined) {
362 if (inlined) {
363 /* Note that the reference to data_obj is only borrowed */
363 /* Note that the reference to data_obj is only borrowed */
364 data_obj = PyTuple_GET_ITEM(args, 0);
364 data_obj = PyTuple_GET_ITEM(args, 0);
365 cache = Py_BuildValue("iO", 0, data_obj);
365 cache = Py_BuildValue("iO", 0, data_obj);
366 if (!cache)
366 if (!cache)
367 goto quit;
367 goto quit;
368 } else {
368 } else {
369 cache = Py_None;
369 cache = Py_None;
370 Py_INCREF(Py_None);
370 Py_INCREF(Py_None);
371 }
371 }
372
372
373 /* actually populate the index with data */
373 /* actually populate the index with data */
374 if (!_parse_index_ng(data, size, inlined, index))
374 if (!_parse_index_ng(data, size, inlined, index))
375 goto quit;
375 goto quit;
376
376
377 rval = Py_BuildValue("NN", index, cache);
377 rval = Py_BuildValue("NN", index, cache);
378 if (!rval)
378 if (!rval)
379 goto quit;
379 goto quit;
380 return rval;
380 return rval;
381
381
382 quit:
382 quit:
383 Py_XDECREF(index);
383 Py_XDECREF(index);
384 Py_XDECREF(cache);
384 Py_XDECREF(cache);
385 Py_XDECREF(rval);
385 Py_XDECREF(rval);
386 return NULL;
386 return NULL;
387 }
387 }
388
388
389
389
390 static char parsers_doc[] = "Efficient content parsing.";
390 static char parsers_doc[] = "Efficient content parsing.";
391
391
392 static PyMethodDef methods[] = {
392 static PyMethodDef methods[] = {
393 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
393 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
394 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
394 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
395 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
395 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
396 {NULL, NULL}
396 {NULL, NULL}
397 };
397 };
398
398
399 #ifdef IS_PY3K
399 #ifdef IS_PY3K
400 static struct PyModuleDef parsers_module = {
400 static struct PyModuleDef parsers_module = {
401 PyModuleDef_HEAD_INIT,
401 PyModuleDef_HEAD_INIT,
402 "parsers",
402 "parsers",
403 parsers_doc,
403 parsers_doc,
404 -1,
404 -1,
405 methods
405 methods
406 };
406 };
407
407
408 PyMODINIT_FUNC PyInit_parsers(void)
408 PyMODINIT_FUNC PyInit_parsers(void)
409 {
409 {
410 return PyModule_Create(&parsers_module);
410 return PyModule_Create(&parsers_module);
411 }
411 }
412 #else
412 #else
413 PyMODINIT_FUNC initparsers(void)
413 PyMODINIT_FUNC initparsers(void)
414 {
414 {
415 Py_InitModule3("parsers", methods, parsers_doc);
415 Py_InitModule3("parsers", methods, parsers_doc);
416 }
416 }
417 #endif
417 #endif
418
418
General Comments 0
You need to be logged in to leave comments. Login now