Line data Source code
1 : #include "Python.h"
2 : #include "code.h"
3 : #include "structmember.h"
4 :
5 : #define NAME_CHARS \
6 : "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
7 :
8 : /* all_name_chars(s): true iff all chars in s are valid NAME_CHARS */
9 :
10 : static int
11 11001 : all_name_chars(PyObject *o)
12 : {
13 : static char ok_name_char[256];
14 : static unsigned char *name_chars = (unsigned char *)NAME_CHARS;
15 11001 : PyUnicodeObject *u = (PyUnicodeObject *)o;
16 : const unsigned char *s;
17 :
18 18178 : if (!PyUnicode_Check(o) || PyUnicode_READY(u) == -1 ||
19 7177 : PyUnicode_MAX_CHAR_VALUE(u) >= 128)
20 3909 : return 0;
21 :
22 7092 : if (ok_name_char[*name_chars] == 0) {
23 : unsigned char *p;
24 64 : for (p = name_chars; *p; p++)
25 63 : ok_name_char[*p] = 1;
26 : }
27 7092 : s = PyUnicode_1BYTE_DATA(u);
28 64085 : while (*s) {
29 53239 : if (ok_name_char[*s++] == 0)
30 3338 : return 0;
31 : }
32 3754 : return 1;
33 : }
34 :
35 : static void
36 5364 : intern_strings(PyObject *tuple)
37 : {
38 : Py_ssize_t i;
39 :
40 23180 : for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
41 12452 : PyObject *v = PyTuple_GET_ITEM(tuple, i);
42 12452 : if (v == NULL || !PyUnicode_CheckExact(v)) {
43 0 : Py_FatalError("non-string found in code slot");
44 : }
45 12452 : PyUnicode_InternInPlace(&PyTuple_GET_ITEM(tuple, i));
46 : }
47 5364 : }
48 :
49 :
50 : PyCodeObject *
51 1341 : PyCode_New(int argcount, int kwonlyargcount,
52 : int nlocals, int stacksize, int flags,
53 : PyObject *code, PyObject *consts, PyObject *names,
54 : PyObject *varnames, PyObject *freevars, PyObject *cellvars,
55 : PyObject *filename, PyObject *name, int firstlineno,
56 : PyObject *lnotab)
57 : {
58 : PyCodeObject *co;
59 1341 : unsigned char *cell2arg = NULL;
60 : Py_ssize_t i, n_cellvars;
61 :
62 : /* Check argument types */
63 1341 : if (argcount < 0 || kwonlyargcount < 0 || nlocals < 0 ||
64 1341 : code == NULL ||
65 1341 : consts == NULL || !PyTuple_Check(consts) ||
66 1341 : names == NULL || !PyTuple_Check(names) ||
67 1341 : varnames == NULL || !PyTuple_Check(varnames) ||
68 1341 : freevars == NULL || !PyTuple_Check(freevars) ||
69 1341 : cellvars == NULL || !PyTuple_Check(cellvars) ||
70 1341 : name == NULL || !PyUnicode_Check(name) ||
71 1341 : filename == NULL || !PyUnicode_Check(filename) ||
72 2682 : lnotab == NULL || !PyBytes_Check(lnotab) ||
73 1341 : !PyObject_CheckReadBuffer(code)) {
74 0 : PyErr_BadInternalCall();
75 0 : return NULL;
76 : }
77 1341 : n_cellvars = PyTuple_GET_SIZE(cellvars);
78 1341 : intern_strings(names);
79 1341 : intern_strings(varnames);
80 1341 : intern_strings(freevars);
81 1341 : intern_strings(cellvars);
82 : /* Intern selected string constants */
83 13683 : for (i = PyTuple_GET_SIZE(consts); --i >= 0; ) {
84 11001 : PyObject *v = PyTuple_GetItem(consts, i);
85 11001 : if (!all_name_chars(v))
86 7247 : continue;
87 3754 : PyUnicode_InternInPlace(&PyTuple_GET_ITEM(consts, i));
88 : }
89 : /* Create mapping between cells and arguments if needed. */
90 1341 : if (n_cellvars) {
91 123 : Py_ssize_t total_args = argcount + kwonlyargcount +
92 82 : ((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0);
93 41 : Py_ssize_t alloc_size = sizeof(unsigned char) * n_cellvars;
94 41 : int used_cell2arg = 0;
95 41 : cell2arg = PyMem_MALLOC(alloc_size);
96 41 : if (cell2arg == NULL)
97 0 : return NULL;
98 41 : memset(cell2arg, CO_CELL_NOT_AN_ARG, alloc_size);
99 : /* Find cells which are also arguments. */
100 104 : for (i = 0; i < n_cellvars; i++) {
101 : Py_ssize_t j;
102 63 : PyObject *cell = PyTuple_GET_ITEM(cellvars, i);
103 126 : for (j = 0; j < total_args; j++) {
104 90 : PyObject *arg = PyTuple_GET_ITEM(varnames, j);
105 90 : if (!PyUnicode_Compare(cell, arg)) {
106 27 : cell2arg[i] = j;
107 27 : used_cell2arg = 1;
108 27 : break;
109 : }
110 : }
111 : }
112 41 : if (!used_cell2arg) {
113 16 : PyMem_FREE(cell2arg);
114 16 : cell2arg = NULL;
115 : }
116 : }
117 1341 : co = PyObject_NEW(PyCodeObject, &PyCode_Type);
118 1341 : if (co == NULL) {
119 0 : if (cell2arg)
120 0 : PyMem_FREE(cell2arg);
121 0 : return NULL;
122 : }
123 1341 : co->co_argcount = argcount;
124 1341 : co->co_kwonlyargcount = kwonlyargcount;
125 1341 : co->co_nlocals = nlocals;
126 1341 : co->co_stacksize = stacksize;
127 1341 : co->co_flags = flags;
128 1341 : Py_INCREF(code);
129 1341 : co->co_code = code;
130 1341 : Py_INCREF(consts);
131 1341 : co->co_consts = consts;
132 1341 : Py_INCREF(names);
133 1341 : co->co_names = names;
134 1341 : Py_INCREF(varnames);
135 1341 : co->co_varnames = varnames;
136 1341 : Py_INCREF(freevars);
137 1341 : co->co_freevars = freevars;
138 1341 : Py_INCREF(cellvars);
139 1341 : co->co_cellvars = cellvars;
140 1341 : co->co_cell2arg = cell2arg;
141 1341 : Py_INCREF(filename);
142 1341 : co->co_filename = filename;
143 1341 : Py_INCREF(name);
144 1341 : co->co_name = name;
145 1341 : co->co_firstlineno = firstlineno;
146 1341 : Py_INCREF(lnotab);
147 1341 : co->co_lnotab = lnotab;
148 1341 : co->co_zombieframe = NULL;
149 1341 : co->co_weakreflist = NULL;
150 1341 : return co;
151 : }
152 :
153 : PyCodeObject *
154 0 : PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
155 : {
156 : static PyObject *emptystring = NULL;
157 : static PyObject *nulltuple = NULL;
158 0 : PyObject *filename_ob = NULL;
159 0 : PyObject *funcname_ob = NULL;
160 0 : PyCodeObject *result = NULL;
161 0 : if (emptystring == NULL) {
162 0 : emptystring = PyBytes_FromString("");
163 0 : if (emptystring == NULL)
164 0 : goto failed;
165 : }
166 0 : if (nulltuple == NULL) {
167 0 : nulltuple = PyTuple_New(0);
168 0 : if (nulltuple == NULL)
169 0 : goto failed;
170 : }
171 0 : funcname_ob = PyUnicode_FromString(funcname);
172 0 : if (funcname_ob == NULL)
173 0 : goto failed;
174 0 : filename_ob = PyUnicode_DecodeFSDefault(filename);
175 0 : if (filename_ob == NULL)
176 0 : goto failed;
177 :
178 0 : result = PyCode_New(0, /* argcount */
179 : 0, /* kwonlyargcount */
180 : 0, /* nlocals */
181 : 0, /* stacksize */
182 : 0, /* flags */
183 : emptystring, /* code */
184 : nulltuple, /* consts */
185 : nulltuple, /* names */
186 : nulltuple, /* varnames */
187 : nulltuple, /* freevars */
188 : nulltuple, /* cellvars */
189 : filename_ob, /* filename */
190 : funcname_ob, /* name */
191 : firstlineno, /* firstlineno */
192 : emptystring /* lnotab */
193 : );
194 :
195 : failed:
196 0 : Py_XDECREF(funcname_ob);
197 0 : Py_XDECREF(filename_ob);
198 0 : return result;
199 : }
200 :
201 : #define OFF(x) offsetof(PyCodeObject, x)
202 :
203 : static PyMemberDef code_memberlist[] = {
204 : {"co_argcount", T_INT, OFF(co_argcount), READONLY},
205 : {"co_kwonlyargcount", T_INT, OFF(co_kwonlyargcount), READONLY},
206 : {"co_nlocals", T_INT, OFF(co_nlocals), READONLY},
207 : {"co_stacksize",T_INT, OFF(co_stacksize), READONLY},
208 : {"co_flags", T_INT, OFF(co_flags), READONLY},
209 : {"co_code", T_OBJECT, OFF(co_code), READONLY},
210 : {"co_consts", T_OBJECT, OFF(co_consts), READONLY},
211 : {"co_names", T_OBJECT, OFF(co_names), READONLY},
212 : {"co_varnames", T_OBJECT, OFF(co_varnames), READONLY},
213 : {"co_freevars", T_OBJECT, OFF(co_freevars), READONLY},
214 : {"co_cellvars", T_OBJECT, OFF(co_cellvars), READONLY},
215 : {"co_filename", T_OBJECT, OFF(co_filename), READONLY},
216 : {"co_name", T_OBJECT, OFF(co_name), READONLY},
217 : {"co_firstlineno", T_INT, OFF(co_firstlineno), READONLY},
218 : {"co_lnotab", T_OBJECT, OFF(co_lnotab), READONLY},
219 : {NULL} /* Sentinel */
220 : };
221 :
222 : /* Helper for code_new: return a shallow copy of a tuple that is
223 : guaranteed to contain exact strings, by converting string subclasses
224 : to exact strings and complaining if a non-string is found. */
225 : static PyObject*
226 0 : validate_and_copy_tuple(PyObject *tup)
227 : {
228 : PyObject *newtuple;
229 : PyObject *item;
230 : Py_ssize_t i, len;
231 :
232 0 : len = PyTuple_GET_SIZE(tup);
233 0 : newtuple = PyTuple_New(len);
234 0 : if (newtuple == NULL)
235 0 : return NULL;
236 :
237 0 : for (i = 0; i < len; i++) {
238 0 : item = PyTuple_GET_ITEM(tup, i);
239 0 : if (PyUnicode_CheckExact(item)) {
240 0 : Py_INCREF(item);
241 : }
242 0 : else if (!PyUnicode_Check(item)) {
243 0 : PyErr_Format(
244 : PyExc_TypeError,
245 : "name tuples must contain only "
246 : "strings, not '%.500s'",
247 0 : item->ob_type->tp_name);
248 0 : Py_DECREF(newtuple);
249 0 : return NULL;
250 : }
251 : else {
252 0 : item = _PyUnicode_Copy(item);
253 0 : if (item == NULL) {
254 0 : Py_DECREF(newtuple);
255 0 : return NULL;
256 : }
257 : }
258 0 : PyTuple_SET_ITEM(newtuple, i, item);
259 : }
260 :
261 0 : return newtuple;
262 : }
263 :
264 : PyDoc_STRVAR(code_doc,
265 : "code(argcount, kwonlyargcount, nlocals, stacksize, flags, codestring,\n\
266 : constants, names, varnames, filename, name, firstlineno,\n\
267 : lnotab[, freevars[, cellvars]])\n\
268 : \n\
269 : Create a code object. Not for the faint of heart.");
270 :
271 : static PyObject *
272 0 : code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
273 : {
274 : int argcount;
275 : int kwonlyargcount;
276 : int nlocals;
277 : int stacksize;
278 : int flags;
279 0 : PyObject *co = NULL;
280 : PyObject *code;
281 : PyObject *consts;
282 0 : PyObject *names, *ournames = NULL;
283 0 : PyObject *varnames, *ourvarnames = NULL;
284 0 : PyObject *freevars = NULL, *ourfreevars = NULL;
285 0 : PyObject *cellvars = NULL, *ourcellvars = NULL;
286 : PyObject *filename;
287 : PyObject *name;
288 : int firstlineno;
289 : PyObject *lnotab;
290 :
291 0 : if (!PyArg_ParseTuple(args, "iiiiiSO!O!O!UUiS|O!O!:code",
292 : &argcount, &kwonlyargcount,
293 : &nlocals, &stacksize, &flags,
294 : &code,
295 : &PyTuple_Type, &consts,
296 : &PyTuple_Type, &names,
297 : &PyTuple_Type, &varnames,
298 : &filename, &name,
299 : &firstlineno, &lnotab,
300 : &PyTuple_Type, &freevars,
301 : &PyTuple_Type, &cellvars))
302 0 : return NULL;
303 :
304 0 : if (argcount < 0) {
305 0 : PyErr_SetString(
306 : PyExc_ValueError,
307 : "code: argcount must not be negative");
308 0 : goto cleanup;
309 : }
310 :
311 0 : if (kwonlyargcount < 0) {
312 0 : PyErr_SetString(
313 : PyExc_ValueError,
314 : "code: kwonlyargcount must not be negative");
315 0 : goto cleanup;
316 : }
317 0 : if (nlocals < 0) {
318 0 : PyErr_SetString(
319 : PyExc_ValueError,
320 : "code: nlocals must not be negative");
321 0 : goto cleanup;
322 : }
323 :
324 0 : ournames = validate_and_copy_tuple(names);
325 0 : if (ournames == NULL)
326 0 : goto cleanup;
327 0 : ourvarnames = validate_and_copy_tuple(varnames);
328 0 : if (ourvarnames == NULL)
329 0 : goto cleanup;
330 0 : if (freevars)
331 0 : ourfreevars = validate_and_copy_tuple(freevars);
332 : else
333 0 : ourfreevars = PyTuple_New(0);
334 0 : if (ourfreevars == NULL)
335 0 : goto cleanup;
336 0 : if (cellvars)
337 0 : ourcellvars = validate_and_copy_tuple(cellvars);
338 : else
339 0 : ourcellvars = PyTuple_New(0);
340 0 : if (ourcellvars == NULL)
341 0 : goto cleanup;
342 :
343 0 : co = (PyObject *)PyCode_New(argcount, kwonlyargcount,
344 : nlocals, stacksize, flags,
345 : code, consts, ournames, ourvarnames,
346 : ourfreevars, ourcellvars, filename,
347 : name, firstlineno, lnotab);
348 : cleanup:
349 0 : Py_XDECREF(ournames);
350 0 : Py_XDECREF(ourvarnames);
351 0 : Py_XDECREF(ourfreevars);
352 0 : Py_XDECREF(ourcellvars);
353 0 : return co;
354 : }
355 :
356 : static void
357 204 : code_dealloc(PyCodeObject *co)
358 : {
359 204 : Py_XDECREF(co->co_code);
360 204 : Py_XDECREF(co->co_consts);
361 204 : Py_XDECREF(co->co_names);
362 204 : Py_XDECREF(co->co_varnames);
363 204 : Py_XDECREF(co->co_freevars);
364 204 : Py_XDECREF(co->co_cellvars);
365 204 : Py_XDECREF(co->co_filename);
366 204 : Py_XDECREF(co->co_name);
367 204 : Py_XDECREF(co->co_lnotab);
368 204 : if (co->co_cell2arg != NULL)
369 1 : PyMem_FREE(co->co_cell2arg);
370 204 : if (co->co_zombieframe != NULL)
371 170 : PyObject_GC_Del(co->co_zombieframe);
372 204 : if (co->co_weakreflist != NULL)
373 0 : PyObject_ClearWeakRefs((PyObject*)co);
374 204 : PyObject_DEL(co);
375 204 : }
376 :
377 : static PyObject *
378 0 : code_sizeof(PyCodeObject *co, void *unused)
379 : {
380 : Py_ssize_t res;
381 :
382 0 : res = sizeof(PyCodeObject);
383 0 : if (co->co_cell2arg != NULL && co->co_cellvars != NULL)
384 0 : res += PyTuple_GET_SIZE(co->co_cellvars) * sizeof(unsigned char);
385 0 : return PyLong_FromSsize_t(res);
386 : }
387 :
388 : static PyObject *
389 0 : code_repr(PyCodeObject *co)
390 : {
391 : int lineno;
392 0 : if (co->co_firstlineno != 0)
393 0 : lineno = co->co_firstlineno;
394 : else
395 0 : lineno = -1;
396 0 : if (co->co_filename && PyUnicode_Check(co->co_filename)) {
397 0 : return PyUnicode_FromFormat(
398 : "<code object %U at %p, file \"%U\", line %d>",
399 : co->co_name, co, co->co_filename, lineno);
400 : } else {
401 0 : return PyUnicode_FromFormat(
402 : "<code object %U at %p, file ???, line %d>",
403 : co->co_name, co, lineno);
404 : }
405 : }
406 :
407 : static PyObject *
408 0 : code_richcompare(PyObject *self, PyObject *other, int op)
409 : {
410 : PyCodeObject *co, *cp;
411 : int eq;
412 : PyObject *res;
413 :
414 0 : if ((op != Py_EQ && op != Py_NE) ||
415 0 : !PyCode_Check(self) ||
416 0 : !PyCode_Check(other)) {
417 0 : Py_RETURN_NOTIMPLEMENTED;
418 : }
419 :
420 0 : co = (PyCodeObject *)self;
421 0 : cp = (PyCodeObject *)other;
422 :
423 0 : eq = PyObject_RichCompareBool(co->co_name, cp->co_name, Py_EQ);
424 0 : if (eq <= 0) goto unequal;
425 0 : eq = co->co_argcount == cp->co_argcount;
426 0 : if (!eq) goto unequal;
427 0 : eq = co->co_kwonlyargcount == cp->co_kwonlyargcount;
428 0 : if (!eq) goto unequal;
429 0 : eq = co->co_nlocals == cp->co_nlocals;
430 0 : if (!eq) goto unequal;
431 0 : eq = co->co_flags == cp->co_flags;
432 0 : if (!eq) goto unequal;
433 0 : eq = co->co_firstlineno == cp->co_firstlineno;
434 0 : if (!eq) goto unequal;
435 0 : eq = PyObject_RichCompareBool(co->co_code, cp->co_code, Py_EQ);
436 0 : if (eq <= 0) goto unequal;
437 0 : eq = PyObject_RichCompareBool(co->co_consts, cp->co_consts, Py_EQ);
438 0 : if (eq <= 0) goto unequal;
439 0 : eq = PyObject_RichCompareBool(co->co_names, cp->co_names, Py_EQ);
440 0 : if (eq <= 0) goto unequal;
441 0 : eq = PyObject_RichCompareBool(co->co_varnames, cp->co_varnames, Py_EQ);
442 0 : if (eq <= 0) goto unequal;
443 0 : eq = PyObject_RichCompareBool(co->co_freevars, cp->co_freevars, Py_EQ);
444 0 : if (eq <= 0) goto unequal;
445 0 : eq = PyObject_RichCompareBool(co->co_cellvars, cp->co_cellvars, Py_EQ);
446 0 : if (eq <= 0) goto unequal;
447 :
448 0 : if (op == Py_EQ)
449 0 : res = Py_True;
450 : else
451 0 : res = Py_False;
452 0 : goto done;
453 :
454 : unequal:
455 0 : if (eq < 0)
456 0 : return NULL;
457 0 : if (op == Py_NE)
458 0 : res = Py_True;
459 : else
460 0 : res = Py_False;
461 :
462 : done:
463 0 : Py_INCREF(res);
464 0 : return res;
465 : }
466 :
467 : static Py_hash_t
468 102 : code_hash(PyCodeObject *co)
469 : {
470 : Py_hash_t h, h0, h1, h2, h3, h4, h5, h6;
471 102 : h0 = PyObject_Hash(co->co_name);
472 102 : if (h0 == -1) return -1;
473 102 : h1 = PyObject_Hash(co->co_code);
474 102 : if (h1 == -1) return -1;
475 102 : h2 = PyObject_Hash(co->co_consts);
476 102 : if (h2 == -1) return -1;
477 102 : h3 = PyObject_Hash(co->co_names);
478 102 : if (h3 == -1) return -1;
479 102 : h4 = PyObject_Hash(co->co_varnames);
480 102 : if (h4 == -1) return -1;
481 102 : h5 = PyObject_Hash(co->co_freevars);
482 102 : if (h5 == -1) return -1;
483 102 : h6 = PyObject_Hash(co->co_cellvars);
484 102 : if (h6 == -1) return -1;
485 306 : h = h0 ^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^
486 306 : co->co_argcount ^ co->co_kwonlyargcount ^
487 204 : co->co_nlocals ^ co->co_flags;
488 102 : if (h == -1) h = -2;
489 102 : return h;
490 : }
491 :
492 : /* XXX code objects need to participate in GC? */
493 :
494 : static struct PyMethodDef code_methods[] = {
495 : {"__sizeof__", (PyCFunction)code_sizeof, METH_NOARGS},
496 : {NULL, NULL} /* sentinel */
497 : };
498 :
499 : PyTypeObject PyCode_Type = {
500 : PyVarObject_HEAD_INIT(&PyType_Type, 0)
501 : "code",
502 : sizeof(PyCodeObject),
503 : 0,
504 : (destructor)code_dealloc, /* tp_dealloc */
505 : 0, /* tp_print */
506 : 0, /* tp_getattr */
507 : 0, /* tp_setattr */
508 : 0, /* tp_reserved */
509 : (reprfunc)code_repr, /* tp_repr */
510 : 0, /* tp_as_number */
511 : 0, /* tp_as_sequence */
512 : 0, /* tp_as_mapping */
513 : (hashfunc)code_hash, /* tp_hash */
514 : 0, /* tp_call */
515 : 0, /* tp_str */
516 : PyObject_GenericGetAttr, /* tp_getattro */
517 : 0, /* tp_setattro */
518 : 0, /* tp_as_buffer */
519 : Py_TPFLAGS_DEFAULT, /* tp_flags */
520 : code_doc, /* tp_doc */
521 : 0, /* tp_traverse */
522 : 0, /* tp_clear */
523 : code_richcompare, /* tp_richcompare */
524 : offsetof(PyCodeObject, co_weakreflist), /* tp_weaklistoffset */
525 : 0, /* tp_iter */
526 : 0, /* tp_iternext */
527 : code_methods, /* tp_methods */
528 : code_memberlist, /* tp_members */
529 : 0, /* tp_getset */
530 : 0, /* tp_base */
531 : 0, /* tp_dict */
532 : 0, /* tp_descr_get */
533 : 0, /* tp_descr_set */
534 : 0, /* tp_dictoffset */
535 : 0, /* tp_init */
536 : 0, /* tp_alloc */
537 : code_new, /* tp_new */
538 : };
539 :
540 : /* Use co_lnotab to compute the line number from a bytecode index, addrq. See
541 : lnotab_notes.txt for the details of the lnotab representation.
542 : */
543 :
544 : int
545 1273 : PyCode_Addr2Line(PyCodeObject *co, int addrq)
546 : {
547 1273 : Py_ssize_t size = PyBytes_Size(co->co_lnotab) / 2;
548 1273 : unsigned char *p = (unsigned char*)PyBytes_AsString(co->co_lnotab);
549 1273 : int line = co->co_firstlineno;
550 1273 : int addr = 0;
551 7991 : while (--size >= 0) {
552 6011 : addr += *p++;
553 6011 : if (addr > addrq)
554 566 : break;
555 5445 : line += *p++;
556 : }
557 1273 : return line;
558 : }
559 :
560 : /* Update *bounds to describe the first and one-past-the-last instructions in
561 : the same line as lasti. Return the number of that line. */
562 : int
563 0 : _PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds)
564 : {
565 : Py_ssize_t size;
566 : int addr, line;
567 : unsigned char* p;
568 :
569 0 : p = (unsigned char*)PyBytes_AS_STRING(co->co_lnotab);
570 0 : size = PyBytes_GET_SIZE(co->co_lnotab) / 2;
571 :
572 0 : addr = 0;
573 0 : line = co->co_firstlineno;
574 : assert(line > 0);
575 :
576 : /* possible optimization: if f->f_lasti == instr_ub
577 : (likely to be a common case) then we already know
578 : instr_lb -- if we stored the matching value of p
579 : somwhere we could skip the first while loop. */
580 :
581 : /* See lnotab_notes.txt for the description of
582 : co_lnotab. A point to remember: increments to p
583 : come in (addr, line) pairs. */
584 :
585 0 : bounds->ap_lower = 0;
586 0 : while (size > 0) {
587 0 : if (addr + *p > lasti)
588 0 : break;
589 0 : addr += *p++;
590 0 : if (*p)
591 0 : bounds->ap_lower = addr;
592 0 : line += *p++;
593 0 : --size;
594 : }
595 :
596 0 : if (size > 0) {
597 0 : while (--size >= 0) {
598 0 : addr += *p++;
599 0 : if (*p++)
600 0 : break;
601 : }
602 0 : bounds->ap_upper = addr;
603 : }
604 : else {
605 0 : bounds->ap_upper = INT_MAX;
606 : }
607 :
608 0 : return line;
609 : }
|