mirror of
https://github.com/python/cpython.git
synced 2025-11-01 06:01:29 +00:00
Recorded merge of revisions 81029 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r81029 | antoine.pitrou | 2010-05-09 16:46:46 +0200 (dim., 09 mai 2010) | 3 lines Untabify C files. Will watch buildbots. ........
This commit is contained in:
parent
bd25030019
commit
f95a1b3c53
248 changed files with 113361 additions and 113361 deletions
|
|
@ -85,10 +85,10 @@ get_default_action(void)
|
|||
|
||||
default_action = get_warnings_attr("defaultaction");
|
||||
if (default_action == NULL) {
|
||||
if (PyErr_Occurred()) {
|
||||
return NULL;
|
||||
}
|
||||
return _default_action;
|
||||
if (PyErr_Occurred()) {
|
||||
return NULL;
|
||||
}
|
||||
return _default_action;
|
||||
}
|
||||
|
||||
Py_DECREF(_default_action);
|
||||
|
|
@ -202,12 +202,12 @@ normalize_module(PyObject *filename)
|
|||
|
||||
mod_str = _PyUnicode_AsString(filename);
|
||||
if (mod_str == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
len = PyUnicode_GetSize(filename);
|
||||
if (len < 0)
|
||||
return NULL;
|
||||
if (len >= 3 &&
|
||||
strncmp(mod_str + (len - 3), ".py", 3) == 0) {
|
||||
strncmp(mod_str + (len - 3), ".py", 3) == 0) {
|
||||
module = PyUnicode_FromStringAndSize(mod_str, len-3);
|
||||
}
|
||||
else {
|
||||
|
|
@ -243,15 +243,15 @@ static void
|
|||
show_warning(PyObject *filename, int lineno, PyObject *text, PyObject
|
||||
*category, PyObject *sourceline)
|
||||
{
|
||||
PyObject *f_stderr;
|
||||
PyObject *name;
|
||||
PyObject *f_stderr;
|
||||
PyObject *name;
|
||||
char lineno_str[128];
|
||||
|
||||
PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno);
|
||||
|
||||
name = PyObject_GetAttrString(category, "__name__");
|
||||
if (name == NULL) /* XXX Can an object lack a '__name__' attribute? */
|
||||
return;
|
||||
return;
|
||||
|
||||
f_stderr = PySys_GetObject("stderr");
|
||||
if (f_stderr == NULL) {
|
||||
|
|
@ -272,8 +272,8 @@ show_warning(PyObject *filename, int lineno, PyObject *text, PyObject
|
|||
/* Print " source_line\n" */
|
||||
if (sourceline) {
|
||||
char *source_line_str = _PyUnicode_AsString(sourceline);
|
||||
if (source_line_str == NULL)
|
||||
return;
|
||||
if (source_line_str == NULL)
|
||||
return;
|
||||
while (*source_line_str == ' ' || *source_line_str == '\t' ||
|
||||
*source_line_str == '\014')
|
||||
source_line_str++;
|
||||
|
|
@ -284,12 +284,12 @@ show_warning(PyObject *filename, int lineno, PyObject *text, PyObject
|
|||
else
|
||||
if (_Py_DisplaySourceLine(f_stderr, _PyUnicode_AsString(filename),
|
||||
lineno, 2) < 0)
|
||||
return;
|
||||
return;
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
warn_explicit(PyObject *category, PyObject *message,
|
||||
warn_explicit(PyObject *category, PyObject *message,
|
||||
PyObject *filename, int lineno,
|
||||
PyObject *module, PyObject *registry, PyObject *sourceline)
|
||||
{
|
||||
|
|
@ -297,7 +297,7 @@ warn_explicit(PyObject *category, PyObject *message,
|
|||
PyObject *item = Py_None;
|
||||
const char *action;
|
||||
int rc;
|
||||
|
||||
|
||||
if (registry && !PyDict_Check(registry) && (registry != Py_None)) {
|
||||
PyErr_SetString(PyExc_TypeError, "'registry' must be a dict");
|
||||
return NULL;
|
||||
|
|
@ -344,7 +344,7 @@ warn_explicit(PyObject *category, PyObject *message,
|
|||
rc = already_warned(registry, key, 0);
|
||||
if (rc == -1)
|
||||
goto cleanup;
|
||||
else if (rc == 1)
|
||||
else if (rc == 1)
|
||||
goto return_none;
|
||||
/* Else this warning hasn't been generated before. */
|
||||
}
|
||||
|
|
@ -374,12 +374,12 @@ warn_explicit(PyObject *category, PyObject *message,
|
|||
goto cleanup;
|
||||
}
|
||||
/* _once_registry[(text, category)] = 1 */
|
||||
rc = update_registry(registry, text, category, 0);
|
||||
rc = update_registry(registry, text, category, 0);
|
||||
}
|
||||
else if (strcmp(action, "module") == 0) {
|
||||
/* registry[(text, category, 0)] = 1 */
|
||||
if (registry != NULL && registry != Py_None)
|
||||
rc = update_registry(registry, text, category, 0);
|
||||
rc = update_registry(registry, text, category, 0);
|
||||
}
|
||||
else if (strcmp(action, "default") != 0) {
|
||||
PyObject *to_str = PyObject_Str(item);
|
||||
|
|
@ -387,9 +387,9 @@ warn_explicit(PyObject *category, PyObject *message,
|
|||
|
||||
if (to_str != NULL) {
|
||||
err_str = _PyUnicode_AsString(to_str);
|
||||
if (err_str == NULL)
|
||||
goto cleanup;
|
||||
}
|
||||
if (err_str == NULL)
|
||||
goto cleanup;
|
||||
}
|
||||
PyErr_Format(PyExc_RuntimeError,
|
||||
"Unrecognized action (%s) in warnings.filters:\n %s",
|
||||
action, err_str);
|
||||
|
|
@ -500,7 +500,7 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
|
|||
if (*filename != NULL) {
|
||||
Py_ssize_t len = PyUnicode_GetSize(*filename);
|
||||
const char *file_str = _PyUnicode_AsString(*filename);
|
||||
if (file_str == NULL || (len < 0 && PyErr_Occurred()))
|
||||
if (file_str == NULL || (len < 0 && PyErr_Occurred()))
|
||||
goto handle_error;
|
||||
|
||||
/* if filename.lower().endswith((".pyc", ".pyo")): */
|
||||
|
|
@ -512,16 +512,16 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
|
|||
tolower(file_str[len-1]) == 'o'))
|
||||
{
|
||||
*filename = PyUnicode_FromStringAndSize(file_str, len-1);
|
||||
if (*filename == NULL)
|
||||
goto handle_error;
|
||||
}
|
||||
else
|
||||
if (*filename == NULL)
|
||||
goto handle_error;
|
||||
}
|
||||
else
|
||||
Py_INCREF(*filename);
|
||||
}
|
||||
else {
|
||||
const char *module_str = _PyUnicode_AsString(*module);
|
||||
if (module_str == NULL)
|
||||
goto handle_error;
|
||||
if (module_str == NULL)
|
||||
goto handle_error;
|
||||
if (strcmp(module_str, "__main__") == 0) {
|
||||
PyObject *argv = PySys_GetObject("argv");
|
||||
if (argv != NULL && PyList_Size(argv) > 0) {
|
||||
|
|
@ -544,8 +544,8 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
|
|||
else {
|
||||
/* embedded interpreters don't have sys.argv, see bug #839151 */
|
||||
*filename = PyUnicode_FromString("__main__");
|
||||
if (*filename == NULL)
|
||||
goto handle_error;
|
||||
if (*filename == NULL)
|
||||
goto handle_error;
|
||||
}
|
||||
}
|
||||
if (*filename == NULL) {
|
||||
|
|
@ -616,7 +616,7 @@ warnings_warn(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
PyObject *message, *category = NULL;
|
||||
Py_ssize_t stack_level = 1;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list,
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list,
|
||||
&message, &category, &stack_level))
|
||||
return NULL;
|
||||
|
||||
|
|
@ -794,7 +794,7 @@ static PyMethodDef warnings_functions[] = {
|
|||
METH_VARARGS | METH_KEYWORDS, warn_explicit_doc},
|
||||
/* XXX(brett.cannon): add showwarning? */
|
||||
/* XXX(brett.cannon): Reasonable to add formatwarning? */
|
||||
{NULL, NULL} /* sentinel */
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -875,15 +875,15 @@ init_filters(void)
|
|||
}
|
||||
|
||||
static struct PyModuleDef warningsmodule = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
MODULE_NAME,
|
||||
warnings__doc__,
|
||||
0,
|
||||
warnings_functions,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
PyModuleDef_HEAD_INIT,
|
||||
MODULE_NAME,
|
||||
warnings__doc__,
|
||||
0,
|
||||
warnings_functions,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,61 +4,61 @@
|
|||
asdl_seq *
|
||||
asdl_seq_new(int size, PyArena *arena)
|
||||
{
|
||||
asdl_seq *seq = NULL;
|
||||
size_t n = (size ? (sizeof(void *) * (size - 1)) : 0);
|
||||
asdl_seq *seq = NULL;
|
||||
size_t n = (size ? (sizeof(void *) * (size - 1)) : 0);
|
||||
|
||||
/* check size is sane */
|
||||
if (size < 0 || size == INT_MIN ||
|
||||
(size && ((size - 1) > (PY_SIZE_MAX / sizeof(void *))))) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
/* check size is sane */
|
||||
if (size < 0 || size == INT_MIN ||
|
||||
(size && ((size - 1) > (PY_SIZE_MAX / sizeof(void *))))) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check if size can be added safely */
|
||||
if (n > PY_SIZE_MAX - sizeof(asdl_seq)) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
/* check if size can be added safely */
|
||||
if (n > PY_SIZE_MAX - sizeof(asdl_seq)) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n += sizeof(asdl_seq);
|
||||
n += sizeof(asdl_seq);
|
||||
|
||||
seq = (asdl_seq *)PyArena_Malloc(arena, n);
|
||||
if (!seq) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
memset(seq, 0, n);
|
||||
seq->size = size;
|
||||
return seq;
|
||||
seq = (asdl_seq *)PyArena_Malloc(arena, n);
|
||||
if (!seq) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
memset(seq, 0, n);
|
||||
seq->size = size;
|
||||
return seq;
|
||||
}
|
||||
|
||||
asdl_int_seq *
|
||||
asdl_int_seq_new(int size, PyArena *arena)
|
||||
{
|
||||
asdl_int_seq *seq = NULL;
|
||||
size_t n = (size ? (sizeof(void *) * (size - 1)) : 0);
|
||||
asdl_int_seq *seq = NULL;
|
||||
size_t n = (size ? (sizeof(void *) * (size - 1)) : 0);
|
||||
|
||||
/* check size is sane */
|
||||
if (size < 0 || size == INT_MIN ||
|
||||
(size && ((size - 1) > (PY_SIZE_MAX / sizeof(void *))))) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
/* check size is sane */
|
||||
if (size < 0 || size == INT_MIN ||
|
||||
(size && ((size - 1) > (PY_SIZE_MAX / sizeof(void *))))) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check if size can be added safely */
|
||||
if (n > PY_SIZE_MAX - sizeof(asdl_seq)) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
/* check if size can be added safely */
|
||||
if (n > PY_SIZE_MAX - sizeof(asdl_seq)) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n += sizeof(asdl_seq);
|
||||
n += sizeof(asdl_seq);
|
||||
|
||||
seq = (asdl_int_seq *)PyArena_Malloc(arena, n);
|
||||
if (!seq) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
memset(seq, 0, n);
|
||||
seq->size = size;
|
||||
return seq;
|
||||
seq = (asdl_int_seq *)PyArena_Malloc(arena, n);
|
||||
if (!seq) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
memset(seq, 0, n);
|
||||
seq->size = size;
|
||||
return seq;
|
||||
}
|
||||
|
|
|
|||
190
Python/ast.c
190
Python/ast.c
|
|
@ -58,19 +58,19 @@ new_identifier(const char* n, PyArena *arena)
|
|||
/* Check whether there are non-ASCII characters in the
|
||||
identifier; if so, normalize to NFKC. */
|
||||
for (; *u; u++) {
|
||||
if (*u >= 128) {
|
||||
PyObject *m = PyImport_ImportModuleNoBlock("unicodedata");
|
||||
PyObject *id2;
|
||||
if (!m)
|
||||
return NULL;
|
||||
id2 = PyObject_CallMethod(m, "normalize", "sO", "NFKC", id);
|
||||
Py_DECREF(m);
|
||||
if (!id2)
|
||||
return NULL;
|
||||
Py_DECREF(id);
|
||||
id = id2;
|
||||
break;
|
||||
}
|
||||
if (*u >= 128) {
|
||||
PyObject *m = PyImport_ImportModuleNoBlock("unicodedata");
|
||||
PyObject *id2;
|
||||
if (!m)
|
||||
return NULL;
|
||||
id2 = PyObject_CallMethod(m, "normalize", "sO", "NFKC", id);
|
||||
Py_DECREF(m);
|
||||
if (!id2)
|
||||
return NULL;
|
||||
Py_DECREF(id);
|
||||
id = id2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
PyUnicode_InternInPlace(&id);
|
||||
PyArena_AddPyObject(arena, id);
|
||||
|
|
@ -226,7 +226,7 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename,
|
|||
c.c_encoding = STR(n);
|
||||
n = CHILD(n, 0);
|
||||
} else {
|
||||
/* PEP 3120 */
|
||||
/* PEP 3120 */
|
||||
c.c_encoding = "utf-8";
|
||||
}
|
||||
c.c_arena = arena;
|
||||
|
|
@ -481,8 +481,8 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
|
|||
expr_name = "conditional expression";
|
||||
break;
|
||||
default:
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"unexpected expression in assignment %d (line %d)",
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"unexpected expression in assignment %d (line %d)",
|
||||
e->kind, e->lineno);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -497,7 +497,7 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
|
|||
}
|
||||
|
||||
/* If the LHS is a list or tuple, we need to set the assignment
|
||||
context for all the contained elements.
|
||||
context for all the contained elements.
|
||||
*/
|
||||
if (s) {
|
||||
int i;
|
||||
|
|
@ -603,7 +603,7 @@ ast_for_comp_op(struct compiling *c, const node *n)
|
|||
static asdl_seq *
|
||||
seq_for_testlist(struct compiling *c, const node *n)
|
||||
{
|
||||
/* testlist: test (',' test)* [',']
|
||||
/* testlist: test (',' test)* [',']
|
||||
testlist_star_expr: test|star_expr (',' test|star_expr)* [',']
|
||||
*/
|
||||
asdl_seq *seq;
|
||||
|
|
@ -616,7 +616,7 @@ seq_for_testlist(struct compiling *c, const node *n)
|
|||
return NULL;
|
||||
|
||||
for (i = 0; i < NCH(n); i += 2) {
|
||||
const node *ch = CHILD(n, i);
|
||||
const node *ch = CHILD(n, i);
|
||||
assert(TYPE(ch) == test || TYPE(ch) == test_nocond || TYPE(ch) == star_expr);
|
||||
|
||||
expression = ast_for_expr(c, ch);
|
||||
|
|
@ -726,7 +726,7 @@ handle_keywordonly_args(struct compiling *c, const node *n, int start,
|
|||
}
|
||||
return i;
|
||||
error:
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Create AST for argument list. */
|
||||
|
|
@ -739,12 +739,12 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
|
||||
parameters: '(' [typedargslist] ')'
|
||||
typedargslist: ((tfpdef ['=' test] ',')*
|
||||
('*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef]
|
||||
('*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef]
|
||||
| '**' tfpdef)
|
||||
| tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
|
||||
tfpdef: NAME [':' test]
|
||||
varargslist: ((vfpdef ['=' test] ',')*
|
||||
('*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef]
|
||||
('*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef]
|
||||
| '**' vfpdef)
|
||||
| vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
|
||||
vfpdef: NAME
|
||||
|
|
@ -785,7 +785,7 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
if (TYPE(ch) == vfpdef || TYPE(ch) == tfpdef) nposargs++;
|
||||
if (TYPE(ch) == EQUAL) nposdefaults++;
|
||||
}
|
||||
/* count the number of keyword only args &
|
||||
/* count the number of keyword only args &
|
||||
defaults for keyword only args */
|
||||
for ( ; i < NCH(n); ++i) {
|
||||
ch = CHILD(n, i);
|
||||
|
|
@ -799,11 +799,11 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
asdl_seq_new(nkwonlyargs, c->c_arena) : NULL);
|
||||
if (!kwonlyargs && nkwonlyargs)
|
||||
goto error;
|
||||
posdefaults = (nposdefaults ?
|
||||
posdefaults = (nposdefaults ?
|
||||
asdl_seq_new(nposdefaults, c->c_arena) : NULL);
|
||||
if (!posdefaults && nposdefaults)
|
||||
goto error;
|
||||
/* The length of kwonlyargs and kwdefaults are same
|
||||
/* The length of kwonlyargs and kwdefaults are same
|
||||
since we set NULL as default for keyword only argument w/o default
|
||||
- we have sequence data structure, but no dictionary */
|
||||
kwdefaults = (nkwonlyargs ?
|
||||
|
|
@ -840,7 +840,7 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
found_default = 1;
|
||||
}
|
||||
else if (found_default) {
|
||||
ast_error(n,
|
||||
ast_error(n,
|
||||
"non-default argument follows default argument");
|
||||
goto error;
|
||||
}
|
||||
|
|
@ -852,7 +852,7 @@ ast_for_arguments(struct compiling *c, const node *n)
|
|||
break;
|
||||
case STAR:
|
||||
if (i+1 >= NCH(n)) {
|
||||
ast_error(CHILD(n, i),
|
||||
ast_error(CHILD(n, i),
|
||||
"named arguments must follow bare *");
|
||||
goto error;
|
||||
}
|
||||
|
|
@ -953,15 +953,15 @@ ast_for_decorator(struct compiling *c, const node *n)
|
|||
/* decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE */
|
||||
expr_ty d = NULL;
|
||||
expr_ty name_expr;
|
||||
|
||||
|
||||
REQ(n, decorator);
|
||||
REQ(CHILD(n, 0), AT);
|
||||
REQ(RCHILD(n, -1), NEWLINE);
|
||||
|
||||
|
||||
name_expr = ast_for_dotted_name(c, CHILD(n, 1));
|
||||
if (!name_expr)
|
||||
return NULL;
|
||||
|
||||
|
||||
if (NCH(n) == 3) { /* No arguments */
|
||||
d = name_expr;
|
||||
name_expr = NULL;
|
||||
|
|
@ -989,12 +989,12 @@ ast_for_decorators(struct compiling *c, const node *n)
|
|||
asdl_seq* decorator_seq;
|
||||
expr_ty d;
|
||||
int i;
|
||||
|
||||
|
||||
REQ(n, decorators);
|
||||
decorator_seq = asdl_seq_new(NCH(n), c->c_arena);
|
||||
if (!decorator_seq)
|
||||
return NULL;
|
||||
|
||||
|
||||
for (i = 0; i < NCH(n); i++) {
|
||||
d = ast_for_decorator(c, CHILD(n, i));
|
||||
if (!d)
|
||||
|
|
@ -1052,7 +1052,7 @@ ast_for_decorated(struct compiling *c, const node *n)
|
|||
return NULL;
|
||||
|
||||
assert(TYPE(CHILD(n, 1)) == funcdef ||
|
||||
TYPE(CHILD(n, 1)) == classdef);
|
||||
TYPE(CHILD(n, 1)) == classdef);
|
||||
|
||||
if (TYPE(CHILD(n, 1)) == funcdef) {
|
||||
thing = ast_for_funcdef(c, CHILD(n, 1), decorator_seq);
|
||||
|
|
@ -1100,7 +1100,7 @@ ast_for_lambdef(struct compiling *c, const node *n)
|
|||
static expr_ty
|
||||
ast_for_ifexpr(struct compiling *c, const node *n)
|
||||
{
|
||||
/* test: or_test 'if' or_test 'else' test */
|
||||
/* test: or_test 'if' or_test 'else' test */
|
||||
expr_ty expression, body, orelse;
|
||||
|
||||
assert(NCH(n) == 5);
|
||||
|
|
@ -1197,9 +1197,9 @@ ast_for_comprehension(struct compiling *c, const node *n)
|
|||
asdl_seq *t;
|
||||
expr_ty expression, first;
|
||||
node *for_ch;
|
||||
|
||||
|
||||
REQ(n, comp_for);
|
||||
|
||||
|
||||
for_ch = CHILD(n, 1);
|
||||
t = ast_for_exprlist(c, for_ch, Store);
|
||||
if (!t)
|
||||
|
|
@ -1223,7 +1223,7 @@ ast_for_comprehension(struct compiling *c, const node *n)
|
|||
if (NCH(n) == 5) {
|
||||
int j, n_ifs;
|
||||
asdl_seq *ifs;
|
||||
|
||||
|
||||
n = CHILD(n, 4);
|
||||
n_ifs = count_comp_ifs(c, n);
|
||||
if (n_ifs == -1)
|
||||
|
|
@ -1237,7 +1237,7 @@ ast_for_comprehension(struct compiling *c, const node *n)
|
|||
REQ(n, comp_iter);
|
||||
n = CHILD(n, 0);
|
||||
REQ(n, comp_if);
|
||||
|
||||
|
||||
expression = ast_for_expr(c, CHILD(n, 1));
|
||||
if (!expression)
|
||||
return NULL;
|
||||
|
|
@ -1262,13 +1262,13 @@ ast_for_itercomp(struct compiling *c, const node *n, int type)
|
|||
argument: [test '='] test [comp_for] # Really [keyword '='] test */
|
||||
expr_ty elt;
|
||||
asdl_seq *comps;
|
||||
|
||||
|
||||
assert(NCH(n) > 1);
|
||||
|
||||
|
||||
elt = ast_for_expr(c, CHILD(n, 0));
|
||||
if (!elt)
|
||||
return NULL;
|
||||
|
||||
|
||||
comps = ast_for_comprehension(c, CHILD(n, 1));
|
||||
if (!comps)
|
||||
return NULL;
|
||||
|
|
@ -1289,21 +1289,21 @@ ast_for_dictcomp(struct compiling *c, const node *n)
|
|||
{
|
||||
expr_ty key, value;
|
||||
asdl_seq *comps;
|
||||
|
||||
|
||||
assert(NCH(n) > 3);
|
||||
REQ(CHILD(n, 1), COLON);
|
||||
|
||||
|
||||
key = ast_for_expr(c, CHILD(n, 0));
|
||||
if (!key)
|
||||
return NULL;
|
||||
value = ast_for_expr(c, CHILD(n, 2));
|
||||
if (!value)
|
||||
return NULL;
|
||||
|
||||
|
||||
comps = ast_for_comprehension(c, CHILD(n, 3));
|
||||
if (!comps)
|
||||
return NULL;
|
||||
|
||||
|
||||
return DictComp(key, value, comps, LINENO(n), n->n_col_offset, c->c_arena);
|
||||
}
|
||||
|
||||
|
|
@ -1338,7 +1338,7 @@ ast_for_atom(struct compiling *c, const node *n)
|
|||
*/
|
||||
node *ch = CHILD(n, 0);
|
||||
int bytesmode = 0;
|
||||
|
||||
|
||||
switch (TYPE(ch)) {
|
||||
case NAME: {
|
||||
/* All names start in Load context, but may later be
|
||||
|
|
@ -1389,24 +1389,24 @@ ast_for_atom(struct compiling *c, const node *n)
|
|||
return Ellipsis(LINENO(n), n->n_col_offset, c->c_arena);
|
||||
case LPAR: /* some parenthesized expressions */
|
||||
ch = CHILD(n, 1);
|
||||
|
||||
|
||||
if (TYPE(ch) == RPAR)
|
||||
return Tuple(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena);
|
||||
|
||||
|
||||
if (TYPE(ch) == yield_expr)
|
||||
return ast_for_expr(c, ch);
|
||||
|
||||
/* testlist_comp: test ( comp_for | (',' test)* [','] ) */
|
||||
/* testlist_comp: test ( comp_for | (',' test)* [','] ) */
|
||||
if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == comp_for))
|
||||
return ast_for_genexp(c, ch);
|
||||
|
||||
return ast_for_testlist(c, ch);
|
||||
case LSQB: /* list (or list comprehension) */
|
||||
ch = CHILD(n, 1);
|
||||
|
||||
|
||||
if (TYPE(ch) == RSQB)
|
||||
return List(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena);
|
||||
|
||||
|
||||
REQ(ch, testlist_comp);
|
||||
if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) {
|
||||
asdl_seq *elts = seq_for_testlist(c, ch);
|
||||
|
|
@ -1453,14 +1453,14 @@ ast_for_atom(struct compiling *c, const node *n)
|
|||
keys = asdl_seq_new(size, c->c_arena);
|
||||
if (!keys)
|
||||
return NULL;
|
||||
|
||||
|
||||
values = asdl_seq_new(size, c->c_arena);
|
||||
if (!values)
|
||||
return NULL;
|
||||
|
||||
|
||||
for (i = 0; i < NCH(ch); i += 4) {
|
||||
expr_ty expression;
|
||||
|
||||
|
||||
expression = ast_for_expr(c, CHILD(ch, i));
|
||||
if (!expression)
|
||||
return NULL;
|
||||
|
|
@ -1498,10 +1498,10 @@ ast_for_slice(struct compiling *c, const node *n)
|
|||
if (NCH(n) == 1 && TYPE(ch) == test) {
|
||||
/* 'step' variable hold no significance in terms of being used over
|
||||
other vars */
|
||||
step = ast_for_expr(c, ch);
|
||||
step = ast_for_expr(c, ch);
|
||||
if (!step)
|
||||
return NULL;
|
||||
|
||||
|
||||
return Index(step, c->c_arena);
|
||||
}
|
||||
|
||||
|
|
@ -1551,7 +1551,7 @@ static expr_ty
|
|||
ast_for_binop(struct compiling *c, const node *n)
|
||||
{
|
||||
/* Must account for a sequence of expressions.
|
||||
How should A op B op C by represented?
|
||||
How should A op B op C by represented?
|
||||
BinOp(BinOp(A, op, B), op, C).
|
||||
*/
|
||||
|
||||
|
|
@ -1589,10 +1589,10 @@ ast_for_binop(struct compiling *c, const node *n)
|
|||
if (!tmp)
|
||||
return NULL;
|
||||
|
||||
tmp_result = BinOp(result, newoperator, tmp,
|
||||
tmp_result = BinOp(result, newoperator, tmp,
|
||||
LINENO(next_oper), next_oper->n_col_offset,
|
||||
c->c_arena);
|
||||
if (!tmp_result)
|
||||
if (!tmp_result)
|
||||
return NULL;
|
||||
result = tmp_result;
|
||||
}
|
||||
|
|
@ -1602,7 +1602,7 @@ ast_for_binop(struct compiling *c, const node *n)
|
|||
static expr_ty
|
||||
ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)
|
||||
{
|
||||
/* trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
|
||||
/* trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
|
||||
subscriptlist: subscript (',' subscript)* [',']
|
||||
subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]
|
||||
*/
|
||||
|
|
@ -1633,7 +1633,7 @@ ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)
|
|||
c->c_arena);
|
||||
}
|
||||
else {
|
||||
/* The grammar is ambiguous here. The ambiguity is resolved
|
||||
/* The grammar is ambiguous here. The ambiguity is resolved
|
||||
by treating the sequence as a tuple literal if there are
|
||||
no slice features.
|
||||
*/
|
||||
|
|
@ -1786,7 +1786,7 @@ ast_for_expr(struct compiling *c, const node *n)
|
|||
/* handle the full range of simple expressions
|
||||
test: or_test ['if' or_test 'else' test] | lambdef
|
||||
test_nocond: or_test | lambdef_nocond
|
||||
or_test: and_test ('or' and_test)*
|
||||
or_test: and_test ('or' and_test)*
|
||||
and_test: not_test ('and' not_test)*
|
||||
not_test: 'not' not_test | comparison
|
||||
comparison: expr (comp_op expr)*
|
||||
|
|
@ -1874,7 +1874,7 @@ ast_for_expr(struct compiling *c, const node *n)
|
|||
if (!expression) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
asdl_seq_SET(ops, i / 2, newoperator);
|
||||
asdl_seq_SET(cmps, i / 2, expression);
|
||||
}
|
||||
|
|
@ -1882,14 +1882,14 @@ ast_for_expr(struct compiling *c, const node *n)
|
|||
if (!expression) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return Compare(expression, ops, cmps, LINENO(n),
|
||||
n->n_col_offset, c->c_arena);
|
||||
}
|
||||
break;
|
||||
|
||||
case star_expr:
|
||||
return ast_for_starred(c, n);
|
||||
return ast_for_starred(c, n);
|
||||
/* The next five cases all handle BinOps. The main body of code
|
||||
is the same in each case, but the switch turned inside out to
|
||||
reuse the code for each type of operator.
|
||||
|
|
@ -1998,7 +1998,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
|
|||
if (!e)
|
||||
return NULL;
|
||||
asdl_seq_SET(args, nargs++, e);
|
||||
}
|
||||
}
|
||||
else if (TYPE(CHILD(ch, 1)) == comp_for) {
|
||||
e = ast_for_genexp(c, ch);
|
||||
if (!e)
|
||||
|
|
@ -2010,7 +2010,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
|
|||
identifier key, tmp;
|
||||
int k;
|
||||
|
||||
/* CHILD(ch, 0) is test, but must be an identifier? */
|
||||
/* CHILD(ch, 0) is test, but must be an identifier? */
|
||||
e = ast_for_expr(c, CHILD(ch, 0));
|
||||
if (!e)
|
||||
return NULL;
|
||||
|
|
@ -2026,8 +2026,8 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func)
|
|||
ast_error(CHILD(ch, 0), "keyword can't be an expression");
|
||||
return NULL;
|
||||
} else if (forbidden_name(e->v.Name.id, ch, 1)) {
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
key = e->v.Name.id;
|
||||
for (k = 0; k < nkeywords; k++) {
|
||||
tmp = ((keyword_ty)asdl_seq_GET(keywords, k))->arg;
|
||||
|
|
@ -2090,7 +2090,7 @@ static stmt_ty
|
|||
ast_for_expr_stmt(struct compiling *c, const node *n)
|
||||
{
|
||||
REQ(n, expr_stmt);
|
||||
/* expr_stmt: testlist_star_expr (augassign (yield_expr|testlist)
|
||||
/* expr_stmt: testlist_star_expr (augassign (yield_expr|testlist)
|
||||
| ('=' (yield_expr|testlist))*)
|
||||
testlist_star_expr: (test|star_expr) (',' test|star_expr)* [',']
|
||||
augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^='
|
||||
|
|
@ -2164,7 +2164,7 @@ ast_for_expr_stmt(struct compiling *c, const node *n)
|
|||
e = ast_for_testlist(c, ch);
|
||||
|
||||
/* set context to assign */
|
||||
if (!e)
|
||||
if (!e)
|
||||
return NULL;
|
||||
|
||||
if (!set_context(c, e, Store, CHILD(n, i)))
|
||||
|
|
@ -2211,7 +2211,7 @@ static stmt_ty
|
|||
ast_for_del_stmt(struct compiling *c, const node *n)
|
||||
{
|
||||
asdl_seq *expr_list;
|
||||
|
||||
|
||||
/* del_stmt: 'del' exprlist */
|
||||
REQ(n, del_stmt);
|
||||
|
||||
|
|
@ -2349,7 +2349,7 @@ alias_for_import_name(struct compiling *c, const node *n, int store)
|
|||
int i;
|
||||
size_t len;
|
||||
char *s;
|
||||
PyObject *uni;
|
||||
PyObject *uni;
|
||||
|
||||
len = 0;
|
||||
for (i = 0; i < NCH(n); i += 2)
|
||||
|
|
@ -2370,13 +2370,13 @@ alias_for_import_name(struct compiling *c, const node *n, int store)
|
|||
}
|
||||
--s;
|
||||
*s = '\0';
|
||||
uni = PyUnicode_DecodeUTF8(PyBytes_AS_STRING(str),
|
||||
PyBytes_GET_SIZE(str),
|
||||
NULL);
|
||||
Py_DECREF(str);
|
||||
if (!uni)
|
||||
return NULL;
|
||||
str = uni;
|
||||
uni = PyUnicode_DecodeUTF8(PyBytes_AS_STRING(str),
|
||||
PyBytes_GET_SIZE(str),
|
||||
NULL);
|
||||
Py_DECREF(str);
|
||||
if (!uni)
|
||||
return NULL;
|
||||
str = uni;
|
||||
PyUnicode_InternInPlace(&str);
|
||||
PyArena_AddPyObject(c->c_arena, str);
|
||||
return alias(str, NULL, c->c_arena);
|
||||
|
|
@ -2433,7 +2433,7 @@ ast_for_import_stmt(struct compiling *c, const node *n)
|
|||
int idx, ndots = 0;
|
||||
alias_ty mod = NULL;
|
||||
identifier modname = NULL;
|
||||
|
||||
|
||||
/* Count the number of dots (for relative imports) and check for the
|
||||
optional module name */
|
||||
for (idx = 1; idx < NCH(n); idx++) {
|
||||
|
|
@ -2444,7 +2444,7 @@ ast_for_import_stmt(struct compiling *c, const node *n)
|
|||
idx++;
|
||||
break;
|
||||
} else if (TYPE(CHILD(n, idx)) == ELLIPSIS) {
|
||||
/* three consecutive dots are tokenized as one ELLIPSIS */
|
||||
/* three consecutive dots are tokenized as one ELLIPSIS */
|
||||
ndots += 3;
|
||||
continue;
|
||||
} else if (TYPE(CHILD(n, idx)) != DOT) {
|
||||
|
|
@ -2571,7 +2571,7 @@ ast_for_assert_stmt(struct compiling *c, const node *n)
|
|||
expr2 = ast_for_expr(c, CHILD(n, 3));
|
||||
if (!expr2)
|
||||
return NULL;
|
||||
|
||||
|
||||
return Assert(expr1, expr2, LINENO(n), n->n_col_offset, c->c_arena);
|
||||
}
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
|
|
@ -2598,7 +2598,7 @@ ast_for_suite(struct compiling *c, const node *n)
|
|||
if (TYPE(CHILD(n, 0)) == simple_stmt) {
|
||||
n = CHILD(n, 0);
|
||||
/* simple_stmt always ends with a NEWLINE,
|
||||
and may have a trailing SEMI
|
||||
and may have a trailing SEMI
|
||||
*/
|
||||
end = NCH(n) - 1;
|
||||
if (TYPE(CHILD(n, end - 1)) == SEMI)
|
||||
|
|
@ -2663,10 +2663,10 @@ ast_for_if_stmt(struct compiling *c, const node *n)
|
|||
expression = ast_for_expr(c, CHILD(n, 1));
|
||||
if (!expression)
|
||||
return NULL;
|
||||
suite_seq = ast_for_suite(c, CHILD(n, 3));
|
||||
suite_seq = ast_for_suite(c, CHILD(n, 3));
|
||||
if (!suite_seq)
|
||||
return NULL;
|
||||
|
||||
|
||||
return If(expression, suite_seq, NULL, LINENO(n), n->n_col_offset,
|
||||
c->c_arena);
|
||||
}
|
||||
|
|
@ -2724,8 +2724,8 @@ ast_for_if_stmt(struct compiling *c, const node *n)
|
|||
if (!suite_seq2)
|
||||
return NULL;
|
||||
|
||||
asdl_seq_SET(orelse, 0,
|
||||
If(expression, suite_seq, suite_seq2,
|
||||
asdl_seq_SET(orelse, 0,
|
||||
If(expression, suite_seq, suite_seq2,
|
||||
LINENO(CHILD(n, NCH(n) - 6)),
|
||||
CHILD(n, NCH(n) - 6)->n_col_offset,
|
||||
c->c_arena));
|
||||
|
|
@ -2746,7 +2746,7 @@ ast_for_if_stmt(struct compiling *c, const node *n)
|
|||
return NULL;
|
||||
|
||||
asdl_seq_SET(newobj, 0,
|
||||
If(expression, suite_seq, orelse,
|
||||
If(expression, suite_seq, orelse,
|
||||
LINENO(CHILD(n, off)),
|
||||
CHILD(n, off)->n_col_offset, c->c_arena));
|
||||
orelse = newobj;
|
||||
|
|
@ -2943,7 +2943,7 @@ ast_for_try_stmt(struct compiling *c, const node *n)
|
|||
ast_error(n, "malformed 'try' statement");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (n_except > 0) {
|
||||
int i;
|
||||
stmt_ty except_st;
|
||||
|
|
@ -3160,8 +3160,8 @@ ast_for_stmt(struct compiling *c, const node *n)
|
|||
return ast_for_funcdef(c, ch, NULL);
|
||||
case classdef:
|
||||
return ast_for_classdef(c, ch, NULL);
|
||||
case decorated:
|
||||
return ast_for_decorated(c, ch);
|
||||
case decorated:
|
||||
return ast_for_decorated(c, ch);
|
||||
default:
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"unhandled small_stmt: TYPE=%d NCH=%d\n",
|
||||
|
|
@ -3317,7 +3317,7 @@ parsestr(struct compiling *c, const node *n, int *bytesmode)
|
|||
if (quote == 'b' || quote == 'B') {
|
||||
quote = *++s;
|
||||
*bytesmode = 1;
|
||||
}
|
||||
}
|
||||
if (quote == 'r' || quote == 'R') {
|
||||
quote = *++s;
|
||||
rawmode = 1;
|
||||
|
|
@ -3330,7 +3330,7 @@ parsestr(struct compiling *c, const node *n, int *bytesmode)
|
|||
s++;
|
||||
len = strlen(s);
|
||||
if (len > INT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"string to parse is too long");
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -3374,7 +3374,7 @@ parsestr(struct compiling *c, const node *n, int *bytesmode)
|
|||
return PyBytes_FromStringAndSize(s, len);
|
||||
} else if (strcmp(c->c_encoding, "utf-8") == 0) {
|
||||
return PyUnicode_FromStringAndSize(s, len);
|
||||
} else {
|
||||
} else {
|
||||
return PyUnicode_DecodeLatin1(s, len, NULL);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
3098
Python/bltinmodule.c
3098
Python/bltinmodule.c
File diff suppressed because it is too large
Load diff
6734
Python/ceval.c
6734
Python/ceval.c
File diff suppressed because it is too large
Load diff
1038
Python/codecs.c
1038
Python/codecs.c
File diff suppressed because it is too large
Load diff
6076
Python/compile.c
6076
Python/compile.c
File diff suppressed because it is too large
Load diff
|
|
@ -4,10 +4,10 @@
|
|||
#include "Python.h"
|
||||
#include "importdl.h"
|
||||
|
||||
#include <ctype.h> /* for isdigit() */
|
||||
#include <errno.h> /* for global errno */
|
||||
#include <string.h> /* for strerror() */
|
||||
#include <stdlib.h> /* for malloc(), free() */
|
||||
#include <ctype.h> /* for isdigit() */
|
||||
#include <errno.h> /* for global errno */
|
||||
#include <string.h> /* for strerror() */
|
||||
#include <stdlib.h> /* for malloc(), free() */
|
||||
#include <sys/ldr.h>
|
||||
|
||||
|
||||
|
|
@ -22,85 +22,85 @@
|
|||
extern char *Py_GetProgramName(void);
|
||||
|
||||
typedef struct Module {
|
||||
struct Module *next;
|
||||
void *entry;
|
||||
struct Module *next;
|
||||
void *entry;
|
||||
} Module, *ModulePtr;
|
||||
|
||||
const struct filedescr _PyImport_DynLoadFiletab[] = {
|
||||
{".so", "rb", C_EXTENSION},
|
||||
{"module.so", "rb", C_EXTENSION},
|
||||
{0, 0}
|
||||
{".so", "rb", C_EXTENSION},
|
||||
{"module.so", "rb", C_EXTENSION},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static int
|
||||
aix_getoldmodules(void **modlistptr)
|
||||
{
|
||||
register ModulePtr modptr, prevmodptr;
|
||||
register struct ld_info *ldiptr;
|
||||
register char *ldibuf;
|
||||
register int errflag, bufsize = 1024;
|
||||
register unsigned int offset;
|
||||
char *progname = Py_GetProgramName();
|
||||
|
||||
/*
|
||||
-- Get the list of loaded modules into ld_info structures.
|
||||
*/
|
||||
if ((ldibuf = malloc(bufsize)) == NULL) {
|
||||
PyErr_SetString(PyExc_ImportError, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
while ((errflag = loadquery(L_GETINFO, ldibuf, bufsize)) == -1
|
||||
&& errno == ENOMEM) {
|
||||
free(ldibuf);
|
||||
bufsize += 1024;
|
||||
if ((ldibuf = malloc(bufsize)) == NULL) {
|
||||
PyErr_SetString(PyExc_ImportError, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (errflag == -1) {
|
||||
PyErr_SetString(PyExc_ImportError, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
-- Make the modules list from the ld_info structures.
|
||||
*/
|
||||
ldiptr = (struct ld_info *)ldibuf;
|
||||
prevmodptr = NULL;
|
||||
do {
|
||||
if (strstr(progname, ldiptr->ldinfo_filename) == NULL &&
|
||||
strstr(ldiptr->ldinfo_filename, "python") == NULL) {
|
||||
/*
|
||||
-- Extract only the modules belonging to the main
|
||||
-- executable + those containing "python" as a
|
||||
-- substring (like the "python[version]" binary or
|
||||
-- "libpython[version].a" in case it's a shared lib).
|
||||
*/
|
||||
offset = (unsigned int)ldiptr->ldinfo_next;
|
||||
ldiptr = (struct ld_info *)((char*)ldiptr + offset);
|
||||
continue;
|
||||
}
|
||||
if ((modptr = (ModulePtr)malloc(sizeof(Module))) == NULL) {
|
||||
PyErr_SetString(PyExc_ImportError, strerror(errno));
|
||||
while (*modlistptr) {
|
||||
modptr = (ModulePtr)*modlistptr;
|
||||
*modlistptr = (void *)modptr->next;
|
||||
free(modptr);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
modptr->entry = ldiptr->ldinfo_dataorg;
|
||||
modptr->next = NULL;
|
||||
if (prevmodptr == NULL)
|
||||
*modlistptr = (void *)modptr;
|
||||
else
|
||||
prevmodptr->next = modptr;
|
||||
prevmodptr = modptr;
|
||||
offset = (unsigned int)ldiptr->ldinfo_next;
|
||||
ldiptr = (struct ld_info *)((char*)ldiptr + offset);
|
||||
} while (offset);
|
||||
free(ldibuf);
|
||||
return 0;
|
||||
register ModulePtr modptr, prevmodptr;
|
||||
register struct ld_info *ldiptr;
|
||||
register char *ldibuf;
|
||||
register int errflag, bufsize = 1024;
|
||||
register unsigned int offset;
|
||||
char *progname = Py_GetProgramName();
|
||||
|
||||
/*
|
||||
-- Get the list of loaded modules into ld_info structures.
|
||||
*/
|
||||
if ((ldibuf = malloc(bufsize)) == NULL) {
|
||||
PyErr_SetString(PyExc_ImportError, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
while ((errflag = loadquery(L_GETINFO, ldibuf, bufsize)) == -1
|
||||
&& errno == ENOMEM) {
|
||||
free(ldibuf);
|
||||
bufsize += 1024;
|
||||
if ((ldibuf = malloc(bufsize)) == NULL) {
|
||||
PyErr_SetString(PyExc_ImportError, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (errflag == -1) {
|
||||
PyErr_SetString(PyExc_ImportError, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
-- Make the modules list from the ld_info structures.
|
||||
*/
|
||||
ldiptr = (struct ld_info *)ldibuf;
|
||||
prevmodptr = NULL;
|
||||
do {
|
||||
if (strstr(progname, ldiptr->ldinfo_filename) == NULL &&
|
||||
strstr(ldiptr->ldinfo_filename, "python") == NULL) {
|
||||
/*
|
||||
-- Extract only the modules belonging to the main
|
||||
-- executable + those containing "python" as a
|
||||
-- substring (like the "python[version]" binary or
|
||||
-- "libpython[version].a" in case it's a shared lib).
|
||||
*/
|
||||
offset = (unsigned int)ldiptr->ldinfo_next;
|
||||
ldiptr = (struct ld_info *)((char*)ldiptr + offset);
|
||||
continue;
|
||||
}
|
||||
if ((modptr = (ModulePtr)malloc(sizeof(Module))) == NULL) {
|
||||
PyErr_SetString(PyExc_ImportError, strerror(errno));
|
||||
while (*modlistptr) {
|
||||
modptr = (ModulePtr)*modlistptr;
|
||||
*modlistptr = (void *)modptr->next;
|
||||
free(modptr);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
modptr->entry = ldiptr->ldinfo_dataorg;
|
||||
modptr->next = NULL;
|
||||
if (prevmodptr == NULL)
|
||||
*modlistptr = (void *)modptr;
|
||||
else
|
||||
prevmodptr->next = modptr;
|
||||
prevmodptr = modptr;
|
||||
offset = (unsigned int)ldiptr->ldinfo_next;
|
||||
ldiptr = (struct ld_info *)((char*)ldiptr + offset);
|
||||
} while (offset);
|
||||
free(ldibuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -108,76 +108,76 @@ static void
|
|||
aix_loaderror(const char *pathname)
|
||||
{
|
||||
|
||||
char *message[1024], errbuf[1024];
|
||||
register int i,j;
|
||||
char *message[1024], errbuf[1024];
|
||||
register int i,j;
|
||||
|
||||
struct errtab {
|
||||
int errNo;
|
||||
char *errstr;
|
||||
} load_errtab[] = {
|
||||
{L_ERROR_TOOMANY, "too many errors, rest skipped."},
|
||||
{L_ERROR_NOLIB, "can't load library:"},
|
||||
{L_ERROR_UNDEF, "can't find symbol in library:"},
|
||||
{L_ERROR_RLDBAD,
|
||||
"RLD index out of range or bad relocation type:"},
|
||||
{L_ERROR_FORMAT, "not a valid, executable xcoff file:"},
|
||||
{L_ERROR_MEMBER,
|
||||
"file not an archive or does not contain requested member:"},
|
||||
{L_ERROR_TYPE, "symbol table mismatch:"},
|
||||
{L_ERROR_ALIGN, "text alignment in file is wrong."},
|
||||
{L_ERROR_SYSTEM, "System error:"},
|
||||
{L_ERROR_ERRNO, NULL}
|
||||
};
|
||||
struct errtab {
|
||||
int errNo;
|
||||
char *errstr;
|
||||
} load_errtab[] = {
|
||||
{L_ERROR_TOOMANY, "too many errors, rest skipped."},
|
||||
{L_ERROR_NOLIB, "can't load library:"},
|
||||
{L_ERROR_UNDEF, "can't find symbol in library:"},
|
||||
{L_ERROR_RLDBAD,
|
||||
"RLD index out of range or bad relocation type:"},
|
||||
{L_ERROR_FORMAT, "not a valid, executable xcoff file:"},
|
||||
{L_ERROR_MEMBER,
|
||||
"file not an archive or does not contain requested member:"},
|
||||
{L_ERROR_TYPE, "symbol table mismatch:"},
|
||||
{L_ERROR_ALIGN, "text alignment in file is wrong."},
|
||||
{L_ERROR_SYSTEM, "System error:"},
|
||||
{L_ERROR_ERRNO, NULL}
|
||||
};
|
||||
|
||||
#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
|
||||
#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
|
||||
#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
|
||||
|
||||
PyOS_snprintf(errbuf, sizeof(errbuf), "from module %.200s ", pathname);
|
||||
PyOS_snprintf(errbuf, sizeof(errbuf), "from module %.200s ", pathname);
|
||||
|
||||
if (!loadquery(L_GETMESSAGES, &message[0], sizeof(message))) {
|
||||
ERRBUF_APPEND(strerror(errno));
|
||||
ERRBUF_APPEND("\n");
|
||||
}
|
||||
for(i = 0; message[i] && *message[i]; i++) {
|
||||
int nerr = atoi(message[i]);
|
||||
for (j=0; j<LOAD_ERRTAB_LEN ; j++) {
|
||||
if (nerr == load_errtab[j].errNo && load_errtab[j].errstr)
|
||||
ERRBUF_APPEND(load_errtab[j].errstr);
|
||||
}
|
||||
while (isdigit(Py_CHARMASK(*message[i]))) message[i]++ ;
|
||||
ERRBUF_APPEND(message[i]);
|
||||
ERRBUF_APPEND("\n");
|
||||
}
|
||||
errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
|
||||
PyErr_SetString(PyExc_ImportError, errbuf);
|
||||
return;
|
||||
if (!loadquery(L_GETMESSAGES, &message[0], sizeof(message))) {
|
||||
ERRBUF_APPEND(strerror(errno));
|
||||
ERRBUF_APPEND("\n");
|
||||
}
|
||||
for(i = 0; message[i] && *message[i]; i++) {
|
||||
int nerr = atoi(message[i]);
|
||||
for (j=0; j<LOAD_ERRTAB_LEN ; j++) {
|
||||
if (nerr == load_errtab[j].errNo && load_errtab[j].errstr)
|
||||
ERRBUF_APPEND(load_errtab[j].errstr);
|
||||
}
|
||||
while (isdigit(Py_CHARMASK(*message[i]))) message[i]++ ;
|
||||
ERRBUF_APPEND(message[i]);
|
||||
ERRBUF_APPEND("\n");
|
||||
}
|
||||
errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
|
||||
PyErr_SetString(PyExc_ImportError, errbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
|
||||
const char *pathname, FILE *fp)
|
||||
const char *pathname, FILE *fp)
|
||||
{
|
||||
dl_funcptr p;
|
||||
dl_funcptr p;
|
||||
|
||||
/*
|
||||
-- Invoke load() with L_NOAUTODEFER leaving the imported symbols
|
||||
-- of the shared module unresolved. Thus we have to resolve them
|
||||
-- explicitly with loadbind. The new module is loaded, then we
|
||||
-- resolve its symbols using the list of already loaded modules
|
||||
-- (only those that belong to the python executable). Get these
|
||||
-- with loadquery(L_GETINFO).
|
||||
*/
|
||||
/*
|
||||
-- Invoke load() with L_NOAUTODEFER leaving the imported symbols
|
||||
-- of the shared module unresolved. Thus we have to resolve them
|
||||
-- explicitly with loadbind. The new module is loaded, then we
|
||||
-- resolve its symbols using the list of already loaded modules
|
||||
-- (only those that belong to the python executable). Get these
|
||||
-- with loadquery(L_GETINFO).
|
||||
*/
|
||||
|
||||
static void *staticmodlistptr = NULL;
|
||||
static void *staticmodlistptr = NULL;
|
||||
|
||||
if (!staticmodlistptr)
|
||||
if (aix_getoldmodules(&staticmodlistptr) == -1)
|
||||
return NULL;
|
||||
p = (dl_funcptr) aix_load((char *)pathname, L_NOAUTODEFER, 0);
|
||||
if (p == NULL) {
|
||||
aix_loaderror(pathname);
|
||||
return NULL;
|
||||
}
|
||||
if (!staticmodlistptr)
|
||||
if (aix_getoldmodules(&staticmodlistptr) == -1)
|
||||
return NULL;
|
||||
p = (dl_funcptr) aix_load((char *)pathname, L_NOAUTODEFER, 0);
|
||||
if (p == NULL) {
|
||||
aix_loaderror(pathname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return p;
|
||||
return p;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,45 +14,45 @@
|
|||
#endif
|
||||
|
||||
const struct filedescr _PyImport_DynLoadFiletab[] = {
|
||||
{SHLIB_EXT, "rb", C_EXTENSION},
|
||||
{"module"SHLIB_EXT, "rb", C_EXTENSION},
|
||||
{0, 0}
|
||||
{SHLIB_EXT, "rb", C_EXTENSION},
|
||||
{"module"SHLIB_EXT, "rb", C_EXTENSION},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
|
||||
const char *pathname, FILE *fp)
|
||||
const char *pathname, FILE *fp)
|
||||
{
|
||||
dl_funcptr p;
|
||||
shl_t lib;
|
||||
int flags;
|
||||
char funcname[258];
|
||||
dl_funcptr p;
|
||||
shl_t lib;
|
||||
int flags;
|
||||
char funcname[258];
|
||||
|
||||
flags = BIND_FIRST | BIND_DEFERRED;
|
||||
if (Py_VerboseFlag) {
|
||||
flags = BIND_FIRST | BIND_IMMEDIATE |
|
||||
BIND_NONFATAL | BIND_VERBOSE;
|
||||
printf("shl_load %s\n",pathname);
|
||||
}
|
||||
lib = shl_load(pathname, flags, 0);
|
||||
/* XXX Chuck Blake once wrote that 0 should be BIND_NOSTART? */
|
||||
if (lib == NULL) {
|
||||
char buf[256];
|
||||
if (Py_VerboseFlag)
|
||||
perror(pathname);
|
||||
PyOS_snprintf(buf, sizeof(buf), "Failed to load %.200s",
|
||||
pathname);
|
||||
PyErr_SetString(PyExc_ImportError, buf);
|
||||
return NULL;
|
||||
}
|
||||
PyOS_snprintf(funcname, sizeof(funcname), FUNCNAME_PATTERN, shortname);
|
||||
if (Py_VerboseFlag)
|
||||
printf("shl_findsym %s\n", funcname);
|
||||
if (shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p) == -1) {
|
||||
shl_unload(lib);
|
||||
p = NULL;
|
||||
}
|
||||
if (p == NULL && Py_VerboseFlag)
|
||||
perror(funcname);
|
||||
flags = BIND_FIRST | BIND_DEFERRED;
|
||||
if (Py_VerboseFlag) {
|
||||
flags = BIND_FIRST | BIND_IMMEDIATE |
|
||||
BIND_NONFATAL | BIND_VERBOSE;
|
||||
printf("shl_load %s\n",pathname);
|
||||
}
|
||||
lib = shl_load(pathname, flags, 0);
|
||||
/* XXX Chuck Blake once wrote that 0 should be BIND_NOSTART? */
|
||||
if (lib == NULL) {
|
||||
char buf[256];
|
||||
if (Py_VerboseFlag)
|
||||
perror(pathname);
|
||||
PyOS_snprintf(buf, sizeof(buf), "Failed to load %.200s",
|
||||
pathname);
|
||||
PyErr_SetString(PyExc_ImportError, buf);
|
||||
return NULL;
|
||||
}
|
||||
PyOS_snprintf(funcname, sizeof(funcname), FUNCNAME_PATTERN, shortname);
|
||||
if (Py_VerboseFlag)
|
||||
printf("shl_findsym %s\n", funcname);
|
||||
if (shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p) == -1) {
|
||||
shl_unload(lib);
|
||||
p = NULL;
|
||||
}
|
||||
if (p == NULL && Py_VerboseFlag)
|
||||
perror(funcname);
|
||||
|
||||
return p;
|
||||
return p;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@
|
|||
#include <mach-o/dyld.h>
|
||||
|
||||
const struct filedescr _PyImport_DynLoadFiletab[] = {
|
||||
{".so", "rb", C_EXTENSION},
|
||||
{"module.so", "rb", C_EXTENSION},
|
||||
{0, 0}
|
||||
{".so", "rb", C_EXTENSION},
|
||||
{"module.so", "rb", C_EXTENSION},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -29,86 +29,86 @@ const struct filedescr _PyImport_DynLoadFiletab[] = {
|
|||
#define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW|NSLINKMODULE_OPTION_RETURN_ON_ERROR
|
||||
#else
|
||||
#define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW| \
|
||||
NSLINKMODULE_OPTION_RETURN_ON_ERROR|NSLINKMODULE_OPTION_PRIVATE
|
||||
NSLINKMODULE_OPTION_RETURN_ON_ERROR|NSLINKMODULE_OPTION_PRIVATE
|
||||
#endif
|
||||
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
|
||||
const char *pathname, FILE *fp)
|
||||
const char *pathname, FILE *fp)
|
||||
{
|
||||
dl_funcptr p = NULL;
|
||||
char funcname[258];
|
||||
NSObjectFileImageReturnCode rc;
|
||||
NSObjectFileImage image;
|
||||
NSModule newModule;
|
||||
NSSymbol theSym;
|
||||
const char *errString;
|
||||
char errBuf[512];
|
||||
dl_funcptr p = NULL;
|
||||
char funcname[258];
|
||||
NSObjectFileImageReturnCode rc;
|
||||
NSObjectFileImage image;
|
||||
NSModule newModule;
|
||||
NSSymbol theSym;
|
||||
const char *errString;
|
||||
char errBuf[512];
|
||||
|
||||
PyOS_snprintf(funcname, sizeof(funcname), "_PyInit_%.200s", shortname);
|
||||
PyOS_snprintf(funcname, sizeof(funcname), "_PyInit_%.200s", shortname);
|
||||
|
||||
#ifdef USE_DYLD_GLOBAL_NAMESPACE
|
||||
if (NSIsSymbolNameDefined(funcname)) {
|
||||
theSym = NSLookupAndBindSymbol(funcname);
|
||||
p = (dl_funcptr)NSAddressOfSymbol(theSym);
|
||||
return p;
|
||||
}
|
||||
if (NSIsSymbolNameDefined(funcname)) {
|
||||
theSym = NSLookupAndBindSymbol(funcname);
|
||||
p = (dl_funcptr)NSAddressOfSymbol(theSym);
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
rc = NSCreateObjectFileImageFromFile(pathname, &image);
|
||||
switch(rc) {
|
||||
default:
|
||||
case NSObjectFileImageFailure:
|
||||
case NSObjectFileImageFormat:
|
||||
/* for these a message is printed on stderr by dyld */
|
||||
errString = "Can't create object file image";
|
||||
break;
|
||||
case NSObjectFileImageSuccess:
|
||||
errString = NULL;
|
||||
break;
|
||||
case NSObjectFileImageInappropriateFile:
|
||||
errString = "Inappropriate file type for dynamic loading";
|
||||
break;
|
||||
case NSObjectFileImageArch:
|
||||
errString = "Wrong CPU type in object file";
|
||||
break;
|
||||
case NSObjectFileImageAccess:
|
||||
errString = "Can't read object file (no access)";
|
||||
break;
|
||||
}
|
||||
if (errString == NULL) {
|
||||
newModule = NSLinkModule(image, pathname, LINKOPTIONS);
|
||||
if (newModule == NULL) {
|
||||
int errNo;
|
||||
const char *fileName, *moreErrorStr;
|
||||
NSLinkEditErrors c;
|
||||
NSLinkEditError( &c, &errNo, &fileName, &moreErrorStr );
|
||||
PyOS_snprintf(errBuf, 512, "Failure linking new module: %s: %s",
|
||||
fileName, moreErrorStr);
|
||||
errString = errBuf;
|
||||
}
|
||||
}
|
||||
if (errString != NULL) {
|
||||
PyErr_SetString(PyExc_ImportError, errString);
|
||||
return NULL;
|
||||
}
|
||||
rc = NSCreateObjectFileImageFromFile(pathname, &image);
|
||||
switch(rc) {
|
||||
default:
|
||||
case NSObjectFileImageFailure:
|
||||
case NSObjectFileImageFormat:
|
||||
/* for these a message is printed on stderr by dyld */
|
||||
errString = "Can't create object file image";
|
||||
break;
|
||||
case NSObjectFileImageSuccess:
|
||||
errString = NULL;
|
||||
break;
|
||||
case NSObjectFileImageInappropriateFile:
|
||||
errString = "Inappropriate file type for dynamic loading";
|
||||
break;
|
||||
case NSObjectFileImageArch:
|
||||
errString = "Wrong CPU type in object file";
|
||||
break;
|
||||
case NSObjectFileImageAccess:
|
||||
errString = "Can't read object file (no access)";
|
||||
break;
|
||||
}
|
||||
if (errString == NULL) {
|
||||
newModule = NSLinkModule(image, pathname, LINKOPTIONS);
|
||||
if (newModule == NULL) {
|
||||
int errNo;
|
||||
const char *fileName, *moreErrorStr;
|
||||
NSLinkEditErrors c;
|
||||
NSLinkEditError( &c, &errNo, &fileName, &moreErrorStr );
|
||||
PyOS_snprintf(errBuf, 512, "Failure linking new module: %s: %s",
|
||||
fileName, moreErrorStr);
|
||||
errString = errBuf;
|
||||
}
|
||||
}
|
||||
if (errString != NULL) {
|
||||
PyErr_SetString(PyExc_ImportError, errString);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef USE_DYLD_GLOBAL_NAMESPACE
|
||||
if (!NSIsSymbolNameDefined(funcname)) {
|
||||
/* UnlinkModule() isn't implemented in current versions, but calling it does no harm */
|
||||
/* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */
|
||||
PyErr_Format(PyExc_ImportError,
|
||||
"Loaded module does not contain symbol %.200s",
|
||||
funcname);
|
||||
return NULL;
|
||||
}
|
||||
theSym = NSLookupAndBindSymbol(funcname);
|
||||
if (!NSIsSymbolNameDefined(funcname)) {
|
||||
/* UnlinkModule() isn't implemented in current versions, but calling it does no harm */
|
||||
/* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */
|
||||
PyErr_Format(PyExc_ImportError,
|
||||
"Loaded module does not contain symbol %.200s",
|
||||
funcname);
|
||||
return NULL;
|
||||
}
|
||||
theSym = NSLookupAndBindSymbol(funcname);
|
||||
#else
|
||||
theSym = NSLookupSymbolInModule(newModule, funcname);
|
||||
if ( theSym == NULL ) {
|
||||
/* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */
|
||||
PyErr_Format(PyExc_ImportError,
|
||||
"Loaded module does not contain symbol %.200s",
|
||||
funcname);
|
||||
return NULL;
|
||||
}
|
||||
theSym = NSLookupSymbolInModule(newModule, funcname);
|
||||
if ( theSym == NULL ) {
|
||||
/* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */
|
||||
PyErr_Format(PyExc_ImportError,
|
||||
"Loaded module does not contain symbol %.200s",
|
||||
funcname);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
p = (dl_funcptr)NSAddressOfSymbol(theSym);
|
||||
return p;
|
||||
p = (dl_funcptr)NSAddressOfSymbol(theSym);
|
||||
return p;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,37 +10,37 @@
|
|||
|
||||
|
||||
const struct filedescr _PyImport_DynLoadFiletab[] = {
|
||||
{".pyd", "rb", C_EXTENSION},
|
||||
{".dll", "rb", C_EXTENSION},
|
||||
{0, 0}
|
||||
{".pyd", "rb", C_EXTENSION},
|
||||
{".dll", "rb", C_EXTENSION},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
|
||||
const char *pathname, FILE *fp)
|
||||
const char *pathname, FILE *fp)
|
||||
{
|
||||
dl_funcptr p;
|
||||
APIRET rc;
|
||||
HMODULE hDLL;
|
||||
char failreason[256];
|
||||
char funcname[258];
|
||||
dl_funcptr p;
|
||||
APIRET rc;
|
||||
HMODULE hDLL;
|
||||
char failreason[256];
|
||||
char funcname[258];
|
||||
|
||||
rc = DosLoadModule(failreason,
|
||||
sizeof(failreason),
|
||||
pathname,
|
||||
&hDLL);
|
||||
rc = DosLoadModule(failreason,
|
||||
sizeof(failreason),
|
||||
pathname,
|
||||
&hDLL);
|
||||
|
||||
if (rc != NO_ERROR) {
|
||||
char errBuf[256];
|
||||
PyOS_snprintf(errBuf, sizeof(errBuf),
|
||||
"DLL load failed, rc = %d: %.200s",
|
||||
rc, failreason);
|
||||
PyErr_SetString(PyExc_ImportError, errBuf);
|
||||
return NULL;
|
||||
}
|
||||
if (rc != NO_ERROR) {
|
||||
char errBuf[256];
|
||||
PyOS_snprintf(errBuf, sizeof(errBuf),
|
||||
"DLL load failed, rc = %d: %.200s",
|
||||
rc, failreason);
|
||||
PyErr_SetString(PyExc_ImportError, errBuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyOS_snprintf(funcname, sizeof(funcname), "PyInit_%.200s", shortname);
|
||||
rc = DosQueryProcAddr(hDLL, 0L, funcname, &p);
|
||||
if (rc != NO_ERROR)
|
||||
p = NULL; /* Signify Failure to Acquire Entrypoint */
|
||||
return p;
|
||||
PyOS_snprintf(funcname, sizeof(funcname), "PyInit_%.200s", shortname);
|
||||
rc = DosQueryProcAddr(hDLL, 0L, funcname, &p);
|
||||
if (rc != NO_ERROR)
|
||||
p = NULL; /* Signify Failure to Acquire Entrypoint */
|
||||
return p;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,111 +33,111 @@
|
|||
|
||||
const struct filedescr _PyImport_DynLoadFiletab[] = {
|
||||
#ifdef __CYGWIN__
|
||||
{".dll", "rb", C_EXTENSION},
|
||||
{"module.dll", "rb", C_EXTENSION},
|
||||
{".dll", "rb", C_EXTENSION},
|
||||
{"module.dll", "rb", C_EXTENSION},
|
||||
#else
|
||||
#if defined(PYOS_OS2) && defined(PYCC_GCC)
|
||||
{".pyd", "rb", C_EXTENSION},
|
||||
{".dll", "rb", C_EXTENSION},
|
||||
{".pyd", "rb", C_EXTENSION},
|
||||
{".dll", "rb", C_EXTENSION},
|
||||
#else
|
||||
#ifdef __VMS
|
||||
{".exe", "rb", C_EXTENSION},
|
||||
{".EXE", "rb", C_EXTENSION},
|
||||
{"module.exe", "rb", C_EXTENSION},
|
||||
{"MODULE.EXE", "rb", C_EXTENSION},
|
||||
{".exe", "rb", C_EXTENSION},
|
||||
{".EXE", "rb", C_EXTENSION},
|
||||
{"module.exe", "rb", C_EXTENSION},
|
||||
{"MODULE.EXE", "rb", C_EXTENSION},
|
||||
#else
|
||||
{".so", "rb", C_EXTENSION},
|
||||
{"module.so", "rb", C_EXTENSION},
|
||||
{".so", "rb", C_EXTENSION},
|
||||
{"module.so", "rb", C_EXTENSION},
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
{0, 0}
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static struct {
|
||||
dev_t dev;
|
||||
dev_t dev;
|
||||
#ifdef __VMS
|
||||
ino_t ino[3];
|
||||
ino_t ino[3];
|
||||
#else
|
||||
ino_t ino;
|
||||
ino_t ino;
|
||||
#endif
|
||||
void *handle;
|
||||
void *handle;
|
||||
} handles[128];
|
||||
static int nhandles = 0;
|
||||
|
||||
|
||||
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
|
||||
const char *pathname, FILE *fp)
|
||||
const char *pathname, FILE *fp)
|
||||
{
|
||||
dl_funcptr p;
|
||||
void *handle;
|
||||
char funcname[258];
|
||||
char pathbuf[260];
|
||||
int dlopenflags=0;
|
||||
dl_funcptr p;
|
||||
void *handle;
|
||||
char funcname[258];
|
||||
char pathbuf[260];
|
||||
int dlopenflags=0;
|
||||
|
||||
if (strchr(pathname, '/') == NULL) {
|
||||
/* Prefix bare filename with "./" */
|
||||
PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
|
||||
pathname = pathbuf;
|
||||
}
|
||||
if (strchr(pathname, '/') == NULL) {
|
||||
/* Prefix bare filename with "./" */
|
||||
PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
|
||||
pathname = pathbuf;
|
||||
}
|
||||
|
||||
PyOS_snprintf(funcname, sizeof(funcname),
|
||||
LEAD_UNDERSCORE "PyInit_%.200s", shortname);
|
||||
PyOS_snprintf(funcname, sizeof(funcname),
|
||||
LEAD_UNDERSCORE "PyInit_%.200s", shortname);
|
||||
|
||||
if (fp != NULL) {
|
||||
int i;
|
||||
struct stat statb;
|
||||
fstat(fileno(fp), &statb);
|
||||
for (i = 0; i < nhandles; i++) {
|
||||
if (statb.st_dev == handles[i].dev &&
|
||||
statb.st_ino == handles[i].ino) {
|
||||
p = (dl_funcptr) dlsym(handles[i].handle,
|
||||
funcname);
|
||||
return p;
|
||||
}
|
||||
}
|
||||
if (nhandles < 128) {
|
||||
handles[nhandles].dev = statb.st_dev;
|
||||
if (fp != NULL) {
|
||||
int i;
|
||||
struct stat statb;
|
||||
fstat(fileno(fp), &statb);
|
||||
for (i = 0; i < nhandles; i++) {
|
||||
if (statb.st_dev == handles[i].dev &&
|
||||
statb.st_ino == handles[i].ino) {
|
||||
p = (dl_funcptr) dlsym(handles[i].handle,
|
||||
funcname);
|
||||
return p;
|
||||
}
|
||||
}
|
||||
if (nhandles < 128) {
|
||||
handles[nhandles].dev = statb.st_dev;
|
||||
#ifdef __VMS
|
||||
handles[nhandles].ino[0] = statb.st_ino[0];
|
||||
handles[nhandles].ino[1] = statb.st_ino[1];
|
||||
handles[nhandles].ino[2] = statb.st_ino[2];
|
||||
handles[nhandles].ino[0] = statb.st_ino[0];
|
||||
handles[nhandles].ino[1] = statb.st_ino[1];
|
||||
handles[nhandles].ino[2] = statb.st_ino[2];
|
||||
#else
|
||||
handles[nhandles].ino = statb.st_ino;
|
||||
handles[nhandles].ino = statb.st_ino;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !(defined(PYOS_OS2) && defined(PYCC_GCC))
|
||||
dlopenflags = PyThreadState_GET()->interp->dlopenflags;
|
||||
dlopenflags = PyThreadState_GET()->interp->dlopenflags;
|
||||
#endif
|
||||
|
||||
if (Py_VerboseFlag)
|
||||
PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname,
|
||||
dlopenflags);
|
||||
if (Py_VerboseFlag)
|
||||
PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname,
|
||||
dlopenflags);
|
||||
|
||||
#ifdef __VMS
|
||||
/* VMS currently don't allow a pathname, use a logical name instead */
|
||||
/* Concatenate 'python_module_' and shortname */
|
||||
/* so "import vms.bar" will use the logical python_module_bar */
|
||||
/* As C module use only one name space this is probably not a */
|
||||
/* important limitation */
|
||||
PyOS_snprintf(pathbuf, sizeof(pathbuf), "python_module_%-.200s",
|
||||
shortname);
|
||||
pathname = pathbuf;
|
||||
/* VMS currently don't allow a pathname, use a logical name instead */
|
||||
/* Concatenate 'python_module_' and shortname */
|
||||
/* so "import vms.bar" will use the logical python_module_bar */
|
||||
/* As C module use only one name space this is probably not a */
|
||||
/* important limitation */
|
||||
PyOS_snprintf(pathbuf, sizeof(pathbuf), "python_module_%-.200s",
|
||||
shortname);
|
||||
pathname = pathbuf;
|
||||
#endif
|
||||
|
||||
handle = dlopen(pathname, dlopenflags);
|
||||
handle = dlopen(pathname, dlopenflags);
|
||||
|
||||
if (handle == NULL) {
|
||||
const char *error = dlerror();
|
||||
if (error == NULL)
|
||||
error = "unknown dlopen() error";
|
||||
PyErr_SetString(PyExc_ImportError, error);
|
||||
return NULL;
|
||||
}
|
||||
if (fp != NULL && nhandles < 128)
|
||||
handles[nhandles++].handle = handle;
|
||||
p = (dl_funcptr) dlsym(handle, funcname);
|
||||
return p;
|
||||
if (handle == NULL) {
|
||||
const char *error = dlerror();
|
||||
if (error == NULL)
|
||||
error = "unknown dlopen() error";
|
||||
PyErr_SetString(PyExc_ImportError, error);
|
||||
return NULL;
|
||||
}
|
||||
if (fp != NULL && nhandles < 128)
|
||||
handles[nhandles++].handle = handle;
|
||||
p = (dl_funcptr) dlsym(handle, funcname);
|
||||
return p;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,11 +17,11 @@ void _Py_DeactivateActCtx(ULONG_PTR cookie);
|
|||
|
||||
const struct filedescr _PyImport_DynLoadFiletab[] = {
|
||||
#ifdef _DEBUG
|
||||
{"_d.pyd", "rb", C_EXTENSION},
|
||||
{"_d.pyd", "rb", C_EXTENSION},
|
||||
#else
|
||||
{".pyd", "rb", C_EXTENSION},
|
||||
{".pyd", "rb", C_EXTENSION},
|
||||
#endif
|
||||
{0, 0}
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -29,18 +29,18 @@ const struct filedescr _PyImport_DynLoadFiletab[] = {
|
|||
C RTL implementations */
|
||||
|
||||
static int strcasecmp (char *string1, char *string2)
|
||||
{
|
||||
int first, second;
|
||||
{
|
||||
int first, second;
|
||||
|
||||
do {
|
||||
first = tolower(*string1);
|
||||
second = tolower(*string2);
|
||||
string1++;
|
||||
string2++;
|
||||
} while (first && first == second);
|
||||
do {
|
||||
first = tolower(*string1);
|
||||
second = tolower(*string2);
|
||||
string1++;
|
||||
string2++;
|
||||
} while (first && first == second);
|
||||
|
||||
return (first - second);
|
||||
}
|
||||
return (first - second);
|
||||
}
|
||||
|
||||
|
||||
/* Function to return the name of the "python" DLL that the supplied module
|
||||
|
|
@ -66,213 +66,213 @@ static int strcasecmp (char *string1, char *string2)
|
|||
|
||||
static char *GetPythonImport (HINSTANCE hModule)
|
||||
{
|
||||
unsigned char *dllbase, *import_data, *import_name;
|
||||
DWORD pe_offset, opt_offset;
|
||||
WORD opt_magic;
|
||||
int num_dict_off, import_off;
|
||||
unsigned char *dllbase, *import_data, *import_name;
|
||||
DWORD pe_offset, opt_offset;
|
||||
WORD opt_magic;
|
||||
int num_dict_off, import_off;
|
||||
|
||||
/* Safety check input */
|
||||
if (hModule == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
/* Safety check input */
|
||||
if (hModule == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Module instance is also the base load address. First portion of
|
||||
memory is the MS-DOS loader, which holds the offset to the PE
|
||||
header (from the load base) at 0x3C */
|
||||
dllbase = (unsigned char *)hModule;
|
||||
pe_offset = DWORD_AT(dllbase + 0x3C);
|
||||
/* Module instance is also the base load address. First portion of
|
||||
memory is the MS-DOS loader, which holds the offset to the PE
|
||||
header (from the load base) at 0x3C */
|
||||
dllbase = (unsigned char *)hModule;
|
||||
pe_offset = DWORD_AT(dllbase + 0x3C);
|
||||
|
||||
/* The PE signature must be "PE\0\0" */
|
||||
if (memcmp(dllbase+pe_offset,"PE\0\0",4)) {
|
||||
return NULL;
|
||||
}
|
||||
/* The PE signature must be "PE\0\0" */
|
||||
if (memcmp(dllbase+pe_offset,"PE\0\0",4)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Following the PE signature is the standard COFF header (20
|
||||
bytes) and then the optional header. The optional header starts
|
||||
with a magic value of 0x10B for PE32 or 0x20B for PE32+ (PE32+
|
||||
uses 64-bits for some fields). It might also be 0x107 for a ROM
|
||||
image, but we don't process that here.
|
||||
/* Following the PE signature is the standard COFF header (20
|
||||
bytes) and then the optional header. The optional header starts
|
||||
with a magic value of 0x10B for PE32 or 0x20B for PE32+ (PE32+
|
||||
uses 64-bits for some fields). It might also be 0x107 for a ROM
|
||||
image, but we don't process that here.
|
||||
|
||||
The optional header ends with a data dictionary that directly
|
||||
points to certain types of data, among them the import entries
|
||||
(in the second table entry). Based on the header type, we
|
||||
determine offsets for the data dictionary count and the entry
|
||||
within the dictionary pointing to the imports. */
|
||||
The optional header ends with a data dictionary that directly
|
||||
points to certain types of data, among them the import entries
|
||||
(in the second table entry). Based on the header type, we
|
||||
determine offsets for the data dictionary count and the entry
|
||||
within the dictionary pointing to the imports. */
|
||||
|
||||
opt_offset = pe_offset + 4 + 20;
|
||||
opt_magic = WORD_AT(dllbase+opt_offset);
|
||||
if (opt_magic == 0x10B) {
|
||||
/* PE32 */
|
||||
num_dict_off = 92;
|
||||
import_off = 104;
|
||||
} else if (opt_magic == 0x20B) {
|
||||
/* PE32+ */
|
||||
num_dict_off = 108;
|
||||
import_off = 120;
|
||||
} else {
|
||||
/* Unsupported */
|
||||
return NULL;
|
||||
}
|
||||
opt_offset = pe_offset + 4 + 20;
|
||||
opt_magic = WORD_AT(dllbase+opt_offset);
|
||||
if (opt_magic == 0x10B) {
|
||||
/* PE32 */
|
||||
num_dict_off = 92;
|
||||
import_off = 104;
|
||||
} else if (opt_magic == 0x20B) {
|
||||
/* PE32+ */
|
||||
num_dict_off = 108;
|
||||
import_off = 120;
|
||||
} else {
|
||||
/* Unsupported */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Now if an import table exists, offset to it and walk the list of
|
||||
imports. The import table is an array (ending when an entry has
|
||||
empty values) of structures (20 bytes each), which contains (at
|
||||
offset 12) a relative address (to the module base) at which a
|
||||
string constant holding the import name is located. */
|
||||
/* Now if an import table exists, offset to it and walk the list of
|
||||
imports. The import table is an array (ending when an entry has
|
||||
empty values) of structures (20 bytes each), which contains (at
|
||||
offset 12) a relative address (to the module base) at which a
|
||||
string constant holding the import name is located. */
|
||||
|
||||
if (DWORD_AT(dllbase + opt_offset + num_dict_off) >= 2) {
|
||||
/* We have at least 2 tables - the import table is the second
|
||||
one. But still it may be that the table size is zero */
|
||||
if (0 == DWORD_AT(dllbase + opt_offset + import_off + sizeof(DWORD)))
|
||||
return NULL;
|
||||
import_data = dllbase + DWORD_AT(dllbase +
|
||||
opt_offset +
|
||||
import_off);
|
||||
while (DWORD_AT(import_data)) {
|
||||
import_name = dllbase + DWORD_AT(import_data+12);
|
||||
if (strlen(import_name) >= 6 &&
|
||||
!strncmp(import_name,"python",6)) {
|
||||
char *pch;
|
||||
if (DWORD_AT(dllbase + opt_offset + num_dict_off) >= 2) {
|
||||
/* We have at least 2 tables - the import table is the second
|
||||
one. But still it may be that the table size is zero */
|
||||
if (0 == DWORD_AT(dllbase + opt_offset + import_off + sizeof(DWORD)))
|
||||
return NULL;
|
||||
import_data = dllbase + DWORD_AT(dllbase +
|
||||
opt_offset +
|
||||
import_off);
|
||||
while (DWORD_AT(import_data)) {
|
||||
import_name = dllbase + DWORD_AT(import_data+12);
|
||||
if (strlen(import_name) >= 6 &&
|
||||
!strncmp(import_name,"python",6)) {
|
||||
char *pch;
|
||||
|
||||
/* Ensure python prefix is followed only
|
||||
by numbers to the end of the basename */
|
||||
pch = import_name + 6;
|
||||
/* Ensure python prefix is followed only
|
||||
by numbers to the end of the basename */
|
||||
pch = import_name + 6;
|
||||
#ifdef _DEBUG
|
||||
while (*pch && pch[0] != '_' && pch[1] != 'd' && pch[2] != '.') {
|
||||
while (*pch && pch[0] != '_' && pch[1] != 'd' && pch[2] != '.') {
|
||||
#else
|
||||
while (*pch && *pch != '.') {
|
||||
while (*pch && *pch != '.') {
|
||||
#endif
|
||||
if (*pch >= '0' && *pch <= '9') {
|
||||
pch++;
|
||||
} else {
|
||||
pch = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pch) {
|
||||
/* Found it - return the name */
|
||||
return import_name;
|
||||
}
|
||||
}
|
||||
import_data += 20;
|
||||
}
|
||||
}
|
||||
if (*pch >= '0' && *pch <= '9') {
|
||||
pch++;
|
||||
} else {
|
||||
pch = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
if (pch) {
|
||||
/* Found it - return the name */
|
||||
return import_name;
|
||||
}
|
||||
}
|
||||
import_data += 20;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
|
||||
const char *pathname, FILE *fp)
|
||||
const char *pathname, FILE *fp)
|
||||
{
|
||||
dl_funcptr p;
|
||||
char funcname[258], *import_python;
|
||||
dl_funcptr p;
|
||||
char funcname[258], *import_python;
|
||||
|
||||
PyOS_snprintf(funcname, sizeof(funcname), "PyInit_%.200s", shortname);
|
||||
PyOS_snprintf(funcname, sizeof(funcname), "PyInit_%.200s", shortname);
|
||||
|
||||
{
|
||||
HINSTANCE hDLL = NULL;
|
||||
char pathbuf[260];
|
||||
LPTSTR dummy;
|
||||
unsigned int old_mode;
|
||||
ULONG_PTR cookie = 0;
|
||||
/* We use LoadLibraryEx so Windows looks for dependent DLLs
|
||||
in directory of pathname first. However, Windows95
|
||||
can sometimes not work correctly unless the absolute
|
||||
path is used. If GetFullPathName() fails, the LoadLibrary
|
||||
will certainly fail too, so use its error code */
|
||||
{
|
||||
HINSTANCE hDLL = NULL;
|
||||
char pathbuf[260];
|
||||
LPTSTR dummy;
|
||||
unsigned int old_mode;
|
||||
ULONG_PTR cookie = 0;
|
||||
/* We use LoadLibraryEx so Windows looks for dependent DLLs
|
||||
in directory of pathname first. However, Windows95
|
||||
can sometimes not work correctly unless the absolute
|
||||
path is used. If GetFullPathName() fails, the LoadLibrary
|
||||
will certainly fail too, so use its error code */
|
||||
|
||||
/* Don't display a message box when Python can't load a DLL */
|
||||
old_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
/* Don't display a message box when Python can't load a DLL */
|
||||
old_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
|
||||
if (GetFullPathName(pathname,
|
||||
sizeof(pathbuf),
|
||||
pathbuf,
|
||||
&dummy)) {
|
||||
ULONG_PTR cookie = _Py_ActivateActCtx();
|
||||
/* XXX This call doesn't exist in Windows CE */
|
||||
hDLL = LoadLibraryEx(pathname, NULL,
|
||||
LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||
_Py_DeactivateActCtx(cookie);
|
||||
}
|
||||
if (GetFullPathName(pathname,
|
||||
sizeof(pathbuf),
|
||||
pathbuf,
|
||||
&dummy)) {
|
||||
ULONG_PTR cookie = _Py_ActivateActCtx();
|
||||
/* XXX This call doesn't exist in Windows CE */
|
||||
hDLL = LoadLibraryEx(pathname, NULL,
|
||||
LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||
_Py_DeactivateActCtx(cookie);
|
||||
}
|
||||
|
||||
/* restore old error mode settings */
|
||||
SetErrorMode(old_mode);
|
||||
/* restore old error mode settings */
|
||||
SetErrorMode(old_mode);
|
||||
|
||||
if (hDLL==NULL){
|
||||
PyObject *message;
|
||||
unsigned int errorCode;
|
||||
if (hDLL==NULL){
|
||||
PyObject *message;
|
||||
unsigned int errorCode;
|
||||
|
||||
/* Get an error string from Win32 error code */
|
||||
wchar_t theInfo[256]; /* Pointer to error text
|
||||
from system */
|
||||
int theLength; /* Length of error text */
|
||||
/* Get an error string from Win32 error code */
|
||||
wchar_t theInfo[256]; /* Pointer to error text
|
||||
from system */
|
||||
int theLength; /* Length of error text */
|
||||
|
||||
errorCode = GetLastError();
|
||||
errorCode = GetLastError();
|
||||
|
||||
theLength = FormatMessageW(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS, /* flags */
|
||||
NULL, /* message source */
|
||||
errorCode, /* the message (error) ID */
|
||||
MAKELANGID(LANG_NEUTRAL,
|
||||
SUBLANG_DEFAULT),
|
||||
/* Default language */
|
||||
theInfo, /* the buffer */
|
||||
sizeof(theInfo), /* the buffer size */
|
||||
NULL); /* no additional format args. */
|
||||
theLength = FormatMessageW(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS, /* flags */
|
||||
NULL, /* message source */
|
||||
errorCode, /* the message (error) ID */
|
||||
MAKELANGID(LANG_NEUTRAL,
|
||||
SUBLANG_DEFAULT),
|
||||
/* Default language */
|
||||
theInfo, /* the buffer */
|
||||
sizeof(theInfo), /* the buffer size */
|
||||
NULL); /* no additional format args. */
|
||||
|
||||
/* Problem: could not get the error message.
|
||||
This should not happen if called correctly. */
|
||||
if (theLength == 0) {
|
||||
message = PyUnicode_FromFormat(
|
||||
"DLL load failed with error code %d",
|
||||
errorCode);
|
||||
} else {
|
||||
/* For some reason a \r\n
|
||||
is appended to the text */
|
||||
if (theLength >= 2 &&
|
||||
theInfo[theLength-2] == '\r' &&
|
||||
theInfo[theLength-1] == '\n') {
|
||||
theLength -= 2;
|
||||
theInfo[theLength] = '\0';
|
||||
}
|
||||
message = PyUnicode_FromString(
|
||||
"DLL load failed: ");
|
||||
/* Problem: could not get the error message.
|
||||
This should not happen if called correctly. */
|
||||
if (theLength == 0) {
|
||||
message = PyUnicode_FromFormat(
|
||||
"DLL load failed with error code %d",
|
||||
errorCode);
|
||||
} else {
|
||||
/* For some reason a \r\n
|
||||
is appended to the text */
|
||||
if (theLength >= 2 &&
|
||||
theInfo[theLength-2] == '\r' &&
|
||||
theInfo[theLength-1] == '\n') {
|
||||
theLength -= 2;
|
||||
theInfo[theLength] = '\0';
|
||||
}
|
||||
message = PyUnicode_FromString(
|
||||
"DLL load failed: ");
|
||||
|
||||
PyUnicode_AppendAndDel(&message,
|
||||
PyUnicode_FromUnicode(
|
||||
theInfo,
|
||||
theLength));
|
||||
}
|
||||
PyErr_SetObject(PyExc_ImportError, message);
|
||||
Py_XDECREF(message);
|
||||
return NULL;
|
||||
} else {
|
||||
char buffer[256];
|
||||
PyUnicode_AppendAndDel(&message,
|
||||
PyUnicode_FromUnicode(
|
||||
theInfo,
|
||||
theLength));
|
||||
}
|
||||
PyErr_SetObject(PyExc_ImportError, message);
|
||||
Py_XDECREF(message);
|
||||
return NULL;
|
||||
} else {
|
||||
char buffer[256];
|
||||
|
||||
#ifdef _DEBUG
|
||||
PyOS_snprintf(buffer, sizeof(buffer), "python%d%d_d.dll",
|
||||
PyOS_snprintf(buffer, sizeof(buffer), "python%d%d_d.dll",
|
||||
#else
|
||||
PyOS_snprintf(buffer, sizeof(buffer), "python%d%d.dll",
|
||||
PyOS_snprintf(buffer, sizeof(buffer), "python%d%d.dll",
|
||||
#endif
|
||||
PY_MAJOR_VERSION,PY_MINOR_VERSION);
|
||||
import_python = GetPythonImport(hDLL);
|
||||
PY_MAJOR_VERSION,PY_MINOR_VERSION);
|
||||
import_python = GetPythonImport(hDLL);
|
||||
|
||||
if (import_python &&
|
||||
strcasecmp(buffer,import_python)) {
|
||||
PyOS_snprintf(buffer, sizeof(buffer),
|
||||
"Module use of %.150s conflicts "
|
||||
"with this version of Python.",
|
||||
import_python);
|
||||
PyErr_SetString(PyExc_ImportError,buffer);
|
||||
FreeLibrary(hDLL);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
p = GetProcAddress(hDLL, funcname);
|
||||
}
|
||||
if (import_python &&
|
||||
strcasecmp(buffer,import_python)) {
|
||||
PyOS_snprintf(buffer, sizeof(buffer),
|
||||
"Module use of %.150s conflicts "
|
||||
"with this version of Python.",
|
||||
import_python);
|
||||
PyErr_SetString(PyExc_ImportError,buffer);
|
||||
FreeLibrary(hDLL);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
p = GetProcAddress(hDLL, funcname);
|
||||
}
|
||||
|
||||
return p;
|
||||
return p;
|
||||
}
|
||||
|
|
|
|||
1234
Python/errors.c
1234
Python/errors.c
File diff suppressed because it is too large
Load diff
|
|
@ -12,25 +12,25 @@
|
|||
the appropriate bytes from M___main__.c. */
|
||||
|
||||
static unsigned char M___hello__[] = {
|
||||
99,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
|
||||
0,64,0,0,0,115,10,0,0,0,100,1,0,90,1,0,
|
||||
100,0,0,83,40,2,0,0,0,78,84,40,2,0,0,0,
|
||||
117,4,0,0,0,84,114,117,101,117,11,0,0,0,105,110,
|
||||
105,116,105,97,108,105,122,101,100,40,0,0,0,0,40,0,
|
||||
0,0,0,40,0,0,0,0,117,7,0,0,0,102,108,97,
|
||||
103,46,112,121,117,8,0,0,0,60,109,111,100,117,108,101,
|
||||
62,1,0,0,0,115,0,0,0,0,
|
||||
99,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
|
||||
0,64,0,0,0,115,10,0,0,0,100,1,0,90,1,0,
|
||||
100,0,0,83,40,2,0,0,0,78,84,40,2,0,0,0,
|
||||
117,4,0,0,0,84,114,117,101,117,11,0,0,0,105,110,
|
||||
105,116,105,97,108,105,122,101,100,40,0,0,0,0,40,0,
|
||||
0,0,0,40,0,0,0,0,117,7,0,0,0,102,108,97,
|
||||
103,46,112,121,117,8,0,0,0,60,109,111,100,117,108,101,
|
||||
62,1,0,0,0,115,0,0,0,0,
|
||||
};
|
||||
|
||||
#define SIZE (int)sizeof(M___hello__)
|
||||
|
||||
static struct _frozen _PyImport_FrozenModules[] = {
|
||||
/* Test module */
|
||||
{"__hello__", M___hello__, SIZE},
|
||||
/* Test package (negative size indicates package-ness) */
|
||||
{"__phello__", M___hello__, -SIZE},
|
||||
{"__phello__.spam", M___hello__, SIZE},
|
||||
{0, 0, 0} /* sentinel */
|
||||
/* Test module */
|
||||
{"__hello__", M___hello__, SIZE},
|
||||
/* Test package (negative size indicates package-ness) */
|
||||
{"__phello__", M___hello__, -SIZE},
|
||||
{"__phello__.spam", M___hello__, SIZE},
|
||||
{0, 0, 0} /* sentinel */
|
||||
};
|
||||
|
||||
/* Embedding apps may change this pointer to point to their favorite
|
||||
|
|
|
|||
|
|
@ -15,96 +15,96 @@ extern int PyInitFrozenExtensions(void);
|
|||
int
|
||||
Py_FrozenMain(int argc, char **argv)
|
||||
{
|
||||
char *p;
|
||||
int i, n, sts;
|
||||
int inspect = 0;
|
||||
int unbuffered = 0;
|
||||
char *oldloc;
|
||||
wchar_t **argv_copy = PyMem_Malloc(sizeof(wchar_t*)*argc);
|
||||
/* We need a second copies, as Python might modify the first one. */
|
||||
wchar_t **argv_copy2 = PyMem_Malloc(sizeof(wchar_t*)*argc);
|
||||
char *p;
|
||||
int i, n, sts;
|
||||
int inspect = 0;
|
||||
int unbuffered = 0;
|
||||
char *oldloc;
|
||||
wchar_t **argv_copy = PyMem_Malloc(sizeof(wchar_t*)*argc);
|
||||
/* We need a second copies, as Python might modify the first one. */
|
||||
wchar_t **argv_copy2 = PyMem_Malloc(sizeof(wchar_t*)*argc);
|
||||
|
||||
Py_FrozenFlag = 1; /* Suppress errors from getpath.c */
|
||||
Py_FrozenFlag = 1; /* Suppress errors from getpath.c */
|
||||
|
||||
if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
|
||||
inspect = 1;
|
||||
if ((p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
|
||||
unbuffered = 1;
|
||||
if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
|
||||
inspect = 1;
|
||||
if ((p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
|
||||
unbuffered = 1;
|
||||
|
||||
if (unbuffered) {
|
||||
setbuf(stdin, (char *)NULL);
|
||||
setbuf(stdout, (char *)NULL);
|
||||
setbuf(stderr, (char *)NULL);
|
||||
}
|
||||
if (unbuffered) {
|
||||
setbuf(stdin, (char *)NULL);
|
||||
setbuf(stdout, (char *)NULL);
|
||||
setbuf(stderr, (char *)NULL);
|
||||
}
|
||||
|
||||
if (!argv_copy) {
|
||||
fprintf(stderr, "out of memory\n");
|
||||
return 1;
|
||||
}
|
||||
if (!argv_copy) {
|
||||
fprintf(stderr, "out of memory\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
oldloc = setlocale(LC_ALL, NULL);
|
||||
setlocale(LC_ALL, "");
|
||||
for (i = 0; i < argc; i++) {
|
||||
oldloc = setlocale(LC_ALL, NULL);
|
||||
setlocale(LC_ALL, "");
|
||||
for (i = 0; i < argc; i++) {
|
||||
#ifdef HAVE_BROKEN_MBSTOWCS
|
||||
size_t argsize = strlen(argv[i]);
|
||||
size_t argsize = strlen(argv[i]);
|
||||
#else
|
||||
size_t argsize = mbstowcs(NULL, argv[i], 0);
|
||||
size_t argsize = mbstowcs(NULL, argv[i], 0);
|
||||
#endif
|
||||
size_t count;
|
||||
if (argsize == (size_t)-1) {
|
||||
fprintf(stderr, "Could not convert argument %d to string\n", i);
|
||||
return 1;
|
||||
}
|
||||
argv_copy[i] = PyMem_Malloc((argsize+1)*sizeof(wchar_t));
|
||||
argv_copy2[i] = argv_copy[i];
|
||||
if (!argv_copy[i]) {
|
||||
fprintf(stderr, "out of memory\n");
|
||||
return 1;
|
||||
}
|
||||
count = mbstowcs(argv_copy[i], argv[i], argsize+1);
|
||||
if (count == (size_t)-1) {
|
||||
fprintf(stderr, "Could not convert argument %d to string\n", i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
setlocale(LC_ALL, oldloc);
|
||||
size_t count;
|
||||
if (argsize == (size_t)-1) {
|
||||
fprintf(stderr, "Could not convert argument %d to string\n", i);
|
||||
return 1;
|
||||
}
|
||||
argv_copy[i] = PyMem_Malloc((argsize+1)*sizeof(wchar_t));
|
||||
argv_copy2[i] = argv_copy[i];
|
||||
if (!argv_copy[i]) {
|
||||
fprintf(stderr, "out of memory\n");
|
||||
return 1;
|
||||
}
|
||||
count = mbstowcs(argv_copy[i], argv[i], argsize+1);
|
||||
if (count == (size_t)-1) {
|
||||
fprintf(stderr, "Could not convert argument %d to string\n", i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
setlocale(LC_ALL, oldloc);
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
PyInitFrozenExtensions();
|
||||
PyInitFrozenExtensions();
|
||||
#endif /* MS_WINDOWS */
|
||||
Py_SetProgramName(argv_copy[0]);
|
||||
Py_Initialize();
|
||||
Py_SetProgramName(argv_copy[0]);
|
||||
Py_Initialize();
|
||||
#ifdef MS_WINDOWS
|
||||
PyWinFreeze_ExeInit();
|
||||
PyWinFreeze_ExeInit();
|
||||
#endif
|
||||
|
||||
if (Py_VerboseFlag)
|
||||
fprintf(stderr, "Python %s\n%s\n",
|
||||
Py_GetVersion(), Py_GetCopyright());
|
||||
if (Py_VerboseFlag)
|
||||
fprintf(stderr, "Python %s\n%s\n",
|
||||
Py_GetVersion(), Py_GetCopyright());
|
||||
|
||||
PySys_SetArgv(argc, argv_copy);
|
||||
PySys_SetArgv(argc, argv_copy);
|
||||
|
||||
n = PyImport_ImportFrozenModule("__main__");
|
||||
if (n == 0)
|
||||
Py_FatalError("__main__ not frozen");
|
||||
if (n < 0) {
|
||||
PyErr_Print();
|
||||
sts = 1;
|
||||
}
|
||||
else
|
||||
sts = 0;
|
||||
n = PyImport_ImportFrozenModule("__main__");
|
||||
if (n == 0)
|
||||
Py_FatalError("__main__ not frozen");
|
||||
if (n < 0) {
|
||||
PyErr_Print();
|
||||
sts = 1;
|
||||
}
|
||||
else
|
||||
sts = 0;
|
||||
|
||||
if (inspect && isatty((int)fileno(stdin)))
|
||||
sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
|
||||
if (inspect && isatty((int)fileno(stdin)))
|
||||
sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
PyWinFreeze_ExeTerm();
|
||||
PyWinFreeze_ExeTerm();
|
||||
#endif
|
||||
Py_Finalize();
|
||||
for (i = 0; i < argc; i++) {
|
||||
PyMem_Free(argv_copy2[i]);
|
||||
}
|
||||
PyMem_Free(argv_copy);
|
||||
PyMem_Free(argv_copy2);
|
||||
return sts;
|
||||
Py_Finalize();
|
||||
for (i = 0; i < argc; i++) {
|
||||
PyMem_Free(argv_copy2[i]);
|
||||
}
|
||||
PyMem_Free(argv_copy);
|
||||
PyMem_Free(argv_copy2);
|
||||
return sts;
|
||||
}
|
||||
|
|
|
|||
210
Python/future.c
210
Python/future.c
|
|
@ -14,131 +14,131 @@
|
|||
static int
|
||||
future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename)
|
||||
{
|
||||
int i;
|
||||
asdl_seq *names;
|
||||
int i;
|
||||
asdl_seq *names;
|
||||
|
||||
assert(s->kind == ImportFrom_kind);
|
||||
assert(s->kind == ImportFrom_kind);
|
||||
|
||||
names = s->v.ImportFrom.names;
|
||||
for (i = 0; i < asdl_seq_LEN(names); i++) {
|
||||
alias_ty name = (alias_ty)asdl_seq_GET(names, i);
|
||||
const char *feature = _PyUnicode_AsString(name->name);
|
||||
if (!feature)
|
||||
return 0;
|
||||
if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
|
||||
continue;
|
||||
} else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
|
||||
continue;
|
||||
} else if (strcmp(feature, FUTURE_DIVISION) == 0) {
|
||||
continue;
|
||||
} else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
|
||||
continue;
|
||||
} else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
|
||||
continue;
|
||||
} else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {
|
||||
continue;
|
||||
} else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
|
||||
continue;
|
||||
} else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) {
|
||||
ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL;
|
||||
} else if (strcmp(feature, "braces") == 0) {
|
||||
PyErr_SetString(PyExc_SyntaxError,
|
||||
"not a chance");
|
||||
PyErr_SyntaxLocation(filename, s->lineno);
|
||||
return 0;
|
||||
} else {
|
||||
PyErr_Format(PyExc_SyntaxError,
|
||||
UNDEFINED_FUTURE_FEATURE, feature);
|
||||
PyErr_SyntaxLocation(filename, s->lineno);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
names = s->v.ImportFrom.names;
|
||||
for (i = 0; i < asdl_seq_LEN(names); i++) {
|
||||
alias_ty name = (alias_ty)asdl_seq_GET(names, i);
|
||||
const char *feature = _PyUnicode_AsString(name->name);
|
||||
if (!feature)
|
||||
return 0;
|
||||
if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
|
||||
continue;
|
||||
} else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
|
||||
continue;
|
||||
} else if (strcmp(feature, FUTURE_DIVISION) == 0) {
|
||||
continue;
|
||||
} else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
|
||||
continue;
|
||||
} else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
|
||||
continue;
|
||||
} else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {
|
||||
continue;
|
||||
} else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
|
||||
continue;
|
||||
} else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) {
|
||||
ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL;
|
||||
} else if (strcmp(feature, "braces") == 0) {
|
||||
PyErr_SetString(PyExc_SyntaxError,
|
||||
"not a chance");
|
||||
PyErr_SyntaxLocation(filename, s->lineno);
|
||||
return 0;
|
||||
} else {
|
||||
PyErr_Format(PyExc_SyntaxError,
|
||||
UNDEFINED_FUTURE_FEATURE, feature);
|
||||
PyErr_SyntaxLocation(filename, s->lineno);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename)
|
||||
{
|
||||
int i, found_docstring = 0, done = 0, prev_line = 0;
|
||||
int i, found_docstring = 0, done = 0, prev_line = 0;
|
||||
|
||||
static PyObject *future;
|
||||
if (!future) {
|
||||
future = PyUnicode_InternFromString("__future__");
|
||||
if (!future)
|
||||
return 0;
|
||||
}
|
||||
static PyObject *future;
|
||||
if (!future) {
|
||||
future = PyUnicode_InternFromString("__future__");
|
||||
if (!future)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
|
||||
return 1;
|
||||
if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
|
||||
return 1;
|
||||
|
||||
/* A subsequent pass will detect future imports that don't
|
||||
appear at the beginning of the file. There's one case,
|
||||
however, that is easier to handle here: A series of imports
|
||||
joined by semi-colons, where the first import is a future
|
||||
statement but some subsequent import has the future form
|
||||
but is preceded by a regular import.
|
||||
*/
|
||||
|
||||
/* A subsequent pass will detect future imports that don't
|
||||
appear at the beginning of the file. There's one case,
|
||||
however, that is easier to handle here: A series of imports
|
||||
joined by semi-colons, where the first import is a future
|
||||
statement but some subsequent import has the future form
|
||||
but is preceded by a regular import.
|
||||
*/
|
||||
|
||||
for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) {
|
||||
stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);
|
||||
|
||||
if (done && s->lineno > prev_line)
|
||||
return 1;
|
||||
prev_line = s->lineno;
|
||||
for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) {
|
||||
stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);
|
||||
|
||||
/* The tests below will return from this function unless it is
|
||||
still possible to find a future statement. The only things
|
||||
that can precede a future statement are another future
|
||||
statement and a doc string.
|
||||
*/
|
||||
if (done && s->lineno > prev_line)
|
||||
return 1;
|
||||
prev_line = s->lineno;
|
||||
|
||||
if (s->kind == ImportFrom_kind) {
|
||||
if (s->v.ImportFrom.module == future) {
|
||||
if (done) {
|
||||
PyErr_SetString(PyExc_SyntaxError,
|
||||
ERR_LATE_FUTURE);
|
||||
PyErr_SyntaxLocation(filename,
|
||||
s->lineno);
|
||||
return 0;
|
||||
}
|
||||
if (!future_check_features(ff, s, filename))
|
||||
return 0;
|
||||
ff->ff_lineno = s->lineno;
|
||||
}
|
||||
else
|
||||
done = 1;
|
||||
}
|
||||
else if (s->kind == Expr_kind && !found_docstring) {
|
||||
expr_ty e = s->v.Expr.value;
|
||||
if (e->kind != Str_kind)
|
||||
done = 1;
|
||||
else
|
||||
found_docstring = 1;
|
||||
}
|
||||
else
|
||||
done = 1;
|
||||
}
|
||||
return 1;
|
||||
/* The tests below will return from this function unless it is
|
||||
still possible to find a future statement. The only things
|
||||
that can precede a future statement are another future
|
||||
statement and a doc string.
|
||||
*/
|
||||
|
||||
if (s->kind == ImportFrom_kind) {
|
||||
if (s->v.ImportFrom.module == future) {
|
||||
if (done) {
|
||||
PyErr_SetString(PyExc_SyntaxError,
|
||||
ERR_LATE_FUTURE);
|
||||
PyErr_SyntaxLocation(filename,
|
||||
s->lineno);
|
||||
return 0;
|
||||
}
|
||||
if (!future_check_features(ff, s, filename))
|
||||
return 0;
|
||||
ff->ff_lineno = s->lineno;
|
||||
}
|
||||
else
|
||||
done = 1;
|
||||
}
|
||||
else if (s->kind == Expr_kind && !found_docstring) {
|
||||
expr_ty e = s->v.Expr.value;
|
||||
if (e->kind != Str_kind)
|
||||
done = 1;
|
||||
else
|
||||
found_docstring = 1;
|
||||
}
|
||||
else
|
||||
done = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
PyFutureFeatures *
|
||||
PyFuture_FromAST(mod_ty mod, const char *filename)
|
||||
{
|
||||
PyFutureFeatures *ff;
|
||||
PyFutureFeatures *ff;
|
||||
|
||||
ff = (PyFutureFeatures *)PyObject_Malloc(sizeof(PyFutureFeatures));
|
||||
if (ff == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
ff->ff_features = 0;
|
||||
ff->ff_lineno = -1;
|
||||
ff = (PyFutureFeatures *)PyObject_Malloc(sizeof(PyFutureFeatures));
|
||||
if (ff == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
ff->ff_features = 0;
|
||||
ff->ff_lineno = -1;
|
||||
|
||||
if (!future_parse(ff, mod, filename)) {
|
||||
PyObject_Free(ff);
|
||||
return NULL;
|
||||
}
|
||||
return ff;
|
||||
if (!future_parse(ff, mod, filename)) {
|
||||
PyObject_Free(ff);
|
||||
return NULL;
|
||||
}
|
||||
return ff;
|
||||
}
|
||||
|
|
|
|||
3138
Python/getargs.c
3138
Python/getargs.c
File diff suppressed because it is too large
Load diff
|
|
@ -26,24 +26,24 @@ extern char *getwd(char *);
|
|||
char *
|
||||
getcwd(char *buf, int size)
|
||||
{
|
||||
char localbuf[MAXPATHLEN+1];
|
||||
char *ret;
|
||||
|
||||
if (size <= 0) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
ret = getwd(localbuf);
|
||||
if (ret != NULL && strlen(localbuf) >= (size_t)size) {
|
||||
errno = ERANGE;
|
||||
return NULL;
|
||||
}
|
||||
if (ret == NULL) {
|
||||
errno = EACCES; /* Most likely error */
|
||||
return NULL;
|
||||
}
|
||||
strncpy(buf, localbuf, size);
|
||||
return buf;
|
||||
char localbuf[MAXPATHLEN+1];
|
||||
char *ret;
|
||||
|
||||
if (size <= 0) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
ret = getwd(localbuf);
|
||||
if (ret != NULL && strlen(localbuf) >= (size_t)size) {
|
||||
errno = ERANGE;
|
||||
return NULL;
|
||||
}
|
||||
if (ret == NULL) {
|
||||
errno = EACCES; /* Most likely error */
|
||||
return NULL;
|
||||
}
|
||||
strncpy(buf, localbuf, size);
|
||||
return buf;
|
||||
}
|
||||
|
||||
#else /* !HAVE_GETWD */
|
||||
|
|
@ -57,27 +57,27 @@ getcwd(char *buf, int size)
|
|||
char *
|
||||
getcwd(char *buf, int size)
|
||||
{
|
||||
FILE *fp;
|
||||
char *p;
|
||||
int sts;
|
||||
if (size <= 0) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if ((fp = popen(PWD_CMD, "r")) == NULL)
|
||||
return NULL;
|
||||
if (fgets(buf, size, fp) == NULL || (sts = pclose(fp)) != 0) {
|
||||
errno = EACCES; /* Most likely error */
|
||||
return NULL;
|
||||
}
|
||||
for (p = buf; *p != '\n'; p++) {
|
||||
if (*p == '\0') {
|
||||
errno = ERANGE;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
return buf;
|
||||
FILE *fp;
|
||||
char *p;
|
||||
int sts;
|
||||
if (size <= 0) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if ((fp = popen(PWD_CMD, "r")) == NULL)
|
||||
return NULL;
|
||||
if (fgets(buf, size, fp) == NULL || (sts = pclose(fp)) != 0) {
|
||||
errno = EACCES; /* Most likely error */
|
||||
return NULL;
|
||||
}
|
||||
for (p = buf; *p != '\n'; p++) {
|
||||
if (*p == '\0') {
|
||||
errno = ERANGE;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif /* !HAVE_GETWD */
|
||||
|
|
|
|||
122
Python/getopt.c
122
Python/getopt.c
|
|
@ -7,8 +7,8 @@
|
|||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright notice, this permission notice and
|
||||
* the following disclaimer notice appear unmodified in all copies.
|
||||
*
|
||||
|
|
@ -43,84 +43,84 @@ wchar_t *_PyOS_optarg = NULL; /* optional argument */
|
|||
|
||||
int _PyOS_GetOpt(int argc, wchar_t **argv, wchar_t *optstring)
|
||||
{
|
||||
static wchar_t *opt_ptr = L"";
|
||||
wchar_t *ptr;
|
||||
wchar_t option;
|
||||
static wchar_t *opt_ptr = L"";
|
||||
wchar_t *ptr;
|
||||
wchar_t option;
|
||||
|
||||
if (*opt_ptr == '\0') {
|
||||
if (*opt_ptr == '\0') {
|
||||
|
||||
if (_PyOS_optind >= argc)
|
||||
return -1;
|
||||
if (_PyOS_optind >= argc)
|
||||
return -1;
|
||||
#ifdef MS_WINDOWS
|
||||
else if (wcscmp(argv[_PyOS_optind], L"/?") == 0) {
|
||||
++_PyOS_optind;
|
||||
return 'h';
|
||||
}
|
||||
else if (wcscmp(argv[_PyOS_optind], L"/?") == 0) {
|
||||
++_PyOS_optind;
|
||||
return 'h';
|
||||
}
|
||||
#endif
|
||||
|
||||
else if (argv[_PyOS_optind][0] != L'-' ||
|
||||
argv[_PyOS_optind][1] == L'\0' /* lone dash */ )
|
||||
return -1;
|
||||
else if (argv[_PyOS_optind][0] != L'-' ||
|
||||
argv[_PyOS_optind][1] == L'\0' /* lone dash */ )
|
||||
return -1;
|
||||
|
||||
else if (wcscmp(argv[_PyOS_optind], L"--") == 0) {
|
||||
++_PyOS_optind;
|
||||
return -1;
|
||||
}
|
||||
else if (wcscmp(argv[_PyOS_optind], L"--") == 0) {
|
||||
++_PyOS_optind;
|
||||
return -1;
|
||||
}
|
||||
|
||||
else if (wcscmp(argv[_PyOS_optind], L"--help") == 0) {
|
||||
++_PyOS_optind;
|
||||
return 'h';
|
||||
}
|
||||
else if (wcscmp(argv[_PyOS_optind], L"--help") == 0) {
|
||||
++_PyOS_optind;
|
||||
return 'h';
|
||||
}
|
||||
|
||||
else if (wcscmp(argv[_PyOS_optind], L"--version") == 0) {
|
||||
++_PyOS_optind;
|
||||
return 'V';
|
||||
}
|
||||
else if (wcscmp(argv[_PyOS_optind], L"--version") == 0) {
|
||||
++_PyOS_optind;
|
||||
return 'V';
|
||||
}
|
||||
|
||||
|
||||
opt_ptr = &argv[_PyOS_optind++][1];
|
||||
}
|
||||
opt_ptr = &argv[_PyOS_optind++][1];
|
||||
}
|
||||
|
||||
if ( (option = *opt_ptr++) == L'\0')
|
||||
return -1;
|
||||
if ( (option = *opt_ptr++) == L'\0')
|
||||
return -1;
|
||||
|
||||
if (option == 'J') {
|
||||
fprintf(stderr, "-J is reserved for Jython\n");
|
||||
return '_';
|
||||
}
|
||||
if (option == 'J') {
|
||||
fprintf(stderr, "-J is reserved for Jython\n");
|
||||
return '_';
|
||||
}
|
||||
|
||||
if (option == 'X') {
|
||||
fprintf(stderr,
|
||||
"-X is reserved for implementation-specific arguments\n");
|
||||
return '_';
|
||||
}
|
||||
if (option == 'X') {
|
||||
fprintf(stderr,
|
||||
"-X is reserved for implementation-specific arguments\n");
|
||||
return '_';
|
||||
}
|
||||
|
||||
if ((ptr = wcschr(optstring, option)) == NULL) {
|
||||
if (_PyOS_opterr)
|
||||
fprintf(stderr, "Unknown option: -%c\n", (char)option);
|
||||
if ((ptr = wcschr(optstring, option)) == NULL) {
|
||||
if (_PyOS_opterr)
|
||||
fprintf(stderr, "Unknown option: -%c\n", (char)option);
|
||||
|
||||
return '_';
|
||||
}
|
||||
return '_';
|
||||
}
|
||||
|
||||
if (*(ptr + 1) == L':') {
|
||||
if (*opt_ptr != L'\0') {
|
||||
_PyOS_optarg = opt_ptr;
|
||||
opt_ptr = L"";
|
||||
}
|
||||
if (*(ptr + 1) == L':') {
|
||||
if (*opt_ptr != L'\0') {
|
||||
_PyOS_optarg = opt_ptr;
|
||||
opt_ptr = L"";
|
||||
}
|
||||
|
||||
else {
|
||||
if (_PyOS_optind >= argc) {
|
||||
if (_PyOS_opterr)
|
||||
fprintf(stderr,
|
||||
"Argument expected for the -%c option\n", (char)option);
|
||||
return '_';
|
||||
}
|
||||
else {
|
||||
if (_PyOS_optind >= argc) {
|
||||
if (_PyOS_opterr)
|
||||
fprintf(stderr,
|
||||
"Argument expected for the -%c option\n", (char)option);
|
||||
return '_';
|
||||
}
|
||||
|
||||
_PyOS_optarg = argv[_PyOS_optind++];
|
||||
}
|
||||
}
|
||||
_PyOS_optarg = argv[_PyOS_optind++];
|
||||
}
|
||||
}
|
||||
|
||||
return option;
|
||||
return option;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
5198
Python/import.c
5198
Python/import.c
File diff suppressed because it is too large
Load diff
|
|
@ -13,76 +13,76 @@
|
|||
#include "importdl.h"
|
||||
|
||||
extern dl_funcptr _PyImport_GetDynLoadFunc(const char *name,
|
||||
const char *shortname,
|
||||
const char *pathname, FILE *fp);
|
||||
const char *shortname,
|
||||
const char *pathname, FILE *fp);
|
||||
|
||||
|
||||
|
||||
PyObject *
|
||||
_PyImport_LoadDynamicModule(char *name, char *pathname, FILE *fp)
|
||||
{
|
||||
PyObject *m;
|
||||
PyObject *path;
|
||||
char *lastdot, *shortname, *packagecontext, *oldcontext;
|
||||
dl_funcptr p0;
|
||||
PyObject* (*p)(void);
|
||||
struct PyModuleDef *def;
|
||||
PyObject *m;
|
||||
PyObject *path;
|
||||
char *lastdot, *shortname, *packagecontext, *oldcontext;
|
||||
dl_funcptr p0;
|
||||
PyObject* (*p)(void);
|
||||
struct PyModuleDef *def;
|
||||
|
||||
if ((m = _PyImport_FindExtension(name, pathname)) != NULL) {
|
||||
Py_INCREF(m);
|
||||
return m;
|
||||
}
|
||||
lastdot = strrchr(name, '.');
|
||||
if (lastdot == NULL) {
|
||||
packagecontext = NULL;
|
||||
shortname = name;
|
||||
}
|
||||
else {
|
||||
packagecontext = name;
|
||||
shortname = lastdot+1;
|
||||
}
|
||||
if ((m = _PyImport_FindExtension(name, pathname)) != NULL) {
|
||||
Py_INCREF(m);
|
||||
return m;
|
||||
}
|
||||
lastdot = strrchr(name, '.');
|
||||
if (lastdot == NULL) {
|
||||
packagecontext = NULL;
|
||||
shortname = name;
|
||||
}
|
||||
else {
|
||||
packagecontext = name;
|
||||
shortname = lastdot+1;
|
||||
}
|
||||
|
||||
p0 = _PyImport_GetDynLoadFunc(name, shortname, pathname, fp);
|
||||
p = (PyObject*(*)(void))p0;
|
||||
if (PyErr_Occurred())
|
||||
return NULL;
|
||||
if (p == NULL) {
|
||||
PyErr_Format(PyExc_ImportError,
|
||||
"dynamic module does not define init function (PyInit_%.200s)",
|
||||
shortname);
|
||||
return NULL;
|
||||
}
|
||||
oldcontext = _Py_PackageContext;
|
||||
_Py_PackageContext = packagecontext;
|
||||
m = (*p)();
|
||||
_Py_PackageContext = oldcontext;
|
||||
if (m == NULL)
|
||||
return NULL;
|
||||
p0 = _PyImport_GetDynLoadFunc(name, shortname, pathname, fp);
|
||||
p = (PyObject*(*)(void))p0;
|
||||
if (PyErr_Occurred())
|
||||
return NULL;
|
||||
if (p == NULL) {
|
||||
PyErr_Format(PyExc_ImportError,
|
||||
"dynamic module does not define init function (PyInit_%.200s)",
|
||||
shortname);
|
||||
return NULL;
|
||||
}
|
||||
oldcontext = _Py_PackageContext;
|
||||
_Py_PackageContext = packagecontext;
|
||||
m = (*p)();
|
||||
_Py_PackageContext = oldcontext;
|
||||
if (m == NULL)
|
||||
return NULL;
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
Py_DECREF(m);
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"initialization of %s raised unreported exception",
|
||||
shortname);
|
||||
return NULL;
|
||||
}
|
||||
if (PyErr_Occurred()) {
|
||||
Py_DECREF(m);
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"initialization of %s raised unreported exception",
|
||||
shortname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Remember pointer to module init function. */
|
||||
def = PyModule_GetDef(m);
|
||||
def->m_base.m_init = p;
|
||||
/* Remember pointer to module init function. */
|
||||
def = PyModule_GetDef(m);
|
||||
def->m_base.m_init = p;
|
||||
|
||||
/* Remember the filename as the __file__ attribute */
|
||||
path = PyUnicode_DecodeFSDefault(pathname);
|
||||
if (PyModule_AddObject(m, "__file__", path) < 0)
|
||||
PyErr_Clear(); /* Not important enough to report */
|
||||
/* Remember the filename as the __file__ attribute */
|
||||
path = PyUnicode_DecodeFSDefault(pathname);
|
||||
if (PyModule_AddObject(m, "__file__", path) < 0)
|
||||
PyErr_Clear(); /* Not important enough to report */
|
||||
|
||||
if (_PyImport_FixupExtension(m, name, pathname) < 0)
|
||||
return NULL;
|
||||
if (Py_VerboseFlag)
|
||||
PySys_WriteStderr(
|
||||
"import %s # dynamically loaded from %s\n",
|
||||
name, pathname);
|
||||
return m;
|
||||
if (_PyImport_FixupExtension(m, name, pathname) < 0)
|
||||
return NULL;
|
||||
if (Py_VerboseFlag)
|
||||
PySys_WriteStderr(
|
||||
"import %s # dynamically loaded from %s\n",
|
||||
name, pathname);
|
||||
return m;
|
||||
}
|
||||
|
||||
#endif /* HAVE_DYNAMIC_LOADING */
|
||||
|
|
|
|||
|
|
@ -8,28 +8,28 @@ extern "C" {
|
|||
|
||||
/* Definitions for dynamic loading of extension modules */
|
||||
enum filetype {
|
||||
SEARCH_ERROR,
|
||||
PY_SOURCE,
|
||||
PY_COMPILED,
|
||||
C_EXTENSION,
|
||||
PY_RESOURCE, /* Mac only */
|
||||
PKG_DIRECTORY,
|
||||
C_BUILTIN,
|
||||
PY_FROZEN,
|
||||
PY_CODERESOURCE, /* Mac only */
|
||||
IMP_HOOK
|
||||
SEARCH_ERROR,
|
||||
PY_SOURCE,
|
||||
PY_COMPILED,
|
||||
C_EXTENSION,
|
||||
PY_RESOURCE, /* Mac only */
|
||||
PKG_DIRECTORY,
|
||||
C_BUILTIN,
|
||||
PY_FROZEN,
|
||||
PY_CODERESOURCE, /* Mac only */
|
||||
IMP_HOOK
|
||||
};
|
||||
|
||||
struct filedescr {
|
||||
char *suffix;
|
||||
char *mode;
|
||||
enum filetype type;
|
||||
char *suffix;
|
||||
char *mode;
|
||||
enum filetype type;
|
||||
};
|
||||
extern struct filedescr * _PyImport_Filetab;
|
||||
extern const struct filedescr _PyImport_DynLoadFiletab[];
|
||||
|
||||
extern PyObject *_PyImport_LoadDynamicModule(char *name, char *pathname,
|
||||
FILE *);
|
||||
FILE *);
|
||||
|
||||
/* Max length of module suffix searched for -- accommodates "module.slb" */
|
||||
#define MAXSUFFIXSIZE 12
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ def write_contents(f):
|
|||
continue
|
||||
targets[op] = "TARGET_%s" % opname
|
||||
f.write("static void *opcode_targets[256] = {\n")
|
||||
f.write(",\n".join(["\t&&%s" % s for s in targets]))
|
||||
f.write(",\n".join([" &&%s" % s for s in targets]))
|
||||
f.write("\n};\n")
|
||||
|
||||
|
||||
|
|
|
|||
2048
Python/marshal.c
2048
Python/marshal.c
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -19,20 +19,20 @@
|
|||
|
||||
Return value (rv):
|
||||
|
||||
When 0 <= rv < size, the output conversion was unexceptional, and
|
||||
rv characters were written to str (excluding a trailing \0 byte at
|
||||
str[rv]).
|
||||
When 0 <= rv < size, the output conversion was unexceptional, and
|
||||
rv characters were written to str (excluding a trailing \0 byte at
|
||||
str[rv]).
|
||||
|
||||
When rv >= size, output conversion was truncated, and a buffer of
|
||||
size rv+1 would have been needed to avoid truncation. str[size-1]
|
||||
is \0 in this case.
|
||||
When rv >= size, output conversion was truncated, and a buffer of
|
||||
size rv+1 would have been needed to avoid truncation. str[size-1]
|
||||
is \0 in this case.
|
||||
|
||||
When rv < 0, "something bad happened". str[size-1] is \0 in this
|
||||
case too, but the rest of str is unreliable. It could be that
|
||||
an error in format codes was detected by libc, or on platforms
|
||||
with a non-C99 vsnprintf simply that the buffer wasn't big enough
|
||||
to avoid truncation, or on platforms without any vsnprintf that
|
||||
PyMem_Malloc couldn't obtain space for a temp buffer.
|
||||
When rv < 0, "something bad happened". str[size-1] is \0 in this
|
||||
case too, but the rest of str is unreliable. It could be that
|
||||
an error in format codes was detected by libc, or on platforms
|
||||
with a non-C99 vsnprintf simply that the buffer wasn't big enough
|
||||
to avoid truncation, or on platforms without any vsnprintf that
|
||||
PyMem_Malloc couldn't obtain space for a temp buffer.
|
||||
|
||||
CAUTION: Unlike C99, str != NULL and size > 0 are required.
|
||||
*/
|
||||
|
|
@ -40,65 +40,65 @@
|
|||
int
|
||||
PyOS_snprintf(char *str, size_t size, const char *format, ...)
|
||||
{
|
||||
int rc;
|
||||
va_list va;
|
||||
int rc;
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
rc = PyOS_vsnprintf(str, size, format, va);
|
||||
va_end(va);
|
||||
return rc;
|
||||
va_start(va, format);
|
||||
rc = PyOS_vsnprintf(str, size, format, va);
|
||||
va_end(va);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
|
||||
{
|
||||
int len; /* # bytes written, excluding \0 */
|
||||
int len; /* # bytes written, excluding \0 */
|
||||
#ifdef HAVE_SNPRINTF
|
||||
#define _PyOS_vsnprintf_EXTRA_SPACE 1
|
||||
#else
|
||||
#define _PyOS_vsnprintf_EXTRA_SPACE 512
|
||||
char *buffer;
|
||||
char *buffer;
|
||||
#endif
|
||||
assert(str != NULL);
|
||||
assert(size > 0);
|
||||
assert(format != NULL);
|
||||
/* We take a size_t as input but return an int. Sanity check
|
||||
* our input so that it won't cause an overflow in the
|
||||
* vsnprintf return value or the buffer malloc size. */
|
||||
if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) {
|
||||
len = -666;
|
||||
goto Done;
|
||||
}
|
||||
assert(str != NULL);
|
||||
assert(size > 0);
|
||||
assert(format != NULL);
|
||||
/* We take a size_t as input but return an int. Sanity check
|
||||
* our input so that it won't cause an overflow in the
|
||||
* vsnprintf return value or the buffer malloc size. */
|
||||
if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) {
|
||||
len = -666;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SNPRINTF
|
||||
len = vsnprintf(str, size, format, va);
|
||||
len = vsnprintf(str, size, format, va);
|
||||
#else
|
||||
/* Emulate it. */
|
||||
buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
|
||||
if (buffer == NULL) {
|
||||
len = -666;
|
||||
goto Done;
|
||||
}
|
||||
/* Emulate it. */
|
||||
buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
|
||||
if (buffer == NULL) {
|
||||
len = -666;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
len = vsprintf(buffer, format, va);
|
||||
if (len < 0)
|
||||
/* ignore the error */;
|
||||
len = vsprintf(buffer, format, va);
|
||||
if (len < 0)
|
||||
/* ignore the error */;
|
||||
|
||||
else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE)
|
||||
Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");
|
||||
else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE)
|
||||
Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");
|
||||
|
||||
else {
|
||||
const size_t to_copy = (size_t)len < size ?
|
||||
(size_t)len : size - 1;
|
||||
assert(to_copy < size);
|
||||
memcpy(str, buffer, to_copy);
|
||||
str[to_copy] = '\0';
|
||||
}
|
||||
PyMem_FREE(buffer);
|
||||
else {
|
||||
const size_t to_copy = (size_t)len < size ?
|
||||
(size_t)len : size - 1;
|
||||
assert(to_copy < size);
|
||||
memcpy(str, buffer, to_copy);
|
||||
str[to_copy] = '\0';
|
||||
}
|
||||
PyMem_FREE(buffer);
|
||||
#endif
|
||||
Done:
|
||||
if (size > 0)
|
||||
str[size-1] = '\0';
|
||||
return len;
|
||||
if (size > 0)
|
||||
str[size-1] = '\0';
|
||||
return len;
|
||||
#undef _PyOS_vsnprintf_EXTRA_SPACE
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,43 +18,43 @@
|
|||
* i * base doesn't overflow unsigned long.
|
||||
*/
|
||||
static unsigned long smallmax[] = {
|
||||
0, /* bases 0 and 1 are invalid */
|
||||
0,
|
||||
ULONG_MAX / 2,
|
||||
ULONG_MAX / 3,
|
||||
ULONG_MAX / 4,
|
||||
ULONG_MAX / 5,
|
||||
ULONG_MAX / 6,
|
||||
ULONG_MAX / 7,
|
||||
ULONG_MAX / 8,
|
||||
ULONG_MAX / 9,
|
||||
ULONG_MAX / 10,
|
||||
ULONG_MAX / 11,
|
||||
ULONG_MAX / 12,
|
||||
ULONG_MAX / 13,
|
||||
ULONG_MAX / 14,
|
||||
ULONG_MAX / 15,
|
||||
ULONG_MAX / 16,
|
||||
ULONG_MAX / 17,
|
||||
ULONG_MAX / 18,
|
||||
ULONG_MAX / 19,
|
||||
ULONG_MAX / 20,
|
||||
ULONG_MAX / 21,
|
||||
ULONG_MAX / 22,
|
||||
ULONG_MAX / 23,
|
||||
ULONG_MAX / 24,
|
||||
ULONG_MAX / 25,
|
||||
ULONG_MAX / 26,
|
||||
ULONG_MAX / 27,
|
||||
ULONG_MAX / 28,
|
||||
ULONG_MAX / 29,
|
||||
ULONG_MAX / 30,
|
||||
ULONG_MAX / 31,
|
||||
ULONG_MAX / 32,
|
||||
ULONG_MAX / 33,
|
||||
ULONG_MAX / 34,
|
||||
ULONG_MAX / 35,
|
||||
ULONG_MAX / 36,
|
||||
0, /* bases 0 and 1 are invalid */
|
||||
0,
|
||||
ULONG_MAX / 2,
|
||||
ULONG_MAX / 3,
|
||||
ULONG_MAX / 4,
|
||||
ULONG_MAX / 5,
|
||||
ULONG_MAX / 6,
|
||||
ULONG_MAX / 7,
|
||||
ULONG_MAX / 8,
|
||||
ULONG_MAX / 9,
|
||||
ULONG_MAX / 10,
|
||||
ULONG_MAX / 11,
|
||||
ULONG_MAX / 12,
|
||||
ULONG_MAX / 13,
|
||||
ULONG_MAX / 14,
|
||||
ULONG_MAX / 15,
|
||||
ULONG_MAX / 16,
|
||||
ULONG_MAX / 17,
|
||||
ULONG_MAX / 18,
|
||||
ULONG_MAX / 19,
|
||||
ULONG_MAX / 20,
|
||||
ULONG_MAX / 21,
|
||||
ULONG_MAX / 22,
|
||||
ULONG_MAX / 23,
|
||||
ULONG_MAX / 24,
|
||||
ULONG_MAX / 25,
|
||||
ULONG_MAX / 26,
|
||||
ULONG_MAX / 27,
|
||||
ULONG_MAX / 28,
|
||||
ULONG_MAX / 29,
|
||||
ULONG_MAX / 30,
|
||||
ULONG_MAX / 31,
|
||||
ULONG_MAX / 32,
|
||||
ULONG_MAX / 33,
|
||||
ULONG_MAX / 34,
|
||||
ULONG_MAX / 35,
|
||||
ULONG_MAX / 36,
|
||||
};
|
||||
|
||||
/* maximum digits that can't ever overflow for bases 2 through 36,
|
||||
|
|
@ -63,229 +63,229 @@ static unsigned long smallmax[] = {
|
|||
*/
|
||||
#if SIZEOF_LONG == 4
|
||||
static int digitlimit[] = {
|
||||
0, 0, 32, 20, 16, 13, 12, 11, 10, 10, /* 0 - 9 */
|
||||
9, 9, 8, 8, 8, 8, 8, 7, 7, 7, /* 10 - 19 */
|
||||
7, 7, 7, 7, 6, 6, 6, 6, 6, 6, /* 20 - 29 */
|
||||
6, 6, 6, 6, 6, 6, 6}; /* 30 - 36 */
|
||||
0, 0, 32, 20, 16, 13, 12, 11, 10, 10, /* 0 - 9 */
|
||||
9, 9, 8, 8, 8, 8, 8, 7, 7, 7, /* 10 - 19 */
|
||||
7, 7, 7, 7, 6, 6, 6, 6, 6, 6, /* 20 - 29 */
|
||||
6, 6, 6, 6, 6, 6, 6}; /* 30 - 36 */
|
||||
#elif SIZEOF_LONG == 8
|
||||
/* [int(math.floor(math.log(2**64, i))) for i in range(2, 37)] */
|
||||
static int digitlimit[] = {
|
||||
0, 0, 64, 40, 32, 27, 24, 22, 21, 20, /* 0 - 9 */
|
||||
19, 18, 17, 17, 16, 16, 16, 15, 15, 15, /* 10 - 19 */
|
||||
14, 14, 14, 14, 13, 13, 13, 13, 13, 13, /* 20 - 29 */
|
||||
13, 12, 12, 12, 12, 12, 12}; /* 30 - 36 */
|
||||
0, 0, 64, 40, 32, 27, 24, 22, 21, 20, /* 0 - 9 */
|
||||
19, 18, 17, 17, 16, 16, 16, 15, 15, 15, /* 10 - 19 */
|
||||
14, 14, 14, 14, 13, 13, 13, 13, 13, 13, /* 20 - 29 */
|
||||
13, 12, 12, 12, 12, 12, 12}; /* 30 - 36 */
|
||||
#else
|
||||
#error "Need table for SIZEOF_LONG"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** strtoul
|
||||
** This is a general purpose routine for converting
|
||||
** an ascii string to an integer in an arbitrary base.
|
||||
** Leading white space is ignored. If 'base' is zero
|
||||
** it looks for a leading 0b, 0o or 0x to tell which
|
||||
** base. If these are absent it defaults to 10.
|
||||
** Base must be 0 or between 2 and 36 (inclusive).
|
||||
** If 'ptr' is non-NULL it will contain a pointer to
|
||||
** the end of the scan.
|
||||
** Errors due to bad pointers will probably result in
|
||||
** exceptions - we don't check for them.
|
||||
** strtoul
|
||||
** This is a general purpose routine for converting
|
||||
** an ascii string to an integer in an arbitrary base.
|
||||
** Leading white space is ignored. If 'base' is zero
|
||||
** it looks for a leading 0b, 0o or 0x to tell which
|
||||
** base. If these are absent it defaults to 10.
|
||||
** Base must be 0 or between 2 and 36 (inclusive).
|
||||
** If 'ptr' is non-NULL it will contain a pointer to
|
||||
** the end of the scan.
|
||||
** Errors due to bad pointers will probably result in
|
||||
** exceptions - we don't check for them.
|
||||
*/
|
||||
unsigned long
|
||||
PyOS_strtoul(register char *str, char **ptr, int base)
|
||||
{
|
||||
register unsigned long result = 0; /* return value of the function */
|
||||
register int c; /* current input character */
|
||||
register int ovlimit; /* required digits to overflow */
|
||||
register unsigned long result = 0; /* return value of the function */
|
||||
register int c; /* current input character */
|
||||
register int ovlimit; /* required digits to overflow */
|
||||
|
||||
/* skip leading white space */
|
||||
while (*str && isspace(Py_CHARMASK(*str)))
|
||||
++str;
|
||||
/* skip leading white space */
|
||||
while (*str && isspace(Py_CHARMASK(*str)))
|
||||
++str;
|
||||
|
||||
/* check for leading 0b, 0o or 0x for auto-base or base 16 */
|
||||
switch (base) {
|
||||
case 0: /* look for leading 0b, 0o or 0x */
|
||||
if (*str == '0') {
|
||||
++str;
|
||||
if (*str == 'x' || *str == 'X') {
|
||||
/* there must be at least one digit after 0x */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
base = 16;
|
||||
} else if (*str == 'o' || *str == 'O') {
|
||||
/* there must be at least one digit after 0o */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
base = 8;
|
||||
} else if (*str == 'b' || *str == 'B') {
|
||||
/* there must be at least one digit after 0b */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
base = 2;
|
||||
} else {
|
||||
/* skip all zeroes... */
|
||||
while (*str == '0')
|
||||
++str;
|
||||
while (isspace(Py_CHARMASK(*str)))
|
||||
++str;
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
base = 10;
|
||||
break;
|
||||
/* check for leading 0b, 0o or 0x for auto-base or base 16 */
|
||||
switch (base) {
|
||||
case 0: /* look for leading 0b, 0o or 0x */
|
||||
if (*str == '0') {
|
||||
++str;
|
||||
if (*str == 'x' || *str == 'X') {
|
||||
/* there must be at least one digit after 0x */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
base = 16;
|
||||
} else if (*str == 'o' || *str == 'O') {
|
||||
/* there must be at least one digit after 0o */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
base = 8;
|
||||
} else if (*str == 'b' || *str == 'B') {
|
||||
/* there must be at least one digit after 0b */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
base = 2;
|
||||
} else {
|
||||
/* skip all zeroes... */
|
||||
while (*str == '0')
|
||||
++str;
|
||||
while (isspace(Py_CHARMASK(*str)))
|
||||
++str;
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
base = 10;
|
||||
break;
|
||||
|
||||
/* even with explicit base, skip leading 0? prefix */
|
||||
case 16:
|
||||
if (*str == '0') {
|
||||
++str;
|
||||
if (*str == 'x' || *str == 'X') {
|
||||
/* there must be at least one digit after 0x */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (*str == '0') {
|
||||
++str;
|
||||
if (*str == 'o' || *str == 'O') {
|
||||
/* there must be at least one digit after 0o */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(*str == '0') {
|
||||
++str;
|
||||
if (*str == 'b' || *str == 'B') {
|
||||
/* there must be at least one digit after 0b */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* even with explicit base, skip leading 0? prefix */
|
||||
case 16:
|
||||
if (*str == '0') {
|
||||
++str;
|
||||
if (*str == 'x' || *str == 'X') {
|
||||
/* there must be at least one digit after 0x */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (*str == '0') {
|
||||
++str;
|
||||
if (*str == 'o' || *str == 'O') {
|
||||
/* there must be at least one digit after 0o */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(*str == '0') {
|
||||
++str;
|
||||
if (*str == 'b' || *str == 'B') {
|
||||
/* there must be at least one digit after 0b */
|
||||
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
return 0;
|
||||
}
|
||||
++str;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* catch silly bases */
|
||||
if (base < 2 || base > 36) {
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
return 0;
|
||||
}
|
||||
/* catch silly bases */
|
||||
if (base < 2 || base > 36) {
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* skip leading zeroes */
|
||||
while (*str == '0')
|
||||
++str;
|
||||
/* skip leading zeroes */
|
||||
while (*str == '0')
|
||||
++str;
|
||||
|
||||
/* base is guaranteed to be in [2, 36] at this point */
|
||||
ovlimit = digitlimit[base];
|
||||
/* base is guaranteed to be in [2, 36] at this point */
|
||||
ovlimit = digitlimit[base];
|
||||
|
||||
/* do the conversion until non-digit character encountered */
|
||||
while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) {
|
||||
if (ovlimit > 0) /* no overflow check required */
|
||||
result = result * base + c;
|
||||
else { /* requires overflow check */
|
||||
register unsigned long temp_result;
|
||||
/* do the conversion until non-digit character encountered */
|
||||
while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) {
|
||||
if (ovlimit > 0) /* no overflow check required */
|
||||
result = result * base + c;
|
||||
else { /* requires overflow check */
|
||||
register unsigned long temp_result;
|
||||
|
||||
if (ovlimit < 0) /* guaranteed overflow */
|
||||
goto overflowed;
|
||||
if (ovlimit < 0) /* guaranteed overflow */
|
||||
goto overflowed;
|
||||
|
||||
/* there could be an overflow */
|
||||
/* check overflow just from shifting */
|
||||
if (result > smallmax[base])
|
||||
goto overflowed;
|
||||
/* there could be an overflow */
|
||||
/* check overflow just from shifting */
|
||||
if (result > smallmax[base])
|
||||
goto overflowed;
|
||||
|
||||
result *= base;
|
||||
result *= base;
|
||||
|
||||
/* check overflow from the digit's value */
|
||||
temp_result = result + c;
|
||||
if (temp_result < result)
|
||||
goto overflowed;
|
||||
/* check overflow from the digit's value */
|
||||
temp_result = result + c;
|
||||
if (temp_result < result)
|
||||
goto overflowed;
|
||||
|
||||
result = temp_result;
|
||||
}
|
||||
result = temp_result;
|
||||
}
|
||||
|
||||
++str;
|
||||
--ovlimit;
|
||||
}
|
||||
++str;
|
||||
--ovlimit;
|
||||
}
|
||||
|
||||
/* set pointer to point to the last character scanned */
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
/* set pointer to point to the last character scanned */
|
||||
if (ptr)
|
||||
*ptr = str;
|
||||
|
||||
return result;
|
||||
return result;
|
||||
|
||||
overflowed:
|
||||
if (ptr) {
|
||||
/* spool through remaining digit characters */
|
||||
while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base)
|
||||
++str;
|
||||
*ptr = str;
|
||||
}
|
||||
errno = ERANGE;
|
||||
return (unsigned long)-1;
|
||||
if (ptr) {
|
||||
/* spool through remaining digit characters */
|
||||
while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base)
|
||||
++str;
|
||||
*ptr = str;
|
||||
}
|
||||
errno = ERANGE;
|
||||
return (unsigned long)-1;
|
||||
}
|
||||
|
||||
/* Checking for overflow in PyOS_strtol is a PITA; see comments
|
||||
* about PY_ABS_LONG_MIN in longobject.c.
|
||||
*/
|
||||
#define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN)
|
||||
#define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN)
|
||||
|
||||
long
|
||||
PyOS_strtol(char *str, char **ptr, int base)
|
||||
{
|
||||
long result;
|
||||
unsigned long uresult;
|
||||
char sign;
|
||||
long result;
|
||||
unsigned long uresult;
|
||||
char sign;
|
||||
|
||||
while (*str && isspace(Py_CHARMASK(*str)))
|
||||
str++;
|
||||
while (*str && isspace(Py_CHARMASK(*str)))
|
||||
str++;
|
||||
|
||||
sign = *str;
|
||||
if (sign == '+' || sign == '-')
|
||||
str++;
|
||||
sign = *str;
|
||||
if (sign == '+' || sign == '-')
|
||||
str++;
|
||||
|
||||
uresult = PyOS_strtoul(str, ptr, base);
|
||||
uresult = PyOS_strtoul(str, ptr, base);
|
||||
|
||||
if (uresult <= (unsigned long)LONG_MAX) {
|
||||
result = (long)uresult;
|
||||
if (sign == '-')
|
||||
result = -result;
|
||||
}
|
||||
else if (sign == '-' && uresult == PY_ABS_LONG_MIN) {
|
||||
result = LONG_MIN;
|
||||
}
|
||||
else {
|
||||
errno = ERANGE;
|
||||
result = LONG_MAX;
|
||||
}
|
||||
return result;
|
||||
if (uresult <= (unsigned long)LONG_MAX) {
|
||||
result = (long)uresult;
|
||||
if (sign == '-')
|
||||
result = -result;
|
||||
}
|
||||
else if (sign == '-' && uresult == PY_ABS_LONG_MIN) {
|
||||
result = LONG_MIN;
|
||||
}
|
||||
else {
|
||||
errno = ERANGE;
|
||||
result = LONG_MAX;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,258 +1,258 @@
|
|||
static void *opcode_targets[256] = {
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_POP_TOP,
|
||||
&&TARGET_ROT_TWO,
|
||||
&&TARGET_ROT_THREE,
|
||||
&&TARGET_DUP_TOP,
|
||||
&&TARGET_ROT_FOUR,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_NOP,
|
||||
&&TARGET_UNARY_POSITIVE,
|
||||
&&TARGET_UNARY_NEGATIVE,
|
||||
&&TARGET_UNARY_NOT,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_UNARY_INVERT,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_BINARY_POWER,
|
||||
&&TARGET_BINARY_MULTIPLY,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_BINARY_MODULO,
|
||||
&&TARGET_BINARY_ADD,
|
||||
&&TARGET_BINARY_SUBTRACT,
|
||||
&&TARGET_BINARY_SUBSCR,
|
||||
&&TARGET_BINARY_FLOOR_DIVIDE,
|
||||
&&TARGET_BINARY_TRUE_DIVIDE,
|
||||
&&TARGET_INPLACE_FLOOR_DIVIDE,
|
||||
&&TARGET_INPLACE_TRUE_DIVIDE,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_STORE_MAP,
|
||||
&&TARGET_INPLACE_ADD,
|
||||
&&TARGET_INPLACE_SUBTRACT,
|
||||
&&TARGET_INPLACE_MULTIPLY,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_INPLACE_MODULO,
|
||||
&&TARGET_STORE_SUBSCR,
|
||||
&&TARGET_DELETE_SUBSCR,
|
||||
&&TARGET_BINARY_LSHIFT,
|
||||
&&TARGET_BINARY_RSHIFT,
|
||||
&&TARGET_BINARY_AND,
|
||||
&&TARGET_BINARY_XOR,
|
||||
&&TARGET_BINARY_OR,
|
||||
&&TARGET_INPLACE_POWER,
|
||||
&&TARGET_GET_ITER,
|
||||
&&TARGET_STORE_LOCALS,
|
||||
&&TARGET_PRINT_EXPR,
|
||||
&&TARGET_LOAD_BUILD_CLASS,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_INPLACE_LSHIFT,
|
||||
&&TARGET_INPLACE_RSHIFT,
|
||||
&&TARGET_INPLACE_AND,
|
||||
&&TARGET_INPLACE_XOR,
|
||||
&&TARGET_INPLACE_OR,
|
||||
&&TARGET_BREAK_LOOP,
|
||||
&&TARGET_WITH_CLEANUP,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_RETURN_VALUE,
|
||||
&&TARGET_IMPORT_STAR,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_YIELD_VALUE,
|
||||
&&TARGET_POP_BLOCK,
|
||||
&&TARGET_END_FINALLY,
|
||||
&&TARGET_POP_EXCEPT,
|
||||
&&TARGET_STORE_NAME,
|
||||
&&TARGET_DELETE_NAME,
|
||||
&&TARGET_UNPACK_SEQUENCE,
|
||||
&&TARGET_FOR_ITER,
|
||||
&&TARGET_UNPACK_EX,
|
||||
&&TARGET_STORE_ATTR,
|
||||
&&TARGET_DELETE_ATTR,
|
||||
&&TARGET_STORE_GLOBAL,
|
||||
&&TARGET_DELETE_GLOBAL,
|
||||
&&TARGET_DUP_TOPX,
|
||||
&&TARGET_LOAD_CONST,
|
||||
&&TARGET_LOAD_NAME,
|
||||
&&TARGET_BUILD_TUPLE,
|
||||
&&TARGET_BUILD_LIST,
|
||||
&&TARGET_BUILD_SET,
|
||||
&&TARGET_BUILD_MAP,
|
||||
&&TARGET_LOAD_ATTR,
|
||||
&&TARGET_COMPARE_OP,
|
||||
&&TARGET_IMPORT_NAME,
|
||||
&&TARGET_IMPORT_FROM,
|
||||
&&TARGET_JUMP_FORWARD,
|
||||
&&TARGET_JUMP_IF_FALSE_OR_POP,
|
||||
&&TARGET_JUMP_IF_TRUE_OR_POP,
|
||||
&&TARGET_JUMP_ABSOLUTE,
|
||||
&&TARGET_POP_JUMP_IF_FALSE,
|
||||
&&TARGET_POP_JUMP_IF_TRUE,
|
||||
&&TARGET_LOAD_GLOBAL,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_CONTINUE_LOOP,
|
||||
&&TARGET_SETUP_LOOP,
|
||||
&&TARGET_SETUP_EXCEPT,
|
||||
&&TARGET_SETUP_FINALLY,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_LOAD_FAST,
|
||||
&&TARGET_STORE_FAST,
|
||||
&&TARGET_DELETE_FAST,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_RAISE_VARARGS,
|
||||
&&TARGET_CALL_FUNCTION,
|
||||
&&TARGET_MAKE_FUNCTION,
|
||||
&&TARGET_BUILD_SLICE,
|
||||
&&TARGET_MAKE_CLOSURE,
|
||||
&&TARGET_LOAD_CLOSURE,
|
||||
&&TARGET_LOAD_DEREF,
|
||||
&&TARGET_STORE_DEREF,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_CALL_FUNCTION_VAR,
|
||||
&&TARGET_CALL_FUNCTION_KW,
|
||||
&&TARGET_CALL_FUNCTION_VAR_KW,
|
||||
&&TARGET_SETUP_WITH,
|
||||
&&TARGET_EXTENDED_ARG,
|
||||
&&TARGET_LIST_APPEND,
|
||||
&&TARGET_SET_ADD,
|
||||
&&TARGET_MAP_ADD,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_POP_TOP,
|
||||
&&TARGET_ROT_TWO,
|
||||
&&TARGET_ROT_THREE,
|
||||
&&TARGET_DUP_TOP,
|
||||
&&TARGET_ROT_FOUR,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_NOP,
|
||||
&&TARGET_UNARY_POSITIVE,
|
||||
&&TARGET_UNARY_NEGATIVE,
|
||||
&&TARGET_UNARY_NOT,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_UNARY_INVERT,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_BINARY_POWER,
|
||||
&&TARGET_BINARY_MULTIPLY,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_BINARY_MODULO,
|
||||
&&TARGET_BINARY_ADD,
|
||||
&&TARGET_BINARY_SUBTRACT,
|
||||
&&TARGET_BINARY_SUBSCR,
|
||||
&&TARGET_BINARY_FLOOR_DIVIDE,
|
||||
&&TARGET_BINARY_TRUE_DIVIDE,
|
||||
&&TARGET_INPLACE_FLOOR_DIVIDE,
|
||||
&&TARGET_INPLACE_TRUE_DIVIDE,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_STORE_MAP,
|
||||
&&TARGET_INPLACE_ADD,
|
||||
&&TARGET_INPLACE_SUBTRACT,
|
||||
&&TARGET_INPLACE_MULTIPLY,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_INPLACE_MODULO,
|
||||
&&TARGET_STORE_SUBSCR,
|
||||
&&TARGET_DELETE_SUBSCR,
|
||||
&&TARGET_BINARY_LSHIFT,
|
||||
&&TARGET_BINARY_RSHIFT,
|
||||
&&TARGET_BINARY_AND,
|
||||
&&TARGET_BINARY_XOR,
|
||||
&&TARGET_BINARY_OR,
|
||||
&&TARGET_INPLACE_POWER,
|
||||
&&TARGET_GET_ITER,
|
||||
&&TARGET_STORE_LOCALS,
|
||||
&&TARGET_PRINT_EXPR,
|
||||
&&TARGET_LOAD_BUILD_CLASS,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_INPLACE_LSHIFT,
|
||||
&&TARGET_INPLACE_RSHIFT,
|
||||
&&TARGET_INPLACE_AND,
|
||||
&&TARGET_INPLACE_XOR,
|
||||
&&TARGET_INPLACE_OR,
|
||||
&&TARGET_BREAK_LOOP,
|
||||
&&TARGET_WITH_CLEANUP,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_RETURN_VALUE,
|
||||
&&TARGET_IMPORT_STAR,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_YIELD_VALUE,
|
||||
&&TARGET_POP_BLOCK,
|
||||
&&TARGET_END_FINALLY,
|
||||
&&TARGET_POP_EXCEPT,
|
||||
&&TARGET_STORE_NAME,
|
||||
&&TARGET_DELETE_NAME,
|
||||
&&TARGET_UNPACK_SEQUENCE,
|
||||
&&TARGET_FOR_ITER,
|
||||
&&TARGET_UNPACK_EX,
|
||||
&&TARGET_STORE_ATTR,
|
||||
&&TARGET_DELETE_ATTR,
|
||||
&&TARGET_STORE_GLOBAL,
|
||||
&&TARGET_DELETE_GLOBAL,
|
||||
&&TARGET_DUP_TOPX,
|
||||
&&TARGET_LOAD_CONST,
|
||||
&&TARGET_LOAD_NAME,
|
||||
&&TARGET_BUILD_TUPLE,
|
||||
&&TARGET_BUILD_LIST,
|
||||
&&TARGET_BUILD_SET,
|
||||
&&TARGET_BUILD_MAP,
|
||||
&&TARGET_LOAD_ATTR,
|
||||
&&TARGET_COMPARE_OP,
|
||||
&&TARGET_IMPORT_NAME,
|
||||
&&TARGET_IMPORT_FROM,
|
||||
&&TARGET_JUMP_FORWARD,
|
||||
&&TARGET_JUMP_IF_FALSE_OR_POP,
|
||||
&&TARGET_JUMP_IF_TRUE_OR_POP,
|
||||
&&TARGET_JUMP_ABSOLUTE,
|
||||
&&TARGET_POP_JUMP_IF_FALSE,
|
||||
&&TARGET_POP_JUMP_IF_TRUE,
|
||||
&&TARGET_LOAD_GLOBAL,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_CONTINUE_LOOP,
|
||||
&&TARGET_SETUP_LOOP,
|
||||
&&TARGET_SETUP_EXCEPT,
|
||||
&&TARGET_SETUP_FINALLY,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_LOAD_FAST,
|
||||
&&TARGET_STORE_FAST,
|
||||
&&TARGET_DELETE_FAST,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_RAISE_VARARGS,
|
||||
&&TARGET_CALL_FUNCTION,
|
||||
&&TARGET_MAKE_FUNCTION,
|
||||
&&TARGET_BUILD_SLICE,
|
||||
&&TARGET_MAKE_CLOSURE,
|
||||
&&TARGET_LOAD_CLOSURE,
|
||||
&&TARGET_LOAD_DEREF,
|
||||
&&TARGET_STORE_DEREF,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_CALL_FUNCTION_VAR,
|
||||
&&TARGET_CALL_FUNCTION_KW,
|
||||
&&TARGET_CALL_FUNCTION_VAR_KW,
|
||||
&&TARGET_SETUP_WITH,
|
||||
&&TARGET_EXTENDED_ARG,
|
||||
&&TARGET_LIST_APPEND,
|
||||
&&TARGET_SET_ADD,
|
||||
&&TARGET_MAP_ADD,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode
|
||||
};
|
||||
|
|
|
|||
1152
Python/peephole.c
1152
Python/peephole.c
File diff suppressed because it is too large
Load diff
284
Python/pyarena.c
284
Python/pyarena.c
|
|
@ -12,32 +12,32 @@
|
|||
*/
|
||||
|
||||
#define DEFAULT_BLOCK_SIZE 8192
|
||||
#define ALIGNMENT 8
|
||||
#define ALIGNMENT_MASK (ALIGNMENT - 1)
|
||||
#define ROUNDUP(x) (((x) + ALIGNMENT_MASK) & ~ALIGNMENT_MASK)
|
||||
#define ALIGNMENT 8
|
||||
#define ALIGNMENT_MASK (ALIGNMENT - 1)
|
||||
#define ROUNDUP(x) (((x) + ALIGNMENT_MASK) & ~ALIGNMENT_MASK)
|
||||
|
||||
typedef struct _block {
|
||||
/* Total number of bytes owned by this block available to pass out.
|
||||
* Read-only after initialization. The first such byte starts at
|
||||
* ab_mem.
|
||||
*/
|
||||
size_t ab_size;
|
||||
/* Total number of bytes owned by this block available to pass out.
|
||||
* Read-only after initialization. The first such byte starts at
|
||||
* ab_mem.
|
||||
*/
|
||||
size_t ab_size;
|
||||
|
||||
/* Total number of bytes already passed out. The next byte available
|
||||
* to pass out starts at ab_mem + ab_offset.
|
||||
*/
|
||||
size_t ab_offset;
|
||||
/* Total number of bytes already passed out. The next byte available
|
||||
* to pass out starts at ab_mem + ab_offset.
|
||||
*/
|
||||
size_t ab_offset;
|
||||
|
||||
/* An arena maintains a singly-linked, NULL-terminated list of
|
||||
* all blocks owned by the arena. These are linked via the
|
||||
* ab_next member.
|
||||
*/
|
||||
struct _block *ab_next;
|
||||
/* An arena maintains a singly-linked, NULL-terminated list of
|
||||
* all blocks owned by the arena. These are linked via the
|
||||
* ab_next member.
|
||||
*/
|
||||
struct _block *ab_next;
|
||||
|
||||
/* Pointer to the first allocatable byte owned by this block. Read-
|
||||
* only after initialization.
|
||||
*/
|
||||
void *ab_mem;
|
||||
/* Pointer to the first allocatable byte owned by this block. Read-
|
||||
* only after initialization.
|
||||
*/
|
||||
void *ab_mem;
|
||||
} block;
|
||||
|
||||
/* The arena manages two kinds of memory, blocks of raw memory
|
||||
|
|
@ -46,175 +46,175 @@ typedef struct _block {
|
|||
*/
|
||||
|
||||
struct _arena {
|
||||
/* Pointer to the first block allocated for the arena, never NULL.
|
||||
It is used only to find the first block when the arena is
|
||||
being freed.
|
||||
*/
|
||||
block *a_head;
|
||||
/* Pointer to the first block allocated for the arena, never NULL.
|
||||
It is used only to find the first block when the arena is
|
||||
being freed.
|
||||
*/
|
||||
block *a_head;
|
||||
|
||||
/* Pointer to the block currently used for allocation. It's
|
||||
ab_next field should be NULL. If it is not-null after a
|
||||
call to block_alloc(), it means a new block has been allocated
|
||||
and a_cur should be reset to point it.
|
||||
*/
|
||||
block *a_cur;
|
||||
/* Pointer to the block currently used for allocation. It's
|
||||
ab_next field should be NULL. If it is not-null after a
|
||||
call to block_alloc(), it means a new block has been allocated
|
||||
and a_cur should be reset to point it.
|
||||
*/
|
||||
block *a_cur;
|
||||
|
||||
/* A Python list object containing references to all the PyObject
|
||||
pointers associated with this area. They will be DECREFed
|
||||
when the arena is freed.
|
||||
*/
|
||||
PyObject *a_objects;
|
||||
/* A Python list object containing references to all the PyObject
|
||||
pointers associated with this area. They will be DECREFed
|
||||
when the arena is freed.
|
||||
*/
|
||||
PyObject *a_objects;
|
||||
|
||||
#if defined(Py_DEBUG)
|
||||
/* Debug output */
|
||||
size_t total_allocs;
|
||||
size_t total_size;
|
||||
size_t total_blocks;
|
||||
size_t total_block_size;
|
||||
size_t total_big_blocks;
|
||||
/* Debug output */
|
||||
size_t total_allocs;
|
||||
size_t total_size;
|
||||
size_t total_blocks;
|
||||
size_t total_block_size;
|
||||
size_t total_big_blocks;
|
||||
#endif
|
||||
};
|
||||
|
||||
static block *
|
||||
block_new(size_t size)
|
||||
{
|
||||
/* Allocate header and block as one unit.
|
||||
ab_mem points just past header. */
|
||||
block *b = (block *)malloc(sizeof(block) + size);
|
||||
if (!b)
|
||||
return NULL;
|
||||
b->ab_size = size;
|
||||
b->ab_mem = (void *)(b + 1);
|
||||
b->ab_next = NULL;
|
||||
b->ab_offset = ROUNDUP((Py_uintptr_t)(b->ab_mem)) -
|
||||
(Py_uintptr_t)(b->ab_mem);
|
||||
return b;
|
||||
/* Allocate header and block as one unit.
|
||||
ab_mem points just past header. */
|
||||
block *b = (block *)malloc(sizeof(block) + size);
|
||||
if (!b)
|
||||
return NULL;
|
||||
b->ab_size = size;
|
||||
b->ab_mem = (void *)(b + 1);
|
||||
b->ab_next = NULL;
|
||||
b->ab_offset = ROUNDUP((Py_uintptr_t)(b->ab_mem)) -
|
||||
(Py_uintptr_t)(b->ab_mem);
|
||||
return b;
|
||||
}
|
||||
|
||||
static void
|
||||
block_free(block *b) {
|
||||
while (b) {
|
||||
block *next = b->ab_next;
|
||||
free(b);
|
||||
b = next;
|
||||
}
|
||||
while (b) {
|
||||
block *next = b->ab_next;
|
||||
free(b);
|
||||
b = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
block_alloc(block *b, size_t size)
|
||||
{
|
||||
void *p;
|
||||
assert(b);
|
||||
size = ROUNDUP(size);
|
||||
if (b->ab_offset + size > b->ab_size) {
|
||||
/* If we need to allocate more memory than will fit in
|
||||
the default block, allocate a one-off block that is
|
||||
exactly the right size. */
|
||||
/* TODO(jhylton): Think about space waste at end of block */
|
||||
block *newbl = block_new(
|
||||
size < DEFAULT_BLOCK_SIZE ?
|
||||
DEFAULT_BLOCK_SIZE : size);
|
||||
if (!newbl)
|
||||
return NULL;
|
||||
assert(!b->ab_next);
|
||||
b->ab_next = newbl;
|
||||
b = newbl;
|
||||
}
|
||||
void *p;
|
||||
assert(b);
|
||||
size = ROUNDUP(size);
|
||||
if (b->ab_offset + size > b->ab_size) {
|
||||
/* If we need to allocate more memory than will fit in
|
||||
the default block, allocate a one-off block that is
|
||||
exactly the right size. */
|
||||
/* TODO(jhylton): Think about space waste at end of block */
|
||||
block *newbl = block_new(
|
||||
size < DEFAULT_BLOCK_SIZE ?
|
||||
DEFAULT_BLOCK_SIZE : size);
|
||||
if (!newbl)
|
||||
return NULL;
|
||||
assert(!b->ab_next);
|
||||
b->ab_next = newbl;
|
||||
b = newbl;
|
||||
}
|
||||
|
||||
assert(b->ab_offset + size <= b->ab_size);
|
||||
p = (void *)(((char *)b->ab_mem) + b->ab_offset);
|
||||
b->ab_offset += size;
|
||||
return p;
|
||||
assert(b->ab_offset + size <= b->ab_size);
|
||||
p = (void *)(((char *)b->ab_mem) + b->ab_offset);
|
||||
b->ab_offset += size;
|
||||
return p;
|
||||
}
|
||||
|
||||
PyArena *
|
||||
PyArena_New()
|
||||
{
|
||||
PyArena* arena = (PyArena *)malloc(sizeof(PyArena));
|
||||
if (!arena)
|
||||
return (PyArena*)PyErr_NoMemory();
|
||||
PyArena* arena = (PyArena *)malloc(sizeof(PyArena));
|
||||
if (!arena)
|
||||
return (PyArena*)PyErr_NoMemory();
|
||||
|
||||
arena->a_head = block_new(DEFAULT_BLOCK_SIZE);
|
||||
arena->a_cur = arena->a_head;
|
||||
if (!arena->a_head) {
|
||||
free((void *)arena);
|
||||
return (PyArena*)PyErr_NoMemory();
|
||||
}
|
||||
arena->a_objects = PyList_New(0);
|
||||
if (!arena->a_objects) {
|
||||
block_free(arena->a_head);
|
||||
free((void *)arena);
|
||||
return (PyArena*)PyErr_NoMemory();
|
||||
}
|
||||
arena->a_head = block_new(DEFAULT_BLOCK_SIZE);
|
||||
arena->a_cur = arena->a_head;
|
||||
if (!arena->a_head) {
|
||||
free((void *)arena);
|
||||
return (PyArena*)PyErr_NoMemory();
|
||||
}
|
||||
arena->a_objects = PyList_New(0);
|
||||
if (!arena->a_objects) {
|
||||
block_free(arena->a_head);
|
||||
free((void *)arena);
|
||||
return (PyArena*)PyErr_NoMemory();
|
||||
}
|
||||
#if defined(Py_DEBUG)
|
||||
arena->total_allocs = 0;
|
||||
arena->total_size = 0;
|
||||
arena->total_blocks = 1;
|
||||
arena->total_block_size = DEFAULT_BLOCK_SIZE;
|
||||
arena->total_big_blocks = 0;
|
||||
arena->total_allocs = 0;
|
||||
arena->total_size = 0;
|
||||
arena->total_blocks = 1;
|
||||
arena->total_block_size = DEFAULT_BLOCK_SIZE;
|
||||
arena->total_big_blocks = 0;
|
||||
#endif
|
||||
return arena;
|
||||
return arena;
|
||||
}
|
||||
|
||||
void
|
||||
PyArena_Free(PyArena *arena)
|
||||
{
|
||||
int r;
|
||||
assert(arena);
|
||||
int r;
|
||||
assert(arena);
|
||||
#if defined(Py_DEBUG)
|
||||
/*
|
||||
fprintf(stderr,
|
||||
"alloc=%d size=%d blocks=%d block_size=%d big=%d objects=%d\n",
|
||||
arena->total_allocs, arena->total_size, arena->total_blocks,
|
||||
arena->total_block_size, arena->total_big_blocks,
|
||||
PyList_Size(arena->a_objects));
|
||||
*/
|
||||
/*
|
||||
fprintf(stderr,
|
||||
"alloc=%d size=%d blocks=%d block_size=%d big=%d objects=%d\n",
|
||||
arena->total_allocs, arena->total_size, arena->total_blocks,
|
||||
arena->total_block_size, arena->total_big_blocks,
|
||||
PyList_Size(arena->a_objects));
|
||||
*/
|
||||
#endif
|
||||
block_free(arena->a_head);
|
||||
/* This property normally holds, except when the code being compiled
|
||||
is sys.getobjects(0), in which case there will be two references.
|
||||
assert(arena->a_objects->ob_refcnt == 1);
|
||||
*/
|
||||
block_free(arena->a_head);
|
||||
/* This property normally holds, except when the code being compiled
|
||||
is sys.getobjects(0), in which case there will be two references.
|
||||
assert(arena->a_objects->ob_refcnt == 1);
|
||||
*/
|
||||
|
||||
/* Clear all the elements from the list. This is necessary
|
||||
to guarantee that they will be DECREFed. */
|
||||
r = PyList_SetSlice(arena->a_objects,
|
||||
0, PyList_GET_SIZE(arena->a_objects), NULL);
|
||||
assert(r == 0);
|
||||
assert(PyList_GET_SIZE(arena->a_objects) == 0);
|
||||
Py_DECREF(arena->a_objects);
|
||||
free(arena);
|
||||
/* Clear all the elements from the list. This is necessary
|
||||
to guarantee that they will be DECREFed. */
|
||||
r = PyList_SetSlice(arena->a_objects,
|
||||
0, PyList_GET_SIZE(arena->a_objects), NULL);
|
||||
assert(r == 0);
|
||||
assert(PyList_GET_SIZE(arena->a_objects) == 0);
|
||||
Py_DECREF(arena->a_objects);
|
||||
free(arena);
|
||||
}
|
||||
|
||||
void *
|
||||
PyArena_Malloc(PyArena *arena, size_t size)
|
||||
{
|
||||
void *p = block_alloc(arena->a_cur, size);
|
||||
if (!p)
|
||||
return PyErr_NoMemory();
|
||||
void *p = block_alloc(arena->a_cur, size);
|
||||
if (!p)
|
||||
return PyErr_NoMemory();
|
||||
#if defined(Py_DEBUG)
|
||||
arena->total_allocs++;
|
||||
arena->total_size += size;
|
||||
arena->total_allocs++;
|
||||
arena->total_size += size;
|
||||
#endif
|
||||
/* Reset cur if we allocated a new block. */
|
||||
if (arena->a_cur->ab_next) {
|
||||
arena->a_cur = arena->a_cur->ab_next;
|
||||
/* Reset cur if we allocated a new block. */
|
||||
if (arena->a_cur->ab_next) {
|
||||
arena->a_cur = arena->a_cur->ab_next;
|
||||
#if defined(Py_DEBUG)
|
||||
arena->total_blocks++;
|
||||
arena->total_block_size += arena->a_cur->ab_size;
|
||||
if (arena->a_cur->ab_size > DEFAULT_BLOCK_SIZE)
|
||||
++arena->total_big_blocks;
|
||||
arena->total_blocks++;
|
||||
arena->total_block_size += arena->a_cur->ab_size;
|
||||
if (arena->a_cur->ab_size > DEFAULT_BLOCK_SIZE)
|
||||
++arena->total_big_blocks;
|
||||
#endif
|
||||
}
|
||||
return p;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
int
|
||||
PyArena_AddPyObject(PyArena *arena, PyObject *obj)
|
||||
{
|
||||
int r = PyList_Append(arena->a_objects, obj);
|
||||
if (r >= 0) {
|
||||
Py_DECREF(obj);
|
||||
}
|
||||
return r;
|
||||
int r = PyList_Append(arena->a_objects, obj);
|
||||
if (r >= 0) {
|
||||
Py_DECREF(obj);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
thus rounding from extended precision to double precision. */
|
||||
double _Py_force_double(double x)
|
||||
{
|
||||
volatile double y;
|
||||
y = x;
|
||||
return y;
|
||||
volatile double y;
|
||||
y = x;
|
||||
return y;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -34,21 +34,21 @@ void _Py_set_387controlword(unsigned short cw) {
|
|||
#ifndef HAVE_HYPOT
|
||||
double hypot(double x, double y)
|
||||
{
|
||||
double yx;
|
||||
double yx;
|
||||
|
||||
x = fabs(x);
|
||||
y = fabs(y);
|
||||
if (x < y) {
|
||||
double temp = x;
|
||||
x = y;
|
||||
y = temp;
|
||||
}
|
||||
if (x == 0.)
|
||||
return 0.;
|
||||
else {
|
||||
yx = y/x;
|
||||
return x*sqrt(1.+yx*yx);
|
||||
}
|
||||
x = fabs(x);
|
||||
y = fabs(y);
|
||||
if (x < y) {
|
||||
double temp = x;
|
||||
x = y;
|
||||
y = temp;
|
||||
}
|
||||
if (x == 0.)
|
||||
return 0.;
|
||||
else {
|
||||
yx = y/x;
|
||||
return x*sqrt(1.+yx*yx);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_HYPOT */
|
||||
|
||||
|
|
@ -56,12 +56,12 @@ double hypot(double x, double y)
|
|||
double
|
||||
copysign(double x, double y)
|
||||
{
|
||||
/* use atan2 to distinguish -0. from 0. */
|
||||
if (y > 0. || (y == 0. && atan2(y, -1.) > 0.)) {
|
||||
return fabs(x);
|
||||
} else {
|
||||
return -fabs(x);
|
||||
}
|
||||
/* use atan2 to distinguish -0. from 0. */
|
||||
if (y > 0. || (y == 0. && atan2(y, -1.) > 0.)) {
|
||||
return fabs(x);
|
||||
} else {
|
||||
return -fabs(x);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_COPYSIGN */
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ round(double x)
|
|||
absx = fabs(x);
|
||||
y = floor(absx);
|
||||
if (absx - y >= 0.5)
|
||||
y += 1.0;
|
||||
y += 1.0;
|
||||
return copysign(y, x);
|
||||
}
|
||||
#endif /* HAVE_ROUND */
|
||||
|
|
|
|||
770
Python/pystate.c
770
Python/pystate.c
|
|
@ -60,95 +60,95 @@ static void _PyGILState_NoteThreadState(PyThreadState* tstate);
|
|||
PyInterpreterState *
|
||||
PyInterpreterState_New(void)
|
||||
{
|
||||
PyInterpreterState *interp = (PyInterpreterState *)
|
||||
malloc(sizeof(PyInterpreterState));
|
||||
PyInterpreterState *interp = (PyInterpreterState *)
|
||||
malloc(sizeof(PyInterpreterState));
|
||||
|
||||
if (interp != NULL) {
|
||||
HEAD_INIT();
|
||||
if (interp != NULL) {
|
||||
HEAD_INIT();
|
||||
#ifdef WITH_THREAD
|
||||
if (head_mutex == NULL)
|
||||
Py_FatalError("Can't initialize threads for interpreter");
|
||||
if (head_mutex == NULL)
|
||||
Py_FatalError("Can't initialize threads for interpreter");
|
||||
#endif
|
||||
interp->modules = NULL;
|
||||
interp->modules_reloading = NULL;
|
||||
interp->modules_by_index = NULL;
|
||||
interp->sysdict = NULL;
|
||||
interp->builtins = NULL;
|
||||
interp->tstate_head = NULL;
|
||||
interp->codec_search_path = NULL;
|
||||
interp->codec_search_cache = NULL;
|
||||
interp->codec_error_registry = NULL;
|
||||
interp->codecs_initialized = 0;
|
||||
interp->modules = NULL;
|
||||
interp->modules_reloading = NULL;
|
||||
interp->modules_by_index = NULL;
|
||||
interp->sysdict = NULL;
|
||||
interp->builtins = NULL;
|
||||
interp->tstate_head = NULL;
|
||||
interp->codec_search_path = NULL;
|
||||
interp->codec_search_cache = NULL;
|
||||
interp->codec_error_registry = NULL;
|
||||
interp->codecs_initialized = 0;
|
||||
#ifdef HAVE_DLOPEN
|
||||
#ifdef RTLD_NOW
|
||||
interp->dlopenflags = RTLD_NOW;
|
||||
interp->dlopenflags = RTLD_NOW;
|
||||
#else
|
||||
interp->dlopenflags = RTLD_LAZY;
|
||||
interp->dlopenflags = RTLD_LAZY;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef WITH_TSC
|
||||
interp->tscdump = 0;
|
||||
interp->tscdump = 0;
|
||||
#endif
|
||||
|
||||
HEAD_LOCK();
|
||||
interp->next = interp_head;
|
||||
interp_head = interp;
|
||||
HEAD_UNLOCK();
|
||||
}
|
||||
HEAD_LOCK();
|
||||
interp->next = interp_head;
|
||||
interp_head = interp;
|
||||
HEAD_UNLOCK();
|
||||
}
|
||||
|
||||
return interp;
|
||||
return interp;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PyInterpreterState_Clear(PyInterpreterState *interp)
|
||||
{
|
||||
PyThreadState *p;
|
||||
HEAD_LOCK();
|
||||
for (p = interp->tstate_head; p != NULL; p = p->next)
|
||||
PyThreadState_Clear(p);
|
||||
HEAD_UNLOCK();
|
||||
Py_CLEAR(interp->codec_search_path);
|
||||
Py_CLEAR(interp->codec_search_cache);
|
||||
Py_CLEAR(interp->codec_error_registry);
|
||||
Py_CLEAR(interp->modules);
|
||||
Py_CLEAR(interp->modules_by_index);
|
||||
Py_CLEAR(interp->modules_reloading);
|
||||
Py_CLEAR(interp->sysdict);
|
||||
Py_CLEAR(interp->builtins);
|
||||
PyThreadState *p;
|
||||
HEAD_LOCK();
|
||||
for (p = interp->tstate_head; p != NULL; p = p->next)
|
||||
PyThreadState_Clear(p);
|
||||
HEAD_UNLOCK();
|
||||
Py_CLEAR(interp->codec_search_path);
|
||||
Py_CLEAR(interp->codec_search_cache);
|
||||
Py_CLEAR(interp->codec_error_registry);
|
||||
Py_CLEAR(interp->modules);
|
||||
Py_CLEAR(interp->modules_by_index);
|
||||
Py_CLEAR(interp->modules_reloading);
|
||||
Py_CLEAR(interp->sysdict);
|
||||
Py_CLEAR(interp->builtins);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
zapthreads(PyInterpreterState *interp)
|
||||
{
|
||||
PyThreadState *p;
|
||||
/* No need to lock the mutex here because this should only happen
|
||||
when the threads are all really dead (XXX famous last words). */
|
||||
while ((p = interp->tstate_head) != NULL) {
|
||||
PyThreadState_Delete(p);
|
||||
}
|
||||
PyThreadState *p;
|
||||
/* No need to lock the mutex here because this should only happen
|
||||
when the threads are all really dead (XXX famous last words). */
|
||||
while ((p = interp->tstate_head) != NULL) {
|
||||
PyThreadState_Delete(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PyInterpreterState_Delete(PyInterpreterState *interp)
|
||||
{
|
||||
PyInterpreterState **p;
|
||||
zapthreads(interp);
|
||||
HEAD_LOCK();
|
||||
for (p = &interp_head; ; p = &(*p)->next) {
|
||||
if (*p == NULL)
|
||||
Py_FatalError(
|
||||
"PyInterpreterState_Delete: invalid interp");
|
||||
if (*p == interp)
|
||||
break;
|
||||
}
|
||||
if (interp->tstate_head != NULL)
|
||||
Py_FatalError("PyInterpreterState_Delete: remaining threads");
|
||||
*p = interp->next;
|
||||
HEAD_UNLOCK();
|
||||
free(interp);
|
||||
PyInterpreterState **p;
|
||||
zapthreads(interp);
|
||||
HEAD_LOCK();
|
||||
for (p = &interp_head; ; p = &(*p)->next) {
|
||||
if (*p == NULL)
|
||||
Py_FatalError(
|
||||
"PyInterpreterState_Delete: invalid interp");
|
||||
if (*p == interp)
|
||||
break;
|
||||
}
|
||||
if (interp->tstate_head != NULL)
|
||||
Py_FatalError("PyInterpreterState_Delete: remaining threads");
|
||||
*p = interp->next;
|
||||
HEAD_UNLOCK();
|
||||
free(interp);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -156,141 +156,141 @@ PyInterpreterState_Delete(PyInterpreterState *interp)
|
|||
static struct _frame *
|
||||
threadstate_getframe(PyThreadState *self)
|
||||
{
|
||||
return self->frame;
|
||||
return self->frame;
|
||||
}
|
||||
|
||||
static PyThreadState *
|
||||
new_threadstate(PyInterpreterState *interp, int init)
|
||||
{
|
||||
PyThreadState *tstate = (PyThreadState *)malloc(sizeof(PyThreadState));
|
||||
PyThreadState *tstate = (PyThreadState *)malloc(sizeof(PyThreadState));
|
||||
|
||||
if (_PyThreadState_GetFrame == NULL)
|
||||
_PyThreadState_GetFrame = threadstate_getframe;
|
||||
if (_PyThreadState_GetFrame == NULL)
|
||||
_PyThreadState_GetFrame = threadstate_getframe;
|
||||
|
||||
if (tstate != NULL) {
|
||||
tstate->interp = interp;
|
||||
if (tstate != NULL) {
|
||||
tstate->interp = interp;
|
||||
|
||||
tstate->frame = NULL;
|
||||
tstate->recursion_depth = 0;
|
||||
tstate->overflowed = 0;
|
||||
tstate->recursion_critical = 0;
|
||||
tstate->tracing = 0;
|
||||
tstate->use_tracing = 0;
|
||||
tstate->tick_counter = 0;
|
||||
tstate->gilstate_counter = 0;
|
||||
tstate->async_exc = NULL;
|
||||
tstate->frame = NULL;
|
||||
tstate->recursion_depth = 0;
|
||||
tstate->overflowed = 0;
|
||||
tstate->recursion_critical = 0;
|
||||
tstate->tracing = 0;
|
||||
tstate->use_tracing = 0;
|
||||
tstate->tick_counter = 0;
|
||||
tstate->gilstate_counter = 0;
|
||||
tstate->async_exc = NULL;
|
||||
#ifdef WITH_THREAD
|
||||
tstate->thread_id = PyThread_get_thread_ident();
|
||||
tstate->thread_id = PyThread_get_thread_ident();
|
||||
#else
|
||||
tstate->thread_id = 0;
|
||||
tstate->thread_id = 0;
|
||||
#endif
|
||||
|
||||
tstate->dict = NULL;
|
||||
tstate->dict = NULL;
|
||||
|
||||
tstate->curexc_type = NULL;
|
||||
tstate->curexc_value = NULL;
|
||||
tstate->curexc_traceback = NULL;
|
||||
tstate->curexc_type = NULL;
|
||||
tstate->curexc_value = NULL;
|
||||
tstate->curexc_traceback = NULL;
|
||||
|
||||
tstate->exc_type = NULL;
|
||||
tstate->exc_value = NULL;
|
||||
tstate->exc_traceback = NULL;
|
||||
tstate->exc_type = NULL;
|
||||
tstate->exc_value = NULL;
|
||||
tstate->exc_traceback = NULL;
|
||||
|
||||
tstate->c_profilefunc = NULL;
|
||||
tstate->c_tracefunc = NULL;
|
||||
tstate->c_profileobj = NULL;
|
||||
tstate->c_traceobj = NULL;
|
||||
tstate->c_profilefunc = NULL;
|
||||
tstate->c_tracefunc = NULL;
|
||||
tstate->c_profileobj = NULL;
|
||||
tstate->c_traceobj = NULL;
|
||||
|
||||
if (init)
|
||||
_PyThreadState_Init(tstate);
|
||||
if (init)
|
||||
_PyThreadState_Init(tstate);
|
||||
|
||||
HEAD_LOCK();
|
||||
tstate->next = interp->tstate_head;
|
||||
interp->tstate_head = tstate;
|
||||
HEAD_UNLOCK();
|
||||
}
|
||||
HEAD_LOCK();
|
||||
tstate->next = interp->tstate_head;
|
||||
interp->tstate_head = tstate;
|
||||
HEAD_UNLOCK();
|
||||
}
|
||||
|
||||
return tstate;
|
||||
return tstate;
|
||||
}
|
||||
|
||||
PyThreadState *
|
||||
PyThreadState_New(PyInterpreterState *interp)
|
||||
{
|
||||
return new_threadstate(interp, 1);
|
||||
return new_threadstate(interp, 1);
|
||||
}
|
||||
|
||||
PyThreadState *
|
||||
_PyThreadState_Prealloc(PyInterpreterState *interp)
|
||||
{
|
||||
return new_threadstate(interp, 0);
|
||||
return new_threadstate(interp, 0);
|
||||
}
|
||||
|
||||
void
|
||||
_PyThreadState_Init(PyThreadState *tstate)
|
||||
{
|
||||
#ifdef WITH_THREAD
|
||||
_PyGILState_NoteThreadState(tstate);
|
||||
_PyGILState_NoteThreadState(tstate);
|
||||
#endif
|
||||
}
|
||||
|
||||
PyObject*
|
||||
PyState_FindModule(struct PyModuleDef* m)
|
||||
{
|
||||
Py_ssize_t index = m->m_base.m_index;
|
||||
PyInterpreterState *state = PyThreadState_GET()->interp;
|
||||
PyObject *res;
|
||||
if (index == 0)
|
||||
return NULL;
|
||||
if (state->modules_by_index == NULL)
|
||||
return NULL;
|
||||
if (index > PyList_GET_SIZE(state->modules_by_index))
|
||||
return NULL;
|
||||
res = PyList_GET_ITEM(state->modules_by_index, index);
|
||||
return res==Py_None ? NULL : res;
|
||||
Py_ssize_t index = m->m_base.m_index;
|
||||
PyInterpreterState *state = PyThreadState_GET()->interp;
|
||||
PyObject *res;
|
||||
if (index == 0)
|
||||
return NULL;
|
||||
if (state->modules_by_index == NULL)
|
||||
return NULL;
|
||||
if (index > PyList_GET_SIZE(state->modules_by_index))
|
||||
return NULL;
|
||||
res = PyList_GET_ITEM(state->modules_by_index, index);
|
||||
return res==Py_None ? NULL : res;
|
||||
}
|
||||
|
||||
int
|
||||
_PyState_AddModule(PyObject* module, struct PyModuleDef* def)
|
||||
{
|
||||
PyInterpreterState *state = PyThreadState_GET()->interp;
|
||||
if (!def)
|
||||
return -1;
|
||||
if (!state->modules_by_index) {
|
||||
state->modules_by_index = PyList_New(0);
|
||||
if (!state->modules_by_index)
|
||||
return -1;
|
||||
}
|
||||
while(PyList_GET_SIZE(state->modules_by_index) <= def->m_base.m_index)
|
||||
if (PyList_Append(state->modules_by_index, Py_None) < 0)
|
||||
return -1;
|
||||
Py_INCREF(module);
|
||||
return PyList_SetItem(state->modules_by_index,
|
||||
def->m_base.m_index, module);
|
||||
PyInterpreterState *state = PyThreadState_GET()->interp;
|
||||
if (!def)
|
||||
return -1;
|
||||
if (!state->modules_by_index) {
|
||||
state->modules_by_index = PyList_New(0);
|
||||
if (!state->modules_by_index)
|
||||
return -1;
|
||||
}
|
||||
while(PyList_GET_SIZE(state->modules_by_index) <= def->m_base.m_index)
|
||||
if (PyList_Append(state->modules_by_index, Py_None) < 0)
|
||||
return -1;
|
||||
Py_INCREF(module);
|
||||
return PyList_SetItem(state->modules_by_index,
|
||||
def->m_base.m_index, module);
|
||||
}
|
||||
|
||||
void
|
||||
PyThreadState_Clear(PyThreadState *tstate)
|
||||
{
|
||||
if (Py_VerboseFlag && tstate->frame != NULL)
|
||||
fprintf(stderr,
|
||||
"PyThreadState_Clear: warning: thread still has a frame\n");
|
||||
if (Py_VerboseFlag && tstate->frame != NULL)
|
||||
fprintf(stderr,
|
||||
"PyThreadState_Clear: warning: thread still has a frame\n");
|
||||
|
||||
Py_CLEAR(tstate->frame);
|
||||
Py_CLEAR(tstate->frame);
|
||||
|
||||
Py_CLEAR(tstate->dict);
|
||||
Py_CLEAR(tstate->async_exc);
|
||||
Py_CLEAR(tstate->dict);
|
||||
Py_CLEAR(tstate->async_exc);
|
||||
|
||||
Py_CLEAR(tstate->curexc_type);
|
||||
Py_CLEAR(tstate->curexc_value);
|
||||
Py_CLEAR(tstate->curexc_traceback);
|
||||
Py_CLEAR(tstate->curexc_type);
|
||||
Py_CLEAR(tstate->curexc_value);
|
||||
Py_CLEAR(tstate->curexc_traceback);
|
||||
|
||||
Py_CLEAR(tstate->exc_type);
|
||||
Py_CLEAR(tstate->exc_value);
|
||||
Py_CLEAR(tstate->exc_traceback);
|
||||
Py_CLEAR(tstate->exc_type);
|
||||
Py_CLEAR(tstate->exc_value);
|
||||
Py_CLEAR(tstate->exc_traceback);
|
||||
|
||||
tstate->c_profilefunc = NULL;
|
||||
tstate->c_tracefunc = NULL;
|
||||
Py_CLEAR(tstate->c_profileobj);
|
||||
Py_CLEAR(tstate->c_traceobj);
|
||||
tstate->c_profilefunc = NULL;
|
||||
tstate->c_tracefunc = NULL;
|
||||
Py_CLEAR(tstate->c_profileobj);
|
||||
Py_CLEAR(tstate->c_traceobj);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -298,50 +298,50 @@ PyThreadState_Clear(PyThreadState *tstate)
|
|||
static void
|
||||
tstate_delete_common(PyThreadState *tstate)
|
||||
{
|
||||
PyInterpreterState *interp;
|
||||
PyThreadState **p;
|
||||
PyThreadState *prev_p = NULL;
|
||||
if (tstate == NULL)
|
||||
Py_FatalError("PyThreadState_Delete: NULL tstate");
|
||||
interp = tstate->interp;
|
||||
if (interp == NULL)
|
||||
Py_FatalError("PyThreadState_Delete: NULL interp");
|
||||
HEAD_LOCK();
|
||||
for (p = &interp->tstate_head; ; p = &(*p)->next) {
|
||||
if (*p == NULL)
|
||||
Py_FatalError(
|
||||
"PyThreadState_Delete: invalid tstate");
|
||||
if (*p == tstate)
|
||||
break;
|
||||
/* Sanity check. These states should never happen but if
|
||||
* they do we must abort. Otherwise we'll end up spinning in
|
||||
* in a tight loop with the lock held. A similar check is done
|
||||
* in thread.c find_key(). */
|
||||
if (*p == prev_p)
|
||||
Py_FatalError(
|
||||
"PyThreadState_Delete: small circular list(!)"
|
||||
" and tstate not found.");
|
||||
prev_p = *p;
|
||||
if ((*p)->next == interp->tstate_head)
|
||||
Py_FatalError(
|
||||
"PyThreadState_Delete: circular list(!) and"
|
||||
" tstate not found.");
|
||||
}
|
||||
*p = tstate->next;
|
||||
HEAD_UNLOCK();
|
||||
free(tstate);
|
||||
PyInterpreterState *interp;
|
||||
PyThreadState **p;
|
||||
PyThreadState *prev_p = NULL;
|
||||
if (tstate == NULL)
|
||||
Py_FatalError("PyThreadState_Delete: NULL tstate");
|
||||
interp = tstate->interp;
|
||||
if (interp == NULL)
|
||||
Py_FatalError("PyThreadState_Delete: NULL interp");
|
||||
HEAD_LOCK();
|
||||
for (p = &interp->tstate_head; ; p = &(*p)->next) {
|
||||
if (*p == NULL)
|
||||
Py_FatalError(
|
||||
"PyThreadState_Delete: invalid tstate");
|
||||
if (*p == tstate)
|
||||
break;
|
||||
/* Sanity check. These states should never happen but if
|
||||
* they do we must abort. Otherwise we'll end up spinning in
|
||||
* in a tight loop with the lock held. A similar check is done
|
||||
* in thread.c find_key(). */
|
||||
if (*p == prev_p)
|
||||
Py_FatalError(
|
||||
"PyThreadState_Delete: small circular list(!)"
|
||||
" and tstate not found.");
|
||||
prev_p = *p;
|
||||
if ((*p)->next == interp->tstate_head)
|
||||
Py_FatalError(
|
||||
"PyThreadState_Delete: circular list(!) and"
|
||||
" tstate not found.");
|
||||
}
|
||||
*p = tstate->next;
|
||||
HEAD_UNLOCK();
|
||||
free(tstate);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PyThreadState_Delete(PyThreadState *tstate)
|
||||
{
|
||||
if (tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current))
|
||||
Py_FatalError("PyThreadState_Delete: tstate is still current");
|
||||
tstate_delete_common(tstate);
|
||||
if (tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current))
|
||||
Py_FatalError("PyThreadState_Delete: tstate is still current");
|
||||
tstate_delete_common(tstate);
|
||||
#ifdef WITH_THREAD
|
||||
if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate)
|
||||
PyThread_delete_key_value(autoTLSkey);
|
||||
if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate)
|
||||
PyThread_delete_key_value(autoTLSkey);
|
||||
#endif /* WITH_THREAD */
|
||||
}
|
||||
|
||||
|
|
@ -350,16 +350,16 @@ PyThreadState_Delete(PyThreadState *tstate)
|
|||
void
|
||||
PyThreadState_DeleteCurrent()
|
||||
{
|
||||
PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
|
||||
&_PyThreadState_Current);
|
||||
if (tstate == NULL)
|
||||
Py_FatalError(
|
||||
"PyThreadState_DeleteCurrent: no current tstate");
|
||||
_Py_atomic_store_relaxed(&_PyThreadState_Current, NULL);
|
||||
tstate_delete_common(tstate);
|
||||
if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate)
|
||||
PyThread_delete_key_value(autoTLSkey);
|
||||
PyEval_ReleaseLock();
|
||||
PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
|
||||
&_PyThreadState_Current);
|
||||
if (tstate == NULL)
|
||||
Py_FatalError(
|
||||
"PyThreadState_DeleteCurrent: no current tstate");
|
||||
_Py_atomic_store_relaxed(&_PyThreadState_Current, NULL);
|
||||
tstate_delete_common(tstate);
|
||||
if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate)
|
||||
PyThread_delete_key_value(autoTLSkey);
|
||||
PyEval_ReleaseLock();
|
||||
}
|
||||
#endif /* WITH_THREAD */
|
||||
|
||||
|
|
@ -367,39 +367,39 @@ PyThreadState_DeleteCurrent()
|
|||
PyThreadState *
|
||||
PyThreadState_Get(void)
|
||||
{
|
||||
PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
|
||||
&_PyThreadState_Current);
|
||||
if (tstate == NULL)
|
||||
Py_FatalError("PyThreadState_Get: no current thread");
|
||||
PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
|
||||
&_PyThreadState_Current);
|
||||
if (tstate == NULL)
|
||||
Py_FatalError("PyThreadState_Get: no current thread");
|
||||
|
||||
return tstate;
|
||||
return tstate;
|
||||
}
|
||||
|
||||
|
||||
PyThreadState *
|
||||
PyThreadState_Swap(PyThreadState *newts)
|
||||
{
|
||||
PyThreadState *oldts = (PyThreadState*)_Py_atomic_load_relaxed(
|
||||
&_PyThreadState_Current);
|
||||
PyThreadState *oldts = (PyThreadState*)_Py_atomic_load_relaxed(
|
||||
&_PyThreadState_Current);
|
||||
|
||||
_Py_atomic_store_relaxed(&_PyThreadState_Current, newts);
|
||||
/* It should not be possible for more than one thread state
|
||||
to be used for a thread. Check this the best we can in debug
|
||||
builds.
|
||||
*/
|
||||
_Py_atomic_store_relaxed(&_PyThreadState_Current, newts);
|
||||
/* It should not be possible for more than one thread state
|
||||
to be used for a thread. Check this the best we can in debug
|
||||
builds.
|
||||
*/
|
||||
#if defined(Py_DEBUG) && defined(WITH_THREAD)
|
||||
if (newts) {
|
||||
/* This can be called from PyEval_RestoreThread(). Similar
|
||||
to it, we need to ensure errno doesn't change.
|
||||
*/
|
||||
int err = errno;
|
||||
PyThreadState *check = PyGILState_GetThisThreadState();
|
||||
if (check && check->interp == newts->interp && check != newts)
|
||||
Py_FatalError("Invalid thread state for this thread");
|
||||
errno = err;
|
||||
}
|
||||
if (newts) {
|
||||
/* This can be called from PyEval_RestoreThread(). Similar
|
||||
to it, we need to ensure errno doesn't change.
|
||||
*/
|
||||
int err = errno;
|
||||
PyThreadState *check = PyGILState_GetThisThreadState();
|
||||
if (check && check->interp == newts->interp && check != newts)
|
||||
Py_FatalError("Invalid thread state for this thread");
|
||||
errno = err;
|
||||
}
|
||||
#endif
|
||||
return oldts;
|
||||
return oldts;
|
||||
}
|
||||
|
||||
/* An extension mechanism to store arbitrary additional per-thread state.
|
||||
|
|
@ -411,18 +411,18 @@ PyThreadState_Swap(PyThreadState *newts)
|
|||
PyObject *
|
||||
PyThreadState_GetDict(void)
|
||||
{
|
||||
PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
|
||||
&_PyThreadState_Current);
|
||||
if (tstate == NULL)
|
||||
return NULL;
|
||||
PyThreadState *tstate = (PyThreadState*)_Py_atomic_load_relaxed(
|
||||
&_PyThreadState_Current);
|
||||
if (tstate == NULL)
|
||||
return NULL;
|
||||
|
||||
if (tstate->dict == NULL) {
|
||||
PyObject *d;
|
||||
tstate->dict = d = PyDict_New();
|
||||
if (d == NULL)
|
||||
PyErr_Clear();
|
||||
}
|
||||
return tstate->dict;
|
||||
if (tstate->dict == NULL) {
|
||||
PyObject *d;
|
||||
tstate->dict = d = PyDict_New();
|
||||
if (d == NULL)
|
||||
PyErr_Clear();
|
||||
}
|
||||
return tstate->dict;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -436,37 +436,37 @@ PyThreadState_GetDict(void)
|
|||
|
||||
int
|
||||
PyThreadState_SetAsyncExc(long id, PyObject *exc) {
|
||||
PyThreadState *tstate = PyThreadState_GET();
|
||||
PyInterpreterState *interp = tstate->interp;
|
||||
PyThreadState *p;
|
||||
PyThreadState *tstate = PyThreadState_GET();
|
||||
PyInterpreterState *interp = tstate->interp;
|
||||
PyThreadState *p;
|
||||
|
||||
/* Although the GIL is held, a few C API functions can be called
|
||||
* without the GIL held, and in particular some that create and
|
||||
* destroy thread and interpreter states. Those can mutate the
|
||||
* list of thread states we're traversing, so to prevent that we lock
|
||||
* head_mutex for the duration.
|
||||
*/
|
||||
HEAD_LOCK();
|
||||
for (p = interp->tstate_head; p != NULL; p = p->next) {
|
||||
if (p->thread_id == id) {
|
||||
/* Tricky: we need to decref the current value
|
||||
* (if any) in p->async_exc, but that can in turn
|
||||
* allow arbitrary Python code to run, including
|
||||
* perhaps calls to this function. To prevent
|
||||
* deadlock, we need to release head_mutex before
|
||||
* the decref.
|
||||
*/
|
||||
PyObject *old_exc = p->async_exc;
|
||||
Py_XINCREF(exc);
|
||||
p->async_exc = exc;
|
||||
HEAD_UNLOCK();
|
||||
Py_XDECREF(old_exc);
|
||||
_PyEval_SignalAsyncExc();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
HEAD_UNLOCK();
|
||||
return 0;
|
||||
/* Although the GIL is held, a few C API functions can be called
|
||||
* without the GIL held, and in particular some that create and
|
||||
* destroy thread and interpreter states. Those can mutate the
|
||||
* list of thread states we're traversing, so to prevent that we lock
|
||||
* head_mutex for the duration.
|
||||
*/
|
||||
HEAD_LOCK();
|
||||
for (p = interp->tstate_head; p != NULL; p = p->next) {
|
||||
if (p->thread_id == id) {
|
||||
/* Tricky: we need to decref the current value
|
||||
* (if any) in p->async_exc, but that can in turn
|
||||
* allow arbitrary Python code to run, including
|
||||
* perhaps calls to this function. To prevent
|
||||
* deadlock, we need to release head_mutex before
|
||||
* the decref.
|
||||
*/
|
||||
PyObject *old_exc = p->async_exc;
|
||||
Py_XINCREF(exc);
|
||||
p->async_exc = exc;
|
||||
HEAD_UNLOCK();
|
||||
Py_XDECREF(old_exc);
|
||||
_PyEval_SignalAsyncExc();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
HEAD_UNLOCK();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -476,22 +476,22 @@ PyThreadState_SetAsyncExc(long id, PyObject *exc) {
|
|||
PyInterpreterState *
|
||||
PyInterpreterState_Head(void)
|
||||
{
|
||||
return interp_head;
|
||||
return interp_head;
|
||||
}
|
||||
|
||||
PyInterpreterState *
|
||||
PyInterpreterState_Next(PyInterpreterState *interp) {
|
||||
return interp->next;
|
||||
return interp->next;
|
||||
}
|
||||
|
||||
PyThreadState *
|
||||
PyInterpreterState_ThreadHead(PyInterpreterState *interp) {
|
||||
return interp->tstate_head;
|
||||
return interp->tstate_head;
|
||||
}
|
||||
|
||||
PyThreadState *
|
||||
PyThreadState_Next(PyThreadState *tstate) {
|
||||
return tstate->next;
|
||||
return tstate->next;
|
||||
}
|
||||
|
||||
/* The implementation of sys._current_frames(). This is intended to be
|
||||
|
|
@ -502,44 +502,44 @@ PyThreadState_Next(PyThreadState *tstate) {
|
|||
PyObject *
|
||||
_PyThread_CurrentFrames(void)
|
||||
{
|
||||
PyObject *result;
|
||||
PyInterpreterState *i;
|
||||
PyObject *result;
|
||||
PyInterpreterState *i;
|
||||
|
||||
result = PyDict_New();
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
result = PyDict_New();
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
/* for i in all interpreters:
|
||||
* for t in all of i's thread states:
|
||||
* if t's frame isn't NULL, map t's id to its frame
|
||||
* Because these lists can mutute even when the GIL is held, we
|
||||
* need to grab head_mutex for the duration.
|
||||
*/
|
||||
HEAD_LOCK();
|
||||
for (i = interp_head; i != NULL; i = i->next) {
|
||||
PyThreadState *t;
|
||||
for (t = i->tstate_head; t != NULL; t = t->next) {
|
||||
PyObject *id;
|
||||
int stat;
|
||||
struct _frame *frame = t->frame;
|
||||
if (frame == NULL)
|
||||
continue;
|
||||
id = PyLong_FromLong(t->thread_id);
|
||||
if (id == NULL)
|
||||
goto Fail;
|
||||
stat = PyDict_SetItem(result, id, (PyObject *)frame);
|
||||
Py_DECREF(id);
|
||||
if (stat < 0)
|
||||
goto Fail;
|
||||
}
|
||||
}
|
||||
HEAD_UNLOCK();
|
||||
return result;
|
||||
/* for i in all interpreters:
|
||||
* for t in all of i's thread states:
|
||||
* if t's frame isn't NULL, map t's id to its frame
|
||||
* Because these lists can mutute even when the GIL is held, we
|
||||
* need to grab head_mutex for the duration.
|
||||
*/
|
||||
HEAD_LOCK();
|
||||
for (i = interp_head; i != NULL; i = i->next) {
|
||||
PyThreadState *t;
|
||||
for (t = i->tstate_head; t != NULL; t = t->next) {
|
||||
PyObject *id;
|
||||
int stat;
|
||||
struct _frame *frame = t->frame;
|
||||
if (frame == NULL)
|
||||
continue;
|
||||
id = PyLong_FromLong(t->thread_id);
|
||||
if (id == NULL)
|
||||
goto Fail;
|
||||
stat = PyDict_SetItem(result, id, (PyObject *)frame);
|
||||
Py_DECREF(id);
|
||||
if (stat < 0)
|
||||
goto Fail;
|
||||
}
|
||||
}
|
||||
HEAD_UNLOCK();
|
||||
return result;
|
||||
|
||||
Fail:
|
||||
HEAD_UNLOCK();
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
HEAD_UNLOCK();
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Python "auto thread state" API. */
|
||||
|
|
@ -556,9 +556,9 @@ _PyThread_CurrentFrames(void)
|
|||
static int
|
||||
PyThreadState_IsCurrent(PyThreadState *tstate)
|
||||
{
|
||||
/* Must be the tstate for this thread */
|
||||
assert(PyGILState_GetThisThreadState()==tstate);
|
||||
return tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current);
|
||||
/* Must be the tstate for this thread */
|
||||
assert(PyGILState_GetThisThreadState()==tstate);
|
||||
return tstate == _Py_atomic_load_relaxed(&_PyThreadState_Current);
|
||||
}
|
||||
|
||||
/* Internal initialization/finalization functions called by
|
||||
|
|
@ -567,21 +567,21 @@ PyThreadState_IsCurrent(PyThreadState *tstate)
|
|||
void
|
||||
_PyGILState_Init(PyInterpreterState *i, PyThreadState *t)
|
||||
{
|
||||
assert(i && t); /* must init with valid states */
|
||||
autoTLSkey = PyThread_create_key();
|
||||
autoInterpreterState = i;
|
||||
assert(PyThread_get_key_value(autoTLSkey) == NULL);
|
||||
assert(t->gilstate_counter == 0);
|
||||
assert(i && t); /* must init with valid states */
|
||||
autoTLSkey = PyThread_create_key();
|
||||
autoInterpreterState = i;
|
||||
assert(PyThread_get_key_value(autoTLSkey) == NULL);
|
||||
assert(t->gilstate_counter == 0);
|
||||
|
||||
_PyGILState_NoteThreadState(t);
|
||||
_PyGILState_NoteThreadState(t);
|
||||
}
|
||||
|
||||
void
|
||||
_PyGILState_Fini(void)
|
||||
{
|
||||
PyThread_delete_key(autoTLSkey);
|
||||
autoTLSkey = 0;
|
||||
autoInterpreterState = NULL;
|
||||
PyThread_delete_key(autoTLSkey);
|
||||
autoTLSkey = 0;
|
||||
autoInterpreterState = NULL;
|
||||
}
|
||||
|
||||
/* When a thread state is created for a thread by some mechanism other than
|
||||
|
|
@ -592,113 +592,113 @@ _PyGILState_Fini(void)
|
|||
static void
|
||||
_PyGILState_NoteThreadState(PyThreadState* tstate)
|
||||
{
|
||||
/* If autoTLSkey is 0, this must be the very first threadstate created
|
||||
in Py_Initialize(). Don't do anything for now (we'll be back here
|
||||
when _PyGILState_Init is called). */
|
||||
if (!autoTLSkey)
|
||||
return;
|
||||
/* If autoTLSkey is 0, this must be the very first threadstate created
|
||||
in Py_Initialize(). Don't do anything for now (we'll be back here
|
||||
when _PyGILState_Init is called). */
|
||||
if (!autoTLSkey)
|
||||
return;
|
||||
|
||||
/* Stick the thread state for this thread in thread local storage.
|
||||
/* Stick the thread state for this thread in thread local storage.
|
||||
|
||||
The only situation where you can legitimately have more than one
|
||||
thread state for an OS level thread is when there are multiple
|
||||
interpreters, when:
|
||||
The only situation where you can legitimately have more than one
|
||||
thread state for an OS level thread is when there are multiple
|
||||
interpreters, when:
|
||||
|
||||
a) You shouldn't really be using the PyGILState_ APIs anyway,
|
||||
and:
|
||||
a) You shouldn't really be using the PyGILState_ APIs anyway,
|
||||
and:
|
||||
|
||||
b) The slightly odd way PyThread_set_key_value works (see
|
||||
comments by its implementation) means that the first thread
|
||||
state created for that given OS level thread will "win",
|
||||
which seems reasonable behaviour.
|
||||
*/
|
||||
if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0)
|
||||
Py_FatalError("Couldn't create autoTLSkey mapping");
|
||||
b) The slightly odd way PyThread_set_key_value works (see
|
||||
comments by its implementation) means that the first thread
|
||||
state created for that given OS level thread will "win",
|
||||
which seems reasonable behaviour.
|
||||
*/
|
||||
if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0)
|
||||
Py_FatalError("Couldn't create autoTLSkey mapping");
|
||||
|
||||
/* PyGILState_Release must not try to delete this thread state. */
|
||||
tstate->gilstate_counter = 1;
|
||||
/* PyGILState_Release must not try to delete this thread state. */
|
||||
tstate->gilstate_counter = 1;
|
||||
}
|
||||
|
||||
/* The public functions */
|
||||
PyThreadState *
|
||||
PyGILState_GetThisThreadState(void)
|
||||
{
|
||||
if (autoInterpreterState == NULL || autoTLSkey == 0)
|
||||
return NULL;
|
||||
return (PyThreadState *)PyThread_get_key_value(autoTLSkey);
|
||||
if (autoInterpreterState == NULL || autoTLSkey == 0)
|
||||
return NULL;
|
||||
return (PyThreadState *)PyThread_get_key_value(autoTLSkey);
|
||||
}
|
||||
|
||||
PyGILState_STATE
|
||||
PyGILState_Ensure(void)
|
||||
{
|
||||
int current;
|
||||
PyThreadState *tcur;
|
||||
/* Note that we do not auto-init Python here - apart from
|
||||
potential races with 2 threads auto-initializing, pep-311
|
||||
spells out other issues. Embedders are expected to have
|
||||
called Py_Initialize() and usually PyEval_InitThreads().
|
||||
*/
|
||||
assert(autoInterpreterState); /* Py_Initialize() hasn't been called! */
|
||||
tcur = (PyThreadState *)PyThread_get_key_value(autoTLSkey);
|
||||
if (tcur == NULL) {
|
||||
/* Create a new thread state for this thread */
|
||||
tcur = PyThreadState_New(autoInterpreterState);
|
||||
if (tcur == NULL)
|
||||
Py_FatalError("Couldn't create thread-state for new thread");
|
||||
/* This is our thread state! We'll need to delete it in the
|
||||
matching call to PyGILState_Release(). */
|
||||
tcur->gilstate_counter = 0;
|
||||
current = 0; /* new thread state is never current */
|
||||
}
|
||||
else
|
||||
current = PyThreadState_IsCurrent(tcur);
|
||||
if (current == 0)
|
||||
PyEval_RestoreThread(tcur);
|
||||
/* Update our counter in the thread-state - no need for locks:
|
||||
- tcur will remain valid as we hold the GIL.
|
||||
- the counter is safe as we are the only thread "allowed"
|
||||
to modify this value
|
||||
*/
|
||||
++tcur->gilstate_counter;
|
||||
return current ? PyGILState_LOCKED : PyGILState_UNLOCKED;
|
||||
int current;
|
||||
PyThreadState *tcur;
|
||||
/* Note that we do not auto-init Python here - apart from
|
||||
potential races with 2 threads auto-initializing, pep-311
|
||||
spells out other issues. Embedders are expected to have
|
||||
called Py_Initialize() and usually PyEval_InitThreads().
|
||||
*/
|
||||
assert(autoInterpreterState); /* Py_Initialize() hasn't been called! */
|
||||
tcur = (PyThreadState *)PyThread_get_key_value(autoTLSkey);
|
||||
if (tcur == NULL) {
|
||||
/* Create a new thread state for this thread */
|
||||
tcur = PyThreadState_New(autoInterpreterState);
|
||||
if (tcur == NULL)
|
||||
Py_FatalError("Couldn't create thread-state for new thread");
|
||||
/* This is our thread state! We'll need to delete it in the
|
||||
matching call to PyGILState_Release(). */
|
||||
tcur->gilstate_counter = 0;
|
||||
current = 0; /* new thread state is never current */
|
||||
}
|
||||
else
|
||||
current = PyThreadState_IsCurrent(tcur);
|
||||
if (current == 0)
|
||||
PyEval_RestoreThread(tcur);
|
||||
/* Update our counter in the thread-state - no need for locks:
|
||||
- tcur will remain valid as we hold the GIL.
|
||||
- the counter is safe as we are the only thread "allowed"
|
||||
to modify this value
|
||||
*/
|
||||
++tcur->gilstate_counter;
|
||||
return current ? PyGILState_LOCKED : PyGILState_UNLOCKED;
|
||||
}
|
||||
|
||||
void
|
||||
PyGILState_Release(PyGILState_STATE oldstate)
|
||||
{
|
||||
PyThreadState *tcur = (PyThreadState *)PyThread_get_key_value(
|
||||
autoTLSkey);
|
||||
if (tcur == NULL)
|
||||
Py_FatalError("auto-releasing thread-state, "
|
||||
"but no thread-state for this thread");
|
||||
/* We must hold the GIL and have our thread state current */
|
||||
/* XXX - remove the check - the assert should be fine,
|
||||
but while this is very new (April 2003), the extra check
|
||||
by release-only users can't hurt.
|
||||
*/
|
||||
if (! PyThreadState_IsCurrent(tcur))
|
||||
Py_FatalError("This thread state must be current when releasing");
|
||||
assert(PyThreadState_IsCurrent(tcur));
|
||||
--tcur->gilstate_counter;
|
||||
assert(tcur->gilstate_counter >= 0); /* illegal counter value */
|
||||
PyThreadState *tcur = (PyThreadState *)PyThread_get_key_value(
|
||||
autoTLSkey);
|
||||
if (tcur == NULL)
|
||||
Py_FatalError("auto-releasing thread-state, "
|
||||
"but no thread-state for this thread");
|
||||
/* We must hold the GIL and have our thread state current */
|
||||
/* XXX - remove the check - the assert should be fine,
|
||||
but while this is very new (April 2003), the extra check
|
||||
by release-only users can't hurt.
|
||||
*/
|
||||
if (! PyThreadState_IsCurrent(tcur))
|
||||
Py_FatalError("This thread state must be current when releasing");
|
||||
assert(PyThreadState_IsCurrent(tcur));
|
||||
--tcur->gilstate_counter;
|
||||
assert(tcur->gilstate_counter >= 0); /* illegal counter value */
|
||||
|
||||
/* If we're going to destroy this thread-state, we must
|
||||
* clear it while the GIL is held, as destructors may run.
|
||||
*/
|
||||
if (tcur->gilstate_counter == 0) {
|
||||
/* can't have been locked when we created it */
|
||||
assert(oldstate == PyGILState_UNLOCKED);
|
||||
PyThreadState_Clear(tcur);
|
||||
/* Delete the thread-state. Note this releases the GIL too!
|
||||
* It's vital that the GIL be held here, to avoid shutdown
|
||||
* races; see bugs 225673 and 1061968 (that nasty bug has a
|
||||
* habit of coming back).
|
||||
*/
|
||||
PyThreadState_DeleteCurrent();
|
||||
}
|
||||
/* Release the lock if necessary */
|
||||
else if (oldstate == PyGILState_UNLOCKED)
|
||||
PyEval_SaveThread();
|
||||
/* If we're going to destroy this thread-state, we must
|
||||
* clear it while the GIL is held, as destructors may run.
|
||||
*/
|
||||
if (tcur->gilstate_counter == 0) {
|
||||
/* can't have been locked when we created it */
|
||||
assert(oldstate == PyGILState_UNLOCKED);
|
||||
PyThreadState_Clear(tcur);
|
||||
/* Delete the thread-state. Note this releases the GIL too!
|
||||
* It's vital that the GIL be held here, to avoid shutdown
|
||||
* races; see bugs 225673 and 1061968 (that nasty bug has a
|
||||
* habit of coming back).
|
||||
*/
|
||||
PyThreadState_DeleteCurrent();
|
||||
}
|
||||
/* Release the lock if necessary */
|
||||
else if (oldstate == PyGILState_UNLOCKED)
|
||||
PyEval_SaveThread();
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -6,21 +6,21 @@
|
|||
int
|
||||
PyOS_mystrnicmp(const char *s1, const char *s2, Py_ssize_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
while ((--size > 0) &&
|
||||
(tolower((unsigned)*s1) == tolower((unsigned)*s2))) {
|
||||
if (!*s1++ || !*s2++)
|
||||
break;
|
||||
}
|
||||
return tolower((unsigned)*s1) - tolower((unsigned)*s2);
|
||||
if (size == 0)
|
||||
return 0;
|
||||
while ((--size > 0) &&
|
||||
(tolower((unsigned)*s1) == tolower((unsigned)*s2))) {
|
||||
if (!*s1++ || !*s2++)
|
||||
break;
|
||||
}
|
||||
return tolower((unsigned)*s1) - tolower((unsigned)*s2);
|
||||
}
|
||||
|
||||
int
|
||||
PyOS_mystricmp(const char *s1, const char *s2)
|
||||
{
|
||||
while (*s1 && (tolower((unsigned)*s1++) == tolower((unsigned)*s2++))) {
|
||||
;
|
||||
}
|
||||
return (tolower((unsigned)*s1) - tolower((unsigned)*s2));
|
||||
while (*s1 && (tolower((unsigned)*s1++) == tolower((unsigned)*s2++))) {
|
||||
;
|
||||
}
|
||||
return (tolower((unsigned)*s1) - tolower((unsigned)*s2));
|
||||
}
|
||||
|
|
|
|||
1688
Python/pystrtod.c
1688
Python/pystrtod.c
File diff suppressed because it is too large
Load diff
3086
Python/pythonrun.c
3086
Python/pythonrun.c
File diff suppressed because it is too large
Load diff
|
|
@ -8,293 +8,293 @@
|
|||
PyObject *
|
||||
PyMember_GetOne(const char *addr, PyMemberDef *l)
|
||||
{
|
||||
PyObject *v;
|
||||
PyObject *v;
|
||||
|
||||
addr += l->offset;
|
||||
switch (l->type) {
|
||||
case T_BOOL:
|
||||
v = PyBool_FromLong(*(char*)addr);
|
||||
break;
|
||||
case T_BYTE:
|
||||
v = PyLong_FromLong(*(char*)addr);
|
||||
break;
|
||||
case T_UBYTE:
|
||||
v = PyLong_FromUnsignedLong(*(unsigned char*)addr);
|
||||
break;
|
||||
case T_SHORT:
|
||||
v = PyLong_FromLong(*(short*)addr);
|
||||
break;
|
||||
case T_USHORT:
|
||||
v = PyLong_FromUnsignedLong(*(unsigned short*)addr);
|
||||
break;
|
||||
case T_INT:
|
||||
v = PyLong_FromLong(*(int*)addr);
|
||||
break;
|
||||
case T_UINT:
|
||||
v = PyLong_FromUnsignedLong(*(unsigned int*)addr);
|
||||
break;
|
||||
case T_LONG:
|
||||
v = PyLong_FromLong(*(long*)addr);
|
||||
break;
|
||||
case T_ULONG:
|
||||
v = PyLong_FromUnsignedLong(*(unsigned long*)addr);
|
||||
break;
|
||||
case T_PYSSIZET:
|
||||
v = PyLong_FromSsize_t(*(Py_ssize_t*)addr);
|
||||
break;
|
||||
case T_FLOAT:
|
||||
v = PyFloat_FromDouble((double)*(float*)addr);
|
||||
break;
|
||||
case T_DOUBLE:
|
||||
v = PyFloat_FromDouble(*(double*)addr);
|
||||
break;
|
||||
case T_STRING:
|
||||
if (*(char**)addr == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
v = Py_None;
|
||||
}
|
||||
else
|
||||
v = PyUnicode_FromString(*(char**)addr);
|
||||
break;
|
||||
case T_STRING_INPLACE:
|
||||
v = PyUnicode_FromString((char*)addr);
|
||||
break;
|
||||
case T_CHAR:
|
||||
v = PyUnicode_FromStringAndSize((char*)addr, 1);
|
||||
break;
|
||||
case T_OBJECT:
|
||||
v = *(PyObject **)addr;
|
||||
if (v == NULL)
|
||||
v = Py_None;
|
||||
Py_INCREF(v);
|
||||
break;
|
||||
case T_OBJECT_EX:
|
||||
v = *(PyObject **)addr;
|
||||
if (v == NULL)
|
||||
PyErr_SetString(PyExc_AttributeError, l->name);
|
||||
Py_XINCREF(v);
|
||||
break;
|
||||
addr += l->offset;
|
||||
switch (l->type) {
|
||||
case T_BOOL:
|
||||
v = PyBool_FromLong(*(char*)addr);
|
||||
break;
|
||||
case T_BYTE:
|
||||
v = PyLong_FromLong(*(char*)addr);
|
||||
break;
|
||||
case T_UBYTE:
|
||||
v = PyLong_FromUnsignedLong(*(unsigned char*)addr);
|
||||
break;
|
||||
case T_SHORT:
|
||||
v = PyLong_FromLong(*(short*)addr);
|
||||
break;
|
||||
case T_USHORT:
|
||||
v = PyLong_FromUnsignedLong(*(unsigned short*)addr);
|
||||
break;
|
||||
case T_INT:
|
||||
v = PyLong_FromLong(*(int*)addr);
|
||||
break;
|
||||
case T_UINT:
|
||||
v = PyLong_FromUnsignedLong(*(unsigned int*)addr);
|
||||
break;
|
||||
case T_LONG:
|
||||
v = PyLong_FromLong(*(long*)addr);
|
||||
break;
|
||||
case T_ULONG:
|
||||
v = PyLong_FromUnsignedLong(*(unsigned long*)addr);
|
||||
break;
|
||||
case T_PYSSIZET:
|
||||
v = PyLong_FromSsize_t(*(Py_ssize_t*)addr);
|
||||
break;
|
||||
case T_FLOAT:
|
||||
v = PyFloat_FromDouble((double)*(float*)addr);
|
||||
break;
|
||||
case T_DOUBLE:
|
||||
v = PyFloat_FromDouble(*(double*)addr);
|
||||
break;
|
||||
case T_STRING:
|
||||
if (*(char**)addr == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
v = Py_None;
|
||||
}
|
||||
else
|
||||
v = PyUnicode_FromString(*(char**)addr);
|
||||
break;
|
||||
case T_STRING_INPLACE:
|
||||
v = PyUnicode_FromString((char*)addr);
|
||||
break;
|
||||
case T_CHAR:
|
||||
v = PyUnicode_FromStringAndSize((char*)addr, 1);
|
||||
break;
|
||||
case T_OBJECT:
|
||||
v = *(PyObject **)addr;
|
||||
if (v == NULL)
|
||||
v = Py_None;
|
||||
Py_INCREF(v);
|
||||
break;
|
||||
case T_OBJECT_EX:
|
||||
v = *(PyObject **)addr;
|
||||
if (v == NULL)
|
||||
PyErr_SetString(PyExc_AttributeError, l->name);
|
||||
Py_XINCREF(v);
|
||||
break;
|
||||
#ifdef HAVE_LONG_LONG
|
||||
case T_LONGLONG:
|
||||
v = PyLong_FromLongLong(*(PY_LONG_LONG *)addr);
|
||||
break;
|
||||
case T_ULONGLONG:
|
||||
v = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)addr);
|
||||
break;
|
||||
case T_LONGLONG:
|
||||
v = PyLong_FromLongLong(*(PY_LONG_LONG *)addr);
|
||||
break;
|
||||
case T_ULONGLONG:
|
||||
v = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)addr);
|
||||
break;
|
||||
#endif /* HAVE_LONG_LONG */
|
||||
case T_NONE:
|
||||
v = Py_None;
|
||||
Py_INCREF(v);
|
||||
break;
|
||||
default:
|
||||
PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
|
||||
v = NULL;
|
||||
}
|
||||
return v;
|
||||
case T_NONE:
|
||||
v = Py_None;
|
||||
Py_INCREF(v);
|
||||
break;
|
||||
default:
|
||||
PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
|
||||
v = NULL;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
#define WARN(msg) \
|
||||
do { \
|
||||
if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) \
|
||||
return -1; \
|
||||
#define WARN(msg) \
|
||||
do { \
|
||||
if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) \
|
||||
return -1; \
|
||||
} while (0)
|
||||
|
||||
int
|
||||
PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
|
||||
{
|
||||
PyObject *oldv;
|
||||
PyObject *oldv;
|
||||
|
||||
addr += l->offset;
|
||||
addr += l->offset;
|
||||
|
||||
if ((l->flags & READONLY))
|
||||
{
|
||||
PyErr_SetString(PyExc_AttributeError, "readonly attribute");
|
||||
return -1;
|
||||
}
|
||||
if (v == NULL) {
|
||||
if (l->type == T_OBJECT_EX) {
|
||||
/* Check if the attribute is set. */
|
||||
if (*(PyObject **)addr == NULL) {
|
||||
PyErr_SetString(PyExc_AttributeError, l->name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (l->type != T_OBJECT) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"can't delete numeric/char attribute");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
switch (l->type) {
|
||||
case T_BOOL:{
|
||||
if (!PyBool_Check(v)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"attribute value type must be bool");
|
||||
return -1;
|
||||
}
|
||||
if (v == Py_True)
|
||||
*(char*)addr = (char) 1;
|
||||
else
|
||||
*(char*)addr = (char) 0;
|
||||
break;
|
||||
}
|
||||
case T_BYTE:{
|
||||
long long_val = PyLong_AsLong(v);
|
||||
if ((long_val == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
*(char*)addr = (char)long_val;
|
||||
/* XXX: For compatibility, only warn about truncations
|
||||
for now. */
|
||||
if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))
|
||||
WARN("Truncation of value to char");
|
||||
break;
|
||||
}
|
||||
case T_UBYTE:{
|
||||
long long_val = PyLong_AsLong(v);
|
||||
if ((long_val == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
*(unsigned char*)addr = (unsigned char)long_val;
|
||||
if ((long_val > UCHAR_MAX) || (long_val < 0))
|
||||
WARN("Truncation of value to unsigned char");
|
||||
break;
|
||||
}
|
||||
case T_SHORT:{
|
||||
long long_val = PyLong_AsLong(v);
|
||||
if ((long_val == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
*(short*)addr = (short)long_val;
|
||||
if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))
|
||||
WARN("Truncation of value to short");
|
||||
break;
|
||||
}
|
||||
case T_USHORT:{
|
||||
long long_val = PyLong_AsLong(v);
|
||||
if ((long_val == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
*(unsigned short*)addr = (unsigned short)long_val;
|
||||
if ((long_val > USHRT_MAX) || (long_val < 0))
|
||||
WARN("Truncation of value to unsigned short");
|
||||
break;
|
||||
}
|
||||
case T_INT:{
|
||||
long long_val = PyLong_AsLong(v);
|
||||
if ((long_val == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
*(int *)addr = (int)long_val;
|
||||
if ((long_val > INT_MAX) || (long_val < INT_MIN))
|
||||
WARN("Truncation of value to int");
|
||||
break;
|
||||
}
|
||||
case T_UINT:{
|
||||
unsigned long ulong_val = PyLong_AsUnsignedLong(v);
|
||||
if ((ulong_val == (unsigned long)-1) && PyErr_Occurred()) {
|
||||
/* XXX: For compatibility, accept negative int values
|
||||
as well. */
|
||||
PyErr_Clear();
|
||||
ulong_val = PyLong_AsLong(v);
|
||||
if ((ulong_val == (unsigned long)-1) &&
|
||||
PyErr_Occurred())
|
||||
return -1;
|
||||
*(unsigned int *)addr = (unsigned int)ulong_val;
|
||||
WARN("Writing negative value into unsigned field");
|
||||
} else
|
||||
*(unsigned int *)addr = (unsigned int)ulong_val;
|
||||
if (ulong_val > UINT_MAX)
|
||||
WARN("Truncation of value to unsigned int");
|
||||
break;
|
||||
}
|
||||
case T_LONG:{
|
||||
*(long*)addr = PyLong_AsLong(v);
|
||||
if ((*(long*)addr == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
case T_ULONG:{
|
||||
*(unsigned long*)addr = PyLong_AsUnsignedLong(v);
|
||||
if ((*(unsigned long*)addr == (unsigned long)-1)
|
||||
&& PyErr_Occurred()) {
|
||||
/* XXX: For compatibility, accept negative int values
|
||||
as well. */
|
||||
PyErr_Clear();
|
||||
*(unsigned long*)addr = PyLong_AsLong(v);
|
||||
if ((*(unsigned long*)addr == (unsigned long)-1)
|
||||
&& PyErr_Occurred())
|
||||
return -1;
|
||||
WARN("Writing negative value into unsigned field");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case T_PYSSIZET:{
|
||||
*(Py_ssize_t*)addr = PyLong_AsSsize_t(v);
|
||||
if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)
|
||||
&& PyErr_Occurred())
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
case T_FLOAT:{
|
||||
double double_val = PyFloat_AsDouble(v);
|
||||
if ((double_val == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
*(float*)addr = (float)double_val;
|
||||
break;
|
||||
}
|
||||
case T_DOUBLE:
|
||||
*(double*)addr = PyFloat_AsDouble(v);
|
||||
if ((*(double*)addr == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
break;
|
||||
case T_OBJECT:
|
||||
case T_OBJECT_EX:
|
||||
Py_XINCREF(v);
|
||||
oldv = *(PyObject **)addr;
|
||||
*(PyObject **)addr = v;
|
||||
Py_XDECREF(oldv);
|
||||
break;
|
||||
case T_CHAR: {
|
||||
char *string;
|
||||
Py_ssize_t len;
|
||||
if ((l->flags & READONLY))
|
||||
{
|
||||
PyErr_SetString(PyExc_AttributeError, "readonly attribute");
|
||||
return -1;
|
||||
}
|
||||
if (v == NULL) {
|
||||
if (l->type == T_OBJECT_EX) {
|
||||
/* Check if the attribute is set. */
|
||||
if (*(PyObject **)addr == NULL) {
|
||||
PyErr_SetString(PyExc_AttributeError, l->name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (l->type != T_OBJECT) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"can't delete numeric/char attribute");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
switch (l->type) {
|
||||
case T_BOOL:{
|
||||
if (!PyBool_Check(v)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"attribute value type must be bool");
|
||||
return -1;
|
||||
}
|
||||
if (v == Py_True)
|
||||
*(char*)addr = (char) 1;
|
||||
else
|
||||
*(char*)addr = (char) 0;
|
||||
break;
|
||||
}
|
||||
case T_BYTE:{
|
||||
long long_val = PyLong_AsLong(v);
|
||||
if ((long_val == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
*(char*)addr = (char)long_val;
|
||||
/* XXX: For compatibility, only warn about truncations
|
||||
for now. */
|
||||
if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))
|
||||
WARN("Truncation of value to char");
|
||||
break;
|
||||
}
|
||||
case T_UBYTE:{
|
||||
long long_val = PyLong_AsLong(v);
|
||||
if ((long_val == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
*(unsigned char*)addr = (unsigned char)long_val;
|
||||
if ((long_val > UCHAR_MAX) || (long_val < 0))
|
||||
WARN("Truncation of value to unsigned char");
|
||||
break;
|
||||
}
|
||||
case T_SHORT:{
|
||||
long long_val = PyLong_AsLong(v);
|
||||
if ((long_val == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
*(short*)addr = (short)long_val;
|
||||
if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))
|
||||
WARN("Truncation of value to short");
|
||||
break;
|
||||
}
|
||||
case T_USHORT:{
|
||||
long long_val = PyLong_AsLong(v);
|
||||
if ((long_val == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
*(unsigned short*)addr = (unsigned short)long_val;
|
||||
if ((long_val > USHRT_MAX) || (long_val < 0))
|
||||
WARN("Truncation of value to unsigned short");
|
||||
break;
|
||||
}
|
||||
case T_INT:{
|
||||
long long_val = PyLong_AsLong(v);
|
||||
if ((long_val == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
*(int *)addr = (int)long_val;
|
||||
if ((long_val > INT_MAX) || (long_val < INT_MIN))
|
||||
WARN("Truncation of value to int");
|
||||
break;
|
||||
}
|
||||
case T_UINT:{
|
||||
unsigned long ulong_val = PyLong_AsUnsignedLong(v);
|
||||
if ((ulong_val == (unsigned long)-1) && PyErr_Occurred()) {
|
||||
/* XXX: For compatibility, accept negative int values
|
||||
as well. */
|
||||
PyErr_Clear();
|
||||
ulong_val = PyLong_AsLong(v);
|
||||
if ((ulong_val == (unsigned long)-1) &&
|
||||
PyErr_Occurred())
|
||||
return -1;
|
||||
*(unsigned int *)addr = (unsigned int)ulong_val;
|
||||
WARN("Writing negative value into unsigned field");
|
||||
} else
|
||||
*(unsigned int *)addr = (unsigned int)ulong_val;
|
||||
if (ulong_val > UINT_MAX)
|
||||
WARN("Truncation of value to unsigned int");
|
||||
break;
|
||||
}
|
||||
case T_LONG:{
|
||||
*(long*)addr = PyLong_AsLong(v);
|
||||
if ((*(long*)addr == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
case T_ULONG:{
|
||||
*(unsigned long*)addr = PyLong_AsUnsignedLong(v);
|
||||
if ((*(unsigned long*)addr == (unsigned long)-1)
|
||||
&& PyErr_Occurred()) {
|
||||
/* XXX: For compatibility, accept negative int values
|
||||
as well. */
|
||||
PyErr_Clear();
|
||||
*(unsigned long*)addr = PyLong_AsLong(v);
|
||||
if ((*(unsigned long*)addr == (unsigned long)-1)
|
||||
&& PyErr_Occurred())
|
||||
return -1;
|
||||
WARN("Writing negative value into unsigned field");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case T_PYSSIZET:{
|
||||
*(Py_ssize_t*)addr = PyLong_AsSsize_t(v);
|
||||
if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)
|
||||
&& PyErr_Occurred())
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
case T_FLOAT:{
|
||||
double double_val = PyFloat_AsDouble(v);
|
||||
if ((double_val == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
*(float*)addr = (float)double_val;
|
||||
break;
|
||||
}
|
||||
case T_DOUBLE:
|
||||
*(double*)addr = PyFloat_AsDouble(v);
|
||||
if ((*(double*)addr == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
break;
|
||||
case T_OBJECT:
|
||||
case T_OBJECT_EX:
|
||||
Py_XINCREF(v);
|
||||
oldv = *(PyObject **)addr;
|
||||
*(PyObject **)addr = v;
|
||||
Py_XDECREF(oldv);
|
||||
break;
|
||||
case T_CHAR: {
|
||||
char *string;
|
||||
Py_ssize_t len;
|
||||
|
||||
if (!PyUnicode_Check(v)) {
|
||||
PyErr_BadArgument();
|
||||
return -1;
|
||||
}
|
||||
string = _PyUnicode_AsStringAndSize(v, &len);
|
||||
if (len != 1) {
|
||||
PyErr_BadArgument();
|
||||
return -1;
|
||||
}
|
||||
*(char*)addr = string[0];
|
||||
break;
|
||||
}
|
||||
case T_STRING:
|
||||
case T_STRING_INPLACE:
|
||||
PyErr_SetString(PyExc_TypeError, "readonly attribute");
|
||||
return -1;
|
||||
if (!PyUnicode_Check(v)) {
|
||||
PyErr_BadArgument();
|
||||
return -1;
|
||||
}
|
||||
string = _PyUnicode_AsStringAndSize(v, &len);
|
||||
if (len != 1) {
|
||||
PyErr_BadArgument();
|
||||
return -1;
|
||||
}
|
||||
*(char*)addr = string[0];
|
||||
break;
|
||||
}
|
||||
case T_STRING:
|
||||
case T_STRING_INPLACE:
|
||||
PyErr_SetString(PyExc_TypeError, "readonly attribute");
|
||||
return -1;
|
||||
#ifdef HAVE_LONG_LONG
|
||||
case T_LONGLONG:{
|
||||
PY_LONG_LONG value;
|
||||
*(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v);
|
||||
if ((value == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
case T_ULONGLONG:{
|
||||
unsigned PY_LONG_LONG value;
|
||||
/* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
|
||||
doesn't ??? */
|
||||
if (PyLong_Check(v))
|
||||
*(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v);
|
||||
else
|
||||
*(unsigned PY_LONG_LONG*)addr = value = PyLong_AsLong(v);
|
||||
if ((value == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
case T_LONGLONG:{
|
||||
PY_LONG_LONG value;
|
||||
*(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v);
|
||||
if ((value == -1) && PyErr_Occurred())
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
case T_ULONGLONG:{
|
||||
unsigned PY_LONG_LONG value;
|
||||
/* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
|
||||
doesn't ??? */
|
||||
if (PyLong_Check(v))
|
||||
*(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v);
|
||||
else
|
||||
*(unsigned PY_LONG_LONG*)addr = value = PyLong_AsLong(v);
|
||||
if ((value == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
#endif /* HAVE_LONG_LONG */
|
||||
default:
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"bad memberdescr type for %s", l->name);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"bad memberdescr type for %s", l->name);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
2522
Python/symtable.c
2522
Python/symtable.c
File diff suppressed because it is too large
Load diff
1894
Python/sysmodule.c
1894
Python/sysmodule.c
File diff suppressed because it is too large
Load diff
250
Python/thread.c
250
Python/thread.c
|
|
@ -40,7 +40,7 @@
|
|||
#endif
|
||||
|
||||
/* Check if we're running on HP-UX and _SC_THREADS is defined. If so, then
|
||||
enough of the Posix threads package is implimented to support python
|
||||
enough of the Posix threads package is implimented to support python
|
||||
threads.
|
||||
|
||||
This is valid for HP-UX 11.23 running on an ia64 system. If needed, add
|
||||
|
|
@ -58,8 +58,8 @@
|
|||
|
||||
#ifdef Py_DEBUG
|
||||
static int thread_debug = 0;
|
||||
#define dprintf(args) (void)((thread_debug & 1) && printf args)
|
||||
#define d2printf(args) ((thread_debug & 8) && printf args)
|
||||
#define dprintf(args) (void)((thread_debug & 1) && printf args)
|
||||
#define d2printf(args) ((thread_debug & 8) && printf args)
|
||||
#else
|
||||
#define dprintf(args)
|
||||
#define d2printf(args)
|
||||
|
|
@ -73,20 +73,20 @@ void
|
|||
PyThread_init_thread(void)
|
||||
{
|
||||
#ifdef Py_DEBUG
|
||||
char *p = Py_GETENV("PYTHONTHREADDEBUG");
|
||||
char *p = Py_GETENV("PYTHONTHREADDEBUG");
|
||||
|
||||
if (p) {
|
||||
if (*p)
|
||||
thread_debug = atoi(p);
|
||||
else
|
||||
thread_debug = 1;
|
||||
}
|
||||
if (p) {
|
||||
if (*p)
|
||||
thread_debug = atoi(p);
|
||||
else
|
||||
thread_debug = 1;
|
||||
}
|
||||
#endif /* Py_DEBUG */
|
||||
if (initialized)
|
||||
return;
|
||||
initialized = 1;
|
||||
dprintf(("PyThread_init_thread called\n"));
|
||||
PyThread__init_thread();
|
||||
if (initialized)
|
||||
return;
|
||||
initialized = 1;
|
||||
dprintf(("PyThread_init_thread called\n"));
|
||||
PyThread__init_thread();
|
||||
}
|
||||
|
||||
/* Support for runtime thread stack size tuning.
|
||||
|
|
@ -145,21 +145,21 @@ static size_t _pythread_stacksize = 0;
|
|||
size_t
|
||||
PyThread_get_stacksize(void)
|
||||
{
|
||||
return _pythread_stacksize;
|
||||
return _pythread_stacksize;
|
||||
}
|
||||
|
||||
/* Only platforms defining a THREAD_SET_STACKSIZE() macro
|
||||
in thread_<platform>.h support changing the stack size.
|
||||
Return 0 if stack size is valid,
|
||||
-1 if stack size value is invalid,
|
||||
-2 if setting stack size is not supported. */
|
||||
-1 if stack size value is invalid,
|
||||
-2 if setting stack size is not supported. */
|
||||
int
|
||||
PyThread_set_stacksize(size_t size)
|
||||
{
|
||||
#if defined(THREAD_SET_STACKSIZE)
|
||||
return THREAD_SET_STACKSIZE(size);
|
||||
return THREAD_SET_STACKSIZE(size);
|
||||
#else
|
||||
return -2;
|
||||
return -2;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -211,15 +211,15 @@ that calls to PyThread_create_key() are serialized externally.
|
|||
* to enforce exclusion internally.
|
||||
*/
|
||||
struct key {
|
||||
/* Next record in the list, or NULL if this is the last record. */
|
||||
struct key *next;
|
||||
/* Next record in the list, or NULL if this is the last record. */
|
||||
struct key *next;
|
||||
|
||||
/* The thread id, according to PyThread_get_thread_ident(). */
|
||||
long id;
|
||||
/* The thread id, according to PyThread_get_thread_ident(). */
|
||||
long id;
|
||||
|
||||
/* The key and its associated value. */
|
||||
int key;
|
||||
void *value;
|
||||
/* The key and its associated value. */
|
||||
int key;
|
||||
void *value;
|
||||
};
|
||||
|
||||
static struct key *keyhead = NULL;
|
||||
|
|
@ -250,41 +250,41 @@ static int nkeys = 0; /* PyThread_create_key() hands out nkeys+1 next */
|
|||
static struct key *
|
||||
find_key(int key, void *value)
|
||||
{
|
||||
struct key *p, *prev_p;
|
||||
long id = PyThread_get_thread_ident();
|
||||
struct key *p, *prev_p;
|
||||
long id = PyThread_get_thread_ident();
|
||||
|
||||
if (!keymutex)
|
||||
return NULL;
|
||||
PyThread_acquire_lock(keymutex, 1);
|
||||
prev_p = NULL;
|
||||
for (p = keyhead; p != NULL; p = p->next) {
|
||||
if (p->id == id && p->key == key)
|
||||
goto Done;
|
||||
/* Sanity check. These states should never happen but if
|
||||
* they do we must abort. Otherwise we'll end up spinning in
|
||||
* in a tight loop with the lock held. A similar check is done
|
||||
* in pystate.c tstate_delete_common(). */
|
||||
if (p == prev_p)
|
||||
Py_FatalError("tls find_key: small circular list(!)");
|
||||
prev_p = p;
|
||||
if (p->next == keyhead)
|
||||
Py_FatalError("tls find_key: circular list(!)");
|
||||
}
|
||||
if (value == NULL) {
|
||||
assert(p == NULL);
|
||||
goto Done;
|
||||
}
|
||||
p = (struct key *)malloc(sizeof(struct key));
|
||||
if (p != NULL) {
|
||||
p->id = id;
|
||||
p->key = key;
|
||||
p->value = value;
|
||||
p->next = keyhead;
|
||||
keyhead = p;
|
||||
}
|
||||
if (!keymutex)
|
||||
return NULL;
|
||||
PyThread_acquire_lock(keymutex, 1);
|
||||
prev_p = NULL;
|
||||
for (p = keyhead; p != NULL; p = p->next) {
|
||||
if (p->id == id && p->key == key)
|
||||
goto Done;
|
||||
/* Sanity check. These states should never happen but if
|
||||
* they do we must abort. Otherwise we'll end up spinning in
|
||||
* in a tight loop with the lock held. A similar check is done
|
||||
* in pystate.c tstate_delete_common(). */
|
||||
if (p == prev_p)
|
||||
Py_FatalError("tls find_key: small circular list(!)");
|
||||
prev_p = p;
|
||||
if (p->next == keyhead)
|
||||
Py_FatalError("tls find_key: circular list(!)");
|
||||
}
|
||||
if (value == NULL) {
|
||||
assert(p == NULL);
|
||||
goto Done;
|
||||
}
|
||||
p = (struct key *)malloc(sizeof(struct key));
|
||||
if (p != NULL) {
|
||||
p->id = id;
|
||||
p->key = key;
|
||||
p->value = value;
|
||||
p->next = keyhead;
|
||||
keyhead = p;
|
||||
}
|
||||
Done:
|
||||
PyThread_release_lock(keymutex);
|
||||
return p;
|
||||
PyThread_release_lock(keymutex);
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Return a new key. This must be called before any other functions in
|
||||
|
|
@ -294,32 +294,32 @@ find_key(int key, void *value)
|
|||
int
|
||||
PyThread_create_key(void)
|
||||
{
|
||||
/* All parts of this function are wrong if it's called by multiple
|
||||
* threads simultaneously.
|
||||
*/
|
||||
if (keymutex == NULL)
|
||||
keymutex = PyThread_allocate_lock();
|
||||
return ++nkeys;
|
||||
/* All parts of this function are wrong if it's called by multiple
|
||||
* threads simultaneously.
|
||||
*/
|
||||
if (keymutex == NULL)
|
||||
keymutex = PyThread_allocate_lock();
|
||||
return ++nkeys;
|
||||
}
|
||||
|
||||
/* Forget the associations for key across *all* threads. */
|
||||
void
|
||||
PyThread_delete_key(int key)
|
||||
{
|
||||
struct key *p, **q;
|
||||
struct key *p, **q;
|
||||
|
||||
PyThread_acquire_lock(keymutex, 1);
|
||||
q = &keyhead;
|
||||
while ((p = *q) != NULL) {
|
||||
if (p->key == key) {
|
||||
*q = p->next;
|
||||
free((void *)p);
|
||||
/* NB This does *not* free p->value! */
|
||||
}
|
||||
else
|
||||
q = &p->next;
|
||||
}
|
||||
PyThread_release_lock(keymutex);
|
||||
PyThread_acquire_lock(keymutex, 1);
|
||||
q = &keyhead;
|
||||
while ((p = *q) != NULL) {
|
||||
if (p->key == key) {
|
||||
*q = p->next;
|
||||
free((void *)p);
|
||||
/* NB This does *not* free p->value! */
|
||||
}
|
||||
else
|
||||
q = &p->next;
|
||||
}
|
||||
PyThread_release_lock(keymutex);
|
||||
}
|
||||
|
||||
/* Confusing: If the current thread has an association for key,
|
||||
|
|
@ -331,14 +331,14 @@ PyThread_delete_key(int key)
|
|||
int
|
||||
PyThread_set_key_value(int key, void *value)
|
||||
{
|
||||
struct key *p;
|
||||
struct key *p;
|
||||
|
||||
assert(value != NULL);
|
||||
p = find_key(key, value);
|
||||
if (p == NULL)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
assert(value != NULL);
|
||||
p = find_key(key, value);
|
||||
if (p == NULL)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Retrieve the value associated with key in the current thread, or NULL
|
||||
|
|
@ -347,34 +347,34 @@ PyThread_set_key_value(int key, void *value)
|
|||
void *
|
||||
PyThread_get_key_value(int key)
|
||||
{
|
||||
struct key *p = find_key(key, NULL);
|
||||
struct key *p = find_key(key, NULL);
|
||||
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
else
|
||||
return p->value;
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
else
|
||||
return p->value;
|
||||
}
|
||||
|
||||
/* Forget the current thread's association for key, if any. */
|
||||
void
|
||||
PyThread_delete_key_value(int key)
|
||||
{
|
||||
long id = PyThread_get_thread_ident();
|
||||
struct key *p, **q;
|
||||
long id = PyThread_get_thread_ident();
|
||||
struct key *p, **q;
|
||||
|
||||
PyThread_acquire_lock(keymutex, 1);
|
||||
q = &keyhead;
|
||||
while ((p = *q) != NULL) {
|
||||
if (p->key == key && p->id == id) {
|
||||
*q = p->next;
|
||||
free((void *)p);
|
||||
/* NB This does *not* free p->value! */
|
||||
break;
|
||||
}
|
||||
else
|
||||
q = &p->next;
|
||||
}
|
||||
PyThread_release_lock(keymutex);
|
||||
PyThread_acquire_lock(keymutex, 1);
|
||||
q = &keyhead;
|
||||
while ((p = *q) != NULL) {
|
||||
if (p->key == key && p->id == id) {
|
||||
*q = p->next;
|
||||
free((void *)p);
|
||||
/* NB This does *not* free p->value! */
|
||||
break;
|
||||
}
|
||||
else
|
||||
q = &p->next;
|
||||
}
|
||||
PyThread_release_lock(keymutex);
|
||||
}
|
||||
|
||||
/* Forget everything not associated with the current thread id.
|
||||
|
|
@ -385,27 +385,27 @@ PyThread_delete_key_value(int key)
|
|||
void
|
||||
PyThread_ReInitTLS(void)
|
||||
{
|
||||
long id = PyThread_get_thread_ident();
|
||||
struct key *p, **q;
|
||||
long id = PyThread_get_thread_ident();
|
||||
struct key *p, **q;
|
||||
|
||||
if (!keymutex)
|
||||
return;
|
||||
|
||||
/* As with interpreter_lock in PyEval_ReInitThreads()
|
||||
we just create a new lock without freeing the old one */
|
||||
keymutex = PyThread_allocate_lock();
|
||||
if (!keymutex)
|
||||
return;
|
||||
|
||||
/* Delete all keys which do not match the current thread id */
|
||||
q = &keyhead;
|
||||
while ((p = *q) != NULL) {
|
||||
if (p->id != id) {
|
||||
*q = p->next;
|
||||
free((void *)p);
|
||||
/* NB This does *not* free p->value! */
|
||||
}
|
||||
else
|
||||
q = &p->next;
|
||||
}
|
||||
/* As with interpreter_lock in PyEval_ReInitThreads()
|
||||
we just create a new lock without freeing the old one */
|
||||
keymutex = PyThread_allocate_lock();
|
||||
|
||||
/* Delete all keys which do not match the current thread id */
|
||||
q = &keyhead;
|
||||
while ((p = *q) != NULL) {
|
||||
if (p->id != id) {
|
||||
*q = p->next;
|
||||
free((void *)p);
|
||||
/* NB This does *not* free p->value! */
|
||||
}
|
||||
else
|
||||
q = &p->next;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* Py_HAVE_NATIVE_TLS */
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ static void
|
|||
PyThread__init_thread(void)
|
||||
{
|
||||
#ifndef HURD_C_THREADS
|
||||
/* Roland McGrath said this should not be used since this is
|
||||
done while linking to threads */
|
||||
cthread_init();
|
||||
/* Roland McGrath said this should not be used since this is
|
||||
done while linking to threads */
|
||||
cthread_init();
|
||||
#else
|
||||
/* do nothing */
|
||||
;
|
||||
;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -29,34 +29,34 @@ PyThread__init_thread(void)
|
|||
long
|
||||
PyThread_start_new_thread(void (*func)(void *), void *arg)
|
||||
{
|
||||
int success = 0; /* init not needed when SOLARIS_THREADS and */
|
||||
/* C_THREADS implemented properly */
|
||||
int success = 0; /* init not needed when SOLARIS_THREADS and */
|
||||
/* C_THREADS implemented properly */
|
||||
|
||||
dprintf(("PyThread_start_new_thread called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
/* looks like solaris detaches the thread to never rejoin
|
||||
* so well do it here
|
||||
*/
|
||||
cthread_detach(cthread_fork((cthread_fn_t) func, arg));
|
||||
return success < 0 ? -1 : 0;
|
||||
dprintf(("PyThread_start_new_thread called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
/* looks like solaris detaches the thread to never rejoin
|
||||
* so well do it here
|
||||
*/
|
||||
cthread_detach(cthread_fork((cthread_fn_t) func, arg));
|
||||
return success < 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
long
|
||||
PyThread_get_thread_ident(void)
|
||||
{
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
return (long) cthread_self();
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
return (long) cthread_self();
|
||||
}
|
||||
|
||||
void
|
||||
PyThread_exit_thread(void)
|
||||
{
|
||||
dprintf(("PyThread_exit_thread called\n"));
|
||||
if (!initialized)
|
||||
exit(0);
|
||||
cthread_exit(0);
|
||||
dprintf(("PyThread_exit_thread called\n"));
|
||||
if (!initialized)
|
||||
exit(0);
|
||||
cthread_exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -65,48 +65,48 @@ PyThread_exit_thread(void)
|
|||
PyThread_type_lock
|
||||
PyThread_allocate_lock(void)
|
||||
{
|
||||
mutex_t lock;
|
||||
mutex_t lock;
|
||||
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
lock = mutex_alloc();
|
||||
if (mutex_init(lock)) {
|
||||
perror("mutex_init");
|
||||
free((void *) lock);
|
||||
lock = 0;
|
||||
}
|
||||
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
|
||||
return (PyThread_type_lock) lock;
|
||||
lock = mutex_alloc();
|
||||
if (mutex_init(lock)) {
|
||||
perror("mutex_init");
|
||||
free((void *) lock);
|
||||
lock = 0;
|
||||
}
|
||||
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
|
||||
return (PyThread_type_lock) lock;
|
||||
}
|
||||
|
||||
void
|
||||
PyThread_free_lock(PyThread_type_lock lock)
|
||||
{
|
||||
dprintf(("PyThread_free_lock(%p) called\n", lock));
|
||||
mutex_free(lock);
|
||||
dprintf(("PyThread_free_lock(%p) called\n", lock));
|
||||
mutex_free(lock);
|
||||
}
|
||||
|
||||
int
|
||||
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
|
||||
{
|
||||
int success = FALSE;
|
||||
int success = FALSE;
|
||||
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
|
||||
if (waitflag) { /* blocking */
|
||||
mutex_lock((mutex_t)lock);
|
||||
success = TRUE;
|
||||
} else { /* non blocking */
|
||||
success = mutex_try_lock((mutex_t)lock);
|
||||
}
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
|
||||
return success;
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
|
||||
if (waitflag) { /* blocking */
|
||||
mutex_lock((mutex_t)lock);
|
||||
success = TRUE;
|
||||
} else { /* non blocking */
|
||||
success = mutex_try_lock((mutex_t)lock);
|
||||
}
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
|
||||
return success;
|
||||
}
|
||||
|
||||
void
|
||||
PyThread_release_lock(PyThread_type_lock lock)
|
||||
{
|
||||
dprintf(("PyThread_release_lock(%p) called\n", lock));
|
||||
mutex_unlock((mutex_t )lock);
|
||||
dprintf(("PyThread_release_lock(%p) called\n", lock));
|
||||
mutex_unlock((mutex_t )lock);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,28 +13,28 @@ PyThread__init_thread(void)
|
|||
long
|
||||
PyThread_start_new_thread(void (*func)(void *), void *arg)
|
||||
{
|
||||
int success = 0; /* init not needed when SOLARIS_THREADS and */
|
||||
/* C_THREADS implemented properly */
|
||||
int success = 0; /* init not needed when SOLARIS_THREADS and */
|
||||
/* C_THREADS implemented properly */
|
||||
|
||||
dprintf(("PyThread_start_new_thread called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
return success < 0 ? -1 : 0;
|
||||
dprintf(("PyThread_start_new_thread called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
return success < 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
long
|
||||
PyThread_get_thread_ident(void)
|
||||
{
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
}
|
||||
|
||||
void
|
||||
PyThread_exit_thread(void)
|
||||
{
|
||||
dprintf(("PyThread_exit_thread called\n"));
|
||||
if (!initialized)
|
||||
exit(0);
|
||||
dprintf(("PyThread_exit_thread called\n"));
|
||||
if (!initialized)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -44,32 +44,32 @@ PyThread_type_lock
|
|||
PyThread_allocate_lock(void)
|
||||
{
|
||||
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
|
||||
return (PyThread_type_lock) lock;
|
||||
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
|
||||
return (PyThread_type_lock) lock;
|
||||
}
|
||||
|
||||
void
|
||||
PyThread_free_lock(PyThread_type_lock lock)
|
||||
{
|
||||
dprintf(("PyThread_free_lock(%p) called\n", lock));
|
||||
dprintf(("PyThread_free_lock(%p) called\n", lock));
|
||||
}
|
||||
|
||||
int
|
||||
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
|
||||
{
|
||||
int success;
|
||||
int success;
|
||||
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
|
||||
return success;
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
|
||||
return success;
|
||||
}
|
||||
|
||||
void
|
||||
PyThread_release_lock(PyThread_type_lock lock)
|
||||
{
|
||||
dprintf(("PyThread_release_lock(%p) called\n", lock));
|
||||
dprintf(("PyThread_release_lock(%p) called\n", lock));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@
|
|||
#include <lwp/lwp.h>
|
||||
#include <lwp/stackdep.h>
|
||||
|
||||
#define STACKSIZE 1000 /* stacksize for a thread */
|
||||
#define NSTACKS 2 /* # stacks to be put in cache initially */
|
||||
#define STACKSIZE 1000 /* stacksize for a thread */
|
||||
#define NSTACKS 2 /* # stacks to be put in cache initially */
|
||||
|
||||
struct lock {
|
||||
int lock_locked;
|
||||
cv_t lock_condvar;
|
||||
mon_t lock_monitor;
|
||||
int lock_locked;
|
||||
cv_t lock_condvar;
|
||||
mon_t lock_monitor;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ struct lock {
|
|||
*/
|
||||
static void PyThread__init_thread(void)
|
||||
{
|
||||
lwp_setstkcache(STACKSIZE, NSTACKS);
|
||||
lwp_setstkcache(STACKSIZE, NSTACKS);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -28,31 +28,31 @@ static void PyThread__init_thread(void)
|
|||
|
||||
long PyThread_start_new_thread(void (*func)(void *), void *arg)
|
||||
{
|
||||
thread_t tid;
|
||||
int success;
|
||||
dprintf(("PyThread_start_new_thread called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
success = lwp_create(&tid, func, MINPRIO, 0, lwp_newstk(), 1, arg);
|
||||
return success < 0 ? -1 : 0;
|
||||
thread_t tid;
|
||||
int success;
|
||||
dprintf(("PyThread_start_new_thread called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
success = lwp_create(&tid, func, MINPRIO, 0, lwp_newstk(), 1, arg);
|
||||
return success < 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
long PyThread_get_thread_ident(void)
|
||||
{
|
||||
thread_t tid;
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
if (lwp_self(&tid) < 0)
|
||||
return -1;
|
||||
return tid.thread_id;
|
||||
thread_t tid;
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
if (lwp_self(&tid) < 0)
|
||||
return -1;
|
||||
return tid.thread_id;
|
||||
}
|
||||
|
||||
void PyThread_exit_thread(void)
|
||||
{
|
||||
dprintf(("PyThread_exit_thread called\n"));
|
||||
if (!initialized)
|
||||
exit(0);
|
||||
lwp_destroy(SELF);
|
||||
dprintf(("PyThread_exit_thread called\n"));
|
||||
if (!initialized)
|
||||
exit(0);
|
||||
lwp_destroy(SELF);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -60,54 +60,54 @@ void PyThread_exit_thread(void)
|
|||
*/
|
||||
PyThread_type_lock PyThread_allocate_lock(void)
|
||||
{
|
||||
struct lock *lock;
|
||||
extern char *malloc(size_t);
|
||||
struct lock *lock;
|
||||
extern char *malloc(size_t);
|
||||
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
lock = (struct lock *) malloc(sizeof(struct lock));
|
||||
lock->lock_locked = 0;
|
||||
(void) mon_create(&lock->lock_monitor);
|
||||
(void) cv_create(&lock->lock_condvar, lock->lock_monitor);
|
||||
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
|
||||
return (PyThread_type_lock) lock;
|
||||
lock = (struct lock *) malloc(sizeof(struct lock));
|
||||
lock->lock_locked = 0;
|
||||
(void) mon_create(&lock->lock_monitor);
|
||||
(void) cv_create(&lock->lock_condvar, lock->lock_monitor);
|
||||
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
|
||||
return (PyThread_type_lock) lock;
|
||||
}
|
||||
|
||||
void PyThread_free_lock(PyThread_type_lock lock)
|
||||
{
|
||||
dprintf(("PyThread_free_lock(%p) called\n", lock));
|
||||
mon_destroy(((struct lock *) lock)->lock_monitor);
|
||||
free((char *) lock);
|
||||
dprintf(("PyThread_free_lock(%p) called\n", lock));
|
||||
mon_destroy(((struct lock *) lock)->lock_monitor);
|
||||
free((char *) lock);
|
||||
}
|
||||
|
||||
int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
|
||||
{
|
||||
int success;
|
||||
int success;
|
||||
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
|
||||
success = 0;
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
|
||||
success = 0;
|
||||
|
||||
(void) mon_enter(((struct lock *) lock)->lock_monitor);
|
||||
if (waitflag)
|
||||
while (((struct lock *) lock)->lock_locked)
|
||||
cv_wait(((struct lock *) lock)->lock_condvar);
|
||||
if (!((struct lock *) lock)->lock_locked) {
|
||||
success = 1;
|
||||
((struct lock *) lock)->lock_locked = 1;
|
||||
}
|
||||
cv_broadcast(((struct lock *) lock)->lock_condvar);
|
||||
mon_exit(((struct lock *) lock)->lock_monitor);
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
|
||||
return success;
|
||||
(void) mon_enter(((struct lock *) lock)->lock_monitor);
|
||||
if (waitflag)
|
||||
while (((struct lock *) lock)->lock_locked)
|
||||
cv_wait(((struct lock *) lock)->lock_condvar);
|
||||
if (!((struct lock *) lock)->lock_locked) {
|
||||
success = 1;
|
||||
((struct lock *) lock)->lock_locked = 1;
|
||||
}
|
||||
cv_broadcast(((struct lock *) lock)->lock_condvar);
|
||||
mon_exit(((struct lock *) lock)->lock_monitor);
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
|
||||
return success;
|
||||
}
|
||||
|
||||
void PyThread_release_lock(PyThread_type_lock lock)
|
||||
{
|
||||
dprintf(("PyThread_release_lock(%p) called\n", lock));
|
||||
(void) mon_enter(((struct lock *) lock)->lock_monitor);
|
||||
((struct lock *) lock)->lock_locked = 0;
|
||||
cv_broadcast(((struct lock *) lock)->lock_condvar);
|
||||
mon_exit(((struct lock *) lock)->lock_monitor);
|
||||
dprintf(("PyThread_release_lock(%p) called\n", lock));
|
||||
(void) mon_enter(((struct lock *) lock)->lock_monitor);
|
||||
((struct lock *) lock)->lock_locked = 0;
|
||||
cv_broadcast(((struct lock *) lock)->lock_condvar);
|
||||
mon_exit(((struct lock *) lock)->lock_monitor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,81 +10,81 @@
|
|||
#endif
|
||||
|
||||
typedef struct NRMUTEX {
|
||||
LONG owned ;
|
||||
DWORD thread_id ;
|
||||
HANDLE hevent ;
|
||||
LONG owned ;
|
||||
DWORD thread_id ;
|
||||
HANDLE hevent ;
|
||||
} NRMUTEX, *PNRMUTEX ;
|
||||
|
||||
|
||||
BOOL
|
||||
InitializeNonRecursiveMutex(PNRMUTEX mutex)
|
||||
{
|
||||
mutex->owned = -1 ; /* No threads have entered NonRecursiveMutex */
|
||||
mutex->thread_id = 0 ;
|
||||
mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ;
|
||||
return mutex->hevent != NULL ; /* TRUE if the mutex is created */
|
||||
mutex->owned = -1 ; /* No threads have entered NonRecursiveMutex */
|
||||
mutex->thread_id = 0 ;
|
||||
mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ;
|
||||
return mutex->hevent != NULL ; /* TRUE if the mutex is created */
|
||||
}
|
||||
|
||||
VOID
|
||||
DeleteNonRecursiveMutex(PNRMUTEX mutex)
|
||||
{
|
||||
/* No in-use check */
|
||||
CloseHandle(mutex->hevent) ;
|
||||
mutex->hevent = NULL ; /* Just in case */
|
||||
/* No in-use check */
|
||||
CloseHandle(mutex->hevent) ;
|
||||
mutex->hevent = NULL ; /* Just in case */
|
||||
}
|
||||
|
||||
DWORD
|
||||
EnterNonRecursiveMutex(PNRMUTEX mutex, DWORD milliseconds)
|
||||
{
|
||||
/* Assume that the thread waits successfully */
|
||||
DWORD ret ;
|
||||
/* Assume that the thread waits successfully */
|
||||
DWORD ret ;
|
||||
|
||||
/* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */
|
||||
if (milliseconds == 0)
|
||||
{
|
||||
if (InterlockedCompareExchange(&mutex->owned, 0, -1) != -1)
|
||||
return WAIT_TIMEOUT ;
|
||||
ret = WAIT_OBJECT_0 ;
|
||||
}
|
||||
else
|
||||
ret = InterlockedIncrement(&mutex->owned) ?
|
||||
/* Some thread owns the mutex, let's wait... */
|
||||
WaitForSingleObject(mutex->hevent, milliseconds) : WAIT_OBJECT_0 ;
|
||||
/* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */
|
||||
if (milliseconds == 0)
|
||||
{
|
||||
if (InterlockedCompareExchange(&mutex->owned, 0, -1) != -1)
|
||||
return WAIT_TIMEOUT ;
|
||||
ret = WAIT_OBJECT_0 ;
|
||||
}
|
||||
else
|
||||
ret = InterlockedIncrement(&mutex->owned) ?
|
||||
/* Some thread owns the mutex, let's wait... */
|
||||
WaitForSingleObject(mutex->hevent, milliseconds) : WAIT_OBJECT_0 ;
|
||||
|
||||
mutex->thread_id = GetCurrentThreadId() ; /* We own it */
|
||||
return ret ;
|
||||
mutex->thread_id = GetCurrentThreadId() ; /* We own it */
|
||||
return ret ;
|
||||
}
|
||||
|
||||
BOOL
|
||||
LeaveNonRecursiveMutex(PNRMUTEX mutex)
|
||||
{
|
||||
/* We don't own the mutex */
|
||||
mutex->thread_id = 0 ;
|
||||
return
|
||||
InterlockedDecrement(&mutex->owned) < 0 ||
|
||||
SetEvent(mutex->hevent) ; /* Other threads are waiting, wake one on them up */
|
||||
/* We don't own the mutex */
|
||||
mutex->thread_id = 0 ;
|
||||
return
|
||||
InterlockedDecrement(&mutex->owned) < 0 ||
|
||||
SetEvent(mutex->hevent) ; /* Other threads are waiting, wake one on them up */
|
||||
}
|
||||
|
||||
PNRMUTEX
|
||||
AllocNonRecursiveMutex(void)
|
||||
{
|
||||
PNRMUTEX mutex = (PNRMUTEX)malloc(sizeof(NRMUTEX)) ;
|
||||
if (mutex && !InitializeNonRecursiveMutex(mutex))
|
||||
{
|
||||
free(mutex) ;
|
||||
mutex = NULL ;
|
||||
}
|
||||
return mutex ;
|
||||
PNRMUTEX mutex = (PNRMUTEX)malloc(sizeof(NRMUTEX)) ;
|
||||
if (mutex && !InitializeNonRecursiveMutex(mutex))
|
||||
{
|
||||
free(mutex) ;
|
||||
mutex = NULL ;
|
||||
}
|
||||
return mutex ;
|
||||
}
|
||||
|
||||
void
|
||||
FreeNonRecursiveMutex(PNRMUTEX mutex)
|
||||
{
|
||||
if (mutex)
|
||||
{
|
||||
DeleteNonRecursiveMutex(mutex) ;
|
||||
free(mutex) ;
|
||||
}
|
||||
if (mutex)
|
||||
{
|
||||
DeleteNonRecursiveMutex(mutex) ;
|
||||
free(mutex) ;
|
||||
}
|
||||
}
|
||||
|
||||
long PyThread_get_thread_ident(void);
|
||||
|
|
@ -102,8 +102,8 @@ PyThread__init_thread(void)
|
|||
*/
|
||||
|
||||
typedef struct {
|
||||
void (*func)(void*);
|
||||
void *arg;
|
||||
void (*func)(void*);
|
||||
void *arg;
|
||||
} callobj;
|
||||
|
||||
/* thunker to call adapt between the function type used by the system's
|
||||
|
|
@ -115,66 +115,66 @@ static unsigned __stdcall
|
|||
#endif
|
||||
bootstrap(void *call)
|
||||
{
|
||||
callobj *obj = (callobj*)call;
|
||||
void (*func)(void*) = obj->func;
|
||||
void *arg = obj->arg;
|
||||
HeapFree(GetProcessHeap(), 0, obj);
|
||||
func(arg);
|
||||
return 0;
|
||||
callobj *obj = (callobj*)call;
|
||||
void (*func)(void*) = obj->func;
|
||||
void *arg = obj->arg;
|
||||
HeapFree(GetProcessHeap(), 0, obj);
|
||||
func(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
PyThread_start_new_thread(void (*func)(void *), void *arg)
|
||||
{
|
||||
HANDLE hThread;
|
||||
unsigned threadID;
|
||||
callobj *obj;
|
||||
|
||||
dprintf(("%ld: PyThread_start_new_thread called\n",
|
||||
PyThread_get_thread_ident()));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
HANDLE hThread;
|
||||
unsigned threadID;
|
||||
callobj *obj;
|
||||
|
||||
obj = (callobj*)HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
|
||||
if (!obj)
|
||||
return -1;
|
||||
obj->func = func;
|
||||
obj->arg = arg;
|
||||
dprintf(("%ld: PyThread_start_new_thread called\n",
|
||||
PyThread_get_thread_ident()));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
obj = (callobj*)HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
|
||||
if (!obj)
|
||||
return -1;
|
||||
obj->func = func;
|
||||
obj->arg = arg;
|
||||
#if defined(MS_WINCE)
|
||||
hThread = CreateThread(NULL,
|
||||
Py_SAFE_DOWNCAST(_pythread_stacksize, Py_ssize_t, SIZE_T),
|
||||
bootstrap, obj, 0, &threadID);
|
||||
hThread = CreateThread(NULL,
|
||||
Py_SAFE_DOWNCAST(_pythread_stacksize, Py_ssize_t, SIZE_T),
|
||||
bootstrap, obj, 0, &threadID);
|
||||
#else
|
||||
hThread = (HANDLE)_beginthreadex(0,
|
||||
Py_SAFE_DOWNCAST(_pythread_stacksize,
|
||||
Py_ssize_t, unsigned int),
|
||||
bootstrap, obj,
|
||||
0, &threadID);
|
||||
hThread = (HANDLE)_beginthreadex(0,
|
||||
Py_SAFE_DOWNCAST(_pythread_stacksize,
|
||||
Py_ssize_t, unsigned int),
|
||||
bootstrap, obj,
|
||||
0, &threadID);
|
||||
#endif
|
||||
if (hThread == 0) {
|
||||
if (hThread == 0) {
|
||||
#if defined(MS_WINCE)
|
||||
/* Save error in variable, to prevent PyThread_get_thread_ident
|
||||
from clobbering it. */
|
||||
unsigned e = GetLastError();
|
||||
dprintf(("%ld: PyThread_start_new_thread failed, win32 error code %u\n",
|
||||
PyThread_get_thread_ident(), e));
|
||||
/* Save error in variable, to prevent PyThread_get_thread_ident
|
||||
from clobbering it. */
|
||||
unsigned e = GetLastError();
|
||||
dprintf(("%ld: PyThread_start_new_thread failed, win32 error code %u\n",
|
||||
PyThread_get_thread_ident(), e));
|
||||
#else
|
||||
/* I've seen errno == EAGAIN here, which means "there are
|
||||
* too many threads".
|
||||
*/
|
||||
int e = errno;
|
||||
dprintf(("%ld: PyThread_start_new_thread failed, errno %d\n",
|
||||
PyThread_get_thread_ident(), e));
|
||||
/* I've seen errno == EAGAIN here, which means "there are
|
||||
* too many threads".
|
||||
*/
|
||||
int e = errno;
|
||||
dprintf(("%ld: PyThread_start_new_thread failed, errno %d\n",
|
||||
PyThread_get_thread_ident(), e));
|
||||
#endif
|
||||
threadID = (unsigned)-1;
|
||||
HeapFree(GetProcessHeap(), 0, obj);
|
||||
}
|
||||
else {
|
||||
dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n",
|
||||
PyThread_get_thread_ident(), (void*)hThread));
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
return (long) threadID;
|
||||
threadID = (unsigned)-1;
|
||||
HeapFree(GetProcessHeap(), 0, obj);
|
||||
}
|
||||
else {
|
||||
dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n",
|
||||
PyThread_get_thread_ident(), (void*)hThread));
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
return (long) threadID;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -184,22 +184,22 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
|
|||
long
|
||||
PyThread_get_thread_ident(void)
|
||||
{
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
return GetCurrentThreadId();
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
|
||||
void
|
||||
PyThread_exit_thread(void)
|
||||
{
|
||||
dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident()));
|
||||
if (!initialized)
|
||||
exit(0);
|
||||
dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident()));
|
||||
if (!initialized)
|
||||
exit(0);
|
||||
#if defined(MS_WINCE)
|
||||
ExitThread(0);
|
||||
ExitThread(0);
|
||||
#else
|
||||
_endthreadex(0);
|
||||
_endthreadex(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -211,25 +211,25 @@ PyThread_exit_thread(void)
|
|||
PyThread_type_lock
|
||||
PyThread_allocate_lock(void)
|
||||
{
|
||||
PNRMUTEX aLock;
|
||||
PNRMUTEX aLock;
|
||||
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
aLock = AllocNonRecursiveMutex() ;
|
||||
aLock = AllocNonRecursiveMutex() ;
|
||||
|
||||
dprintf(("%ld: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock));
|
||||
dprintf(("%ld: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock));
|
||||
|
||||
return (PyThread_type_lock) aLock;
|
||||
return (PyThread_type_lock) aLock;
|
||||
}
|
||||
|
||||
void
|
||||
PyThread_free_lock(PyThread_type_lock aLock)
|
||||
{
|
||||
dprintf(("%ld: PyThread_free_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
|
||||
dprintf(("%ld: PyThread_free_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
|
||||
|
||||
FreeNonRecursiveMutex(aLock) ;
|
||||
FreeNonRecursiveMutex(aLock) ;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -241,48 +241,48 @@ PyThread_free_lock(PyThread_type_lock aLock)
|
|||
int
|
||||
PyThread_acquire_lock_timed(PyThread_type_lock aLock, PY_TIMEOUT_T microseconds)
|
||||
{
|
||||
int success ;
|
||||
PY_TIMEOUT_T milliseconds;
|
||||
int success ;
|
||||
PY_TIMEOUT_T milliseconds;
|
||||
|
||||
if (microseconds >= 0) {
|
||||
milliseconds = microseconds / 1000;
|
||||
if (microseconds % 1000 > 0)
|
||||
++milliseconds;
|
||||
if ((DWORD) milliseconds != milliseconds)
|
||||
Py_FatalError("Timeout too large for a DWORD, "
|
||||
"please check PY_TIMEOUT_MAX");
|
||||
}
|
||||
else
|
||||
milliseconds = INFINITE;
|
||||
if (microseconds >= 0) {
|
||||
milliseconds = microseconds / 1000;
|
||||
if (microseconds % 1000 > 0)
|
||||
++milliseconds;
|
||||
if ((DWORD) milliseconds != milliseconds)
|
||||
Py_FatalError("Timeout too large for a DWORD, "
|
||||
"please check PY_TIMEOUT_MAX");
|
||||
}
|
||||
else
|
||||
milliseconds = INFINITE;
|
||||
|
||||
dprintf(("%ld: PyThread_acquire_lock_timed(%p, %lld) called\n",
|
||||
PyThread_get_thread_ident(), aLock, microseconds));
|
||||
dprintf(("%ld: PyThread_acquire_lock_timed(%p, %lld) called\n",
|
||||
PyThread_get_thread_ident(), aLock, microseconds));
|
||||
|
||||
success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (DWORD) milliseconds) == WAIT_OBJECT_0 ;
|
||||
success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (DWORD) milliseconds) == WAIT_OBJECT_0 ;
|
||||
|
||||
dprintf(("%ld: PyThread_acquire_lock(%p, %lld) -> %d\n",
|
||||
PyThread_get_thread_ident(), aLock, microseconds, success));
|
||||
dprintf(("%ld: PyThread_acquire_lock(%p, %lld) -> %d\n",
|
||||
PyThread_get_thread_ident(), aLock, microseconds, success));
|
||||
|
||||
return success;
|
||||
return success;
|
||||
}
|
||||
int
|
||||
PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
|
||||
{
|
||||
return PyThread_acquire_lock_timed(aLock, waitflag ? -1 : 0);
|
||||
return PyThread_acquire_lock_timed(aLock, waitflag ? -1 : 0);
|
||||
}
|
||||
|
||||
void
|
||||
PyThread_release_lock(PyThread_type_lock aLock)
|
||||
{
|
||||
dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
|
||||
dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
|
||||
|
||||
if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock)))
|
||||
dprintf(("%ld: Could not PyThread_release_lock(%p) error: %ld\n", PyThread_get_thread_ident(), aLock, GetLastError()));
|
||||
if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock)))
|
||||
dprintf(("%ld: Could not PyThread_release_lock(%p) error: %ld\n", PyThread_get_thread_ident(), aLock, GetLastError()));
|
||||
}
|
||||
|
||||
/* minimum/maximum thread stack sizes supported */
|
||||
#define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */
|
||||
#define THREAD_MAX_STACKSIZE 0x10000000 /* 256MB */
|
||||
#define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */
|
||||
#define THREAD_MAX_STACKSIZE 0x10000000 /* 256MB */
|
||||
|
||||
/* set the thread stack size.
|
||||
* Return 0 if size is valid, -1 otherwise.
|
||||
|
|
@ -290,22 +290,22 @@ PyThread_release_lock(PyThread_type_lock aLock)
|
|||
static int
|
||||
_pythread_nt_set_stacksize(size_t size)
|
||||
{
|
||||
/* set to default */
|
||||
if (size == 0) {
|
||||
_pythread_stacksize = 0;
|
||||
return 0;
|
||||
}
|
||||
/* set to default */
|
||||
if (size == 0) {
|
||||
_pythread_stacksize = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* valid range? */
|
||||
if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {
|
||||
_pythread_stacksize = size;
|
||||
return 0;
|
||||
}
|
||||
/* valid range? */
|
||||
if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {
|
||||
_pythread_stacksize = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define THREAD_SET_STACKSIZE(x) _pythread_nt_set_stacksize(x)
|
||||
#define THREAD_SET_STACKSIZE(x) _pythread_nt_set_stacksize(x)
|
||||
|
||||
|
||||
/* use native Windows TLS functions */
|
||||
|
|
@ -315,13 +315,13 @@ _pythread_nt_set_stacksize(size_t size)
|
|||
int
|
||||
PyThread_create_key(void)
|
||||
{
|
||||
return (int) TlsAlloc();
|
||||
return (int) TlsAlloc();
|
||||
}
|
||||
|
||||
void
|
||||
PyThread_delete_key(int key)
|
||||
{
|
||||
TlsFree(key);
|
||||
TlsFree(key);
|
||||
}
|
||||
|
||||
/* We must be careful to emulate the strange semantics implemented in thread.c,
|
||||
|
|
@ -330,42 +330,42 @@ PyThread_delete_key(int key)
|
|||
int
|
||||
PyThread_set_key_value(int key, void *value)
|
||||
{
|
||||
BOOL ok;
|
||||
void *oldvalue;
|
||||
BOOL ok;
|
||||
void *oldvalue;
|
||||
|
||||
assert(value != NULL);
|
||||
oldvalue = TlsGetValue(key);
|
||||
if (oldvalue != NULL)
|
||||
/* ignore value if already set */
|
||||
return 0;
|
||||
ok = TlsSetValue(key, value);
|
||||
if (!ok)
|
||||
return -1;
|
||||
return 0;
|
||||
assert(value != NULL);
|
||||
oldvalue = TlsGetValue(key);
|
||||
if (oldvalue != NULL)
|
||||
/* ignore value if already set */
|
||||
return 0;
|
||||
ok = TlsSetValue(key, value);
|
||||
if (!ok)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *
|
||||
PyThread_get_key_value(int key)
|
||||
{
|
||||
/* because TLS is used in the Py_END_ALLOW_THREAD macro,
|
||||
* it is necessary to preserve the windows error state, because
|
||||
* it is assumed to be preserved across the call to the macro.
|
||||
* Ideally, the macro should be fixed, but it is simpler to
|
||||
* do it here.
|
||||
*/
|
||||
DWORD error = GetLastError();
|
||||
void *result = TlsGetValue(key);
|
||||
SetLastError(error);
|
||||
return result;
|
||||
/* because TLS is used in the Py_END_ALLOW_THREAD macro,
|
||||
* it is necessary to preserve the windows error state, because
|
||||
* it is assumed to be preserved across the call to the macro.
|
||||
* Ideally, the macro should be fixed, but it is simpler to
|
||||
* do it here.
|
||||
*/
|
||||
DWORD error = GetLastError();
|
||||
void *result = TlsGetValue(key);
|
||||
SetLastError(error);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
PyThread_delete_key_value(int key)
|
||||
{
|
||||
/* NULL is used as "key missing", and it is also the default
|
||||
* given by TlsGetValue() if nothing has been set yet.
|
||||
*/
|
||||
TlsSetValue(key, NULL);
|
||||
/* NULL is used as "key missing", and it is also the default
|
||||
* given by TlsGetValue() if nothing has been set yet.
|
||||
*/
|
||||
TlsSetValue(key, NULL);
|
||||
}
|
||||
|
||||
/* reinitialization of TLS is not necessary after fork when using
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@ long PyThread_get_thread_ident(void);
|
|||
|
||||
/* default thread stack size of 64kB */
|
||||
#if !defined(THREAD_STACK_SIZE)
|
||||
#define THREAD_STACK_SIZE 0x10000
|
||||
#define THREAD_STACK_SIZE 0x10000
|
||||
#endif
|
||||
|
||||
#define OS2_STACKSIZE(x) (x ? x : THREAD_STACK_SIZE)
|
||||
#define OS2_STACKSIZE(x) (x ? x : THREAD_STACK_SIZE)
|
||||
|
||||
/*
|
||||
* Initialization of the C package, should not be needed.
|
||||
|
|
@ -35,113 +35,113 @@ PyThread__init_thread(void)
|
|||
long
|
||||
PyThread_start_new_thread(void (*func)(void *), void *arg)
|
||||
{
|
||||
int thread_id;
|
||||
int thread_id;
|
||||
|
||||
thread_id = _beginthread(func,
|
||||
NULL,
|
||||
OS2_STACKSIZE(_pythread_stacksize),
|
||||
arg);
|
||||
thread_id = _beginthread(func,
|
||||
NULL,
|
||||
OS2_STACKSIZE(_pythread_stacksize),
|
||||
arg);
|
||||
|
||||
if (thread_id == -1) {
|
||||
dprintf(("_beginthread failed. return %ld\n", errno));
|
||||
}
|
||||
if (thread_id == -1) {
|
||||
dprintf(("_beginthread failed. return %ld\n", errno));
|
||||
}
|
||||
|
||||
return thread_id;
|
||||
return thread_id;
|
||||
}
|
||||
|
||||
long
|
||||
PyThread_get_thread_ident(void)
|
||||
{
|
||||
#if !defined(PYCC_GCC)
|
||||
PPIB pib;
|
||||
PTIB tib;
|
||||
PPIB pib;
|
||||
PTIB tib;
|
||||
#endif
|
||||
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
#if defined(PYCC_GCC)
|
||||
return _gettid();
|
||||
return _gettid();
|
||||
#else
|
||||
DosGetInfoBlocks(&tib, &pib);
|
||||
return tib->tib_ptib2->tib2_ultid;
|
||||
DosGetInfoBlocks(&tib, &pib);
|
||||
return tib->tib_ptib2->tib2_ultid;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
PyThread_exit_thread(void)
|
||||
{
|
||||
dprintf(("%ld: PyThread_exit_thread called\n",
|
||||
PyThread_get_thread_ident()));
|
||||
if (!initialized)
|
||||
exit(0);
|
||||
_endthread();
|
||||
dprintf(("%ld: PyThread_exit_thread called\n",
|
||||
PyThread_get_thread_ident()));
|
||||
if (!initialized)
|
||||
exit(0);
|
||||
_endthread();
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock support. This is implemented with an event semaphore and critical
|
||||
* sections to make it behave more like a posix mutex than its OS/2
|
||||
* sections to make it behave more like a posix mutex than its OS/2
|
||||
* counterparts.
|
||||
*/
|
||||
|
||||
typedef struct os2_lock_t {
|
||||
int is_set;
|
||||
HEV changed;
|
||||
int is_set;
|
||||
HEV changed;
|
||||
} *type_os2_lock;
|
||||
|
||||
PyThread_type_lock
|
||||
PyThread_type_lock
|
||||
PyThread_allocate_lock(void)
|
||||
{
|
||||
#if defined(PYCC_GCC)
|
||||
_fmutex *sem = malloc(sizeof(_fmutex));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
dprintf(("%ld: PyThread_allocate_lock() -> %lx\n",
|
||||
PyThread_get_thread_ident(),
|
||||
(long)sem));
|
||||
if (_fmutex_create(sem, 0)) {
|
||||
free(sem);
|
||||
sem = NULL;
|
||||
}
|
||||
return (PyThread_type_lock)sem;
|
||||
_fmutex *sem = malloc(sizeof(_fmutex));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
dprintf(("%ld: PyThread_allocate_lock() -> %lx\n",
|
||||
PyThread_get_thread_ident(),
|
||||
(long)sem));
|
||||
if (_fmutex_create(sem, 0)) {
|
||||
free(sem);
|
||||
sem = NULL;
|
||||
}
|
||||
return (PyThread_type_lock)sem;
|
||||
#else
|
||||
APIRET rc;
|
||||
type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t));
|
||||
APIRET rc;
|
||||
type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t));
|
||||
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
lock->is_set = 0;
|
||||
lock->is_set = 0;
|
||||
|
||||
DosCreateEventSem(NULL, &lock->changed, 0, 0);
|
||||
DosCreateEventSem(NULL, &lock->changed, 0, 0);
|
||||
|
||||
dprintf(("%ld: PyThread_allocate_lock() -> %p\n",
|
||||
PyThread_get_thread_ident(),
|
||||
lock->changed));
|
||||
dprintf(("%ld: PyThread_allocate_lock() -> %p\n",
|
||||
PyThread_get_thread_ident(),
|
||||
lock->changed));
|
||||
|
||||
return (PyThread_type_lock)lock;
|
||||
return (PyThread_type_lock)lock;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
PyThread_free_lock(PyThread_type_lock aLock)
|
||||
{
|
||||
#if !defined(PYCC_GCC)
|
||||
type_os2_lock lock = (type_os2_lock)aLock;
|
||||
type_os2_lock lock = (type_os2_lock)aLock;
|
||||
#endif
|
||||
|
||||
dprintf(("%ld: PyThread_free_lock(%p) called\n",
|
||||
PyThread_get_thread_ident(),aLock));
|
||||
dprintf(("%ld: PyThread_free_lock(%p) called\n",
|
||||
PyThread_get_thread_ident(),aLock));
|
||||
|
||||
#if defined(PYCC_GCC)
|
||||
if (aLock) {
|
||||
_fmutex_close((_fmutex *)aLock);
|
||||
free((_fmutex *)aLock);
|
||||
}
|
||||
if (aLock) {
|
||||
_fmutex_close((_fmutex *)aLock);
|
||||
free((_fmutex *)aLock);
|
||||
}
|
||||
#else
|
||||
DosCloseEventSem(lock->changed);
|
||||
free(aLock);
|
||||
DosCloseEventSem(lock->changed);
|
||||
free(aLock);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -150,98 +150,98 @@ PyThread_free_lock(PyThread_type_lock aLock)
|
|||
*
|
||||
* and 0 if the lock was not acquired.
|
||||
*/
|
||||
int
|
||||
int
|
||||
PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
|
||||
{
|
||||
#if !defined(PYCC_GCC)
|
||||
int done = 0;
|
||||
ULONG count;
|
||||
PID pid = 0;
|
||||
TID tid = 0;
|
||||
type_os2_lock lock = (type_os2_lock)aLock;
|
||||
int done = 0;
|
||||
ULONG count;
|
||||
PID pid = 0;
|
||||
TID tid = 0;
|
||||
type_os2_lock lock = (type_os2_lock)aLock;
|
||||
#endif
|
||||
|
||||
dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n",
|
||||
PyThread_get_thread_ident(),
|
||||
aLock,
|
||||
waitflag));
|
||||
dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n",
|
||||
PyThread_get_thread_ident(),
|
||||
aLock,
|
||||
waitflag));
|
||||
|
||||
#if defined(PYCC_GCC)
|
||||
/* always successful if the lock doesn't exist */
|
||||
if (aLock &&
|
||||
_fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT))
|
||||
return 0;
|
||||
/* always successful if the lock doesn't exist */
|
||||
if (aLock &&
|
||||
_fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT))
|
||||
return 0;
|
||||
#else
|
||||
while (!done) {
|
||||
/* if the lock is currently set, we have to wait for
|
||||
* the state to change
|
||||
*/
|
||||
if (lock->is_set) {
|
||||
if (!waitflag)
|
||||
return 0;
|
||||
DosWaitEventSem(lock->changed, SEM_INDEFINITE_WAIT);
|
||||
}
|
||||
while (!done) {
|
||||
/* if the lock is currently set, we have to wait for
|
||||
* the state to change
|
||||
*/
|
||||
if (lock->is_set) {
|
||||
if (!waitflag)
|
||||
return 0;
|
||||
DosWaitEventSem(lock->changed, SEM_INDEFINITE_WAIT);
|
||||
}
|
||||
|
||||
/* enter a critical section and try to get the semaphore. If
|
||||
* it is still locked, we will try again.
|
||||
*/
|
||||
if (DosEnterCritSec())
|
||||
return 0;
|
||||
/* enter a critical section and try to get the semaphore. If
|
||||
* it is still locked, we will try again.
|
||||
*/
|
||||
if (DosEnterCritSec())
|
||||
return 0;
|
||||
|
||||
if (!lock->is_set) {
|
||||
lock->is_set = 1;
|
||||
DosResetEventSem(lock->changed, &count);
|
||||
done = 1;
|
||||
}
|
||||
if (!lock->is_set) {
|
||||
lock->is_set = 1;
|
||||
DosResetEventSem(lock->changed, &count);
|
||||
done = 1;
|
||||
}
|
||||
|
||||
DosExitCritSec();
|
||||
}
|
||||
DosExitCritSec();
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
PyThread_release_lock(PyThread_type_lock aLock)
|
||||
{
|
||||
#if !defined(PYCC_GCC)
|
||||
type_os2_lock lock = (type_os2_lock)aLock;
|
||||
type_os2_lock lock = (type_os2_lock)aLock;
|
||||
#endif
|
||||
|
||||
dprintf(("%ld: PyThread_release_lock(%p) called\n",
|
||||
PyThread_get_thread_ident(),
|
||||
aLock));
|
||||
dprintf(("%ld: PyThread_release_lock(%p) called\n",
|
||||
PyThread_get_thread_ident(),
|
||||
aLock));
|
||||
|
||||
#if defined(PYCC_GCC)
|
||||
if (aLock)
|
||||
_fmutex_release((_fmutex *)aLock);
|
||||
if (aLock)
|
||||
_fmutex_release((_fmutex *)aLock);
|
||||
#else
|
||||
if (!lock->is_set) {
|
||||
dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
|
||||
PyThread_get_thread_ident(),
|
||||
aLock,
|
||||
GetLastError()));
|
||||
return;
|
||||
}
|
||||
if (!lock->is_set) {
|
||||
dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
|
||||
PyThread_get_thread_ident(),
|
||||
aLock,
|
||||
GetLastError()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (DosEnterCritSec()) {
|
||||
dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
|
||||
PyThread_get_thread_ident(),
|
||||
aLock,
|
||||
GetLastError()));
|
||||
return;
|
||||
}
|
||||
if (DosEnterCritSec()) {
|
||||
dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
|
||||
PyThread_get_thread_ident(),
|
||||
aLock,
|
||||
GetLastError()));
|
||||
return;
|
||||
}
|
||||
|
||||
lock->is_set = 0;
|
||||
DosPostEventSem(lock->changed);
|
||||
lock->is_set = 0;
|
||||
DosPostEventSem(lock->changed);
|
||||
|
||||
DosExitCritSec();
|
||||
DosExitCritSec();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* minimum/maximum thread stack sizes supported */
|
||||
#define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */
|
||||
#define THREAD_MAX_STACKSIZE 0x2000000 /* 32MB */
|
||||
#define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */
|
||||
#define THREAD_MAX_STACKSIZE 0x2000000 /* 32MB */
|
||||
|
||||
/* set the thread stack size.
|
||||
* Return 0 if size is valid, -1 otherwise.
|
||||
|
|
@ -249,19 +249,19 @@ PyThread_release_lock(PyThread_type_lock aLock)
|
|||
static int
|
||||
_pythread_os2_set_stacksize(size_t size)
|
||||
{
|
||||
/* set to default */
|
||||
if (size == 0) {
|
||||
_pythread_stacksize = 0;
|
||||
return 0;
|
||||
}
|
||||
/* set to default */
|
||||
if (size == 0) {
|
||||
_pythread_stacksize = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* valid range? */
|
||||
if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {
|
||||
_pythread_stacksize = size;
|
||||
return 0;
|
||||
}
|
||||
/* valid range? */
|
||||
if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {
|
||||
_pythread_stacksize = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define THREAD_SET_STACKSIZE(x) _pythread_os2_set_stacksize(x)
|
||||
#define THREAD_SET_STACKSIZE(x) _pythread_os2_set_stacksize(x)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
http://www.gnu.org/software/pth
|
||||
2000-05-03 Andy Dustman <andy@dustman.net>
|
||||
|
||||
Adapted from Posix threads interface
|
||||
Adapted from Posix threads interface
|
||||
12 May 1997 -- david arnold <davida@pobox.com>
|
||||
*/
|
||||
|
||||
|
|
@ -22,10 +22,10 @@
|
|||
*/
|
||||
|
||||
typedef struct {
|
||||
char locked; /* 0=unlocked, 1=locked */
|
||||
/* a <cond, mutex> pair to handle an acquire of a locked lock */
|
||||
pth_cond_t lock_released;
|
||||
pth_mutex_t mut;
|
||||
char locked; /* 0=unlocked, 1=locked */
|
||||
/* a <cond, mutex> pair to handle an acquire of a locked lock */
|
||||
pth_cond_t lock_released;
|
||||
pth_mutex_t mut;
|
||||
} pth_lock;
|
||||
|
||||
#define CHECK_STATUS(name) if (status == -1) { printf("%d ", status); perror(name); error = 1; }
|
||||
|
|
@ -38,10 +38,10 @@ pth_attr_t PyThread_attr;
|
|||
|
||||
static void PyThread__init_thread(void)
|
||||
{
|
||||
pth_init();
|
||||
PyThread_attr = pth_attr_new();
|
||||
pth_attr_set(PyThread_attr, PTH_ATTR_STACK_SIZE, 1<<18);
|
||||
pth_attr_set(PyThread_attr, PTH_ATTR_JOINABLE, FALSE);
|
||||
pth_init();
|
||||
PyThread_attr = pth_attr_new();
|
||||
pth_attr_set(PyThread_attr, PTH_ATTR_STACK_SIZE, 1<<18);
|
||||
pth_attr_set(PyThread_attr, PTH_ATTR_JOINABLE, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -51,35 +51,35 @@ static void PyThread__init_thread(void)
|
|||
|
||||
long PyThread_start_new_thread(void (*func)(void *), void *arg)
|
||||
{
|
||||
pth_t th;
|
||||
dprintf(("PyThread_start_new_thread called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
pth_t th;
|
||||
dprintf(("PyThread_start_new_thread called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
th = pth_spawn(PyThread_attr,
|
||||
(void* (*)(void *))func,
|
||||
(void *)arg
|
||||
);
|
||||
th = pth_spawn(PyThread_attr,
|
||||
(void* (*)(void *))func,
|
||||
(void *)arg
|
||||
);
|
||||
|
||||
return th;
|
||||
return th;
|
||||
}
|
||||
|
||||
long PyThread_get_thread_ident(void)
|
||||
{
|
||||
volatile pth_t threadid;
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
/* Jump through some hoops for Alpha OSF/1 */
|
||||
threadid = pth_self();
|
||||
return (long) *(long *) &threadid;
|
||||
volatile pth_t threadid;
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
/* Jump through some hoops for Alpha OSF/1 */
|
||||
threadid = pth_self();
|
||||
return (long) *(long *) &threadid;
|
||||
}
|
||||
|
||||
void PyThread_exit_thread(void)
|
||||
{
|
||||
dprintf(("PyThread_exit_thread called\n"));
|
||||
if (!initialized) {
|
||||
exit(0);
|
||||
}
|
||||
dprintf(("PyThread_exit_thread called\n"));
|
||||
if (!initialized) {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -87,92 +87,92 @@ void PyThread_exit_thread(void)
|
|||
*/
|
||||
PyThread_type_lock PyThread_allocate_lock(void)
|
||||
{
|
||||
pth_lock *lock;
|
||||
int status, error = 0;
|
||||
pth_lock *lock;
|
||||
int status, error = 0;
|
||||
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
lock = (pth_lock *) malloc(sizeof(pth_lock));
|
||||
memset((void *)lock, '\0', sizeof(pth_lock));
|
||||
if (lock) {
|
||||
lock->locked = 0;
|
||||
status = pth_mutex_init(&lock->mut);
|
||||
CHECK_STATUS("pth_mutex_init");
|
||||
status = pth_cond_init(&lock->lock_released);
|
||||
CHECK_STATUS("pth_cond_init");
|
||||
if (error) {
|
||||
free((void *)lock);
|
||||
lock = NULL;
|
||||
}
|
||||
}
|
||||
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
|
||||
return (PyThread_type_lock) lock;
|
||||
lock = (pth_lock *) malloc(sizeof(pth_lock));
|
||||
memset((void *)lock, '\0', sizeof(pth_lock));
|
||||
if (lock) {
|
||||
lock->locked = 0;
|
||||
status = pth_mutex_init(&lock->mut);
|
||||
CHECK_STATUS("pth_mutex_init");
|
||||
status = pth_cond_init(&lock->lock_released);
|
||||
CHECK_STATUS("pth_cond_init");
|
||||
if (error) {
|
||||
free((void *)lock);
|
||||
lock = NULL;
|
||||
}
|
||||
}
|
||||
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
|
||||
return (PyThread_type_lock) lock;
|
||||
}
|
||||
|
||||
void PyThread_free_lock(PyThread_type_lock lock)
|
||||
{
|
||||
pth_lock *thelock = (pth_lock *)lock;
|
||||
pth_lock *thelock = (pth_lock *)lock;
|
||||
|
||||
dprintf(("PyThread_free_lock(%p) called\n", lock));
|
||||
dprintf(("PyThread_free_lock(%p) called\n", lock));
|
||||
|
||||
free((void *)thelock);
|
||||
free((void *)thelock);
|
||||
}
|
||||
|
||||
int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
|
||||
{
|
||||
int success;
|
||||
pth_lock *thelock = (pth_lock *)lock;
|
||||
int status, error = 0;
|
||||
int success;
|
||||
pth_lock *thelock = (pth_lock *)lock;
|
||||
int status, error = 0;
|
||||
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
|
||||
|
||||
status = pth_mutex_acquire(&thelock->mut, !waitflag, NULL);
|
||||
CHECK_STATUS("pth_mutex_acquire[1]");
|
||||
success = thelock->locked == 0;
|
||||
if (success) thelock->locked = 1;
|
||||
status = pth_mutex_release( &thelock->mut );
|
||||
CHECK_STATUS("pth_mutex_release[1]");
|
||||
status = pth_mutex_acquire(&thelock->mut, !waitflag, NULL);
|
||||
CHECK_STATUS("pth_mutex_acquire[1]");
|
||||
success = thelock->locked == 0;
|
||||
if (success) thelock->locked = 1;
|
||||
status = pth_mutex_release( &thelock->mut );
|
||||
CHECK_STATUS("pth_mutex_release[1]");
|
||||
|
||||
if ( !success && waitflag ) {
|
||||
/* continue trying until we get the lock */
|
||||
if ( !success && waitflag ) {
|
||||
/* continue trying until we get the lock */
|
||||
|
||||
/* mut must be locked by me -- part of the condition
|
||||
* protocol */
|
||||
status = pth_mutex_acquire( &thelock->mut, !waitflag, NULL );
|
||||
CHECK_STATUS("pth_mutex_acquire[2]");
|
||||
while ( thelock->locked ) {
|
||||
status = pth_cond_await(&thelock->lock_released,
|
||||
&thelock->mut, NULL);
|
||||
CHECK_STATUS("pth_cond_await");
|
||||
}
|
||||
thelock->locked = 1;
|
||||
status = pth_mutex_release( &thelock->mut );
|
||||
CHECK_STATUS("pth_mutex_release[2]");
|
||||
success = 1;
|
||||
/* mut must be locked by me -- part of the condition
|
||||
* protocol */
|
||||
status = pth_mutex_acquire( &thelock->mut, !waitflag, NULL );
|
||||
CHECK_STATUS("pth_mutex_acquire[2]");
|
||||
while ( thelock->locked ) {
|
||||
status = pth_cond_await(&thelock->lock_released,
|
||||
&thelock->mut, NULL);
|
||||
CHECK_STATUS("pth_cond_await");
|
||||
}
|
||||
if (error) success = 0;
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
|
||||
return success;
|
||||
thelock->locked = 1;
|
||||
status = pth_mutex_release( &thelock->mut );
|
||||
CHECK_STATUS("pth_mutex_release[2]");
|
||||
success = 1;
|
||||
}
|
||||
if (error) success = 0;
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
|
||||
return success;
|
||||
}
|
||||
|
||||
void PyThread_release_lock(PyThread_type_lock lock)
|
||||
{
|
||||
pth_lock *thelock = (pth_lock *)lock;
|
||||
int status, error = 0;
|
||||
pth_lock *thelock = (pth_lock *)lock;
|
||||
int status, error = 0;
|
||||
|
||||
dprintf(("PyThread_release_lock(%p) called\n", lock));
|
||||
dprintf(("PyThread_release_lock(%p) called\n", lock));
|
||||
|
||||
status = pth_mutex_acquire( &thelock->mut, 0, NULL );
|
||||
CHECK_STATUS("pth_mutex_acquire[3]");
|
||||
status = pth_mutex_acquire( &thelock->mut, 0, NULL );
|
||||
CHECK_STATUS("pth_mutex_acquire[3]");
|
||||
|
||||
thelock->locked = 0;
|
||||
thelock->locked = 0;
|
||||
|
||||
status = pth_mutex_release( &thelock->mut );
|
||||
CHECK_STATUS("pth_mutex_release[3]");
|
||||
status = pth_mutex_release( &thelock->mut );
|
||||
CHECK_STATUS("pth_mutex_release[3]");
|
||||
|
||||
/* wake up someone (anyone, if any) waiting on the lock */
|
||||
status = pth_cond_notify( &thelock->lock_released, 0 );
|
||||
CHECK_STATUS("pth_cond_notify");
|
||||
/* wake up someone (anyone, if any) waiting on the lock */
|
||||
status = pth_cond_notify( &thelock->lock_released, 0 );
|
||||
CHECK_STATUS("pth_cond_notify");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@
|
|||
be conditional on _POSIX_THREAD_ATTR_STACKSIZE being defined. */
|
||||
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
|
||||
#ifndef THREAD_STACK_SIZE
|
||||
#define THREAD_STACK_SIZE 0 /* use default stack size */
|
||||
#define THREAD_STACK_SIZE 0 /* use default stack size */
|
||||
#endif
|
||||
/* for safety, ensure a viable minimum stacksize */
|
||||
#define THREAD_STACK_MIN 0x8000 /* 32kB */
|
||||
#define THREAD_STACK_MIN 0x8000 /* 32kB */
|
||||
#else /* !_POSIX_THREAD_ATTR_STACKSIZE */
|
||||
#ifdef THREAD_STACK_SIZE
|
||||
#error "THREAD_STACK_SIZE defined but _POSIX_THREAD_ATTR_STACKSIZE undefined"
|
||||
|
|
@ -28,9 +28,9 @@
|
|||
|
||||
/* The POSIX spec says that implementations supporting the sem_*
|
||||
family of functions must indicate this by defining
|
||||
_POSIX_SEMAPHORES. */
|
||||
_POSIX_SEMAPHORES. */
|
||||
#ifdef _POSIX_SEMAPHORES
|
||||
/* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so
|
||||
/* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so
|
||||
we need to add 0 to make it work there as well. */
|
||||
#if (_POSIX_SEMAPHORES+0) == -1
|
||||
#define HAVE_BROKEN_POSIX_SEMAPHORES
|
||||
|
|
@ -92,14 +92,14 @@
|
|||
|
||||
#define MICROSECONDS_TO_TIMESPEC(microseconds, ts) \
|
||||
do { \
|
||||
struct timeval tv; \
|
||||
GETTIMEOFDAY(&tv); \
|
||||
tv.tv_usec += microseconds % 1000000; \
|
||||
tv.tv_sec += microseconds / 1000000; \
|
||||
tv.tv_sec += tv.tv_usec / 1000000; \
|
||||
tv.tv_usec %= 1000000; \
|
||||
ts.tv_sec = tv.tv_sec; \
|
||||
ts.tv_nsec = tv.tv_usec * 1000; \
|
||||
struct timeval tv; \
|
||||
GETTIMEOFDAY(&tv); \
|
||||
tv.tv_usec += microseconds % 1000000; \
|
||||
tv.tv_sec += microseconds / 1000000; \
|
||||
tv.tv_sec += tv.tv_usec / 1000000; \
|
||||
tv.tv_usec %= 1000000; \
|
||||
ts.tv_sec = tv.tv_sec; \
|
||||
ts.tv_nsec = tv.tv_usec * 1000; \
|
||||
} while(0)
|
||||
|
||||
|
||||
|
|
@ -119,10 +119,10 @@ do { \
|
|||
*/
|
||||
|
||||
typedef struct {
|
||||
char locked; /* 0=unlocked, 1=locked */
|
||||
/* a <cond, mutex> pair to handle an acquire of a locked lock */
|
||||
pthread_cond_t lock_released;
|
||||
pthread_mutex_t mut;
|
||||
char locked; /* 0=unlocked, 1=locked */
|
||||
/* a <cond, mutex> pair to handle an acquire of a locked lock */
|
||||
pthread_cond_t lock_released;
|
||||
pthread_mutex_t mut;
|
||||
} pthread_lock;
|
||||
|
||||
#define CHECK_STATUS(name) if (status != 0) { perror(name); error = 1; }
|
||||
|
|
@ -140,11 +140,11 @@ void _noop(void)
|
|||
static void
|
||||
PyThread__init_thread(void)
|
||||
{
|
||||
/* DO AN INIT BY STARTING THE THREAD */
|
||||
static int dummy = 0;
|
||||
pthread_t thread1;
|
||||
pthread_create(&thread1, NULL, (void *) _noop, &dummy);
|
||||
pthread_join(thread1, NULL);
|
||||
/* DO AN INIT BY STARTING THE THREAD */
|
||||
static int dummy = 0;
|
||||
pthread_t thread1;
|
||||
pthread_create(&thread1, NULL, (void *) _noop, &dummy);
|
||||
pthread_join(thread1, NULL);
|
||||
}
|
||||
|
||||
#else /* !_HAVE_BSDI */
|
||||
|
|
@ -153,7 +153,7 @@ static void
|
|||
PyThread__init_thread(void)
|
||||
{
|
||||
#if defined(_AIX) && defined(__GNUC__)
|
||||
pthread_init();
|
||||
pthread_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -167,59 +167,59 @@ PyThread__init_thread(void)
|
|||
long
|
||||
PyThread_start_new_thread(void (*func)(void *), void *arg)
|
||||
{
|
||||
pthread_t th;
|
||||
int status;
|
||||
pthread_t th;
|
||||
int status;
|
||||
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
|
||||
pthread_attr_t attrs;
|
||||
pthread_attr_t attrs;
|
||||
#endif
|
||||
#if defined(THREAD_STACK_SIZE)
|
||||
size_t tss;
|
||||
size_t tss;
|
||||
#endif
|
||||
|
||||
dprintf(("PyThread_start_new_thread called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
dprintf(("PyThread_start_new_thread called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
|
||||
if (pthread_attr_init(&attrs) != 0)
|
||||
return -1;
|
||||
if (pthread_attr_init(&attrs) != 0)
|
||||
return -1;
|
||||
#endif
|
||||
#if defined(THREAD_STACK_SIZE)
|
||||
tss = (_pythread_stacksize != 0) ? _pythread_stacksize
|
||||
: THREAD_STACK_SIZE;
|
||||
if (tss != 0) {
|
||||
if (pthread_attr_setstacksize(&attrs, tss) != 0) {
|
||||
pthread_attr_destroy(&attrs);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
tss = (_pythread_stacksize != 0) ? _pythread_stacksize
|
||||
: THREAD_STACK_SIZE;
|
||||
if (tss != 0) {
|
||||
if (pthread_attr_setstacksize(&attrs, tss) != 0) {
|
||||
pthread_attr_destroy(&attrs);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
|
||||
pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
|
||||
pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
|
||||
#endif
|
||||
|
||||
status = pthread_create(&th,
|
||||
status = pthread_create(&th,
|
||||
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
|
||||
&attrs,
|
||||
&attrs,
|
||||
#else
|
||||
(pthread_attr_t*)NULL,
|
||||
(pthread_attr_t*)NULL,
|
||||
#endif
|
||||
(void* (*)(void *))func,
|
||||
(void *)arg
|
||||
);
|
||||
(void* (*)(void *))func,
|
||||
(void *)arg
|
||||
);
|
||||
|
||||
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
|
||||
pthread_attr_destroy(&attrs);
|
||||
pthread_attr_destroy(&attrs);
|
||||
#endif
|
||||
if (status != 0)
|
||||
return -1;
|
||||
if (status != 0)
|
||||
return -1;
|
||||
|
||||
pthread_detach(th);
|
||||
pthread_detach(th);
|
||||
|
||||
#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
|
||||
return (long) th;
|
||||
return (long) th;
|
||||
#else
|
||||
return (long) *(long *) &th;
|
||||
return (long) *(long *) &th;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -230,28 +230,28 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
|
|||
- It is not clear that the 'volatile' (for AIX?) and ugly casting in the
|
||||
latter return statement (for Alpha OSF/1) are any longer necessary.
|
||||
*/
|
||||
long
|
||||
long
|
||||
PyThread_get_thread_ident(void)
|
||||
{
|
||||
volatile pthread_t threadid;
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
/* Jump through some hoops for Alpha OSF/1 */
|
||||
threadid = pthread_self();
|
||||
volatile pthread_t threadid;
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
/* Jump through some hoops for Alpha OSF/1 */
|
||||
threadid = pthread_self();
|
||||
#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
|
||||
return (long) threadid;
|
||||
return (long) threadid;
|
||||
#else
|
||||
return (long) *(long *) &threadid;
|
||||
return (long) *(long *) &threadid;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
PyThread_exit_thread(void)
|
||||
{
|
||||
dprintf(("PyThread_exit_thread called\n"));
|
||||
if (!initialized) {
|
||||
exit(0);
|
||||
}
|
||||
dprintf(("PyThread_exit_thread called\n"));
|
||||
if (!initialized) {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_SEMAPHORES
|
||||
|
|
@ -260,47 +260,47 @@ PyThread_exit_thread(void)
|
|||
* Lock support.
|
||||
*/
|
||||
|
||||
PyThread_type_lock
|
||||
PyThread_type_lock
|
||||
PyThread_allocate_lock(void)
|
||||
{
|
||||
sem_t *lock;
|
||||
int status, error = 0;
|
||||
sem_t *lock;
|
||||
int status, error = 0;
|
||||
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
lock = (sem_t *)malloc(sizeof(sem_t));
|
||||
lock = (sem_t *)malloc(sizeof(sem_t));
|
||||
|
||||
if (lock) {
|
||||
status = sem_init(lock,0,1);
|
||||
CHECK_STATUS("sem_init");
|
||||
if (lock) {
|
||||
status = sem_init(lock,0,1);
|
||||
CHECK_STATUS("sem_init");
|
||||
|
||||
if (error) {
|
||||
free((void *)lock);
|
||||
lock = NULL;
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
free((void *)lock);
|
||||
lock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
|
||||
return (PyThread_type_lock)lock;
|
||||
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
|
||||
return (PyThread_type_lock)lock;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
PyThread_free_lock(PyThread_type_lock lock)
|
||||
{
|
||||
sem_t *thelock = (sem_t *)lock;
|
||||
int status, error = 0;
|
||||
sem_t *thelock = (sem_t *)lock;
|
||||
int status, error = 0;
|
||||
|
||||
dprintf(("PyThread_free_lock(%p) called\n", lock));
|
||||
dprintf(("PyThread_free_lock(%p) called\n", lock));
|
||||
|
||||
if (!thelock)
|
||||
return;
|
||||
if (!thelock)
|
||||
return;
|
||||
|
||||
status = sem_destroy(thelock);
|
||||
CHECK_STATUS("sem_destroy");
|
||||
status = sem_destroy(thelock);
|
||||
CHECK_STATUS("sem_destroy");
|
||||
|
||||
free((void *)thelock);
|
||||
free((void *)thelock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -312,66 +312,66 @@ PyThread_free_lock(PyThread_type_lock lock)
|
|||
static int
|
||||
fix_status(int status)
|
||||
{
|
||||
return (status == -1) ? errno : status;
|
||||
return (status == -1) ? errno : status;
|
||||
}
|
||||
|
||||
int
|
||||
PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds)
|
||||
{
|
||||
int success;
|
||||
sem_t *thelock = (sem_t *)lock;
|
||||
int status, error = 0;
|
||||
struct timespec ts;
|
||||
int success;
|
||||
sem_t *thelock = (sem_t *)lock;
|
||||
int status, error = 0;
|
||||
struct timespec ts;
|
||||
|
||||
dprintf(("PyThread_acquire_lock_timed(%p, %lld) called\n",
|
||||
lock, microseconds));
|
||||
dprintf(("PyThread_acquire_lock_timed(%p, %lld) called\n",
|
||||
lock, microseconds));
|
||||
|
||||
if (microseconds > 0)
|
||||
MICROSECONDS_TO_TIMESPEC(microseconds, ts);
|
||||
do {
|
||||
if (microseconds > 0)
|
||||
status = fix_status(sem_timedwait(thelock, &ts));
|
||||
else if (microseconds == 0)
|
||||
status = fix_status(sem_trywait(thelock));
|
||||
else
|
||||
status = fix_status(sem_wait(thelock));
|
||||
} while (status == EINTR); /* Retry if interrupted by a signal */
|
||||
if (microseconds > 0)
|
||||
MICROSECONDS_TO_TIMESPEC(microseconds, ts);
|
||||
do {
|
||||
if (microseconds > 0)
|
||||
status = fix_status(sem_timedwait(thelock, &ts));
|
||||
else if (microseconds == 0)
|
||||
status = fix_status(sem_trywait(thelock));
|
||||
else
|
||||
status = fix_status(sem_wait(thelock));
|
||||
} while (status == EINTR); /* Retry if interrupted by a signal */
|
||||
|
||||
if (microseconds > 0) {
|
||||
if (status != ETIMEDOUT)
|
||||
CHECK_STATUS("sem_timedwait");
|
||||
}
|
||||
else if (microseconds == 0) {
|
||||
if (status != EAGAIN)
|
||||
CHECK_STATUS("sem_trywait");
|
||||
}
|
||||
else {
|
||||
CHECK_STATUS("sem_wait");
|
||||
}
|
||||
|
||||
success = (status == 0) ? 1 : 0;
|
||||
if (microseconds > 0) {
|
||||
if (status != ETIMEDOUT)
|
||||
CHECK_STATUS("sem_timedwait");
|
||||
}
|
||||
else if (microseconds == 0) {
|
||||
if (status != EAGAIN)
|
||||
CHECK_STATUS("sem_trywait");
|
||||
}
|
||||
else {
|
||||
CHECK_STATUS("sem_wait");
|
||||
}
|
||||
|
||||
dprintf(("PyThread_acquire_lock_timed(%p, %lld) -> %d\n",
|
||||
lock, microseconds, success));
|
||||
return success;
|
||||
success = (status == 0) ? 1 : 0;
|
||||
|
||||
dprintf(("PyThread_acquire_lock_timed(%p, %lld) -> %d\n",
|
||||
lock, microseconds, success));
|
||||
return success;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
|
||||
{
|
||||
return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0);
|
||||
return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0);
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
PyThread_release_lock(PyThread_type_lock lock)
|
||||
{
|
||||
sem_t *thelock = (sem_t *)lock;
|
||||
int status, error = 0;
|
||||
sem_t *thelock = (sem_t *)lock;
|
||||
int status, error = 0;
|
||||
|
||||
dprintf(("PyThread_release_lock(%p) called\n", lock));
|
||||
dprintf(("PyThread_release_lock(%p) called\n", lock));
|
||||
|
||||
status = sem_post(thelock);
|
||||
CHECK_STATUS("sem_post");
|
||||
status = sem_post(thelock);
|
||||
CHECK_STATUS("sem_post");
|
||||
}
|
||||
|
||||
#else /* USE_SEMAPHORES */
|
||||
|
|
@ -379,137 +379,137 @@ PyThread_release_lock(PyThread_type_lock lock)
|
|||
/*
|
||||
* Lock support.
|
||||
*/
|
||||
PyThread_type_lock
|
||||
PyThread_type_lock
|
||||
PyThread_allocate_lock(void)
|
||||
{
|
||||
pthread_lock *lock;
|
||||
int status, error = 0;
|
||||
pthread_lock *lock;
|
||||
int status, error = 0;
|
||||
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
lock = (pthread_lock *) malloc(sizeof(pthread_lock));
|
||||
if (lock) {
|
||||
memset((void *)lock, '\0', sizeof(pthread_lock));
|
||||
lock->locked = 0;
|
||||
lock = (pthread_lock *) malloc(sizeof(pthread_lock));
|
||||
if (lock) {
|
||||
memset((void *)lock, '\0', sizeof(pthread_lock));
|
||||
lock->locked = 0;
|
||||
|
||||
status = pthread_mutex_init(&lock->mut,
|
||||
pthread_mutexattr_default);
|
||||
CHECK_STATUS("pthread_mutex_init");
|
||||
/* Mark the pthread mutex underlying a Python mutex as
|
||||
pure happens-before. We can't simply mark the
|
||||
Python-level mutex as a mutex because it can be
|
||||
acquired and released in different threads, which
|
||||
will cause errors. */
|
||||
_Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&lock->mut);
|
||||
status = pthread_mutex_init(&lock->mut,
|
||||
pthread_mutexattr_default);
|
||||
CHECK_STATUS("pthread_mutex_init");
|
||||
/* Mark the pthread mutex underlying a Python mutex as
|
||||
pure happens-before. We can't simply mark the
|
||||
Python-level mutex as a mutex because it can be
|
||||
acquired and released in different threads, which
|
||||
will cause errors. */
|
||||
_Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&lock->mut);
|
||||
|
||||
status = pthread_cond_init(&lock->lock_released,
|
||||
pthread_condattr_default);
|
||||
CHECK_STATUS("pthread_cond_init");
|
||||
status = pthread_cond_init(&lock->lock_released,
|
||||
pthread_condattr_default);
|
||||
CHECK_STATUS("pthread_cond_init");
|
||||
|
||||
if (error) {
|
||||
free((void *)lock);
|
||||
lock = 0;
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
free((void *)lock);
|
||||
lock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
|
||||
return (PyThread_type_lock) lock;
|
||||
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
|
||||
return (PyThread_type_lock) lock;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
PyThread_free_lock(PyThread_type_lock lock)
|
||||
{
|
||||
pthread_lock *thelock = (pthread_lock *)lock;
|
||||
int status, error = 0;
|
||||
pthread_lock *thelock = (pthread_lock *)lock;
|
||||
int status, error = 0;
|
||||
|
||||
dprintf(("PyThread_free_lock(%p) called\n", lock));
|
||||
dprintf(("PyThread_free_lock(%p) called\n", lock));
|
||||
|
||||
status = pthread_mutex_destroy( &thelock->mut );
|
||||
CHECK_STATUS("pthread_mutex_destroy");
|
||||
status = pthread_mutex_destroy( &thelock->mut );
|
||||
CHECK_STATUS("pthread_mutex_destroy");
|
||||
|
||||
status = pthread_cond_destroy( &thelock->lock_released );
|
||||
CHECK_STATUS("pthread_cond_destroy");
|
||||
status = pthread_cond_destroy( &thelock->lock_released );
|
||||
CHECK_STATUS("pthread_cond_destroy");
|
||||
|
||||
free((void *)thelock);
|
||||
free((void *)thelock);
|
||||
}
|
||||
|
||||
int
|
||||
PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds)
|
||||
{
|
||||
int success;
|
||||
pthread_lock *thelock = (pthread_lock *)lock;
|
||||
int status, error = 0;
|
||||
int success;
|
||||
pthread_lock *thelock = (pthread_lock *)lock;
|
||||
int status, error = 0;
|
||||
|
||||
dprintf(("PyThread_acquire_lock_timed(%p, %lld) called\n",
|
||||
lock, microseconds));
|
||||
dprintf(("PyThread_acquire_lock_timed(%p, %lld) called\n",
|
||||
lock, microseconds));
|
||||
|
||||
status = pthread_mutex_lock( &thelock->mut );
|
||||
CHECK_STATUS("pthread_mutex_lock[1]");
|
||||
success = thelock->locked == 0;
|
||||
status = pthread_mutex_lock( &thelock->mut );
|
||||
CHECK_STATUS("pthread_mutex_lock[1]");
|
||||
success = thelock->locked == 0;
|
||||
|
||||
if (!success && microseconds != 0) {
|
||||
struct timespec ts;
|
||||
if (microseconds > 0)
|
||||
MICROSECONDS_TO_TIMESPEC(microseconds, ts);
|
||||
/* continue trying until we get the lock */
|
||||
if (!success && microseconds != 0) {
|
||||
struct timespec ts;
|
||||
if (microseconds > 0)
|
||||
MICROSECONDS_TO_TIMESPEC(microseconds, ts);
|
||||
/* continue trying until we get the lock */
|
||||
|
||||
/* mut must be locked by me -- part of the condition
|
||||
* protocol */
|
||||
while (thelock->locked) {
|
||||
if (microseconds > 0) {
|
||||
status = pthread_cond_timedwait(
|
||||
&thelock->lock_released,
|
||||
&thelock->mut, &ts);
|
||||
if (status == ETIMEDOUT)
|
||||
break;
|
||||
CHECK_STATUS("pthread_cond_timed_wait");
|
||||
}
|
||||
else {
|
||||
status = pthread_cond_wait(
|
||||
&thelock->lock_released,
|
||||
&thelock->mut);
|
||||
CHECK_STATUS("pthread_cond_wait");
|
||||
}
|
||||
}
|
||||
success = (status == 0);
|
||||
}
|
||||
if (success) thelock->locked = 1;
|
||||
status = pthread_mutex_unlock( &thelock->mut );
|
||||
CHECK_STATUS("pthread_mutex_unlock[1]");
|
||||
/* mut must be locked by me -- part of the condition
|
||||
* protocol */
|
||||
while (thelock->locked) {
|
||||
if (microseconds > 0) {
|
||||
status = pthread_cond_timedwait(
|
||||
&thelock->lock_released,
|
||||
&thelock->mut, &ts);
|
||||
if (status == ETIMEDOUT)
|
||||
break;
|
||||
CHECK_STATUS("pthread_cond_timed_wait");
|
||||
}
|
||||
else {
|
||||
status = pthread_cond_wait(
|
||||
&thelock->lock_released,
|
||||
&thelock->mut);
|
||||
CHECK_STATUS("pthread_cond_wait");
|
||||
}
|
||||
}
|
||||
success = (status == 0);
|
||||
}
|
||||
if (success) thelock->locked = 1;
|
||||
status = pthread_mutex_unlock( &thelock->mut );
|
||||
CHECK_STATUS("pthread_mutex_unlock[1]");
|
||||
|
||||
if (error) success = 0;
|
||||
dprintf(("PyThread_acquire_lock_timed(%p, %lld) -> %d\n",
|
||||
lock, microseconds, success));
|
||||
return success;
|
||||
if (error) success = 0;
|
||||
dprintf(("PyThread_acquire_lock_timed(%p, %lld) -> %d\n",
|
||||
lock, microseconds, success));
|
||||
return success;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
|
||||
{
|
||||
return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0);
|
||||
return PyThread_acquire_lock_timed(lock, waitflag ? -1 : 0);
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
PyThread_release_lock(PyThread_type_lock lock)
|
||||
{
|
||||
pthread_lock *thelock = (pthread_lock *)lock;
|
||||
int status, error = 0;
|
||||
pthread_lock *thelock = (pthread_lock *)lock;
|
||||
int status, error = 0;
|
||||
|
||||
dprintf(("PyThread_release_lock(%p) called\n", lock));
|
||||
dprintf(("PyThread_release_lock(%p) called\n", lock));
|
||||
|
||||
status = pthread_mutex_lock( &thelock->mut );
|
||||
CHECK_STATUS("pthread_mutex_lock[3]");
|
||||
status = pthread_mutex_lock( &thelock->mut );
|
||||
CHECK_STATUS("pthread_mutex_lock[3]");
|
||||
|
||||
thelock->locked = 0;
|
||||
thelock->locked = 0;
|
||||
|
||||
status = pthread_mutex_unlock( &thelock->mut );
|
||||
CHECK_STATUS("pthread_mutex_unlock[3]");
|
||||
status = pthread_mutex_unlock( &thelock->mut );
|
||||
CHECK_STATUS("pthread_mutex_unlock[3]");
|
||||
|
||||
/* wake up someone (anyone, if any) waiting on the lock */
|
||||
status = pthread_cond_signal( &thelock->lock_released );
|
||||
CHECK_STATUS("pthread_cond_signal");
|
||||
/* wake up someone (anyone, if any) waiting on the lock */
|
||||
status = pthread_cond_signal( &thelock->lock_released );
|
||||
CHECK_STATUS("pthread_cond_signal");
|
||||
}
|
||||
|
||||
#endif /* USE_SEMAPHORES */
|
||||
|
|
@ -522,39 +522,39 @@ static int
|
|||
_pythread_pthread_set_stacksize(size_t size)
|
||||
{
|
||||
#if defined(THREAD_STACK_SIZE)
|
||||
pthread_attr_t attrs;
|
||||
size_t tss_min;
|
||||
int rc = 0;
|
||||
pthread_attr_t attrs;
|
||||
size_t tss_min;
|
||||
int rc = 0;
|
||||
#endif
|
||||
|
||||
/* set to default */
|
||||
if (size == 0) {
|
||||
_pythread_stacksize = 0;
|
||||
return 0;
|
||||
}
|
||||
/* set to default */
|
||||
if (size == 0) {
|
||||
_pythread_stacksize = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(THREAD_STACK_SIZE)
|
||||
#if defined(PTHREAD_STACK_MIN)
|
||||
tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN
|
||||
: THREAD_STACK_MIN;
|
||||
tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN
|
||||
: THREAD_STACK_MIN;
|
||||
#else
|
||||
tss_min = THREAD_STACK_MIN;
|
||||
tss_min = THREAD_STACK_MIN;
|
||||
#endif
|
||||
if (size >= tss_min) {
|
||||
/* validate stack size by setting thread attribute */
|
||||
if (pthread_attr_init(&attrs) == 0) {
|
||||
rc = pthread_attr_setstacksize(&attrs, size);
|
||||
pthread_attr_destroy(&attrs);
|
||||
if (rc == 0) {
|
||||
_pythread_stacksize = size;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
if (size >= tss_min) {
|
||||
/* validate stack size by setting thread attribute */
|
||||
if (pthread_attr_init(&attrs) == 0) {
|
||||
rc = pthread_attr_setstacksize(&attrs, size);
|
||||
pthread_attr_destroy(&attrs);
|
||||
if (rc == 0) {
|
||||
_pythread_stacksize = size;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
#else
|
||||
return -2;
|
||||
return -2;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x)
|
||||
#define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x)
|
||||
|
|
|
|||
|
|
@ -8,67 +8,67 @@
|
|||
#include <ulocks.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define HDR_SIZE 2680 /* sizeof(ushdr_t) */
|
||||
#define MAXPROC 100 /* max # of threads that can be started */
|
||||
#define HDR_SIZE 2680 /* sizeof(ushdr_t) */
|
||||
#define MAXPROC 100 /* max # of threads that can be started */
|
||||
|
||||
static usptr_t *shared_arena;
|
||||
static ulock_t count_lock; /* protection for some variables */
|
||||
static ulock_t wait_lock; /* lock used to wait for other threads */
|
||||
static int waiting_for_threads; /* protected by count_lock */
|
||||
static int nthreads; /* protected by count_lock */
|
||||
static ulock_t count_lock; /* protection for some variables */
|
||||
static ulock_t wait_lock; /* lock used to wait for other threads */
|
||||
static int waiting_for_threads; /* protected by count_lock */
|
||||
static int nthreads; /* protected by count_lock */
|
||||
static int exit_status;
|
||||
static int exiting; /* we're already exiting (for maybe_exit) */
|
||||
static pid_t my_pid; /* PID of main thread */
|
||||
static int exiting; /* we're already exiting (for maybe_exit) */
|
||||
static pid_t my_pid; /* PID of main thread */
|
||||
static struct pidlist {
|
||||
pid_t parent;
|
||||
pid_t child;
|
||||
} pidlist[MAXPROC]; /* PIDs of other threads; protected by count_lock */
|
||||
static int maxpidindex; /* # of PIDs in pidlist */
|
||||
pid_t parent;
|
||||
pid_t child;
|
||||
} pidlist[MAXPROC]; /* PIDs of other threads; protected by count_lock */
|
||||
static int maxpidindex; /* # of PIDs in pidlist */
|
||||
/*
|
||||
* Initialization.
|
||||
*/
|
||||
static void PyThread__init_thread(void)
|
||||
{
|
||||
#ifdef USE_DL
|
||||
long addr, size;
|
||||
long addr, size;
|
||||
#endif /* USE_DL */
|
||||
|
||||
|
||||
#ifdef USE_DL
|
||||
if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
|
||||
perror("usconfig - CONF_INITSIZE (check)");
|
||||
if (usconfig(CONF_INITSIZE, size) < 0)
|
||||
perror("usconfig - CONF_INITSIZE (reset)");
|
||||
addr = (long) dl_getrange(size + HDR_SIZE);
|
||||
dprintf(("trying to use addr %p-%p for shared arena\n", addr, addr+size));
|
||||
errno = 0;
|
||||
if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0)
|
||||
perror("usconfig - CONF_ATTACHADDR (set)");
|
||||
if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
|
||||
perror("usconfig - CONF_INITSIZE (check)");
|
||||
if (usconfig(CONF_INITSIZE, size) < 0)
|
||||
perror("usconfig - CONF_INITSIZE (reset)");
|
||||
addr = (long) dl_getrange(size + HDR_SIZE);
|
||||
dprintf(("trying to use addr %p-%p for shared arena\n", addr, addr+size));
|
||||
errno = 0;
|
||||
if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0)
|
||||
perror("usconfig - CONF_ATTACHADDR (set)");
|
||||
#endif /* USE_DL */
|
||||
if (usconfig(CONF_INITUSERS, 16) < 0)
|
||||
perror("usconfig - CONF_INITUSERS");
|
||||
my_pid = getpid(); /* so that we know which is the main thread */
|
||||
if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0)
|
||||
perror("usconfig - CONF_ARENATYPE");
|
||||
usconfig(CONF_LOCKTYPE, US_DEBUG); /* XXX */
|
||||
if (usconfig(CONF_INITUSERS, 16) < 0)
|
||||
perror("usconfig - CONF_INITUSERS");
|
||||
my_pid = getpid(); /* so that we know which is the main thread */
|
||||
if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0)
|
||||
perror("usconfig - CONF_ARENATYPE");
|
||||
usconfig(CONF_LOCKTYPE, US_DEBUG); /* XXX */
|
||||
#ifdef Py_DEBUG
|
||||
if (thread_debug & 4)
|
||||
usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);
|
||||
else if (thread_debug & 2)
|
||||
usconfig(CONF_LOCKTYPE, US_DEBUG);
|
||||
if (thread_debug & 4)
|
||||
usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);
|
||||
else if (thread_debug & 2)
|
||||
usconfig(CONF_LOCKTYPE, US_DEBUG);
|
||||
#endif /* Py_DEBUG */
|
||||
if ((shared_arena = usinit(tmpnam(0))) == 0)
|
||||
perror("usinit");
|
||||
if ((shared_arena = usinit(tmpnam(0))) == 0)
|
||||
perror("usinit");
|
||||
#ifdef USE_DL
|
||||
if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */
|
||||
perror("usconfig - CONF_ATTACHADDR (reset)");
|
||||
if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */
|
||||
perror("usconfig - CONF_ATTACHADDR (reset)");
|
||||
#endif /* USE_DL */
|
||||
if ((count_lock = usnewlock(shared_arena)) == NULL)
|
||||
perror("usnewlock (count_lock)");
|
||||
(void) usinitlock(count_lock);
|
||||
if ((wait_lock = usnewlock(shared_arena)) == NULL)
|
||||
perror("usnewlock (wait_lock)");
|
||||
dprintf(("arena start: %p, arena size: %ld\n", shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena)));
|
||||
if ((count_lock = usnewlock(shared_arena)) == NULL)
|
||||
perror("usnewlock (count_lock)");
|
||||
(void) usinitlock(count_lock);
|
||||
if ((wait_lock = usnewlock(shared_arena)) == NULL)
|
||||
perror("usnewlock (wait_lock)");
|
||||
dprintf(("arena start: %p, arena size: %ld\n", shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -77,138 +77,138 @@ static void PyThread__init_thread(void)
|
|||
|
||||
static void clean_threads(void)
|
||||
{
|
||||
int i, j;
|
||||
pid_t mypid, pid;
|
||||
int i, j;
|
||||
pid_t mypid, pid;
|
||||
|
||||
/* clean up any exited threads */
|
||||
mypid = getpid();
|
||||
i = 0;
|
||||
while (i < maxpidindex) {
|
||||
if (pidlist[i].parent == mypid && (pid = pidlist[i].child) > 0) {
|
||||
pid = waitpid(pid, 0, WNOHANG);
|
||||
if (pid > 0) {
|
||||
/* a thread has exited */
|
||||
pidlist[i] = pidlist[--maxpidindex];
|
||||
/* remove references to children of dead proc */
|
||||
for (j = 0; j < maxpidindex; j++)
|
||||
if (pidlist[j].parent == pid)
|
||||
pidlist[j].child = -1;
|
||||
continue; /* don't increment i */
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
/* clean up the list */
|
||||
i = 0;
|
||||
while (i < maxpidindex) {
|
||||
if (pidlist[i].child == -1) {
|
||||
pidlist[i] = pidlist[--maxpidindex];
|
||||
continue; /* don't increment i */
|
||||
}
|
||||
i++;
|
||||
}
|
||||
/* clean up any exited threads */
|
||||
mypid = getpid();
|
||||
i = 0;
|
||||
while (i < maxpidindex) {
|
||||
if (pidlist[i].parent == mypid && (pid = pidlist[i].child) > 0) {
|
||||
pid = waitpid(pid, 0, WNOHANG);
|
||||
if (pid > 0) {
|
||||
/* a thread has exited */
|
||||
pidlist[i] = pidlist[--maxpidindex];
|
||||
/* remove references to children of dead proc */
|
||||
for (j = 0; j < maxpidindex; j++)
|
||||
if (pidlist[j].parent == pid)
|
||||
pidlist[j].child = -1;
|
||||
continue; /* don't increment i */
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
/* clean up the list */
|
||||
i = 0;
|
||||
while (i < maxpidindex) {
|
||||
if (pidlist[i].child == -1) {
|
||||
pidlist[i] = pidlist[--maxpidindex];
|
||||
continue; /* don't increment i */
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
long PyThread_start_new_thread(void (*func)(void *), void *arg)
|
||||
{
|
||||
#ifdef USE_DL
|
||||
long addr, size;
|
||||
static int local_initialized = 0;
|
||||
long addr, size;
|
||||
static int local_initialized = 0;
|
||||
#endif /* USE_DL */
|
||||
int success = 0; /* init not needed when SOLARIS_THREADS and */
|
||||
/* C_THREADS implemented properly */
|
||||
int success = 0; /* init not needed when SOLARIS_THREADS and */
|
||||
/* C_THREADS implemented properly */
|
||||
|
||||
dprintf(("PyThread_start_new_thread called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
switch (ussetlock(count_lock)) {
|
||||
case 0: return 0;
|
||||
case -1: perror("ussetlock (count_lock)");
|
||||
}
|
||||
if (maxpidindex >= MAXPROC)
|
||||
success = -1;
|
||||
else {
|
||||
dprintf(("PyThread_start_new_thread called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
switch (ussetlock(count_lock)) {
|
||||
case 0: return 0;
|
||||
case -1: perror("ussetlock (count_lock)");
|
||||
}
|
||||
if (maxpidindex >= MAXPROC)
|
||||
success = -1;
|
||||
else {
|
||||
#ifdef USE_DL
|
||||
if (!local_initialized) {
|
||||
if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
|
||||
perror("usconfig - CONF_INITSIZE (check)");
|
||||
if (usconfig(CONF_INITSIZE, size) < 0)
|
||||
perror("usconfig - CONF_INITSIZE (reset)");
|
||||
addr = (long) dl_getrange(size + HDR_SIZE);
|
||||
dprintf(("trying to use addr %p-%p for sproc\n",
|
||||
addr, addr+size));
|
||||
errno = 0;
|
||||
if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 &&
|
||||
errno != 0)
|
||||
perror("usconfig - CONF_ATTACHADDR (set)");
|
||||
}
|
||||
if (!local_initialized) {
|
||||
if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
|
||||
perror("usconfig - CONF_INITSIZE (check)");
|
||||
if (usconfig(CONF_INITSIZE, size) < 0)
|
||||
perror("usconfig - CONF_INITSIZE (reset)");
|
||||
addr = (long) dl_getrange(size + HDR_SIZE);
|
||||
dprintf(("trying to use addr %p-%p for sproc\n",
|
||||
addr, addr+size));
|
||||
errno = 0;
|
||||
if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 &&
|
||||
errno != 0)
|
||||
perror("usconfig - CONF_ATTACHADDR (set)");
|
||||
}
|
||||
#endif /* USE_DL */
|
||||
clean_threads();
|
||||
if ((success = sproc(func, PR_SALL, arg)) < 0)
|
||||
perror("sproc");
|
||||
clean_threads();
|
||||
if ((success = sproc(func, PR_SALL, arg)) < 0)
|
||||
perror("sproc");
|
||||
#ifdef USE_DL
|
||||
if (!local_initialized) {
|
||||
if (usconfig(CONF_ATTACHADDR, addr) < 0)
|
||||
/* reset address */
|
||||
perror("usconfig - CONF_ATTACHADDR (reset)");
|
||||
local_initialized = 1;
|
||||
}
|
||||
if (!local_initialized) {
|
||||
if (usconfig(CONF_ATTACHADDR, addr) < 0)
|
||||
/* reset address */
|
||||
perror("usconfig - CONF_ATTACHADDR (reset)");
|
||||
local_initialized = 1;
|
||||
}
|
||||
#endif /* USE_DL */
|
||||
if (success >= 0) {
|
||||
nthreads++;
|
||||
pidlist[maxpidindex].parent = getpid();
|
||||
pidlist[maxpidindex++].child = success;
|
||||
dprintf(("pidlist[%d] = %d\n",
|
||||
maxpidindex-1, success));
|
||||
}
|
||||
}
|
||||
if (usunsetlock(count_lock) < 0)
|
||||
perror("usunsetlock (count_lock)");
|
||||
return success;
|
||||
if (success >= 0) {
|
||||
nthreads++;
|
||||
pidlist[maxpidindex].parent = getpid();
|
||||
pidlist[maxpidindex++].child = success;
|
||||
dprintf(("pidlist[%d] = %d\n",
|
||||
maxpidindex-1, success));
|
||||
}
|
||||
}
|
||||
if (usunsetlock(count_lock) < 0)
|
||||
perror("usunsetlock (count_lock)");
|
||||
return success;
|
||||
}
|
||||
|
||||
long PyThread_get_thread_ident(void)
|
||||
{
|
||||
return getpid();
|
||||
return getpid();
|
||||
}
|
||||
|
||||
void PyThread_exit_thread(void)
|
||||
{
|
||||
dprintf(("PyThread_exit_thread called\n"));
|
||||
if (!initialized)
|
||||
exit(0);
|
||||
if (ussetlock(count_lock) < 0)
|
||||
perror("ussetlock (count_lock)");
|
||||
nthreads--;
|
||||
if (getpid() == my_pid) {
|
||||
/* main thread; wait for other threads to exit */
|
||||
exiting = 1;
|
||||
waiting_for_threads = 1;
|
||||
if (ussetlock(wait_lock) < 0)
|
||||
perror("ussetlock (wait_lock)");
|
||||
for (;;) {
|
||||
if (nthreads < 0) {
|
||||
dprintf(("really exit (%d)\n", exit_status));
|
||||
exit(exit_status);
|
||||
}
|
||||
if (usunsetlock(count_lock) < 0)
|
||||
perror("usunsetlock (count_lock)");
|
||||
dprintf(("waiting for other threads (%d)\n", nthreads));
|
||||
if (ussetlock(wait_lock) < 0)
|
||||
perror("ussetlock (wait_lock)");
|
||||
if (ussetlock(count_lock) < 0)
|
||||
perror("ussetlock (count_lock)");
|
||||
}
|
||||
}
|
||||
/* not the main thread */
|
||||
if (waiting_for_threads) {
|
||||
dprintf(("main thread is waiting\n"));
|
||||
if (usunsetlock(wait_lock) < 0)
|
||||
perror("usunsetlock (wait_lock)");
|
||||
}
|
||||
if (usunsetlock(count_lock) < 0)
|
||||
perror("usunsetlock (count_lock)");
|
||||
_exit(0);
|
||||
dprintf(("PyThread_exit_thread called\n"));
|
||||
if (!initialized)
|
||||
exit(0);
|
||||
if (ussetlock(count_lock) < 0)
|
||||
perror("ussetlock (count_lock)");
|
||||
nthreads--;
|
||||
if (getpid() == my_pid) {
|
||||
/* main thread; wait for other threads to exit */
|
||||
exiting = 1;
|
||||
waiting_for_threads = 1;
|
||||
if (ussetlock(wait_lock) < 0)
|
||||
perror("ussetlock (wait_lock)");
|
||||
for (;;) {
|
||||
if (nthreads < 0) {
|
||||
dprintf(("really exit (%d)\n", exit_status));
|
||||
exit(exit_status);
|
||||
}
|
||||
if (usunsetlock(count_lock) < 0)
|
||||
perror("usunsetlock (count_lock)");
|
||||
dprintf(("waiting for other threads (%d)\n", nthreads));
|
||||
if (ussetlock(wait_lock) < 0)
|
||||
perror("ussetlock (wait_lock)");
|
||||
if (ussetlock(count_lock) < 0)
|
||||
perror("ussetlock (count_lock)");
|
||||
}
|
||||
}
|
||||
/* not the main thread */
|
||||
if (waiting_for_threads) {
|
||||
dprintf(("main thread is waiting\n"));
|
||||
if (usunsetlock(wait_lock) < 0)
|
||||
perror("usunsetlock (wait_lock)");
|
||||
}
|
||||
if (usunsetlock(count_lock) < 0)
|
||||
perror("usunsetlock (count_lock)");
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -216,44 +216,44 @@ void PyThread_exit_thread(void)
|
|||
*/
|
||||
PyThread_type_lock PyThread_allocate_lock(void)
|
||||
{
|
||||
ulock_t lock;
|
||||
ulock_t lock;
|
||||
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
if ((lock = usnewlock(shared_arena)) == NULL)
|
||||
perror("usnewlock");
|
||||
(void) usinitlock(lock);
|
||||
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
|
||||
return (PyThread_type_lock) lock;
|
||||
if ((lock = usnewlock(shared_arena)) == NULL)
|
||||
perror("usnewlock");
|
||||
(void) usinitlock(lock);
|
||||
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
|
||||
return (PyThread_type_lock) lock;
|
||||
}
|
||||
|
||||
void PyThread_free_lock(PyThread_type_lock lock)
|
||||
{
|
||||
dprintf(("PyThread_free_lock(%p) called\n", lock));
|
||||
usfreelock((ulock_t) lock, shared_arena);
|
||||
dprintf(("PyThread_free_lock(%p) called\n", lock));
|
||||
usfreelock((ulock_t) lock, shared_arena);
|
||||
}
|
||||
|
||||
int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
|
||||
{
|
||||
int success;
|
||||
int success;
|
||||
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
|
||||
errno = 0; /* clear it just in case */
|
||||
if (waitflag)
|
||||
success = ussetlock((ulock_t) lock);
|
||||
else
|
||||
success = uscsetlock((ulock_t) lock, 1); /* Try it once */
|
||||
if (success < 0)
|
||||
perror(waitflag ? "ussetlock" : "uscsetlock");
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
|
||||
return success;
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
|
||||
errno = 0; /* clear it just in case */
|
||||
if (waitflag)
|
||||
success = ussetlock((ulock_t) lock);
|
||||
else
|
||||
success = uscsetlock((ulock_t) lock, 1); /* Try it once */
|
||||
if (success < 0)
|
||||
perror(waitflag ? "ussetlock" : "uscsetlock");
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
|
||||
return success;
|
||||
}
|
||||
|
||||
void PyThread_release_lock(PyThread_type_lock lock)
|
||||
{
|
||||
dprintf(("PyThread_release_lock(%p) called\n", lock));
|
||||
if (usunsetlock((ulock_t) lock) < 0)
|
||||
perror("usunsetlock");
|
||||
dprintf(("PyThread_release_lock(%p) called\n", lock));
|
||||
if (usunsetlock((ulock_t) lock) < 0)
|
||||
perror("usunsetlock");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,114 +17,114 @@ static void PyThread__init_thread(void)
|
|||
* Thread support.
|
||||
*/
|
||||
struct func_arg {
|
||||
void (*func)(void *);
|
||||
void *arg;
|
||||
void (*func)(void *);
|
||||
void *arg;
|
||||
};
|
||||
|
||||
static void *
|
||||
new_func(void *funcarg)
|
||||
{
|
||||
void (*func)(void *);
|
||||
void *arg;
|
||||
void (*func)(void *);
|
||||
void *arg;
|
||||
|
||||
func = ((struct func_arg *) funcarg)->func;
|
||||
arg = ((struct func_arg *) funcarg)->arg;
|
||||
free(funcarg);
|
||||
(*func)(arg);
|
||||
return 0;
|
||||
func = ((struct func_arg *) funcarg)->func;
|
||||
arg = ((struct func_arg *) funcarg)->arg;
|
||||
free(funcarg);
|
||||
(*func)(arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long
|
||||
PyThread_start_new_thread(void (*func)(void *), void *arg)
|
||||
{
|
||||
thread_t tid;
|
||||
struct func_arg *funcarg;
|
||||
thread_t tid;
|
||||
struct func_arg *funcarg;
|
||||
|
||||
dprintf(("PyThread_start_new_thread called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
funcarg = (struct func_arg *) malloc(sizeof(struct func_arg));
|
||||
funcarg->func = func;
|
||||
funcarg->arg = arg;
|
||||
if (thr_create(0, 0, new_func, funcarg,
|
||||
THR_DETACHED | THR_NEW_LWP, &tid)) {
|
||||
perror("thr_create");
|
||||
free((void *) funcarg);
|
||||
return -1;
|
||||
}
|
||||
return tid;
|
||||
dprintf(("PyThread_start_new_thread called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
funcarg = (struct func_arg *) malloc(sizeof(struct func_arg));
|
||||
funcarg->func = func;
|
||||
funcarg->arg = arg;
|
||||
if (thr_create(0, 0, new_func, funcarg,
|
||||
THR_DETACHED | THR_NEW_LWP, &tid)) {
|
||||
perror("thr_create");
|
||||
free((void *) funcarg);
|
||||
return -1;
|
||||
}
|
||||
return tid;
|
||||
}
|
||||
|
||||
long
|
||||
PyThread_get_thread_ident(void)
|
||||
{
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
return thr_self();
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
return thr_self();
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
PyThread_exit_thread(void)
|
||||
{
|
||||
dprintf(("PyThread_exit_thread called\n"));
|
||||
if (!initialized)
|
||||
exit(0);
|
||||
thr_exit(0);
|
||||
dprintf(("PyThread_exit_thread called\n"));
|
||||
if (!initialized)
|
||||
exit(0);
|
||||
thr_exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock support.
|
||||
*/
|
||||
PyThread_type_lock
|
||||
PyThread_type_lock
|
||||
PyThread_allocate_lock(void)
|
||||
{
|
||||
mutex_t *lock;
|
||||
mutex_t *lock;
|
||||
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
lock = (mutex_t *) malloc(sizeof(mutex_t));
|
||||
if (mutex_init(lock, USYNC_THREAD, 0)) {
|
||||
perror("mutex_init");
|
||||
free((void *) lock);
|
||||
lock = 0;
|
||||
}
|
||||
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
|
||||
return (PyThread_type_lock) lock;
|
||||
lock = (mutex_t *) malloc(sizeof(mutex_t));
|
||||
if (mutex_init(lock, USYNC_THREAD, 0)) {
|
||||
perror("mutex_init");
|
||||
free((void *) lock);
|
||||
lock = 0;
|
||||
}
|
||||
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
|
||||
return (PyThread_type_lock) lock;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
PyThread_free_lock(PyThread_type_lock lock)
|
||||
{
|
||||
dprintf(("PyThread_free_lock(%p) called\n", lock));
|
||||
mutex_destroy((mutex_t *) lock);
|
||||
free((void *) lock);
|
||||
dprintf(("PyThread_free_lock(%p) called\n", lock));
|
||||
mutex_destroy((mutex_t *) lock);
|
||||
free((void *) lock);
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
|
||||
{
|
||||
int success;
|
||||
int success;
|
||||
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
|
||||
if (waitflag)
|
||||
success = mutex_lock((mutex_t *) lock);
|
||||
else
|
||||
success = mutex_trylock((mutex_t *) lock);
|
||||
if (success < 0)
|
||||
perror(waitflag ? "mutex_lock" : "mutex_trylock");
|
||||
else
|
||||
success = !success; /* solaris does it the other way round */
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
|
||||
return success;
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
|
||||
if (waitflag)
|
||||
success = mutex_lock((mutex_t *) lock);
|
||||
else
|
||||
success = mutex_trylock((mutex_t *) lock);
|
||||
if (success < 0)
|
||||
perror(waitflag ? "mutex_lock" : "mutex_trylock");
|
||||
else
|
||||
success = !success; /* solaris does it the other way round */
|
||||
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
|
||||
return success;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
PyThread_release_lock(PyThread_type_lock lock)
|
||||
{
|
||||
dprintf(("PyThread_release_lock(%p) called\n", lock));
|
||||
if (mutex_unlock((mutex_t *) lock))
|
||||
perror("mutex_unlock");
|
||||
dprintf(("PyThread_release_lock(%p) called\n", lock));
|
||||
if (mutex_unlock((mutex_t *) lock))
|
||||
perror("mutex_unlock");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,21 +24,21 @@ static void PyThread__init_thread(void)
|
|||
*/
|
||||
long PyThread_start_new_thread(void (*func)(void *), void *arg)
|
||||
{
|
||||
long rv;
|
||||
int success = -1;
|
||||
long rv;
|
||||
int success = -1;
|
||||
|
||||
dprintf(("%ld: PyThread_start_new_thread called\n", PyThread_get_thread_ident()));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
dprintf(("%ld: PyThread_start_new_thread called\n", PyThread_get_thread_ident()));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
rv = _beginthread(func, 0, arg); /* use default stack size */
|
||||
|
||||
if (rv != -1) {
|
||||
success = 0;
|
||||
dprintf(("%ld: PyThread_start_new_thread succeeded:\n", PyThread_get_thread_ident()));
|
||||
}
|
||||
rv = _beginthread(func, 0, arg); /* use default stack size */
|
||||
|
||||
return success;
|
||||
if (rv != -1) {
|
||||
success = 0;
|
||||
dprintf(("%ld: PyThread_start_new_thread succeeded:\n", PyThread_get_thread_ident()));
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -47,18 +47,18 @@ long PyThread_start_new_thread(void (*func)(void *), void *arg)
|
|||
*/
|
||||
long PyThread_get_thread_ident(void)
|
||||
{
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
return GetCurrentThreadId();
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
|
||||
void PyThread_exit_thread(void)
|
||||
{
|
||||
dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident()));
|
||||
if (!initialized)
|
||||
exit(0);
|
||||
_endthread();
|
||||
dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident()));
|
||||
if (!initialized)
|
||||
exit(0);
|
||||
_endthread();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -72,12 +72,12 @@ PyThread_type_lock PyThread_allocate_lock(void)
|
|||
|
||||
dprintf(("PyThread_allocate_lock called\n"));
|
||||
if (!initialized)
|
||||
PyThread_init_thread();
|
||||
PyThread_init_thread();
|
||||
|
||||
aLock = CreateEvent(NULL, /* Security attributes */
|
||||
0, /* Manual-Reset */
|
||||
1, /* Is initially signalled */
|
||||
NULL); /* Name of event */
|
||||
0, /* Manual-Reset */
|
||||
1, /* Is initially signalled */
|
||||
NULL); /* Name of event */
|
||||
|
||||
dprintf(("%ld: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock));
|
||||
|
||||
|
|
@ -107,22 +107,22 @@ int PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
|
|||
#ifndef DEBUG
|
||||
waitResult = WaitForSingleObject(aLock, (waitflag ? INFINITE : 0));
|
||||
#else
|
||||
/* To aid in debugging, we regularly wake up. This allows us to
|
||||
break into the debugger */
|
||||
while (TRUE) {
|
||||
waitResult = WaitForSingleObject(aLock, waitflag ? 3000 : 0);
|
||||
if (waitflag==0 || (waitflag && waitResult == WAIT_OBJECT_0))
|
||||
break;
|
||||
}
|
||||
/* To aid in debugging, we regularly wake up. This allows us to
|
||||
break into the debugger */
|
||||
while (TRUE) {
|
||||
waitResult = WaitForSingleObject(aLock, waitflag ? 3000 : 0);
|
||||
if (waitflag==0 || (waitflag && waitResult == WAIT_OBJECT_0))
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (waitResult != WAIT_OBJECT_0) {
|
||||
success = 0; /* We failed */
|
||||
success = 0; /* We failed */
|
||||
}
|
||||
|
||||
dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n", PyThread_get_thread_ident(),aLock, waitflag, success));
|
||||
dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n", PyThread_get_thread_ident(),aLock, waitflag, success));
|
||||
|
||||
return success;
|
||||
return success;
|
||||
}
|
||||
|
||||
void PyThread_release_lock(PyThread_type_lock aLock)
|
||||
|
|
@ -130,7 +130,7 @@ void PyThread_release_lock(PyThread_type_lock aLock)
|
|||
dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
|
||||
|
||||
if (!SetEvent(aLock))
|
||||
dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", PyThread_get_thread_ident(), aLock, GetLastError()));
|
||||
dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", PyThread_get_thread_ident(), aLock, GetLastError()));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -30,303 +30,303 @@ static PyMethodDef tb_methods[] = {
|
|||
};
|
||||
|
||||
static PyMemberDef tb_memberlist[] = {
|
||||
{"tb_next", T_OBJECT, OFF(tb_next), READONLY},
|
||||
{"tb_frame", T_OBJECT, OFF(tb_frame), READONLY},
|
||||
{"tb_lasti", T_INT, OFF(tb_lasti), READONLY},
|
||||
{"tb_lineno", T_INT, OFF(tb_lineno), READONLY},
|
||||
{NULL} /* Sentinel */
|
||||
{"tb_next", T_OBJECT, OFF(tb_next), READONLY},
|
||||
{"tb_frame", T_OBJECT, OFF(tb_frame), READONLY},
|
||||
{"tb_lasti", T_INT, OFF(tb_lasti), READONLY},
|
||||
{"tb_lineno", T_INT, OFF(tb_lineno), READONLY},
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
static void
|
||||
tb_dealloc(PyTracebackObject *tb)
|
||||
{
|
||||
PyObject_GC_UnTrack(tb);
|
||||
Py_TRASHCAN_SAFE_BEGIN(tb)
|
||||
Py_XDECREF(tb->tb_next);
|
||||
Py_XDECREF(tb->tb_frame);
|
||||
PyObject_GC_Del(tb);
|
||||
Py_TRASHCAN_SAFE_END(tb)
|
||||
PyObject_GC_UnTrack(tb);
|
||||
Py_TRASHCAN_SAFE_BEGIN(tb)
|
||||
Py_XDECREF(tb->tb_next);
|
||||
Py_XDECREF(tb->tb_frame);
|
||||
PyObject_GC_Del(tb);
|
||||
Py_TRASHCAN_SAFE_END(tb)
|
||||
}
|
||||
|
||||
static int
|
||||
tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg)
|
||||
{
|
||||
Py_VISIT(tb->tb_next);
|
||||
Py_VISIT(tb->tb_frame);
|
||||
return 0;
|
||||
Py_VISIT(tb->tb_next);
|
||||
Py_VISIT(tb->tb_frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
tb_clear(PyTracebackObject *tb)
|
||||
{
|
||||
Py_CLEAR(tb->tb_next);
|
||||
Py_CLEAR(tb->tb_frame);
|
||||
Py_CLEAR(tb->tb_next);
|
||||
Py_CLEAR(tb->tb_frame);
|
||||
}
|
||||
|
||||
PyTypeObject PyTraceBack_Type = {
|
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||
"traceback",
|
||||
sizeof(PyTracebackObject),
|
||||
0,
|
||||
(destructor)tb_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_reserved*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
PyObject_GenericGetAttr, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
|
||||
0, /* tp_doc */
|
||||
(traverseproc)tb_traverse, /* tp_traverse */
|
||||
(inquiry)tb_clear, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
tb_methods, /* tp_methods */
|
||||
tb_memberlist, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||
"traceback",
|
||||
sizeof(PyTracebackObject),
|
||||
0,
|
||||
(destructor)tb_dealloc, /*tp_dealloc*/
|
||||
0, /*tp_print*/
|
||||
0, /*tp_getattr*/
|
||||
0, /*tp_setattr*/
|
||||
0, /*tp_reserved*/
|
||||
0, /*tp_repr*/
|
||||
0, /*tp_as_number*/
|
||||
0, /*tp_as_sequence*/
|
||||
0, /*tp_as_mapping*/
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
PyObject_GenericGetAttr, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
|
||||
0, /* tp_doc */
|
||||
(traverseproc)tb_traverse, /* tp_traverse */
|
||||
(inquiry)tb_clear, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
tb_methods, /* tp_methods */
|
||||
tb_memberlist, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
};
|
||||
|
||||
static PyTracebackObject *
|
||||
newtracebackobject(PyTracebackObject *next, PyFrameObject *frame)
|
||||
{
|
||||
PyTracebackObject *tb;
|
||||
if ((next != NULL && !PyTraceBack_Check(next)) ||
|
||||
frame == NULL || !PyFrame_Check(frame)) {
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
}
|
||||
tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);
|
||||
if (tb != NULL) {
|
||||
Py_XINCREF(next);
|
||||
tb->tb_next = next;
|
||||
Py_XINCREF(frame);
|
||||
tb->tb_frame = frame;
|
||||
tb->tb_lasti = frame->f_lasti;
|
||||
tb->tb_lineno = PyFrame_GetLineNumber(frame);
|
||||
PyObject_GC_Track(tb);
|
||||
}
|
||||
return tb;
|
||||
PyTracebackObject *tb;
|
||||
if ((next != NULL && !PyTraceBack_Check(next)) ||
|
||||
frame == NULL || !PyFrame_Check(frame)) {
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
}
|
||||
tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);
|
||||
if (tb != NULL) {
|
||||
Py_XINCREF(next);
|
||||
tb->tb_next = next;
|
||||
Py_XINCREF(frame);
|
||||
tb->tb_frame = frame;
|
||||
tb->tb_lasti = frame->f_lasti;
|
||||
tb->tb_lineno = PyFrame_GetLineNumber(frame);
|
||||
PyObject_GC_Track(tb);
|
||||
}
|
||||
return tb;
|
||||
}
|
||||
|
||||
int
|
||||
PyTraceBack_Here(PyFrameObject *frame)
|
||||
{
|
||||
PyThreadState *tstate = PyThreadState_GET();
|
||||
PyTracebackObject *oldtb = (PyTracebackObject *) tstate->curexc_traceback;
|
||||
PyTracebackObject *tb = newtracebackobject(oldtb, frame);
|
||||
if (tb == NULL)
|
||||
return -1;
|
||||
tstate->curexc_traceback = (PyObject *)tb;
|
||||
Py_XDECREF(oldtb);
|
||||
return 0;
|
||||
PyThreadState *tstate = PyThreadState_GET();
|
||||
PyTracebackObject *oldtb = (PyTracebackObject *) tstate->curexc_traceback;
|
||||
PyTracebackObject *tb = newtracebackobject(oldtb, frame);
|
||||
if (tb == NULL)
|
||||
return -1;
|
||||
tstate->curexc_traceback = (PyObject *)tb;
|
||||
Py_XDECREF(oldtb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_Py_FindSourceFile(const char* filename, char* namebuf, size_t namelen, int open_flags)
|
||||
{
|
||||
int i;
|
||||
int fd = -1;
|
||||
PyObject *v;
|
||||
Py_ssize_t _npath;
|
||||
int npath;
|
||||
size_t taillen;
|
||||
PyObject *syspath;
|
||||
const char* path;
|
||||
const char* tail;
|
||||
Py_ssize_t len;
|
||||
int i;
|
||||
int fd = -1;
|
||||
PyObject *v;
|
||||
Py_ssize_t _npath;
|
||||
int npath;
|
||||
size_t taillen;
|
||||
PyObject *syspath;
|
||||
const char* path;
|
||||
const char* tail;
|
||||
Py_ssize_t len;
|
||||
|
||||
/* Search tail of filename in sys.path before giving up */
|
||||
tail = strrchr(filename, SEP);
|
||||
if (tail == NULL)
|
||||
tail = filename;
|
||||
else
|
||||
tail++;
|
||||
taillen = strlen(tail);
|
||||
/* Search tail of filename in sys.path before giving up */
|
||||
tail = strrchr(filename, SEP);
|
||||
if (tail == NULL)
|
||||
tail = filename;
|
||||
else
|
||||
tail++;
|
||||
taillen = strlen(tail);
|
||||
|
||||
syspath = PySys_GetObject("path");
|
||||
if (syspath == NULL || !PyList_Check(syspath))
|
||||
return -1;
|
||||
_npath = PyList_Size(syspath);
|
||||
npath = Py_SAFE_DOWNCAST(_npath, Py_ssize_t, int);
|
||||
syspath = PySys_GetObject("path");
|
||||
if (syspath == NULL || !PyList_Check(syspath))
|
||||
return -1;
|
||||
_npath = PyList_Size(syspath);
|
||||
npath = Py_SAFE_DOWNCAST(_npath, Py_ssize_t, int);
|
||||
|
||||
for (i = 0; i < npath; i++) {
|
||||
v = PyList_GetItem(syspath, i);
|
||||
if (v == NULL) {
|
||||
PyErr_Clear();
|
||||
break;
|
||||
}
|
||||
if (!PyUnicode_Check(v))
|
||||
continue;
|
||||
path = _PyUnicode_AsStringAndSize(v, &len);
|
||||
if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1)
|
||||
continue; /* Too long */
|
||||
strcpy(namebuf, path);
|
||||
if (strlen(namebuf) != len)
|
||||
continue; /* v contains '\0' */
|
||||
if (len > 0 && namebuf[len-1] != SEP)
|
||||
namebuf[len++] = SEP;
|
||||
strcpy(namebuf+len, tail);
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
fd = open(namebuf, open_flags);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (0 <= fd) {
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
for (i = 0; i < npath; i++) {
|
||||
v = PyList_GetItem(syspath, i);
|
||||
if (v == NULL) {
|
||||
PyErr_Clear();
|
||||
break;
|
||||
}
|
||||
if (!PyUnicode_Check(v))
|
||||
continue;
|
||||
path = _PyUnicode_AsStringAndSize(v, &len);
|
||||
if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1)
|
||||
continue; /* Too long */
|
||||
strcpy(namebuf, path);
|
||||
if (strlen(namebuf) != len)
|
||||
continue; /* v contains '\0' */
|
||||
if (len > 0 && namebuf[len-1] != SEP)
|
||||
namebuf[len++] = SEP;
|
||||
strcpy(namebuf+len, tail);
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
fd = open(namebuf, open_flags);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (0 <= fd) {
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
_Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno, int indent)
|
||||
{
|
||||
int err = 0;
|
||||
int fd;
|
||||
int i;
|
||||
char *found_encoding;
|
||||
char *encoding;
|
||||
PyObject *fob = NULL;
|
||||
PyObject *lineobj = NULL;
|
||||
int err = 0;
|
||||
int fd;
|
||||
int i;
|
||||
char *found_encoding;
|
||||
char *encoding;
|
||||
PyObject *fob = NULL;
|
||||
PyObject *lineobj = NULL;
|
||||
#ifdef O_BINARY
|
||||
const int open_flags = O_RDONLY | O_BINARY; /* necessary for Windows */
|
||||
const int open_flags = O_RDONLY | O_BINARY; /* necessary for Windows */
|
||||
#else
|
||||
const int open_flags = O_RDONLY;
|
||||
const int open_flags = O_RDONLY;
|
||||
#endif
|
||||
char buf[MAXPATHLEN+1];
|
||||
Py_UNICODE *u, *p;
|
||||
Py_ssize_t len;
|
||||
char buf[MAXPATHLEN+1];
|
||||
Py_UNICODE *u, *p;
|
||||
Py_ssize_t len;
|
||||
|
||||
/* open the file */
|
||||
if (filename == NULL)
|
||||
return 0;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
fd = open(filename, open_flags);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (fd < 0) {
|
||||
fd = _Py_FindSourceFile(filename, buf, sizeof(buf), open_flags);
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
filename = buf;
|
||||
}
|
||||
/* open the file */
|
||||
if (filename == NULL)
|
||||
return 0;
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
fd = open(filename, open_flags);
|
||||
Py_END_ALLOW_THREADS
|
||||
if (fd < 0) {
|
||||
fd = _Py_FindSourceFile(filename, buf, sizeof(buf), open_flags);
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
filename = buf;
|
||||
}
|
||||
|
||||
/* use the right encoding to decode the file as unicode */
|
||||
found_encoding = PyTokenizer_FindEncoding(fd);
|
||||
encoding = (found_encoding != NULL) ? found_encoding :
|
||||
(char*)PyUnicode_GetDefaultEncoding();
|
||||
lseek(fd, 0, 0); /* Reset position */
|
||||
fob = PyFile_FromFd(fd, (char*)filename, "r", -1, (char*)encoding,
|
||||
NULL, NULL, 1);
|
||||
PyMem_FREE(found_encoding);
|
||||
if (fob == NULL) {
|
||||
PyErr_Clear();
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
/* use the right encoding to decode the file as unicode */
|
||||
found_encoding = PyTokenizer_FindEncoding(fd);
|
||||
encoding = (found_encoding != NULL) ? found_encoding :
|
||||
(char*)PyUnicode_GetDefaultEncoding();
|
||||
lseek(fd, 0, 0); /* Reset position */
|
||||
fob = PyFile_FromFd(fd, (char*)filename, "r", -1, (char*)encoding,
|
||||
NULL, NULL, 1);
|
||||
PyMem_FREE(found_encoding);
|
||||
if (fob == NULL) {
|
||||
PyErr_Clear();
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get the line number lineno */
|
||||
for (i = 0; i < lineno; i++) {
|
||||
Py_XDECREF(lineobj);
|
||||
lineobj = PyFile_GetLine(fob, -1);
|
||||
if (!lineobj) {
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Py_DECREF(fob);
|
||||
if (!lineobj || !PyUnicode_Check(lineobj)) {
|
||||
Py_XDECREF(lineobj);
|
||||
return err;
|
||||
}
|
||||
/* get the line number lineno */
|
||||
for (i = 0; i < lineno; i++) {
|
||||
Py_XDECREF(lineobj);
|
||||
lineobj = PyFile_GetLine(fob, -1);
|
||||
if (!lineobj) {
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Py_DECREF(fob);
|
||||
if (!lineobj || !PyUnicode_Check(lineobj)) {
|
||||
Py_XDECREF(lineobj);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* remove the indentation of the line */
|
||||
u = PyUnicode_AS_UNICODE(lineobj);
|
||||
len = PyUnicode_GET_SIZE(lineobj);
|
||||
for (p=u; *p == ' ' || *p == '\t' || *p == '\014'; p++)
|
||||
len--;
|
||||
if (u != p) {
|
||||
PyObject *truncated;
|
||||
truncated = PyUnicode_FromUnicode(p, len);
|
||||
if (truncated) {
|
||||
Py_DECREF(lineobj);
|
||||
lineobj = truncated;
|
||||
} else {
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
/* remove the indentation of the line */
|
||||
u = PyUnicode_AS_UNICODE(lineobj);
|
||||
len = PyUnicode_GET_SIZE(lineobj);
|
||||
for (p=u; *p == ' ' || *p == '\t' || *p == '\014'; p++)
|
||||
len--;
|
||||
if (u != p) {
|
||||
PyObject *truncated;
|
||||
truncated = PyUnicode_FromUnicode(p, len);
|
||||
if (truncated) {
|
||||
Py_DECREF(lineobj);
|
||||
lineobj = truncated;
|
||||
} else {
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/* Write some spaces before the line */
|
||||
strcpy(buf, " ");
|
||||
assert (strlen(buf) == 10);
|
||||
while (indent > 0) {
|
||||
if(indent < 10)
|
||||
buf[indent] = '\0';
|
||||
err = PyFile_WriteString(buf, f);
|
||||
if (err != 0)
|
||||
break;
|
||||
indent -= 10;
|
||||
}
|
||||
/* Write some spaces before the line */
|
||||
strcpy(buf, " ");
|
||||
assert (strlen(buf) == 10);
|
||||
while (indent > 0) {
|
||||
if(indent < 10)
|
||||
buf[indent] = '\0';
|
||||
err = PyFile_WriteString(buf, f);
|
||||
if (err != 0)
|
||||
break;
|
||||
indent -= 10;
|
||||
}
|
||||
|
||||
/* finally display the line */
|
||||
if (err == 0)
|
||||
err = PyFile_WriteObject(lineobj, f, Py_PRINT_RAW);
|
||||
Py_DECREF(lineobj);
|
||||
if (err == 0)
|
||||
err = PyFile_WriteString("\n", f);
|
||||
return err;
|
||||
/* finally display the line */
|
||||
if (err == 0)
|
||||
err = PyFile_WriteObject(lineobj, f, Py_PRINT_RAW);
|
||||
Py_DECREF(lineobj);
|
||||
if (err == 0)
|
||||
err = PyFile_WriteString("\n", f);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
tb_displayline(PyObject *f, const char *filename, int lineno, const char *name)
|
||||
{
|
||||
int err = 0;
|
||||
char linebuf[2000];
|
||||
int err = 0;
|
||||
char linebuf[2000];
|
||||
|
||||
if (filename == NULL || name == NULL)
|
||||
return -1;
|
||||
/* This is needed by Emacs' compile command */
|
||||
if (filename == NULL || name == NULL)
|
||||
return -1;
|
||||
/* This is needed by Emacs' compile command */
|
||||
#define FMT " File \"%.500s\", line %d, in %.500s\n"
|
||||
PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name);
|
||||
err = PyFile_WriteString(linebuf, f);
|
||||
if (err != 0)
|
||||
return err;
|
||||
return _Py_DisplaySourceLine(f, filename, lineno, 4);
|
||||
PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name);
|
||||
err = PyFile_WriteString(linebuf, f);
|
||||
if (err != 0)
|
||||
return err;
|
||||
return _Py_DisplaySourceLine(f, filename, lineno, 4);
|
||||
}
|
||||
|
||||
static int
|
||||
tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
|
||||
{
|
||||
int err = 0;
|
||||
long depth = 0;
|
||||
PyTracebackObject *tb1 = tb;
|
||||
while (tb1 != NULL) {
|
||||
depth++;
|
||||
tb1 = tb1->tb_next;
|
||||
}
|
||||
while (tb != NULL && err == 0) {
|
||||
if (depth <= limit) {
|
||||
err = tb_displayline(f,
|
||||
_PyUnicode_AsString(
|
||||
tb->tb_frame->f_code->co_filename),
|
||||
tb->tb_lineno,
|
||||
_PyUnicode_AsString(tb->tb_frame->f_code->co_name));
|
||||
}
|
||||
depth--;
|
||||
tb = tb->tb_next;
|
||||
if (err == 0)
|
||||
err = PyErr_CheckSignals();
|
||||
}
|
||||
return err;
|
||||
int err = 0;
|
||||
long depth = 0;
|
||||
PyTracebackObject *tb1 = tb;
|
||||
while (tb1 != NULL) {
|
||||
depth++;
|
||||
tb1 = tb1->tb_next;
|
||||
}
|
||||
while (tb != NULL && err == 0) {
|
||||
if (depth <= limit) {
|
||||
err = tb_displayline(f,
|
||||
_PyUnicode_AsString(
|
||||
tb->tb_frame->f_code->co_filename),
|
||||
tb->tb_lineno,
|
||||
_PyUnicode_AsString(tb->tb_frame->f_code->co_name));
|
||||
}
|
||||
depth--;
|
||||
tb = tb->tb_next;
|
||||
if (err == 0)
|
||||
err = PyErr_CheckSignals();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
#define PyTraceBack_LIMIT 1000
|
||||
|
|
@ -334,40 +334,40 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
|
|||
int
|
||||
PyTraceBack_Print(PyObject *v, PyObject *f)
|
||||
{
|
||||
int err;
|
||||
PyObject *limitv;
|
||||
long limit = PyTraceBack_LIMIT;
|
||||
int err;
|
||||
PyObject *limitv;
|
||||
long limit = PyTraceBack_LIMIT;
|
||||
|
||||
if (v == NULL)
|
||||
return 0;
|
||||
if (!PyTraceBack_Check(v)) {
|
||||
PyErr_BadInternalCall();
|
||||
return -1;
|
||||
}
|
||||
limitv = PySys_GetObject("tracebacklimit");
|
||||
if (limitv) {
|
||||
PyObject *exc_type, *exc_value, *exc_tb;
|
||||
if (v == NULL)
|
||||
return 0;
|
||||
if (!PyTraceBack_Check(v)) {
|
||||
PyErr_BadInternalCall();
|
||||
return -1;
|
||||
}
|
||||
limitv = PySys_GetObject("tracebacklimit");
|
||||
if (limitv) {
|
||||
PyObject *exc_type, *exc_value, *exc_tb;
|
||||
|
||||
PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
|
||||
limit = PyLong_AsLong(limitv);
|
||||
if (limit == -1 && PyErr_Occurred()) {
|
||||
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
||||
limit = PyTraceBack_LIMIT;
|
||||
}
|
||||
else {
|
||||
Py_XDECREF(exc_type);
|
||||
Py_XDECREF(exc_value);
|
||||
Py_XDECREF(exc_tb);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (limit <= 0) {
|
||||
limit = PyTraceBack_LIMIT;
|
||||
}
|
||||
PyErr_Restore(exc_type, exc_value, exc_tb);
|
||||
}
|
||||
err = PyFile_WriteString("Traceback (most recent call last):\n", f);
|
||||
if (!err)
|
||||
err = tb_printinternal((PyTracebackObject *)v, f, limit);
|
||||
return err;
|
||||
PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
|
||||
limit = PyLong_AsLong(limitv);
|
||||
if (limit == -1 && PyErr_Occurred()) {
|
||||
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
||||
limit = PyTraceBack_LIMIT;
|
||||
}
|
||||
else {
|
||||
Py_XDECREF(exc_type);
|
||||
Py_XDECREF(exc_value);
|
||||
Py_XDECREF(exc_tb);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (limit <= 0) {
|
||||
limit = PyTraceBack_LIMIT;
|
||||
}
|
||||
PyErr_Restore(exc_type, exc_value, exc_tb);
|
||||
}
|
||||
err = PyFile_WriteString("Traceback (most recent call last):\n", f);
|
||||
if (!err)
|
||||
err = tb_printinternal((PyTracebackObject *)v, f, limit);
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue