AppPkg/Applications/Python/Python-2.7.10: Initial Checkin part 1/5.

The Include, Parser, and Python directories from the cPython 2.7.10 distribution.
These files are unchanged and set the baseline for subsequent commits.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Daryl McDaniel <edk2-lists@mc2research.org>


git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18737 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Daryl McDaniel
2015-11-07 19:19:19 +00:00
committed by darylm503
parent 3535213aae
commit c8042e1076
145 changed files with 62620 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,911 @@
#include "Python.h"
#include "frameobject.h"
#define MODULE_NAME "_warnings"
PyDoc_STRVAR(warnings__doc__,
MODULE_NAME " provides basic warning filtering support.\n"
"It is a helper module to speed up interpreter start-up.");
/* Both 'filters' and 'onceregistry' can be set in warnings.py;
get_warnings_attr() will reset these variables accordingly. */
static PyObject *_filters; /* List */
static PyObject *_once_registry; /* Dict */
static PyObject *_default_action; /* String */
static int
check_matched(PyObject *obj, PyObject *arg)
{
PyObject *result;
int rc;
if (obj == Py_None)
return 1;
result = PyObject_CallMethod(obj, "match", "O", arg);
if (result == NULL)
return -1;
rc = PyObject_IsTrue(result);
Py_DECREF(result);
return rc;
}
/*
Returns a new reference.
A NULL return value can mean false or an error.
*/
static PyObject *
get_warnings_attr(const char *attr)
{
static PyObject *warnings_str = NULL;
PyObject *all_modules;
PyObject *warnings_module;
int result;
if (warnings_str == NULL) {
warnings_str = PyString_InternFromString("warnings");
if (warnings_str == NULL)
return NULL;
}
all_modules = PyImport_GetModuleDict();
result = PyDict_Contains(all_modules, warnings_str);
if (result == -1 || result == 0)
return NULL;
warnings_module = PyDict_GetItem(all_modules, warnings_str);
if (!PyObject_HasAttrString(warnings_module, attr))
return NULL;
return PyObject_GetAttrString(warnings_module, attr);
}
static PyObject *
get_once_registry(void)
{
PyObject *registry;
registry = get_warnings_attr("onceregistry");
if (registry == NULL) {
if (PyErr_Occurred())
return NULL;
return _once_registry;
}
Py_DECREF(_once_registry);
_once_registry = registry;
return registry;
}
static PyObject *
get_default_action(void)
{
PyObject *default_action;
default_action = get_warnings_attr("defaultaction");
if (default_action == NULL) {
if (PyErr_Occurred()) {
return NULL;
}
return _default_action;
}
Py_DECREF(_default_action);
_default_action = default_action;
return default_action;
}
/* The item is a borrowed reference. */
static const char *
get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno,
PyObject *module, PyObject **item)
{
PyObject *action;
Py_ssize_t i;
PyObject *warnings_filters;
warnings_filters = get_warnings_attr("filters");
if (warnings_filters == NULL) {
if (PyErr_Occurred())
return NULL;
}
else {
Py_DECREF(_filters);
_filters = warnings_filters;
}
if (!PyList_Check(_filters)) {
PyErr_SetString(PyExc_ValueError,
MODULE_NAME ".filters must be a list");
return NULL;
}
/* _filters could change while we are iterating over it. */
for (i = 0; i < PyList_GET_SIZE(_filters); i++) {
PyObject *tmp_item, *action, *msg, *cat, *mod, *ln_obj;
Py_ssize_t ln;
int is_subclass, good_msg, good_mod;
tmp_item = *item = PyList_GET_ITEM(_filters, i);
if (PyTuple_Size(tmp_item) != 5) {
PyErr_Format(PyExc_ValueError,
MODULE_NAME ".filters item %zd isn't a 5-tuple", i);
return NULL;
}
/* Python code: action, msg, cat, mod, ln = item */
action = PyTuple_GET_ITEM(tmp_item, 0);
msg = PyTuple_GET_ITEM(tmp_item, 1);
cat = PyTuple_GET_ITEM(tmp_item, 2);
mod = PyTuple_GET_ITEM(tmp_item, 3);
ln_obj = PyTuple_GET_ITEM(tmp_item, 4);
good_msg = check_matched(msg, text);
good_mod = check_matched(mod, module);
is_subclass = PyObject_IsSubclass(category, cat);
ln = PyInt_AsSsize_t(ln_obj);
if (good_msg == -1 || good_mod == -1 || is_subclass == -1 ||
(ln == -1 && PyErr_Occurred()))
return NULL;
if (good_msg && is_subclass && good_mod && (ln == 0 || lineno == ln))
return PyString_AsString(action);
}
action = get_default_action();
if (action != NULL) {
return PyString_AsString(action);
}
PyErr_SetString(PyExc_ValueError,
MODULE_NAME ".defaultaction not found");
return NULL;
}
static int
already_warned(PyObject *registry, PyObject *key, int should_set)
{
PyObject *already_warned;
if (key == NULL)
return -1;
already_warned = PyDict_GetItem(registry, key);
if (already_warned != NULL) {
int rc = PyObject_IsTrue(already_warned);
if (rc != 0)
return rc;
}
/* This warning wasn't found in the registry, set it. */
if (should_set)
return PyDict_SetItem(registry, key, Py_True);
return 0;
}
/* New reference. */
static PyObject *
normalize_module(PyObject *filename)
{
PyObject *module;
const char *mod_str;
Py_ssize_t len;
int rc = PyObject_IsTrue(filename);
if (rc == -1)
return NULL;
else if (rc == 0)
return PyString_FromString("<unknown>");
mod_str = PyString_AsString(filename);
if (mod_str == NULL)
return NULL;
len = PyString_Size(filename);
if (len < 0)
return NULL;
if (len >= 3 &&
strncmp(mod_str + (len - 3), ".py", 3) == 0) {
module = PyString_FromStringAndSize(mod_str, len-3);
}
else {
module = filename;
Py_INCREF(module);
}
return module;
}
static int
update_registry(PyObject *registry, PyObject *text, PyObject *category,
int add_zero)
{
PyObject *altkey, *zero = NULL;
int rc;
if (add_zero) {
zero = PyInt_FromLong(0);
if (zero == NULL)
return -1;
altkey = PyTuple_Pack(3, text, category, zero);
}
else
altkey = PyTuple_Pack(2, text, category);
rc = already_warned(registry, altkey, 1);
Py_XDECREF(zero);
Py_XDECREF(altkey);
return rc;
}
static void
show_warning(PyObject *filename, int lineno, PyObject *text, PyObject
*category, PyObject *sourceline)
{
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;
f_stderr = PySys_GetObject("stderr");
if (f_stderr == NULL) {
fprintf(stderr, "lost sys.stderr\n");
Py_DECREF(name);
return;
}
/* Print "filename:lineno: category: text\n" */
PyFile_WriteObject(filename, f_stderr, Py_PRINT_RAW);
PyFile_WriteString(lineno_str, f_stderr);
PyFile_WriteObject(name, f_stderr, Py_PRINT_RAW);
PyFile_WriteString(": ", f_stderr);
PyFile_WriteObject(text, f_stderr, Py_PRINT_RAW);
PyFile_WriteString("\n", f_stderr);
Py_XDECREF(name);
/* Print " source_line\n" */
if (sourceline) {
char *source_line_str = PyString_AS_STRING(sourceline);
while (*source_line_str == ' ' || *source_line_str == '\t' ||
*source_line_str == '\014')
source_line_str++;
PyFile_WriteString(source_line_str, f_stderr);
PyFile_WriteString("\n", f_stderr);
}
else
_Py_DisplaySourceLine(f_stderr, PyString_AS_STRING(filename),
lineno, 2);
PyErr_Clear();
}
static PyObject *
warn_explicit(PyObject *category, PyObject *message,
PyObject *filename, int lineno,
PyObject *module, PyObject *registry, PyObject *sourceline)
{
PyObject *key = NULL, *text = NULL, *result = NULL, *lineno_obj = NULL;
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;
}
/* Normalize module. */
if (module == NULL) {
module = normalize_module(filename);
if (module == NULL)
return NULL;
}
else
Py_INCREF(module);
/* Normalize message. */
Py_INCREF(message); /* DECREF'ed in cleanup. */
rc = PyObject_IsInstance(message, PyExc_Warning);
if (rc == -1) {
goto cleanup;
}
if (rc == 1) {
text = PyObject_Str(message);
if (text == NULL)
goto cleanup;
category = (PyObject*)message->ob_type;
}
else {
text = message;
message = PyObject_CallFunction(category, "O", message);
if (message == NULL)
goto cleanup;
}
lineno_obj = PyInt_FromLong(lineno);
if (lineno_obj == NULL)
goto cleanup;
/* Create key. */
key = PyTuple_Pack(3, text, category, lineno_obj);
if (key == NULL)
goto cleanup;
if ((registry != NULL) && (registry != Py_None)) {
rc = already_warned(registry, key, 0);
if (rc == -1)
goto cleanup;
else if (rc == 1)
goto return_none;
/* Else this warning hasn't been generated before. */
}
action = get_filter(category, text, lineno, module, &item);
if (action == NULL)
goto cleanup;
if (strcmp(action, "error") == 0) {
PyErr_SetObject(category, message);
goto cleanup;
}
/* Store in the registry that we've been here, *except* when the action
is "always". */
rc = 0;
if (strcmp(action, "always") != 0) {
if (registry != NULL && registry != Py_None &&
PyDict_SetItem(registry, key, Py_True) < 0)
goto cleanup;
else if (strcmp(action, "ignore") == 0)
goto return_none;
else if (strcmp(action, "once") == 0) {
if (registry == NULL || registry == Py_None) {
registry = get_once_registry();
if (registry == NULL)
goto cleanup;
}
/* _once_registry[(text, category)] = 1 */
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);
}
else if (strcmp(action, "default") != 0) {
PyObject *to_str = PyObject_Str(item);
const char *err_str = "???";
if (to_str != NULL)
err_str = PyString_AS_STRING(to_str);
PyErr_Format(PyExc_RuntimeError,
"Unrecognized action (%s) in warnings.filters:\n %s",
action, err_str);
Py_XDECREF(to_str);
goto cleanup;
}
}
if (rc == 1) /* Already warned for this module. */
goto return_none;
if (rc == 0) {
PyObject *show_fxn = get_warnings_attr("showwarning");
if (show_fxn == NULL) {
if (PyErr_Occurred())
goto cleanup;
show_warning(filename, lineno, text, category, sourceline);
}
else {
PyObject *res;
if (!PyMethod_Check(show_fxn) && !PyFunction_Check(show_fxn)) {
PyErr_SetString(PyExc_TypeError,
"warnings.showwarning() must be set to a "
"function or method");
Py_DECREF(show_fxn);
goto cleanup;
}
res = PyObject_CallFunctionObjArgs(show_fxn, message, category,
filename, lineno_obj,
NULL);
Py_DECREF(show_fxn);
Py_XDECREF(res);
if (res == NULL)
goto cleanup;
}
}
else /* if (rc == -1) */
goto cleanup;
return_none:
result = Py_None;
Py_INCREF(result);
cleanup:
Py_XDECREF(key);
Py_XDECREF(text);
Py_XDECREF(lineno_obj);
Py_DECREF(module);
Py_XDECREF(message);
return result; /* Py_None or NULL. */
}
/* filename, module, and registry are new refs, globals is borrowed */
/* Returns 0 on error (no new refs), 1 on success */
static int
setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
PyObject **module, PyObject **registry)
{
PyObject *globals;
/* Setup globals and lineno. */
PyFrameObject *f = PyThreadState_GET()->frame;
while (--stack_level > 0 && f != NULL)
f = f->f_back;
if (f == NULL) {
globals = PyThreadState_Get()->interp->sysdict;
*lineno = 1;
}
else {
globals = f->f_globals;
*lineno = PyFrame_GetLineNumber(f);
}
*module = NULL;
/* Setup registry. */
assert(globals != NULL);
assert(PyDict_Check(globals));
*registry = PyDict_GetItemString(globals, "__warningregistry__");
if (*registry == NULL) {
int rc;
*registry = PyDict_New();
if (*registry == NULL)
return 0;
rc = PyDict_SetItemString(globals, "__warningregistry__", *registry);
if (rc < 0)
goto handle_error;
}
else
Py_INCREF(*registry);
/* Setup module. */
*module = PyDict_GetItemString(globals, "__name__");
if (*module == NULL) {
*module = PyString_FromString("<string>");
if (*module == NULL)
goto handle_error;
}
else
Py_INCREF(*module);
/* Setup filename. */
*filename = PyDict_GetItemString(globals, "__file__");
if (*filename != NULL && PyString_Check(*filename)) {
Py_ssize_t len = PyString_Size(*filename);
const char *file_str = PyString_AsString(*filename);
if (file_str == NULL || (len < 0 && PyErr_Occurred()))
goto handle_error;
/* if filename.lower().endswith((".pyc", ".pyo")): */
if (len >= 4 &&
file_str[len-4] == '.' &&
tolower(file_str[len-3]) == 'p' &&
tolower(file_str[len-2]) == 'y' &&
(tolower(file_str[len-1]) == 'c' ||
tolower(file_str[len-1]) == 'o'))
{
*filename = PyString_FromStringAndSize(file_str, len-1);
if (*filename == NULL)
goto handle_error;
}
else
Py_INCREF(*filename);
}
else {
const char *module_str = PyString_AsString(*module);
*filename = NULL;
if (module_str && strcmp(module_str, "__main__") == 0) {
PyObject *argv = PySys_GetObject("argv");
if (argv != NULL && PyList_Size(argv) > 0) {
int is_true;
*filename = PyList_GetItem(argv, 0);
Py_INCREF(*filename);
/* If sys.argv[0] is false, then use '__main__'. */
is_true = PyObject_IsTrue(*filename);
if (is_true < 0) {
Py_DECREF(*filename);
goto handle_error;
}
else if (!is_true) {
Py_DECREF(*filename);
*filename = PyString_FromString("__main__");
if (*filename == NULL)
goto handle_error;
}
}
else {
/* embedded interpreters don't have sys.argv, see bug #839151 */
*filename = PyString_FromString("__main__");
if (*filename == NULL)
goto handle_error;
}
}
if (*filename == NULL) {
*filename = *module;
Py_INCREF(*filename);
}
}
return 1;
handle_error:
/* filename not XDECREF'ed here as there is no way to jump here with a
dangling reference. */
Py_XDECREF(*registry);
Py_XDECREF(*module);
return 0;
}
static PyObject *
get_category(PyObject *message, PyObject *category)
{
int rc;
/* Get category. */
rc = PyObject_IsInstance(message, PyExc_Warning);
if (rc == -1)
return NULL;
if (rc == 1)
category = (PyObject*)message->ob_type;
else if (category == NULL)
category = PyExc_UserWarning;
/* Validate category. */
rc = PyObject_IsSubclass(category, PyExc_Warning);
if (rc == -1)
return NULL;
if (rc == 0) {
PyErr_SetString(PyExc_ValueError,
"category is not a subclass of Warning");
return NULL;
}
return category;
}
static PyObject *
do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level)
{
PyObject *filename, *module, *registry, *res;
int lineno;
if (!setup_context(stack_level, &filename, &lineno, &module, &registry))
return NULL;
res = warn_explicit(category, message, filename, lineno, module, registry,
NULL);
Py_DECREF(filename);
Py_DECREF(registry);
Py_DECREF(module);
return res;
}
static PyObject *
warnings_warn(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kw_list[] = { "message", "category", "stacklevel", 0 };
PyObject *message, *category = NULL;
Py_ssize_t stack_level = 1;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list,
&message, &category, &stack_level))
return NULL;
category = get_category(message, category);
if (category == NULL)
return NULL;
return do_warn(message, category, stack_level);
}
static PyObject *
warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kwd_list[] = {"message", "category", "filename", "lineno",
"module", "registry", "module_globals", 0};
PyObject *message;
PyObject *category;
PyObject *filename;
int lineno;
PyObject *module = NULL;
PyObject *registry = NULL;
PyObject *module_globals = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOOi|OOO:warn_explicit",
kwd_list, &message, &category, &filename, &lineno, &module,
&registry, &module_globals))
return NULL;
if (module_globals) {
static PyObject *get_source_name = NULL;
static PyObject *splitlines_name = NULL;
PyObject *loader;
PyObject *module_name;
PyObject *source;
PyObject *source_list;
PyObject *source_line;
PyObject *returned;
if (get_source_name == NULL) {
get_source_name = PyString_InternFromString("get_source");
if (!get_source_name)
return NULL;
}
if (splitlines_name == NULL) {
splitlines_name = PyString_InternFromString("splitlines");
if (!splitlines_name)
return NULL;
}
/* Check/get the requisite pieces needed for the loader. */
loader = PyDict_GetItemString(module_globals, "__loader__");
module_name = PyDict_GetItemString(module_globals, "__name__");
if (loader == NULL || module_name == NULL)
goto standard_call;
/* Make sure the loader implements the optional get_source() method. */
if (!PyObject_HasAttrString(loader, "get_source"))
goto standard_call;
/* Call get_source() to get the source code. */
source = PyObject_CallMethodObjArgs(loader, get_source_name,
module_name, NULL);
if (!source)
return NULL;
else if (source == Py_None) {
Py_DECREF(Py_None);
goto standard_call;
}
/* Split the source into lines. */
source_list = PyObject_CallMethodObjArgs(source, splitlines_name,
NULL);
Py_DECREF(source);
if (!source_list)
return NULL;
/* Get the source line. */
source_line = PyList_GetItem(source_list, lineno-1);
if (!source_line) {
Py_DECREF(source_list);
return NULL;
}
/* Handle the warning. */
returned = warn_explicit(category, message, filename, lineno, module,
registry, source_line);
Py_DECREF(source_list);
return returned;
}
standard_call:
return warn_explicit(category, message, filename, lineno, module,
registry, NULL);
}
/* Function to issue a warning message; may raise an exception. */
int
PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level)
{
PyObject *res;
PyObject *message = PyString_FromString(text);
if (message == NULL)
return -1;
if (category == NULL)
category = PyExc_RuntimeWarning;
res = do_warn(message, category, stack_level);
Py_DECREF(message);
if (res == NULL)
return -1;
Py_DECREF(res);
return 0;
}
/* PyErr_Warn is only for backwards compatibility and will be removed.
Use PyErr_WarnEx instead. */
#undef PyErr_Warn
PyAPI_FUNC(int)
PyErr_Warn(PyObject *category, char *text)
{
return PyErr_WarnEx(category, text, 1);
}
/* Warning with explicit origin */
int
PyErr_WarnExplicit(PyObject *category, const char *text,
const char *filename_str, int lineno,
const char *module_str, PyObject *registry)
{
PyObject *res;
PyObject *message = PyString_FromString(text);
PyObject *filename = PyString_FromString(filename_str);
PyObject *module = NULL;
int ret = -1;
if (message == NULL || filename == NULL)
goto exit;
if (module_str != NULL) {
module = PyString_FromString(module_str);
if (module == NULL)
goto exit;
}
if (category == NULL)
category = PyExc_RuntimeWarning;
res = warn_explicit(category, message, filename, lineno, module, registry,
NULL);
if (res == NULL)
goto exit;
Py_DECREF(res);
ret = 0;
exit:
Py_XDECREF(message);
Py_XDECREF(module);
Py_XDECREF(filename);
return ret;
}
PyDoc_STRVAR(warn_doc,
"Issue a warning, or maybe ignore it or raise an exception.");
PyDoc_STRVAR(warn_explicit_doc,
"Low-level inferface to warnings functionality.");
static PyMethodDef warnings_functions[] = {
{"warn", (PyCFunction)warnings_warn, METH_VARARGS | METH_KEYWORDS,
warn_doc},
{"warn_explicit", (PyCFunction)warnings_warn_explicit,
METH_VARARGS | METH_KEYWORDS, warn_explicit_doc},
/* XXX(brett.cannon): add showwarning? */
/* XXX(brett.cannon): Reasonable to add formatwarning? */
{NULL, NULL} /* sentinel */
};
static PyObject *
create_filter(PyObject *category, const char *action)
{
static PyObject *ignore_str = NULL;
static PyObject *error_str = NULL;
static PyObject *default_str = NULL;
PyObject *action_obj = NULL;
PyObject *lineno, *result;
if (!strcmp(action, "ignore")) {
if (ignore_str == NULL) {
ignore_str = PyString_InternFromString("ignore");
if (ignore_str == NULL)
return NULL;
}
action_obj = ignore_str;
}
else if (!strcmp(action, "error")) {
if (error_str == NULL) {
error_str = PyString_InternFromString("error");
if (error_str == NULL)
return NULL;
}
action_obj = error_str;
}
else if (!strcmp(action, "default")) {
if (default_str == NULL) {
default_str = PyString_InternFromString("default");
if (default_str == NULL)
return NULL;
}
action_obj = default_str;
}
else {
Py_FatalError("unknown action");
}
/* This assumes the line number is zero for now. */
lineno = PyInt_FromLong(0);
if (lineno == NULL)
return NULL;
result = PyTuple_Pack(5, action_obj, Py_None, category, Py_None, lineno);
Py_DECREF(lineno);
return result;
}
static PyObject *
init_filters(void)
{
/* Don't silence DeprecationWarning if -3 or -Q were used. */
PyObject *filters = PyList_New(Py_Py3kWarningFlag ||
Py_DivisionWarningFlag ? 3 : 4);
unsigned int pos = 0; /* Post-incremented in each use. */
unsigned int x;
const char *bytes_action;
if (filters == NULL)
return NULL;
/* If guard changes, make sure to update 'filters' initialization above. */
if (!Py_Py3kWarningFlag && !Py_DivisionWarningFlag) {
PyList_SET_ITEM(filters, pos++,
create_filter(PyExc_DeprecationWarning, "ignore"));
}
PyList_SET_ITEM(filters, pos++,
create_filter(PyExc_PendingDeprecationWarning, "ignore"));
PyList_SET_ITEM(filters, pos++,
create_filter(PyExc_ImportWarning, "ignore"));
if (Py_BytesWarningFlag > 1)
bytes_action = "error";
else if (Py_BytesWarningFlag)
bytes_action = "default";
else
bytes_action = "ignore";
PyList_SET_ITEM(filters, pos++, create_filter(PyExc_BytesWarning,
bytes_action));
for (x = 0; x < pos; x += 1) {
if (PyList_GET_ITEM(filters, x) == NULL) {
Py_DECREF(filters);
return NULL;
}
}
return filters;
}
PyMODINIT_FUNC
_PyWarnings_Init(void)
{
PyObject *m;
m = Py_InitModule3(MODULE_NAME, warnings_functions, warnings__doc__);
if (m == NULL)
return;
_filters = init_filters();
if (_filters == NULL)
return;
Py_INCREF(_filters);
if (PyModule_AddObject(m, "filters", _filters) < 0)
return;
_once_registry = PyDict_New();
if (_once_registry == NULL)
return;
Py_INCREF(_once_registry);
if (PyModule_AddObject(m, "once_registry", _once_registry) < 0)
return;
_default_action = PyString_FromString("default");
if (_default_action == NULL)
return;
Py_INCREF(_default_action);
if (PyModule_AddObject(m, "default_action", _default_action) < 0)
return;
}

View File

@ -0,0 +1,64 @@
#include "Python.h"
#include "asdl.h"
asdl_seq *
asdl_seq_new(int size, PyArena *arena)
{
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 if size can be added safely */
if (n > PY_SIZE_MAX - sizeof(asdl_seq)) {
PyErr_NoMemory();
return NULL;
}
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;
}
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);
/* 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;
}
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;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,889 @@
/* ------------------------------------------------------------------------
Python Codec Registry and support functions
Written by Marc-Andre Lemburg (mal@lemburg.com).
Copyright (c) Corporation for National Research Initiatives.
------------------------------------------------------------------------ */
#include "Python.h"
#include <ctype.h>
/* --- Codec Registry ----------------------------------------------------- */
/* Import the standard encodings package which will register the first
codec search function.
This is done in a lazy way so that the Unicode implementation does
not downgrade startup time of scripts not needing it.
ImportErrors are silently ignored by this function. Only one try is
made.
*/
static int _PyCodecRegistry_Init(void); /* Forward */
int PyCodec_Register(PyObject *search_function)
{
PyInterpreterState *interp = PyThreadState_GET()->interp;
if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
goto onError;
if (search_function == NULL) {
PyErr_BadArgument();
goto onError;
}
if (!PyCallable_Check(search_function)) {
PyErr_SetString(PyExc_TypeError, "argument must be callable");
goto onError;
}
return PyList_Append(interp->codec_search_path, search_function);
onError:
return -1;
}
/* Convert a string to a normalized Python string: all characters are
converted to lower case, spaces are replaced with underscores. */
static
PyObject *normalizestring(const char *string)
{
register size_t i;
size_t len = strlen(string);
char *p;
PyObject *v;
if (len > PY_SSIZE_T_MAX) {
PyErr_SetString(PyExc_OverflowError, "string is too large");
return NULL;
}
v = PyString_FromStringAndSize(NULL, len);
if (v == NULL)
return NULL;
p = PyString_AS_STRING(v);
for (i = 0; i < len; i++) {
register char ch = string[i];
if (ch == ' ')
ch = '-';
else
ch = Py_TOLOWER(Py_CHARMASK(ch));
p[i] = ch;
}
return v;
}
/* Lookup the given encoding and return a tuple providing the codec
facilities.
The encoding string is looked up converted to all lower-case
characters. This makes encodings looked up through this mechanism
effectively case-insensitive.
If no codec is found, a LookupError is set and NULL returned.
As side effect, this tries to load the encodings package, if not
yet done. This is part of the lazy load strategy for the encodings
package.
*/
PyObject *_PyCodec_Lookup(const char *encoding)
{
PyInterpreterState *interp;
PyObject *result, *args = NULL, *v;
Py_ssize_t i, len;
if (encoding == NULL) {
PyErr_BadArgument();
goto onError;
}
interp = PyThreadState_GET()->interp;
if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
goto onError;
/* Convert the encoding to a normalized Python string: all
characters are converted to lower case, spaces and hyphens are
replaced with underscores. */
v = normalizestring(encoding);
if (v == NULL)
goto onError;
PyString_InternInPlace(&v);
/* First, try to lookup the name in the registry dictionary */
result = PyDict_GetItem(interp->codec_search_cache, v);
if (result != NULL) {
Py_INCREF(result);
Py_DECREF(v);
return result;
}
/* Next, scan the search functions in order of registration */
args = PyTuple_New(1);
if (args == NULL)
goto onError;
PyTuple_SET_ITEM(args,0,v);
len = PyList_Size(interp->codec_search_path);
if (len < 0)
goto onError;
if (len == 0) {
PyErr_SetString(PyExc_LookupError,
"no codec search functions registered: "
"can't find encoding");
goto onError;
}
for (i = 0; i < len; i++) {
PyObject *func;
func = PyList_GetItem(interp->codec_search_path, i);
if (func == NULL)
goto onError;
result = PyEval_CallObject(func, args);
if (result == NULL)
goto onError;
if (result == Py_None) {
Py_DECREF(result);
continue;
}
if (!PyTuple_Check(result) || PyTuple_GET_SIZE(result) != 4) {
PyErr_SetString(PyExc_TypeError,
"codec search functions must return 4-tuples");
Py_DECREF(result);
goto onError;
}
break;
}
if (i == len) {
/* XXX Perhaps we should cache misses too ? */
PyErr_Format(PyExc_LookupError,
"unknown encoding: %s", encoding);
goto onError;
}
/* Cache and return the result */
PyDict_SetItem(interp->codec_search_cache, v, result);
Py_DECREF(args);
return result;
onError:
Py_XDECREF(args);
return NULL;
}
static
PyObject *args_tuple(PyObject *object,
const char *errors)
{
PyObject *args;
args = PyTuple_New(1 + (errors != NULL));
if (args == NULL)
return NULL;
Py_INCREF(object);
PyTuple_SET_ITEM(args,0,object);
if (errors) {
PyObject *v;
v = PyString_FromString(errors);
if (v == NULL) {
Py_DECREF(args);
return NULL;
}
PyTuple_SET_ITEM(args, 1, v);
}
return args;
}
/* Helper function to get a codec item */
static
PyObject *codec_getitem(const char *encoding, int index)
{
PyObject *codecs;
PyObject *v;
codecs = _PyCodec_Lookup(encoding);
if (codecs == NULL)
return NULL;
v = PyTuple_GET_ITEM(codecs, index);
Py_DECREF(codecs);
Py_INCREF(v);
return v;
}
/* Helper function to create an incremental codec. */
static
PyObject *codec_getincrementalcodec(const char *encoding,
const char *errors,
const char *attrname)
{
PyObject *codecs, *ret, *inccodec;
codecs = _PyCodec_Lookup(encoding);
if (codecs == NULL)
return NULL;
inccodec = PyObject_GetAttrString(codecs, attrname);
Py_DECREF(codecs);
if (inccodec == NULL)
return NULL;
if (errors)
ret = PyObject_CallFunction(inccodec, "s", errors);
else
ret = PyObject_CallFunction(inccodec, NULL);
Py_DECREF(inccodec);
return ret;
}
/* Helper function to create a stream codec. */
static
PyObject *codec_getstreamcodec(const char *encoding,
PyObject *stream,
const char *errors,
const int index)
{
PyObject *codecs, *streamcodec, *codeccls;
codecs = _PyCodec_Lookup(encoding);
if (codecs == NULL)
return NULL;
codeccls = PyTuple_GET_ITEM(codecs, index);
if (errors != NULL)
streamcodec = PyObject_CallFunction(codeccls, "Os", stream, errors);
else
streamcodec = PyObject_CallFunction(codeccls, "O", stream);
Py_DECREF(codecs);
return streamcodec;
}
/* Convenience APIs to query the Codec registry.
All APIs return a codec object with incremented refcount.
*/
PyObject *PyCodec_Encoder(const char *encoding)
{
return codec_getitem(encoding, 0);
}
PyObject *PyCodec_Decoder(const char *encoding)
{
return codec_getitem(encoding, 1);
}
PyObject *PyCodec_IncrementalEncoder(const char *encoding,
const char *errors)
{
return codec_getincrementalcodec(encoding, errors, "incrementalencoder");
}
PyObject *PyCodec_IncrementalDecoder(const char *encoding,
const char *errors)
{
return codec_getincrementalcodec(encoding, errors, "incrementaldecoder");
}
PyObject *PyCodec_StreamReader(const char *encoding,
PyObject *stream,
const char *errors)
{
return codec_getstreamcodec(encoding, stream, errors, 2);
}
PyObject *PyCodec_StreamWriter(const char *encoding,
PyObject *stream,
const char *errors)
{
return codec_getstreamcodec(encoding, stream, errors, 3);
}
/* Encode an object (e.g. an Unicode object) using the given encoding
and return the resulting encoded object (usually a Python string).
errors is passed to the encoder factory as argument if non-NULL. */
PyObject *PyCodec_Encode(PyObject *object,
const char *encoding,
const char *errors)
{
PyObject *encoder = NULL;
PyObject *args = NULL, *result = NULL;
PyObject *v;
encoder = PyCodec_Encoder(encoding);
if (encoder == NULL)
goto onError;
args = args_tuple(object, errors);
if (args == NULL)
goto onError;
result = PyEval_CallObject(encoder,args);
if (result == NULL)
goto onError;
if (!PyTuple_Check(result) ||
PyTuple_GET_SIZE(result) != 2) {
PyErr_SetString(PyExc_TypeError,
"encoder must return a tuple (object,integer)");
goto onError;
}
v = PyTuple_GET_ITEM(result,0);
Py_INCREF(v);
/* We don't check or use the second (integer) entry. */
Py_DECREF(args);
Py_DECREF(encoder);
Py_DECREF(result);
return v;
onError:
Py_XDECREF(result);
Py_XDECREF(args);
Py_XDECREF(encoder);
return NULL;
}
/* Decode an object (usually a Python string) using the given encoding
and return an equivalent object (e.g. an Unicode object).
errors is passed to the decoder factory as argument if non-NULL. */
PyObject *PyCodec_Decode(PyObject *object,
const char *encoding,
const char *errors)
{
PyObject *decoder = NULL;
PyObject *args = NULL, *result = NULL;
PyObject *v;
decoder = PyCodec_Decoder(encoding);
if (decoder == NULL)
goto onError;
args = args_tuple(object, errors);
if (args == NULL)
goto onError;
result = PyEval_CallObject(decoder,args);
if (result == NULL)
goto onError;
if (!PyTuple_Check(result) ||
PyTuple_GET_SIZE(result) != 2) {
PyErr_SetString(PyExc_TypeError,
"decoder must return a tuple (object,integer)");
goto onError;
}
v = PyTuple_GET_ITEM(result,0);
Py_INCREF(v);
/* We don't check or use the second (integer) entry. */
Py_DECREF(args);
Py_DECREF(decoder);
Py_DECREF(result);
return v;
onError:
Py_XDECREF(args);
Py_XDECREF(decoder);
Py_XDECREF(result);
return NULL;
}
/* Register the error handling callback function error under the name
name. This function will be called by the codec when it encounters
an unencodable characters/undecodable bytes and doesn't know the
callback name, when name is specified as the error parameter
in the call to the encode/decode function.
Return 0 on success, -1 on error */
int PyCodec_RegisterError(const char *name, PyObject *error)
{
PyInterpreterState *interp = PyThreadState_GET()->interp;
if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
return -1;
if (!PyCallable_Check(error)) {
PyErr_SetString(PyExc_TypeError, "handler must be callable");
return -1;
}
return PyDict_SetItemString(interp->codec_error_registry,
(char *)name, error);
}
/* Lookup the error handling callback function registered under the
name error. As a special case NULL can be passed, in which case
the error handling callback for strict encoding will be returned. */
PyObject *PyCodec_LookupError(const char *name)
{
PyObject *handler = NULL;
PyInterpreterState *interp = PyThreadState_GET()->interp;
if (interp->codec_search_path == NULL && _PyCodecRegistry_Init())
return NULL;
if (name==NULL)
name = "strict";
handler = PyDict_GetItemString(interp->codec_error_registry, (char *)name);
if (!handler)
PyErr_Format(PyExc_LookupError, "unknown error handler name '%.400s'", name);
else
Py_INCREF(handler);
return handler;
}
static void wrong_exception_type(PyObject *exc)
{
PyObject *type = PyObject_GetAttrString(exc, "__class__");
if (type != NULL) {
PyObject *name = PyObject_GetAttrString(type, "__name__");
Py_DECREF(type);
if (name != NULL) {
PyObject *string = PyObject_Str(name);
Py_DECREF(name);
if (string != NULL) {
PyErr_Format(PyExc_TypeError,
"don't know how to handle %.400s in error callback",
PyString_AS_STRING(string));
Py_DECREF(string);
}
}
}
}
PyObject *PyCodec_StrictErrors(PyObject *exc)
{
if (PyExceptionInstance_Check(exc))
PyErr_SetObject(PyExceptionInstance_Class(exc), exc);
else
PyErr_SetString(PyExc_TypeError, "codec must pass exception instance");
return NULL;
}
#ifdef Py_USING_UNICODE
PyObject *PyCodec_IgnoreErrors(PyObject *exc)
{
Py_ssize_t end;
if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) {
if (PyUnicodeEncodeError_GetEnd(exc, &end))
return NULL;
}
else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) {
if (PyUnicodeDecodeError_GetEnd(exc, &end))
return NULL;
}
else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) {
if (PyUnicodeTranslateError_GetEnd(exc, &end))
return NULL;
}
else {
wrong_exception_type(exc);
return NULL;
}
/* ouch: passing NULL, 0, pos gives None instead of u'' */
return Py_BuildValue("(u#n)", &end, 0, end);
}
PyObject *PyCodec_ReplaceErrors(PyObject *exc)
{
PyObject *restuple;
Py_ssize_t start;
Py_ssize_t end;
Py_ssize_t i;
if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) {
PyObject *res;
Py_UNICODE *p;
if (PyUnicodeEncodeError_GetStart(exc, &start))
return NULL;
if (PyUnicodeEncodeError_GetEnd(exc, &end))
return NULL;
res = PyUnicode_FromUnicode(NULL, end-start);
if (res == NULL)
return NULL;
for (p = PyUnicode_AS_UNICODE(res), i = start;
i<end; ++p, ++i)
*p = '?';
restuple = Py_BuildValue("(On)", res, end);
Py_DECREF(res);
return restuple;
}
else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) {
Py_UNICODE res = Py_UNICODE_REPLACEMENT_CHARACTER;
if (PyUnicodeDecodeError_GetEnd(exc, &end))
return NULL;
return Py_BuildValue("(u#n)", &res, (Py_ssize_t)1, end);
}
else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) {
PyObject *res;
Py_UNICODE *p;
if (PyUnicodeTranslateError_GetStart(exc, &start))
return NULL;
if (PyUnicodeTranslateError_GetEnd(exc, &end))
return NULL;
res = PyUnicode_FromUnicode(NULL, end-start);
if (res == NULL)
return NULL;
for (p = PyUnicode_AS_UNICODE(res), i = start;
i<end; ++p, ++i)
*p = Py_UNICODE_REPLACEMENT_CHARACTER;
restuple = Py_BuildValue("(On)", res, end);
Py_DECREF(res);
return restuple;
}
else {
wrong_exception_type(exc);
return NULL;
}
}
PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc)
{
if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) {
PyObject *restuple;
PyObject *object;
Py_ssize_t start;
Py_ssize_t end;
PyObject *res;
Py_UNICODE *p;
Py_UNICODE *startp;
Py_UNICODE *e;
Py_UNICODE *outp;
Py_ssize_t ressize;
if (PyUnicodeEncodeError_GetStart(exc, &start))
return NULL;
if (PyUnicodeEncodeError_GetEnd(exc, &end))
return NULL;
if (!(object = PyUnicodeEncodeError_GetObject(exc)))
return NULL;
startp = PyUnicode_AS_UNICODE(object);
if (end - start > PY_SSIZE_T_MAX / (2+7+1)) {
end = start + PY_SSIZE_T_MAX / (2+7+1);
#ifndef Py_UNICODE_WIDE
if (0xD800 <= startp[end - 1] && startp[end - 1] <= 0xDBFF)
end--;
#endif
}
e = startp + end;
for (p = startp+start, ressize = 0; p < e;) {
Py_UCS4 ch = *p++;
#ifndef Py_UNICODE_WIDE
if ((0xD800 <= ch && ch <= 0xDBFF) &&
(p < e) &&
(0xDC00 <= *p && *p <= 0xDFFF)) {
ch = ((((ch & 0x03FF) << 10) |
((Py_UCS4)*p++ & 0x03FF)) + 0x10000);
}
#endif
if (ch < 10)
ressize += 2+1+1;
else if (ch < 100)
ressize += 2+2+1;
else if (ch < 1000)
ressize += 2+3+1;
else if (ch < 10000)
ressize += 2+4+1;
else if (ch < 100000)
ressize += 2+5+1;
else if (ch < 1000000)
ressize += 2+6+1;
else
ressize += 2+7+1;
}
/* allocate replacement */
res = PyUnicode_FromUnicode(NULL, ressize);
if (res == NULL) {
Py_DECREF(object);
return NULL;
}
/* generate replacement */
for (p = startp+start, outp = PyUnicode_AS_UNICODE(res); p < e;) {
int digits;
int base;
Py_UCS4 ch = *p++;
#ifndef Py_UNICODE_WIDE
if ((0xD800 <= ch && ch <= 0xDBFF) &&
(p < startp+end) &&
(0xDC00 <= *p && *p <= 0xDFFF)) {
ch = ((((ch & 0x03FF) << 10) |
((Py_UCS4)*p++ & 0x03FF)) + 0x10000);
}
#endif
*outp++ = '&';
*outp++ = '#';
if (ch < 10) {
digits = 1;
base = 1;
}
else if (ch < 100) {
digits = 2;
base = 10;
}
else if (ch < 1000) {
digits = 3;
base = 100;
}
else if (ch < 10000) {
digits = 4;
base = 1000;
}
else if (ch < 100000) {
digits = 5;
base = 10000;
}
else if (ch < 1000000) {
digits = 6;
base = 100000;
}
else {
digits = 7;
base = 1000000;
}
while (digits-->0) {
*outp++ = '0' + ch/base;
ch %= base;
base /= 10;
}
*outp++ = ';';
}
restuple = Py_BuildValue("(On)", res, end);
Py_DECREF(res);
Py_DECREF(object);
return restuple;
}
else {
wrong_exception_type(exc);
return NULL;
}
}
static Py_UNICODE hexdigits[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc)
{
if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) {
PyObject *restuple;
PyObject *object;
Py_ssize_t start;
Py_ssize_t end;
PyObject *res;
Py_UNICODE *p;
Py_UNICODE *startp;
Py_UNICODE *outp;
Py_ssize_t ressize;
if (PyUnicodeEncodeError_GetStart(exc, &start))
return NULL;
if (PyUnicodeEncodeError_GetEnd(exc, &end))
return NULL;
if (!(object = PyUnicodeEncodeError_GetObject(exc)))
return NULL;
if (end - start > PY_SSIZE_T_MAX / (1+1+8))
end = start + PY_SSIZE_T_MAX / (1+1+8);
startp = PyUnicode_AS_UNICODE(object);
for (p = startp+start, ressize = 0; p < startp+end; ++p) {
#ifdef Py_UNICODE_WIDE
if (*p >= 0x00010000)
ressize += 1+1+8;
else
#endif
if (*p >= 0x100) {
ressize += 1+1+4;
}
else
ressize += 1+1+2;
}
res = PyUnicode_FromUnicode(NULL, ressize);
if (res == NULL) {
Py_DECREF(object);
return NULL;
}
for (p = startp+start, outp = PyUnicode_AS_UNICODE(res);
p < startp+end; ++p) {
Py_UNICODE c = *p;
*outp++ = '\\';
#ifdef Py_UNICODE_WIDE
if (c >= 0x00010000) {
*outp++ = 'U';
*outp++ = hexdigits[(c>>28)&0xf];
*outp++ = hexdigits[(c>>24)&0xf];
*outp++ = hexdigits[(c>>20)&0xf];
*outp++ = hexdigits[(c>>16)&0xf];
*outp++ = hexdigits[(c>>12)&0xf];
*outp++ = hexdigits[(c>>8)&0xf];
}
else
#endif
if (c >= 0x100) {
*outp++ = 'u';
*outp++ = hexdigits[(c>>12)&0xf];
*outp++ = hexdigits[(c>>8)&0xf];
}
else
*outp++ = 'x';
*outp++ = hexdigits[(c>>4)&0xf];
*outp++ = hexdigits[c&0xf];
}
restuple = Py_BuildValue("(On)", res, end);
Py_DECREF(res);
Py_DECREF(object);
return restuple;
}
else {
wrong_exception_type(exc);
return NULL;
}
}
#endif
static PyObject *strict_errors(PyObject *self, PyObject *exc)
{
return PyCodec_StrictErrors(exc);
}
#ifdef Py_USING_UNICODE
static PyObject *ignore_errors(PyObject *self, PyObject *exc)
{
return PyCodec_IgnoreErrors(exc);
}
static PyObject *replace_errors(PyObject *self, PyObject *exc)
{
return PyCodec_ReplaceErrors(exc);
}
static PyObject *xmlcharrefreplace_errors(PyObject *self, PyObject *exc)
{
return PyCodec_XMLCharRefReplaceErrors(exc);
}
static PyObject *backslashreplace_errors(PyObject *self, PyObject *exc)
{
return PyCodec_BackslashReplaceErrors(exc);
}
#endif
static int _PyCodecRegistry_Init(void)
{
static struct {
char *name;
PyMethodDef def;
} methods[] =
{
{
"strict",
{
"strict_errors",
strict_errors,
METH_O,
PyDoc_STR("Implements the 'strict' error handling, which "
"raises a UnicodeError on coding errors.")
}
},
#ifdef Py_USING_UNICODE
{
"ignore",
{
"ignore_errors",
ignore_errors,
METH_O,
PyDoc_STR("Implements the 'ignore' error handling, which "
"ignores malformed data and continues.")
}
},
{
"replace",
{
"replace_errors",
replace_errors,
METH_O,
PyDoc_STR("Implements the 'replace' error handling, which "
"replaces malformed data with a replacement marker.")
}
},
{
"xmlcharrefreplace",
{
"xmlcharrefreplace_errors",
xmlcharrefreplace_errors,
METH_O,
PyDoc_STR("Implements the 'xmlcharrefreplace' error handling, "
"which replaces an unencodable character with the "
"appropriate XML character reference.")
}
},
{
"backslashreplace",
{
"backslashreplace_errors",
backslashreplace_errors,
METH_O,
PyDoc_STR("Implements the 'backslashreplace' error handling, "
"which replaces an unencodable character with a "
"backslashed escape sequence.")
}
}
#endif
};
PyInterpreterState *interp = PyThreadState_GET()->interp;
PyObject *mod;
unsigned i;
if (interp->codec_search_path != NULL)
return 0;
interp->codec_search_path = PyList_New(0);
interp->codec_search_cache = PyDict_New();
interp->codec_error_registry = PyDict_New();
if (interp->codec_error_registry) {
for (i = 0; i < sizeof(methods)/sizeof(methods[0]); ++i) {
PyObject *func = PyCFunction_New(&methods[i].def, NULL);
int res;
if (!func)
Py_FatalError("can't initialize codec error registry");
res = PyCodec_RegisterError(methods[i].name, func);
Py_DECREF(func);
if (res)
Py_FatalError("can't initialize codec error registry");
}
}
if (interp->codec_search_path == NULL ||
interp->codec_search_cache == NULL ||
interp->codec_error_registry == NULL)
Py_FatalError("can't initialize codec registry");
mod = PyImport_ImportModuleLevel("encodings", NULL, NULL, NULL, 0);
if (mod == NULL) {
if (PyErr_ExceptionMatches(PyExc_ImportError)) {
/* Ignore ImportErrors... this is done so that
distributions can disable the encodings package. Note
that other errors are not masked, e.g. SystemErrors
raised to inform the user of an error in the Python
configuration are still reported back to the user. */
PyErr_Clear();
return 0;
}
return -1;
}
Py_DECREF(mod);
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
/* This module provides the necessary stubs for when dynamic loading is
not present. */
#include "Python.h"
#include "importdl.h"
const struct filedescr _PyImport_DynLoadFiletab[] = {
{0, 0}
};

View File

@ -0,0 +1,827 @@
/* Error handling */
#include "Python.h"
#ifndef __STDC__
#ifndef MS_WINDOWS
extern char *strerror(int);
#endif
#endif
#ifdef MS_WINDOWS
#include "windows.h"
#include "winbase.h"
#endif
#include <ctype.h>
#ifdef __cplusplus
extern "C" {
#endif
void
PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)
{
PyThreadState *tstate = PyThreadState_GET();
PyObject *oldtype, *oldvalue, *oldtraceback;
if (traceback != NULL && !PyTraceBack_Check(traceback)) {
/* XXX Should never happen -- fatal error instead? */
/* Well, it could be None. */
Py_DECREF(traceback);
traceback = NULL;
}
/* Save these in locals to safeguard against recursive
invocation through Py_XDECREF */
oldtype = tstate->curexc_type;
oldvalue = tstate->curexc_value;
oldtraceback = tstate->curexc_traceback;
tstate->curexc_type = type;
tstate->curexc_value = value;
tstate->curexc_traceback = traceback;
Py_XDECREF(oldtype);
Py_XDECREF(oldvalue);
Py_XDECREF(oldtraceback);
}
void
PyErr_SetObject(PyObject *exception, PyObject *value)
{
Py_XINCREF(exception);
Py_XINCREF(value);
PyErr_Restore(exception, value, (PyObject *)NULL);
}
void
PyErr_SetNone(PyObject *exception)
{
PyErr_SetObject(exception, (PyObject *)NULL);
}
void
PyErr_SetString(PyObject *exception, const char *string)
{
PyObject *value = PyString_FromString(string);
PyErr_SetObject(exception, value);
Py_XDECREF(value);
}
PyObject *
PyErr_Occurred(void)
{
PyThreadState *tstate = PyThreadState_GET();
return tstate->curexc_type;
}
int
PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc)
{
if (err == NULL || exc == NULL) {
/* maybe caused by "import exceptions" that failed early on */
return 0;
}
if (PyTuple_Check(exc)) {
Py_ssize_t i, n;
n = PyTuple_Size(exc);
for (i = 0; i < n; i++) {
/* Test recursively */
if (PyErr_GivenExceptionMatches(
err, PyTuple_GET_ITEM(exc, i)))
{
return 1;
}
}
return 0;
}
/* err might be an instance, so check its class. */
if (PyExceptionInstance_Check(err))
err = PyExceptionInstance_Class(err);
if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) {
int res = 0, reclimit;
PyObject *exception, *value, *tb;
PyErr_Fetch(&exception, &value, &tb);
/* Temporarily bump the recursion limit, so that in the most
common case PyObject_IsSubclass will not raise a recursion
error we have to ignore anyway. Don't do it when the limit
is already insanely high, to avoid overflow */
reclimit = Py_GetRecursionLimit();
if (reclimit < (1 << 30))
Py_SetRecursionLimit(reclimit + 5);
res = PyObject_IsSubclass(err, exc);
Py_SetRecursionLimit(reclimit);
/* This function must not fail, so print the error here */
if (res == -1) {
PyErr_WriteUnraisable(err);
res = 0;
}
PyErr_Restore(exception, value, tb);
return res;
}
return err == exc;
}
int
PyErr_ExceptionMatches(PyObject *exc)
{
return PyErr_GivenExceptionMatches(PyErr_Occurred(), exc);
}
/* Used in many places to normalize a raised exception, including in
eval_code2(), do_raise(), and PyErr_Print()
*/
void
PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)
{
PyObject *type = *exc;
PyObject *value = *val;
PyObject *inclass = NULL;
PyObject *initial_tb = NULL;
PyThreadState *tstate = NULL;
if (type == NULL) {
/* There was no exception, so nothing to do. */
return;
}
/* If PyErr_SetNone() was used, the value will have been actually
set to NULL.
*/
if (!value) {
value = Py_None;
Py_INCREF(value);
}
if (PyExceptionInstance_Check(value))
inclass = PyExceptionInstance_Class(value);
/* Normalize the exception so that if the type is a class, the
value will be an instance.
*/
if (PyExceptionClass_Check(type)) {
/* if the value was not an instance, or is not an instance
whose class is (or is derived from) type, then use the
value as an argument to instantiation of the type
class.
*/
if (!inclass || !PyObject_IsSubclass(inclass, type)) {
PyObject *args, *res;
if (value == Py_None)
args = PyTuple_New(0);
else if (PyTuple_Check(value)) {
Py_INCREF(value);
args = value;
}
else
args = PyTuple_Pack(1, value);
if (args == NULL)
goto finally;
res = PyEval_CallObject(type, args);
Py_DECREF(args);
if (res == NULL)
goto finally;
Py_DECREF(value);
value = res;
}
/* if the class of the instance doesn't exactly match the
class of the type, believe the instance
*/
else if (inclass != type) {
Py_DECREF(type);
type = inclass;
Py_INCREF(type);
}
}
*exc = type;
*val = value;
return;
finally:
Py_DECREF(type);
Py_DECREF(value);
/* If the new exception doesn't set a traceback and the old
exception had a traceback, use the old traceback for the
new exception. It's better than nothing.
*/
initial_tb = *tb;
PyErr_Fetch(exc, val, tb);
if (initial_tb != NULL) {
if (*tb == NULL)
*tb = initial_tb;
else
Py_DECREF(initial_tb);
}
/* normalize recursively */
tstate = PyThreadState_GET();
if (++tstate->recursion_depth > Py_GetRecursionLimit()) {
--tstate->recursion_depth;
/* throw away the old exception... */
Py_DECREF(*exc);
Py_DECREF(*val);
/* ... and use the recursion error instead */
*exc = PyExc_RuntimeError;
*val = PyExc_RecursionErrorInst;
Py_INCREF(*exc);
Py_INCREF(*val);
/* just keeping the old traceback */
return;
}
PyErr_NormalizeException(exc, val, tb);
--tstate->recursion_depth;
}
void
PyErr_Fetch(PyObject **p_type, PyObject **p_value, PyObject **p_traceback)
{
PyThreadState *tstate = PyThreadState_GET();
*p_type = tstate->curexc_type;
*p_value = tstate->curexc_value;
*p_traceback = tstate->curexc_traceback;
tstate->curexc_type = NULL;
tstate->curexc_value = NULL;
tstate->curexc_traceback = NULL;
}
void
PyErr_Clear(void)
{
PyErr_Restore(NULL, NULL, NULL);
}
/* Restore previously fetched exception if an exception is not set,
otherwise drop previously fetched exception.
Like _PyErr_ChainExceptions() in Python 3, but doesn't set the context.
*/
void
_PyErr_ReplaceException(PyObject *exc, PyObject *val, PyObject *tb)
{
if (exc == NULL)
return;
if (PyErr_Occurred()) {
Py_DECREF(exc);
Py_XDECREF(val);
Py_XDECREF(tb);
}
else {
PyErr_Restore(exc, val, tb);
}
}
/* Convenience functions to set a type error exception and return 0 */
int
PyErr_BadArgument(void)
{
PyErr_SetString(PyExc_TypeError,
"bad argument type for built-in operation");
return 0;
}
PyObject *
PyErr_NoMemory(void)
{
if (PyErr_ExceptionMatches(PyExc_MemoryError))
/* already current */
return NULL;
/* raise the pre-allocated instance if it still exists */
if (PyExc_MemoryErrorInst)
PyErr_SetObject(PyExc_MemoryError, PyExc_MemoryErrorInst);
else
/* this will probably fail since there's no memory and hee,
hee, we have to instantiate this class
*/
PyErr_SetNone(PyExc_MemoryError);
return NULL;
}
PyObject *
PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
{
PyObject *v;
char *s;
int i = errno;
#ifdef PLAN9
char errbuf[ERRMAX];
#endif
#ifdef MS_WINDOWS
char *s_buf = NULL;
char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */
#endif
#ifdef EINTR
if (i == EINTR && PyErr_CheckSignals())
return NULL;
#endif
#ifdef PLAN9
rerrstr(errbuf, sizeof errbuf);
s = errbuf;
#else
if (i == 0)
s = "Error"; /* Sometimes errno didn't get set */
else
#ifndef MS_WINDOWS
s = strerror(i);
#else
{
/* Note that the Win32 errors do not lineup with the
errno error. So if the error is in the MSVC error
table, we use it, otherwise we assume it really _is_
a Win32 error code
*/
if (i > 0 && i < _sys_nerr) {
s = _sys_errlist[i];
}
else {
int len = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, /* no message source */
i,
MAKELANGID(LANG_NEUTRAL,
SUBLANG_DEFAULT),
/* Default language */
(LPTSTR) &s_buf,
0, /* size not used */
NULL); /* no args */
if (len==0) {
/* Only ever seen this in out-of-mem
situations */
sprintf(s_small_buf, "Windows Error 0x%X", i);
s = s_small_buf;
s_buf = NULL;
} else {
s = s_buf;
/* remove trailing cr/lf and dots */
while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.'))
s[--len] = '\0';
}
}
}
#endif /* Unix/Windows */
#endif /* PLAN 9*/
if (filenameObject != NULL)
v = Py_BuildValue("(isO)", i, s, filenameObject);
else
v = Py_BuildValue("(is)", i, s);
if (v != NULL) {
PyErr_SetObject(exc, v);
Py_DECREF(v);
}
#ifdef MS_WINDOWS
LocalFree(s_buf);
#endif
return NULL;
}
PyObject *
PyErr_SetFromErrnoWithFilename(PyObject *exc, const char *filename)
{
PyObject *name = filename ? PyString_FromString(filename) : NULL;
PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name);
Py_XDECREF(name);
return result;
}
#ifdef MS_WINDOWS
PyObject *
PyErr_SetFromErrnoWithUnicodeFilename(PyObject *exc, const Py_UNICODE *filename)
{
PyObject *name = filename ?
PyUnicode_FromUnicode(filename, wcslen(filename)) :
NULL;
PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name);
Py_XDECREF(name);
return result;
}
#endif /* MS_WINDOWS */
PyObject *
PyErr_SetFromErrno(PyObject *exc)
{
return PyErr_SetFromErrnoWithFilenameObject(exc, NULL);
}
#ifdef MS_WINDOWS
/* Windows specific error code handling */
PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject(
PyObject *exc,
int ierr,
PyObject *filenameObject)
{
int len;
char *s;
char *s_buf = NULL; /* Free via LocalFree */
char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */
PyObject *v;
DWORD err = (DWORD)ierr;
if (err==0) err = GetLastError();
len = FormatMessage(
/* Error API error */
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, /* no message source */
err,
MAKELANGID(LANG_NEUTRAL,
SUBLANG_DEFAULT), /* Default language */
(LPTSTR) &s_buf,
0, /* size not used */
NULL); /* no args */
if (len==0) {
/* Only seen this in out of mem situations */
sprintf(s_small_buf, "Windows Error 0x%X", err);
s = s_small_buf;
s_buf = NULL;
} else {
s = s_buf;
/* remove trailing cr/lf and dots */
while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.'))
s[--len] = '\0';
}
if (filenameObject != NULL)
v = Py_BuildValue("(isO)", err, s, filenameObject);
else
v = Py_BuildValue("(is)", err, s);
if (v != NULL) {
PyErr_SetObject(exc, v);
Py_DECREF(v);
}
LocalFree(s_buf);
return NULL;
}
PyObject *PyErr_SetExcFromWindowsErrWithFilename(
PyObject *exc,
int ierr,
const char *filename)
{
PyObject *name = filename ? PyString_FromString(filename) : NULL;
PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc,
ierr,
name);
Py_XDECREF(name);
return ret;
}
PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilename(
PyObject *exc,
int ierr,
const Py_UNICODE *filename)
{
PyObject *name = filename ?
PyUnicode_FromUnicode(filename, wcslen(filename)) :
NULL;
PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc,
ierr,
name);
Py_XDECREF(name);
return ret;
}
PyObject *PyErr_SetExcFromWindowsErr(PyObject *exc, int ierr)
{
return PyErr_SetExcFromWindowsErrWithFilename(exc, ierr, NULL);
}
PyObject *PyErr_SetFromWindowsErr(int ierr)
{
return PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError,
ierr, NULL);
}
PyObject *PyErr_SetFromWindowsErrWithFilename(
int ierr,
const char *filename)
{
PyObject *name = filename ? PyString_FromString(filename) : NULL;
PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject(
PyExc_WindowsError,
ierr, name);
Py_XDECREF(name);
return result;
}
PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename(
int ierr,
const Py_UNICODE *filename)
{
PyObject *name = filename ?
PyUnicode_FromUnicode(filename, wcslen(filename)) :
NULL;
PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject(
PyExc_WindowsError,
ierr, name);
Py_XDECREF(name);
return result;
}
#endif /* MS_WINDOWS */
void
_PyErr_BadInternalCall(char *filename, int lineno)
{
PyErr_Format(PyExc_SystemError,
"%s:%d: bad argument to internal function",
filename, lineno);
}
/* Remove the preprocessor macro for PyErr_BadInternalCall() so that we can
export the entry point for existing object code: */
#undef PyErr_BadInternalCall
void
PyErr_BadInternalCall(void)
{
PyErr_Format(PyExc_SystemError,
"bad argument to internal function");
}
#define PyErr_BadInternalCall() _PyErr_BadInternalCall(__FILE__, __LINE__)
PyObject *
PyErr_Format(PyObject *exception, const char *format, ...)
{
va_list vargs;
PyObject* string;
#ifdef HAVE_STDARG_PROTOTYPES
va_start(vargs, format);
#else
va_start(vargs);
#endif
string = PyString_FromFormatV(format, vargs);
PyErr_SetObject(exception, string);
Py_XDECREF(string);
va_end(vargs);
return NULL;
}
PyObject *
PyErr_NewException(char *name, PyObject *base, PyObject *dict)
{
char *dot;
PyObject *modulename = NULL;
PyObject *classname = NULL;
PyObject *mydict = NULL;
PyObject *bases = NULL;
PyObject *result = NULL;
dot = strrchr(name, '.');
if (dot == NULL) {
PyErr_SetString(PyExc_SystemError,
"PyErr_NewException: name must be module.class");
return NULL;
}
if (base == NULL)
base = PyExc_Exception;
if (dict == NULL) {
dict = mydict = PyDict_New();
if (dict == NULL)
goto failure;
}
if (PyDict_GetItemString(dict, "__module__") == NULL) {
modulename = PyString_FromStringAndSize(name,
(Py_ssize_t)(dot-name));
if (modulename == NULL)
goto failure;
if (PyDict_SetItemString(dict, "__module__", modulename) != 0)
goto failure;
}
if (PyTuple_Check(base)) {
bases = base;
/* INCREF as we create a new ref in the else branch */
Py_INCREF(bases);
} else {
bases = PyTuple_Pack(1, base);
if (bases == NULL)
goto failure;
}
/* Create a real new-style class. */
result = PyObject_CallFunction((PyObject *)&PyType_Type, "sOO",
dot+1, bases, dict);
failure:
Py_XDECREF(bases);
Py_XDECREF(mydict);
Py_XDECREF(classname);
Py_XDECREF(modulename);
return result;
}
/* Create an exception with docstring */
PyObject *
PyErr_NewExceptionWithDoc(char *name, char *doc, PyObject *base, PyObject *dict)
{
int result;
PyObject *ret = NULL;
PyObject *mydict = NULL; /* points to the dict only if we create it */
PyObject *docobj;
if (dict == NULL) {
dict = mydict = PyDict_New();
if (dict == NULL) {
return NULL;
}
}
if (doc != NULL) {
docobj = PyString_FromString(doc);
if (docobj == NULL)
goto failure;
result = PyDict_SetItemString(dict, "__doc__", docobj);
Py_DECREF(docobj);
if (result < 0)
goto failure;
}
ret = PyErr_NewException(name, base, dict);
failure:
Py_XDECREF(mydict);
return ret;
}
/* Call when an exception has occurred but there is no way for Python
to handle it. Examples: exception in __del__ or during GC. */
void
PyErr_WriteUnraisable(PyObject *obj)
{
PyObject *f, *t, *v, *tb;
PyErr_Fetch(&t, &v, &tb);
f = PySys_GetObject("stderr");
if (f != NULL) {
PyFile_WriteString("Exception ", f);
if (t) {
PyObject* moduleName;
char* className;
assert(PyExceptionClass_Check(t));
className = PyExceptionClass_Name(t);
if (className != NULL) {
char *dot = strrchr(className, '.');
if (dot != NULL)
className = dot+1;
}
moduleName = PyObject_GetAttrString(t, "__module__");
if (moduleName == NULL)
PyFile_WriteString("<unknown>", f);
else {
char* modstr = PyString_AsString(moduleName);
if (modstr &&
strcmp(modstr, "exceptions") != 0)
{
PyFile_WriteString(modstr, f);
PyFile_WriteString(".", f);
}
}
if (className == NULL)
PyFile_WriteString("<unknown>", f);
else
PyFile_WriteString(className, f);
if (v && v != Py_None) {
PyFile_WriteString(": ", f);
PyFile_WriteObject(v, f, 0);
}
Py_XDECREF(moduleName);
}
PyFile_WriteString(" in ", f);
PyFile_WriteObject(obj, f, 0);
PyFile_WriteString(" ignored\n", f);
PyErr_Clear(); /* Just in case */
}
Py_XDECREF(t);
Py_XDECREF(v);
Py_XDECREF(tb);
}
extern PyObject *PyModule_GetWarningsModule(void);
/* Set file and line information for the current exception.
If the exception is not a SyntaxError, also sets additional attributes
to make printing of exceptions believe it is a syntax error. */
void
PyErr_SyntaxLocation(const char *filename, int lineno)
{
PyObject *exc, *v, *tb, *tmp;
/* add attributes for the line number and filename for the error */
PyErr_Fetch(&exc, &v, &tb);
PyErr_NormalizeException(&exc, &v, &tb);
/* XXX check that it is, indeed, a syntax error. It might not
* be, though. */
tmp = PyInt_FromLong(lineno);
if (tmp == NULL)
PyErr_Clear();
else {
if (PyObject_SetAttrString(v, "lineno", tmp))
PyErr_Clear();
Py_DECREF(tmp);
}
if (filename != NULL) {
tmp = PyString_FromString(filename);
if (tmp == NULL)
PyErr_Clear();
else {
if (PyObject_SetAttrString(v, "filename", tmp))
PyErr_Clear();
Py_DECREF(tmp);
}
tmp = PyErr_ProgramText(filename, lineno);
if (tmp) {
if (PyObject_SetAttrString(v, "text", tmp))
PyErr_Clear();
Py_DECREF(tmp);
}
}
if (PyObject_SetAttrString(v, "offset", Py_None)) {
PyErr_Clear();
}
if (exc != PyExc_SyntaxError) {
if (!PyObject_HasAttrString(v, "msg")) {
tmp = PyObject_Str(v);
if (tmp) {
if (PyObject_SetAttrString(v, "msg", tmp))
PyErr_Clear();
Py_DECREF(tmp);
} else {
PyErr_Clear();
}
}
if (!PyObject_HasAttrString(v, "print_file_and_line")) {
if (PyObject_SetAttrString(v, "print_file_and_line",
Py_None))
PyErr_Clear();
}
}
PyErr_Restore(exc, v, tb);
}
/* com_fetch_program_text will attempt to load the line of text that
the exception refers to. If it fails, it will return NULL but will
not set an exception.
XXX The functionality of this function is quite similar to the
functionality in tb_displayline() in traceback.c.
*/
PyObject *
PyErr_ProgramText(const char *filename, int lineno)
{
FILE *fp;
int i;
char linebuf[1000];
if (filename == NULL || *filename == '\0' || lineno <= 0)
return NULL;
fp = fopen(filename, "r" PY_STDIOTEXTMODE);
if (fp == NULL)
return NULL;
for (i = 0; i < lineno; i++) {
char *pLastChar = &linebuf[sizeof(linebuf) - 2];
do {
*pLastChar = '\0';
if (Py_UniversalNewlineFgets(linebuf, sizeof linebuf, fp, NULL) == NULL)
break;
/* fgets read *something*; if it didn't get as
far as pLastChar, it must have found a newline
or hit the end of the file; if pLastChar is \n,
it obviously found a newline; else we haven't
yet seen a newline, so must continue */
} while (*pLastChar != '\0' && *pLastChar != '\n');
}
fclose(fp);
if (i == lineno) {
char *p = linebuf;
while (*p == ' ' || *p == '\t' || *p == '\014')
p++;
return PyString_FromString(p);
}
return NULL;
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,17 @@
/***********************************************************************/
/* Implements the string (as opposed to unicode) version of the
built-in formatters for string, int, float. That is, the versions
of int.__format__, etc., that take and return string objects */
#include "Python.h"
#include "../Objects/stringlib/stringdefs.h"
#define FORMAT_STRING _PyBytes_FormatAdvanced
#define FORMAT_LONG _PyLong_FormatAdvanced
#define FORMAT_INT _PyInt_FormatAdvanced
#define FORMAT_FLOAT _PyFloat_FormatAdvanced
#ifndef WITHOUT_COMPLEX
#define FORMAT_COMPLEX _PyComplex_FormatAdvanced
#endif
#include "../Objects/stringlib/formatter.h"

View File

@ -0,0 +1,18 @@
/* Implements the unicode (as opposed to string) version of the
built-in formatter for unicode. That is, unicode.__format__(). */
#include "Python.h"
#ifdef Py_USING_UNICODE
#include "../Objects/stringlib/unicodedefs.h"
#define FORMAT_STRING _PyUnicode_FormatAdvanced
/* don't define FORMAT_LONG, FORMAT_FLOAT, and FORMAT_COMPLEX, since
we can live with only the string versions of those. The builtin
format() will convert them to unicode. */
#include "../Objects/stringlib/formatter.h"
#endif

View File

@ -0,0 +1,38 @@
/* Dummy frozen modules initializer */
#include "Python.h"
/* In order to test the support for frozen modules, by default we
define a single frozen module, __hello__. Loading it will print
some famous words... */
/* To regenerate this data after the bytecode or marshal format has changed,
go to ../Tools/freeze/ and freeze the hello.py file; then copy and paste
the appropriate bytes from M___main__.c. */
static unsigned char M___hello__[] = {
99,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,115,9,0,0,0,100,0,0,71,72,100,1,0,83,40,
2,0,0,0,115,14,0,0,0,72,101,108,108,111,32,119,
111,114,108,100,46,46,46,78,40,0,0,0,0,40,0,0,
0,0,40,0,0,0,0,40,0,0,0,0,115,8,0,0,
0,104,101,108,108,111,46,112,121,115,1,0,0,0,63,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 */
};
/* Embedding apps may change this pointer to point to their favorite
collection of frozen modules: */
struct _frozen *PyImport_FrozenModules = _PyImport_FrozenModules;

View File

@ -0,0 +1,137 @@
#include "Python.h"
#include "Python-ast.h"
#include "node.h"
#include "token.h"
#include "graminit.h"
#include "code.h"
#include "compile.h"
#include "symtable.h"
#define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"
#define ERR_LATE_FUTURE \
"from __future__ imports must occur at the beginning of the file"
static int
future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename)
{
int i;
asdl_seq *names;
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 = PyString_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) {
ff->ff_features |= CO_FUTURE_DIVISION;
} else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
ff->ff_features |= CO_FUTURE_ABSOLUTE_IMPORT;
} else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
ff->ff_features |= CO_FUTURE_WITH_STATEMENT;
} else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {
ff->ff_features |= CO_FUTURE_PRINT_FUNCTION;
} else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
ff->ff_features |= CO_FUTURE_UNICODE_LITERALS;
} 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;
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.
*/
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;
/* 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) {
identifier modname = s->v.ImportFrom.module;
if (modname && PyString_GET_SIZE(modname) == 10 &&
!strcmp(PyString_AS_STRING(modname), "__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;
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;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
/* Return the compiler identification, if possible. */
#include "Python.h"
#ifndef COMPILER
#ifdef __GNUC__
#define COMPILER "\n[GCC " __VERSION__ "]"
#endif
#endif /* !COMPILER */
#ifndef COMPILER
#ifdef __cplusplus
#define COMPILER "[C++]"
#else
#define COMPILER "[C]"
#endif
#endif /* !COMPILER */
const char *
Py_GetCompiler(void)
{
return COMPILER;
}

View File

@ -0,0 +1,136 @@
/*---------------------------------------------------------------------------*
* <RCS keywords>
*
* C++ Library
*
* Copyright 1992-1994, David Gottner
*
* All Rights Reserved
*
* 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.
*
* I DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL I
* BE LIABLE FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Nevertheless, I would like to know about bugs in this library or
* suggestions for improvment. Send bug reports and feedback to
* davegottner@delphi.com.
*---------------------------------------------------------------------------*/
/* Modified to support --help and --version, as well as /? on Windows
* by Georg Brandl. */
#include <stdio.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
int _PyOS_opterr = 1; /* generate error messages */
int _PyOS_optind = 1; /* index into argv array */
char *_PyOS_optarg = NULL; /* optional argument */
static char *opt_ptr = "";
void _PyOS_ResetGetOpt(void)
{
_PyOS_opterr = 1;
_PyOS_optind = 1;
_PyOS_optarg = NULL;
opt_ptr = "";
}
int _PyOS_GetOpt(int argc, char **argv, char *optstring)
{
char *ptr;
int option;
if (*opt_ptr == '\0') {
if (_PyOS_optind >= argc)
return -1;
#ifdef MS_WINDOWS
else if (strcmp(argv[_PyOS_optind], "/?") == 0) {
++_PyOS_optind;
return 'h';
}
#endif
else if (argv[_PyOS_optind][0] != '-' ||
argv[_PyOS_optind][1] == '\0' /* lone dash */ )
return -1;
else if (strcmp(argv[_PyOS_optind], "--") == 0) {
++_PyOS_optind;
return -1;
}
else if (strcmp(argv[_PyOS_optind], "--help") == 0) {
++_PyOS_optind;
return 'h';
}
else if (strcmp(argv[_PyOS_optind], "--version") == 0) {
++_PyOS_optind;
return 'V';
}
opt_ptr = &argv[_PyOS_optind++][1];
}
if ((option = *opt_ptr++) == '\0')
return -1;
if (option == 'J') {
if (_PyOS_opterr)
fprintf(stderr, "-J is reserved for Jython\n");
return '_';
}
if (option == 'X') {
if (_PyOS_opterr)
fprintf(stderr,
"-X is reserved for implementation-specific arguments\n");
return '_';
}
if ((ptr = strchr(optstring, option)) == NULL) {
if (_PyOS_opterr)
fprintf(stderr, "Unknown option: -%c\n", option);
return '_';
}
if (*(ptr + 1) == ':') {
if (*opt_ptr != '\0') {
_PyOS_optarg = opt_ptr;
opt_ptr = "";
}
else {
if (_PyOS_optind >= argc) {
if (_PyOS_opterr)
fprintf(stderr,
"Argument expected for the -%c option\n", option);
return '_';
}
_PyOS_optarg = argv[_PyOS_optind++];
}
}
return option;
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,12 @@
#include "Python.h"
#ifndef PLATFORM
#define PLATFORM "unknown"
#endif
const char *
Py_GetPlatform(void)
{
return PLATFORM;
}

View File

@ -0,0 +1,15 @@
/* Return the full version string. */
#include "Python.h"
#include "patchlevel.h"
const char *
Py_GetVersion(void)
{
static char version[250];
PyOS_snprintf(version, sizeof(version), "%.80s (%.80s) %.80s",
PY_VERSION, Py_GetBuildInfo(), Py_GetCompiler());
return version;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,78 @@
/* Support for dynamic loading of extension modules */
#include "Python.h"
/* ./configure sets HAVE_DYNAMIC_LOADING if dynamic loading of modules is
supported on this platform. configure will then compile and link in one
of the dynload_*.c files, as appropriate. We will call a function in
those modules to get a function pointer to the module's init function.
*/
#ifdef HAVE_DYNAMIC_LOADING
#include "importdl.h"
extern dl_funcptr _PyImport_GetDynLoadFunc(const char *name,
const char *shortname,
const char *pathname, FILE *fp);
PyObject *
_PyImport_LoadDynamicModule(char *name, char *pathname, FILE *fp)
{
PyObject *m;
char *lastdot, *shortname, *packagecontext, *oldcontext;
dl_funcptr p;
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;
}
p = _PyImport_GetDynLoadFunc(name, shortname, pathname, fp);
if (PyErr_Occurred())
return NULL;
if (p == NULL) {
PyErr_Format(PyExc_ImportError,
"dynamic module does not define init function (init%.200s)",
shortname);
return NULL;
}
oldcontext = _Py_PackageContext;
_Py_PackageContext = packagecontext;
(*p)();
_Py_PackageContext = oldcontext;
if (PyErr_Occurred())
return NULL;
m = PyDict_GetItemString(PyImport_GetModuleDict(), name);
if (m == NULL) {
PyErr_SetString(PyExc_SystemError,
"dynamic module not initialized properly");
return NULL;
}
/* Remember the filename as the __file__ attribute */
if (PyModule_AddStringConstant(m, "__file__", pathname) < 0)
PyErr_Clear(); /* Not important enough to report */
if (_PyImport_FixupExtension(name, pathname) == NULL)
return NULL;
if (Py_VerboseFlag)
PySys_WriteStderr(
"import %s # dynamically loaded from %s\n",
name, pathname);
Py_INCREF(m);
return m;
}
#endif /* HAVE_DYNAMIC_LOADING */

View File

@ -0,0 +1,53 @@
#ifndef Py_IMPORTDL_H
#define Py_IMPORTDL_H
#ifdef __cplusplus
extern "C" {
#endif
/* 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
};
struct filedescr {
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 *);
/* Max length of module suffix searched for -- accommodates "module.slb" */
#define MAXSUFFIXSIZE 12
#ifdef MS_WINDOWS
#include <windows.h>
typedef FARPROC dl_funcptr;
#else
#if defined(PYOS_OS2) && !defined(PYCC_GCC)
#include <os2def.h>
typedef int (* APIENTRY dl_funcptr)();
#else
typedef void (*dl_funcptr)(void);
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif /* !Py_IMPORTDL_H */

View File

@ -0,0 +1,644 @@
/* Module support implementation */
#include "Python.h"
#define FLAG_SIZE_T 1
typedef double va_double;
static PyObject *va_build_value(const char *, va_list, int);
/* Package context -- the full module name for package imports */
char *_Py_PackageContext = NULL;
/* Py_InitModule4() parameters:
- name is the module name
- methods is the list of top-level functions
- doc is the documentation string
- passthrough is passed as self to functions defined in the module
- api_version is the value of PYTHON_API_VERSION at the time the
module was compiled
Return value is a borrowed reference to the module object; or NULL
if an error occurred (in Python 1.4 and before, errors were fatal).
Errors may still leak memory.
*/
static char api_version_warning[] =
"Python C API version mismatch for module %.100s:\
This Python has API version %d, module %.100s has version %d.";
PyObject *
Py_InitModule4(const char *name, PyMethodDef *methods, const char *doc,
PyObject *passthrough, int module_api_version)
{
PyObject *m, *d, *v, *n;
PyMethodDef *ml;
PyInterpreterState *interp = PyThreadState_Get()->interp;
if (interp->modules == NULL)
Py_FatalError("Python import machinery not initialized");
if (module_api_version != PYTHON_API_VERSION) {
char message[512];
PyOS_snprintf(message, sizeof(message),
api_version_warning, name,
PYTHON_API_VERSION, name,
module_api_version);
if (PyErr_Warn(PyExc_RuntimeWarning, message))
return NULL;
}
/* Make sure name is fully qualified.
This is a bit of a hack: when the shared library is loaded,
the module name is "package.module", but the module calls
Py_InitModule*() with just "module" for the name. The shared
library loader squirrels away the true name of the module in
_Py_PackageContext, and Py_InitModule*() will substitute this
(if the name actually matches).
*/
if (_Py_PackageContext != NULL) {
char *p = strrchr(_Py_PackageContext, '.');
if (p != NULL && strcmp(name, p+1) == 0) {
name = _Py_PackageContext;
_Py_PackageContext = NULL;
}
}
if ((m = PyImport_AddModule(name)) == NULL)
return NULL;
d = PyModule_GetDict(m);
if (methods != NULL) {
n = PyString_FromString(name);
if (n == NULL)
return NULL;
for (ml = methods; ml->ml_name != NULL; ml++) {
if ((ml->ml_flags & METH_CLASS) ||
(ml->ml_flags & METH_STATIC)) {
PyErr_SetString(PyExc_ValueError,
"module functions cannot set"
" METH_CLASS or METH_STATIC");
Py_DECREF(n);
return NULL;
}
v = PyCFunction_NewEx(ml, passthrough, n);
if (v == NULL) {
Py_DECREF(n);
return NULL;
}
if (PyDict_SetItemString(d, ml->ml_name, v) != 0) {
Py_DECREF(v);
Py_DECREF(n);
return NULL;
}
Py_DECREF(v);
}
Py_DECREF(n);
}
if (doc != NULL) {
v = PyString_FromString(doc);
if (v == NULL || PyDict_SetItemString(d, "__doc__", v) != 0) {
Py_XDECREF(v);
return NULL;
}
Py_DECREF(v);
}
return m;
}
/* Helper for mkvalue() to scan the length of a format */
static int
countformat(const char *format, int endchar)
{
int count = 0;
int level = 0;
while (level > 0 || *format != endchar) {
switch (*format) {
case '\0':
/* Premature end */
PyErr_SetString(PyExc_SystemError,
"unmatched paren in format");
return -1;
case '(':
case '[':
case '{':
if (level == 0)
count++;
level++;
break;
case ')':
case ']':
case '}':
level--;
break;
case '#':
case '&':
case ',':
case ':':
case ' ':
case '\t':
break;
default:
if (level == 0)
count++;
}
format++;
}
return count;
}
/* Generic function to create a value -- the inverse of getargs() */
/* After an original idea and first implementation by Steven Miale */
static PyObject *do_mktuple(const char**, va_list *, int, int, int);
static PyObject *do_mklist(const char**, va_list *, int, int, int);
static PyObject *do_mkdict(const char**, va_list *, int, int, int);
static PyObject *do_mkvalue(const char**, va_list *, int);
static PyObject *
do_mkdict(const char **p_format, va_list *p_va, int endchar, int n, int flags)
{
PyObject *d;
int i;
int itemfailed = 0;
if (n < 0)
return NULL;
if ((d = PyDict_New()) == NULL)
return NULL;
/* Note that we can't bail immediately on error as this will leak
refcounts on any 'N' arguments. */
for (i = 0; i < n; i+= 2) {
PyObject *k, *v;
int err;
k = do_mkvalue(p_format, p_va, flags);
if (k == NULL) {
itemfailed = 1;
Py_INCREF(Py_None);
k = Py_None;
}
v = do_mkvalue(p_format, p_va, flags);
if (v == NULL) {
itemfailed = 1;
Py_INCREF(Py_None);
v = Py_None;
}
err = PyDict_SetItem(d, k, v);
Py_DECREF(k);
Py_DECREF(v);
if (err < 0 || itemfailed) {
Py_DECREF(d);
return NULL;
}
}
if (d != NULL && **p_format != endchar) {
Py_DECREF(d);
d = NULL;
PyErr_SetString(PyExc_SystemError,
"Unmatched paren in format");
}
else if (endchar)
++*p_format;
return d;
}
static PyObject *
do_mklist(const char **p_format, va_list *p_va, int endchar, int n, int flags)
{
PyObject *v;
int i;
int itemfailed = 0;
if (n < 0)
return NULL;
v = PyList_New(n);
if (v == NULL)
return NULL;
/* Note that we can't bail immediately on error as this will leak
refcounts on any 'N' arguments. */
for (i = 0; i < n; i++) {
PyObject *w = do_mkvalue(p_format, p_va, flags);
if (w == NULL) {
itemfailed = 1;
Py_INCREF(Py_None);
w = Py_None;
}
PyList_SET_ITEM(v, i, w);
}
if (itemfailed) {
/* do_mkvalue() should have already set an error */
Py_DECREF(v);
return NULL;
}
if (**p_format != endchar) {
Py_DECREF(v);
PyErr_SetString(PyExc_SystemError,
"Unmatched paren in format");
return NULL;
}
if (endchar)
++*p_format;
return v;
}
#ifdef Py_USING_UNICODE
static int
_ustrlen(Py_UNICODE *u)
{
int i = 0;
Py_UNICODE *v = u;
while (*v != 0) { i++; v++; }
return i;
}
#endif
static PyObject *
do_mktuple(const char **p_format, va_list *p_va, int endchar, int n, int flags)
{
PyObject *v;
int i;
int itemfailed = 0;
if (n < 0)
return NULL;
if ((v = PyTuple_New(n)) == NULL)
return NULL;
/* Note that we can't bail immediately on error as this will leak
refcounts on any 'N' arguments. */
for (i = 0; i < n; i++) {
PyObject *w = do_mkvalue(p_format, p_va, flags);
if (w == NULL) {
itemfailed = 1;
Py_INCREF(Py_None);
w = Py_None;
}
PyTuple_SET_ITEM(v, i, w);
}
if (itemfailed) {
/* do_mkvalue() should have already set an error */
Py_DECREF(v);
return NULL;
}
if (**p_format != endchar) {
Py_DECREF(v);
PyErr_SetString(PyExc_SystemError,
"Unmatched paren in format");
return NULL;
}
if (endchar)
++*p_format;
return v;
}
static PyObject *
do_mkvalue(const char **p_format, va_list *p_va, int flags)
{
for (;;) {
switch (*(*p_format)++) {
case '(':
return do_mktuple(p_format, p_va, ')',
countformat(*p_format, ')'), flags);
case '[':
return do_mklist(p_format, p_va, ']',
countformat(*p_format, ']'), flags);
case '{':
return do_mkdict(p_format, p_va, '}',
countformat(*p_format, '}'), flags);
case 'b':
case 'B':
case 'h':
case 'i':
return PyInt_FromLong((long)va_arg(*p_va, int));
case 'H':
return PyInt_FromLong((long)va_arg(*p_va, unsigned int));
case 'I':
{
unsigned int n;
n = va_arg(*p_va, unsigned int);
if (n > (unsigned long)PyInt_GetMax())
return PyLong_FromUnsignedLong((unsigned long)n);
else
return PyInt_FromLong(n);
}
case 'n':
#if SIZEOF_SIZE_T!=SIZEOF_LONG
return PyInt_FromSsize_t(va_arg(*p_va, Py_ssize_t));
#endif
/* Fall through from 'n' to 'l' if Py_ssize_t is long */
case 'l':
return PyInt_FromLong(va_arg(*p_va, long));
case 'k':
{
unsigned long n;
n = va_arg(*p_va, unsigned long);
if (n > (unsigned long)PyInt_GetMax())
return PyLong_FromUnsignedLong(n);
else
return PyInt_FromLong(n);
}
#ifdef HAVE_LONG_LONG
case 'L':
return PyLong_FromLongLong((PY_LONG_LONG)va_arg(*p_va, PY_LONG_LONG));
case 'K':
return PyLong_FromUnsignedLongLong((PY_LONG_LONG)va_arg(*p_va, unsigned PY_LONG_LONG));
#endif
#ifdef Py_USING_UNICODE
case 'u':
{
PyObject *v;
Py_UNICODE *u = va_arg(*p_va, Py_UNICODE *);
Py_ssize_t n;
if (**p_format == '#') {
++*p_format;
if (flags & FLAG_SIZE_T)
n = va_arg(*p_va, Py_ssize_t);
else
n = va_arg(*p_va, int);
}
else
n = -1;
if (u == NULL) {
v = Py_None;
Py_INCREF(v);
}
else {
if (n < 0)
n = _ustrlen(u);
v = PyUnicode_FromUnicode(u, n);
}
return v;
}
#endif
case 'f':
case 'd':
return PyFloat_FromDouble(
(double)va_arg(*p_va, va_double));
#ifndef WITHOUT_COMPLEX
case 'D':
return PyComplex_FromCComplex(
*((Py_complex *)va_arg(*p_va, Py_complex *)));
#endif /* WITHOUT_COMPLEX */
case 'c':
{
char p[1];
p[0] = (char)va_arg(*p_va, int);
return PyString_FromStringAndSize(p, 1);
}
case 's':
case 'z':
{
PyObject *v;
char *str = va_arg(*p_va, char *);
Py_ssize_t n;
if (**p_format == '#') {
++*p_format;
if (flags & FLAG_SIZE_T)
n = va_arg(*p_va, Py_ssize_t);
else
n = va_arg(*p_va, int);
}
else
n = -1;
if (str == NULL) {
v = Py_None;
Py_INCREF(v);
}
else {
if (n < 0) {
size_t m = strlen(str);
if (m > PY_SSIZE_T_MAX) {
PyErr_SetString(PyExc_OverflowError,
"string too long for Python string");
return NULL;
}
n = (Py_ssize_t)m;
}
v = PyString_FromStringAndSize(str, n);
}
return v;
}
case 'N':
case 'S':
case 'O':
if (**p_format == '&') {
typedef PyObject *(*converter)(void *);
converter func = va_arg(*p_va, converter);
void *arg = va_arg(*p_va, void *);
++*p_format;
return (*func)(arg);
}
else {
PyObject *v;
v = va_arg(*p_va, PyObject *);
if (v != NULL) {
if (*(*p_format - 1) != 'N')
Py_INCREF(v);
}
else if (!PyErr_Occurred())
/* If a NULL was passed
* because a call that should
* have constructed a value
* failed, that's OK, and we
* pass the error on; but if
* no error occurred it's not
* clear that the caller knew
* what she was doing. */
PyErr_SetString(PyExc_SystemError,
"NULL object passed to Py_BuildValue");
return v;
}
case ':':
case ',':
case ' ':
case '\t':
break;
default:
PyErr_SetString(PyExc_SystemError,
"bad format char passed to Py_BuildValue");
return NULL;
}
}
}
PyObject *
Py_BuildValue(const char *format, ...)
{
va_list va;
PyObject* retval;
va_start(va, format);
retval = va_build_value(format, va, 0);
va_end(va);
return retval;
}
PyObject *
_Py_BuildValue_SizeT(const char *format, ...)
{
va_list va;
PyObject* retval;
va_start(va, format);
retval = va_build_value(format, va, FLAG_SIZE_T);
va_end(va);
return retval;
}
PyObject *
Py_VaBuildValue(const char *format, va_list va)
{
return va_build_value(format, va, 0);
}
PyObject *
_Py_VaBuildValue_SizeT(const char *format, va_list va)
{
return va_build_value(format, va, FLAG_SIZE_T);
}
static PyObject *
va_build_value(const char *format, va_list va, int flags)
{
const char *f = format;
int n = countformat(f, '\0');
va_list lva;
#ifdef VA_LIST_IS_ARRAY
memcpy(lva, va, sizeof(va_list));
#else
#ifdef __va_copy
__va_copy(lva, va);
#else
lva = va;
#endif
#endif
if (n < 0)
return NULL;
if (n == 0) {
Py_INCREF(Py_None);
return Py_None;
}
if (n == 1)
return do_mkvalue(&f, &lva, flags);
return do_mktuple(&f, &lva, '\0', n, flags);
}
PyObject *
PyEval_CallFunction(PyObject *obj, const char *format, ...)
{
va_list vargs;
PyObject *args;
PyObject *res;
va_start(vargs, format);
args = Py_VaBuildValue(format, vargs);
va_end(vargs);
if (args == NULL)
return NULL;
res = PyEval_CallObject(obj, args);
Py_DECREF(args);
return res;
}
PyObject *
PyEval_CallMethod(PyObject *obj, const char *methodname, const char *format, ...)
{
va_list vargs;
PyObject *meth;
PyObject *args;
PyObject *res;
meth = PyObject_GetAttrString(obj, methodname);
if (meth == NULL)
return NULL;
va_start(vargs, format);
args = Py_VaBuildValue(format, vargs);
va_end(vargs);
if (args == NULL) {
Py_DECREF(meth);
return NULL;
}
res = PyEval_CallObject(meth, args);
Py_DECREF(meth);
Py_DECREF(args);
return res;
}
int
PyModule_AddObject(PyObject *m, const char *name, PyObject *o)
{
PyObject *dict;
if (!PyModule_Check(m)) {
PyErr_SetString(PyExc_TypeError,
"PyModule_AddObject() needs module as first arg");
return -1;
}
if (!o) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_TypeError,
"PyModule_AddObject() needs non-NULL value");
return -1;
}
dict = PyModule_GetDict(m);
if (dict == NULL) {
/* Internal error -- modules must have a dict! */
PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__",
PyModule_GetName(m));
return -1;
}
if (PyDict_SetItemString(dict, name, o))
return -1;
Py_DECREF(o);
return 0;
}
int
PyModule_AddIntConstant(PyObject *m, const char *name, long value)
{
PyObject *o = PyInt_FromLong(value);
if (!o)
return -1;
if (PyModule_AddObject(m, name, o) == 0)
return 0;
Py_DECREF(o);
return -1;
}
int
PyModule_AddStringConstant(PyObject *m, const char *name, const char *value)
{
PyObject *o = PyString_FromString(value);
if (!o)
return -1;
if (PyModule_AddObject(m, name, o) == 0)
return 0;
Py_DECREF(o);
return -1;
}

View File

@ -0,0 +1,105 @@
#include "Python.h"
#include <ctype.h>
/* snprintf() wrappers. If the platform has vsnprintf, we use it, else we
emulate it in a half-hearted way. Even if the platform has it, we wrap
it because platforms differ in what vsnprintf does in case the buffer
is too small: C99 behavior is to return the number of characters that
would have been written had the buffer not been too small, and to set
the last byte of the buffer to \0. At least MS _vsnprintf returns a
negative value instead, and fills the entire buffer with non-\0 data.
The wrappers ensure that str[size-1] is always \0 upon return.
PyOS_snprintf and PyOS_vsnprintf never write more than size bytes
(including the trailing '\0') into str.
If the platform doesn't have vsnprintf, and the buffer size needed to
avoid truncation exceeds size by more than 512, Python aborts with a
Py_FatalError.
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 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.
CAUTION: Unlike C99, str != NULL and size > 0 are required.
*/
int
PyOS_snprintf(char *str, size_t size, const char *format, ...)
{
int rc;
va_list va;
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 */
#ifdef HAVE_SNPRINTF
#define _PyOS_vsnprintf_EXTRA_SPACE 1
#else
#define _PyOS_vsnprintf_EXTRA_SPACE 512
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;
}
#ifdef HAVE_SNPRINTF
len = vsnprintf(str, size, format, va);
#else
/* 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 */;
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);
#endif
Done:
if (size > 0)
str[size-1] = '\0';
return len;
#undef _PyOS_vsnprintf_EXTRA_SPACE
}

View File

@ -0,0 +1,285 @@
#include "Python.h"
#if defined(__sgi) && defined(WITH_THREAD) && !defined(_SGI_MP_SOURCE)
#define _SGI_MP_SOURCE
#endif
/* strtol and strtoul, renamed to avoid conflicts */
#include <ctype.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
/* Static overflow check values for bases 2 through 36.
* smallmax[base] is the largest unsigned long i such that
* 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,
};
/* maximum digits that can't ever overflow for bases 2 through 36,
* calculated by [int(math.floor(math.log(2**32, i))) for i in range(2, 37)].
* Note that this is pessimistic if sizeof(long) > 4.
*/
#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 */
#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 */
#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 0, 0b, 0B, 0o, 0O, 0x 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 */
/* skip leading white space */
while (*str && isspace(Py_CHARMASK(*str)))
++str;
/* check for leading 0 or 0x for auto-base or base 16 */
switch (base) {
case 0: /* look for leading 0, 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 {
base = 8;
}
}
else
base = 10;
break;
case 2: /* skip leading 0b or 0B */
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;
case 8: /* skip leading 0o or 0O */
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 16: /* skip leading 0x 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;
}
}
break;
}
/* catch silly bases */
if (base < 2 || base > 36) {
if (ptr)
*ptr = str;
return 0;
}
/* skip leading zeroes */
while (*str == '0')
++str;
/* 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;
if (ovlimit < 0) /* guaranteed overflow */
goto overflowed;
/* there could be an overflow */
/* check overflow just from shifting */
if (result > smallmax[base])
goto overflowed;
result *= base;
/* check overflow from the digit's value */
temp_result = result + c;
if (temp_result < result)
goto overflowed;
result = temp_result;
}
++str;
--ovlimit;
}
/* set pointer to point to the last character scanned */
if (ptr)
*ptr = str;
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;
}
/* 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)
long
PyOS_strtol(char *str, char **ptr, int base)
{
long result;
unsigned long uresult;
char sign;
while (*str && isspace(Py_CHARMASK(*str)))
str++;
sign = *str;
if (sign == '+' || sign == '-')
str++;
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;
}

View File

@ -0,0 +1,667 @@
/* Peephole optimizations for bytecode compiler. */
#include "Python.h"
#include "Python-ast.h"
#include "node.h"
#include "pyarena.h"
#include "ast.h"
#include "code.h"
#include "compile.h"
#include "symtable.h"
#include "opcode.h"
#define GETARG(arr, i) ((int)((arr[i+2]<<8) + arr[i+1]))
#define UNCONDITIONAL_JUMP(op) (op==JUMP_ABSOLUTE || op==JUMP_FORWARD)
#define CONDITIONAL_JUMP(op) (op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \
|| op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP)
#define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE || op==CONTINUE_LOOP \
|| op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \
|| op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP)
#define JUMPS_ON_TRUE(op) (op==POP_JUMP_IF_TRUE || op==JUMP_IF_TRUE_OR_POP)
#define GETJUMPTGT(arr, i) (GETARG(arr,i) + (ABSOLUTE_JUMP(arr[i]) ? 0 : i+3))
#define SETARG(arr, i, val) arr[i+2] = val>>8; arr[i+1] = val & 255
#define CODESIZE(op) (HAS_ARG(op) ? 3 : 1)
#define ISBASICBLOCK(blocks, start, bytes) \
(blocks[start]==blocks[start+bytes-1])
/* Replace LOAD_CONST c1. LOAD_CONST c2 ... LOAD_CONST cn BUILD_TUPLE n
with LOAD_CONST (c1, c2, ... cn).
The consts table must still be in list form so that the
new constant (c1, c2, ... cn) can be appended.
Called with codestr pointing to the first LOAD_CONST.
Bails out with no change if one or more of the LOAD_CONSTs is missing.
Also works for BUILD_LIST when followed by an "in" or "not in" test.
*/
static int
tuple_of_constants(unsigned char *codestr, Py_ssize_t n, PyObject *consts)
{
PyObject *newconst, *constant;
Py_ssize_t i, arg, len_consts;
/* Pre-conditions */
assert(PyList_CheckExact(consts));
assert(codestr[n*3] == BUILD_TUPLE || codestr[n*3] == BUILD_LIST);
assert(GETARG(codestr, (n*3)) == n);
for (i=0 ; i<n ; i++)
assert(codestr[i*3] == LOAD_CONST);
/* Buildup new tuple of constants */
newconst = PyTuple_New(n);
if (newconst == NULL)
return 0;
len_consts = PyList_GET_SIZE(consts);
for (i=0 ; i<n ; i++) {
arg = GETARG(codestr, (i*3));
assert(arg < len_consts);
constant = PyList_GET_ITEM(consts, arg);
Py_INCREF(constant);
PyTuple_SET_ITEM(newconst, i, constant);
}
/* Append folded constant onto consts */
if (PyList_Append(consts, newconst)) {
Py_DECREF(newconst);
return 0;
}
Py_DECREF(newconst);
/* Write NOPs over old LOAD_CONSTS and
add a new LOAD_CONST newconst on top of the BUILD_TUPLE n */
memset(codestr, NOP, n*3);
codestr[n*3] = LOAD_CONST;
SETARG(codestr, (n*3), len_consts);
return 1;
}
/* Replace LOAD_CONST c1. LOAD_CONST c2 BINOP
with LOAD_CONST binop(c1,c2)
The consts table must still be in list form so that the
new constant can be appended.
Called with codestr pointing to the first LOAD_CONST.
Abandons the transformation if the folding fails (i.e. 1+'a').
If the new constant is a sequence, only folds when the size
is below a threshold value. That keeps pyc files from
becoming large in the presence of code like: (None,)*1000.
*/
static int
fold_binops_on_constants(unsigned char *codestr, PyObject *consts)
{
PyObject *newconst, *v, *w;
Py_ssize_t len_consts, size;
int opcode;
/* Pre-conditions */
assert(PyList_CheckExact(consts));
assert(codestr[0] == LOAD_CONST);
assert(codestr[3] == LOAD_CONST);
/* Create new constant */
v = PyList_GET_ITEM(consts, GETARG(codestr, 0));
w = PyList_GET_ITEM(consts, GETARG(codestr, 3));
opcode = codestr[6];
switch (opcode) {
case BINARY_POWER:
newconst = PyNumber_Power(v, w, Py_None);
break;
case BINARY_MULTIPLY:
newconst = PyNumber_Multiply(v, w);
break;
case BINARY_DIVIDE:
/* Cannot fold this operation statically since
the result can depend on the run-time presence
of the -Qnew flag */
return 0;
case BINARY_TRUE_DIVIDE:
newconst = PyNumber_TrueDivide(v, w);
break;
case BINARY_FLOOR_DIVIDE:
newconst = PyNumber_FloorDivide(v, w);
break;
case BINARY_MODULO:
newconst = PyNumber_Remainder(v, w);
break;
case BINARY_ADD:
newconst = PyNumber_Add(v, w);
break;
case BINARY_SUBTRACT:
newconst = PyNumber_Subtract(v, w);
break;
case BINARY_SUBSCR:
/* #5057: if v is unicode, there might be differences between
wide and narrow builds in cases like '\U00012345'[0] or
'\U00012345abcdef'[3], so it's better to skip the optimization
in order to produce compatible pycs.
*/
if (PyUnicode_Check(v))
return 0;
newconst = PyObject_GetItem(v, w);
break;
case BINARY_LSHIFT:
newconst = PyNumber_Lshift(v, w);
break;
case BINARY_RSHIFT:
newconst = PyNumber_Rshift(v, w);
break;
case BINARY_AND:
newconst = PyNumber_And(v, w);
break;
case BINARY_XOR:
newconst = PyNumber_Xor(v, w);
break;
case BINARY_OR:
newconst = PyNumber_Or(v, w);
break;
default:
/* Called with an unknown opcode */
PyErr_Format(PyExc_SystemError,
"unexpected binary operation %d on a constant",
opcode);
return 0;
}
if (newconst == NULL) {
PyErr_Clear();
return 0;
}
size = PyObject_Size(newconst);
if (size == -1)
PyErr_Clear();
else if (size > 20) {
Py_DECREF(newconst);
return 0;
}
/* Append folded constant into consts table */
len_consts = PyList_GET_SIZE(consts);
if (PyList_Append(consts, newconst)) {
Py_DECREF(newconst);
return 0;
}
Py_DECREF(newconst);
/* Write NOP NOP NOP NOP LOAD_CONST newconst */
memset(codestr, NOP, 4);
codestr[4] = LOAD_CONST;
SETARG(codestr, 4, len_consts);
return 1;
}
static int
fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts)
{
PyObject *newconst=NULL, *v;
Py_ssize_t len_consts;
int opcode;
/* Pre-conditions */
assert(PyList_CheckExact(consts));
assert(codestr[0] == LOAD_CONST);
/* Create new constant */
v = PyList_GET_ITEM(consts, GETARG(codestr, 0));
opcode = codestr[3];
switch (opcode) {
case UNARY_NEGATIVE:
/* Preserve the sign of -0.0 */
if (PyObject_IsTrue(v) == 1)
newconst = PyNumber_Negative(v);
break;
case UNARY_CONVERT:
newconst = PyObject_Repr(v);
break;
case UNARY_INVERT:
newconst = PyNumber_Invert(v);
break;
default:
/* Called with an unknown opcode */
PyErr_Format(PyExc_SystemError,
"unexpected unary operation %d on a constant",
opcode);
return 0;
}
if (newconst == NULL) {
PyErr_Clear();
return 0;
}
/* Append folded constant into consts table */
len_consts = PyList_GET_SIZE(consts);
if (PyList_Append(consts, newconst)) {
Py_DECREF(newconst);
return 0;
}
Py_DECREF(newconst);
/* Write NOP LOAD_CONST newconst */
codestr[0] = NOP;
codestr[1] = LOAD_CONST;
SETARG(codestr, 1, len_consts);
return 1;
}
static unsigned int *
markblocks(unsigned char *code, Py_ssize_t len)
{
unsigned int *blocks = PyMem_New(unsigned int, len);
int i,j, opcode, blockcnt = 0;
if (blocks == NULL) {
PyErr_NoMemory();
return NULL;
}
memset(blocks, 0, len*sizeof(int));
/* Mark labels in the first pass */
for (i=0 ; i<len ; i+=CODESIZE(opcode)) {
opcode = code[i];
switch (opcode) {
case FOR_ITER:
case JUMP_FORWARD:
case JUMP_IF_FALSE_OR_POP:
case JUMP_IF_TRUE_OR_POP:
case POP_JUMP_IF_FALSE:
case POP_JUMP_IF_TRUE:
case JUMP_ABSOLUTE:
case CONTINUE_LOOP:
case SETUP_LOOP:
case SETUP_EXCEPT:
case SETUP_FINALLY:
case SETUP_WITH:
j = GETJUMPTGT(code, i);
blocks[j] = 1;
break;
}
}
/* Build block numbers in the second pass */
for (i=0 ; i<len ; i++) {
blockcnt += blocks[i]; /* increment blockcnt over labels */
blocks[i] = blockcnt;
}
return blocks;
}
/* Perform basic peephole optimizations to components of a code object.
The consts object should still be in list form to allow new constants
to be appended.
To keep the optimizer simple, it bails out (does nothing) for code
containing extended arguments or that has a length over 32,700. That
allows us to avoid overflow and sign issues. Likewise, it bails when
the lineno table has complex encoding for gaps >= 255.
Optimizations are restricted to simple transformations occuring within a
single basic block. All transformations keep the code size the same or
smaller. For those that reduce size, the gaps are initially filled with
NOPs. Later those NOPs are removed and the jump addresses retargeted in
a single pass. Line numbering is adjusted accordingly. */
PyObject *
PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
PyObject *lineno_obj)
{
Py_ssize_t i, j, codelen;
int nops, h, adj;
int tgt, tgttgt, opcode;
unsigned char *codestr = NULL;
unsigned char *lineno;
int *addrmap = NULL;
int new_line, cum_orig_line, last_line, tabsiz;
int cumlc=0, lastlc=0; /* Count runs of consecutive LOAD_CONSTs */
unsigned int *blocks = NULL;
char *name;
/* Bail out if an exception is set */
if (PyErr_Occurred())
goto exitError;
/* Bypass optimization when the lineno table is too complex */
assert(PyString_Check(lineno_obj));
lineno = (unsigned char*)PyString_AS_STRING(lineno_obj);
tabsiz = PyString_GET_SIZE(lineno_obj);
if (memchr(lineno, 255, tabsiz) != NULL)
goto exitUnchanged;
/* Avoid situations where jump retargeting could overflow */
assert(PyString_Check(code));
codelen = PyString_GET_SIZE(code);
if (codelen > 32700)
goto exitUnchanged;
/* Make a modifiable copy of the code string */
codestr = (unsigned char *)PyMem_Malloc(codelen);
if (codestr == NULL)
goto exitError;
codestr = (unsigned char *)memcpy(codestr,
PyString_AS_STRING(code), codelen);
/* Verify that RETURN_VALUE terminates the codestring. This allows
the various transformation patterns to look ahead several
instructions without additional checks to make sure they are not
looking beyond the end of the code string.
*/
if (codestr[codelen-1] != RETURN_VALUE)
goto exitUnchanged;
/* Mapping to new jump targets after NOPs are removed */
addrmap = PyMem_New(int, codelen);
if (addrmap == NULL) {
PyErr_NoMemory();
goto exitError;
}
blocks = markblocks(codestr, codelen);
if (blocks == NULL)
goto exitError;
assert(PyList_Check(consts));
for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
reoptimize_current:
opcode = codestr[i];
lastlc = cumlc;
cumlc = 0;
switch (opcode) {
/* Replace UNARY_NOT POP_JUMP_IF_FALSE
with POP_JUMP_IF_TRUE */
case UNARY_NOT:
if (codestr[i+1] != POP_JUMP_IF_FALSE
|| !ISBASICBLOCK(blocks,i,4))
continue;
j = GETARG(codestr, i+1);
codestr[i] = POP_JUMP_IF_TRUE;
SETARG(codestr, i, j);
codestr[i+3] = NOP;
goto reoptimize_current;
/* not a is b --> a is not b
not a in b --> a not in b
not a is not b --> a is b
not a not in b --> a in b
*/
case COMPARE_OP:
j = GETARG(codestr, i);
if (j < 6 || j > 9 ||
codestr[i+3] != UNARY_NOT ||
!ISBASICBLOCK(blocks,i,4))
continue;
SETARG(codestr, i, (j^1));
codestr[i+3] = NOP;
break;
/* Replace LOAD_GLOBAL/LOAD_NAME None
with LOAD_CONST None */
case LOAD_NAME:
case LOAD_GLOBAL:
j = GETARG(codestr, i);
name = PyString_AsString(PyTuple_GET_ITEM(names, j));
if (name == NULL || strcmp(name, "None") != 0)
continue;
for (j=0 ; j < PyList_GET_SIZE(consts) ; j++) {
if (PyList_GET_ITEM(consts, j) == Py_None)
break;
}
if (j == PyList_GET_SIZE(consts)) {
if (PyList_Append(consts, Py_None) == -1)
goto exitError;
}
assert(PyList_GET_ITEM(consts, j) == Py_None);
codestr[i] = LOAD_CONST;
SETARG(codestr, i, j);
cumlc = lastlc + 1;
break;
/* Skip over LOAD_CONST trueconst
POP_JUMP_IF_FALSE xx. This improves
"while 1" performance. */
case LOAD_CONST:
cumlc = lastlc + 1;
j = GETARG(codestr, i);
if (codestr[i+3] != POP_JUMP_IF_FALSE ||
!ISBASICBLOCK(blocks,i,6) ||
!PyObject_IsTrue(PyList_GET_ITEM(consts, j)))
continue;
memset(codestr+i, NOP, 6);
cumlc = 0;
break;
/* Try to fold tuples of constants (includes a case for lists
which are only used for "in" and "not in" tests).
Skip over BUILD_SEQN 1 UNPACK_SEQN 1.
Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2.
Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */
case BUILD_TUPLE:
case BUILD_LIST:
j = GETARG(codestr, i);
h = i - 3 * j;
if (h >= 0 &&
j <= lastlc &&
((opcode == BUILD_TUPLE &&
ISBASICBLOCK(blocks, h, 3*(j+1))) ||
(opcode == BUILD_LIST &&
codestr[i+3]==COMPARE_OP &&
ISBASICBLOCK(blocks, h, 3*(j+2)) &&
(GETARG(codestr,i+3)==6 ||
GETARG(codestr,i+3)==7))) &&
tuple_of_constants(&codestr[h], j, consts)) {
assert(codestr[i] == LOAD_CONST);
cumlc = 1;
break;
}
if (codestr[i+3] != UNPACK_SEQUENCE ||
!ISBASICBLOCK(blocks,i,6) ||
j != GETARG(codestr, i+3))
continue;
if (j == 1) {
memset(codestr+i, NOP, 6);
} else if (j == 2) {
codestr[i] = ROT_TWO;
memset(codestr+i+1, NOP, 5);
} else if (j == 3) {
codestr[i] = ROT_THREE;
codestr[i+1] = ROT_TWO;
memset(codestr+i+2, NOP, 4);
}
break;
/* Fold binary ops on constants.
LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */
case BINARY_POWER:
case BINARY_MULTIPLY:
case BINARY_TRUE_DIVIDE:
case BINARY_FLOOR_DIVIDE:
case BINARY_MODULO:
case BINARY_ADD:
case BINARY_SUBTRACT:
case BINARY_SUBSCR:
case BINARY_LSHIFT:
case BINARY_RSHIFT:
case BINARY_AND:
case BINARY_XOR:
case BINARY_OR:
if (lastlc >= 2 &&
ISBASICBLOCK(blocks, i-6, 7) &&
fold_binops_on_constants(&codestr[i-6], consts)) {
i -= 2;
assert(codestr[i] == LOAD_CONST);
cumlc = 1;
}
break;
/* Fold unary ops on constants.
LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
case UNARY_NEGATIVE:
case UNARY_CONVERT:
case UNARY_INVERT:
if (lastlc >= 1 &&
ISBASICBLOCK(blocks, i-3, 4) &&
fold_unaryops_on_constants(&codestr[i-3], consts)) {
i -= 2;
assert(codestr[i] == LOAD_CONST);
cumlc = 1;
}
break;
/* Simplify conditional jump to conditional jump where the
result of the first test implies the success of a similar
test or the failure of the opposite test.
Arises in code like:
"if a and b:"
"if a or b:"
"a and b or c"
"(a and b) and c"
x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_FALSE_OR_POP z
--> x:JUMP_IF_FALSE_OR_POP z
x:JUMP_IF_FALSE_OR_POP y y:JUMP_IF_TRUE_OR_POP z
--> x:POP_JUMP_IF_FALSE y+3
where y+3 is the instruction following the second test.
*/
case JUMP_IF_FALSE_OR_POP:
case JUMP_IF_TRUE_OR_POP:
tgt = GETJUMPTGT(codestr, i);
j = codestr[tgt];
if (CONDITIONAL_JUMP(j)) {
/* NOTE: all possible jumps here are absolute! */
if (JUMPS_ON_TRUE(j) == JUMPS_ON_TRUE(opcode)) {
/* The second jump will be
taken iff the first is. */
tgttgt = GETJUMPTGT(codestr, tgt);
/* The current opcode inherits
its target's stack behaviour */
codestr[i] = j;
SETARG(codestr, i, tgttgt);
goto reoptimize_current;
} else {
/* The second jump is not taken if the first is (so
jump past it), and all conditional jumps pop their
argument when they're not taken (so change the
first jump to pop its argument when it's taken). */
if (JUMPS_ON_TRUE(opcode))
codestr[i] = POP_JUMP_IF_TRUE;
else
codestr[i] = POP_JUMP_IF_FALSE;
SETARG(codestr, i, (tgt + 3));
goto reoptimize_current;
}
}
/* Intentional fallthrough */
/* Replace jumps to unconditional jumps */
case POP_JUMP_IF_FALSE:
case POP_JUMP_IF_TRUE:
case FOR_ITER:
case JUMP_FORWARD:
case JUMP_ABSOLUTE:
case CONTINUE_LOOP:
case SETUP_LOOP:
case SETUP_EXCEPT:
case SETUP_FINALLY:
case SETUP_WITH:
tgt = GETJUMPTGT(codestr, i);
/* Replace JUMP_* to a RETURN into just a RETURN */
if (UNCONDITIONAL_JUMP(opcode) &&
codestr[tgt] == RETURN_VALUE) {
codestr[i] = RETURN_VALUE;
memset(codestr+i+1, NOP, 2);
continue;
}
if (!UNCONDITIONAL_JUMP(codestr[tgt]))
continue;
tgttgt = GETJUMPTGT(codestr, tgt);
if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */
opcode = JUMP_ABSOLUTE;
if (!ABSOLUTE_JUMP(opcode))
tgttgt -= i + 3; /* Calc relative jump addr */
if (tgttgt < 0) /* No backward relative jumps */
continue;
codestr[i] = opcode;
SETARG(codestr, i, tgttgt);
break;
case EXTENDED_ARG:
goto exitUnchanged;
/* Replace RETURN LOAD_CONST None RETURN with just RETURN */
/* Remove unreachable JUMPs after RETURN */
case RETURN_VALUE:
if (i+4 >= codelen)
continue;
if (codestr[i+4] == RETURN_VALUE &&
ISBASICBLOCK(blocks,i,5))
memset(codestr+i+1, NOP, 4);
else if (UNCONDITIONAL_JUMP(codestr[i+1]) &&
ISBASICBLOCK(blocks,i,4))
memset(codestr+i+1, NOP, 3);
break;
}
}
/* Fixup linenotab */
for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) {
addrmap[i] = i - nops;
if (codestr[i] == NOP)
nops++;
}
cum_orig_line = 0;
last_line = 0;
for (i=0 ; i < tabsiz ; i+=2) {
cum_orig_line += lineno[i];
new_line = addrmap[cum_orig_line];
assert (new_line - last_line < 255);
lineno[i] =((unsigned char)(new_line - last_line));
last_line = new_line;
}
/* Remove NOPs and fixup jump targets */
for (i=0, h=0 ; i<codelen ; ) {
opcode = codestr[i];
switch (opcode) {
case NOP:
i++;
continue;
case JUMP_ABSOLUTE:
case CONTINUE_LOOP:
case POP_JUMP_IF_FALSE:
case POP_JUMP_IF_TRUE:
case JUMP_IF_FALSE_OR_POP:
case JUMP_IF_TRUE_OR_POP:
j = addrmap[GETARG(codestr, i)];
SETARG(codestr, i, j);
break;
case FOR_ITER:
case JUMP_FORWARD:
case SETUP_LOOP:
case SETUP_EXCEPT:
case SETUP_FINALLY:
case SETUP_WITH:
j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3;
SETARG(codestr, i, j);
break;
}
adj = CODESIZE(opcode);
while (adj--)
codestr[h++] = codestr[i++];
}
assert(h + nops == codelen);
code = PyString_FromStringAndSize((char *)codestr, h);
PyMem_Free(addrmap);
PyMem_Free(codestr);
PyMem_Free(blocks);
return code;
exitError:
code = NULL;
exitUnchanged:
if (blocks != NULL)
PyMem_Free(blocks);
if (addrmap != NULL)
PyMem_Free(addrmap);
if (codestr != NULL)
PyMem_Free(codestr);
Py_XINCREF(code);
return code;
}

View File

@ -0,0 +1,213 @@
#include "Python.h"
#include "pyarena.h"
/* A simple arena block structure.
Measurements with standard library modules suggest the average
allocation is about 20 bytes and that most compiles use a single
block.
TODO(jhylton): Think about a realloc API, maybe just for the last
allocation?
*/
#define DEFAULT_BLOCK_SIZE 8192
#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 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;
/* 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
and a list of PyObject* pointers. PyObjects are decrefed
when the arena is freed.
*/
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 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;
#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;
#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;
}
static void
block_free(block *b) {
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;
}
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();
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;
#endif
return arena;
}
void
PyArena_Free(PyArena *arena)
{
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));
*/
#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);
*/
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();
#if defined(Py_DEBUG)
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;
#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;
#endif
}
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;
}

View File

@ -0,0 +1,214 @@
#include "Python.h"
/* Our own locale-independent ctype.h-like macros */
const unsigned int _Py_ctype_table[256] = {
0, /* 0x0 '\x00' */
0, /* 0x1 '\x01' */
0, /* 0x2 '\x02' */
0, /* 0x3 '\x03' */
0, /* 0x4 '\x04' */
0, /* 0x5 '\x05' */
0, /* 0x6 '\x06' */
0, /* 0x7 '\x07' */
0, /* 0x8 '\x08' */
PY_CTF_SPACE, /* 0x9 '\t' */
PY_CTF_SPACE, /* 0xa '\n' */
PY_CTF_SPACE, /* 0xb '\v' */
PY_CTF_SPACE, /* 0xc '\f' */
PY_CTF_SPACE, /* 0xd '\r' */
0, /* 0xe '\x0e' */
0, /* 0xf '\x0f' */
0, /* 0x10 '\x10' */
0, /* 0x11 '\x11' */
0, /* 0x12 '\x12' */
0, /* 0x13 '\x13' */
0, /* 0x14 '\x14' */
0, /* 0x15 '\x15' */
0, /* 0x16 '\x16' */
0, /* 0x17 '\x17' */
0, /* 0x18 '\x18' */
0, /* 0x19 '\x19' */
0, /* 0x1a '\x1a' */
0, /* 0x1b '\x1b' */
0, /* 0x1c '\x1c' */
0, /* 0x1d '\x1d' */
0, /* 0x1e '\x1e' */
0, /* 0x1f '\x1f' */
PY_CTF_SPACE, /* 0x20 ' ' */
0, /* 0x21 '!' */
0, /* 0x22 '"' */
0, /* 0x23 '#' */
0, /* 0x24 '$' */
0, /* 0x25 '%' */
0, /* 0x26 '&' */
0, /* 0x27 "'" */
0, /* 0x28 '(' */
0, /* 0x29 ')' */
0, /* 0x2a '*' */
0, /* 0x2b '+' */
0, /* 0x2c ',' */
0, /* 0x2d '-' */
0, /* 0x2e '.' */
0, /* 0x2f '/' */
PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x30 '0' */
PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x31 '1' */
PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x32 '2' */
PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x33 '3' */
PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x34 '4' */
PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x35 '5' */
PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x36 '6' */
PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x37 '7' */
PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x38 '8' */
PY_CTF_DIGIT|PY_CTF_XDIGIT, /* 0x39 '9' */
0, /* 0x3a ':' */
0, /* 0x3b ';' */
0, /* 0x3c '<' */
0, /* 0x3d '=' */
0, /* 0x3e '>' */
0, /* 0x3f '?' */
0, /* 0x40 '@' */
PY_CTF_UPPER|PY_CTF_XDIGIT, /* 0x41 'A' */
PY_CTF_UPPER|PY_CTF_XDIGIT, /* 0x42 'B' */
PY_CTF_UPPER|PY_CTF_XDIGIT, /* 0x43 'C' */
PY_CTF_UPPER|PY_CTF_XDIGIT, /* 0x44 'D' */
PY_CTF_UPPER|PY_CTF_XDIGIT, /* 0x45 'E' */
PY_CTF_UPPER|PY_CTF_XDIGIT, /* 0x46 'F' */
PY_CTF_UPPER, /* 0x47 'G' */
PY_CTF_UPPER, /* 0x48 'H' */
PY_CTF_UPPER, /* 0x49 'I' */
PY_CTF_UPPER, /* 0x4a 'J' */
PY_CTF_UPPER, /* 0x4b 'K' */
PY_CTF_UPPER, /* 0x4c 'L' */
PY_CTF_UPPER, /* 0x4d 'M' */
PY_CTF_UPPER, /* 0x4e 'N' */
PY_CTF_UPPER, /* 0x4f 'O' */
PY_CTF_UPPER, /* 0x50 'P' */
PY_CTF_UPPER, /* 0x51 'Q' */
PY_CTF_UPPER, /* 0x52 'R' */
PY_CTF_UPPER, /* 0x53 'S' */
PY_CTF_UPPER, /* 0x54 'T' */
PY_CTF_UPPER, /* 0x55 'U' */
PY_CTF_UPPER, /* 0x56 'V' */
PY_CTF_UPPER, /* 0x57 'W' */
PY_CTF_UPPER, /* 0x58 'X' */
PY_CTF_UPPER, /* 0x59 'Y' */
PY_CTF_UPPER, /* 0x5a 'Z' */
0, /* 0x5b '[' */
0, /* 0x5c '\\' */
0, /* 0x5d ']' */
0, /* 0x5e '^' */
0, /* 0x5f '_' */
0, /* 0x60 '`' */
PY_CTF_LOWER|PY_CTF_XDIGIT, /* 0x61 'a' */
PY_CTF_LOWER|PY_CTF_XDIGIT, /* 0x62 'b' */
PY_CTF_LOWER|PY_CTF_XDIGIT, /* 0x63 'c' */
PY_CTF_LOWER|PY_CTF_XDIGIT, /* 0x64 'd' */
PY_CTF_LOWER|PY_CTF_XDIGIT, /* 0x65 'e' */
PY_CTF_LOWER|PY_CTF_XDIGIT, /* 0x66 'f' */
PY_CTF_LOWER, /* 0x67 'g' */
PY_CTF_LOWER, /* 0x68 'h' */
PY_CTF_LOWER, /* 0x69 'i' */
PY_CTF_LOWER, /* 0x6a 'j' */
PY_CTF_LOWER, /* 0x6b 'k' */
PY_CTF_LOWER, /* 0x6c 'l' */
PY_CTF_LOWER, /* 0x6d 'm' */
PY_CTF_LOWER, /* 0x6e 'n' */
PY_CTF_LOWER, /* 0x6f 'o' */
PY_CTF_LOWER, /* 0x70 'p' */
PY_CTF_LOWER, /* 0x71 'q' */
PY_CTF_LOWER, /* 0x72 'r' */
PY_CTF_LOWER, /* 0x73 's' */
PY_CTF_LOWER, /* 0x74 't' */
PY_CTF_LOWER, /* 0x75 'u' */
PY_CTF_LOWER, /* 0x76 'v' */
PY_CTF_LOWER, /* 0x77 'w' */
PY_CTF_LOWER, /* 0x78 'x' */
PY_CTF_LOWER, /* 0x79 'y' */
PY_CTF_LOWER, /* 0x7a 'z' */
0, /* 0x7b '{' */
0, /* 0x7c '|' */
0, /* 0x7d '}' */
0, /* 0x7e '~' */
0, /* 0x7f '\x7f' */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
const unsigned char _Py_ctype_tolower[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
};
const unsigned char _Py_ctype_toupper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
};

View File

@ -0,0 +1,23 @@
#include "pyconfig.h"
#include "pyfpe.h"
/*
* The signal handler for SIGFPE is actually declared in an external
* module fpectl, or as preferred by the user. These variable
* definitions are required in order to compile Python without
* getting missing externals, but to actually handle SIGFPE requires
* defining a handler and enabling generation of SIGFPE.
*/
#ifdef WANT_SIGFPE_HANDLER
jmp_buf PyFPE_jbuf;
int PyFPE_counter = 0;
#endif
/* Have this outside the above #ifdef, since some picky ANSI compilers issue a
warning when compiling an empty file. */
double
PyFPE_dummy(void *dummy)
{
return 1.0;
}

View File

@ -0,0 +1,79 @@
#include "Python.h"
#ifdef X87_DOUBLE_ROUNDING
/* On x86 platforms using an x87 FPU, this function is called from the
Py_FORCE_DOUBLE macro (defined in pymath.h) to force a floating-point
number out of an 80-bit x87 FPU register and into a 64-bit memory location,
thus rounding from extended precision to double precision. */
double _Py_force_double(double x)
{
volatile double y;
y = x;
return y;
}
#endif
#ifdef HAVE_GCC_ASM_FOR_X87
/* inline assembly for getting and setting the 387 FPU control word on
gcc/x86 */
unsigned short _Py_get_387controlword(void) {
unsigned short cw;
__asm__ __volatile__ ("fnstcw %0" : "=m" (cw));
return cw;
}
void _Py_set_387controlword(unsigned short cw) {
__asm__ __volatile__ ("fldcw %0" : : "m" (cw));
}
#endif
#ifndef HAVE_HYPOT
double hypot(double x, double y)
{
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);
}
}
#endif /* HAVE_HYPOT */
#ifndef HAVE_COPYSIGN
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);
}
}
#endif /* HAVE_COPYSIGN */
#ifndef HAVE_ROUND
double
round(double x)
{
double absx, y;
absx = fabs(x);
y = floor(absx);
if (absx - y >= 0.5)
y += 1.0;
return copysign(y, x);
}
#endif /* HAVE_ROUND */

View File

@ -0,0 +1,665 @@
/* Thread and interpreter state structures and their interfaces */
#include "Python.h"
/* --------------------------------------------------------------------------
CAUTION
Always use malloc() and free() directly in this file. A number of these
functions are advertised as safe to call when the GIL isn't held, and in
a debug build Python redirects (e.g.) PyMem_NEW (etc) to Python's debugging
obmalloc functions. Those aren't thread-safe (they rely on the GIL to avoid
the expense of doing their own locking).
-------------------------------------------------------------------------- */
#ifdef HAVE_DLOPEN
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
#ifndef RTLD_LAZY
#define RTLD_LAZY 1
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef WITH_THREAD
#include "pythread.h"
static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */
#define HEAD_INIT() (void)(head_mutex || (head_mutex = PyThread_allocate_lock()))
#define HEAD_LOCK() PyThread_acquire_lock(head_mutex, WAIT_LOCK)
#define HEAD_UNLOCK() PyThread_release_lock(head_mutex)
/* The single PyInterpreterState used by this process'
GILState implementation
*/
static PyInterpreterState *autoInterpreterState = NULL;
static int autoTLSkey = 0;
#else
#define HEAD_INIT() /* Nothing */
#define HEAD_LOCK() /* Nothing */
#define HEAD_UNLOCK() /* Nothing */
#endif
static PyInterpreterState *interp_head = NULL;
PyThreadState *_PyThreadState_Current = NULL;
PyThreadFrameGetter _PyThreadState_GetFrame = NULL;
#ifdef WITH_THREAD
static void _PyGILState_NoteThreadState(PyThreadState* tstate);
#endif
PyInterpreterState *
PyInterpreterState_New(void)
{
PyInterpreterState *interp = (PyInterpreterState *)
malloc(sizeof(PyInterpreterState));
if (interp != NULL) {
HEAD_INIT();
#ifdef WITH_THREAD
if (head_mutex == NULL)
Py_FatalError("Can't initialize threads for interpreter");
#endif
interp->modules = NULL;
interp->modules_reloading = 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;
#ifdef HAVE_DLOPEN
#ifdef RTLD_NOW
interp->dlopenflags = RTLD_NOW;
#else
interp->dlopenflags = RTLD_LAZY;
#endif
#endif
#ifdef WITH_TSC
interp->tscdump = 0;
#endif
HEAD_LOCK();
interp->next = interp_head;
interp_head = interp;
HEAD_UNLOCK();
}
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_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);
}
}
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);
}
/* Default implementation for _PyThreadState_GetFrame */
static struct _frame *
threadstate_getframe(PyThreadState *self)
{
return self->frame;
}
static PyThreadState *
new_threadstate(PyInterpreterState *interp, int init)
{
PyThreadState *tstate = (PyThreadState *)malloc(sizeof(PyThreadState));
if (_PyThreadState_GetFrame == NULL)
_PyThreadState_GetFrame = threadstate_getframe;
if (tstate != NULL) {
tstate->interp = interp;
tstate->frame = NULL;
tstate->recursion_depth = 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();
#else
tstate->thread_id = 0;
#endif
tstate->dict = 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->c_profilefunc = NULL;
tstate->c_tracefunc = NULL;
tstate->c_profileobj = NULL;
tstate->c_traceobj = NULL;
tstate->trash_delete_nesting = 0;
tstate->trash_delete_later = NULL;
if (init)
_PyThreadState_Init(tstate);
HEAD_LOCK();
tstate->next = interp->tstate_head;
interp->tstate_head = tstate;
HEAD_UNLOCK();
}
return tstate;
}
PyThreadState *
PyThreadState_New(PyInterpreterState *interp)
{
return new_threadstate(interp, 1);
}
PyThreadState *
_PyThreadState_Prealloc(PyInterpreterState *interp)
{
return new_threadstate(interp, 0);
}
void
_PyThreadState_Init(PyThreadState *tstate)
{
#ifdef WITH_THREAD
_PyGILState_NoteThreadState(tstate);
#endif
}
void
PyThreadState_Clear(PyThreadState *tstate)
{
if (Py_VerboseFlag && tstate->frame != NULL)
fprintf(stderr,
"PyThreadState_Clear: warning: thread still has a frame\n");
Py_CLEAR(tstate->frame);
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->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);
}
/* Common code for PyThreadState_Delete() and PyThreadState_DeleteCurrent() */
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);
}
void
PyThreadState_Delete(PyThreadState *tstate)
{
if (tstate == _PyThreadState_Current)
Py_FatalError("PyThreadState_Delete: tstate is still current");
tstate_delete_common(tstate);
#ifdef WITH_THREAD
if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate)
PyThread_delete_key_value(autoTLSkey);
#endif /* WITH_THREAD */
}
#ifdef WITH_THREAD
void
PyThreadState_DeleteCurrent()
{
PyThreadState *tstate = _PyThreadState_Current;
if (tstate == NULL)
Py_FatalError(
"PyThreadState_DeleteCurrent: no current tstate");
_PyThreadState_Current = NULL;
if (autoInterpreterState && PyThread_get_key_value(autoTLSkey) == tstate)
PyThread_delete_key_value(autoTLSkey);
tstate_delete_common(tstate);
PyEval_ReleaseLock();
}
#endif /* WITH_THREAD */
PyThreadState *
PyThreadState_Get(void)
{
if (_PyThreadState_Current == NULL)
Py_FatalError("PyThreadState_Get: no current thread");
return _PyThreadState_Current;
}
PyThreadState *
PyThreadState_Swap(PyThreadState *newts)
{
PyThreadState *oldts = _PyThreadState_Current;
_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;
}
#endif
return oldts;
}
/* An extension mechanism to store arbitrary additional per-thread state.
PyThreadState_GetDict() returns a dictionary that can be used to hold such
state; the caller should pick a unique key and store its state there. If
PyThreadState_GetDict() returns NULL, an exception has *not* been raised
and the caller should assume no per-thread state is available. */
PyObject *
PyThreadState_GetDict(void)
{
if (_PyThreadState_Current == NULL)
return NULL;
if (_PyThreadState_Current->dict == NULL) {
PyObject *d;
_PyThreadState_Current->dict = d = PyDict_New();
if (d == NULL)
PyErr_Clear();
}
return _PyThreadState_Current->dict;
}
/* Asynchronously raise an exception in a thread.
Requested by Just van Rossum and Alex Martelli.
To prevent naive misuse, you must write your own extension
to call this, or use ctypes. Must be called with the GIL held.
Returns the number of tstates modified (normally 1, but 0 if `id` didn't
match any known thread id). Can be called with exc=NULL to clear an
existing async exception. This raises no exceptions. */
int
PyThreadState_SetAsyncExc(long id, PyObject *exc) {
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);
return 1;
}
}
HEAD_UNLOCK();
return 0;
}
/* Routines for advanced debuggers, requested by David Beazley.
Don't use unless you know what you are doing! */
PyInterpreterState *
PyInterpreterState_Head(void)
{
return interp_head;
}
PyInterpreterState *
PyInterpreterState_Next(PyInterpreterState *interp) {
return interp->next;
}
PyThreadState *
PyInterpreterState_ThreadHead(PyInterpreterState *interp) {
return interp->tstate_head;
}
PyThreadState *
PyThreadState_Next(PyThreadState *tstate) {
return tstate->next;
}
/* The implementation of sys._current_frames(). This is intended to be
called with the GIL held, as it will be when called via
sys._current_frames(). It's possible it would work fine even without
the GIL held, but haven't thought enough about that.
*/
PyObject *
_PyThread_CurrentFrames(void)
{
PyObject *result;
PyInterpreterState *i;
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 mutate 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 = PyInt_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;
}
/* Python "auto thread state" API. */
#ifdef WITH_THREAD
/* Keep this as a static, as it is not reliable! It can only
ever be compared to the state for the *current* thread.
* If not equal, then it doesn't matter that the actual
value may change immediately after comparison, as it can't
possibly change to the current thread's state.
* If equal, then the current thread holds the lock, so the value can't
change until we yield the lock.
*/
static int
PyThreadState_IsCurrent(PyThreadState *tstate)
{
/* Must be the tstate for this thread */
assert(PyGILState_GetThisThreadState()==tstate);
/* On Windows at least, simple reads and writes to 32 bit values
are atomic.
*/
return tstate == _PyThreadState_Current;
}
/* Internal initialization/finalization functions called by
Py_Initialize/Py_Finalize
*/
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);
_PyGILState_NoteThreadState(t);
}
void
_PyGILState_Fini(void)
{
PyThread_delete_key(autoTLSkey);
autoInterpreterState = NULL;
}
/* When a thread state is created for a thread by some mechanism other than
PyGILState_Ensure, it's important that the GILState machinery knows about
it so it doesn't try to create another thread state for the thread (this is
a better fix for SF bug #1010677 than the first one attempted).
*/
static void
_PyGILState_NoteThreadState(PyThreadState* tstate)
{
/* If autoTLSkey isn't initialized, 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 (!autoInterpreterState)
return;
/* 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:
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");
/* PyGILState_Release must not try to delete this thread state. */
tstate->gilstate_counter = 1;
}
/* The public functions */
PyThreadState *
PyGILState_GetThisThreadState(void)
{
if (autoInterpreterState == NULL)
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;
}
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 */
/* 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();
}
#endif /* WITH_THREAD */
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,26 @@
/* Cross platform case insensitive string compare functions
*/
#include "Python.h"
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);
}
int
PyOS_mystricmp(const char *s1, const char *s2)
{
while (*s1 && (tolower((unsigned)*s1++) == tolower((unsigned)*s2++))) {
;
}
return (tolower((unsigned)*s1) - tolower((unsigned)*s2));
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,363 @@
/* Map C struct members to Python object attributes */
#include "Python.h"
#include "structmember.h"
static PyObject *
listmembers(struct memberlist *mlist)
{
int i, n;
PyObject *v;
for (n = 0; mlist[n].name != NULL; n++)
;
v = PyList_New(n);
if (v != NULL) {
for (i = 0; i < n; i++)
PyList_SetItem(v, i,
PyString_FromString(mlist[i].name));
if (PyErr_Occurred()) {
Py_DECREF(v);
v = NULL;
}
else {
PyList_Sort(v);
}
}
return v;
}
PyObject *
PyMember_Get(const char *addr, struct memberlist *mlist, const char *name)
{
struct memberlist *l;
if (strcmp(name, "__members__") == 0)
return listmembers(mlist);
for (l = mlist; l->name != NULL; l++) {
if (strcmp(l->name, name) == 0) {
PyMemberDef copy;
copy.name = l->name;
copy.type = l->type;
copy.offset = l->offset;
copy.flags = l->flags;
copy.doc = NULL;
return PyMember_GetOne(addr, &copy);
}
}
PyErr_SetString(PyExc_AttributeError, name);
return NULL;
}
PyObject *
PyMember_GetOne(const char *addr, PyMemberDef *l)
{
PyObject *v;
if ((l->flags & READ_RESTRICTED) &&
PyEval_GetRestricted()) {
PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
return NULL;
}
addr += l->offset;
switch (l->type) {
case T_BOOL:
v = PyBool_FromLong(*(char*)addr);
break;
case T_BYTE:
v = PyInt_FromLong(*(char*)addr);
break;
case T_UBYTE:
v = PyLong_FromUnsignedLong(*(unsigned char*)addr);
break;
case T_SHORT:
v = PyInt_FromLong(*(short*)addr);
break;
case T_USHORT:
v = PyLong_FromUnsignedLong(*(unsigned short*)addr);
break;
case T_INT:
v = PyInt_FromLong(*(int*)addr);
break;
case T_UINT:
v = PyLong_FromUnsignedLong(*(unsigned int*)addr);
break;
case T_LONG:
v = PyInt_FromLong(*(long*)addr);
break;
case T_ULONG:
v = PyLong_FromUnsignedLong(*(unsigned long*)addr);
break;
case T_PYSSIZET:
v = PyInt_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 = PyString_FromString(*(char**)addr);
break;
case T_STRING_INPLACE:
v = PyString_FromString((char*)addr);
break;
case T_CHAR:
v = PyString_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;
#endif /* HAVE_LONG_LONG */
default:
PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
v = NULL;
}
return v;
}
int
PyMember_Set(char *addr, struct memberlist *mlist, const char *name, PyObject *v)
{
struct memberlist *l;
for (l = mlist; l->name != NULL; l++) {
if (strcmp(l->name, name) == 0) {
PyMemberDef copy;
copy.name = l->name;
copy.type = l->type;
copy.offset = l->offset;
copy.flags = l->flags;
copy.doc = NULL;
return PyMember_SetOne(addr, &copy, v);
}
}
PyErr_SetString(PyExc_AttributeError, name);
return -1;
}
#define WARN(msg) \
do { \
if (PyErr_Warn(PyExc_RuntimeWarning, msg) < 0) \
return -1; \
} while (0)
int
PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
{
PyObject *oldv;
addr += l->offset;
if ((l->flags & READONLY))
{
PyErr_SetString(PyExc_TypeError, "readonly attribute");
return -1;
}
if ((l->flags & PY_WRITE_RESTRICTED) && PyEval_GetRestricted()) {
PyErr_SetString(PyExc_RuntimeError, "restricted 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 = PyInt_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 = PyInt_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 = PyInt_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 = PyInt_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 = PyInt_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 = PyInt_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:
if (PyString_Check(v) && PyString_Size(v) == 1) {
*(char*)addr = PyString_AsString(v)[0];
}
else {
PyErr_BadArgument();
return -1;
}
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 = PyInt_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;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,283 @@
/* Traceback implementation */
#include "Python.h"
#include "code.h"
#include "frameobject.h"
#include "structmember.h"
#include "osdefs.h"
#include "traceback.h"
#define OFF(x) offsetof(PyTracebackObject, x)
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 */
};
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)
}
static int
tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg)
{
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);
}
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_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* 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 */
0, /* 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;
}
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;
}
int
_Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno, int indent)
{
int err = 0;
FILE *xfp = NULL;
char linebuf[2000];
int i;
char namebuf[MAXPATHLEN+1];
if (filename == NULL)
return -1;
/* This is needed by Emacs' compile command */
#define FMT " File \"%.500s\", line %d, in %.500s\n"
xfp = fopen(filename, "r" PY_STDIOTEXTMODE);
if (xfp == NULL) {
/* Search tail of filename in sys.path before giving up */
PyObject *path;
const char *tail = strrchr(filename, SEP);
if (tail == NULL)
tail = filename;
else
tail++;
path = PySys_GetObject("path");
if (path != NULL && PyList_Check(path)) {
Py_ssize_t _npath = PyList_Size(path);
int npath = Py_SAFE_DOWNCAST(_npath, Py_ssize_t, int);
size_t taillen = strlen(tail);
for (i = 0; i < npath; i++) {
PyObject *v = PyList_GetItem(path, i);
if (v == NULL) {
PyErr_Clear();
break;
}
if (PyString_Check(v)) {
size_t len;
len = PyString_GET_SIZE(v);
if (len + 1 + taillen >= MAXPATHLEN)
continue; /* Too long */
strcpy(namebuf, PyString_AsString(v));
if (strlen(namebuf) != len)
continue; /* v contains '\0' */
if (len > 0 && namebuf[len-1] != SEP)
namebuf[len++] = SEP;
strcpy(namebuf+len, tail);
xfp = fopen(namebuf, "r" PY_STDIOTEXTMODE);
if (xfp != NULL) {
break;
}
}
}
}
}
if (xfp == NULL)
return err;
if (err != 0) {
fclose(xfp);
return err;
}
for (i = 0; i < lineno; i++) {
char* pLastChar = &linebuf[sizeof(linebuf)-2];
do {
*pLastChar = '\0';
if (Py_UniversalNewlineFgets(linebuf, sizeof linebuf, xfp, NULL) == NULL)
break;
/* fgets read *something*; if it didn't get as
far as pLastChar, it must have found a newline
or hit the end of the file; if pLastChar is \n,
it obviously found a newline; else we haven't
yet seen a newline, so must continue */
} while (*pLastChar != '\0' && *pLastChar != '\n');
}
if (i == lineno) {
char buf[11];
char *p = linebuf;
while (*p == ' ' || *p == '\t' || *p == '\014')
p++;
/* 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;
}
if (err == 0)
err = PyFile_WriteString(p, f);
if (err == 0 && strchr(p, '\n') == NULL)
err = PyFile_WriteString("\n", f);
}
fclose(xfp);
return err;
}
static int
tb_displayline(PyObject *f, const char *filename, int lineno, const char *name)
{
int err = 0;
char linebuf[2000];
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);
}
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,
PyString_AsString(
tb->tb_frame->f_code->co_filename),
tb->tb_lineno,
PyString_AsString(tb->tb_frame->f_code->co_name));
}
depth--;
tb = tb->tb_next;
if (err == 0)
err = PyErr_CheckSignals();
}
return err;
}
int
PyTraceBack_Print(PyObject *v, PyObject *f)
{
int err;
PyObject *limitv;
long limit = 1000;
if (v == NULL)
return 0;
if (!PyTraceBack_Check(v)) {
PyErr_BadInternalCall();
return -1;
}
limitv = PySys_GetObject("tracebacklimit");
if (limitv && PyInt_Check(limitv)) {
limit = PyInt_AsLong(limitv);
if (limit <= 0)
return 0;
}
err = PyFile_WriteString("Traceback (most recent call last):\n", f);
if (!err)
err = tb_printinternal((PyTracebackObject *)v, f, limit);
return err;
}