Save new folder

This commit is contained in:
2025-11-09 10:02:18 +01:00
commit 5c733eac6b
21738 changed files with 4477854 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
Miscellaneous source files for the main Python shared library

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,64 @@
#include "Python.h"
#include "asdl.h"
asdl_seq *
_Py_asdl_seq_new(Py_ssize_t size, PyArena *arena)
{
asdl_seq *seq = NULL;
size_t n;
/* check size is sane */
if (size < 0 ||
(size && (((size_t)size - 1) > (SIZE_MAX / sizeof(void *))))) {
PyErr_NoMemory();
return NULL;
}
n = (size ? (sizeof(void *) * (size - 1)) : 0);
/* check if size can be added safely */
if (n > 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 *
_Py_asdl_int_seq_new(Py_ssize_t size, PyArena *arena)
{
asdl_int_seq *seq = NULL;
size_t n;
/* check size is sane */
if (size < 0 ||
(size && (((size_t)size - 1) > (SIZE_MAX / sizeof(void *))))) {
PyErr_NoMemory();
return NULL;
}
n = (size ? (sizeof(void *) * (size - 1)) : 0);
/* check if size can be added safely */
if (n > 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

Binary file not shown.

View File

@ -0,0 +1,752 @@
/* AST Optimizer */
#include "Python.h"
#include "Python-ast.h"
#include "ast.h"
static int
make_const(expr_ty node, PyObject *val, PyArena *arena)
{
if (val == NULL) {
if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
return 0;
}
PyErr_Clear();
return 1;
}
if (PyArena_AddPyObject(arena, val) < 0) {
Py_DECREF(val);
return 0;
}
node->kind = Constant_kind;
node->v.Constant.kind = NULL;
node->v.Constant.value = val;
return 1;
}
#define COPY_NODE(TO, FROM) (memcpy((TO), (FROM), sizeof(struct _expr)))
static PyObject*
unary_not(PyObject *v)
{
int r = PyObject_IsTrue(v);
if (r < 0)
return NULL;
return PyBool_FromLong(!r);
}
static int
fold_unaryop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
{
expr_ty arg = node->v.UnaryOp.operand;
if (arg->kind != Constant_kind) {
/* Fold not into comparison */
if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
asdl_seq_LEN(arg->v.Compare.ops) == 1) {
/* Eq and NotEq are often implemented in terms of one another, so
folding not (self == other) into self != other breaks implementation
of !=. Detecting such cases doesn't seem worthwhile.
Python uses </> for 'is subset'/'is superset' operations on sets.
They don't satisfy not folding laws. */
int op = asdl_seq_GET(arg->v.Compare.ops, 0);
switch (op) {
case Is:
op = IsNot;
break;
case IsNot:
op = Is;
break;
case In:
op = NotIn;
break;
case NotIn:
op = In;
break;
default:
op = 0;
}
if (op) {
asdl_seq_SET(arg->v.Compare.ops, 0, op);
COPY_NODE(node, arg);
return 1;
}
}
return 1;
}
typedef PyObject *(*unary_op)(PyObject*);
static const unary_op ops[] = {
[Invert] = PyNumber_Invert,
[Not] = unary_not,
[UAdd] = PyNumber_Positive,
[USub] = PyNumber_Negative,
};
PyObject *newval = ops[node->v.UnaryOp.op](arg->v.Constant.value);
return make_const(node, newval, arena);
}
/* Check whether a collection doesn't containing too much items (including
subcollections). This protects from creating a constant that needs
too much time for calculating a hash.
"limit" is the maximal number of items.
Returns the negative number if the total number of items exceeds the
limit. Otherwise returns the limit minus the total number of items.
*/
static Py_ssize_t
check_complexity(PyObject *obj, Py_ssize_t limit)
{
if (PyTuple_Check(obj)) {
Py_ssize_t i;
limit -= PyTuple_GET_SIZE(obj);
for (i = 0; limit >= 0 && i < PyTuple_GET_SIZE(obj); i++) {
limit = check_complexity(PyTuple_GET_ITEM(obj, i), limit);
}
return limit;
}
else if (PyFrozenSet_Check(obj)) {
Py_ssize_t i = 0;
PyObject *item;
Py_hash_t hash;
limit -= PySet_GET_SIZE(obj);
while (limit >= 0 && _PySet_NextEntry(obj, &i, &item, &hash)) {
limit = check_complexity(item, limit);
}
}
return limit;
}
#define MAX_INT_SIZE 128 /* bits */
#define MAX_COLLECTION_SIZE 256 /* items */
#define MAX_STR_SIZE 4096 /* characters */
#define MAX_TOTAL_ITEMS 1024 /* including nested collections */
static PyObject *
safe_multiply(PyObject *v, PyObject *w)
{
if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
size_t vbits = _PyLong_NumBits(v);
size_t wbits = _PyLong_NumBits(w);
if (vbits == (size_t)-1 || wbits == (size_t)-1) {
return NULL;
}
if (vbits + wbits > MAX_INT_SIZE) {
return NULL;
}
}
else if (PyLong_Check(v) && (PyTuple_Check(w) || PyFrozenSet_Check(w))) {
Py_ssize_t size = PyTuple_Check(w) ? PyTuple_GET_SIZE(w) :
PySet_GET_SIZE(w);
if (size) {
long n = PyLong_AsLong(v);
if (n < 0 || n > MAX_COLLECTION_SIZE / size) {
return NULL;
}
if (n && check_complexity(w, MAX_TOTAL_ITEMS / n) < 0) {
return NULL;
}
}
}
else if (PyLong_Check(v) && (PyUnicode_Check(w) || PyBytes_Check(w))) {
Py_ssize_t size = PyUnicode_Check(w) ? PyUnicode_GET_LENGTH(w) :
PyBytes_GET_SIZE(w);
if (size) {
long n = PyLong_AsLong(v);
if (n < 0 || n > MAX_STR_SIZE / size) {
return NULL;
}
}
}
else if (PyLong_Check(w) &&
(PyTuple_Check(v) || PyFrozenSet_Check(v) ||
PyUnicode_Check(v) || PyBytes_Check(v)))
{
return safe_multiply(w, v);
}
return PyNumber_Multiply(v, w);
}
static PyObject *
safe_power(PyObject *v, PyObject *w)
{
if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w) > 0) {
size_t vbits = _PyLong_NumBits(v);
size_t wbits = PyLong_AsSize_t(w);
if (vbits == (size_t)-1 || wbits == (size_t)-1) {
return NULL;
}
if (vbits > MAX_INT_SIZE / wbits) {
return NULL;
}
}
return PyNumber_Power(v, w, Py_None);
}
static PyObject *
safe_lshift(PyObject *v, PyObject *w)
{
if (PyLong_Check(v) && PyLong_Check(w) && Py_SIZE(v) && Py_SIZE(w)) {
size_t vbits = _PyLong_NumBits(v);
size_t wbits = PyLong_AsSize_t(w);
if (vbits == (size_t)-1 || wbits == (size_t)-1) {
return NULL;
}
if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) {
return NULL;
}
}
return PyNumber_Lshift(v, w);
}
static PyObject *
safe_mod(PyObject *v, PyObject *w)
{
if (PyUnicode_Check(v) || PyBytes_Check(v)) {
return NULL;
}
return PyNumber_Remainder(v, w);
}
static int
fold_binop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
{
expr_ty lhs, rhs;
lhs = node->v.BinOp.left;
rhs = node->v.BinOp.right;
if (lhs->kind != Constant_kind || rhs->kind != Constant_kind) {
return 1;
}
PyObject *lv = lhs->v.Constant.value;
PyObject *rv = rhs->v.Constant.value;
PyObject *newval;
switch (node->v.BinOp.op) {
case Add:
newval = PyNumber_Add(lv, rv);
break;
case Sub:
newval = PyNumber_Subtract(lv, rv);
break;
case Mult:
newval = safe_multiply(lv, rv);
break;
case Div:
newval = PyNumber_TrueDivide(lv, rv);
break;
case FloorDiv:
newval = PyNumber_FloorDivide(lv, rv);
break;
case Mod:
newval = safe_mod(lv, rv);
break;
case Pow:
newval = safe_power(lv, rv);
break;
case LShift:
newval = safe_lshift(lv, rv);
break;
case RShift:
newval = PyNumber_Rshift(lv, rv);
break;
case BitOr:
newval = PyNumber_Or(lv, rv);
break;
case BitXor:
newval = PyNumber_Xor(lv, rv);
break;
case BitAnd:
newval = PyNumber_And(lv, rv);
break;
default: // Unknown operator
return 1;
}
return make_const(node, newval, arena);
}
static PyObject*
make_const_tuple(asdl_seq *elts)
{
for (int i = 0; i < asdl_seq_LEN(elts); i++) {
expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
if (e->kind != Constant_kind) {
return NULL;
}
}
PyObject *newval = PyTuple_New(asdl_seq_LEN(elts));
if (newval == NULL) {
return NULL;
}
for (int i = 0; i < asdl_seq_LEN(elts); i++) {
expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
PyObject *v = e->v.Constant.value;
Py_INCREF(v);
PyTuple_SET_ITEM(newval, i, v);
}
return newval;
}
static int
fold_tuple(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
{
PyObject *newval;
if (node->v.Tuple.ctx != Load)
return 1;
newval = make_const_tuple(node->v.Tuple.elts);
return make_const(node, newval, arena);
}
static int
fold_subscr(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
{
PyObject *newval;
expr_ty arg, idx;
arg = node->v.Subscript.value;
idx = node->v.Subscript.slice;
if (node->v.Subscript.ctx != Load ||
arg->kind != Constant_kind ||
idx->kind != Constant_kind)
{
return 1;
}
newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value);
return make_const(node, newval, arena);
}
/* Change literal list or set of constants into constant
tuple or frozenset respectively. Change literal list of
non-constants into tuple.
Used for right operand of "in" and "not in" tests and for iterable
in "for" loop and comprehensions.
*/
static int
fold_iter(expr_ty arg, PyArena *arena, _PyASTOptimizeState *state)
{
PyObject *newval;
if (arg->kind == List_kind) {
/* First change a list into tuple. */
asdl_seq *elts = arg->v.List.elts;
Py_ssize_t n = asdl_seq_LEN(elts);
for (Py_ssize_t i = 0; i < n; i++) {
expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
if (e->kind == Starred_kind) {
return 1;
}
}
expr_context_ty ctx = arg->v.List.ctx;
arg->kind = Tuple_kind;
arg->v.Tuple.elts = elts;
arg->v.Tuple.ctx = ctx;
/* Try to create a constant tuple. */
newval = make_const_tuple(elts);
}
else if (arg->kind == Set_kind) {
newval = make_const_tuple(arg->v.Set.elts);
if (newval) {
Py_SETREF(newval, PyFrozenSet_New(newval));
}
}
else {
return 1;
}
return make_const(arg, newval, arena);
}
static int
fold_compare(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
{
asdl_int_seq *ops;
asdl_seq *args;
Py_ssize_t i;
ops = node->v.Compare.ops;
args = node->v.Compare.comparators;
/* TODO: optimize cases with literal arguments. */
/* Change literal list or set in 'in' or 'not in' into
tuple or frozenset respectively. */
i = asdl_seq_LEN(ops) - 1;
int op = asdl_seq_GET(ops, i);
if (op == In || op == NotIn) {
if (!fold_iter((expr_ty)asdl_seq_GET(args, i), arena, state)) {
return 0;
}
}
return 1;
}
static int astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
static int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
static int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
static int astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
static int astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
static int astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
#define CALL(FUNC, TYPE, ARG) \
if (!FUNC((ARG), ctx_, state)) \
return 0;
#define CALL_OPT(FUNC, TYPE, ARG) \
if ((ARG) != NULL && !FUNC((ARG), ctx_, state)) \
return 0;
#define CALL_SEQ(FUNC, TYPE, ARG) { \
int i; \
asdl_seq *seq = (ARG); /* avoid variable capture */ \
for (i = 0; i < asdl_seq_LEN(seq); i++) { \
TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
if (elt != NULL && !FUNC(elt, ctx_, state)) \
return 0; \
} \
}
#define CALL_INT_SEQ(FUNC, TYPE, ARG) { \
int i; \
asdl_int_seq *seq = (ARG); /* avoid variable capture */ \
for (i = 0; i < asdl_seq_LEN(seq); i++) { \
TYPE elt = (TYPE)asdl_seq_GET(seq, i); \
if (!FUNC(elt, ctx_, state)) \
return 0; \
} \
}
static int
astfold_body(asdl_seq *stmts, PyArena *ctx_, _PyASTOptimizeState *state)
{
int docstring = _PyAST_GetDocString(stmts) != NULL;
CALL_SEQ(astfold_stmt, stmt_ty, stmts);
if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
asdl_seq *values = _Py_asdl_seq_new(1, ctx_);
if (!values) {
return 0;
}
asdl_seq_SET(values, 0, st->v.Expr.value);
expr_ty expr = JoinedStr(values, st->lineno, st->col_offset,
st->end_lineno, st->end_col_offset, ctx_);
if (!expr) {
return 0;
}
st->v.Expr.value = expr;
}
return 1;
}
static int
astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
{
switch (node_->kind) {
case Module_kind:
CALL(astfold_body, asdl_seq, node_->v.Module.body);
break;
case Interactive_kind:
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Interactive.body);
break;
case Expression_kind:
CALL(astfold_expr, expr_ty, node_->v.Expression.body);
break;
default:
break;
}
return 1;
}
static int
astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
{
switch (node_->kind) {
case BoolOp_kind:
CALL_SEQ(astfold_expr, expr_ty, node_->v.BoolOp.values);
break;
case BinOp_kind:
CALL(astfold_expr, expr_ty, node_->v.BinOp.left);
CALL(astfold_expr, expr_ty, node_->v.BinOp.right);
CALL(fold_binop, expr_ty, node_);
break;
case UnaryOp_kind:
CALL(astfold_expr, expr_ty, node_->v.UnaryOp.operand);
CALL(fold_unaryop, expr_ty, node_);
break;
case Lambda_kind:
CALL(astfold_arguments, arguments_ty, node_->v.Lambda.args);
CALL(astfold_expr, expr_ty, node_->v.Lambda.body);
break;
case IfExp_kind:
CALL(astfold_expr, expr_ty, node_->v.IfExp.test);
CALL(astfold_expr, expr_ty, node_->v.IfExp.body);
CALL(astfold_expr, expr_ty, node_->v.IfExp.orelse);
break;
case Dict_kind:
CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.keys);
CALL_SEQ(astfold_expr, expr_ty, node_->v.Dict.values);
break;
case Set_kind:
CALL_SEQ(astfold_expr, expr_ty, node_->v.Set.elts);
break;
case ListComp_kind:
CALL(astfold_expr, expr_ty, node_->v.ListComp.elt);
CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.ListComp.generators);
break;
case SetComp_kind:
CALL(astfold_expr, expr_ty, node_->v.SetComp.elt);
CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.SetComp.generators);
break;
case DictComp_kind:
CALL(astfold_expr, expr_ty, node_->v.DictComp.key);
CALL(astfold_expr, expr_ty, node_->v.DictComp.value);
CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.DictComp.generators);
break;
case GeneratorExp_kind:
CALL(astfold_expr, expr_ty, node_->v.GeneratorExp.elt);
CALL_SEQ(astfold_comprehension, comprehension_ty, node_->v.GeneratorExp.generators);
break;
case Await_kind:
CALL(astfold_expr, expr_ty, node_->v.Await.value);
break;
case Yield_kind:
CALL_OPT(astfold_expr, expr_ty, node_->v.Yield.value);
break;
case YieldFrom_kind:
CALL(astfold_expr, expr_ty, node_->v.YieldFrom.value);
break;
case Compare_kind:
CALL(astfold_expr, expr_ty, node_->v.Compare.left);
CALL_SEQ(astfold_expr, expr_ty, node_->v.Compare.comparators);
CALL(fold_compare, expr_ty, node_);
break;
case Call_kind:
CALL(astfold_expr, expr_ty, node_->v.Call.func);
CALL_SEQ(astfold_expr, expr_ty, node_->v.Call.args);
CALL_SEQ(astfold_keyword, keyword_ty, node_->v.Call.keywords);
break;
case FormattedValue_kind:
CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value);
CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec);
break;
case JoinedStr_kind:
CALL_SEQ(astfold_expr, expr_ty, node_->v.JoinedStr.values);
break;
case Attribute_kind:
CALL(astfold_expr, expr_ty, node_->v.Attribute.value);
break;
case Subscript_kind:
CALL(astfold_expr, expr_ty, node_->v.Subscript.value);
CALL(astfold_expr, expr_ty, node_->v.Subscript.slice);
CALL(fold_subscr, expr_ty, node_);
break;
case Starred_kind:
CALL(astfold_expr, expr_ty, node_->v.Starred.value);
break;
case Slice_kind:
CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower);
CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper);
CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step);
break;
case List_kind:
CALL_SEQ(astfold_expr, expr_ty, node_->v.List.elts);
break;
case Tuple_kind:
CALL_SEQ(astfold_expr, expr_ty, node_->v.Tuple.elts);
CALL(fold_tuple, expr_ty, node_);
break;
case Name_kind:
if (node_->v.Name.ctx == Load &&
_PyUnicode_EqualToASCIIString(node_->v.Name.id, "__debug__")) {
return make_const(node_, PyBool_FromLong(!state->optimize), ctx_);
}
break;
default:
break;
}
return 1;
}
static int
astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
{
CALL(astfold_expr, expr_ty, node_->value);
return 1;
}
static int
astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
{
CALL(astfold_expr, expr_ty, node_->target);
CALL(astfold_expr, expr_ty, node_->iter);
CALL_SEQ(astfold_expr, expr_ty, node_->ifs);
CALL(fold_iter, expr_ty, node_->iter);
return 1;
}
static int
astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
{
CALL_SEQ(astfold_arg, arg_ty, node_->posonlyargs);
CALL_SEQ(astfold_arg, arg_ty, node_->args);
CALL_OPT(astfold_arg, arg_ty, node_->vararg);
CALL_SEQ(astfold_arg, arg_ty, node_->kwonlyargs);
CALL_SEQ(astfold_expr, expr_ty, node_->kw_defaults);
CALL_OPT(astfold_arg, arg_ty, node_->kwarg);
CALL_SEQ(astfold_expr, expr_ty, node_->defaults);
return 1;
}
static int
astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
{
if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
CALL_OPT(astfold_expr, expr_ty, node_->annotation);
}
return 1;
}
static int
astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
{
switch (node_->kind) {
case FunctionDef_kind:
CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
CALL_SEQ(astfold_expr, expr_ty, node_->v.FunctionDef.decorator_list);
if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);
}
break;
case AsyncFunctionDef_kind:
CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
CALL_SEQ(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.decorator_list);
if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);
}
break;
case ClassDef_kind:
CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.bases);
CALL_SEQ(astfold_keyword, keyword_ty, node_->v.ClassDef.keywords);
CALL(astfold_body, asdl_seq, node_->v.ClassDef.body);
CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.decorator_list);
break;
case Return_kind:
CALL_OPT(astfold_expr, expr_ty, node_->v.Return.value);
break;
case Delete_kind:
CALL_SEQ(astfold_expr, expr_ty, node_->v.Delete.targets);
break;
case Assign_kind:
CALL_SEQ(astfold_expr, expr_ty, node_->v.Assign.targets);
CALL(astfold_expr, expr_ty, node_->v.Assign.value);
break;
case AugAssign_kind:
CALL(astfold_expr, expr_ty, node_->v.AugAssign.target);
CALL(astfold_expr, expr_ty, node_->v.AugAssign.value);
break;
case AnnAssign_kind:
CALL(astfold_expr, expr_ty, node_->v.AnnAssign.target);
if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
CALL(astfold_expr, expr_ty, node_->v.AnnAssign.annotation);
}
CALL_OPT(astfold_expr, expr_ty, node_->v.AnnAssign.value);
break;
case For_kind:
CALL(astfold_expr, expr_ty, node_->v.For.target);
CALL(astfold_expr, expr_ty, node_->v.For.iter);
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.body);
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.For.orelse);
CALL(fold_iter, expr_ty, node_->v.For.iter);
break;
case AsyncFor_kind:
CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.body);
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFor.orelse);
break;
case While_kind:
CALL(astfold_expr, expr_ty, node_->v.While.test);
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.body);
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.While.orelse);
break;
case If_kind:
CALL(astfold_expr, expr_ty, node_->v.If.test);
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.body);
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.If.orelse);
break;
case With_kind:
CALL_SEQ(astfold_withitem, withitem_ty, node_->v.With.items);
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.With.body);
break;
case AsyncWith_kind:
CALL_SEQ(astfold_withitem, withitem_ty, node_->v.AsyncWith.items);
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncWith.body);
break;
case Raise_kind:
CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.exc);
CALL_OPT(astfold_expr, expr_ty, node_->v.Raise.cause);
break;
case Try_kind:
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.body);
CALL_SEQ(astfold_excepthandler, excepthandler_ty, node_->v.Try.handlers);
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.orelse);
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Try.finalbody);
break;
case Assert_kind:
CALL(astfold_expr, expr_ty, node_->v.Assert.test);
CALL_OPT(astfold_expr, expr_ty, node_->v.Assert.msg);
break;
case Expr_kind:
CALL(astfold_expr, expr_ty, node_->v.Expr.value);
break;
default:
break;
}
return 1;
}
static int
astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
{
switch (node_->kind) {
case ExceptHandler_kind:
CALL_OPT(astfold_expr, expr_ty, node_->v.ExceptHandler.type);
CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ExceptHandler.body);
break;
default:
break;
}
return 1;
}
static int
astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
{
CALL(astfold_expr, expr_ty, node_->context_expr);
CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
return 1;
}
#undef CALL
#undef CALL_OPT
#undef CALL_SEQ
#undef CALL_INT_SEQ
int
_PyAST_Optimize(mod_ty mod, PyArena *arena, _PyASTOptimizeState *state)
{
int ret = astfold_mod(mod, arena, state);
assert(ret || PyErr_Occurred());
return ret;
}

View File

@ -0,0 +1,972 @@
#include <float.h> /* DBL_MAX_10_EXP */
#include <stdbool.h>
#include "Python.h"
#include "Python-ast.h"
static PyObject *_str_open_br;
static PyObject *_str_dbl_open_br;
static PyObject *_str_close_br;
static PyObject *_str_dbl_close_br;
static PyObject *_str_inf;
static PyObject *_str_replace_inf;
/* Forward declarations for recursion via helper functions. */
static PyObject *
expr_as_unicode(expr_ty e, int level);
static int
append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level);
static int
append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec);
static int
append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e);
static int
append_ast_slice(_PyUnicodeWriter *writer, expr_ty e);
static int
append_charp(_PyUnicodeWriter *writer, const char *charp)
{
return _PyUnicodeWriter_WriteASCIIString(writer, charp, -1);
}
#define APPEND_STR_FINISH(str) do { \
return append_charp(writer, (str)); \
} while (0)
#define APPEND_STR(str) do { \
if (-1 == append_charp(writer, (str))) { \
return -1; \
} \
} while (0)
#define APPEND_STR_IF(cond, str) do { \
if ((cond) && -1 == append_charp(writer, (str))) { \
return -1; \
} \
} while (0)
#define APPEND_STR_IF_NOT_FIRST(str) do { \
APPEND_STR_IF(!first, (str)); \
first = false; \
} while (0)
#define APPEND_EXPR(expr, pr) do { \
if (-1 == append_ast_expr(writer, (expr), (pr))) { \
return -1; \
} \
} while (0)
#define APPEND(type, value) do { \
if (-1 == append_ast_ ## type(writer, (value))) { \
return -1; \
} \
} while (0)
static int
append_repr(_PyUnicodeWriter *writer, PyObject *obj)
{
PyObject *repr = PyObject_Repr(obj);
if (!repr) {
return -1;
}
if ((PyFloat_CheckExact(obj) && Py_IS_INFINITY(PyFloat_AS_DOUBLE(obj))) ||
PyComplex_CheckExact(obj))
{
PyObject *new_repr = PyUnicode_Replace(
repr,
_str_inf,
_str_replace_inf,
-1
);
Py_DECREF(repr);
if (!new_repr) {
return -1;
}
repr = new_repr;
}
int ret = _PyUnicodeWriter_WriteStr(writer, repr);
Py_DECREF(repr);
return ret;
}
/* Priority levels */
enum {
PR_TUPLE,
PR_TEST, /* 'if'-'else', 'lambda' */
PR_OR, /* 'or' */
PR_AND, /* 'and' */
PR_NOT, /* 'not' */
PR_CMP, /* '<', '>', '==', '>=', '<=', '!=',
'in', 'not in', 'is', 'is not' */
PR_EXPR,
PR_BOR = PR_EXPR, /* '|' */
PR_BXOR, /* '^' */
PR_BAND, /* '&' */
PR_SHIFT, /* '<<', '>>' */
PR_ARITH, /* '+', '-' */
PR_TERM, /* '*', '@', '/', '%', '//' */
PR_FACTOR, /* unary '+', '-', '~' */
PR_POWER, /* '**' */
PR_AWAIT, /* 'await' */
PR_ATOM,
};
static int
append_ast_boolop(_PyUnicodeWriter *writer, expr_ty e, int level)
{
Py_ssize_t i, value_count;
asdl_seq *values;
const char *op = (e->v.BoolOp.op == And) ? " and " : " or ";
int pr = (e->v.BoolOp.op == And) ? PR_AND : PR_OR;
APPEND_STR_IF(level > pr, "(");
values = e->v.BoolOp.values;
value_count = asdl_seq_LEN(values);
for (i = 0; i < value_count; ++i) {
APPEND_STR_IF(i > 0, op);
APPEND_EXPR((expr_ty)asdl_seq_GET(values, i), pr + 1);
}
APPEND_STR_IF(level > pr, ")");
return 0;
}
static int
append_ast_binop(_PyUnicodeWriter *writer, expr_ty e, int level)
{
const char *op;
int pr;
bool rassoc = false; /* is right-associative? */
switch (e->v.BinOp.op) {
case Add: op = " + "; pr = PR_ARITH; break;
case Sub: op = " - "; pr = PR_ARITH; break;
case Mult: op = " * "; pr = PR_TERM; break;
case MatMult: op = " @ "; pr = PR_TERM; break;
case Div: op = " / "; pr = PR_TERM; break;
case Mod: op = " % "; pr = PR_TERM; break;
case LShift: op = " << "; pr = PR_SHIFT; break;
case RShift: op = " >> "; pr = PR_SHIFT; break;
case BitOr: op = " | "; pr = PR_BOR; break;
case BitXor: op = " ^ "; pr = PR_BXOR; break;
case BitAnd: op = " & "; pr = PR_BAND; break;
case FloorDiv: op = " // "; pr = PR_TERM; break;
case Pow: op = " ** "; pr = PR_POWER; rassoc = true; break;
default:
PyErr_SetString(PyExc_SystemError,
"unknown binary operator");
return -1;
}
APPEND_STR_IF(level > pr, "(");
APPEND_EXPR(e->v.BinOp.left, pr + rassoc);
APPEND_STR(op);
APPEND_EXPR(e->v.BinOp.right, pr + !rassoc);
APPEND_STR_IF(level > pr, ")");
return 0;
}
static int
append_ast_unaryop(_PyUnicodeWriter *writer, expr_ty e, int level)
{
const char *op;
int pr;
switch (e->v.UnaryOp.op) {
case Invert: op = "~"; pr = PR_FACTOR; break;
case Not: op = "not "; pr = PR_NOT; break;
case UAdd: op = "+"; pr = PR_FACTOR; break;
case USub: op = "-"; pr = PR_FACTOR; break;
default:
PyErr_SetString(PyExc_SystemError,
"unknown unary operator");
return -1;
}
APPEND_STR_IF(level > pr, "(");
APPEND_STR(op);
APPEND_EXPR(e->v.UnaryOp.operand, pr);
APPEND_STR_IF(level > pr, ")");
return 0;
}
static int
append_ast_arg(_PyUnicodeWriter *writer, arg_ty arg)
{
if (-1 == _PyUnicodeWriter_WriteStr(writer, arg->arg)) {
return -1;
}
if (arg->annotation) {
APPEND_STR(": ");
APPEND_EXPR(arg->annotation, PR_TEST);
}
return 0;
}
static int
append_ast_args(_PyUnicodeWriter *writer, arguments_ty args)
{
bool first;
Py_ssize_t i, di, arg_count, posonlyarg_count, default_count;
first = true;
/* positional-only and positional arguments with defaults */
posonlyarg_count = asdl_seq_LEN(args->posonlyargs);
arg_count = asdl_seq_LEN(args->args);
default_count = asdl_seq_LEN(args->defaults);
for (i = 0; i < posonlyarg_count + arg_count; i++) {
APPEND_STR_IF_NOT_FIRST(", ");
if (i < posonlyarg_count){
APPEND(arg, (arg_ty)asdl_seq_GET(args->posonlyargs, i));
} else {
APPEND(arg, (arg_ty)asdl_seq_GET(args->args, i-posonlyarg_count));
}
di = i - posonlyarg_count - arg_count + default_count;
if (di >= 0) {
APPEND_STR("=");
APPEND_EXPR((expr_ty)asdl_seq_GET(args->defaults, di), PR_TEST);
}
if (posonlyarg_count && i + 1 == posonlyarg_count) {
APPEND_STR(", /");
}
}
/* vararg, or bare '*' if no varargs but keyword-only arguments present */
if (args->vararg || asdl_seq_LEN(args->kwonlyargs)) {
APPEND_STR_IF_NOT_FIRST(", ");
APPEND_STR("*");
if (args->vararg) {
APPEND(arg, args->vararg);
}
}
/* keyword-only arguments */
arg_count = asdl_seq_LEN(args->kwonlyargs);
default_count = asdl_seq_LEN(args->kw_defaults);
for (i = 0; i < arg_count; i++) {
APPEND_STR_IF_NOT_FIRST(", ");
APPEND(arg, (arg_ty)asdl_seq_GET(args->kwonlyargs, i));
di = i - arg_count + default_count;
if (di >= 0) {
expr_ty default_ = (expr_ty)asdl_seq_GET(args->kw_defaults, di);
if (default_) {
APPEND_STR("=");
APPEND_EXPR(default_, PR_TEST);
}
}
}
/* **kwargs */
if (args->kwarg) {
APPEND_STR_IF_NOT_FIRST(", ");
APPEND_STR("**");
APPEND(arg, args->kwarg);
}
return 0;
}
static int
append_ast_lambda(_PyUnicodeWriter *writer, expr_ty e, int level)
{
APPEND_STR_IF(level > PR_TEST, "(");
Py_ssize_t n_positional = (asdl_seq_LEN(e->v.Lambda.args->args) +
asdl_seq_LEN(e->v.Lambda.args->posonlyargs));
APPEND_STR(n_positional ? "lambda " : "lambda");
APPEND(args, e->v.Lambda.args);
APPEND_STR(": ");
APPEND_EXPR(e->v.Lambda.body, PR_TEST);
APPEND_STR_IF(level > PR_TEST, ")");
return 0;
}
static int
append_ast_ifexp(_PyUnicodeWriter *writer, expr_ty e, int level)
{
APPEND_STR_IF(level > PR_TEST, "(");
APPEND_EXPR(e->v.IfExp.body, PR_TEST + 1);
APPEND_STR(" if ");
APPEND_EXPR(e->v.IfExp.test, PR_TEST + 1);
APPEND_STR(" else ");
APPEND_EXPR(e->v.IfExp.orelse, PR_TEST);
APPEND_STR_IF(level > PR_TEST, ")");
return 0;
}
static int
append_ast_dict(_PyUnicodeWriter *writer, expr_ty e)
{
Py_ssize_t i, value_count;
expr_ty key_node;
APPEND_STR("{");
value_count = asdl_seq_LEN(e->v.Dict.values);
for (i = 0; i < value_count; i++) {
APPEND_STR_IF(i > 0, ", ");
key_node = (expr_ty)asdl_seq_GET(e->v.Dict.keys, i);
if (key_node != NULL) {
APPEND_EXPR(key_node, PR_TEST);
APPEND_STR(": ");
APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Dict.values, i), PR_TEST);
}
else {
APPEND_STR("**");
APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Dict.values, i), PR_EXPR);
}
}
APPEND_STR_FINISH("}");
}
static int
append_ast_set(_PyUnicodeWriter *writer, expr_ty e)
{
Py_ssize_t i, elem_count;
APPEND_STR("{");
elem_count = asdl_seq_LEN(e->v.Set.elts);
for (i = 0; i < elem_count; i++) {
APPEND_STR_IF(i > 0, ", ");
APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Set.elts, i), PR_TEST);
}
APPEND_STR_FINISH("}");
}
static int
append_ast_list(_PyUnicodeWriter *writer, expr_ty e)
{
Py_ssize_t i, elem_count;
APPEND_STR("[");
elem_count = asdl_seq_LEN(e->v.List.elts);
for (i = 0; i < elem_count; i++) {
APPEND_STR_IF(i > 0, ", ");
APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.List.elts, i), PR_TEST);
}
APPEND_STR_FINISH("]");
}
static int
append_ast_tuple(_PyUnicodeWriter *writer, expr_ty e, int level)
{
Py_ssize_t i, elem_count;
elem_count = asdl_seq_LEN(e->v.Tuple.elts);
if (elem_count == 0) {
APPEND_STR_FINISH("()");
}
APPEND_STR_IF(level > PR_TUPLE, "(");
for (i = 0; i < elem_count; i++) {
APPEND_STR_IF(i > 0, ", ");
APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Tuple.elts, i), PR_TEST);
}
APPEND_STR_IF(elem_count == 1, ",");
APPEND_STR_IF(level > PR_TUPLE, ")");
return 0;
}
static int
append_ast_comprehension(_PyUnicodeWriter *writer, comprehension_ty gen)
{
Py_ssize_t i, if_count;
APPEND_STR(gen->is_async ? " async for " : " for ");
APPEND_EXPR(gen->target, PR_TUPLE);
APPEND_STR(" in ");
APPEND_EXPR(gen->iter, PR_TEST + 1);
if_count = asdl_seq_LEN(gen->ifs);
for (i = 0; i < if_count; i++) {
APPEND_STR(" if ");
APPEND_EXPR((expr_ty)asdl_seq_GET(gen->ifs, i), PR_TEST + 1);
}
return 0;
}
static int
append_ast_comprehensions(_PyUnicodeWriter *writer, asdl_seq *comprehensions)
{
Py_ssize_t i, gen_count;
gen_count = asdl_seq_LEN(comprehensions);
for (i = 0; i < gen_count; i++) {
APPEND(comprehension, (comprehension_ty)asdl_seq_GET(comprehensions, i));
}
return 0;
}
static int
append_ast_genexp(_PyUnicodeWriter *writer, expr_ty e)
{
APPEND_STR("(");
APPEND_EXPR(e->v.GeneratorExp.elt, PR_TEST);
APPEND(comprehensions, e->v.GeneratorExp.generators);
APPEND_STR_FINISH(")");
}
static int
append_ast_listcomp(_PyUnicodeWriter *writer, expr_ty e)
{
APPEND_STR("[");
APPEND_EXPR(e->v.ListComp.elt, PR_TEST);
APPEND(comprehensions, e->v.ListComp.generators);
APPEND_STR_FINISH("]");
}
static int
append_ast_setcomp(_PyUnicodeWriter *writer, expr_ty e)
{
APPEND_STR("{");
APPEND_EXPR(e->v.SetComp.elt, PR_TEST);
APPEND(comprehensions, e->v.SetComp.generators);
APPEND_STR_FINISH("}");
}
static int
append_ast_dictcomp(_PyUnicodeWriter *writer, expr_ty e)
{
APPEND_STR("{");
APPEND_EXPR(e->v.DictComp.key, PR_TEST);
APPEND_STR(": ");
APPEND_EXPR(e->v.DictComp.value, PR_TEST);
APPEND(comprehensions, e->v.DictComp.generators);
APPEND_STR_FINISH("}");
}
static int
append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, int level)
{
const char *op;
Py_ssize_t i, comparator_count;
asdl_seq *comparators;
asdl_int_seq *ops;
APPEND_STR_IF(level > PR_CMP, "(");
comparators = e->v.Compare.comparators;
ops = e->v.Compare.ops;
comparator_count = asdl_seq_LEN(comparators);
assert(comparator_count > 0);
assert(comparator_count == asdl_seq_LEN(ops));
APPEND_EXPR(e->v.Compare.left, PR_CMP + 1);
for (i = 0; i < comparator_count; i++) {
switch ((cmpop_ty)asdl_seq_GET(ops, i)) {
case Eq:
op = " == ";
break;
case NotEq:
op = " != ";
break;
case Lt:
op = " < ";
break;
case LtE:
op = " <= ";
break;
case Gt:
op = " > ";
break;
case GtE:
op = " >= ";
break;
case Is:
op = " is ";
break;
case IsNot:
op = " is not ";
break;
case In:
op = " in ";
break;
case NotIn:
op = " not in ";
break;
default:
PyErr_SetString(PyExc_SystemError,
"unexpected comparison kind");
return -1;
}
APPEND_STR(op);
APPEND_EXPR((expr_ty)asdl_seq_GET(comparators, i), PR_CMP + 1);
}
APPEND_STR_IF(level > PR_CMP, ")");
return 0;
}
static int
append_ast_keyword(_PyUnicodeWriter *writer, keyword_ty kw)
{
if (kw->arg == NULL) {
APPEND_STR("**");
}
else {
if (-1 == _PyUnicodeWriter_WriteStr(writer, kw->arg)) {
return -1;
}
APPEND_STR("=");
}
APPEND_EXPR(kw->value, PR_TEST);
return 0;
}
static int
append_ast_call(_PyUnicodeWriter *writer, expr_ty e)
{
bool first;
Py_ssize_t i, arg_count, kw_count;
expr_ty expr;
APPEND_EXPR(e->v.Call.func, PR_ATOM);
arg_count = asdl_seq_LEN(e->v.Call.args);
kw_count = asdl_seq_LEN(e->v.Call.keywords);
if (arg_count == 1 && kw_count == 0) {
expr = (expr_ty)asdl_seq_GET(e->v.Call.args, 0);
if (expr->kind == GeneratorExp_kind) {
/* Special case: a single generator expression. */
return append_ast_genexp(writer, expr);
}
}
APPEND_STR("(");
first = true;
for (i = 0; i < arg_count; i++) {
APPEND_STR_IF_NOT_FIRST(", ");
APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Call.args, i), PR_TEST);
}
for (i = 0; i < kw_count; i++) {
APPEND_STR_IF_NOT_FIRST(", ");
APPEND(keyword, (keyword_ty)asdl_seq_GET(e->v.Call.keywords, i));
}
APPEND_STR_FINISH(")");
}
static PyObject *
escape_braces(PyObject *orig)
{
PyObject *temp;
PyObject *result;
temp = PyUnicode_Replace(orig, _str_open_br, _str_dbl_open_br, -1);
if (!temp) {
return NULL;
}
result = PyUnicode_Replace(temp, _str_close_br, _str_dbl_close_br, -1);
Py_DECREF(temp);
return result;
}
static int
append_fstring_unicode(_PyUnicodeWriter *writer, PyObject *unicode)
{
PyObject *escaped;
int result = -1;
escaped = escape_braces(unicode);
if (escaped) {
result = _PyUnicodeWriter_WriteStr(writer, escaped);
Py_DECREF(escaped);
}
return result;
}
static int
append_fstring_element(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
{
switch (e->kind) {
case Constant_kind:
return append_fstring_unicode(writer, e->v.Constant.value);
case JoinedStr_kind:
return append_joinedstr(writer, e, is_format_spec);
case FormattedValue_kind:
return append_formattedvalue(writer, e);
default:
PyErr_SetString(PyExc_SystemError,
"unknown expression kind inside f-string");
return -1;
}
}
/* Build body separately to enable wrapping the entire stream of Strs,
Constants and FormattedValues in one opening and one closing quote. */
static PyObject *
build_fstring_body(asdl_seq *values, bool is_format_spec)
{
Py_ssize_t i, value_count;
_PyUnicodeWriter body_writer;
_PyUnicodeWriter_Init(&body_writer);
body_writer.min_length = 256;
body_writer.overallocate = 1;
value_count = asdl_seq_LEN(values);
for (i = 0; i < value_count; ++i) {
if (-1 == append_fstring_element(&body_writer,
(expr_ty)asdl_seq_GET(values, i),
is_format_spec
)) {
_PyUnicodeWriter_Dealloc(&body_writer);
return NULL;
}
}
return _PyUnicodeWriter_Finish(&body_writer);
}
static int
append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
{
int result = -1;
PyObject *body = build_fstring_body(e->v.JoinedStr.values, is_format_spec);
if (!body) {
return -1;
}
if (!is_format_spec) {
if (-1 != append_charp(writer, "f") &&
-1 != append_repr(writer, body))
{
result = 0;
}
}
else {
result = _PyUnicodeWriter_WriteStr(writer, body);
}
Py_DECREF(body);
return result;
}
static int
append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e)
{
const char *conversion;
const char *outer_brace = "{";
/* Grammar allows PR_TUPLE, but use >PR_TEST for adding parenthesis
around a lambda with ':' */
PyObject *temp_fv_str = expr_as_unicode(e->v.FormattedValue.value, PR_TEST + 1);
if (!temp_fv_str) {
return -1;
}
if (PyUnicode_Find(temp_fv_str, _str_open_br, 0, 1, 1) == 0) {
/* Expression starts with a brace, split it with a space from the outer
one. */
outer_brace = "{ ";
}
if (-1 == append_charp(writer, outer_brace)) {
Py_DECREF(temp_fv_str);
return -1;
}
if (-1 == _PyUnicodeWriter_WriteStr(writer, temp_fv_str)) {
Py_DECREF(temp_fv_str);
return -1;
}
Py_DECREF(temp_fv_str);
if (e->v.FormattedValue.conversion > 0) {
switch (e->v.FormattedValue.conversion) {
case 'a':
conversion = "!a";
break;
case 'r':
conversion = "!r";
break;
case 's':
conversion = "!s";
break;
default:
PyErr_SetString(PyExc_SystemError,
"unknown f-value conversion kind");
return -1;
}
APPEND_STR(conversion);
}
if (e->v.FormattedValue.format_spec) {
if (-1 == _PyUnicodeWriter_WriteASCIIString(writer, ":", 1) ||
-1 == append_fstring_element(writer,
e->v.FormattedValue.format_spec,
true
))
{
return -1;
}
}
APPEND_STR_FINISH("}");
}
static int
append_ast_constant(_PyUnicodeWriter *writer, PyObject *constant)
{
if (PyTuple_CheckExact(constant)) {
Py_ssize_t i, elem_count;
elem_count = PyTuple_GET_SIZE(constant);
APPEND_STR("(");
for (i = 0; i < elem_count; i++) {
APPEND_STR_IF(i > 0, ", ");
if (append_ast_constant(writer, PyTuple_GET_ITEM(constant, i)) < 0) {
return -1;
}
}
APPEND_STR_IF(elem_count == 1, ",");
APPEND_STR(")");
return 0;
}
return append_repr(writer, constant);
}
static int
append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e)
{
const char *period;
expr_ty v = e->v.Attribute.value;
APPEND_EXPR(v, PR_ATOM);
/* Special case: integers require a space for attribute access to be
unambiguous. */
if (v->kind == Constant_kind && PyLong_CheckExact(v->v.Constant.value)) {
period = " .";
}
else {
period = ".";
}
APPEND_STR(period);
return _PyUnicodeWriter_WriteStr(writer, e->v.Attribute.attr);
}
static int
append_ast_slice(_PyUnicodeWriter *writer, expr_ty e)
{
if (e->v.Slice.lower) {
APPEND_EXPR(e->v.Slice.lower, PR_TEST);
}
APPEND_STR(":");
if (e->v.Slice.upper) {
APPEND_EXPR(e->v.Slice.upper, PR_TEST);
}
if (e->v.Slice.step) {
APPEND_STR(":");
APPEND_EXPR(e->v.Slice.step, PR_TEST);
}
return 0;
}
static int
append_ast_subscript(_PyUnicodeWriter *writer, expr_ty e)
{
APPEND_EXPR(e->v.Subscript.value, PR_ATOM);
int level = PR_TUPLE;
expr_ty slice = e->v.Subscript.slice;
if (slice->kind == Tuple_kind) {
for (Py_ssize_t i = 0; i < asdl_seq_LEN(slice->v.Tuple.elts); i++) {
expr_ty element = asdl_seq_GET(slice->v.Tuple.elts, i);
if (element->kind == Starred_kind) {
++level;
break;
}
}
}
APPEND_STR("[");
APPEND_EXPR(e->v.Subscript.slice, level);
APPEND_STR_FINISH("]");
}
static int
append_ast_starred(_PyUnicodeWriter *writer, expr_ty e)
{
APPEND_STR("*");
APPEND_EXPR(e->v.Starred.value, PR_EXPR);
return 0;
}
static int
append_ast_yield(_PyUnicodeWriter *writer, expr_ty e)
{
if (!e->v.Yield.value) {
APPEND_STR_FINISH("(yield)");
}
APPEND_STR("(yield ");
APPEND_EXPR(e->v.Yield.value, PR_TEST);
APPEND_STR_FINISH(")");
}
static int
append_ast_yield_from(_PyUnicodeWriter *writer, expr_ty e)
{
APPEND_STR("(yield from ");
APPEND_EXPR(e->v.YieldFrom.value, PR_TEST);
APPEND_STR_FINISH(")");
}
static int
append_ast_await(_PyUnicodeWriter *writer, expr_ty e, int level)
{
APPEND_STR_IF(level > PR_AWAIT, "(");
APPEND_STR("await ");
APPEND_EXPR(e->v.Await.value, PR_ATOM);
APPEND_STR_IF(level > PR_AWAIT, ")");
return 0;
}
static int
append_named_expr(_PyUnicodeWriter *writer, expr_ty e, int level)
{
APPEND_STR_IF(level > PR_TUPLE, "(");
APPEND_EXPR(e->v.NamedExpr.target, PR_ATOM);
APPEND_STR(" := ");
APPEND_EXPR(e->v.NamedExpr.value, PR_ATOM);
APPEND_STR_IF(level > PR_TUPLE, ")");
return 0;
}
static int
append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level)
{
switch (e->kind) {
case BoolOp_kind:
return append_ast_boolop(writer, e, level);
case BinOp_kind:
return append_ast_binop(writer, e, level);
case UnaryOp_kind:
return append_ast_unaryop(writer, e, level);
case Lambda_kind:
return append_ast_lambda(writer, e, level);
case IfExp_kind:
return append_ast_ifexp(writer, e, level);
case Dict_kind:
return append_ast_dict(writer, e);
case Set_kind:
return append_ast_set(writer, e);
case GeneratorExp_kind:
return append_ast_genexp(writer, e);
case ListComp_kind:
return append_ast_listcomp(writer, e);
case SetComp_kind:
return append_ast_setcomp(writer, e);
case DictComp_kind:
return append_ast_dictcomp(writer, e);
case Yield_kind:
return append_ast_yield(writer, e);
case YieldFrom_kind:
return append_ast_yield_from(writer, e);
case Await_kind:
return append_ast_await(writer, e, level);
case Compare_kind:
return append_ast_compare(writer, e, level);
case Call_kind:
return append_ast_call(writer, e);
case Constant_kind:
if (e->v.Constant.value == Py_Ellipsis) {
APPEND_STR_FINISH("...");
}
if (e->v.Constant.kind != NULL
&& -1 == _PyUnicodeWriter_WriteStr(writer, e->v.Constant.kind)) {
return -1;
}
return append_ast_constant(writer, e->v.Constant.value);
case JoinedStr_kind:
return append_joinedstr(writer, e, false);
case FormattedValue_kind:
return append_formattedvalue(writer, e);
/* The following exprs can be assignment targets. */
case Attribute_kind:
return append_ast_attribute(writer, e);
case Subscript_kind:
return append_ast_subscript(writer, e);
case Starred_kind:
return append_ast_starred(writer, e);
case Slice_kind:
return append_ast_slice(writer, e);
case Name_kind:
return _PyUnicodeWriter_WriteStr(writer, e->v.Name.id);
case List_kind:
return append_ast_list(writer, e);
case Tuple_kind:
return append_ast_tuple(writer, e, level);
case NamedExpr_kind:
return append_named_expr(writer, e, level);
default:
PyErr_SetString(PyExc_SystemError,
"unknown expression kind");
return -1;
}
}
static int
maybe_init_static_strings(void)
{
if (!_str_open_br &&
!(_str_open_br = PyUnicode_InternFromString("{"))) {
return -1;
}
if (!_str_dbl_open_br &&
!(_str_dbl_open_br = PyUnicode_InternFromString("{{"))) {
return -1;
}
if (!_str_close_br &&
!(_str_close_br = PyUnicode_InternFromString("}"))) {
return -1;
}
if (!_str_dbl_close_br &&
!(_str_dbl_close_br = PyUnicode_InternFromString("}}"))) {
return -1;
}
if (!_str_inf &&
!(_str_inf = PyUnicode_FromString("inf"))) {
return -1;
}
if (!_str_replace_inf &&
!(_str_replace_inf = PyUnicode_FromFormat("1e%d", 1 + DBL_MAX_10_EXP))) {
return -1;
}
return 0;
}
static PyObject *
expr_as_unicode(expr_ty e, int level)
{
_PyUnicodeWriter writer;
_PyUnicodeWriter_Init(&writer);
writer.min_length = 256;
writer.overallocate = 1;
if (-1 == maybe_init_static_strings() ||
-1 == append_ast_expr(&writer, e, level))
{
_PyUnicodeWriter_Dealloc(&writer);
return NULL;
}
return _PyUnicodeWriter_Finish(&writer);
}
PyObject *
_PyAST_ExprAsUnicode(expr_ty e)
{
return expr_as_unicode(e, PR_TEST);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,623 @@
#include "Python.h"
#include "pycore_initconfig.h"
#ifdef MS_WINDOWS
# include <windows.h>
/* All sample MSDN wincrypt programs include the header below. It is at least
* required with Min GW. */
# include <wincrypt.h>
#else
# include <fcntl.h>
# ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
# endif
# ifdef HAVE_LINUX_RANDOM_H
# include <linux/random.h>
# endif
# if defined(HAVE_SYS_RANDOM_H) && (defined(HAVE_GETRANDOM) || defined(HAVE_GETENTROPY))
# include <sys/random.h>
# endif
# if !defined(HAVE_GETRANDOM) && defined(HAVE_GETRANDOM_SYSCALL)
# include <sys/syscall.h>
# endif
#endif
#ifdef _Py_MEMORY_SANITIZER
# include <sanitizer/msan_interface.h>
#endif
#if defined(__APPLE__) && defined(__has_builtin)
# if __has_builtin(__builtin_available)
# define HAVE_GETENTRYPY_GETRANDOM_RUNTIME __builtin_available(macOS 10.12, iOS 10.10, tvOS 10.0, watchOS 3.0, *)
# endif
#endif
#ifndef HAVE_GETENTRYPY_GETRANDOM_RUNTIME
# define HAVE_GETENTRYPY_GETRANDOM_RUNTIME 1
#endif
#ifdef Py_DEBUG
int _Py_HashSecret_Initialized = 0;
#else
static int _Py_HashSecret_Initialized = 0;
#endif
#ifdef MS_WINDOWS
static HCRYPTPROV hCryptProv = 0;
static int
win32_urandom_init(int raise)
{
/* Acquire context */
if (!CryptAcquireContextW(&hCryptProv, NULL, NULL,
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
goto error;
return 0;
error:
if (raise) {
PyErr_SetFromWindowsErr(0);
}
return -1;
}
/* Fill buffer with size pseudo-random bytes generated by the Windows CryptoGen
API. Return 0 on success, or raise an exception and return -1 on error. */
static int
win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
{
if (hCryptProv == 0)
{
if (win32_urandom_init(raise) == -1) {
return -1;
}
}
while (size > 0)
{
DWORD chunk = (DWORD)Py_MIN(size, PY_DWORD_MAX);
if (!CryptGenRandom(hCryptProv, chunk, buffer))
{
/* CryptGenRandom() failed */
if (raise) {
PyErr_SetFromWindowsErr(0);
}
return -1;
}
buffer += chunk;
size -= chunk;
}
return 0;
}
#else /* !MS_WINDOWS */
#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
#define PY_GETRANDOM 1
/* Call getrandom() to get random bytes:
- Return 1 on success
- Return 0 if getrandom() is not available (failed with ENOSYS or EPERM),
or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom not
initialized yet) and raise=0.
- Raise an exception (if raise is non-zero) and return -1 on error:
if getrandom() failed with EINTR, raise is non-zero and the Python signal
handler raised an exception, or if getrandom() failed with a different
error.
getrandom() is retried if it failed with EINTR: interrupted by a signal. */
static int
py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)
{
/* Is getrandom() supported by the running kernel? Set to 0 if getrandom()
failed with ENOSYS or EPERM. Need Linux kernel 3.17 or newer, or Solaris
11.3 or newer */
static int getrandom_works = 1;
int flags;
char *dest;
long n;
if (!getrandom_works) {
return 0;
}
flags = blocking ? 0 : GRND_NONBLOCK;
dest = buffer;
while (0 < size) {
#if defined(__sun) && defined(__SVR4)
/* Issue #26735: On Solaris, getrandom() is limited to returning up
to 1024 bytes. Call it multiple times if more bytes are
requested. */
n = Py_MIN(size, 1024);
#else
n = Py_MIN(size, LONG_MAX);
#endif
errno = 0;
#ifdef HAVE_GETRANDOM
if (raise) {
Py_BEGIN_ALLOW_THREADS
n = getrandom(dest, n, flags);
Py_END_ALLOW_THREADS
}
else {
n = getrandom(dest, n, flags);
}
#else
/* On Linux, use the syscall() function because the GNU libc doesn't
expose the Linux getrandom() syscall yet. See:
https://sourceware.org/bugzilla/show_bug.cgi?id=17252 */
if (raise) {
Py_BEGIN_ALLOW_THREADS
n = syscall(SYS_getrandom, dest, n, flags);
Py_END_ALLOW_THREADS
}
else {
n = syscall(SYS_getrandom, dest, n, flags);
}
# ifdef _Py_MEMORY_SANITIZER
if (n > 0) {
__msan_unpoison(dest, n);
}
# endif
#endif
if (n < 0) {
/* ENOSYS: the syscall is not supported by the kernel.
EPERM: the syscall is blocked by a security policy (ex: SECCOMP)
or something else. */
if (errno == ENOSYS || errno == EPERM) {
getrandom_works = 0;
return 0;
}
/* getrandom(GRND_NONBLOCK) fails with EAGAIN if the system urandom
is not initialized yet. For _PyRandom_Init(), we ignore the
error and fall back on reading /dev/urandom which never blocks,
even if the system urandom is not initialized yet:
see the PEP 524. */
if (errno == EAGAIN && !raise && !blocking) {
return 0;
}
if (errno == EINTR) {
if (raise) {
if (PyErr_CheckSignals()) {
return -1;
}
}
/* retry getrandom() if it was interrupted by a signal */
continue;
}
if (raise) {
PyErr_SetFromErrno(PyExc_OSError);
}
return -1;
}
dest += n;
size -= n;
}
return 1;
}
#elif defined(HAVE_GETENTROPY)
#define PY_GETENTROPY 1
/* Fill buffer with size pseudo-random bytes generated by getentropy():
- Return 1 on success
- Return 0 if getentropy() syscall is not available (failed with ENOSYS or
EPERM).
- Raise an exception (if raise is non-zero) and return -1 on error:
if getentropy() failed with EINTR, raise is non-zero and the Python signal
handler raised an exception, or if getentropy() failed with a different
error.
getentropy() is retried if it failed with EINTR: interrupted by a signal. */
#if defined(__APPLE__) && defined(__has_attribute) && __has_attribute(availability)
static int
py_getentropy(char *buffer, Py_ssize_t size, int raise)
__attribute__((availability(macos,introduced=10.12)))
__attribute__((availability(ios,introduced=10.0)))
__attribute__((availability(tvos,introduced=10.0)))
__attribute__((availability(watchos,introduced=3.0)));
#endif
static int
py_getentropy(char *buffer, Py_ssize_t size, int raise)
{
/* Is getentropy() supported by the running kernel? Set to 0 if
getentropy() failed with ENOSYS or EPERM. */
static int getentropy_works = 1;
if (!getentropy_works) {
return 0;
}
while (size > 0) {
/* getentropy() is limited to returning up to 256 bytes. Call it
multiple times if more bytes are requested. */
Py_ssize_t len = Py_MIN(size, 256);
int res;
if (raise) {
Py_BEGIN_ALLOW_THREADS
res = getentropy(buffer, len);
Py_END_ALLOW_THREADS
}
else {
res = getentropy(buffer, len);
}
if (res < 0) {
/* ENOSYS: the syscall is not supported by the running kernel.
EPERM: the syscall is blocked by a security policy (ex: SECCOMP)
or something else. */
if (errno == ENOSYS || errno == EPERM) {
getentropy_works = 0;
return 0;
}
if (errno == EINTR) {
if (raise) {
if (PyErr_CheckSignals()) {
return -1;
}
}
/* retry getentropy() if it was interrupted by a signal */
continue;
}
if (raise) {
PyErr_SetFromErrno(PyExc_OSError);
}
return -1;
}
buffer += len;
size -= len;
}
return 1;
}
#endif /* defined(HAVE_GETENTROPY) && !(defined(__sun) && defined(__SVR4)) */
static struct {
int fd;
dev_t st_dev;
ino_t st_ino;
} urandom_cache = { -1 };
/* Read random bytes from the /dev/urandom device:
- Return 0 on success
- Raise an exception (if raise is non-zero) and return -1 on error
Possible causes of errors:
- open() failed with ENOENT, ENXIO, ENODEV, EACCES: the /dev/urandom device
was not found. For example, it was removed manually or not exposed in a
chroot or container.
- open() failed with a different error
- fstat() failed
- read() failed or returned 0
read() is retried if it failed with EINTR: interrupted by a signal.
The file descriptor of the device is kept open between calls to avoid using
many file descriptors when run in parallel from multiple threads:
see the issue #18756.
st_dev and st_ino fields of the file descriptor (from fstat()) are cached to
check if the file descriptor was replaced by a different file (which is
likely a bug in the application): see the issue #21207.
If the file descriptor was closed or replaced, open a new file descriptor
but don't close the old file descriptor: it probably points to something
important for some third-party code. */
static int
dev_urandom(char *buffer, Py_ssize_t size, int raise)
{
int fd;
Py_ssize_t n;
if (raise) {
struct _Py_stat_struct st;
int fstat_result;
if (urandom_cache.fd >= 0) {
Py_BEGIN_ALLOW_THREADS
fstat_result = _Py_fstat_noraise(urandom_cache.fd, &st);
Py_END_ALLOW_THREADS
/* Does the fd point to the same thing as before? (issue #21207) */
if (fstat_result
|| st.st_dev != urandom_cache.st_dev
|| st.st_ino != urandom_cache.st_ino) {
/* Something changed: forget the cached fd (but don't close it,
since it probably points to something important for some
third-party code). */
urandom_cache.fd = -1;
}
}
if (urandom_cache.fd >= 0)
fd = urandom_cache.fd;
else {
fd = _Py_open("/dev/urandom", O_RDONLY);
if (fd < 0) {
if (errno == ENOENT || errno == ENXIO ||
errno == ENODEV || errno == EACCES) {
PyErr_SetString(PyExc_NotImplementedError,
"/dev/urandom (or equivalent) not found");
}
/* otherwise, keep the OSError exception raised by _Py_open() */
return -1;
}
if (urandom_cache.fd >= 0) {
/* urandom_fd was initialized by another thread while we were
not holding the GIL, keep it. */
close(fd);
fd = urandom_cache.fd;
}
else {
if (_Py_fstat(fd, &st)) {
close(fd);
return -1;
}
else {
urandom_cache.fd = fd;
urandom_cache.st_dev = st.st_dev;
urandom_cache.st_ino = st.st_ino;
}
}
}
do {
n = _Py_read(fd, buffer, (size_t)size);
if (n == -1)
return -1;
if (n == 0) {
PyErr_Format(PyExc_RuntimeError,
"Failed to read %zi bytes from /dev/urandom",
size);
return -1;
}
buffer += n;
size -= n;
} while (0 < size);
}
else {
fd = _Py_open_noraise("/dev/urandom", O_RDONLY);
if (fd < 0) {
return -1;
}
while (0 < size)
{
do {
n = read(fd, buffer, (size_t)size);
} while (n < 0 && errno == EINTR);
if (n <= 0) {
/* stop on error or if read(size) returned 0 */
close(fd);
return -1;
}
buffer += n;
size -= n;
}
close(fd);
}
return 0;
}
static void
dev_urandom_close(void)
{
if (urandom_cache.fd >= 0) {
close(urandom_cache.fd);
urandom_cache.fd = -1;
}
}
#endif /* !MS_WINDOWS */
/* Fill buffer with pseudo-random bytes generated by a linear congruent
generator (LCG):
x(n+1) = (x(n) * 214013 + 2531011) % 2^32
Use bits 23..16 of x(n) to generate a byte. */
static void
lcg_urandom(unsigned int x0, unsigned char *buffer, size_t size)
{
size_t index;
unsigned int x;
x = x0;
for (index=0; index < size; index++) {
x *= 214013;
x += 2531011;
/* modulo 2 ^ (8 * sizeof(int)) */
buffer[index] = (x >> 16) & 0xff;
}
}
/* Read random bytes:
- Return 0 on success
- Raise an exception (if raise is non-zero) and return -1 on error
Used sources of entropy ordered by preference, preferred source first:
- CryptGenRandom() on Windows
- getrandom() function (ex: Linux and Solaris): call py_getrandom()
- getentropy() function (ex: OpenBSD): call py_getentropy()
- /dev/urandom device
Read from the /dev/urandom device if getrandom() or getentropy() function
is not available or does not work.
Prefer getrandom() over getentropy() because getrandom() supports blocking
and non-blocking mode: see the PEP 524. Python requires non-blocking RNG at
startup to initialize its hash secret, but os.urandom() must block until the
system urandom is initialized (at least on Linux 3.17 and newer).
Prefer getrandom() and getentropy() over reading directly /dev/urandom
because these functions don't need file descriptors and so avoid ENFILE or
EMFILE errors (too many open files): see the issue #18756.
Only the getrandom() function supports non-blocking mode.
Only use RNG running in the kernel. They are more secure because it is
harder to get the internal state of a RNG running in the kernel land than a
RNG running in the user land. The kernel has a direct access to the hardware
and has access to hardware RNG, they are used as entropy sources.
Note: the OpenSSL RAND_pseudo_bytes() function does not automatically reseed
its RNG on fork(), two child processes (with the same pid) generate the same
random numbers: see issue #18747. Kernel RNGs don't have this issue,
they have access to good quality entropy sources.
If raise is zero:
- Don't raise an exception on error
- Don't call the Python signal handler (don't call PyErr_CheckSignals()) if
a function fails with EINTR: retry directly the interrupted function
- Don't release the GIL to call functions.
*/
static int
pyurandom(void *buffer, Py_ssize_t size, int blocking, int raise)
{
#if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
int res;
#endif
if (size < 0) {
if (raise) {
PyErr_Format(PyExc_ValueError,
"negative argument not allowed");
}
return -1;
}
if (size == 0) {
return 0;
}
#ifdef MS_WINDOWS
return win32_urandom((unsigned char *)buffer, size, raise);
#else
#if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
if (HAVE_GETENTRYPY_GETRANDOM_RUNTIME) {
#ifdef PY_GETRANDOM
res = py_getrandom(buffer, size, blocking, raise);
#else
res = py_getentropy(buffer, size, raise);
#endif
if (res < 0) {
return -1;
}
if (res == 1) {
return 0;
}
/* getrandom() or getentropy() function is not available: failed with
ENOSYS or EPERM. Fall back on reading from /dev/urandom. */
} /* end of availability block */
#endif
return dev_urandom(buffer, size, raise);
#endif
}
/* Fill buffer with size pseudo-random bytes from the operating system random
number generator (RNG). It is suitable for most cryptographic purposes
except long living private keys for asymmetric encryption.
On Linux 3.17 and newer, the getrandom() syscall is used in blocking mode:
block until the system urandom entropy pool is initialized (128 bits are
collected by the kernel).
Return 0 on success. Raise an exception and return -1 on error. */
int
_PyOS_URandom(void *buffer, Py_ssize_t size)
{
return pyurandom(buffer, size, 1, 1);
}
/* Fill buffer with size pseudo-random bytes from the operating system random
number generator (RNG). It is not suitable for cryptographic purpose.
On Linux 3.17 and newer (when getrandom() syscall is used), if the system
urandom is not initialized yet, the function returns "weak" entropy read
from /dev/urandom.
Return 0 on success. Raise an exception and return -1 on error. */
int
_PyOS_URandomNonblock(void *buffer, Py_ssize_t size)
{
return pyurandom(buffer, size, 0, 1);
}
PyStatus
_Py_HashRandomization_Init(const PyConfig *config)
{
void *secret = &_Py_HashSecret;
Py_ssize_t secret_size = sizeof(_Py_HashSecret_t);
if (_Py_HashSecret_Initialized) {
return _PyStatus_OK();
}
_Py_HashSecret_Initialized = 1;
if (config->use_hash_seed) {
if (config->hash_seed == 0) {
/* disable the randomized hash */
memset(secret, 0, secret_size);
}
else {
/* use the specified hash seed */
lcg_urandom(config->hash_seed, secret, secret_size);
}
}
else {
/* use a random hash seed */
int res;
/* _PyRandom_Init() is called very early in the Python initialization
and so exceptions cannot be used (use raise=0).
_PyRandom_Init() must not block Python initialization: call
pyurandom() is non-blocking mode (blocking=0): see the PEP 524. */
res = pyurandom(secret, secret_size, 0, 0);
if (res < 0) {
return _PyStatus_ERR("failed to get random numbers "
"to initialize Python");
}
}
return _PyStatus_OK();
}
void
_Py_HashRandomization_Fini(void)
{
#ifdef MS_WINDOWS
if (hCryptProv) {
CryptReleaseContext(hCryptProv, 0);
hCryptProv = 0;
}
#else
dev_urandom_close();
#endif
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,331 @@
/*
* Implementation of the Global Interpreter Lock (GIL).
*/
#include <stdlib.h>
#include <errno.h>
#include "pycore_atomic.h"
/*
Notes about the implementation:
- The GIL is just a boolean variable (locked) whose access is protected
by a mutex (gil_mutex), and whose changes are signalled by a condition
variable (gil_cond). gil_mutex is taken for short periods of time,
and therefore mostly uncontended.
- In the GIL-holding thread, the main loop (PyEval_EvalFrameEx) must be
able to release the GIL on demand by another thread. A volatile boolean
variable (gil_drop_request) is used for that purpose, which is checked
at every turn of the eval loop. That variable is set after a wait of
`interval` microseconds on `gil_cond` has timed out.
[Actually, another volatile boolean variable (eval_breaker) is used
which ORs several conditions into one. Volatile booleans are
sufficient as inter-thread signalling means since Python is run
on cache-coherent architectures only.]
- A thread wanting to take the GIL will first let pass a given amount of
time (`interval` microseconds) before setting gil_drop_request. This
encourages a defined switching period, but doesn't enforce it since
opcodes can take an arbitrary time to execute.
The `interval` value is available for the user to read and modify
using the Python API `sys.{get,set}switchinterval()`.
- When a thread releases the GIL and gil_drop_request is set, that thread
ensures that another GIL-awaiting thread gets scheduled.
It does so by waiting on a condition variable (switch_cond) until
the value of last_holder is changed to something else than its
own thread state pointer, indicating that another thread was able to
take the GIL.
This is meant to prohibit the latency-adverse behaviour on multi-core
machines where one thread would speculatively release the GIL, but still
run and end up being the first to re-acquire it, making the "timeslices"
much longer than expected.
(Note: this mechanism is enabled with FORCE_SWITCHING above)
*/
#include "condvar.h"
#define MUTEX_INIT(mut) \
if (PyMUTEX_INIT(&(mut))) { \
Py_FatalError("PyMUTEX_INIT(" #mut ") failed"); };
#define MUTEX_FINI(mut) \
if (PyMUTEX_FINI(&(mut))) { \
Py_FatalError("PyMUTEX_FINI(" #mut ") failed"); };
#define MUTEX_LOCK(mut) \
if (PyMUTEX_LOCK(&(mut))) { \
Py_FatalError("PyMUTEX_LOCK(" #mut ") failed"); };
#define MUTEX_UNLOCK(mut) \
if (PyMUTEX_UNLOCK(&(mut))) { \
Py_FatalError("PyMUTEX_UNLOCK(" #mut ") failed"); };
#define COND_INIT(cond) \
if (PyCOND_INIT(&(cond))) { \
Py_FatalError("PyCOND_INIT(" #cond ") failed"); };
#define COND_FINI(cond) \
if (PyCOND_FINI(&(cond))) { \
Py_FatalError("PyCOND_FINI(" #cond ") failed"); };
#define COND_SIGNAL(cond) \
if (PyCOND_SIGNAL(&(cond))) { \
Py_FatalError("PyCOND_SIGNAL(" #cond ") failed"); };
#define COND_WAIT(cond, mut) \
if (PyCOND_WAIT(&(cond), &(mut))) { \
Py_FatalError("PyCOND_WAIT(" #cond ") failed"); };
#define COND_TIMED_WAIT(cond, mut, microseconds, timeout_result) \
{ \
int r = PyCOND_TIMEDWAIT(&(cond), &(mut), (microseconds)); \
if (r < 0) \
Py_FatalError("PyCOND_WAIT(" #cond ") failed"); \
if (r) /* 1 == timeout, 2 == impl. can't say, so assume timeout */ \
timeout_result = 1; \
else \
timeout_result = 0; \
} \
#define DEFAULT_INTERVAL 5000
static void _gil_initialize(struct _gil_runtime_state *gil)
{
_Py_atomic_int uninitialized = {-1};
gil->locked = uninitialized;
gil->interval = DEFAULT_INTERVAL;
}
static int gil_created(struct _gil_runtime_state *gil)
{
return (_Py_atomic_load_explicit(&gil->locked, _Py_memory_order_acquire) >= 0);
}
static void create_gil(struct _gil_runtime_state *gil)
{
MUTEX_INIT(gil->mutex);
#ifdef FORCE_SWITCHING
MUTEX_INIT(gil->switch_mutex);
#endif
COND_INIT(gil->cond);
#ifdef FORCE_SWITCHING
COND_INIT(gil->switch_cond);
#endif
_Py_atomic_store_relaxed(&gil->last_holder, 0);
_Py_ANNOTATE_RWLOCK_CREATE(&gil->locked);
_Py_atomic_store_explicit(&gil->locked, 0, _Py_memory_order_release);
}
static void destroy_gil(struct _gil_runtime_state *gil)
{
/* some pthread-like implementations tie the mutex to the cond
* and must have the cond destroyed first.
*/
COND_FINI(gil->cond);
MUTEX_FINI(gil->mutex);
#ifdef FORCE_SWITCHING
COND_FINI(gil->switch_cond);
MUTEX_FINI(gil->switch_mutex);
#endif
_Py_atomic_store_explicit(&gil->locked, -1,
_Py_memory_order_release);
_Py_ANNOTATE_RWLOCK_DESTROY(&gil->locked);
}
static void recreate_gil(struct _gil_runtime_state *gil)
{
_Py_ANNOTATE_RWLOCK_DESTROY(&gil->locked);
/* XXX should we destroy the old OS resources here? */
create_gil(gil);
}
static void
drop_gil(struct _ceval_runtime_state *ceval, struct _ceval_state *ceval2,
PyThreadState *tstate)
{
struct _gil_runtime_state *gil = &ceval->gil;
if (!_Py_atomic_load_relaxed(&gil->locked)) {
Py_FatalError("drop_gil: GIL is not locked");
}
/* tstate is allowed to be NULL (early interpreter init) */
if (tstate != NULL) {
/* Sub-interpreter support: threads might have been switched
under our feet using PyThreadState_Swap(). Fix the GIL last
holder variable so that our heuristics work. */
_Py_atomic_store_relaxed(&gil->last_holder, (uintptr_t)tstate);
}
MUTEX_LOCK(gil->mutex);
_Py_ANNOTATE_RWLOCK_RELEASED(&gil->locked, /*is_write=*/1);
_Py_atomic_store_relaxed(&gil->locked, 0);
COND_SIGNAL(gil->cond);
MUTEX_UNLOCK(gil->mutex);
#ifdef FORCE_SWITCHING
if (_Py_atomic_load_relaxed(&ceval2->gil_drop_request) && tstate != NULL) {
MUTEX_LOCK(gil->switch_mutex);
/* Not switched yet => wait */
if (((PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) == tstate)
{
assert(is_tstate_valid(tstate));
RESET_GIL_DROP_REQUEST(tstate->interp);
/* NOTE: if COND_WAIT does not atomically start waiting when
releasing the mutex, another thread can run through, take
the GIL and drop it again, and reset the condition
before we even had a chance to wait for it. */
COND_WAIT(gil->switch_cond, gil->switch_mutex);
}
MUTEX_UNLOCK(gil->switch_mutex);
}
#endif
}
/* Check if a Python thread must exit immediately, rather than taking the GIL
if Py_Finalize() has been called.
When this function is called by a daemon thread after Py_Finalize() has been
called, the GIL does no longer exist.
tstate must be non-NULL. */
static inline int
tstate_must_exit(PyThreadState *tstate)
{
/* bpo-39877: Access _PyRuntime directly rather than using
tstate->interp->runtime to support calls from Python daemon threads.
After Py_Finalize() has been called, tstate can be a dangling pointer:
point to PyThreadState freed memory. */
PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(&_PyRuntime);
return (finalizing != NULL && finalizing != tstate);
}
/* Take the GIL.
The function saves errno at entry and restores its value at exit.
tstate must be non-NULL. */
static void
take_gil(PyThreadState *tstate)
{
int err = errno;
assert(tstate != NULL);
if (tstate_must_exit(tstate)) {
/* bpo-39877: If Py_Finalize() has been called and tstate is not the
thread which called Py_Finalize(), exit immediately the thread.
This code path can be reached by a daemon thread after Py_Finalize()
completes. In this case, tstate is a dangling pointer: points to
PyThreadState freed memory. */
PyThread_exit_thread();
}
assert(is_tstate_valid(tstate));
PyInterpreterState *interp = tstate->interp;
struct _ceval_runtime_state *ceval = &interp->runtime->ceval;
struct _ceval_state *ceval2 = &interp->ceval;
struct _gil_runtime_state *gil = &ceval->gil;
/* Check that _PyEval_InitThreads() was called to create the lock */
assert(gil_created(gil));
MUTEX_LOCK(gil->mutex);
if (!_Py_atomic_load_relaxed(&gil->locked)) {
goto _ready;
}
while (_Py_atomic_load_relaxed(&gil->locked)) {
unsigned long saved_switchnum = gil->switch_number;
unsigned long interval = (gil->interval >= 1 ? gil->interval : 1);
int timed_out = 0;
COND_TIMED_WAIT(gil->cond, gil->mutex, interval, timed_out);
/* If we timed out and no switch occurred in the meantime, it is time
to ask the GIL-holding thread to drop it. */
if (timed_out &&
_Py_atomic_load_relaxed(&gil->locked) &&
gil->switch_number == saved_switchnum)
{
if (tstate_must_exit(tstate)) {
MUTEX_UNLOCK(gil->mutex);
PyThread_exit_thread();
}
assert(is_tstate_valid(tstate));
SET_GIL_DROP_REQUEST(interp);
}
}
_ready:
#ifdef FORCE_SWITCHING
/* This mutex must be taken before modifying gil->last_holder:
see drop_gil(). */
MUTEX_LOCK(gil->switch_mutex);
#endif
/* We now hold the GIL */
_Py_atomic_store_relaxed(&gil->locked, 1);
_Py_ANNOTATE_RWLOCK_ACQUIRED(&gil->locked, /*is_write=*/1);
if (tstate != (PyThreadState*)_Py_atomic_load_relaxed(&gil->last_holder)) {
_Py_atomic_store_relaxed(&gil->last_holder, (uintptr_t)tstate);
++gil->switch_number;
}
#ifdef FORCE_SWITCHING
COND_SIGNAL(gil->switch_cond);
MUTEX_UNLOCK(gil->switch_mutex);
#endif
if (tstate_must_exit(tstate)) {
/* bpo-36475: If Py_Finalize() has been called and tstate is not
the thread which called Py_Finalize(), exit immediately the
thread.
This code path can be reached by a daemon thread which was waiting
in take_gil() while the main thread called
wait_for_thread_shutdown() from Py_Finalize(). */
MUTEX_UNLOCK(gil->mutex);
drop_gil(ceval, ceval2, tstate);
PyThread_exit_thread();
}
assert(is_tstate_valid(tstate));
if (_Py_atomic_load_relaxed(&ceval2->gil_drop_request)) {
RESET_GIL_DROP_REQUEST(interp);
}
else {
/* bpo-40010: eval_breaker should be recomputed to be set to 1 if there
is a pending signal: signal received by another thread which cannot
handle signals.
Note: RESET_GIL_DROP_REQUEST() calls COMPUTE_EVAL_BREAKER(). */
COMPUTE_EVAL_BREAKER(interp, ceval, ceval2);
}
/* Don't access tstate if the thread must exit */
if (tstate->async_exc != NULL) {
_PyEval_SignalAsyncExc(tstate);
}
MUTEX_UNLOCK(gil->mutex);
errno = err;
}
void _PyEval_SetSwitchInterval(unsigned long microseconds)
{
struct _gil_runtime_state *gil = &_PyRuntime.ceval.gil;
gil->interval = microseconds;
}
unsigned long _PyEval_GetSwitchInterval()
{
struct _gil_runtime_state *gil = &_PyRuntime.ceval.gil;
return gil->interval;
}

View File

@ -0,0 +1,74 @@
/*[clinic input]
preserve
[clinic start generated code]*/
PyDoc_STRVAR(warnings_warn__doc__,
"warn($module, /, message, category=None, stacklevel=1, source=None)\n"
"--\n"
"\n"
"Issue a warning, or maybe ignore it or raise an exception.");
#define WARNINGS_WARN_METHODDEF \
{"warn", (PyCFunction)(void(*)(void))warnings_warn, METH_FASTCALL|METH_KEYWORDS, warnings_warn__doc__},
static PyObject *
warnings_warn_impl(PyObject *module, PyObject *message, PyObject *category,
Py_ssize_t stacklevel, PyObject *source);
static PyObject *
warnings_warn(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"message", "category", "stacklevel", "source", NULL};
static _PyArg_Parser _parser = {NULL, _keywords, "warn", 0};
PyObject *argsbuf[4];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
PyObject *message;
PyObject *category = Py_None;
Py_ssize_t stacklevel = 1;
PyObject *source = Py_None;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 4, 0, argsbuf);
if (!args) {
goto exit;
}
message = args[0];
if (!noptargs) {
goto skip_optional_pos;
}
if (args[1]) {
category = args[1];
if (!--noptargs) {
goto skip_optional_pos;
}
}
if (args[2]) {
if (PyFloat_Check(args[2])) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float" );
goto exit;
}
{
Py_ssize_t ival = -1;
PyObject *iobj = PyNumber_Index(args[2]);
if (iobj != NULL) {
ival = PyLong_AsSsize_t(iobj);
Py_DECREF(iobj);
}
if (ival == -1 && PyErr_Occurred()) {
goto exit;
}
stacklevel = ival;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
source = args[3];
skip_optional_pos:
return_value = warnings_warn_impl(module, message, category, stacklevel, source);
exit:
return return_value;
}
/*[clinic end generated code: output=b7bb54c73b5433ec input=a9049054013a1b77]*/

View File

@ -0,0 +1,858 @@
/*[clinic input]
preserve
[clinic start generated code]*/
PyDoc_STRVAR(builtin_abs__doc__,
"abs($module, x, /)\n"
"--\n"
"\n"
"Return the absolute value of the argument.");
#define BUILTIN_ABS_METHODDEF \
{"abs", (PyCFunction)builtin_abs, METH_O, builtin_abs__doc__},
PyDoc_STRVAR(builtin_all__doc__,
"all($module, iterable, /)\n"
"--\n"
"\n"
"Return True if bool(x) is True for all values x in the iterable.\n"
"\n"
"If the iterable is empty, return True.");
#define BUILTIN_ALL_METHODDEF \
{"all", (PyCFunction)builtin_all, METH_O, builtin_all__doc__},
PyDoc_STRVAR(builtin_any__doc__,
"any($module, iterable, /)\n"
"--\n"
"\n"
"Return True if bool(x) is True for any x in the iterable.\n"
"\n"
"If the iterable is empty, return False.");
#define BUILTIN_ANY_METHODDEF \
{"any", (PyCFunction)builtin_any, METH_O, builtin_any__doc__},
PyDoc_STRVAR(builtin_ascii__doc__,
"ascii($module, obj, /)\n"
"--\n"
"\n"
"Return an ASCII-only representation of an object.\n"
"\n"
"As repr(), return a string containing a printable representation of an\n"
"object, but escape the non-ASCII characters in the string returned by\n"
"repr() using \\\\x, \\\\u or \\\\U escapes. This generates a string similar\n"
"to that returned by repr() in Python 2.");
#define BUILTIN_ASCII_METHODDEF \
{"ascii", (PyCFunction)builtin_ascii, METH_O, builtin_ascii__doc__},
PyDoc_STRVAR(builtin_bin__doc__,
"bin($module, number, /)\n"
"--\n"
"\n"
"Return the binary representation of an integer.\n"
"\n"
" >>> bin(2796202)\n"
" \'0b1010101010101010101010\'");
#define BUILTIN_BIN_METHODDEF \
{"bin", (PyCFunction)builtin_bin, METH_O, builtin_bin__doc__},
PyDoc_STRVAR(builtin_callable__doc__,
"callable($module, obj, /)\n"
"--\n"
"\n"
"Return whether the object is callable (i.e., some kind of function).\n"
"\n"
"Note that classes are callable, as are instances of classes with a\n"
"__call__() method.");
#define BUILTIN_CALLABLE_METHODDEF \
{"callable", (PyCFunction)builtin_callable, METH_O, builtin_callable__doc__},
PyDoc_STRVAR(builtin_format__doc__,
"format($module, value, format_spec=\'\', /)\n"
"--\n"
"\n"
"Return value.__format__(format_spec)\n"
"\n"
"format_spec defaults to the empty string.\n"
"See the Format Specification Mini-Language section of help(\'FORMATTING\') for\n"
"details.");
#define BUILTIN_FORMAT_METHODDEF \
{"format", (PyCFunction)(void(*)(void))builtin_format, METH_FASTCALL, builtin_format__doc__},
static PyObject *
builtin_format_impl(PyObject *module, PyObject *value, PyObject *format_spec);
static PyObject *
builtin_format(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *value;
PyObject *format_spec = NULL;
if (!_PyArg_CheckPositional("format", nargs, 1, 2)) {
goto exit;
}
value = args[0];
if (nargs < 2) {
goto skip_optional;
}
if (!PyUnicode_Check(args[1])) {
_PyArg_BadArgument("format", "argument 2", "str", args[1]);
goto exit;
}
if (PyUnicode_READY(args[1]) == -1) {
goto exit;
}
format_spec = args[1];
skip_optional:
return_value = builtin_format_impl(module, value, format_spec);
exit:
return return_value;
}
PyDoc_STRVAR(builtin_chr__doc__,
"chr($module, i, /)\n"
"--\n"
"\n"
"Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff.");
#define BUILTIN_CHR_METHODDEF \
{"chr", (PyCFunction)builtin_chr, METH_O, builtin_chr__doc__},
static PyObject *
builtin_chr_impl(PyObject *module, int i);
static PyObject *
builtin_chr(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
int i;
if (PyFloat_Check(arg)) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float" );
goto exit;
}
i = _PyLong_AsInt(arg);
if (i == -1 && PyErr_Occurred()) {
goto exit;
}
return_value = builtin_chr_impl(module, i);
exit:
return return_value;
}
PyDoc_STRVAR(builtin_compile__doc__,
"compile($module, /, source, filename, mode, flags=0,\n"
" dont_inherit=False, optimize=-1, *, _feature_version=-1)\n"
"--\n"
"\n"
"Compile source into a code object that can be executed by exec() or eval().\n"
"\n"
"The source code may represent a Python module, statement or expression.\n"
"The filename will be used for run-time error messages.\n"
"The mode must be \'exec\' to compile a module, \'single\' to compile a\n"
"single (interactive) statement, or \'eval\' to compile an expression.\n"
"The flags argument, if present, controls which future statements influence\n"
"the compilation of the code.\n"
"The dont_inherit argument, if true, stops the compilation inheriting\n"
"the effects of any future statements in effect in the code calling\n"
"compile; if absent or false these statements do influence the compilation,\n"
"in addition to any features explicitly specified.");
#define BUILTIN_COMPILE_METHODDEF \
{"compile", (PyCFunction)(void(*)(void))builtin_compile, METH_FASTCALL|METH_KEYWORDS, builtin_compile__doc__},
static PyObject *
builtin_compile_impl(PyObject *module, PyObject *source, PyObject *filename,
const char *mode, int flags, int dont_inherit,
int optimize, int feature_version);
static PyObject *
builtin_compile(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"source", "filename", "mode", "flags", "dont_inherit", "optimize", "_feature_version", NULL};
static _PyArg_Parser _parser = {NULL, _keywords, "compile", 0};
PyObject *argsbuf[7];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3;
PyObject *source;
PyObject *filename;
const char *mode;
int flags = 0;
int dont_inherit = 0;
int optimize = -1;
int feature_version = -1;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 6, 0, argsbuf);
if (!args) {
goto exit;
}
source = args[0];
if (!PyUnicode_FSDecoder(args[1], &filename)) {
goto exit;
}
if (!PyUnicode_Check(args[2])) {
_PyArg_BadArgument("compile", "argument 'mode'", "str", args[2]);
goto exit;
}
Py_ssize_t mode_length;
mode = PyUnicode_AsUTF8AndSize(args[2], &mode_length);
if (mode == NULL) {
goto exit;
}
if (strlen(mode) != (size_t)mode_length) {
PyErr_SetString(PyExc_ValueError, "embedded null character");
goto exit;
}
if (!noptargs) {
goto skip_optional_pos;
}
if (args[3]) {
if (PyFloat_Check(args[3])) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float" );
goto exit;
}
flags = _PyLong_AsInt(args[3]);
if (flags == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
if (args[4]) {
if (PyFloat_Check(args[4])) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float" );
goto exit;
}
dont_inherit = _PyLong_AsInt(args[4]);
if (dont_inherit == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
if (args[5]) {
if (PyFloat_Check(args[5])) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float" );
goto exit;
}
optimize = _PyLong_AsInt(args[5]);
if (optimize == -1 && PyErr_Occurred()) {
goto exit;
}
if (!--noptargs) {
goto skip_optional_pos;
}
}
skip_optional_pos:
if (!noptargs) {
goto skip_optional_kwonly;
}
if (PyFloat_Check(args[6])) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float" );
goto exit;
}
feature_version = _PyLong_AsInt(args[6]);
if (feature_version == -1 && PyErr_Occurred()) {
goto exit;
}
skip_optional_kwonly:
return_value = builtin_compile_impl(module, source, filename, mode, flags, dont_inherit, optimize, feature_version);
exit:
return return_value;
}
PyDoc_STRVAR(builtin_divmod__doc__,
"divmod($module, x, y, /)\n"
"--\n"
"\n"
"Return the tuple (x//y, x%y). Invariant: div*y + mod == x.");
#define BUILTIN_DIVMOD_METHODDEF \
{"divmod", (PyCFunction)(void(*)(void))builtin_divmod, METH_FASTCALL, builtin_divmod__doc__},
static PyObject *
builtin_divmod_impl(PyObject *module, PyObject *x, PyObject *y);
static PyObject *
builtin_divmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *x;
PyObject *y;
if (!_PyArg_CheckPositional("divmod", nargs, 2, 2)) {
goto exit;
}
x = args[0];
y = args[1];
return_value = builtin_divmod_impl(module, x, y);
exit:
return return_value;
}
PyDoc_STRVAR(builtin_eval__doc__,
"eval($module, source, globals=None, locals=None, /)\n"
"--\n"
"\n"
"Evaluate the given source in the context of globals and locals.\n"
"\n"
"The source may be a string representing a Python expression\n"
"or a code object as returned by compile().\n"
"The globals must be a dictionary and locals can be any mapping,\n"
"defaulting to the current globals and locals.\n"
"If only globals is given, locals defaults to it.");
#define BUILTIN_EVAL_METHODDEF \
{"eval", (PyCFunction)(void(*)(void))builtin_eval, METH_FASTCALL, builtin_eval__doc__},
static PyObject *
builtin_eval_impl(PyObject *module, PyObject *source, PyObject *globals,
PyObject *locals);
static PyObject *
builtin_eval(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *source;
PyObject *globals = Py_None;
PyObject *locals = Py_None;
if (!_PyArg_CheckPositional("eval", nargs, 1, 3)) {
goto exit;
}
source = args[0];
if (nargs < 2) {
goto skip_optional;
}
globals = args[1];
if (nargs < 3) {
goto skip_optional;
}
locals = args[2];
skip_optional:
return_value = builtin_eval_impl(module, source, globals, locals);
exit:
return return_value;
}
PyDoc_STRVAR(builtin_exec__doc__,
"exec($module, source, globals=None, locals=None, /)\n"
"--\n"
"\n"
"Execute the given source in the context of globals and locals.\n"
"\n"
"The source may be a string representing one or more Python statements\n"
"or a code object as returned by compile().\n"
"The globals must be a dictionary and locals can be any mapping,\n"
"defaulting to the current globals and locals.\n"
"If only globals is given, locals defaults to it.");
#define BUILTIN_EXEC_METHODDEF \
{"exec", (PyCFunction)(void(*)(void))builtin_exec, METH_FASTCALL, builtin_exec__doc__},
static PyObject *
builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
PyObject *locals);
static PyObject *
builtin_exec(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *source;
PyObject *globals = Py_None;
PyObject *locals = Py_None;
if (!_PyArg_CheckPositional("exec", nargs, 1, 3)) {
goto exit;
}
source = args[0];
if (nargs < 2) {
goto skip_optional;
}
globals = args[1];
if (nargs < 3) {
goto skip_optional;
}
locals = args[2];
skip_optional:
return_value = builtin_exec_impl(module, source, globals, locals);
exit:
return return_value;
}
PyDoc_STRVAR(builtin_globals__doc__,
"globals($module, /)\n"
"--\n"
"\n"
"Return the dictionary containing the current scope\'s global variables.\n"
"\n"
"NOTE: Updates to this dictionary *will* affect name lookups in the current\n"
"global scope and vice-versa.");
#define BUILTIN_GLOBALS_METHODDEF \
{"globals", (PyCFunction)builtin_globals, METH_NOARGS, builtin_globals__doc__},
static PyObject *
builtin_globals_impl(PyObject *module);
static PyObject *
builtin_globals(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return builtin_globals_impl(module);
}
PyDoc_STRVAR(builtin_hasattr__doc__,
"hasattr($module, obj, name, /)\n"
"--\n"
"\n"
"Return whether the object has an attribute with the given name.\n"
"\n"
"This is done by calling getattr(obj, name) and catching AttributeError.");
#define BUILTIN_HASATTR_METHODDEF \
{"hasattr", (PyCFunction)(void(*)(void))builtin_hasattr, METH_FASTCALL, builtin_hasattr__doc__},
static PyObject *
builtin_hasattr_impl(PyObject *module, PyObject *obj, PyObject *name);
static PyObject *
builtin_hasattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *obj;
PyObject *name;
if (!_PyArg_CheckPositional("hasattr", nargs, 2, 2)) {
goto exit;
}
obj = args[0];
name = args[1];
return_value = builtin_hasattr_impl(module, obj, name);
exit:
return return_value;
}
PyDoc_STRVAR(builtin_id__doc__,
"id($module, obj, /)\n"
"--\n"
"\n"
"Return the identity of an object.\n"
"\n"
"This is guaranteed to be unique among simultaneously existing objects.\n"
"(CPython uses the object\'s memory address.)");
#define BUILTIN_ID_METHODDEF \
{"id", (PyCFunction)builtin_id, METH_O, builtin_id__doc__},
PyDoc_STRVAR(builtin_setattr__doc__,
"setattr($module, obj, name, value, /)\n"
"--\n"
"\n"
"Sets the named attribute on the given object to the specified value.\n"
"\n"
"setattr(x, \'y\', v) is equivalent to ``x.y = v\'\'");
#define BUILTIN_SETATTR_METHODDEF \
{"setattr", (PyCFunction)(void(*)(void))builtin_setattr, METH_FASTCALL, builtin_setattr__doc__},
static PyObject *
builtin_setattr_impl(PyObject *module, PyObject *obj, PyObject *name,
PyObject *value);
static PyObject *
builtin_setattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *obj;
PyObject *name;
PyObject *value;
if (!_PyArg_CheckPositional("setattr", nargs, 3, 3)) {
goto exit;
}
obj = args[0];
name = args[1];
value = args[2];
return_value = builtin_setattr_impl(module, obj, name, value);
exit:
return return_value;
}
PyDoc_STRVAR(builtin_delattr__doc__,
"delattr($module, obj, name, /)\n"
"--\n"
"\n"
"Deletes the named attribute from the given object.\n"
"\n"
"delattr(x, \'y\') is equivalent to ``del x.y\'\'");
#define BUILTIN_DELATTR_METHODDEF \
{"delattr", (PyCFunction)(void(*)(void))builtin_delattr, METH_FASTCALL, builtin_delattr__doc__},
static PyObject *
builtin_delattr_impl(PyObject *module, PyObject *obj, PyObject *name);
static PyObject *
builtin_delattr(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *obj;
PyObject *name;
if (!_PyArg_CheckPositional("delattr", nargs, 2, 2)) {
goto exit;
}
obj = args[0];
name = args[1];
return_value = builtin_delattr_impl(module, obj, name);
exit:
return return_value;
}
PyDoc_STRVAR(builtin_hash__doc__,
"hash($module, obj, /)\n"
"--\n"
"\n"
"Return the hash value for the given object.\n"
"\n"
"Two objects that compare equal must also have the same hash value, but the\n"
"reverse is not necessarily true.");
#define BUILTIN_HASH_METHODDEF \
{"hash", (PyCFunction)builtin_hash, METH_O, builtin_hash__doc__},
PyDoc_STRVAR(builtin_hex__doc__,
"hex($module, number, /)\n"
"--\n"
"\n"
"Return the hexadecimal representation of an integer.\n"
"\n"
" >>> hex(12648430)\n"
" \'0xc0ffee\'");
#define BUILTIN_HEX_METHODDEF \
{"hex", (PyCFunction)builtin_hex, METH_O, builtin_hex__doc__},
PyDoc_STRVAR(builtin_len__doc__,
"len($module, obj, /)\n"
"--\n"
"\n"
"Return the number of items in a container.");
#define BUILTIN_LEN_METHODDEF \
{"len", (PyCFunction)builtin_len, METH_O, builtin_len__doc__},
PyDoc_STRVAR(builtin_locals__doc__,
"locals($module, /)\n"
"--\n"
"\n"
"Return a dictionary containing the current scope\'s local variables.\n"
"\n"
"NOTE: Whether or not updates to this dictionary will affect name lookups in\n"
"the local scope and vice-versa is *implementation dependent* and not\n"
"covered by any backwards compatibility guarantees.");
#define BUILTIN_LOCALS_METHODDEF \
{"locals", (PyCFunction)builtin_locals, METH_NOARGS, builtin_locals__doc__},
static PyObject *
builtin_locals_impl(PyObject *module);
static PyObject *
builtin_locals(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return builtin_locals_impl(module);
}
PyDoc_STRVAR(builtin_oct__doc__,
"oct($module, number, /)\n"
"--\n"
"\n"
"Return the octal representation of an integer.\n"
"\n"
" >>> oct(342391)\n"
" \'0o1234567\'");
#define BUILTIN_OCT_METHODDEF \
{"oct", (PyCFunction)builtin_oct, METH_O, builtin_oct__doc__},
PyDoc_STRVAR(builtin_ord__doc__,
"ord($module, c, /)\n"
"--\n"
"\n"
"Return the Unicode code point for a one-character string.");
#define BUILTIN_ORD_METHODDEF \
{"ord", (PyCFunction)builtin_ord, METH_O, builtin_ord__doc__},
PyDoc_STRVAR(builtin_pow__doc__,
"pow($module, /, base, exp, mod=None)\n"
"--\n"
"\n"
"Equivalent to base**exp with 2 arguments or base**exp % mod with 3 arguments\n"
"\n"
"Some types, such as ints, are able to use a more efficient algorithm when\n"
"invoked using the three argument form.");
#define BUILTIN_POW_METHODDEF \
{"pow", (PyCFunction)(void(*)(void))builtin_pow, METH_FASTCALL|METH_KEYWORDS, builtin_pow__doc__},
static PyObject *
builtin_pow_impl(PyObject *module, PyObject *base, PyObject *exp,
PyObject *mod);
static PyObject *
builtin_pow(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"base", "exp", "mod", NULL};
static _PyArg_Parser _parser = {NULL, _keywords, "pow", 0};
PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
PyObject *base;
PyObject *exp;
PyObject *mod = Py_None;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf);
if (!args) {
goto exit;
}
base = args[0];
exp = args[1];
if (!noptargs) {
goto skip_optional_pos;
}
mod = args[2];
skip_optional_pos:
return_value = builtin_pow_impl(module, base, exp, mod);
exit:
return return_value;
}
PyDoc_STRVAR(builtin_input__doc__,
"input($module, prompt=None, /)\n"
"--\n"
"\n"
"Read a string from standard input. The trailing newline is stripped.\n"
"\n"
"The prompt string, if given, is printed to standard output without a\n"
"trailing newline before reading input.\n"
"\n"
"If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError.\n"
"On *nix systems, readline is used if available.");
#define BUILTIN_INPUT_METHODDEF \
{"input", (PyCFunction)(void(*)(void))builtin_input, METH_FASTCALL, builtin_input__doc__},
static PyObject *
builtin_input_impl(PyObject *module, PyObject *prompt);
static PyObject *
builtin_input(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *prompt = NULL;
if (!_PyArg_CheckPositional("input", nargs, 0, 1)) {
goto exit;
}
if (nargs < 1) {
goto skip_optional;
}
prompt = args[0];
skip_optional:
return_value = builtin_input_impl(module, prompt);
exit:
return return_value;
}
PyDoc_STRVAR(builtin_repr__doc__,
"repr($module, obj, /)\n"
"--\n"
"\n"
"Return the canonical string representation of the object.\n"
"\n"
"For many object types, including most builtins, eval(repr(obj)) == obj.");
#define BUILTIN_REPR_METHODDEF \
{"repr", (PyCFunction)builtin_repr, METH_O, builtin_repr__doc__},
PyDoc_STRVAR(builtin_round__doc__,
"round($module, /, number, ndigits=None)\n"
"--\n"
"\n"
"Round a number to a given precision in decimal digits.\n"
"\n"
"The return value is an integer if ndigits is omitted or None. Otherwise\n"
"the return value has the same type as the number. ndigits may be negative.");
#define BUILTIN_ROUND_METHODDEF \
{"round", (PyCFunction)(void(*)(void))builtin_round, METH_FASTCALL|METH_KEYWORDS, builtin_round__doc__},
static PyObject *
builtin_round_impl(PyObject *module, PyObject *number, PyObject *ndigits);
static PyObject *
builtin_round(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"number", "ndigits", NULL};
static _PyArg_Parser _parser = {NULL, _keywords, "round", 0};
PyObject *argsbuf[2];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
PyObject *number;
PyObject *ndigits = Py_None;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);
if (!args) {
goto exit;
}
number = args[0];
if (!noptargs) {
goto skip_optional_pos;
}
ndigits = args[1];
skip_optional_pos:
return_value = builtin_round_impl(module, number, ndigits);
exit:
return return_value;
}
PyDoc_STRVAR(builtin_sum__doc__,
"sum($module, iterable, /, start=0)\n"
"--\n"
"\n"
"Return the sum of a \'start\' value (default: 0) plus an iterable of numbers\n"
"\n"
"When the iterable is empty, return the start value.\n"
"This function is intended specifically for use with numeric values and may\n"
"reject non-numeric types.");
#define BUILTIN_SUM_METHODDEF \
{"sum", (PyCFunction)(void(*)(void))builtin_sum, METH_FASTCALL|METH_KEYWORDS, builtin_sum__doc__},
static PyObject *
builtin_sum_impl(PyObject *module, PyObject *iterable, PyObject *start);
static PyObject *
builtin_sum(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", "start", NULL};
static _PyArg_Parser _parser = {NULL, _keywords, "sum", 0};
PyObject *argsbuf[2];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
PyObject *iterable;
PyObject *start = NULL;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);
if (!args) {
goto exit;
}
iterable = args[0];
if (!noptargs) {
goto skip_optional_pos;
}
start = args[1];
skip_optional_pos:
return_value = builtin_sum_impl(module, iterable, start);
exit:
return return_value;
}
PyDoc_STRVAR(builtin_isinstance__doc__,
"isinstance($module, obj, class_or_tuple, /)\n"
"--\n"
"\n"
"Return whether an object is an instance of a class or of a subclass thereof.\n"
"\n"
"A tuple, as in ``isinstance(x, (A, B, ...))``, may be given as the target to\n"
"check against. This is equivalent to ``isinstance(x, A) or isinstance(x, B)\n"
"or ...`` etc.");
#define BUILTIN_ISINSTANCE_METHODDEF \
{"isinstance", (PyCFunction)(void(*)(void))builtin_isinstance, METH_FASTCALL, builtin_isinstance__doc__},
static PyObject *
builtin_isinstance_impl(PyObject *module, PyObject *obj,
PyObject *class_or_tuple);
static PyObject *
builtin_isinstance(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *obj;
PyObject *class_or_tuple;
if (!_PyArg_CheckPositional("isinstance", nargs, 2, 2)) {
goto exit;
}
obj = args[0];
class_or_tuple = args[1];
return_value = builtin_isinstance_impl(module, obj, class_or_tuple);
exit:
return return_value;
}
PyDoc_STRVAR(builtin_issubclass__doc__,
"issubclass($module, cls, class_or_tuple, /)\n"
"--\n"
"\n"
"Return whether \'cls\' is a derived from another class or is the same class.\n"
"\n"
"A tuple, as in ``issubclass(x, (A, B, ...))``, may be given as the target to\n"
"check against. This is equivalent to ``issubclass(x, A) or issubclass(x, B)\n"
"or ...`` etc.");
#define BUILTIN_ISSUBCLASS_METHODDEF \
{"issubclass", (PyCFunction)(void(*)(void))builtin_issubclass, METH_FASTCALL, builtin_issubclass__doc__},
static PyObject *
builtin_issubclass_impl(PyObject *module, PyObject *cls,
PyObject *class_or_tuple);
static PyObject *
builtin_issubclass(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *cls;
PyObject *class_or_tuple;
if (!_PyArg_CheckPositional("issubclass", nargs, 2, 2)) {
goto exit;
}
cls = args[0];
class_or_tuple = args[1];
return_value = builtin_issubclass_impl(module, cls, class_or_tuple);
exit:
return return_value;
}
/*[clinic end generated code: output=29686a89b739d600 input=a9049054013a1b77]*/

View File

@ -0,0 +1,180 @@
/*[clinic input]
preserve
[clinic start generated code]*/
PyDoc_STRVAR(_contextvars_Context_get__doc__,
"get($self, key, default=None, /)\n"
"--\n"
"\n"
"Return the value for `key` if `key` has the value in the context object.\n"
"\n"
"If `key` does not exist, return `default`. If `default` is not given,\n"
"return None.");
#define _CONTEXTVARS_CONTEXT_GET_METHODDEF \
{"get", (PyCFunction)(void(*)(void))_contextvars_Context_get, METH_FASTCALL, _contextvars_Context_get__doc__},
static PyObject *
_contextvars_Context_get_impl(PyContext *self, PyObject *key,
PyObject *default_value);
static PyObject *
_contextvars_Context_get(PyContext *self, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *key;
PyObject *default_value = Py_None;
if (!_PyArg_CheckPositional("get", nargs, 1, 2)) {
goto exit;
}
key = args[0];
if (nargs < 2) {
goto skip_optional;
}
default_value = args[1];
skip_optional:
return_value = _contextvars_Context_get_impl(self, key, default_value);
exit:
return return_value;
}
PyDoc_STRVAR(_contextvars_Context_items__doc__,
"items($self, /)\n"
"--\n"
"\n"
"Return all variables and their values in the context object.\n"
"\n"
"The result is returned as a list of 2-tuples (variable, value).");
#define _CONTEXTVARS_CONTEXT_ITEMS_METHODDEF \
{"items", (PyCFunction)_contextvars_Context_items, METH_NOARGS, _contextvars_Context_items__doc__},
static PyObject *
_contextvars_Context_items_impl(PyContext *self);
static PyObject *
_contextvars_Context_items(PyContext *self, PyObject *Py_UNUSED(ignored))
{
return _contextvars_Context_items_impl(self);
}
PyDoc_STRVAR(_contextvars_Context_keys__doc__,
"keys($self, /)\n"
"--\n"
"\n"
"Return a list of all variables in the context object.");
#define _CONTEXTVARS_CONTEXT_KEYS_METHODDEF \
{"keys", (PyCFunction)_contextvars_Context_keys, METH_NOARGS, _contextvars_Context_keys__doc__},
static PyObject *
_contextvars_Context_keys_impl(PyContext *self);
static PyObject *
_contextvars_Context_keys(PyContext *self, PyObject *Py_UNUSED(ignored))
{
return _contextvars_Context_keys_impl(self);
}
PyDoc_STRVAR(_contextvars_Context_values__doc__,
"values($self, /)\n"
"--\n"
"\n"
"Return a list of all variables\' values in the context object.");
#define _CONTEXTVARS_CONTEXT_VALUES_METHODDEF \
{"values", (PyCFunction)_contextvars_Context_values, METH_NOARGS, _contextvars_Context_values__doc__},
static PyObject *
_contextvars_Context_values_impl(PyContext *self);
static PyObject *
_contextvars_Context_values(PyContext *self, PyObject *Py_UNUSED(ignored))
{
return _contextvars_Context_values_impl(self);
}
PyDoc_STRVAR(_contextvars_Context_copy__doc__,
"copy($self, /)\n"
"--\n"
"\n"
"Return a shallow copy of the context object.");
#define _CONTEXTVARS_CONTEXT_COPY_METHODDEF \
{"copy", (PyCFunction)_contextvars_Context_copy, METH_NOARGS, _contextvars_Context_copy__doc__},
static PyObject *
_contextvars_Context_copy_impl(PyContext *self);
static PyObject *
_contextvars_Context_copy(PyContext *self, PyObject *Py_UNUSED(ignored))
{
return _contextvars_Context_copy_impl(self);
}
PyDoc_STRVAR(_contextvars_ContextVar_get__doc__,
"get($self, default=<unrepresentable>, /)\n"
"--\n"
"\n"
"Return a value for the context variable for the current context.\n"
"\n"
"If there is no value for the variable in the current context, the method will:\n"
" * return the value of the default argument of the method, if provided; or\n"
" * return the default value for the context variable, if it was created\n"
" with one; or\n"
" * raise a LookupError.");
#define _CONTEXTVARS_CONTEXTVAR_GET_METHODDEF \
{"get", (PyCFunction)(void(*)(void))_contextvars_ContextVar_get, METH_FASTCALL, _contextvars_ContextVar_get__doc__},
static PyObject *
_contextvars_ContextVar_get_impl(PyContextVar *self, PyObject *default_value);
static PyObject *
_contextvars_ContextVar_get(PyContextVar *self, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *default_value = NULL;
if (!_PyArg_CheckPositional("get", nargs, 0, 1)) {
goto exit;
}
if (nargs < 1) {
goto skip_optional;
}
default_value = args[0];
skip_optional:
return_value = _contextvars_ContextVar_get_impl(self, default_value);
exit:
return return_value;
}
PyDoc_STRVAR(_contextvars_ContextVar_set__doc__,
"set($self, value, /)\n"
"--\n"
"\n"
"Call to set a new value for the context variable in the current context.\n"
"\n"
"The required value argument is the new value for the context variable.\n"
"\n"
"Returns a Token object that can be used to restore the variable to its previous\n"
"value via the `ContextVar.reset()` method.");
#define _CONTEXTVARS_CONTEXTVAR_SET_METHODDEF \
{"set", (PyCFunction)_contextvars_ContextVar_set, METH_O, _contextvars_ContextVar_set__doc__},
PyDoc_STRVAR(_contextvars_ContextVar_reset__doc__,
"reset($self, token, /)\n"
"--\n"
"\n"
"Reset the context variable.\n"
"\n"
"The variable is reset to the value it had before the `ContextVar.set()` that\n"
"created the token was used.");
#define _CONTEXTVARS_CONTEXTVAR_RESET_METHODDEF \
{"reset", (PyCFunction)_contextvars_ContextVar_reset, METH_O, _contextvars_ContextVar_reset__doc__},
/*[clinic end generated code: output=f2e42f34e358e179 input=a9049054013a1b77]*/

View File

@ -0,0 +1,457 @@
/*[clinic input]
preserve
[clinic start generated code]*/
PyDoc_STRVAR(_imp_lock_held__doc__,
"lock_held($module, /)\n"
"--\n"
"\n"
"Return True if the import lock is currently held, else False.\n"
"\n"
"On platforms without threads, return False.");
#define _IMP_LOCK_HELD_METHODDEF \
{"lock_held", (PyCFunction)_imp_lock_held, METH_NOARGS, _imp_lock_held__doc__},
static PyObject *
_imp_lock_held_impl(PyObject *module);
static PyObject *
_imp_lock_held(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return _imp_lock_held_impl(module);
}
PyDoc_STRVAR(_imp_acquire_lock__doc__,
"acquire_lock($module, /)\n"
"--\n"
"\n"
"Acquires the interpreter\'s import lock for the current thread.\n"
"\n"
"This lock should be used by import hooks to ensure thread-safety when importing\n"
"modules. On platforms without threads, this function does nothing.");
#define _IMP_ACQUIRE_LOCK_METHODDEF \
{"acquire_lock", (PyCFunction)_imp_acquire_lock, METH_NOARGS, _imp_acquire_lock__doc__},
static PyObject *
_imp_acquire_lock_impl(PyObject *module);
static PyObject *
_imp_acquire_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return _imp_acquire_lock_impl(module);
}
PyDoc_STRVAR(_imp_release_lock__doc__,
"release_lock($module, /)\n"
"--\n"
"\n"
"Release the interpreter\'s import lock.\n"
"\n"
"On platforms without threads, this function does nothing.");
#define _IMP_RELEASE_LOCK_METHODDEF \
{"release_lock", (PyCFunction)_imp_release_lock, METH_NOARGS, _imp_release_lock__doc__},
static PyObject *
_imp_release_lock_impl(PyObject *module);
static PyObject *
_imp_release_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return _imp_release_lock_impl(module);
}
PyDoc_STRVAR(_imp__fix_co_filename__doc__,
"_fix_co_filename($module, code, path, /)\n"
"--\n"
"\n"
"Changes code.co_filename to specify the passed-in file path.\n"
"\n"
" code\n"
" Code object to change.\n"
" path\n"
" File path to use.");
#define _IMP__FIX_CO_FILENAME_METHODDEF \
{"_fix_co_filename", (PyCFunction)(void(*)(void))_imp__fix_co_filename, METH_FASTCALL, _imp__fix_co_filename__doc__},
static PyObject *
_imp__fix_co_filename_impl(PyObject *module, PyCodeObject *code,
PyObject *path);
static PyObject *
_imp__fix_co_filename(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyCodeObject *code;
PyObject *path;
if (!_PyArg_CheckPositional("_fix_co_filename", nargs, 2, 2)) {
goto exit;
}
if (!PyObject_TypeCheck(args[0], &PyCode_Type)) {
_PyArg_BadArgument("_fix_co_filename", "argument 1", (&PyCode_Type)->tp_name, args[0]);
goto exit;
}
code = (PyCodeObject *)args[0];
if (!PyUnicode_Check(args[1])) {
_PyArg_BadArgument("_fix_co_filename", "argument 2", "str", args[1]);
goto exit;
}
if (PyUnicode_READY(args[1]) == -1) {
goto exit;
}
path = args[1];
return_value = _imp__fix_co_filename_impl(module, code, path);
exit:
return return_value;
}
PyDoc_STRVAR(_imp_create_builtin__doc__,
"create_builtin($module, spec, /)\n"
"--\n"
"\n"
"Create an extension module.");
#define _IMP_CREATE_BUILTIN_METHODDEF \
{"create_builtin", (PyCFunction)_imp_create_builtin, METH_O, _imp_create_builtin__doc__},
PyDoc_STRVAR(_imp_extension_suffixes__doc__,
"extension_suffixes($module, /)\n"
"--\n"
"\n"
"Returns the list of file suffixes used to identify extension modules.");
#define _IMP_EXTENSION_SUFFIXES_METHODDEF \
{"extension_suffixes", (PyCFunction)_imp_extension_suffixes, METH_NOARGS, _imp_extension_suffixes__doc__},
static PyObject *
_imp_extension_suffixes_impl(PyObject *module);
static PyObject *
_imp_extension_suffixes(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return _imp_extension_suffixes_impl(module);
}
PyDoc_STRVAR(_imp_init_frozen__doc__,
"init_frozen($module, name, /)\n"
"--\n"
"\n"
"Initializes a frozen module.");
#define _IMP_INIT_FROZEN_METHODDEF \
{"init_frozen", (PyCFunction)_imp_init_frozen, METH_O, _imp_init_frozen__doc__},
static PyObject *
_imp_init_frozen_impl(PyObject *module, PyObject *name);
static PyObject *
_imp_init_frozen(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
PyObject *name;
if (!PyUnicode_Check(arg)) {
_PyArg_BadArgument("init_frozen", "argument", "str", arg);
goto exit;
}
if (PyUnicode_READY(arg) == -1) {
goto exit;
}
name = arg;
return_value = _imp_init_frozen_impl(module, name);
exit:
return return_value;
}
PyDoc_STRVAR(_imp_get_frozen_object__doc__,
"get_frozen_object($module, name, /)\n"
"--\n"
"\n"
"Create a code object for a frozen module.");
#define _IMP_GET_FROZEN_OBJECT_METHODDEF \
{"get_frozen_object", (PyCFunction)_imp_get_frozen_object, METH_O, _imp_get_frozen_object__doc__},
static PyObject *
_imp_get_frozen_object_impl(PyObject *module, PyObject *name);
static PyObject *
_imp_get_frozen_object(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
PyObject *name;
if (!PyUnicode_Check(arg)) {
_PyArg_BadArgument("get_frozen_object", "argument", "str", arg);
goto exit;
}
if (PyUnicode_READY(arg) == -1) {
goto exit;
}
name = arg;
return_value = _imp_get_frozen_object_impl(module, name);
exit:
return return_value;
}
PyDoc_STRVAR(_imp_is_frozen_package__doc__,
"is_frozen_package($module, name, /)\n"
"--\n"
"\n"
"Returns True if the module name is of a frozen package.");
#define _IMP_IS_FROZEN_PACKAGE_METHODDEF \
{"is_frozen_package", (PyCFunction)_imp_is_frozen_package, METH_O, _imp_is_frozen_package__doc__},
static PyObject *
_imp_is_frozen_package_impl(PyObject *module, PyObject *name);
static PyObject *
_imp_is_frozen_package(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
PyObject *name;
if (!PyUnicode_Check(arg)) {
_PyArg_BadArgument("is_frozen_package", "argument", "str", arg);
goto exit;
}
if (PyUnicode_READY(arg) == -1) {
goto exit;
}
name = arg;
return_value = _imp_is_frozen_package_impl(module, name);
exit:
return return_value;
}
PyDoc_STRVAR(_imp_is_builtin__doc__,
"is_builtin($module, name, /)\n"
"--\n"
"\n"
"Returns True if the module name corresponds to a built-in module.");
#define _IMP_IS_BUILTIN_METHODDEF \
{"is_builtin", (PyCFunction)_imp_is_builtin, METH_O, _imp_is_builtin__doc__},
static PyObject *
_imp_is_builtin_impl(PyObject *module, PyObject *name);
static PyObject *
_imp_is_builtin(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
PyObject *name;
if (!PyUnicode_Check(arg)) {
_PyArg_BadArgument("is_builtin", "argument", "str", arg);
goto exit;
}
if (PyUnicode_READY(arg) == -1) {
goto exit;
}
name = arg;
return_value = _imp_is_builtin_impl(module, name);
exit:
return return_value;
}
PyDoc_STRVAR(_imp_is_frozen__doc__,
"is_frozen($module, name, /)\n"
"--\n"
"\n"
"Returns True if the module name corresponds to a frozen module.");
#define _IMP_IS_FROZEN_METHODDEF \
{"is_frozen", (PyCFunction)_imp_is_frozen, METH_O, _imp_is_frozen__doc__},
static PyObject *
_imp_is_frozen_impl(PyObject *module, PyObject *name);
static PyObject *
_imp_is_frozen(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
PyObject *name;
if (!PyUnicode_Check(arg)) {
_PyArg_BadArgument("is_frozen", "argument", "str", arg);
goto exit;
}
if (PyUnicode_READY(arg) == -1) {
goto exit;
}
name = arg;
return_value = _imp_is_frozen_impl(module, name);
exit:
return return_value;
}
#if defined(HAVE_DYNAMIC_LOADING)
PyDoc_STRVAR(_imp_create_dynamic__doc__,
"create_dynamic($module, spec, file=<unrepresentable>, /)\n"
"--\n"
"\n"
"Create an extension module.");
#define _IMP_CREATE_DYNAMIC_METHODDEF \
{"create_dynamic", (PyCFunction)(void(*)(void))_imp_create_dynamic, METH_FASTCALL, _imp_create_dynamic__doc__},
static PyObject *
_imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file);
static PyObject *
_imp_create_dynamic(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *spec;
PyObject *file = NULL;
if (!_PyArg_CheckPositional("create_dynamic", nargs, 1, 2)) {
goto exit;
}
spec = args[0];
if (nargs < 2) {
goto skip_optional;
}
file = args[1];
skip_optional:
return_value = _imp_create_dynamic_impl(module, spec, file);
exit:
return return_value;
}
#endif /* defined(HAVE_DYNAMIC_LOADING) */
#if defined(HAVE_DYNAMIC_LOADING)
PyDoc_STRVAR(_imp_exec_dynamic__doc__,
"exec_dynamic($module, mod, /)\n"
"--\n"
"\n"
"Initialize an extension module.");
#define _IMP_EXEC_DYNAMIC_METHODDEF \
{"exec_dynamic", (PyCFunction)_imp_exec_dynamic, METH_O, _imp_exec_dynamic__doc__},
static int
_imp_exec_dynamic_impl(PyObject *module, PyObject *mod);
static PyObject *
_imp_exec_dynamic(PyObject *module, PyObject *mod)
{
PyObject *return_value = NULL;
int _return_value;
_return_value = _imp_exec_dynamic_impl(module, mod);
if ((_return_value == -1) && PyErr_Occurred()) {
goto exit;
}
return_value = PyLong_FromLong((long)_return_value);
exit:
return return_value;
}
#endif /* defined(HAVE_DYNAMIC_LOADING) */
PyDoc_STRVAR(_imp_exec_builtin__doc__,
"exec_builtin($module, mod, /)\n"
"--\n"
"\n"
"Initialize a built-in module.");
#define _IMP_EXEC_BUILTIN_METHODDEF \
{"exec_builtin", (PyCFunction)_imp_exec_builtin, METH_O, _imp_exec_builtin__doc__},
static int
_imp_exec_builtin_impl(PyObject *module, PyObject *mod);
static PyObject *
_imp_exec_builtin(PyObject *module, PyObject *mod)
{
PyObject *return_value = NULL;
int _return_value;
_return_value = _imp_exec_builtin_impl(module, mod);
if ((_return_value == -1) && PyErr_Occurred()) {
goto exit;
}
return_value = PyLong_FromLong((long)_return_value);
exit:
return return_value;
}
PyDoc_STRVAR(_imp_source_hash__doc__,
"source_hash($module, /, key, source)\n"
"--\n"
"\n");
#define _IMP_SOURCE_HASH_METHODDEF \
{"source_hash", (PyCFunction)(void(*)(void))_imp_source_hash, METH_FASTCALL|METH_KEYWORDS, _imp_source_hash__doc__},
static PyObject *
_imp_source_hash_impl(PyObject *module, long key, Py_buffer *source);
static PyObject *
_imp_source_hash(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"key", "source", NULL};
static _PyArg_Parser _parser = {NULL, _keywords, "source_hash", 0};
PyObject *argsbuf[2];
long key;
Py_buffer source = {NULL, NULL};
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
if (!args) {
goto exit;
}
if (PyFloat_Check(args[0])) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float" );
goto exit;
}
key = PyLong_AsLong(args[0]);
if (key == -1 && PyErr_Occurred()) {
goto exit;
}
if (PyObject_GetBuffer(args[1], &source, PyBUF_SIMPLE) != 0) {
goto exit;
}
if (!PyBuffer_IsContiguous(&source, 'C')) {
_PyArg_BadArgument("source_hash", "argument 'source'", "contiguous buffer", args[1]);
goto exit;
}
return_value = _imp_source_hash_impl(module, key, &source);
exit:
/* Cleanup for source */
if (source.obj) {
PyBuffer_Release(&source);
}
return return_value;
}
#ifndef _IMP_CREATE_DYNAMIC_METHODDEF
#define _IMP_CREATE_DYNAMIC_METHODDEF
#endif /* !defined(_IMP_CREATE_DYNAMIC_METHODDEF) */
#ifndef _IMP_EXEC_DYNAMIC_METHODDEF
#define _IMP_EXEC_DYNAMIC_METHODDEF
#endif /* !defined(_IMP_EXEC_DYNAMIC_METHODDEF) */
/*[clinic end generated code: output=3dc495e9c64d944e input=a9049054013a1b77]*/

View File

@ -0,0 +1,168 @@
/*[clinic input]
preserve
[clinic start generated code]*/
PyDoc_STRVAR(marshal_dump__doc__,
"dump($module, value, file, version=version, /)\n"
"--\n"
"\n"
"Write the value on the open file.\n"
"\n"
" value\n"
" Must be a supported type.\n"
" file\n"
" Must be a writeable binary file.\n"
" version\n"
" Indicates the data format that dump should use.\n"
"\n"
"If the value has (or contains an object that has) an unsupported type, a\n"
"ValueError exception is raised - but garbage data will also be written\n"
"to the file. The object will not be properly read back by load().");
#define MARSHAL_DUMP_METHODDEF \
{"dump", (PyCFunction)(void(*)(void))marshal_dump, METH_FASTCALL, marshal_dump__doc__},
static PyObject *
marshal_dump_impl(PyObject *module, PyObject *value, PyObject *file,
int version);
static PyObject *
marshal_dump(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *value;
PyObject *file;
int version = Py_MARSHAL_VERSION;
if (!_PyArg_CheckPositional("dump", nargs, 2, 3)) {
goto exit;
}
value = args[0];
file = args[1];
if (nargs < 3) {
goto skip_optional;
}
if (PyFloat_Check(args[2])) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float" );
goto exit;
}
version = _PyLong_AsInt(args[2]);
if (version == -1 && PyErr_Occurred()) {
goto exit;
}
skip_optional:
return_value = marshal_dump_impl(module, value, file, version);
exit:
return return_value;
}
PyDoc_STRVAR(marshal_load__doc__,
"load($module, file, /)\n"
"--\n"
"\n"
"Read one value from the open file and return it.\n"
"\n"
" file\n"
" Must be readable binary file.\n"
"\n"
"If no valid value is read (e.g. because the data has a different Python\n"
"version\'s incompatible marshal format), raise EOFError, ValueError or\n"
"TypeError.\n"
"\n"
"Note: If an object containing an unsupported type was marshalled with\n"
"dump(), load() will substitute None for the unmarshallable type.");
#define MARSHAL_LOAD_METHODDEF \
{"load", (PyCFunction)marshal_load, METH_O, marshal_load__doc__},
PyDoc_STRVAR(marshal_dumps__doc__,
"dumps($module, value, version=version, /)\n"
"--\n"
"\n"
"Return the bytes object that would be written to a file by dump(value, file).\n"
"\n"
" value\n"
" Must be a supported type.\n"
" version\n"
" Indicates the data format that dumps should use.\n"
"\n"
"Raise a ValueError exception if value has (or contains an object that has) an\n"
"unsupported type.");
#define MARSHAL_DUMPS_METHODDEF \
{"dumps", (PyCFunction)(void(*)(void))marshal_dumps, METH_FASTCALL, marshal_dumps__doc__},
static PyObject *
marshal_dumps_impl(PyObject *module, PyObject *value, int version);
static PyObject *
marshal_dumps(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *value;
int version = Py_MARSHAL_VERSION;
if (!_PyArg_CheckPositional("dumps", nargs, 1, 2)) {
goto exit;
}
value = args[0];
if (nargs < 2) {
goto skip_optional;
}
if (PyFloat_Check(args[1])) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float" );
goto exit;
}
version = _PyLong_AsInt(args[1]);
if (version == -1 && PyErr_Occurred()) {
goto exit;
}
skip_optional:
return_value = marshal_dumps_impl(module, value, version);
exit:
return return_value;
}
PyDoc_STRVAR(marshal_loads__doc__,
"loads($module, bytes, /)\n"
"--\n"
"\n"
"Convert the bytes-like object to a value.\n"
"\n"
"If no valid value is found, raise EOFError, ValueError or TypeError. Extra\n"
"bytes in the input are ignored.");
#define MARSHAL_LOADS_METHODDEF \
{"loads", (PyCFunction)marshal_loads, METH_O, marshal_loads__doc__},
static PyObject *
marshal_loads_impl(PyObject *module, Py_buffer *bytes);
static PyObject *
marshal_loads(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
Py_buffer bytes = {NULL, NULL};
if (PyObject_GetBuffer(arg, &bytes, PyBUF_SIMPLE) != 0) {
goto exit;
}
if (!PyBuffer_IsContiguous(&bytes, 'C')) {
_PyArg_BadArgument("loads", "argument", "contiguous buffer", arg);
goto exit;
}
return_value = marshal_loads_impl(module, &bytes);
exit:
/* Cleanup for bytes */
if (bytes.obj) {
PyBuffer_Release(&bytes);
}
return return_value;
}
/*[clinic end generated code: output=a859dabe8b0afeb6 input=a9049054013a1b77]*/

View File

@ -0,0 +1,973 @@
/*[clinic input]
preserve
[clinic start generated code]*/
PyDoc_STRVAR(sys_addaudithook__doc__,
"addaudithook($module, /, hook)\n"
"--\n"
"\n"
"Adds a new audit hook callback.");
#define SYS_ADDAUDITHOOK_METHODDEF \
{"addaudithook", (PyCFunction)(void(*)(void))sys_addaudithook, METH_FASTCALL|METH_KEYWORDS, sys_addaudithook__doc__},
static PyObject *
sys_addaudithook_impl(PyObject *module, PyObject *hook);
static PyObject *
sys_addaudithook(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"hook", NULL};
static _PyArg_Parser _parser = {NULL, _keywords, "addaudithook", 0};
PyObject *argsbuf[1];
PyObject *hook;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
hook = args[0];
return_value = sys_addaudithook_impl(module, hook);
exit:
return return_value;
}
PyDoc_STRVAR(sys_displayhook__doc__,
"displayhook($module, object, /)\n"
"--\n"
"\n"
"Print an object to sys.stdout and also save it in builtins._");
#define SYS_DISPLAYHOOK_METHODDEF \
{"displayhook", (PyCFunction)sys_displayhook, METH_O, sys_displayhook__doc__},
PyDoc_STRVAR(sys_excepthook__doc__,
"excepthook($module, exctype, value, traceback, /)\n"
"--\n"
"\n"
"Handle an exception by displaying it with a traceback on sys.stderr.");
#define SYS_EXCEPTHOOK_METHODDEF \
{"excepthook", (PyCFunction)(void(*)(void))sys_excepthook, METH_FASTCALL, sys_excepthook__doc__},
static PyObject *
sys_excepthook_impl(PyObject *module, PyObject *exctype, PyObject *value,
PyObject *traceback);
static PyObject *
sys_excepthook(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *exctype;
PyObject *value;
PyObject *traceback;
if (!_PyArg_CheckPositional("excepthook", nargs, 3, 3)) {
goto exit;
}
exctype = args[0];
value = args[1];
traceback = args[2];
return_value = sys_excepthook_impl(module, exctype, value, traceback);
exit:
return return_value;
}
PyDoc_STRVAR(sys_exc_info__doc__,
"exc_info($module, /)\n"
"--\n"
"\n"
"Return current exception information: (type, value, traceback).\n"
"\n"
"Return information about the most recent exception caught by an except\n"
"clause in the current stack frame or in an older stack frame.");
#define SYS_EXC_INFO_METHODDEF \
{"exc_info", (PyCFunction)sys_exc_info, METH_NOARGS, sys_exc_info__doc__},
static PyObject *
sys_exc_info_impl(PyObject *module);
static PyObject *
sys_exc_info(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return sys_exc_info_impl(module);
}
PyDoc_STRVAR(sys_unraisablehook__doc__,
"unraisablehook($module, unraisable, /)\n"
"--\n"
"\n"
"Handle an unraisable exception.\n"
"\n"
"The unraisable argument has the following attributes:\n"
"\n"
"* exc_type: Exception type.\n"
"* exc_value: Exception value, can be None.\n"
"* exc_traceback: Exception traceback, can be None.\n"
"* err_msg: Error message, can be None.\n"
"* object: Object causing the exception, can be None.");
#define SYS_UNRAISABLEHOOK_METHODDEF \
{"unraisablehook", (PyCFunction)sys_unraisablehook, METH_O, sys_unraisablehook__doc__},
PyDoc_STRVAR(sys_exit__doc__,
"exit($module, status=None, /)\n"
"--\n"
"\n"
"Exit the interpreter by raising SystemExit(status).\n"
"\n"
"If the status is omitted or None, it defaults to zero (i.e., success).\n"
"If the status is an integer, it will be used as the system exit status.\n"
"If it is another kind of object, it will be printed and the system\n"
"exit status will be one (i.e., failure).");
#define SYS_EXIT_METHODDEF \
{"exit", (PyCFunction)(void(*)(void))sys_exit, METH_FASTCALL, sys_exit__doc__},
static PyObject *
sys_exit_impl(PyObject *module, PyObject *status);
static PyObject *
sys_exit(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *status = Py_None;
if (!_PyArg_CheckPositional("exit", nargs, 0, 1)) {
goto exit;
}
if (nargs < 1) {
goto skip_optional;
}
status = args[0];
skip_optional:
return_value = sys_exit_impl(module, status);
exit:
return return_value;
}
PyDoc_STRVAR(sys_getdefaultencoding__doc__,
"getdefaultencoding($module, /)\n"
"--\n"
"\n"
"Return the current default encoding used by the Unicode implementation.");
#define SYS_GETDEFAULTENCODING_METHODDEF \
{"getdefaultencoding", (PyCFunction)sys_getdefaultencoding, METH_NOARGS, sys_getdefaultencoding__doc__},
static PyObject *
sys_getdefaultencoding_impl(PyObject *module);
static PyObject *
sys_getdefaultencoding(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return sys_getdefaultencoding_impl(module);
}
PyDoc_STRVAR(sys_getfilesystemencoding__doc__,
"getfilesystemencoding($module, /)\n"
"--\n"
"\n"
"Return the encoding used to convert Unicode filenames to OS filenames.");
#define SYS_GETFILESYSTEMENCODING_METHODDEF \
{"getfilesystemencoding", (PyCFunction)sys_getfilesystemencoding, METH_NOARGS, sys_getfilesystemencoding__doc__},
static PyObject *
sys_getfilesystemencoding_impl(PyObject *module);
static PyObject *
sys_getfilesystemencoding(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return sys_getfilesystemencoding_impl(module);
}
PyDoc_STRVAR(sys_getfilesystemencodeerrors__doc__,
"getfilesystemencodeerrors($module, /)\n"
"--\n"
"\n"
"Return the error mode used Unicode to OS filename conversion.");
#define SYS_GETFILESYSTEMENCODEERRORS_METHODDEF \
{"getfilesystemencodeerrors", (PyCFunction)sys_getfilesystemencodeerrors, METH_NOARGS, sys_getfilesystemencodeerrors__doc__},
static PyObject *
sys_getfilesystemencodeerrors_impl(PyObject *module);
static PyObject *
sys_getfilesystemencodeerrors(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return sys_getfilesystemencodeerrors_impl(module);
}
PyDoc_STRVAR(sys_intern__doc__,
"intern($module, string, /)\n"
"--\n"
"\n"
"``Intern\'\' the given string.\n"
"\n"
"This enters the string in the (global) table of interned strings whose\n"
"purpose is to speed up dictionary lookups. Return the string itself or\n"
"the previously interned string object with the same value.");
#define SYS_INTERN_METHODDEF \
{"intern", (PyCFunction)sys_intern, METH_O, sys_intern__doc__},
static PyObject *
sys_intern_impl(PyObject *module, PyObject *s);
static PyObject *
sys_intern(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
PyObject *s;
if (!PyUnicode_Check(arg)) {
_PyArg_BadArgument("intern", "argument", "str", arg);
goto exit;
}
if (PyUnicode_READY(arg) == -1) {
goto exit;
}
s = arg;
return_value = sys_intern_impl(module, s);
exit:
return return_value;
}
PyDoc_STRVAR(sys_gettrace__doc__,
"gettrace($module, /)\n"
"--\n"
"\n"
"Return the global debug tracing function set with sys.settrace.\n"
"\n"
"See the debugger chapter in the library manual.");
#define SYS_GETTRACE_METHODDEF \
{"gettrace", (PyCFunction)sys_gettrace, METH_NOARGS, sys_gettrace__doc__},
static PyObject *
sys_gettrace_impl(PyObject *module);
static PyObject *
sys_gettrace(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return sys_gettrace_impl(module);
}
PyDoc_STRVAR(sys_getprofile__doc__,
"getprofile($module, /)\n"
"--\n"
"\n"
"Return the profiling function set with sys.setprofile.\n"
"\n"
"See the profiler chapter in the library manual.");
#define SYS_GETPROFILE_METHODDEF \
{"getprofile", (PyCFunction)sys_getprofile, METH_NOARGS, sys_getprofile__doc__},
static PyObject *
sys_getprofile_impl(PyObject *module);
static PyObject *
sys_getprofile(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return sys_getprofile_impl(module);
}
PyDoc_STRVAR(sys_setswitchinterval__doc__,
"setswitchinterval($module, interval, /)\n"
"--\n"
"\n"
"Set the ideal thread switching delay inside the Python interpreter.\n"
"\n"
"The actual frequency of switching threads can be lower if the\n"
"interpreter executes long sequences of uninterruptible code\n"
"(this is implementation-specific and workload-dependent).\n"
"\n"
"The parameter must represent the desired switching delay in seconds\n"
"A typical value is 0.005 (5 milliseconds).");
#define SYS_SETSWITCHINTERVAL_METHODDEF \
{"setswitchinterval", (PyCFunction)sys_setswitchinterval, METH_O, sys_setswitchinterval__doc__},
static PyObject *
sys_setswitchinterval_impl(PyObject *module, double interval);
static PyObject *
sys_setswitchinterval(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
double interval;
if (PyFloat_CheckExact(arg)) {
interval = PyFloat_AS_DOUBLE(arg);
}
else
{
interval = PyFloat_AsDouble(arg);
if (interval == -1.0 && PyErr_Occurred()) {
goto exit;
}
}
return_value = sys_setswitchinterval_impl(module, interval);
exit:
return return_value;
}
PyDoc_STRVAR(sys_getswitchinterval__doc__,
"getswitchinterval($module, /)\n"
"--\n"
"\n"
"Return the current thread switch interval; see sys.setswitchinterval().");
#define SYS_GETSWITCHINTERVAL_METHODDEF \
{"getswitchinterval", (PyCFunction)sys_getswitchinterval, METH_NOARGS, sys_getswitchinterval__doc__},
static double
sys_getswitchinterval_impl(PyObject *module);
static PyObject *
sys_getswitchinterval(PyObject *module, PyObject *Py_UNUSED(ignored))
{
PyObject *return_value = NULL;
double _return_value;
_return_value = sys_getswitchinterval_impl(module);
if ((_return_value == -1.0) && PyErr_Occurred()) {
goto exit;
}
return_value = PyFloat_FromDouble(_return_value);
exit:
return return_value;
}
PyDoc_STRVAR(sys_setrecursionlimit__doc__,
"setrecursionlimit($module, limit, /)\n"
"--\n"
"\n"
"Set the maximum depth of the Python interpreter stack to n.\n"
"\n"
"This limit prevents infinite recursion from causing an overflow of the C\n"
"stack and crashing Python. The highest possible limit is platform-\n"
"dependent.");
#define SYS_SETRECURSIONLIMIT_METHODDEF \
{"setrecursionlimit", (PyCFunction)sys_setrecursionlimit, METH_O, sys_setrecursionlimit__doc__},
static PyObject *
sys_setrecursionlimit_impl(PyObject *module, int new_limit);
static PyObject *
sys_setrecursionlimit(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
int new_limit;
if (PyFloat_Check(arg)) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float" );
goto exit;
}
new_limit = _PyLong_AsInt(arg);
if (new_limit == -1 && PyErr_Occurred()) {
goto exit;
}
return_value = sys_setrecursionlimit_impl(module, new_limit);
exit:
return return_value;
}
PyDoc_STRVAR(sys_set_coroutine_origin_tracking_depth__doc__,
"set_coroutine_origin_tracking_depth($module, /, depth)\n"
"--\n"
"\n"
"Enable or disable origin tracking for coroutine objects in this thread.\n"
"\n"
"Coroutine objects will track \'depth\' frames of traceback information\n"
"about where they came from, available in their cr_origin attribute.\n"
"\n"
"Set a depth of 0 to disable.");
#define SYS_SET_COROUTINE_ORIGIN_TRACKING_DEPTH_METHODDEF \
{"set_coroutine_origin_tracking_depth", (PyCFunction)(void(*)(void))sys_set_coroutine_origin_tracking_depth, METH_FASTCALL|METH_KEYWORDS, sys_set_coroutine_origin_tracking_depth__doc__},
static PyObject *
sys_set_coroutine_origin_tracking_depth_impl(PyObject *module, int depth);
static PyObject *
sys_set_coroutine_origin_tracking_depth(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"depth", NULL};
static _PyArg_Parser _parser = {NULL, _keywords, "set_coroutine_origin_tracking_depth", 0};
PyObject *argsbuf[1];
int depth;
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
if (!args) {
goto exit;
}
if (PyFloat_Check(args[0])) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float" );
goto exit;
}
depth = _PyLong_AsInt(args[0]);
if (depth == -1 && PyErr_Occurred()) {
goto exit;
}
return_value = sys_set_coroutine_origin_tracking_depth_impl(module, depth);
exit:
return return_value;
}
PyDoc_STRVAR(sys_get_coroutine_origin_tracking_depth__doc__,
"get_coroutine_origin_tracking_depth($module, /)\n"
"--\n"
"\n"
"Check status of origin tracking for coroutine objects in this thread.");
#define SYS_GET_COROUTINE_ORIGIN_TRACKING_DEPTH_METHODDEF \
{"get_coroutine_origin_tracking_depth", (PyCFunction)sys_get_coroutine_origin_tracking_depth, METH_NOARGS, sys_get_coroutine_origin_tracking_depth__doc__},
static int
sys_get_coroutine_origin_tracking_depth_impl(PyObject *module);
static PyObject *
sys_get_coroutine_origin_tracking_depth(PyObject *module, PyObject *Py_UNUSED(ignored))
{
PyObject *return_value = NULL;
int _return_value;
_return_value = sys_get_coroutine_origin_tracking_depth_impl(module);
if ((_return_value == -1) && PyErr_Occurred()) {
goto exit;
}
return_value = PyLong_FromLong((long)_return_value);
exit:
return return_value;
}
PyDoc_STRVAR(sys_get_asyncgen_hooks__doc__,
"get_asyncgen_hooks($module, /)\n"
"--\n"
"\n"
"Return the installed asynchronous generators hooks.\n"
"\n"
"This returns a namedtuple of the form (firstiter, finalizer).");
#define SYS_GET_ASYNCGEN_HOOKS_METHODDEF \
{"get_asyncgen_hooks", (PyCFunction)sys_get_asyncgen_hooks, METH_NOARGS, sys_get_asyncgen_hooks__doc__},
static PyObject *
sys_get_asyncgen_hooks_impl(PyObject *module);
static PyObject *
sys_get_asyncgen_hooks(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return sys_get_asyncgen_hooks_impl(module);
}
PyDoc_STRVAR(sys_getrecursionlimit__doc__,
"getrecursionlimit($module, /)\n"
"--\n"
"\n"
"Return the current value of the recursion limit.\n"
"\n"
"The recursion limit is the maximum depth of the Python interpreter\n"
"stack. This limit prevents infinite recursion from causing an overflow\n"
"of the C stack and crashing Python.");
#define SYS_GETRECURSIONLIMIT_METHODDEF \
{"getrecursionlimit", (PyCFunction)sys_getrecursionlimit, METH_NOARGS, sys_getrecursionlimit__doc__},
static PyObject *
sys_getrecursionlimit_impl(PyObject *module);
static PyObject *
sys_getrecursionlimit(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return sys_getrecursionlimit_impl(module);
}
#if defined(MS_WINDOWS)
PyDoc_STRVAR(sys_getwindowsversion__doc__,
"getwindowsversion($module, /)\n"
"--\n"
"\n"
"Return info about the running version of Windows as a named tuple.\n"
"\n"
"The members are named: major, minor, build, platform, service_pack,\n"
"service_pack_major, service_pack_minor, suite_mask, product_type and\n"
"platform_version. For backward compatibility, only the first 5 items\n"
"are available by indexing. All elements are numbers, except\n"
"service_pack and platform_type which are strings, and platform_version\n"
"which is a 3-tuple. Platform is always 2. Product_type may be 1 for a\n"
"workstation, 2 for a domain controller, 3 for a server.\n"
"Platform_version is a 3-tuple containing a version number that is\n"
"intended for identifying the OS rather than feature detection.");
#define SYS_GETWINDOWSVERSION_METHODDEF \
{"getwindowsversion", (PyCFunction)sys_getwindowsversion, METH_NOARGS, sys_getwindowsversion__doc__},
static PyObject *
sys_getwindowsversion_impl(PyObject *module);
static PyObject *
sys_getwindowsversion(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return sys_getwindowsversion_impl(module);
}
#endif /* defined(MS_WINDOWS) */
#if defined(MS_WINDOWS)
PyDoc_STRVAR(sys__enablelegacywindowsfsencoding__doc__,
"_enablelegacywindowsfsencoding($module, /)\n"
"--\n"
"\n"
"Changes the default filesystem encoding to mbcs:replace.\n"
"\n"
"This is done for consistency with earlier versions of Python. See PEP\n"
"529 for more information.\n"
"\n"
"This is equivalent to defining the PYTHONLEGACYWINDOWSFSENCODING\n"
"environment variable before launching Python.");
#define SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF \
{"_enablelegacywindowsfsencoding", (PyCFunction)sys__enablelegacywindowsfsencoding, METH_NOARGS, sys__enablelegacywindowsfsencoding__doc__},
static PyObject *
sys__enablelegacywindowsfsencoding_impl(PyObject *module);
static PyObject *
sys__enablelegacywindowsfsencoding(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return sys__enablelegacywindowsfsencoding_impl(module);
}
#endif /* defined(MS_WINDOWS) */
#if defined(HAVE_DLOPEN)
PyDoc_STRVAR(sys_setdlopenflags__doc__,
"setdlopenflags($module, flags, /)\n"
"--\n"
"\n"
"Set the flags used by the interpreter for dlopen calls.\n"
"\n"
"This is used, for example, when the interpreter loads extension\n"
"modules. Among other things, this will enable a lazy resolving of\n"
"symbols when importing a module, if called as sys.setdlopenflags(0).\n"
"To share symbols across extension modules, call as\n"
"sys.setdlopenflags(os.RTLD_GLOBAL). Symbolic names for the flag\n"
"modules can be found in the os module (RTLD_xxx constants, e.g.\n"
"os.RTLD_LAZY).");
#define SYS_SETDLOPENFLAGS_METHODDEF \
{"setdlopenflags", (PyCFunction)sys_setdlopenflags, METH_O, sys_setdlopenflags__doc__},
static PyObject *
sys_setdlopenflags_impl(PyObject *module, int new_val);
static PyObject *
sys_setdlopenflags(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
int new_val;
if (PyFloat_Check(arg)) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float" );
goto exit;
}
new_val = _PyLong_AsInt(arg);
if (new_val == -1 && PyErr_Occurred()) {
goto exit;
}
return_value = sys_setdlopenflags_impl(module, new_val);
exit:
return return_value;
}
#endif /* defined(HAVE_DLOPEN) */
#if defined(HAVE_DLOPEN)
PyDoc_STRVAR(sys_getdlopenflags__doc__,
"getdlopenflags($module, /)\n"
"--\n"
"\n"
"Return the current value of the flags that are used for dlopen calls.\n"
"\n"
"The flag constants are defined in the os module.");
#define SYS_GETDLOPENFLAGS_METHODDEF \
{"getdlopenflags", (PyCFunction)sys_getdlopenflags, METH_NOARGS, sys_getdlopenflags__doc__},
static PyObject *
sys_getdlopenflags_impl(PyObject *module);
static PyObject *
sys_getdlopenflags(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return sys_getdlopenflags_impl(module);
}
#endif /* defined(HAVE_DLOPEN) */
#if defined(USE_MALLOPT)
PyDoc_STRVAR(sys_mdebug__doc__,
"mdebug($module, flag, /)\n"
"--\n"
"\n");
#define SYS_MDEBUG_METHODDEF \
{"mdebug", (PyCFunction)sys_mdebug, METH_O, sys_mdebug__doc__},
static PyObject *
sys_mdebug_impl(PyObject *module, int flag);
static PyObject *
sys_mdebug(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
int flag;
if (PyFloat_Check(arg)) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float" );
goto exit;
}
flag = _PyLong_AsInt(arg);
if (flag == -1 && PyErr_Occurred()) {
goto exit;
}
return_value = sys_mdebug_impl(module, flag);
exit:
return return_value;
}
#endif /* defined(USE_MALLOPT) */
PyDoc_STRVAR(sys_getrefcount__doc__,
"getrefcount($module, object, /)\n"
"--\n"
"\n"
"Return the reference count of object.\n"
"\n"
"The count returned is generally one higher than you might expect,\n"
"because it includes the (temporary) reference as an argument to\n"
"getrefcount().");
#define SYS_GETREFCOUNT_METHODDEF \
{"getrefcount", (PyCFunction)sys_getrefcount, METH_O, sys_getrefcount__doc__},
static Py_ssize_t
sys_getrefcount_impl(PyObject *module, PyObject *object);
static PyObject *
sys_getrefcount(PyObject *module, PyObject *object)
{
PyObject *return_value = NULL;
Py_ssize_t _return_value;
_return_value = sys_getrefcount_impl(module, object);
if ((_return_value == -1) && PyErr_Occurred()) {
goto exit;
}
return_value = PyLong_FromSsize_t(_return_value);
exit:
return return_value;
}
#if defined(Py_REF_DEBUG)
PyDoc_STRVAR(sys_gettotalrefcount__doc__,
"gettotalrefcount($module, /)\n"
"--\n"
"\n");
#define SYS_GETTOTALREFCOUNT_METHODDEF \
{"gettotalrefcount", (PyCFunction)sys_gettotalrefcount, METH_NOARGS, sys_gettotalrefcount__doc__},
static Py_ssize_t
sys_gettotalrefcount_impl(PyObject *module);
static PyObject *
sys_gettotalrefcount(PyObject *module, PyObject *Py_UNUSED(ignored))
{
PyObject *return_value = NULL;
Py_ssize_t _return_value;
_return_value = sys_gettotalrefcount_impl(module);
if ((_return_value == -1) && PyErr_Occurred()) {
goto exit;
}
return_value = PyLong_FromSsize_t(_return_value);
exit:
return return_value;
}
#endif /* defined(Py_REF_DEBUG) */
PyDoc_STRVAR(sys_getallocatedblocks__doc__,
"getallocatedblocks($module, /)\n"
"--\n"
"\n"
"Return the number of memory blocks currently allocated.");
#define SYS_GETALLOCATEDBLOCKS_METHODDEF \
{"getallocatedblocks", (PyCFunction)sys_getallocatedblocks, METH_NOARGS, sys_getallocatedblocks__doc__},
static Py_ssize_t
sys_getallocatedblocks_impl(PyObject *module);
static PyObject *
sys_getallocatedblocks(PyObject *module, PyObject *Py_UNUSED(ignored))
{
PyObject *return_value = NULL;
Py_ssize_t _return_value;
_return_value = sys_getallocatedblocks_impl(module);
if ((_return_value == -1) && PyErr_Occurred()) {
goto exit;
}
return_value = PyLong_FromSsize_t(_return_value);
exit:
return return_value;
}
PyDoc_STRVAR(sys__getframe__doc__,
"_getframe($module, depth=0, /)\n"
"--\n"
"\n"
"Return a frame object from the call stack.\n"
"\n"
"If optional integer depth is given, return the frame object that many\n"
"calls below the top of the stack. If that is deeper than the call\n"
"stack, ValueError is raised. The default for depth is zero, returning\n"
"the frame at the top of the call stack.\n"
"\n"
"This function should be used for internal and specialized purposes\n"
"only.");
#define SYS__GETFRAME_METHODDEF \
{"_getframe", (PyCFunction)(void(*)(void))sys__getframe, METH_FASTCALL, sys__getframe__doc__},
static PyObject *
sys__getframe_impl(PyObject *module, int depth);
static PyObject *
sys__getframe(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
int depth = 0;
if (!_PyArg_CheckPositional("_getframe", nargs, 0, 1)) {
goto exit;
}
if (nargs < 1) {
goto skip_optional;
}
if (PyFloat_Check(args[0])) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float" );
goto exit;
}
depth = _PyLong_AsInt(args[0]);
if (depth == -1 && PyErr_Occurred()) {
goto exit;
}
skip_optional:
return_value = sys__getframe_impl(module, depth);
exit:
return return_value;
}
PyDoc_STRVAR(sys__current_frames__doc__,
"_current_frames($module, /)\n"
"--\n"
"\n"
"Return a dict mapping each thread\'s thread id to its current stack frame.\n"
"\n"
"This function should be used for specialized purposes only.");
#define SYS__CURRENT_FRAMES_METHODDEF \
{"_current_frames", (PyCFunction)sys__current_frames, METH_NOARGS, sys__current_frames__doc__},
static PyObject *
sys__current_frames_impl(PyObject *module);
static PyObject *
sys__current_frames(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return sys__current_frames_impl(module);
}
PyDoc_STRVAR(sys_call_tracing__doc__,
"call_tracing($module, func, args, /)\n"
"--\n"
"\n"
"Call func(*args), while tracing is enabled.\n"
"\n"
"The tracing state is saved, and restored afterwards. This is intended\n"
"to be called from a debugger from a checkpoint, to recursively debug\n"
"some other code.");
#define SYS_CALL_TRACING_METHODDEF \
{"call_tracing", (PyCFunction)(void(*)(void))sys_call_tracing, METH_FASTCALL, sys_call_tracing__doc__},
static PyObject *
sys_call_tracing_impl(PyObject *module, PyObject *func, PyObject *funcargs);
static PyObject *
sys_call_tracing(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
PyObject *func;
PyObject *funcargs;
if (!_PyArg_CheckPositional("call_tracing", nargs, 2, 2)) {
goto exit;
}
func = args[0];
if (!PyTuple_Check(args[1])) {
_PyArg_BadArgument("call_tracing", "argument 2", "tuple", args[1]);
goto exit;
}
funcargs = args[1];
return_value = sys_call_tracing_impl(module, func, funcargs);
exit:
return return_value;
}
PyDoc_STRVAR(sys__debugmallocstats__doc__,
"_debugmallocstats($module, /)\n"
"--\n"
"\n"
"Print summary info to stderr about the state of pymalloc\'s structures.\n"
"\n"
"In Py_DEBUG mode, also perform some expensive internal consistency\n"
"checks.");
#define SYS__DEBUGMALLOCSTATS_METHODDEF \
{"_debugmallocstats", (PyCFunction)sys__debugmallocstats, METH_NOARGS, sys__debugmallocstats__doc__},
static PyObject *
sys__debugmallocstats_impl(PyObject *module);
static PyObject *
sys__debugmallocstats(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return sys__debugmallocstats_impl(module);
}
PyDoc_STRVAR(sys__clear_type_cache__doc__,
"_clear_type_cache($module, /)\n"
"--\n"
"\n"
"Clear the internal type lookup cache.");
#define SYS__CLEAR_TYPE_CACHE_METHODDEF \
{"_clear_type_cache", (PyCFunction)sys__clear_type_cache, METH_NOARGS, sys__clear_type_cache__doc__},
static PyObject *
sys__clear_type_cache_impl(PyObject *module);
static PyObject *
sys__clear_type_cache(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return sys__clear_type_cache_impl(module);
}
PyDoc_STRVAR(sys_is_finalizing__doc__,
"is_finalizing($module, /)\n"
"--\n"
"\n"
"Return True if Python is exiting.");
#define SYS_IS_FINALIZING_METHODDEF \
{"is_finalizing", (PyCFunction)sys_is_finalizing, METH_NOARGS, sys_is_finalizing__doc__},
static PyObject *
sys_is_finalizing_impl(PyObject *module);
static PyObject *
sys_is_finalizing(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return sys_is_finalizing_impl(module);
}
#if defined(ANDROID_API_LEVEL)
PyDoc_STRVAR(sys_getandroidapilevel__doc__,
"getandroidapilevel($module, /)\n"
"--\n"
"\n"
"Return the build time API version of Android as an integer.");
#define SYS_GETANDROIDAPILEVEL_METHODDEF \
{"getandroidapilevel", (PyCFunction)sys_getandroidapilevel, METH_NOARGS, sys_getandroidapilevel__doc__},
static PyObject *
sys_getandroidapilevel_impl(PyObject *module);
static PyObject *
sys_getandroidapilevel(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return sys_getandroidapilevel_impl(module);
}
#endif /* defined(ANDROID_API_LEVEL) */
#ifndef SYS_GETWINDOWSVERSION_METHODDEF
#define SYS_GETWINDOWSVERSION_METHODDEF
#endif /* !defined(SYS_GETWINDOWSVERSION_METHODDEF) */
#ifndef SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF
#define SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF
#endif /* !defined(SYS__ENABLELEGACYWINDOWSFSENCODING_METHODDEF) */
#ifndef SYS_SETDLOPENFLAGS_METHODDEF
#define SYS_SETDLOPENFLAGS_METHODDEF
#endif /* !defined(SYS_SETDLOPENFLAGS_METHODDEF) */
#ifndef SYS_GETDLOPENFLAGS_METHODDEF
#define SYS_GETDLOPENFLAGS_METHODDEF
#endif /* !defined(SYS_GETDLOPENFLAGS_METHODDEF) */
#ifndef SYS_MDEBUG_METHODDEF
#define SYS_MDEBUG_METHODDEF
#endif /* !defined(SYS_MDEBUG_METHODDEF) */
#ifndef SYS_GETTOTALREFCOUNT_METHODDEF
#define SYS_GETTOTALREFCOUNT_METHODDEF
#endif /* !defined(SYS_GETTOTALREFCOUNT_METHODDEF) */
#ifndef SYS_GETANDROIDAPILEVEL_METHODDEF
#define SYS_GETANDROIDAPILEVEL_METHODDEF
#endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */
/*[clinic end generated code: output=39eb34a01fb9a919 input=a9049054013a1b77]*/

View File

@ -0,0 +1,62 @@
/*[clinic input]
preserve
[clinic start generated code]*/
PyDoc_STRVAR(tb_new__doc__,
"TracebackType(tb_next, tb_frame, tb_lasti, tb_lineno)\n"
"--\n"
"\n"
"Create a new traceback object.");
static PyObject *
tb_new_impl(PyTypeObject *type, PyObject *tb_next, PyFrameObject *tb_frame,
int tb_lasti, int tb_lineno);
static PyObject *
tb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"tb_next", "tb_frame", "tb_lasti", "tb_lineno", NULL};
static _PyArg_Parser _parser = {NULL, _keywords, "TracebackType", 0};
PyObject *argsbuf[4];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
PyObject *tb_next;
PyFrameObject *tb_frame;
int tb_lasti;
int tb_lineno;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser, 4, 4, 0, argsbuf);
if (!fastargs) {
goto exit;
}
tb_next = fastargs[0];
if (!PyObject_TypeCheck(fastargs[1], &PyFrame_Type)) {
_PyArg_BadArgument("TracebackType", "argument 'tb_frame'", (&PyFrame_Type)->tp_name, fastargs[1]);
goto exit;
}
tb_frame = (PyFrameObject *)fastargs[1];
if (PyFloat_Check(fastargs[2])) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float" );
goto exit;
}
tb_lasti = _PyLong_AsInt(fastargs[2]);
if (tb_lasti == -1 && PyErr_Occurred()) {
goto exit;
}
if (PyFloat_Check(fastargs[3])) {
PyErr_SetString(PyExc_TypeError,
"integer argument expected, got float" );
goto exit;
}
tb_lineno = _PyLong_AsInt(fastargs[3]);
if (tb_lineno == -1 && PyErr_Occurred()) {
goto exit;
}
return_value = tb_new_impl(type, tb_next, tb_frame, tb_lasti, tb_lineno);
exit:
return return_value;
}
/*[clinic end generated code: output=3def6c06248feed8 input=a9049054013a1b77]*/

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,309 @@
/*
* Portable condition variable support for windows and pthreads.
* Everything is inline, this header can be included where needed.
*
* APIs generally return 0 on success and non-zero on error,
* and the caller needs to use its platform's error mechanism to
* discover the error (errno, or GetLastError())
*
* Note that some implementations cannot distinguish between a
* condition variable wait time-out and successful wait. Most often
* the difference is moot anyway since the wait condition must be
* re-checked.
* PyCOND_TIMEDWAIT, in addition to returning negative on error,
* thus returns 0 on regular success, 1 on timeout
* or 2 if it can't tell.
*
* There are at least two caveats with using these condition variables,
* due to the fact that they may be emulated with Semaphores on
* Windows:
* 1) While PyCOND_SIGNAL() will wake up at least one thread, we
* cannot currently guarantee that it will be one of the threads
* already waiting in a PyCOND_WAIT() call. It _could_ cause
* the wakeup of a subsequent thread to try a PyCOND_WAIT(),
* including the thread doing the PyCOND_SIGNAL() itself.
* The same applies to PyCOND_BROADCAST(), if N threads are waiting
* then at least N threads will be woken up, but not necessarily
* those already waiting.
* For this reason, don't make the scheduling assumption that a
* specific other thread will get the wakeup signal
* 2) The _mutex_ must be held when calling PyCOND_SIGNAL() and
* PyCOND_BROADCAST().
* While e.g. the posix standard strongly recommends that the mutex
* associated with the condition variable is held when a
* pthread_cond_signal() call is made, this is not a hard requirement,
* although scheduling will not be "reliable" if it isn't. Here
* the mutex is used for internal synchronization of the emulated
* Condition Variable.
*/
#ifndef _CONDVAR_IMPL_H_
#define _CONDVAR_IMPL_H_
#include "Python.h"
#include "pycore_condvar.h"
#ifdef _POSIX_THREADS
/*
* POSIX support
*/
/* These private functions are implemented in Python/thread_pthread.h */
int _PyThread_cond_init(PyCOND_T *cond);
void _PyThread_cond_after(long long us, struct timespec *abs);
/* The following functions return 0 on success, nonzero on error */
#define PyMUTEX_INIT(mut) pthread_mutex_init((mut), NULL)
#define PyMUTEX_FINI(mut) pthread_mutex_destroy(mut)
#define PyMUTEX_LOCK(mut) pthread_mutex_lock(mut)
#define PyMUTEX_UNLOCK(mut) pthread_mutex_unlock(mut)
#define PyCOND_INIT(cond) _PyThread_cond_init(cond)
#define PyCOND_FINI(cond) pthread_cond_destroy(cond)
#define PyCOND_SIGNAL(cond) pthread_cond_signal(cond)
#define PyCOND_BROADCAST(cond) pthread_cond_broadcast(cond)
#define PyCOND_WAIT(cond, mut) pthread_cond_wait((cond), (mut))
/* return 0 for success, 1 on timeout, -1 on error */
Py_LOCAL_INLINE(int)
PyCOND_TIMEDWAIT(PyCOND_T *cond, PyMUTEX_T *mut, long long us)
{
struct timespec abs;
_PyThread_cond_after(us, &abs);
int ret = pthread_cond_timedwait(cond, mut, &abs);
if (ret == ETIMEDOUT) {
return 1;
}
if (ret) {
return -1;
}
return 0;
}
#elif defined(NT_THREADS)
/*
* Windows (XP, 2003 server and later, as well as (hopefully) CE) support
*
* Emulated condition variables ones that work with XP and later, plus
* example native support on VISTA and onwards.
*/
#if _PY_EMULATED_WIN_CV
/* The mutex is a CriticalSection object and
The condition variables is emulated with the help of a semaphore.
This implementation still has the problem that the threads woken
with a "signal" aren't necessarily those that are already
waiting. It corresponds to listing 2 in:
http://birrell.org/andrew/papers/ImplementingCVs.pdf
Generic emulations of the pthread_cond_* API using
earlier Win32 functions can be found on the Web.
The following read can be give background information to these issues,
but the implementations are all broken in some way.
http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
*/
Py_LOCAL_INLINE(int)
PyMUTEX_INIT(PyMUTEX_T *cs)
{
InitializeCriticalSection(cs);
return 0;
}
Py_LOCAL_INLINE(int)
PyMUTEX_FINI(PyMUTEX_T *cs)
{
DeleteCriticalSection(cs);
return 0;
}
Py_LOCAL_INLINE(int)
PyMUTEX_LOCK(PyMUTEX_T *cs)
{
EnterCriticalSection(cs);
return 0;
}
Py_LOCAL_INLINE(int)
PyMUTEX_UNLOCK(PyMUTEX_T *cs)
{
LeaveCriticalSection(cs);
return 0;
}
Py_LOCAL_INLINE(int)
PyCOND_INIT(PyCOND_T *cv)
{
/* A semaphore with a "large" max value, The positive value
* is only needed to catch those "lost wakeup" events and
* race conditions when a timed wait elapses.
*/
cv->sem = CreateSemaphore(NULL, 0, 100000, NULL);
if (cv->sem==NULL)
return -1;
cv->waiting = 0;
return 0;
}
Py_LOCAL_INLINE(int)
PyCOND_FINI(PyCOND_T *cv)
{
return CloseHandle(cv->sem) ? 0 : -1;
}
/* this implementation can detect a timeout. Returns 1 on timeout,
* 0 otherwise (and -1 on error)
*/
Py_LOCAL_INLINE(int)
_PyCOND_WAIT_MS(PyCOND_T *cv, PyMUTEX_T *cs, DWORD ms)
{
DWORD wait;
cv->waiting++;
PyMUTEX_UNLOCK(cs);
/* "lost wakeup bug" would occur if the caller were interrupted here,
* but we are safe because we are using a semaphore which has an internal
* count.
*/
wait = WaitForSingleObjectEx(cv->sem, ms, FALSE);
PyMUTEX_LOCK(cs);
if (wait != WAIT_OBJECT_0)
--cv->waiting;
/* Here we have a benign race condition with PyCOND_SIGNAL.
* When failure occurs or timeout, it is possible that
* PyCOND_SIGNAL also decrements this value
* and signals releases the mutex. This is benign because it
* just means an extra spurious wakeup for a waiting thread.
* ('waiting' corresponds to the semaphore's "negative" count and
* we may end up with e.g. (waiting == -1 && sem.count == 1). When
* a new thread comes along, it will pass right through, having
* adjusted it to (waiting == 0 && sem.count == 0).
*/
if (wait == WAIT_FAILED)
return -1;
/* return 0 on success, 1 on timeout */
return wait != WAIT_OBJECT_0;
}
Py_LOCAL_INLINE(int)
PyCOND_WAIT(PyCOND_T *cv, PyMUTEX_T *cs)
{
int result = _PyCOND_WAIT_MS(cv, cs, INFINITE);
return result >= 0 ? 0 : result;
}
Py_LOCAL_INLINE(int)
PyCOND_TIMEDWAIT(PyCOND_T *cv, PyMUTEX_T *cs, long long us)
{
return _PyCOND_WAIT_MS(cv, cs, (DWORD)(us/1000));
}
Py_LOCAL_INLINE(int)
PyCOND_SIGNAL(PyCOND_T *cv)
{
/* this test allows PyCOND_SIGNAL to be a no-op unless required
* to wake someone up, thus preventing an unbounded increase of
* the semaphore's internal counter.
*/
if (cv->waiting > 0) {
/* notifying thread decreases the cv->waiting count so that
* a delay between notify and actual wakeup of the target thread
* doesn't cause a number of extra ReleaseSemaphore calls.
*/
cv->waiting--;
return ReleaseSemaphore(cv->sem, 1, NULL) ? 0 : -1;
}
return 0;
}
Py_LOCAL_INLINE(int)
PyCOND_BROADCAST(PyCOND_T *cv)
{
int waiting = cv->waiting;
if (waiting > 0) {
cv->waiting = 0;
return ReleaseSemaphore(cv->sem, waiting, NULL) ? 0 : -1;
}
return 0;
}
#else /* !_PY_EMULATED_WIN_CV */
Py_LOCAL_INLINE(int)
PyMUTEX_INIT(PyMUTEX_T *cs)
{
InitializeSRWLock(cs);
return 0;
}
Py_LOCAL_INLINE(int)
PyMUTEX_FINI(PyMUTEX_T *cs)
{
return 0;
}
Py_LOCAL_INLINE(int)
PyMUTEX_LOCK(PyMUTEX_T *cs)
{
AcquireSRWLockExclusive(cs);
return 0;
}
Py_LOCAL_INLINE(int)
PyMUTEX_UNLOCK(PyMUTEX_T *cs)
{
ReleaseSRWLockExclusive(cs);
return 0;
}
Py_LOCAL_INLINE(int)
PyCOND_INIT(PyCOND_T *cv)
{
InitializeConditionVariable(cv);
return 0;
}
Py_LOCAL_INLINE(int)
PyCOND_FINI(PyCOND_T *cv)
{
return 0;
}
Py_LOCAL_INLINE(int)
PyCOND_WAIT(PyCOND_T *cv, PyMUTEX_T *cs)
{
return SleepConditionVariableSRW(cv, cs, INFINITE, 0) ? 0 : -1;
}
/* This implementation makes no distinction about timeouts. Signal
* 2 to indicate that we don't know.
*/
Py_LOCAL_INLINE(int)
PyCOND_TIMEDWAIT(PyCOND_T *cv, PyMUTEX_T *cs, long long us)
{
return SleepConditionVariableSRW(cv, cs, (DWORD)(us/1000), 0) ? 2 : -1;
}
Py_LOCAL_INLINE(int)
PyCOND_SIGNAL(PyCOND_T *cv)
{
WakeConditionVariable(cv);
return 0;
}
Py_LOCAL_INLINE(int)
PyCOND_BROADCAST(PyCOND_T *cv)
{
WakeAllConditionVariable(cv);
return 0;
}
#endif /* _PY_EMULATED_WIN_CV */
#endif /* _POSIX_THREADS, NT_THREADS */
#endif /* _CONDVAR_IMPL_H_ */

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,31 @@
/*
* Public domain dup2() lookalike
* by Curtis Jackson @ AT&T Technologies, Burlington, NC
* electronic address: burl!rcj
*
* dup2 performs the following functions:
*
* Check to make sure that fd1 is a valid open file descriptor.
* Check to see if fd2 is already open; if so, close it.
* Duplicate fd1 onto fd2; checking to make sure fd2 is a valid fd.
* Return fd2 if all went well; return BADEXIT otherwise.
*/
#include <fcntl.h>
#include <unistd.h>
#define BADEXIT -1
int
dup2(int fd1, int fd2)
{
if (fd1 != fd2) {
if (fcntl(fd1, F_GETFL) < 0)
return BADEXIT;
if (fcntl(fd2, F_GETFL) >= 0)
close(fd2);
if (fcntl(fd1, F_DUPFD, fd2) < 0)
return BADEXIT;
}
return fd2;
}

View File

@ -0,0 +1,154 @@
/* Copyright (c) 2008-2009, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ---
* Author: Kostya Serebryany
*/
#ifdef _MSC_VER
# include <windows.h>
#endif
#ifdef __cplusplus
# error "This file should be built as pure C to avoid name mangling"
#endif
#include <stdlib.h>
#include <string.h>
#include "dynamic_annotations.h"
/* Each function is empty and called (via a macro) only in debug mode.
The arguments are captured by dynamic tools at runtime. */
#if DYNAMIC_ANNOTATIONS_ENABLED == 1
void AnnotateRWLockCreate(const char *file, int line,
const volatile void *lock){}
void AnnotateRWLockDestroy(const char *file, int line,
const volatile void *lock){}
void AnnotateRWLockAcquired(const char *file, int line,
const volatile void *lock, long is_w){}
void AnnotateRWLockReleased(const char *file, int line,
const volatile void *lock, long is_w){}
void AnnotateBarrierInit(const char *file, int line,
const volatile void *barrier, long count,
long reinitialization_allowed) {}
void AnnotateBarrierWaitBefore(const char *file, int line,
const volatile void *barrier) {}
void AnnotateBarrierWaitAfter(const char *file, int line,
const volatile void *barrier) {}
void AnnotateBarrierDestroy(const char *file, int line,
const volatile void *barrier) {}
void AnnotateCondVarWait(const char *file, int line,
const volatile void *cv,
const volatile void *lock){}
void AnnotateCondVarSignal(const char *file, int line,
const volatile void *cv){}
void AnnotateCondVarSignalAll(const char *file, int line,
const volatile void *cv){}
void AnnotatePublishMemoryRange(const char *file, int line,
const volatile void *address,
long size){}
void AnnotateUnpublishMemoryRange(const char *file, int line,
const volatile void *address,
long size){}
void AnnotatePCQCreate(const char *file, int line,
const volatile void *pcq){}
void AnnotatePCQDestroy(const char *file, int line,
const volatile void *pcq){}
void AnnotatePCQPut(const char *file, int line,
const volatile void *pcq){}
void AnnotatePCQGet(const char *file, int line,
const volatile void *pcq){}
void AnnotateNewMemory(const char *file, int line,
const volatile void *mem,
long size){}
void AnnotateExpectRace(const char *file, int line,
const volatile void *mem,
const char *description){}
void AnnotateBenignRace(const char *file, int line,
const volatile void *mem,
const char *description){}
void AnnotateBenignRaceSized(const char *file, int line,
const volatile void *mem,
long size,
const char *description) {}
void AnnotateMutexIsUsedAsCondVar(const char *file, int line,
const volatile void *mu){}
void AnnotateTraceMemory(const char *file, int line,
const volatile void *arg){}
void AnnotateThreadName(const char *file, int line,
const char *name){}
void AnnotateIgnoreReadsBegin(const char *file, int line){}
void AnnotateIgnoreReadsEnd(const char *file, int line){}
void AnnotateIgnoreWritesBegin(const char *file, int line){}
void AnnotateIgnoreWritesEnd(const char *file, int line){}
void AnnotateIgnoreSyncBegin(const char *file, int line){}
void AnnotateIgnoreSyncEnd(const char *file, int line){}
void AnnotateEnableRaceDetection(const char *file, int line, int enable){}
void AnnotateNoOp(const char *file, int line,
const volatile void *arg){}
void AnnotateFlushState(const char *file, int line){}
static int GetRunningOnValgrind(void) {
#ifdef RUNNING_ON_VALGRIND
if (RUNNING_ON_VALGRIND) return 1;
#endif
#ifndef _MSC_VER
const char *running_on_valgrind_str = getenv("RUNNING_ON_VALGRIND");
if (running_on_valgrind_str) {
return strcmp(running_on_valgrind_str, "0") != 0;
}
#else
/* Visual Studio issues warnings if we use getenv,
* so we use GetEnvironmentVariableA instead.
*/
char value[100] = "1";
int res = GetEnvironmentVariableA("RUNNING_ON_VALGRIND",
value, sizeof(value));
/* value will remain "1" if res == 0 or res >= sizeof(value). The latter
* can happen only if the given value is long, in this case it can't be "0".
*/
if (res > 0 && !strcmp(value, "0"))
return 1;
#endif
return 0;
}
/* See the comments in dynamic_annotations.h */
int RunningOnValgrind(void) {
static volatile int running_on_valgrind = -1;
/* C doesn't have thread-safe initialization of statics, and we
don't want to depend on pthread_once here, so hack it. */
int local_running_on_valgrind = running_on_valgrind;
if (local_running_on_valgrind == -1)
running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind();
return local_running_on_valgrind;
}
#endif /* DYNAMIC_ANNOTATIONS_ENABLED == 1 */

View File

@ -0,0 +1,190 @@
/* Support for dynamic loading of extension modules */
#include "Python.h"
#include "importdl.h"
#include <errno.h> /* for global errno */
#include <string.h> /* for strerror() */
#include <stdlib.h> /* for malloc(), free() */
#include <sys/ldr.h>
#ifdef AIX_GENUINE_CPLUSPLUS
#include <load.h>
#define aix_load loadAndInit
#else
#define aix_load load
#endif
extern char *Py_GetProgramName(void);
typedef struct Module {
struct Module *next;
void *entry;
} Module, *ModulePtr;
const char *_PyImport_DynLoadFiletab[] = {".so", NULL};
static int
aix_getoldmodules(void **modlistptr)
{
ModulePtr modptr, prevmodptr;
struct ld_info *ldiptr;
char *ldibuf;
int errflag, bufsize = 1024;
unsigned int offset;
char *progname = Py_GetProgramName();
/*
-- Get the list of loaded modules into ld_info structures.
*/
if ((ldibuf = malloc(bufsize)) == NULL) {
PyErr_SetString(PyExc_ImportError, strerror(errno));
return -1;
}
while ((errflag = loadquery(L_GETINFO, ldibuf, bufsize)) == -1
&& errno == ENOMEM) {
free(ldibuf);
bufsize += 1024;
if ((ldibuf = malloc(bufsize)) == NULL) {
PyErr_SetString(PyExc_ImportError, strerror(errno));
return -1;
}
}
if (errflag == -1) {
PyErr_SetString(PyExc_ImportError, strerror(errno));
return -1;
}
/*
-- Make the modules list from the ld_info structures.
*/
ldiptr = (struct ld_info *)ldibuf;
prevmodptr = NULL;
do {
if (strstr(progname, ldiptr->ldinfo_filename) == NULL &&
strstr(ldiptr->ldinfo_filename, "python") == NULL) {
/*
-- Extract only the modules belonging to the main
-- executable + those containing "python" as a
-- substring (like the "python[version]" binary or
-- "libpython[version].a" in case it's a shared lib).
*/
offset = (unsigned int)ldiptr->ldinfo_next;
ldiptr = (struct ld_info *)((char*)ldiptr + offset);
continue;
}
if ((modptr = (ModulePtr)malloc(sizeof(Module))) == NULL) {
PyErr_SetString(PyExc_ImportError, strerror(errno));
while (*modlistptr) {
modptr = (ModulePtr)*modlistptr;
*modlistptr = (void *)modptr->next;
free(modptr);
}
return -1;
}
modptr->entry = ldiptr->ldinfo_dataorg;
modptr->next = NULL;
if (prevmodptr == NULL)
*modlistptr = (void *)modptr;
else
prevmodptr->next = modptr;
prevmodptr = modptr;
offset = (unsigned int)ldiptr->ldinfo_next;
ldiptr = (struct ld_info *)((char*)ldiptr + offset);
} while (offset);
free(ldibuf);
return 0;
}
static void
aix_loaderror(const char *pathname)
{
char *message[1024], errbuf[1024];
PyObject *pathname_ob = NULL;
PyObject *errbuf_ob = NULL;
int i,j;
struct errtab {
int errNo;
char *errstr;
} load_errtab[] = {
{L_ERROR_TOOMANY, "too many errors, rest skipped."},
{L_ERROR_NOLIB, "can't load library:"},
{L_ERROR_UNDEF, "can't find symbol in library:"},
{L_ERROR_RLDBAD,
"RLD index out of range or bad relocation type:"},
{L_ERROR_FORMAT, "not a valid, executable xcoff file:"},
{L_ERROR_MEMBER,
"file not an archive or does not contain requested member:"},
{L_ERROR_TYPE, "symbol table mismatch:"},
{L_ERROR_ALIGN, "text alignment in file is wrong."},
{L_ERROR_SYSTEM, "System error:"},
{L_ERROR_ERRNO, NULL}
};
#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
PyOS_snprintf(errbuf, sizeof(errbuf), "from module %.200s ", pathname);
if (!loadquery(L_GETMESSAGES, &message[0], sizeof(message))) {
ERRBUF_APPEND(strerror(errno));
ERRBUF_APPEND("\n");
}
for(i = 0; message[i] && *message[i]; i++) {
int nerr = atoi(message[i]);
for (j=0; j < Py_ARRAY_LENGTH(load_errtab); j++) {
if (nerr == load_errtab[j].errNo && load_errtab[j].errstr)
ERRBUF_APPEND(load_errtab[j].errstr);
}
while (Py_ISDIGIT(*message[i])) message[i]++ ;
ERRBUF_APPEND(message[i]);
ERRBUF_APPEND("\n");
}
/* Subtract 1 from the length to trim off trailing newline */
errbuf_ob = PyUnicode_DecodeLocaleAndSize(errbuf, strlen(errbuf)-1, "surrogateescape");
if (errbuf_ob == NULL)
return;
pathname_ob = PyUnicode_DecodeFSDefault(pathname);
if (pathname_ob == NULL) {
Py_DECREF(errbuf_ob);
return;
}
PyErr_SetImportError(errbuf_ob, NULL, pathname_ob);
Py_DECREF(pathname_ob);
Py_DECREF(errbuf_ob);
return;
}
dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix,
const char *shortname,
const char *pathname, FILE *fp)
{
dl_funcptr p;
/*
-- Invoke load() with L_NOAUTODEFER leaving the imported symbols
-- of the shared module unresolved. Thus we have to resolve them
-- explicitly with loadbind. The new module is loaded, then we
-- resolve its symbols using the list of already loaded modules
-- (only those that belong to the python executable). Get these
-- with loadquery(L_GETINFO).
*/
static void *staticmodlistptr = NULL;
if (!staticmodlistptr)
if (aix_getoldmodules(&staticmodlistptr) == -1)
return NULL;
p = (dl_funcptr) aix_load((char *)pathname, L_NOAUTODEFER, 0);
if (p == NULL) {
aix_loaderror(pathname);
return NULL;
}
return p;
}

View File

@ -0,0 +1,23 @@
/* Support for dynamic loading of extension modules */
#include "dl.h"
#include "Python.h"
#include "importdl.h"
extern char *Py_GetProgramName(void);
const char *_PyImport_DynLoadFiletab[] = {".o", NULL};
dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix,
const char *shortname,
const char *pathname, FILE *fp)
{
char funcname[258];
PyOS_snprintf(funcname, sizeof(funcname), "%.20s_%.200s", prefix, shortname);
return dl_loadmod(Py_GetProgramName(), pathname, funcname);
}

View File

@ -0,0 +1,76 @@
/* Support for dynamic loading of extension modules */
#include "dl.h"
#include <errno.h>
#include "Python.h"
#include "importdl.h"
#if defined(__hp9000s300)
#define FUNCNAME_PATTERN "_%.20s_%.200s"
#else
#define FUNCNAME_PATTERN "%.20s_%.200s"
#endif
const char *_PyImport_DynLoadFiletab[] = {SHLIB_EXT, NULL};
dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix,
const char *shortname,
const char *pathname, FILE *fp)
{
int flags = BIND_FIRST | BIND_DEFERRED;
int verbose = _Py_GetConfig()->verbose;
if (verbose) {
flags = BIND_FIRST | BIND_IMMEDIATE |
BIND_NONFATAL | BIND_VERBOSE;
printf("shl_load %s\n",pathname);
}
shl_t lib = shl_load(pathname, flags, 0);
/* XXX Chuck Blake once wrote that 0 should be BIND_NOSTART? */
if (lib == NULL) {
if (verbose) {
perror(pathname);
}
char buf[256];
PyOS_snprintf(buf, sizeof(buf), "Failed to load %.200s",
pathname);
PyObject *buf_ob = PyUnicode_DecodeFSDefault(buf);
if (buf_ob == NULL)
return NULL;
PyObject *shortname_ob = PyUnicode_FromString(shortname);
if (shortname_ob == NULL) {
Py_DECREF(buf_ob);
return NULL;
}
PyObject *pathname_ob = PyUnicode_DecodeFSDefault(pathname);
if (pathname_ob == NULL) {
Py_DECREF(buf_ob);
Py_DECREF(shortname_ob);
return NULL;
}
PyErr_SetImportError(buf_ob, shortname_ob, pathname_ob);
Py_DECREF(buf_ob);
Py_DECREF(shortname_ob);
Py_DECREF(pathname_ob);
return NULL;
}
char funcname[258];
PyOS_snprintf(funcname, sizeof(funcname), FUNCNAME_PATTERN,
prefix, shortname);
if (verbose) {
printf("shl_findsym %s\n", funcname);
}
dl_funcptr p;
if (shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p) == -1) {
shl_unload(lib);
p = NULL;
}
if (p == NULL && verbose) {
perror(funcname);
}
return p;
}

View File

@ -0,0 +1,133 @@
/* Support for dynamic loading of extension modules */
#include "Python.h"
#include "pycore_interp.h" // _PyInterpreterState.dlopenflags
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "importdl.h"
#include <sys/types.h>
#include <sys/stat.h>
#if defined(__NetBSD__)
#include <sys/param.h>
#if (NetBSD < 199712)
#include <nlist.h>
#include <link.h>
#define dlerror() "error in dynamic linking"
#endif
#endif /* NetBSD */
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
#if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__)
#define LEAD_UNDERSCORE "_"
#else
#define LEAD_UNDERSCORE ""
#endif
/* The .so extension module ABI tag, supplied by the Makefile via
Makefile.pre.in and configure. This is used to discriminate between
incompatible .so files so that extensions for different Python builds can
live in the same directory. E.g. foomodule.cpython-32.so
*/
const char *_PyImport_DynLoadFiletab[] = {
#ifdef __CYGWIN__
".dll",
#else /* !__CYGWIN__ */
"." SOABI ".so",
#ifdef ALT_SOABI
"." ALT_SOABI ".so",
#endif
".abi" PYTHON_ABI_STRING ".so",
".so",
#endif /* __CYGWIN__ */
NULL,
};
static struct {
dev_t dev;
ino_t ino;
void *handle;
} handles[128];
static int nhandles = 0;
dl_funcptr
_PyImport_FindSharedFuncptr(const char *prefix,
const char *shortname,
const char *pathname, FILE *fp)
{
dl_funcptr p;
void *handle;
char funcname[258];
char pathbuf[260];
int dlopenflags=0;
if (strchr(pathname, '/') == NULL) {
/* Prefix bare filename with "./" */
PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
pathname = pathbuf;
}
PyOS_snprintf(funcname, sizeof(funcname),
LEAD_UNDERSCORE "%.20s_%.200s", prefix, shortname);
if (fp != NULL) {
int i;
struct _Py_stat_struct status;
if (_Py_fstat(fileno(fp), &status) == -1)
return NULL;
for (i = 0; i < nhandles; i++) {
if (status.st_dev == handles[i].dev &&
status.st_ino == handles[i].ino) {
p = (dl_funcptr) dlsym(handles[i].handle,
funcname);
return p;
}
}
if (nhandles < 128) {
handles[nhandles].dev = status.st_dev;
handles[nhandles].ino = status.st_ino;
}
}
dlopenflags = _PyInterpreterState_GET()->dlopenflags;
handle = dlopen(pathname, dlopenflags);
if (handle == NULL) {
PyObject *mod_name;
PyObject *path;
PyObject *error_ob;
const char *error = dlerror();
if (error == NULL)
error = "unknown dlopen() error";
error_ob = PyUnicode_DecodeLocale(error, "surrogateescape");
if (error_ob == NULL)
return NULL;
mod_name = PyUnicode_FromString(shortname);
if (mod_name == NULL) {
Py_DECREF(error_ob);
return NULL;
}
path = PyUnicode_DecodeFSDefault(pathname);
if (path == NULL) {
Py_DECREF(error_ob);
Py_DECREF(mod_name);
return NULL;
}
PyErr_SetImportError(error_ob, mod_name, path);
Py_DECREF(error_ob);
Py_DECREF(mod_name);
Py_DECREF(path);
return NULL;
}
if (fp != NULL && nhandles < 128)
handles[nhandles++].handle = handle;
p = (dl_funcptr) dlsym(handle, funcname);
return p;
}

View File

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

View File

@ -0,0 +1,285 @@
/* Support for dynamic loading of extension modules */
#include "Python.h"
#ifdef HAVE_DIRECT_H
#include <direct.h>
#endif
#include <ctype.h>
#include "importdl.h"
#include "patchlevel.h"
#include <windows.h>
#ifdef _DEBUG
#define PYD_DEBUG_SUFFIX "_d"
#else
#define PYD_DEBUG_SUFFIX ""
#endif
#ifdef PYD_PLATFORM_TAG
#define PYD_TAGGED_SUFFIX PYD_DEBUG_SUFFIX ".cp" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) "-" PYD_PLATFORM_TAG ".pyd"
#else
#define PYD_TAGGED_SUFFIX PYD_DEBUG_SUFFIX ".cp" Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION) ".pyd"
#endif
#define PYD_UNTAGGED_SUFFIX PYD_DEBUG_SUFFIX ".pyd"
const char *_PyImport_DynLoadFiletab[] = {
PYD_TAGGED_SUFFIX,
PYD_UNTAGGED_SUFFIX,
NULL
};
/* Function to return the name of the "python" DLL that the supplied module
directly imports. Looks through the list of imported modules and
returns the first entry that starts with "python" (case sensitive) and
is followed by nothing but numbers until the separator (period).
Returns a pointer to the import name, or NULL if no matching name was
located.
This function parses through the PE header for the module as loaded in
memory by the system loader. The PE header is accessed as documented by
Microsoft in the MSDN PE and COFF specification (2/99), and handles
both PE32 and PE32+. It only worries about the direct import table and
not the delay load import table since it's unlikely an extension is
going to be delay loading Python (after all, it's already loaded).
If any magic values are not found (e.g., the PE header or optional
header magic), then this function simply returns NULL. */
#define DWORD_AT(mem) (*(DWORD *)(mem))
#define WORD_AT(mem) (*(WORD *)(mem))
static char *GetPythonImport (HINSTANCE hModule)
{
unsigned char *dllbase, *import_data, *import_name;
DWORD pe_offset, opt_offset;
WORD opt_magic;
int num_dict_off, import_off;
/* Safety check input */
if (hModule == NULL) {
return NULL;
}
/* Module instance is also the base load address. First portion of
memory is the MS-DOS loader, which holds the offset to the PE
header (from the load base) at 0x3C */
dllbase = (unsigned char *)hModule;
pe_offset = DWORD_AT(dllbase + 0x3C);
/* The PE signature must be "PE\0\0" */
if (memcmp(dllbase+pe_offset,"PE\0\0",4)) {
return NULL;
}
/* Following the PE signature is the standard COFF header (20
bytes) and then the optional header. The optional header starts
with a magic value of 0x10B for PE32 or 0x20B for PE32+ (PE32+
uses 64-bits for some fields). It might also be 0x107 for a ROM
image, but we don't process that here.
The optional header ends with a data dictionary that directly
points to certain types of data, among them the import entries
(in the second table entry). Based on the header type, we
determine offsets for the data dictionary count and the entry
within the dictionary pointing to the imports. */
opt_offset = pe_offset + 4 + 20;
opt_magic = WORD_AT(dllbase+opt_offset);
if (opt_magic == 0x10B) {
/* PE32 */
num_dict_off = 92;
import_off = 104;
} else if (opt_magic == 0x20B) {
/* PE32+ */
num_dict_off = 108;
import_off = 120;
} else {
/* Unsupported */
return NULL;
}
/* Now if an import table exists, offset to it and walk the list of
imports. The import table is an array (ending when an entry has
empty values) of structures (20 bytes each), which contains (at
offset 12) a relative address (to the module base) at which a
string constant holding the import name is located. */
if (DWORD_AT(dllbase + opt_offset + num_dict_off) >= 2) {
/* We have at least 2 tables - the import table is the second
one. But still it may be that the table size is zero */
if (0 == DWORD_AT(dllbase + opt_offset + import_off + sizeof(DWORD)))
return NULL;
import_data = dllbase + DWORD_AT(dllbase +
opt_offset +
import_off);
while (DWORD_AT(import_data)) {
import_name = dllbase + DWORD_AT(import_data+12);
if (strlen(import_name) >= 6 &&
!strncmp(import_name,"python",6)) {
char *pch;
#ifndef _DEBUG
/* In a release version, don't claim that python3.dll is
a Python DLL. */
if (strcmp(import_name, "python3.dll") == 0) {
import_data += 20;
continue;
}
#endif
/* Ensure python prefix is followed only
by numbers to the end of the basename */
pch = import_name + 6;
#ifdef _DEBUG
while (*pch && pch[0] != '_' && pch[1] != 'd' && pch[2] != '.') {
#else
while (*pch && *pch != '.') {
#endif
if (*pch >= '0' && *pch <= '9') {
pch++;
} else {
pch = NULL;
break;
}
}
if (pch) {
/* Found it - return the name */
return import_name;
}
}
import_data += 20;
}
}
return NULL;
}
dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
const char *shortname,
PyObject *pathname, FILE *fp)
{
dl_funcptr p;
char funcname[258], *import_python;
const wchar_t *wpathname;
_Py_CheckPython3();
_Py_COMP_DIAG_PUSH
_Py_COMP_DIAG_IGNORE_DEPR_DECLS
wpathname = _PyUnicode_AsUnicode(pathname);
_Py_COMP_DIAG_POP
if (wpathname == NULL)
return NULL;
PyOS_snprintf(funcname, sizeof(funcname), "%.20s_%.200s", prefix, shortname);
{
HINSTANCE hDLL = NULL;
unsigned int old_mode;
/* Don't display a message box when Python can't load a DLL */
old_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
/* bpo-36085: We use LoadLibraryEx with restricted search paths
to avoid DLL preloading attacks and enable use of the
AddDllDirectory function. We add SEARCH_DLL_LOAD_DIR to
ensure DLLs adjacent to the PYD are preferred. */
Py_BEGIN_ALLOW_THREADS
hDLL = LoadLibraryExW(wpathname, NULL,
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS |
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
Py_END_ALLOW_THREADS
/* restore old error mode settings */
SetErrorMode(old_mode);
if (hDLL==NULL){
PyObject *message;
unsigned int errorCode;
/* Get an error string from Win32 error code */
wchar_t theInfo[256]; /* Pointer to error text
from system */
int theLength; /* Length of error text */
errorCode = GetLastError();
theLength = FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, /* flags */
NULL, /* message source */
errorCode, /* the message (error) ID */
MAKELANGID(LANG_NEUTRAL,
SUBLANG_DEFAULT),
/* Default language */
theInfo, /* the buffer */
sizeof(theInfo) / sizeof(wchar_t), /* size in wchars */
NULL); /* no additional format args. */
/* Problem: could not get the error message.
This should not happen if called correctly. */
if (theLength == 0) {
message = PyUnicode_FromFormat(
"DLL load failed with error code %u while importing %s",
errorCode, shortname);
} else {
/* For some reason a \r\n
is appended to the text */
if (theLength >= 2 &&
theInfo[theLength-2] == '\r' &&
theInfo[theLength-1] == '\n') {
theLength -= 2;
theInfo[theLength] = '\0';
}
message = PyUnicode_FromFormat(
"DLL load failed while importing %s: ", shortname);
PyUnicode_AppendAndDel(&message,
PyUnicode_FromWideChar(
theInfo,
theLength));
}
if (message != NULL) {
PyObject *shortname_obj = PyUnicode_FromString(shortname);
PyErr_SetImportError(message, shortname_obj, pathname);
Py_XDECREF(shortname_obj);
Py_DECREF(message);
}
return NULL;
} else {
char buffer[256];
PyOS_snprintf(buffer, sizeof(buffer),
#ifdef _DEBUG
"python%d%d_d.dll",
#else
"python%d%d.dll",
#endif
PY_MAJOR_VERSION,PY_MINOR_VERSION);
import_python = GetPythonImport(hDLL);
if (import_python &&
_stricmp(buffer,import_python)) {
PyErr_Format(PyExc_ImportError,
"Module use of %.150s conflicts "
"with this version of Python.",
import_python);
Py_BEGIN_ALLOW_THREADS
FreeLibrary(hDLL);
Py_END_ALLOW_THREADS
return NULL;
}
}
Py_BEGIN_ALLOW_THREADS
p = GetProcAddress(hDLL, funcname);
Py_END_ALLOW_THREADS
}
return p;
}

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,50 @@
/* Dummy frozen modules initializer */
#include "Python.h"
#include "importlib.h"
#include "importlib_external.h"
#include "importlib_zipimport.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 flag.py file; then copy and paste
the appropriate bytes from M___main__.c. */
static unsigned char M___hello__[] = {
227,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,2,0,0,0,64,0,0,0,115,16,0,0,0,100,0,
90,0,101,1,100,1,131,1,1,0,100,2,83,0,41,3,
84,122,12,72,101,108,108,111,32,119,111,114,108,100,33,78,
41,2,218,11,105,110,105,116,105,97,108,105,122,101,100,218,
5,112,114,105,110,116,169,0,114,3,0,0,0,114,3,0,
0,0,250,20,84,111,111,108,115,47,102,114,101,101,122,101,
47,102,108,97,103,46,112,121,218,8,60,109,111,100,117,108,
101,62,1,0,0,0,115,2,0,0,0,4,1,
};
#define SIZE (int)sizeof(M___hello__)
static const struct _frozen _PyImport_FrozenModules[] = {
/* importlib */
{"_frozen_importlib", _Py_M__importlib_bootstrap,
(int)sizeof(_Py_M__importlib_bootstrap)},
{"_frozen_importlib_external", _Py_M__importlib_bootstrap_external,
(int)sizeof(_Py_M__importlib_bootstrap_external)},
{"zipimport", _Py_M__zipimport,
(int)sizeof(_Py_M__zipimport)},
/* 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: */
const struct _frozen *PyImport_FrozenModules = _PyImport_FrozenModules;

View File

@ -0,0 +1,129 @@
/* Python interpreter main program for frozen scripts */
#include "Python.h"
#include "pycore_runtime.h" // _PyRuntime_Initialize()
#include <locale.h>
#ifdef MS_WINDOWS
extern void PyWinFreeze_ExeInit(void);
extern void PyWinFreeze_ExeTerm(void);
extern int PyInitFrozenExtensions(void);
#endif
/* Main program */
int
Py_FrozenMain(int argc, char **argv)
{
PyStatus status = _PyRuntime_Initialize();
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
const char *p;
int i, n, sts = 1;
int inspect = 0;
int unbuffered = 0;
char *oldloc = NULL;
wchar_t **argv_copy = NULL;
/* We need a second copies, as Python might modify the first one. */
wchar_t **argv_copy2 = NULL;
if (argc > 0) {
argv_copy = PyMem_RawMalloc(sizeof(wchar_t*) * argc);
argv_copy2 = PyMem_RawMalloc(sizeof(wchar_t*) * argc);
if (!argv_copy || !argv_copy2) {
fprintf(stderr, "out of memory\n");
goto error;
}
}
PyConfig config;
PyConfig_InitPythonConfig(&config);
config.pathconfig_warnings = 0; /* Suppress errors from getpath.c */
if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
inspect = 1;
if ((p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
unbuffered = 1;
if (unbuffered) {
setbuf(stdin, (char *)NULL);
setbuf(stdout, (char *)NULL);
setbuf(stderr, (char *)NULL);
}
oldloc = _PyMem_RawStrdup(setlocale(LC_ALL, NULL));
if (!oldloc) {
fprintf(stderr, "out of memory\n");
goto error;
}
setlocale(LC_ALL, "");
for (i = 0; i < argc; i++) {
argv_copy[i] = Py_DecodeLocale(argv[i], NULL);
argv_copy2[i] = argv_copy[i];
if (!argv_copy[i]) {
fprintf(stderr, "Unable to decode the command line argument #%i\n",
i + 1);
argc = i;
goto error;
}
}
setlocale(LC_ALL, oldloc);
PyMem_RawFree(oldloc);
oldloc = NULL;
#ifdef MS_WINDOWS
PyInitFrozenExtensions();
#endif /* MS_WINDOWS */
if (argc >= 1)
Py_SetProgramName(argv_copy[0]);
status = Py_InitializeFromConfig(&config);
PyConfig_Clear(&config);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}
#ifdef MS_WINDOWS
PyWinFreeze_ExeInit();
#endif
if (Py_VerboseFlag)
fprintf(stderr, "Python %s\n%s\n",
Py_GetVersion(), Py_GetCopyright());
PySys_SetArgv(argc, argv_copy);
n = PyImport_ImportFrozenModule("__main__");
if (n == 0)
Py_FatalError("the __main__ module is not frozen");
if (n < 0) {
PyErr_Print();
sts = 1;
}
else
sts = 0;
if (inspect && isatty((int)fileno(stdin)))
sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
#ifdef MS_WINDOWS
PyWinFreeze_ExeTerm();
#endif
if (Py_FinalizeEx() < 0) {
sts = 120;
}
error:
PyMem_RawFree(argv_copy);
if (argv_copy2) {
for (i = 0; i < argc; i++)
PyMem_RawFree(argv_copy2[i]);
PyMem_RawFree(argv_copy2);
}
PyMem_RawFree(oldloc);
return sts;
}

View File

@ -0,0 +1,158 @@
#include "Python.h"
#include "Python-ast.h"
#include "node.h"
#include "token.h"
#include "graminit.h"
#include "code.h"
#include "symtable.h"
#include "ast.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, PyObject *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 = PyUnicode_AsUTF8(name->name);
if (!feature)
return 0;
if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
continue;
} else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
continue;
} else if (strcmp(feature, FUTURE_DIVISION) == 0) {
continue;
} else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
continue;
} else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
continue;
} else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {
continue;
} else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
continue;
} else if (strcmp(feature, FUTURE_BARRY_AS_BDFL) == 0) {
ff->ff_features |= CO_FUTURE_BARRY_AS_BDFL;
} else if (strcmp(feature, FUTURE_GENERATOR_STOP) == 0) {
continue;
} else if (strcmp(feature, FUTURE_ANNOTATIONS) == 0) {
ff->ff_features |= CO_FUTURE_ANNOTATIONS;
} else if (strcmp(feature, "braces") == 0) {
PyErr_SetString(PyExc_SyntaxError,
"not a chance");
PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset + 1);
return 0;
} else {
PyErr_Format(PyExc_SyntaxError,
UNDEFINED_FUTURE_FEATURE, feature);
PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset + 1);
return 0;
}
}
return 1;
}
static int
future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
{
int i, done = 0, prev_line = 0;
if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
return 1;
if (asdl_seq_LEN(mod->v.Module.body) == 0)
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.
*/
i = 0;
if (_PyAST_GetDocString(mod->v.Module.body) != NULL)
i++;
for (; 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 &&
_PyUnicode_EqualToASCIIString(modname, "__future__")) {
if (done) {
PyErr_SetString(PyExc_SyntaxError,
ERR_LATE_FUTURE);
PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
return 0;
}
if (!future_check_features(ff, s, filename))
return 0;
ff->ff_lineno = s->lineno;
}
else {
done = 1;
}
}
else {
done = 1;
}
}
return 1;
}
PyFutureFeatures *
PyFuture_FromASTObject(mod_ty mod, PyObject *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;
}
PyFutureFeatures *
PyFuture_FromAST(mod_ty mod, const char *filename_str)
{
PyFutureFeatures *ff;
PyObject *filename;
filename = PyUnicode_DecodeFSDefault(filename_str);
if (filename == NULL)
return NULL;
ff = PyFuture_FromASTObject(mod, filename);
Py_DECREF(filename);
return ff;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
/* Return the compiler identification, if possible. */
#include "Python.h"
#ifndef COMPILER
// Note the __clang__ conditional has to come before the __GNUC__ one because
// clang pretends to be GCC.
#if defined(__clang__)
#define COMPILER "\n[Clang " __clang_version__ "]"
#elif defined(__GNUC__)
#define COMPILER "\n[GCC " __VERSION__ "]"
// Generic fallbacks.
#elif defined(__cplusplus)
#define COMPILER "[C++]"
#else
#define COMPILER "[C]"
#endif
#endif /* !COMPILER */
const char *
Py_GetCompiler(void)
{
return COMPILER;
}

View File

@ -0,0 +1,23 @@
/* Return the copyright string. This is updated manually. */
#include "Python.h"
static const char cprt[] =
"\
Copyright (c) 2001-2021 Python Software Foundation.\n\
All Rights Reserved.\n\
\n\
Copyright (c) 2000 BeOpen.com.\n\
All Rights Reserved.\n\
\n\
Copyright (c) 1995-2001 Corporation for National Research Initiatives.\n\
All Rights Reserved.\n\
\n\
Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.\n\
All Rights Reserved.";
const char *
Py_GetCopyright(void)
{
return cprt;
}

View File

@ -0,0 +1,175 @@
/*---------------------------------------------------------------------------*
* <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.
*---------------------------------------------------------------------------*/
/* Modified to support --help and --version, as well as /? on Windows
* by Georg Brandl. */
#include <Python.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include "pycore_getopt.h"
#ifdef __cplusplus
extern "C" {
#endif
int _PyOS_opterr = 1; /* generate error messages */
Py_ssize_t _PyOS_optind = 1; /* index into argv array */
const wchar_t *_PyOS_optarg = NULL; /* optional argument */
static const wchar_t *opt_ptr = L"";
/* Python command line short and long options */
#define SHORT_OPTS L"bBc:dEhiIJm:OqRsStuvVW:xX:?"
static const _PyOS_LongOption longopts[] = {
{L"check-hash-based-pycs", 1, 0},
{NULL, 0, 0},
};
void _PyOS_ResetGetOpt(void)
{
_PyOS_opterr = 1;
_PyOS_optind = 1;
_PyOS_optarg = NULL;
opt_ptr = L"";
}
int _PyOS_GetOpt(Py_ssize_t argc, wchar_t * const *argv, int *longindex)
{
wchar_t *ptr;
wchar_t option;
if (*opt_ptr == '\0') {
if (_PyOS_optind >= argc)
return -1;
#ifdef MS_WINDOWS
else if (wcscmp(argv[_PyOS_optind], L"/?") == 0) {
++_PyOS_optind;
return 'h';
}
#endif
else if (argv[_PyOS_optind][0] != L'-' ||
argv[_PyOS_optind][1] == L'\0' /* lone dash */ )
return -1;
else if (wcscmp(argv[_PyOS_optind], L"--") == 0) {
++_PyOS_optind;
return -1;
}
else if (wcscmp(argv[_PyOS_optind], L"--help") == 0) {
++_PyOS_optind;
return 'h';
}
else if (wcscmp(argv[_PyOS_optind], L"--version") == 0) {
++_PyOS_optind;
return 'V';
}
opt_ptr = &argv[_PyOS_optind++][1];
}
if ((option = *opt_ptr++) == L'\0')
return -1;
if (option == L'-') {
// Parse long option.
if (*opt_ptr == L'\0') {
if (_PyOS_opterr) {
fprintf(stderr, "expected long option\n");
}
return -1;
}
*longindex = 0;
const _PyOS_LongOption *opt;
for (opt = &longopts[*longindex]; opt->name; opt = &longopts[++(*longindex)]) {
if (!wcscmp(opt->name, opt_ptr))
break;
}
if (!opt->name) {
if (_PyOS_opterr) {
fprintf(stderr, "unknown option %ls\n", argv[_PyOS_optind - 1]);
}
return '_';
}
opt_ptr = L"";
if (!opt->has_arg) {
return opt->val;
}
if (_PyOS_optind >= argc) {
if (_PyOS_opterr) {
fprintf(stderr, "Argument expected for the %ls options\n",
argv[_PyOS_optind - 1]);
}
return '_';
}
_PyOS_optarg = argv[_PyOS_optind++];
return opt->val;
}
if (option == 'J') {
if (_PyOS_opterr) {
fprintf(stderr, "-J is reserved for Jython\n");
}
return '_';
}
if ((ptr = wcschr(SHORT_OPTS, option)) == NULL) {
if (_PyOS_opterr) {
fprintf(stderr, "Unknown option: -%c\n", (char)option);
}
return '_';
}
if (*(ptr + 1) == L':') {
if (*opt_ptr != L'\0') {
_PyOS_optarg = opt_ptr;
opt_ptr = L"";
}
else {
if (_PyOS_optind >= argc) {
if (_PyOS_opterr) {
fprintf(stderr,
"Argument expected for the -%c option\n", (char)option);
}
return '_';
}
_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,417 @@
/* The implementation of the hash table (_Py_hashtable_t) is based on the
cfuhash project:
http://sourceforge.net/projects/libcfu/
Copyright of cfuhash:
----------------------------------
Creation date: 2005-06-24 21:22:40
Authors: Don
Change log:
Copyright (c) 2005 Don Owens
All rights reserved.
This code is released under the BSD license:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------
*/
#include "Python.h"
#include "pycore_hashtable.h"
#define HASHTABLE_MIN_SIZE 16
#define HASHTABLE_HIGH 0.50
#define HASHTABLE_LOW 0.10
#define HASHTABLE_REHASH_FACTOR 2.0 / (HASHTABLE_LOW + HASHTABLE_HIGH)
#define BUCKETS_HEAD(SLIST) \
((_Py_hashtable_entry_t *)_Py_SLIST_HEAD(&(SLIST)))
#define TABLE_HEAD(HT, BUCKET) \
((_Py_hashtable_entry_t *)_Py_SLIST_HEAD(&(HT)->buckets[BUCKET]))
#define ENTRY_NEXT(ENTRY) \
((_Py_hashtable_entry_t *)_Py_SLIST_ITEM_NEXT(ENTRY))
/* Forward declaration */
static int hashtable_rehash(_Py_hashtable_t *ht);
static void
_Py_slist_init(_Py_slist_t *list)
{
list->head = NULL;
}
static void
_Py_slist_prepend(_Py_slist_t *list, _Py_slist_item_t *item)
{
item->next = list->head;
list->head = item;
}
static void
_Py_slist_remove(_Py_slist_t *list, _Py_slist_item_t *previous,
_Py_slist_item_t *item)
{
if (previous != NULL)
previous->next = item->next;
else
list->head = item->next;
}
Py_uhash_t
_Py_hashtable_hash_ptr(const void *key)
{
return (Py_uhash_t)_Py_HashPointerRaw(key);
}
int
_Py_hashtable_compare_direct(const void *key1, const void *key2)
{
return (key1 == key2);
}
/* makes sure the real size of the buckets array is a power of 2 */
static size_t
round_size(size_t s)
{
size_t i;
if (s < HASHTABLE_MIN_SIZE)
return HASHTABLE_MIN_SIZE;
i = 1;
while (i < s)
i <<= 1;
return i;
}
size_t
_Py_hashtable_size(const _Py_hashtable_t *ht)
{
size_t size = sizeof(_Py_hashtable_t);
/* buckets */
size += ht->nbuckets * sizeof(_Py_hashtable_entry_t *);
/* entries */
size += ht->nentries * sizeof(_Py_hashtable_entry_t);
return size;
}
_Py_hashtable_entry_t *
_Py_hashtable_get_entry_generic(_Py_hashtable_t *ht, const void *key)
{
Py_uhash_t key_hash = ht->hash_func(key);
size_t index = key_hash & (ht->nbuckets - 1);
_Py_hashtable_entry_t *entry = TABLE_HEAD(ht, index);
while (1) {
if (entry == NULL) {
return NULL;
}
if (entry->key_hash == key_hash && ht->compare_func(key, entry->key)) {
break;
}
entry = ENTRY_NEXT(entry);
}
return entry;
}
// Specialized for:
// hash_func == _Py_hashtable_hash_ptr
// compare_func == _Py_hashtable_compare_direct
static _Py_hashtable_entry_t *
_Py_hashtable_get_entry_ptr(_Py_hashtable_t *ht, const void *key)
{
Py_uhash_t key_hash = _Py_hashtable_hash_ptr(key);
size_t index = key_hash & (ht->nbuckets - 1);
_Py_hashtable_entry_t *entry = TABLE_HEAD(ht, index);
while (1) {
if (entry == NULL) {
return NULL;
}
// Compare directly keys (ignore entry->key_hash)
if (entry->key == key) {
break;
}
entry = ENTRY_NEXT(entry);
}
return entry;
}
void*
_Py_hashtable_steal(_Py_hashtable_t *ht, const void *key)
{
Py_uhash_t key_hash = ht->hash_func(key);
size_t index = key_hash & (ht->nbuckets - 1);
_Py_hashtable_entry_t *entry = TABLE_HEAD(ht, index);
_Py_hashtable_entry_t *previous = NULL;
while (1) {
if (entry == NULL) {
// not found
return NULL;
}
if (entry->key_hash == key_hash && ht->compare_func(key, entry->key)) {
break;
}
previous = entry;
entry = ENTRY_NEXT(entry);
}
_Py_slist_remove(&ht->buckets[index], (_Py_slist_item_t *)previous,
(_Py_slist_item_t *)entry);
ht->nentries--;
void *value = entry->value;
ht->alloc.free(entry);
if ((float)ht->nentries / (float)ht->nbuckets < HASHTABLE_LOW) {
// Ignore failure: error cannot be reported to the caller
hashtable_rehash(ht);
}
return value;
}
int
_Py_hashtable_set(_Py_hashtable_t *ht, const void *key, void *value)
{
_Py_hashtable_entry_t *entry;
#ifndef NDEBUG
/* Don't write the assertion on a single line because it is interesting
to know the duplicated entry if the assertion failed. The entry can
be read using a debugger. */
entry = ht->get_entry_func(ht, key);
assert(entry == NULL);
#endif
entry = ht->alloc.malloc(sizeof(_Py_hashtable_entry_t));
if (entry == NULL) {
/* memory allocation failed */
return -1;
}
entry->key_hash = ht->hash_func(key);
entry->key = (void *)key;
entry->value = value;
ht->nentries++;
if ((float)ht->nentries / (float)ht->nbuckets > HASHTABLE_HIGH) {
if (hashtable_rehash(ht) < 0) {
ht->nentries--;
ht->alloc.free(entry);
return -1;
}
}
size_t index = entry->key_hash & (ht->nbuckets - 1);
_Py_slist_prepend(&ht->buckets[index], (_Py_slist_item_t*)entry);
return 0;
}
void*
_Py_hashtable_get(_Py_hashtable_t *ht, const void *key)
{
_Py_hashtable_entry_t *entry = ht->get_entry_func(ht, key);
if (entry != NULL) {
return entry->value;
}
else {
return NULL;
}
}
int
_Py_hashtable_foreach(_Py_hashtable_t *ht,
_Py_hashtable_foreach_func func,
void *user_data)
{
for (size_t hv = 0; hv < ht->nbuckets; hv++) {
_Py_hashtable_entry_t *entry = TABLE_HEAD(ht, hv);
while (entry != NULL) {
int res = func(ht, entry->key, entry->value, user_data);
if (res) {
return res;
}
entry = ENTRY_NEXT(entry);
}
}
return 0;
}
static int
hashtable_rehash(_Py_hashtable_t *ht)
{
size_t new_size = round_size((size_t)(ht->nentries * HASHTABLE_REHASH_FACTOR));
if (new_size == ht->nbuckets) {
return 0;
}
size_t buckets_size = new_size * sizeof(ht->buckets[0]);
_Py_slist_t *new_buckets = ht->alloc.malloc(buckets_size);
if (new_buckets == NULL) {
/* memory allocation failed */
return -1;
}
memset(new_buckets, 0, buckets_size);
for (size_t bucket = 0; bucket < ht->nbuckets; bucket++) {
_Py_hashtable_entry_t *entry = BUCKETS_HEAD(ht->buckets[bucket]);
while (entry != NULL) {
assert(ht->hash_func(entry->key) == entry->key_hash);
_Py_hashtable_entry_t *next = ENTRY_NEXT(entry);
size_t entry_index = entry->key_hash & (new_size - 1);
_Py_slist_prepend(&new_buckets[entry_index], (_Py_slist_item_t*)entry);
entry = next;
}
}
ht->alloc.free(ht->buckets);
ht->nbuckets = new_size;
ht->buckets = new_buckets;
return 0;
}
_Py_hashtable_t *
_Py_hashtable_new_full(_Py_hashtable_hash_func hash_func,
_Py_hashtable_compare_func compare_func,
_Py_hashtable_destroy_func key_destroy_func,
_Py_hashtable_destroy_func value_destroy_func,
_Py_hashtable_allocator_t *allocator)
{
_Py_hashtable_allocator_t alloc;
if (allocator == NULL) {
alloc.malloc = PyMem_Malloc;
alloc.free = PyMem_Free;
}
else {
alloc = *allocator;
}
_Py_hashtable_t *ht = (_Py_hashtable_t *)alloc.malloc(sizeof(_Py_hashtable_t));
if (ht == NULL) {
return ht;
}
ht->nbuckets = HASHTABLE_MIN_SIZE;
ht->nentries = 0;
size_t buckets_size = ht->nbuckets * sizeof(ht->buckets[0]);
ht->buckets = alloc.malloc(buckets_size);
if (ht->buckets == NULL) {
alloc.free(ht);
return NULL;
}
memset(ht->buckets, 0, buckets_size);
ht->get_entry_func = _Py_hashtable_get_entry_generic;
ht->hash_func = hash_func;
ht->compare_func = compare_func;
ht->key_destroy_func = key_destroy_func;
ht->value_destroy_func = value_destroy_func;
ht->alloc = alloc;
if (ht->hash_func == _Py_hashtable_hash_ptr
&& ht->compare_func == _Py_hashtable_compare_direct)
{
ht->get_entry_func = _Py_hashtable_get_entry_ptr;
}
return ht;
}
_Py_hashtable_t *
_Py_hashtable_new(_Py_hashtable_hash_func hash_func,
_Py_hashtable_compare_func compare_func)
{
return _Py_hashtable_new_full(hash_func, compare_func,
NULL, NULL, NULL);
}
static void
_Py_hashtable_destroy_entry(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry)
{
if (ht->key_destroy_func) {
ht->key_destroy_func(entry->key);
}
if (ht->value_destroy_func) {
ht->value_destroy_func(entry->value);
}
ht->alloc.free(entry);
}
void
_Py_hashtable_clear(_Py_hashtable_t *ht)
{
for (size_t i=0; i < ht->nbuckets; i++) {
_Py_hashtable_entry_t *entry = TABLE_HEAD(ht, i);
while (entry != NULL) {
_Py_hashtable_entry_t *next = ENTRY_NEXT(entry);
_Py_hashtable_destroy_entry(ht, entry);
entry = next;
}
_Py_slist_init(&ht->buckets[i]);
}
ht->nentries = 0;
// Ignore failure: clear function is not expected to fail
// because of a memory allocation failure.
(void)hashtable_rehash(ht);
}
void
_Py_hashtable_destroy(_Py_hashtable_t *ht)
{
for (size_t i = 0; i < ht->nbuckets; i++) {
_Py_hashtable_entry_t *entry = TABLE_HEAD(ht, i);
while (entry) {
_Py_hashtable_entry_t *entry_next = ENTRY_NEXT(entry);
_Py_hashtable_destroy_entry(ht, entry);
entry = entry_next;
}
}
ht->alloc.free(ht->buckets);
ht->alloc.free(ht);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,246 @@
/* 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"
#ifdef MS_WINDOWS
extern dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
const char *shortname,
PyObject *pathname,
FILE *fp);
#else
extern dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix,
const char *shortname,
const char *pathname, FILE *fp);
#endif
static const char * const ascii_only_prefix = "PyInit";
static const char * const nonascii_prefix = "PyInitU";
/* Get the variable part of a module's export symbol name.
* Returns a bytes instance. For non-ASCII-named modules, the name is
* encoded as per PEP 489.
* The hook_prefix pointer is set to either ascii_only_prefix or
* nonascii_prefix, as appropriate.
*/
static PyObject *
get_encoded_name(PyObject *name, const char **hook_prefix) {
PyObject *tmp;
PyObject *encoded = NULL;
PyObject *modname = NULL;
Py_ssize_t name_len, lastdot;
_Py_IDENTIFIER(replace);
/* Get the short name (substring after last dot) */
name_len = PyUnicode_GetLength(name);
lastdot = PyUnicode_FindChar(name, '.', 0, name_len, -1);
if (lastdot < -1) {
return NULL;
} else if (lastdot >= 0) {
tmp = PyUnicode_Substring(name, lastdot + 1, name_len);
if (tmp == NULL)
return NULL;
name = tmp;
/* "name" now holds a new reference to the substring */
} else {
Py_INCREF(name);
}
/* Encode to ASCII or Punycode, as needed */
encoded = PyUnicode_AsEncodedString(name, "ascii", NULL);
if (encoded != NULL) {
*hook_prefix = ascii_only_prefix;
} else {
if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) {
PyErr_Clear();
encoded = PyUnicode_AsEncodedString(name, "punycode", NULL);
if (encoded == NULL) {
goto error;
}
*hook_prefix = nonascii_prefix;
} else {
goto error;
}
}
/* Replace '-' by '_' */
modname = _PyObject_CallMethodId(encoded, &PyId_replace, "cc", '-', '_');
if (modname == NULL)
goto error;
Py_DECREF(name);
Py_DECREF(encoded);
return modname;
error:
Py_DECREF(name);
Py_XDECREF(encoded);
return NULL;
}
PyObject *
_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp)
{
#ifndef MS_WINDOWS
PyObject *pathbytes = NULL;
#endif
PyObject *name_unicode = NULL, *name = NULL, *path = NULL, *m = NULL;
const char *name_buf, *hook_prefix;
const char *oldcontext;
dl_funcptr exportfunc;
PyModuleDef *def;
PyObject *(*p0)(void);
name_unicode = PyObject_GetAttrString(spec, "name");
if (name_unicode == NULL) {
return NULL;
}
if (!PyUnicode_Check(name_unicode)) {
PyErr_SetString(PyExc_TypeError,
"spec.name must be a string");
goto error;
}
name = get_encoded_name(name_unicode, &hook_prefix);
if (name == NULL) {
goto error;
}
name_buf = PyBytes_AS_STRING(name);
path = PyObject_GetAttrString(spec, "origin");
if (path == NULL)
goto error;
if (PySys_Audit("import", "OOOOO", name_unicode, path,
Py_None, Py_None, Py_None) < 0) {
return NULL;
}
#ifdef MS_WINDOWS
exportfunc = _PyImport_FindSharedFuncptrWindows(hook_prefix, name_buf,
path, fp);
#else
pathbytes = PyUnicode_EncodeFSDefault(path);
if (pathbytes == NULL)
goto error;
exportfunc = _PyImport_FindSharedFuncptr(hook_prefix, name_buf,
PyBytes_AS_STRING(pathbytes),
fp);
Py_DECREF(pathbytes);
#endif
if (exportfunc == NULL) {
if (!PyErr_Occurred()) {
PyObject *msg;
msg = PyUnicode_FromFormat(
"dynamic module does not define "
"module export function (%s_%s)",
hook_prefix, name_buf);
if (msg == NULL)
goto error;
PyErr_SetImportError(msg, name_unicode, path);
Py_DECREF(msg);
}
goto error;
}
p0 = (PyObject *(*)(void))exportfunc;
/* Package context is needed for single-phase init */
oldcontext = _Py_PackageContext;
_Py_PackageContext = PyUnicode_AsUTF8(name_unicode);
if (_Py_PackageContext == NULL) {
_Py_PackageContext = oldcontext;
goto error;
}
m = p0();
_Py_PackageContext = oldcontext;
if (m == NULL) {
if (!PyErr_Occurred()) {
PyErr_Format(
PyExc_SystemError,
"initialization of %s failed without raising an exception",
name_buf);
}
goto error;
} else if (PyErr_Occurred()) {
PyErr_Clear();
PyErr_Format(
PyExc_SystemError,
"initialization of %s raised unreported exception",
name_buf);
m = NULL;
goto error;
}
if (Py_IS_TYPE(m, NULL)) {
/* This can happen when a PyModuleDef is returned without calling
* PyModuleDef_Init on it
*/
PyErr_Format(PyExc_SystemError,
"init function of %s returned uninitialized object",
name_buf);
m = NULL; /* prevent segfault in DECREF */
goto error;
}
if (PyObject_TypeCheck(m, &PyModuleDef_Type)) {
Py_DECREF(name_unicode);
Py_DECREF(name);
Py_DECREF(path);
return PyModule_FromDefAndSpec((PyModuleDef*)m, spec);
}
/* Fall back to single-phase init mechanism */
if (hook_prefix == nonascii_prefix) {
/* don't allow legacy init for non-ASCII module names */
PyErr_Format(
PyExc_SystemError,
"initialization of * did not return PyModuleDef",
name_buf);
goto error;
}
/* Remember pointer to module init function. */
def = PyModule_GetDef(m);
if (def == NULL) {
PyErr_Format(PyExc_SystemError,
"initialization of %s did not return an extension "
"module", name_buf);
goto error;
}
def->m_base.m_init = p0;
/* Remember the filename as the __file__ attribute */
if (PyModule_AddObject(m, "__file__", path) < 0)
PyErr_Clear(); /* Not important enough to report */
else
Py_INCREF(path);
PyObject *modules = PyImport_GetModuleDict();
if (_PyImport_FixupExtensionObject(m, name_unicode, path, modules) < 0)
goto error;
Py_DECREF(name_unicode);
Py_DECREF(name);
Py_DECREF(path);
return m;
error:
Py_DECREF(name_unicode);
Py_XDECREF(name);
Py_XDECREF(path);
Py_XDECREF(m);
return NULL;
}
#endif /* HAVE_DYNAMIC_LOADING */

View File

@ -0,0 +1,27 @@
#ifndef Py_IMPORTDL_H
#define Py_IMPORTDL_H
#ifdef __cplusplus
extern "C" {
#endif
extern const char *_PyImport_DynLoadFiletab[];
extern PyObject *_PyImport_LoadDynamicModuleWithSpec(PyObject *spec, 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
typedef void (*dl_funcptr)(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* !Py_IMPORTDL_H */

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
#! /usr/bin/env python
"""Generate C code for the jump table of the threaded code interpreter
(for compilers supporting computed gotos or "labels-as-values", such as gcc).
"""
import os
import sys
try:
from importlib.machinery import SourceFileLoader
except ImportError:
import imp
def find_module(modname):
"""Finds and returns a module in the local dist/checkout.
"""
modpath = os.path.join(
os.path.dirname(os.path.dirname(__file__)), "Lib")
return imp.load_module(modname, *imp.find_module(modname, [modpath]))
else:
def find_module(modname):
"""Finds and returns a module in the local dist/checkout.
"""
modpath = os.path.join(
os.path.dirname(os.path.dirname(__file__)), "Lib", modname + ".py")
return SourceFileLoader(modname, modpath).load_module()
def write_contents(f):
"""Write C code contents to the target file object.
"""
opcode = find_module('opcode')
targets = ['_unknown_opcode'] * 256
for opname, op in opcode.opmap.items():
targets[op] = "TARGET_%s" % opname
f.write("static void *opcode_targets[256] = {\n")
f.write(",\n".join([" &&%s" % s for s in targets]))
f.write("\n};\n")
def main():
if len(sys.argv) >= 3:
sys.exit("Too many arguments")
if len(sys.argv) == 2:
target = sys.argv[1]
else:
target = "Python/opcode_targets.h"
with open(target, "w") as f:
write_contents(f)
print("Jump table written into %s" % target)
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,703 @@
/* Module support implementation */
#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#define FLAG_SIZE_T 1
typedef double va_double;
static PyObject *va_build_value(const char *, va_list, int);
static PyObject **va_build_stack(PyObject **small_stack, Py_ssize_t small_stack_len, const char *, va_list, int, Py_ssize_t*);
/* Package context -- the full module name for package imports */
const char *_Py_PackageContext = NULL;
int
_Py_convert_optional_to_ssize_t(PyObject *obj, void *result)
{
Py_ssize_t limit;
if (obj == Py_None) {
return 1;
}
else if (_PyIndex_Check(obj)) {
limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError);
if (limit == -1 && PyErr_Occurred()) {
return 0;
}
}
else {
PyErr_Format(PyExc_TypeError,
"argument should be integer or None, not '%.200s'",
Py_TYPE(obj)->tp_name);
return 0;
}
*((Py_ssize_t *)result) = limit;
return 1;
}
/* Helper for mkvalue() to scan the length of a format */
static Py_ssize_t
countformat(const char *format, char endchar)
{
Py_ssize_t 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 *, char, Py_ssize_t, int);
static int do_mkstack(PyObject **, const char**, va_list *, char, Py_ssize_t, int);
static PyObject *do_mklist(const char**, va_list *, char, Py_ssize_t, int);
static PyObject *do_mkdict(const char**, va_list *, char, Py_ssize_t, int);
static PyObject *do_mkvalue(const char**, va_list *, int);
static void
do_ignore(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int flags)
{
PyObject *v;
Py_ssize_t i;
assert(PyErr_Occurred());
v = PyTuple_New(n);
for (i = 0; i < n; i++) {
PyObject *exception, *value, *tb, *w;
PyErr_Fetch(&exception, &value, &tb);
w = do_mkvalue(p_format, p_va, flags);
PyErr_Restore(exception, value, tb);
if (w != NULL) {
if (v != NULL) {
PyTuple_SET_ITEM(v, i, w);
}
else {
Py_DECREF(w);
}
}
}
Py_XDECREF(v);
if (**p_format != endchar) {
PyErr_SetString(PyExc_SystemError,
"Unmatched paren in format");
return;
}
if (endchar) {
++*p_format;
}
}
static PyObject *
do_mkdict(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int flags)
{
PyObject *d;
Py_ssize_t i;
if (n < 0)
return NULL;
if (n % 2) {
PyErr_SetString(PyExc_SystemError,
"Bad dict format");
do_ignore(p_format, p_va, endchar, n, flags);
return NULL;
}
/* Note that we can't bail immediately on error as this will leak
refcounts on any 'N' arguments. */
if ((d = PyDict_New()) == NULL) {
do_ignore(p_format, p_va, endchar, n, flags);
return NULL;
}
for (i = 0; i < n; i+= 2) {
PyObject *k, *v;
k = do_mkvalue(p_format, p_va, flags);
if (k == NULL) {
do_ignore(p_format, p_va, endchar, n - i - 1, flags);
Py_DECREF(d);
return NULL;
}
v = do_mkvalue(p_format, p_va, flags);
if (v == NULL || PyDict_SetItem(d, k, v) < 0) {
do_ignore(p_format, p_va, endchar, n - i - 2, flags);
Py_DECREF(k);
Py_XDECREF(v);
Py_DECREF(d);
return NULL;
}
Py_DECREF(k);
Py_DECREF(v);
}
if (**p_format != endchar) {
Py_DECREF(d);
PyErr_SetString(PyExc_SystemError,
"Unmatched paren in format");
return NULL;
}
if (endchar)
++*p_format;
return d;
}
static PyObject *
do_mklist(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int flags)
{
PyObject *v;
Py_ssize_t i;
if (n < 0)
return NULL;
/* Note that we can't bail immediately on error as this will leak
refcounts on any 'N' arguments. */
v = PyList_New(n);
if (v == NULL) {
do_ignore(p_format, p_va, endchar, n, flags);
return NULL;
}
for (i = 0; i < n; i++) {
PyObject *w = do_mkvalue(p_format, p_va, flags);
if (w == NULL) {
do_ignore(p_format, p_va, endchar, n - i - 1, flags);
Py_DECREF(v);
return NULL;
}
PyList_SET_ITEM(v, i, w);
}
if (**p_format != endchar) {
Py_DECREF(v);
PyErr_SetString(PyExc_SystemError,
"Unmatched paren in format");
return NULL;
}
if (endchar)
++*p_format;
return v;
}
static int
do_mkstack(PyObject **stack, const char **p_format, va_list *p_va,
char endchar, Py_ssize_t n, int flags)
{
Py_ssize_t i;
if (n < 0) {
return -1;
}
/* 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) {
do_ignore(p_format, p_va, endchar, n - i - 1, flags);
goto error;
}
stack[i] = w;
}
if (**p_format != endchar) {
PyErr_SetString(PyExc_SystemError,
"Unmatched paren in format");
goto error;
}
if (endchar) {
++*p_format;
}
return 0;
error:
n = i;
for (i=0; i < n; i++) {
Py_DECREF(stack[i]);
}
return -1;
}
static PyObject *
do_mktuple(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int flags)
{
PyObject *v;
Py_ssize_t i;
if (n < 0)
return NULL;
/* Note that we can't bail immediately on error as this will leak
refcounts on any 'N' arguments. */
if ((v = PyTuple_New(n)) == NULL) {
do_ignore(p_format, p_va, endchar, n, flags);
return NULL;
}
for (i = 0; i < n; i++) {
PyObject *w = do_mkvalue(p_format, p_va, flags);
if (w == NULL) {
do_ignore(p_format, p_va, endchar, n - i - 1, flags);
Py_DECREF(v);
return NULL;
}
PyTuple_SET_ITEM(v, i, w);
}
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 PyLong_FromLong((long)va_arg(*p_va, int));
case 'H':
return PyLong_FromLong((long)va_arg(*p_va, unsigned int));
case 'I':
{
unsigned int n;
n = va_arg(*p_va, unsigned int);
return PyLong_FromUnsignedLong(n);
}
case 'n':
#if SIZEOF_SIZE_T!=SIZEOF_LONG
return PyLong_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 PyLong_FromLong(va_arg(*p_va, long));
case 'k':
{
unsigned long n;
n = va_arg(*p_va, unsigned long);
return PyLong_FromUnsignedLong(n);
}
case 'L':
return PyLong_FromLongLong((long long)va_arg(*p_va, long long));
case 'K':
return PyLong_FromUnsignedLongLong((long long)va_arg(*p_va, unsigned long long));
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);
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) {
return NULL;
}
}
}
else
n = -1;
if (u == NULL) {
v = Py_None;
Py_INCREF(v);
}
else {
if (n < 0)
n = wcslen(u);
v = PyUnicode_FromWideChar(u, n);
}
return v;
}
case 'f':
case 'd':
return PyFloat_FromDouble(
(double)va_arg(*p_va, va_double));
case 'D':
return PyComplex_FromCComplex(
*((Py_complex *)va_arg(*p_va, Py_complex *)));
case 'c':
{
char p[1];
p[0] = (char)va_arg(*p_va, int);
return PyBytes_FromStringAndSize(p, 1);
}
case 'C':
{
int i = va_arg(*p_va, int);
return PyUnicode_FromOrdinal(i);
}
case 's':
case 'z':
case 'U': /* XXX deprecated alias */
{
PyObject *v;
const char *str = va_arg(*p_va, const 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);
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) {
return NULL;
}
}
}
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 = PyUnicode_FromStringAndSize(str, n);
}
return v;
}
case 'y':
{
PyObject *v;
const char *str = va_arg(*p_va, const 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);
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) {
return NULL;
}
}
}
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 bytes");
return NULL;
}
n = (Py_ssize_t)m;
}
v = PyBytes_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;
Py_ssize_t n = countformat(f, '\0');
va_list lva;
PyObject *retval;
if (n < 0)
return NULL;
if (n == 0) {
Py_RETURN_NONE;
}
va_copy(lva, va);
if (n == 1) {
retval = do_mkvalue(&f, &lva, flags);
} else {
retval = do_mktuple(&f, &lva, '\0', n, flags);
}
va_end(lva);
return retval;
}
PyObject **
_Py_VaBuildStack(PyObject **small_stack, Py_ssize_t small_stack_len,
const char *format, va_list va, Py_ssize_t *p_nargs)
{
return va_build_stack(small_stack, small_stack_len, format, va, 0, p_nargs);
}
PyObject **
_Py_VaBuildStack_SizeT(PyObject **small_stack, Py_ssize_t small_stack_len,
const char *format, va_list va, Py_ssize_t *p_nargs)
{
return va_build_stack(small_stack, small_stack_len, format, va, FLAG_SIZE_T, p_nargs);
}
static PyObject **
va_build_stack(PyObject **small_stack, Py_ssize_t small_stack_len,
const char *format, va_list va, int flags, Py_ssize_t *p_nargs)
{
const char *f;
Py_ssize_t n;
va_list lva;
PyObject **stack;
int res;
n = countformat(format, '\0');
if (n < 0) {
*p_nargs = 0;
return NULL;
}
if (n == 0) {
*p_nargs = 0;
return small_stack;
}
if (n <= small_stack_len) {
stack = small_stack;
}
else {
stack = PyMem_Malloc(n * sizeof(stack[0]));
if (stack == NULL) {
PyErr_NoMemory();
return NULL;
}
}
va_copy(lva, va);
f = format;
res = do_mkstack(stack, &f, &lva, '\0', n, flags);
va_end(lva);
if (res < 0) {
if (stack != small_stack) {
PyMem_Free(stack);
}
return NULL;
}
*p_nargs = n;
return stack;
}
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 = PyLong_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 = PyUnicode_FromString(value);
if (!o)
return -1;
if (PyModule_AddObject(m, name, o) == 0)
return 0;
Py_DECREF(o);
return -1;
}
int
PyModule_AddType(PyObject *module, PyTypeObject *type)
{
if (PyType_Ready(type) < 0) {
return -1;
}
const char *name = _PyType_Name(type);
assert(name != NULL);
Py_INCREF(type);
if (PyModule_AddObject(module, name, (PyObject *)type) < 0) {
Py_DECREF(type);
return -1;
}
return 0;
}

View File

@ -0,0 +1,111 @@
#include "Python.h"
/* snprintf() and vsnprintf() 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)
{
assert(str != NULL);
assert(size > 0);
assert(format != NULL);
int len; /* # bytes written, excluding \0 */
#if defined(_MSC_VER) || defined(HAVE_SNPRINTF)
# define _PyOS_vsnprintf_EXTRA_SPACE 1
#else
# define _PyOS_vsnprintf_EXTRA_SPACE 512
char *buffer;
#endif
/* 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;
}
#if defined(_MSC_VER)
len = _vsnprintf(str, size, format, va);
#elif defined(HAVE_SNPRINTF)
len = vsnprintf(str, size, format, va);
#else
/* Emulate vsnprintf(). */
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_FatalErrorFunc(__func__, "Buffer overflow");
}
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,291 @@
#include "Python.h"
#if defined(__sgi) && !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 const 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 const 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 const 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 0b, 0o or 0x to tell which
** base. If these are absent it defaults to 10.
** Base must be 0 or between 2 and 36 (inclusive).
** If 'ptr' is non-NULL it will contain a pointer to
** the end of the scan.
** Errors due to bad pointers will probably result in
** exceptions - we don't check for them.
*/
unsigned long
PyOS_strtoul(const char *str, char **ptr, int base)
{
unsigned long result = 0; /* return value of the function */
int c; /* current input character */
int ovlimit; /* required digits to overflow */
/* skip leading white space */
while (*str && Py_ISSPACE(*str))
++str;
/* check for leading 0b, 0o or 0x for auto-base or base 16 */
switch (base) {
case 0: /* look for leading 0b, 0o or 0x */
if (*str == '0') {
++str;
if (*str == 'x' || *str == 'X') {
/* there must be at least one digit after 0x */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
if (ptr)
*ptr = (char *)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 = (char *)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 = (char *)str;
return 0;
}
++str;
base = 2;
} else {
/* skip all zeroes... */
while (*str == '0')
++str;
while (Py_ISSPACE(*str))
++str;
if (ptr)
*ptr = (char *)str;
return 0;
}
}
else
base = 10;
break;
/* even with explicit base, skip leading 0? prefix */
case 16:
if (*str == '0') {
++str;
if (*str == 'x' || *str == 'X') {
/* there must be at least one digit after 0x */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
if (ptr)
*ptr = (char *)str;
return 0;
}
++str;
}
}
break;
case 8:
if (*str == '0') {
++str;
if (*str == 'o' || *str == 'O') {
/* there must be at least one digit after 0o */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
if (ptr)
*ptr = (char *)str;
return 0;
}
++str;
}
}
break;
case 2:
if(*str == '0') {
++str;
if (*str == 'b' || *str == 'B') {
/* there must be at least one digit after 0b */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
if (ptr)
*ptr = (char *)str;
return 0;
}
++str;
}
}
break;
}
/* catch silly bases */
if (base < 2 || base > 36) {
if (ptr)
*ptr = (char *)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 */
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 = (char *)str;
return result;
overflowed:
if (ptr) {
/* spool through remaining digit characters */
while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base)
++str;
*ptr = (char *)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(const char *str, char **ptr, int base)
{
long result;
unsigned long uresult;
char sign;
while (*str && Py_ISSPACE(*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,258 @@
static void *opcode_targets[256] = {
&&_unknown_opcode,
&&TARGET_POP_TOP,
&&TARGET_ROT_TWO,
&&TARGET_ROT_THREE,
&&TARGET_DUP_TOP,
&&TARGET_DUP_TOP_TWO,
&&TARGET_ROT_FOUR,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_NOP,
&&TARGET_UNARY_POSITIVE,
&&TARGET_UNARY_NEGATIVE,
&&TARGET_UNARY_NOT,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_UNARY_INVERT,
&&TARGET_BINARY_MATRIX_MULTIPLY,
&&TARGET_INPLACE_MATRIX_MULTIPLY,
&&_unknown_opcode,
&&TARGET_BINARY_POWER,
&&TARGET_BINARY_MULTIPLY,
&&_unknown_opcode,
&&TARGET_BINARY_MODULO,
&&TARGET_BINARY_ADD,
&&TARGET_BINARY_SUBTRACT,
&&TARGET_BINARY_SUBSCR,
&&TARGET_BINARY_FLOOR_DIVIDE,
&&TARGET_BINARY_TRUE_DIVIDE,
&&TARGET_INPLACE_FLOOR_DIVIDE,
&&TARGET_INPLACE_TRUE_DIVIDE,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_RERAISE,
&&TARGET_WITH_EXCEPT_START,
&&TARGET_GET_AITER,
&&TARGET_GET_ANEXT,
&&TARGET_BEFORE_ASYNC_WITH,
&&_unknown_opcode,
&&TARGET_END_ASYNC_FOR,
&&TARGET_INPLACE_ADD,
&&TARGET_INPLACE_SUBTRACT,
&&TARGET_INPLACE_MULTIPLY,
&&_unknown_opcode,
&&TARGET_INPLACE_MODULO,
&&TARGET_STORE_SUBSCR,
&&TARGET_DELETE_SUBSCR,
&&TARGET_BINARY_LSHIFT,
&&TARGET_BINARY_RSHIFT,
&&TARGET_BINARY_AND,
&&TARGET_BINARY_XOR,
&&TARGET_BINARY_OR,
&&TARGET_INPLACE_POWER,
&&TARGET_GET_ITER,
&&TARGET_GET_YIELD_FROM_ITER,
&&TARGET_PRINT_EXPR,
&&TARGET_LOAD_BUILD_CLASS,
&&TARGET_YIELD_FROM,
&&TARGET_GET_AWAITABLE,
&&TARGET_LOAD_ASSERTION_ERROR,
&&TARGET_INPLACE_LSHIFT,
&&TARGET_INPLACE_RSHIFT,
&&TARGET_INPLACE_AND,
&&TARGET_INPLACE_XOR,
&&TARGET_INPLACE_OR,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_LIST_TO_TUPLE,
&&TARGET_RETURN_VALUE,
&&TARGET_IMPORT_STAR,
&&TARGET_SETUP_ANNOTATIONS,
&&TARGET_YIELD_VALUE,
&&TARGET_POP_BLOCK,
&&_unknown_opcode,
&&TARGET_POP_EXCEPT,
&&TARGET_STORE_NAME,
&&TARGET_DELETE_NAME,
&&TARGET_UNPACK_SEQUENCE,
&&TARGET_FOR_ITER,
&&TARGET_UNPACK_EX,
&&TARGET_STORE_ATTR,
&&TARGET_DELETE_ATTR,
&&TARGET_STORE_GLOBAL,
&&TARGET_DELETE_GLOBAL,
&&_unknown_opcode,
&&TARGET_LOAD_CONST,
&&TARGET_LOAD_NAME,
&&TARGET_BUILD_TUPLE,
&&TARGET_BUILD_LIST,
&&TARGET_BUILD_SET,
&&TARGET_BUILD_MAP,
&&TARGET_LOAD_ATTR,
&&TARGET_COMPARE_OP,
&&TARGET_IMPORT_NAME,
&&TARGET_IMPORT_FROM,
&&TARGET_JUMP_FORWARD,
&&TARGET_JUMP_IF_FALSE_OR_POP,
&&TARGET_JUMP_IF_TRUE_OR_POP,
&&TARGET_JUMP_ABSOLUTE,
&&TARGET_POP_JUMP_IF_FALSE,
&&TARGET_POP_JUMP_IF_TRUE,
&&TARGET_LOAD_GLOBAL,
&&TARGET_IS_OP,
&&TARGET_CONTAINS_OP,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_JUMP_IF_NOT_EXC_MATCH,
&&TARGET_SETUP_FINALLY,
&&_unknown_opcode,
&&TARGET_LOAD_FAST,
&&TARGET_STORE_FAST,
&&TARGET_DELETE_FAST,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_RAISE_VARARGS,
&&TARGET_CALL_FUNCTION,
&&TARGET_MAKE_FUNCTION,
&&TARGET_BUILD_SLICE,
&&_unknown_opcode,
&&TARGET_LOAD_CLOSURE,
&&TARGET_LOAD_DEREF,
&&TARGET_STORE_DEREF,
&&TARGET_DELETE_DEREF,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_CALL_FUNCTION_KW,
&&TARGET_CALL_FUNCTION_EX,
&&TARGET_SETUP_WITH,
&&TARGET_EXTENDED_ARG,
&&TARGET_LIST_APPEND,
&&TARGET_SET_ADD,
&&TARGET_MAP_ADD,
&&TARGET_LOAD_CLASSDEREF,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_SETUP_ASYNC_WITH,
&&TARGET_FORMAT_VALUE,
&&TARGET_BUILD_CONST_KEY_MAP,
&&TARGET_BUILD_STRING,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_LOAD_METHOD,
&&TARGET_CALL_METHOD,
&&TARGET_LIST_EXTEND,
&&TARGET_SET_UPDATE,
&&TARGET_DICT_MERGE,
&&TARGET_DICT_UPDATE,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode
};

View File

@ -0,0 +1,803 @@
/* Path configuration like module_search_path (sys.path) */
#include "Python.h"
#include "osdefs.h" // DELIM
#include "pycore_initconfig.h"
#include "pycore_fileutils.h"
#include "pycore_pathconfig.h"
#include "pycore_pymem.h" // _PyMem_SetDefaultAllocator()
#include <wchar.h>
#ifdef MS_WINDOWS
# include <windows.h> // GetFullPathNameW(), MAX_PATH
#endif
#ifdef __cplusplus
extern "C" {
#endif
_PyPathConfig _Py_path_config = _PyPathConfig_INIT;
static int
copy_wstr(wchar_t **dst, const wchar_t *src)
{
assert(*dst == NULL);
if (src != NULL) {
*dst = _PyMem_RawWcsdup(src);
if (*dst == NULL) {
return -1;
}
}
else {
*dst = NULL;
}
return 0;
}
static void
pathconfig_clear(_PyPathConfig *config)
{
/* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
called before Py_Initialize() which can changes the memory allocator. */
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
#define CLEAR(ATTR) \
do { \
PyMem_RawFree(ATTR); \
ATTR = NULL; \
} while (0)
CLEAR(config->program_full_path);
CLEAR(config->prefix);
CLEAR(config->exec_prefix);
CLEAR(config->module_search_path);
CLEAR(config->program_name);
CLEAR(config->home);
#ifdef MS_WINDOWS
CLEAR(config->base_executable);
#endif
#undef CLEAR
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
}
static PyStatus
pathconfig_copy(_PyPathConfig *config, const _PyPathConfig *config2)
{
pathconfig_clear(config);
#define COPY_ATTR(ATTR) \
do { \
if (copy_wstr(&config->ATTR, config2->ATTR) < 0) { \
return _PyStatus_NO_MEMORY(); \
} \
} while (0)
COPY_ATTR(program_full_path);
COPY_ATTR(prefix);
COPY_ATTR(exec_prefix);
COPY_ATTR(module_search_path);
COPY_ATTR(program_name);
COPY_ATTR(home);
#ifdef MS_WINDOWS
config->isolated = config2->isolated;
config->site_import = config2->site_import;
COPY_ATTR(base_executable);
#endif
#undef COPY_ATTR
return _PyStatus_OK();
}
void
_PyPathConfig_ClearGlobal(void)
{
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
pathconfig_clear(&_Py_path_config);
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
}
static wchar_t*
_PyWideStringList_Join(const PyWideStringList *list, wchar_t sep)
{
size_t len = 1; /* NUL terminator */
for (Py_ssize_t i=0; i < list->length; i++) {
if (i != 0) {
len++;
}
len += wcslen(list->items[i]);
}
wchar_t *text = PyMem_RawMalloc(len * sizeof(wchar_t));
if (text == NULL) {
return NULL;
}
wchar_t *str = text;
for (Py_ssize_t i=0; i < list->length; i++) {
wchar_t *path = list->items[i];
if (i != 0) {
*str++ = sep;
}
len = wcslen(path);
memcpy(str, path, len * sizeof(wchar_t));
str += len;
}
*str = L'\0';
return text;
}
static PyStatus
pathconfig_set_from_config(_PyPathConfig *pathconfig, const PyConfig *config)
{
PyStatus status;
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (config->module_search_paths_set) {
PyMem_RawFree(pathconfig->module_search_path);
pathconfig->module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM);
if (pathconfig->module_search_path == NULL) {
goto no_memory;
}
}
#define COPY_CONFIG(PATH_ATTR, CONFIG_ATTR) \
if (config->CONFIG_ATTR) { \
PyMem_RawFree(pathconfig->PATH_ATTR); \
pathconfig->PATH_ATTR = NULL; \
if (copy_wstr(&pathconfig->PATH_ATTR, config->CONFIG_ATTR) < 0) { \
goto no_memory; \
} \
}
COPY_CONFIG(program_full_path, executable);
COPY_CONFIG(prefix, prefix);
COPY_CONFIG(exec_prefix, exec_prefix);
COPY_CONFIG(program_name, program_name);
COPY_CONFIG(home, home);
#ifdef MS_WINDOWS
COPY_CONFIG(base_executable, base_executable);
#endif
#undef COPY_CONFIG
status = _PyStatus_OK();
goto done;
no_memory:
status = _PyStatus_NO_MEMORY();
done:
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
return status;
}
PyStatus
_PyConfig_WritePathConfig(const PyConfig *config)
{
return pathconfig_set_from_config(&_Py_path_config, config);
}
static PyStatus
config_init_module_search_paths(PyConfig *config, _PyPathConfig *pathconfig)
{
assert(!config->module_search_paths_set);
_PyWideStringList_Clear(&config->module_search_paths);
const wchar_t *sys_path = pathconfig->module_search_path;
const wchar_t delim = DELIM;
while (1) {
const wchar_t *p = wcschr(sys_path, delim);
if (p == NULL) {
p = sys_path + wcslen(sys_path); /* End of string */
}
size_t path_len = (p - sys_path);
wchar_t *path = PyMem_RawMalloc((path_len + 1) * sizeof(wchar_t));
if (path == NULL) {
return _PyStatus_NO_MEMORY();
}
memcpy(path, sys_path, path_len * sizeof(wchar_t));
path[path_len] = L'\0';
PyStatus status = PyWideStringList_Append(&config->module_search_paths, path);
PyMem_RawFree(path);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
if (*p == '\0') {
break;
}
sys_path = p + 1;
}
config->module_search_paths_set = 1;
return _PyStatus_OK();
}
/* Calculate the path configuration:
- exec_prefix
- module_search_path
- prefix
- program_full_path
On Windows, more fields are calculated:
- base_executable
- isolated
- site_import
On other platforms, isolated and site_import are left unchanged, and
_PyConfig_InitPathConfig() copies executable to base_executable (if it's not
set).
Priority, highest to lowest:
- PyConfig
- _Py_path_config: set by Py_SetPath(), Py_SetPythonHome()
and Py_SetProgramName()
- _PyPathConfig_Calculate()
*/
static PyStatus
pathconfig_calculate(_PyPathConfig *pathconfig, const PyConfig *config)
{
PyStatus status;
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
status = pathconfig_copy(pathconfig, &_Py_path_config);
if (_PyStatus_EXCEPTION(status)) {
goto done;
}
status = pathconfig_set_from_config(pathconfig, config);
if (_PyStatus_EXCEPTION(status)) {
goto done;
}
if (_Py_path_config.module_search_path == NULL) {
status = _PyPathConfig_Calculate(pathconfig, config);
}
else {
/* Py_SetPath() has been called: avoid _PyPathConfig_Calculate() */
}
done:
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
return status;
}
static PyStatus
config_calculate_pathconfig(PyConfig *config)
{
_PyPathConfig pathconfig = _PyPathConfig_INIT;
PyStatus status;
status = pathconfig_calculate(&pathconfig, config);
if (_PyStatus_EXCEPTION(status)) {
goto done;
}
if (!config->module_search_paths_set) {
status = config_init_module_search_paths(config, &pathconfig);
if (_PyStatus_EXCEPTION(status)) {
goto done;
}
}
#define COPY_ATTR(PATH_ATTR, CONFIG_ATTR) \
if (config->CONFIG_ATTR == NULL) { \
if (copy_wstr(&config->CONFIG_ATTR, pathconfig.PATH_ATTR) < 0) { \
goto no_memory; \
} \
}
#ifdef MS_WINDOWS
if (config->executable != NULL && config->base_executable == NULL) {
/* If executable is set explicitly in the configuration,
ignore calculated base_executable: _PyConfig_InitPathConfig()
will copy executable to base_executable */
}
else {
COPY_ATTR(base_executable, base_executable);
}
#endif
COPY_ATTR(program_full_path, executable);
COPY_ATTR(prefix, prefix);
COPY_ATTR(exec_prefix, exec_prefix);
#undef COPY_ATTR
#ifdef MS_WINDOWS
/* If a ._pth file is found: isolated and site_import are overriden */
if (pathconfig.isolated != -1) {
config->isolated = pathconfig.isolated;
}
if (pathconfig.site_import != -1) {
config->site_import = pathconfig.site_import;
}
#endif
status = _PyStatus_OK();
goto done;
no_memory:
status = _PyStatus_NO_MEMORY();
done:
pathconfig_clear(&pathconfig);
return status;
}
PyStatus
_PyConfig_InitPathConfig(PyConfig *config)
{
/* Do we need to calculate the path? */
if (!config->module_search_paths_set
|| config->executable == NULL
|| config->prefix == NULL
|| config->exec_prefix == NULL)
{
PyStatus status = config_calculate_pathconfig(config);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
}
if (config->base_prefix == NULL) {
if (copy_wstr(&config->base_prefix, config->prefix) < 0) {
return _PyStatus_NO_MEMORY();
}
}
if (config->base_exec_prefix == NULL) {
if (copy_wstr(&config->base_exec_prefix,
config->exec_prefix) < 0) {
return _PyStatus_NO_MEMORY();
}
}
if (config->base_executable == NULL) {
if (copy_wstr(&config->base_executable,
config->executable) < 0) {
return _PyStatus_NO_MEMORY();
}
}
return _PyStatus_OK();
}
static PyStatus
pathconfig_global_read(_PyPathConfig *pathconfig)
{
PyConfig config;
_PyConfig_InitCompatConfig(&config);
/* Call _PyConfig_InitPathConfig() */
PyStatus status = PyConfig_Read(&config);
if (_PyStatus_EXCEPTION(status)) {
goto done;
}
status = pathconfig_set_from_config(pathconfig, &config);
done:
PyConfig_Clear(&config);
return status;
}
static void
pathconfig_global_init(void)
{
PyStatus status;
if (_Py_path_config.module_search_path == NULL) {
status = pathconfig_global_read(&_Py_path_config);
if (_PyStatus_EXCEPTION(status)) {
Py_ExitStatusException(status);
}
}
else {
/* Global configuration already initialized */
}
assert(_Py_path_config.program_full_path != NULL);
assert(_Py_path_config.prefix != NULL);
assert(_Py_path_config.exec_prefix != NULL);
assert(_Py_path_config.module_search_path != NULL);
assert(_Py_path_config.program_name != NULL);
/* home can be NULL */
#ifdef MS_WINDOWS
assert(_Py_path_config.base_executable != NULL);
#endif
}
/* External interface */
static void _Py_NO_RETURN
path_out_of_memory(const char *func)
{
_Py_FatalErrorFunc(func, "out of memory");
}
void
Py_SetPath(const wchar_t *path)
{
if (path == NULL) {
pathconfig_clear(&_Py_path_config);
return;
}
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
/* Getting the program full path calls pathconfig_global_init() */
wchar_t *program_full_path = _PyMem_RawWcsdup(Py_GetProgramFullPath());
PyMem_RawFree(_Py_path_config.program_full_path);
PyMem_RawFree(_Py_path_config.prefix);
PyMem_RawFree(_Py_path_config.exec_prefix);
PyMem_RawFree(_Py_path_config.module_search_path);
_Py_path_config.program_full_path = program_full_path;
_Py_path_config.prefix = _PyMem_RawWcsdup(L"");
_Py_path_config.exec_prefix = _PyMem_RawWcsdup(L"");
_Py_path_config.module_search_path = _PyMem_RawWcsdup(path);
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (_Py_path_config.program_full_path == NULL
|| _Py_path_config.prefix == NULL
|| _Py_path_config.exec_prefix == NULL
|| _Py_path_config.module_search_path == NULL)
{
path_out_of_memory(__func__);
}
}
void
Py_SetPythonHome(const wchar_t *home)
{
if (home == NULL) {
return;
}
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
PyMem_RawFree(_Py_path_config.home);
_Py_path_config.home = _PyMem_RawWcsdup(home);
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (_Py_path_config.home == NULL) {
path_out_of_memory(__func__);
}
}
void
Py_SetProgramName(const wchar_t *program_name)
{
if (program_name == NULL || program_name[0] == L'\0') {
return;
}
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
PyMem_RawFree(_Py_path_config.program_name);
_Py_path_config.program_name = _PyMem_RawWcsdup(program_name);
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (_Py_path_config.program_name == NULL) {
path_out_of_memory(__func__);
}
}
void
_Py_SetProgramFullPath(const wchar_t *program_full_path)
{
if (program_full_path == NULL || program_full_path[0] == L'\0') {
return;
}
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
PyMem_RawFree(_Py_path_config.program_full_path);
_Py_path_config.program_full_path = _PyMem_RawWcsdup(program_full_path);
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (_Py_path_config.program_full_path == NULL) {
path_out_of_memory(__func__);
}
}
wchar_t *
Py_GetPath(void)
{
pathconfig_global_init();
return _Py_path_config.module_search_path;
}
wchar_t *
Py_GetPrefix(void)
{
pathconfig_global_init();
return _Py_path_config.prefix;
}
wchar_t *
Py_GetExecPrefix(void)
{
pathconfig_global_init();
return _Py_path_config.exec_prefix;
}
wchar_t *
Py_GetProgramFullPath(void)
{
pathconfig_global_init();
return _Py_path_config.program_full_path;
}
wchar_t*
Py_GetPythonHome(void)
{
pathconfig_global_init();
return _Py_path_config.home;
}
wchar_t *
Py_GetProgramName(void)
{
pathconfig_global_init();
return _Py_path_config.program_name;
}
/* Compute module search path from argv[0] or the current working
directory ("-m module" case) which will be prepended to sys.argv:
sys.path[0].
Return 1 if the path is correctly resolved and written into *path0_p.
Return 0 if it fails to resolve the full path. For example, return 0 if the
current working directory has been removed (bpo-36236) or if argv is empty.
Raise an exception and return -1 on error.
*/
int
_PyPathConfig_ComputeSysPath0(const PyWideStringList *argv, PyObject **path0_p)
{
assert(_PyWideStringList_CheckConsistency(argv));
if (argv->length == 0) {
/* Leave sys.path unchanged if sys.argv is empty */
return 0;
}
wchar_t *argv0 = argv->items[0];
int have_module_arg = (wcscmp(argv0, L"-m") == 0);
int have_script_arg = (!have_module_arg && (wcscmp(argv0, L"-c") != 0));
wchar_t *path0 = argv0;
Py_ssize_t n = 0;
#ifdef HAVE_REALPATH
wchar_t fullpath[MAXPATHLEN];
#elif defined(MS_WINDOWS)
wchar_t fullpath[MAX_PATH];
#endif
if (have_module_arg) {
#if defined(HAVE_REALPATH) || defined(MS_WINDOWS)
if (!_Py_wgetcwd(fullpath, Py_ARRAY_LENGTH(fullpath))) {
return 0;
}
path0 = fullpath;
#else
path0 = L".";
#endif
n = wcslen(path0);
}
#ifdef HAVE_READLINK
wchar_t link[MAXPATHLEN + 1];
int nr = 0;
wchar_t path0copy[2 * MAXPATHLEN + 1];
if (have_script_arg) {
nr = _Py_wreadlink(path0, link, Py_ARRAY_LENGTH(link));
}
if (nr > 0) {
/* It's a symlink */
link[nr] = '\0';
if (link[0] == SEP) {
path0 = link; /* Link to absolute path */
}
else if (wcschr(link, SEP) == NULL) {
/* Link without path */
}
else {
/* Must join(dirname(path0), link) */
wchar_t *q = wcsrchr(path0, SEP);
if (q == NULL) {
/* path0 without path */
path0 = link;
}
else {
/* Must make a copy, path0copy has room for 2 * MAXPATHLEN */
wcsncpy(path0copy, path0, MAXPATHLEN);
q = wcsrchr(path0copy, SEP);
wcsncpy(q+1, link, MAXPATHLEN);
q[MAXPATHLEN + 1] = L'\0';
path0 = path0copy;
}
}
}
#endif /* HAVE_READLINK */
wchar_t *p = NULL;
#if SEP == '\\'
/* Special case for Microsoft filename syntax */
if (have_script_arg) {
wchar_t *q;
#if defined(MS_WINDOWS)
/* Replace the first element in argv with the full path. */
wchar_t *ptemp;
if (GetFullPathNameW(path0,
Py_ARRAY_LENGTH(fullpath),
fullpath,
&ptemp)) {
path0 = fullpath;
}
#endif
p = wcsrchr(path0, SEP);
/* Test for alternate separator */
q = wcsrchr(p ? p : path0, '/');
if (q != NULL)
p = q;
if (p != NULL) {
n = p + 1 - path0;
if (n > 1 && p[-1] != ':')
n--; /* Drop trailing separator */
}
}
#else
/* All other filename syntaxes */
if (have_script_arg) {
#if defined(HAVE_REALPATH)
if (_Py_wrealpath(path0, fullpath, Py_ARRAY_LENGTH(fullpath))) {
path0 = fullpath;
}
#endif
p = wcsrchr(path0, SEP);
}
if (p != NULL) {
n = p + 1 - path0;
#if SEP == '/' /* Special case for Unix filename syntax */
if (n > 1) {
/* Drop trailing separator */
n--;
}
#endif /* Unix */
}
#endif /* All others */
PyObject *path0_obj = PyUnicode_FromWideChar(path0, n);
if (path0_obj == NULL) {
return -1;
}
*path0_p = path0_obj;
return 1;
}
#ifdef MS_WINDOWS
#define WCSTOK wcstok_s
#else
#define WCSTOK wcstok
#endif
/* Search for a prefix value in an environment file (pyvenv.cfg).
- If found, copy it into *value_p: string which must be freed by
PyMem_RawFree().
- If not found, *value_p is set to NULL.
*/
PyStatus
_Py_FindEnvConfigValue(FILE *env_file, const wchar_t *key,
wchar_t **value_p)
{
*value_p = NULL;
char buffer[MAXPATHLEN * 2 + 1]; /* allow extra for key, '=', etc. */
buffer[Py_ARRAY_LENGTH(buffer)-1] = '\0';
while (!feof(env_file)) {
char * p = fgets(buffer, Py_ARRAY_LENGTH(buffer) - 1, env_file);
if (p == NULL) {
break;
}
size_t n = strlen(p);
if (p[n - 1] != '\n') {
/* line has overflowed - bail */
break;
}
if (p[0] == '#') {
/* Comment - skip */
continue;
}
wchar_t *tmpbuffer = _Py_DecodeUTF8_surrogateescape(buffer, n, NULL);
if (tmpbuffer) {
wchar_t * state;
wchar_t * tok = WCSTOK(tmpbuffer, L" \t\r\n", &state);
if ((tok != NULL) && !wcscmp(tok, key)) {
tok = WCSTOK(NULL, L" \t", &state);
if ((tok != NULL) && !wcscmp(tok, L"=")) {
tok = WCSTOK(NULL, L"\r\n", &state);
if (tok != NULL) {
*value_p = _PyMem_RawWcsdup(tok);
PyMem_RawFree(tmpbuffer);
if (*value_p == NULL) {
return _PyStatus_NO_MEMORY();
}
/* found */
return _PyStatus_OK();
}
}
}
PyMem_RawFree(tmpbuffer);
}
}
/* not found */
return _PyStatus_OK();
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,538 @@
/* Peephole optimizations for bytecode compiler. */
#include "Python.h"
#include "Python-ast.h"
#include "node.h"
#include "ast.h"
#include "code.h"
#include "symtable.h"
#include "opcode.h"
#include "wordcode_helpers.h"
#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==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \
|| op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP || op==JUMP_IF_NOT_EXC_MATCH)
#define JUMPS_ON_TRUE(op) (op==POP_JUMP_IF_TRUE || op==JUMP_IF_TRUE_OR_POP)
#define GETJUMPTGT(arr, i) (get_arg(arr, i) / sizeof(_Py_CODEUNIT) + \
(ABSOLUTE_JUMP(_Py_OPCODE(arr[i])) ? 0 : i+1))
#define ISBASICBLOCK(blocks, start, end) \
(blocks[start]==blocks[end])
/* Scans back N consecutive LOAD_CONST instructions, skipping NOPs,
returns index of the Nth last's LOAD_CONST's EXTENDED_ARG prefix.
Callers are responsible to check CONST_STACK_LEN beforehand.
*/
static Py_ssize_t
lastn_const_start(const _Py_CODEUNIT *codestr, Py_ssize_t i, Py_ssize_t n)
{
assert(n > 0);
for (;;) {
i--;
assert(i >= 0);
if (_Py_OPCODE(codestr[i]) == LOAD_CONST) {
if (!--n) {
while (i > 0 && _Py_OPCODE(codestr[i-1]) == EXTENDED_ARG) {
i--;
}
return i;
}
}
else {
assert(_Py_OPCODE(codestr[i]) == EXTENDED_ARG);
}
}
}
/* Scans through EXTENDED ARGs, seeking the index of the effective opcode */
static Py_ssize_t
find_op(const _Py_CODEUNIT *codestr, Py_ssize_t codelen, Py_ssize_t i)
{
while (i < codelen && _Py_OPCODE(codestr[i]) == EXTENDED_ARG) {
i++;
}
return i;
}
/* Given the index of the effective opcode,
scan back to construct the oparg with EXTENDED_ARG */
static unsigned int
get_arg(const _Py_CODEUNIT *codestr, Py_ssize_t i)
{
_Py_CODEUNIT word;
unsigned int oparg = _Py_OPARG(codestr[i]);
if (i >= 1 && _Py_OPCODE(word = codestr[i-1]) == EXTENDED_ARG) {
oparg |= _Py_OPARG(word) << 8;
if (i >= 2 && _Py_OPCODE(word = codestr[i-2]) == EXTENDED_ARG) {
oparg |= _Py_OPARG(word) << 16;
if (i >= 3 && _Py_OPCODE(word = codestr[i-3]) == EXTENDED_ARG) {
oparg |= _Py_OPARG(word) << 24;
}
}
}
return oparg;
}
/* Fill the region with NOPs. */
static void
fill_nops(_Py_CODEUNIT *codestr, Py_ssize_t start, Py_ssize_t end)
{
memset(codestr + start, NOP, (end - start) * sizeof(_Py_CODEUNIT));
}
/* Given the index of the effective opcode,
attempt to replace the argument, taking into account EXTENDED_ARG.
Returns -1 on failure, or the new op index on success */
static Py_ssize_t
set_arg(_Py_CODEUNIT *codestr, Py_ssize_t i, unsigned int oparg)
{
unsigned int curarg = get_arg(codestr, i);
int curilen, newilen;
if (curarg == oparg)
return i;
curilen = instrsize(curarg);
newilen = instrsize(oparg);
if (curilen < newilen) {
return -1;
}
write_op_arg(codestr + i + 1 - curilen, _Py_OPCODE(codestr[i]), oparg, newilen);
fill_nops(codestr, i + 1 - curilen + newilen, i + 1);
return i-curilen+newilen;
}
/* Attempt to write op/arg at end of specified region of memory.
Preceding memory in the region is overwritten with NOPs.
Returns -1 on failure, op index on success */
static Py_ssize_t
copy_op_arg(_Py_CODEUNIT *codestr, Py_ssize_t i, unsigned char op,
unsigned int oparg, Py_ssize_t maxi)
{
int ilen = instrsize(oparg);
if (i + ilen > maxi) {
return -1;
}
write_op_arg(codestr + maxi - ilen, op, oparg, ilen);
fill_nops(codestr, i, maxi - ilen);
return maxi - 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.
*/
static Py_ssize_t
fold_tuple_on_constants(_Py_CODEUNIT *codestr, Py_ssize_t codelen,
Py_ssize_t c_start, Py_ssize_t opcode_end,
PyObject *consts, int n)
{
/* Pre-conditions */
assert(PyList_CheckExact(consts));
/* Buildup new tuple of constants */
PyObject *newconst = PyTuple_New(n);
if (newconst == NULL) {
return -1;
}
for (Py_ssize_t i = 0, pos = c_start; i < n; i++, pos++) {
assert(pos < opcode_end);
pos = find_op(codestr, codelen, pos);
assert(_Py_OPCODE(codestr[pos]) == LOAD_CONST);
unsigned int arg = get_arg(codestr, pos);
PyObject *constant = PyList_GET_ITEM(consts, arg);
Py_INCREF(constant);
PyTuple_SET_ITEM(newconst, i, constant);
}
Py_ssize_t index = PyList_GET_SIZE(consts);
#if SIZEOF_SIZE_T > SIZEOF_INT
if ((size_t)index >= UINT_MAX - 1) {
Py_DECREF(newconst);
PyErr_SetString(PyExc_OverflowError, "too many constants");
return -1;
}
#endif
/* Append folded constant onto consts */
if (PyList_Append(consts, newconst)) {
Py_DECREF(newconst);
return -1;
}
Py_DECREF(newconst);
return copy_op_arg(codestr, c_start, LOAD_CONST,
(unsigned int)index, opcode_end);
}
static unsigned int *
markblocks(_Py_CODEUNIT *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++) {
opcode = _Py_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_IF_NOT_EXC_MATCH:
case JUMP_ABSOLUTE:
case SETUP_FINALLY:
case SETUP_WITH:
case SETUP_ASYNC_WITH:
j = GETJUMPTGT(code, i);
assert(j < len);
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 when the lineno table has complex
encoding for gaps >= 255.
Optimizations are restricted to simple transformations occurring 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. */
PyObject *
PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
PyObject *lnotab_obj)
{
Py_ssize_t h, i, nexti, op_start, tgt;
unsigned int j, nops;
unsigned char opcode, nextop;
_Py_CODEUNIT *codestr = NULL;
unsigned char *lnotab;
unsigned int cum_orig_offset, last_offset;
Py_ssize_t tabsiz;
// Count runs of consecutive LOAD_CONSTs
unsigned int cumlc = 0, lastlc = 0;
unsigned int *blocks = NULL;
/* Bail out if an exception is set */
if (PyErr_Occurred())
goto exitError;
/* Bypass optimization when the lnotab table is too complex */
assert(PyBytes_Check(lnotab_obj));
lnotab = (unsigned char*)PyBytes_AS_STRING(lnotab_obj);
tabsiz = PyBytes_GET_SIZE(lnotab_obj);
assert(tabsiz == 0 || Py_REFCNT(lnotab_obj) == 1);
/* Don't optimize if lnotab contains instruction pointer delta larger
than +255 (encoded as multiple bytes), just to keep the peephole optimizer
simple. The optimizer leaves line number deltas unchanged. */
for (i = 0; i < tabsiz; i += 2) {
if (lnotab[i] == 255) {
goto exitUnchanged;
}
}
assert(PyBytes_Check(code));
Py_ssize_t codesize = PyBytes_GET_SIZE(code);
assert(codesize % sizeof(_Py_CODEUNIT) == 0);
Py_ssize_t codelen = codesize / sizeof(_Py_CODEUNIT);
if (codelen > INT_MAX) {
/* Python assembler is limited to INT_MAX: see assembler.a_offset in
compile.c. */
goto exitUnchanged;
}
/* Make a modifiable copy of the code string */
codestr = (_Py_CODEUNIT *)PyMem_Malloc(codesize);
if (codestr == NULL) {
PyErr_NoMemory();
goto exitError;
}
memcpy(codestr, PyBytes_AS_STRING(code), codesize);
blocks = markblocks(codestr, codelen);
if (blocks == NULL)
goto exitError;
assert(PyList_Check(consts));
for (i=find_op(codestr, codelen, 0) ; i<codelen ; i=nexti) {
opcode = _Py_OPCODE(codestr[i]);
op_start = i;
while (op_start >= 1 && _Py_OPCODE(codestr[op_start-1]) == EXTENDED_ARG) {
op_start--;
}
nexti = i + 1;
while (nexti < codelen && _Py_OPCODE(codestr[nexti]) == EXTENDED_ARG)
nexti++;
nextop = nexti < codelen ? _Py_OPCODE(codestr[nexti]) : 0;
lastlc = cumlc;
cumlc = 0;
switch (opcode) {
/* Skip over LOAD_CONST trueconst
POP_JUMP_IF_FALSE xx. This improves
"while 1" performance. */
case LOAD_CONST:
cumlc = lastlc + 1;
if (nextop != POP_JUMP_IF_FALSE ||
!ISBASICBLOCK(blocks, op_start, i + 1)) {
break;
}
PyObject* cnt = PyList_GET_ITEM(consts, get_arg(codestr, i));
int is_true = PyObject_IsTrue(cnt);
if (is_true == -1) {
goto exitError;
}
if (is_true == 1) {
fill_nops(codestr, op_start, nexti + 1);
cumlc = 0;
}
break;
/* Try to fold tuples of constants.
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:
j = get_arg(codestr, i);
if (j > 0 && lastlc >= j) {
h = lastn_const_start(codestr, op_start, j);
if (ISBASICBLOCK(blocks, h, op_start)) {
h = fold_tuple_on_constants(codestr, codelen,
h, i+1, consts, j);
break;
}
}
if (nextop != UNPACK_SEQUENCE ||
!ISBASICBLOCK(blocks, op_start, i + 1) ||
j != get_arg(codestr, nexti))
break;
if (j < 2) {
fill_nops(codestr, op_start, nexti + 1);
} else if (j == 2) {
codestr[op_start] = PACKOPARG(ROT_TWO, 0);
fill_nops(codestr, op_start + 1, nexti + 1);
} else if (j == 3) {
codestr[op_start] = PACKOPARG(ROT_THREE, 0);
codestr[op_start + 1] = PACKOPARG(ROT_TWO, 0);
fill_nops(codestr, op_start + 2, nexti + 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:
"a and b or c"
"(a and b) and c"
"(a or b) or c"
"(a or 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+1
where y+1 is the instruction following the second test.
*/
case JUMP_IF_FALSE_OR_POP:
case JUMP_IF_TRUE_OR_POP:
h = get_arg(codestr, i) / sizeof(_Py_CODEUNIT);
tgt = find_op(codestr, codelen, h);
j = _Py_OPCODE(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.
The current opcode inherits its target's
stack effect */
h = set_arg(codestr, i, get_arg(codestr, tgt));
} 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). */
Py_ssize_t arg = (tgt + 1);
/* cannot overflow: codelen <= INT_MAX */
assert((size_t)arg <= UINT_MAX / sizeof(_Py_CODEUNIT));
arg *= sizeof(_Py_CODEUNIT);
h = set_arg(codestr, i, (unsigned int)arg);
j = opcode == JUMP_IF_TRUE_OR_POP ?
POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE;
}
if (h >= 0) {
nexti = h;
codestr[nexti] = PACKOPARG(j, _Py_OPARG(codestr[nexti]));
break;
}
}
/* Intentional fallthrough */
/* Replace jumps to unconditional jumps */
case POP_JUMP_IF_FALSE:
case POP_JUMP_IF_TRUE:
case JUMP_FORWARD:
case JUMP_ABSOLUTE:
h = GETJUMPTGT(codestr, i);
tgt = find_op(codestr, codelen, h);
/* Replace JUMP_* to a RETURN into just a RETURN */
if (UNCONDITIONAL_JUMP(opcode) &&
_Py_OPCODE(codestr[tgt]) == RETURN_VALUE) {
codestr[op_start] = PACKOPARG(RETURN_VALUE, 0);
fill_nops(codestr, op_start + 1, i + 1);
} else if (UNCONDITIONAL_JUMP(_Py_OPCODE(codestr[tgt]))) {
size_t arg = GETJUMPTGT(codestr, tgt);
if (opcode == JUMP_FORWARD) { /* JMP_ABS can go backwards */
opcode = JUMP_ABSOLUTE;
} else if (!ABSOLUTE_JUMP(opcode)) {
if (arg < (size_t)(i + 1)) {
break; /* No backward relative jumps */
}
arg -= i + 1; /* Calc relative jump addr */
}
/* cannot overflow: codelen <= INT_MAX */
assert(arg <= (UINT_MAX / sizeof(_Py_CODEUNIT)));
arg *= sizeof(_Py_CODEUNIT);
copy_op_arg(codestr, op_start, opcode,
(unsigned int)arg, i + 1);
}
break;
/* Remove unreachable ops after RETURN */
case RETURN_VALUE:
h = i + 1;
while (h < codelen && ISBASICBLOCK(blocks, i, h))
{
/* Leave SETUP_FINALLY and RERAISE in place to help find block limits. */
if (_Py_OPCODE(codestr[h]) == SETUP_FINALLY || _Py_OPCODE(codestr[h]) == RERAISE) {
while (h > i + 1 &&
_Py_OPCODE(codestr[h - 1]) == EXTENDED_ARG)
{
h--;
}
break;
}
h++;
}
if (h > i + 1) {
fill_nops(codestr, i + 1, h);
nexti = find_op(codestr, codelen, h);
}
break;
}
}
/* Fixup lnotab */
for (i = 0, nops = 0; i < codelen; i++) {
size_t block = (size_t)i - nops;
/* cannot overflow: codelen <= INT_MAX */
assert(block <= UINT_MAX);
/* original code offset => new code offset */
blocks[i] = (unsigned int)block;
if (_Py_OPCODE(codestr[i]) == NOP) {
nops++;
}
}
cum_orig_offset = 0;
last_offset = 0;
for (i=0 ; i < tabsiz ; i+=2) {
unsigned int offset_delta, new_offset;
cum_orig_offset += lnotab[i];
assert(cum_orig_offset % sizeof(_Py_CODEUNIT) == 0);
new_offset = blocks[cum_orig_offset / sizeof(_Py_CODEUNIT)] *
sizeof(_Py_CODEUNIT);
offset_delta = new_offset - last_offset;
assert(offset_delta <= 255);
lnotab[i] = (unsigned char)offset_delta;
last_offset = new_offset;
}
/* Remove NOPs and fixup jump targets */
for (op_start = i = h = 0; i < codelen; i++, op_start = i) {
j = _Py_OPARG(codestr[i]);
while (_Py_OPCODE(codestr[i]) == EXTENDED_ARG) {
i++;
j = j<<8 | _Py_OPARG(codestr[i]);
}
opcode = _Py_OPCODE(codestr[i]);
switch (opcode) {
case NOP:continue;
case JUMP_ABSOLUTE:
case POP_JUMP_IF_FALSE:
case POP_JUMP_IF_TRUE:
case JUMP_IF_FALSE_OR_POP:
case JUMP_IF_TRUE_OR_POP:
case JUMP_IF_NOT_EXC_MATCH:
j = blocks[j / sizeof(_Py_CODEUNIT)] * sizeof(_Py_CODEUNIT);
break;
case FOR_ITER:
case JUMP_FORWARD:
case SETUP_FINALLY:
case SETUP_WITH:
case SETUP_ASYNC_WITH:
j = blocks[j / sizeof(_Py_CODEUNIT) + i + 1] - blocks[i] - 1;
j *= sizeof(_Py_CODEUNIT);
break;
}
Py_ssize_t ilen = i - op_start + 1;
if (instrsize(j) > ilen) {
goto exitUnchanged;
}
/* If instrsize(j) < ilen, we'll emit EXTENDED_ARG 0 */
if (ilen > 4) {
/* Can only happen when PyCode_Optimize() is called with
malformed bytecode. */
goto exitUnchanged;
}
write_op_arg(codestr + h, opcode, j, (int)ilen);
h += ilen;
}
assert(h + (Py_ssize_t)nops == codelen);
PyMem_Free(blocks);
code = PyBytes_FromStringAndSize((char *)codestr, h * sizeof(_Py_CODEUNIT));
PyMem_Free(codestr);
return code;
exitError:
code = NULL;
exitUnchanged:
Py_XINCREF(code);
PyMem_Free(blocks);
PyMem_Free(codestr);
return code;
}

Some files were not shown because too many files have changed in this diff Show More