diff options
author | Ori Bernstein <ori@eigenstate.org> | 2021-06-14 00:00:37 +0000 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2021-06-14 00:00:37 +0000 |
commit | a73a964e51247ed169d322c725a3a18859f109a3 (patch) | |
tree | 3f752d117274d444bda44e85609aeac1acf313f3 /sys/src/cmd/python/Python | |
parent | e64efe273fcb921a61bf27d33b230c4e64fcd425 (diff) |
python, hg: tow outside the environment.
they've served us well, and can ride off into the sunset.
Diffstat (limited to 'sys/src/cmd/python/Python')
70 files changed, 0 insertions, 39493 deletions
diff --git a/sys/src/cmd/python/Python/Python-ast.c b/sys/src/cmd/python/Python/Python-ast.c deleted file mode 100644 index 7a0f52825..000000000 --- a/sys/src/cmd/python/Python/Python-ast.c +++ /dev/null @@ -1,3202 +0,0 @@ -/* File automatically generated by Parser/asdl_c.py */ - -#include "Python.h" -#include "Python-ast.h" - -static PyTypeObject* AST_type; -static PyTypeObject *mod_type; -static PyObject* ast2obj_mod(void*); -static PyTypeObject *Module_type; -static char *Module_fields[]={ - "body", -}; -static PyTypeObject *Interactive_type; -static char *Interactive_fields[]={ - "body", -}; -static PyTypeObject *Expression_type; -static char *Expression_fields[]={ - "body", -}; -static PyTypeObject *Suite_type; -static char *Suite_fields[]={ - "body", -}; -static PyTypeObject *stmt_type; -static char *stmt_attributes[] = { - "lineno", - "col_offset", -}; -static PyObject* ast2obj_stmt(void*); -static PyTypeObject *FunctionDef_type; -static char *FunctionDef_fields[]={ - "name", - "args", - "body", - "decorators", -}; -static PyTypeObject *ClassDef_type; -static char *ClassDef_fields[]={ - "name", - "bases", - "body", -}; -static PyTypeObject *Return_type; -static char *Return_fields[]={ - "value", -}; -static PyTypeObject *Delete_type; -static char *Delete_fields[]={ - "targets", -}; -static PyTypeObject *Assign_type; -static char *Assign_fields[]={ - "targets", - "value", -}; -static PyTypeObject *AugAssign_type; -static char *AugAssign_fields[]={ - "target", - "op", - "value", -}; -static PyTypeObject *Print_type; -static char *Print_fields[]={ - "dest", - "values", - "nl", -}; -static PyTypeObject *For_type; -static char *For_fields[]={ - "target", - "iter", - "body", - "orelse", -}; -static PyTypeObject *While_type; -static char *While_fields[]={ - "test", - "body", - "orelse", -}; -static PyTypeObject *If_type; -static char *If_fields[]={ - "test", - "body", - "orelse", -}; -static PyTypeObject *With_type; -static char *With_fields[]={ - "context_expr", - "optional_vars", - "body", -}; -static PyTypeObject *Raise_type; -static char *Raise_fields[]={ - "type", - "inst", - "tback", -}; -static PyTypeObject *TryExcept_type; -static char *TryExcept_fields[]={ - "body", - "handlers", - "orelse", -}; -static PyTypeObject *TryFinally_type; -static char *TryFinally_fields[]={ - "body", - "finalbody", -}; -static PyTypeObject *Assert_type; -static char *Assert_fields[]={ - "test", - "msg", -}; -static PyTypeObject *Import_type; -static char *Import_fields[]={ - "names", -}; -static PyTypeObject *ImportFrom_type; -static char *ImportFrom_fields[]={ - "module", - "names", - "level", -}; -static PyTypeObject *Exec_type; -static char *Exec_fields[]={ - "body", - "globals", - "locals", -}; -static PyTypeObject *Global_type; -static char *Global_fields[]={ - "names", -}; -static PyTypeObject *Expr_type; -static char *Expr_fields[]={ - "value", -}; -static PyTypeObject *Pass_type; -static PyTypeObject *Break_type; -static PyTypeObject *Continue_type; -static PyTypeObject *expr_type; -static char *expr_attributes[] = { - "lineno", - "col_offset", -}; -static PyObject* ast2obj_expr(void*); -static PyTypeObject *BoolOp_type; -static char *BoolOp_fields[]={ - "op", - "values", -}; -static PyTypeObject *BinOp_type; -static char *BinOp_fields[]={ - "left", - "op", - "right", -}; -static PyTypeObject *UnaryOp_type; -static char *UnaryOp_fields[]={ - "op", - "operand", -}; -static PyTypeObject *Lambda_type; -static char *Lambda_fields[]={ - "args", - "body", -}; -static PyTypeObject *IfExp_type; -static char *IfExp_fields[]={ - "test", - "body", - "orelse", -}; -static PyTypeObject *Dict_type; -static char *Dict_fields[]={ - "keys", - "values", -}; -static PyTypeObject *ListComp_type; -static char *ListComp_fields[]={ - "elt", - "generators", -}; -static PyTypeObject *GeneratorExp_type; -static char *GeneratorExp_fields[]={ - "elt", - "generators", -}; -static PyTypeObject *Yield_type; -static char *Yield_fields[]={ - "value", -}; -static PyTypeObject *Compare_type; -static char *Compare_fields[]={ - "left", - "ops", - "comparators", -}; -static PyTypeObject *Call_type; -static char *Call_fields[]={ - "func", - "args", - "keywords", - "starargs", - "kwargs", -}; -static PyTypeObject *Repr_type; -static char *Repr_fields[]={ - "value", -}; -static PyTypeObject *Num_type; -static char *Num_fields[]={ - "n", -}; -static PyTypeObject *Str_type; -static char *Str_fields[]={ - "s", -}; -static PyTypeObject *Attribute_type; -static char *Attribute_fields[]={ - "value", - "attr", - "ctx", -}; -static PyTypeObject *Subscript_type; -static char *Subscript_fields[]={ - "value", - "slice", - "ctx", -}; -static PyTypeObject *Name_type; -static char *Name_fields[]={ - "id", - "ctx", -}; -static PyTypeObject *List_type; -static char *List_fields[]={ - "elts", - "ctx", -}; -static PyTypeObject *Tuple_type; -static char *Tuple_fields[]={ - "elts", - "ctx", -}; -static PyTypeObject *expr_context_type; -static PyObject *Load_singleton, *Store_singleton, *Del_singleton, -*AugLoad_singleton, *AugStore_singleton, *Param_singleton; -static PyObject* ast2obj_expr_context(expr_context_ty); -static PyTypeObject *Load_type; -static PyTypeObject *Store_type; -static PyTypeObject *Del_type; -static PyTypeObject *AugLoad_type; -static PyTypeObject *AugStore_type; -static PyTypeObject *Param_type; -static PyTypeObject *slice_type; -static PyObject* ast2obj_slice(void*); -static PyTypeObject *Ellipsis_type; -static PyTypeObject *Slice_type; -static char *Slice_fields[]={ - "lower", - "upper", - "step", -}; -static PyTypeObject *ExtSlice_type; -static char *ExtSlice_fields[]={ - "dims", -}; -static PyTypeObject *Index_type; -static char *Index_fields[]={ - "value", -}; -static PyTypeObject *boolop_type; -static PyObject *And_singleton, *Or_singleton; -static PyObject* ast2obj_boolop(boolop_ty); -static PyTypeObject *And_type; -static PyTypeObject *Or_type; -static PyTypeObject *operator_type; -static PyObject *Add_singleton, *Sub_singleton, *Mult_singleton, -*Div_singleton, *Mod_singleton, *Pow_singleton, *LShift_singleton, -*RShift_singleton, *BitOr_singleton, *BitXor_singleton, *BitAnd_singleton, -*FloorDiv_singleton; -static PyObject* ast2obj_operator(operator_ty); -static PyTypeObject *Add_type; -static PyTypeObject *Sub_type; -static PyTypeObject *Mult_type; -static PyTypeObject *Div_type; -static PyTypeObject *Mod_type; -static PyTypeObject *Pow_type; -static PyTypeObject *LShift_type; -static PyTypeObject *RShift_type; -static PyTypeObject *BitOr_type; -static PyTypeObject *BitXor_type; -static PyTypeObject *BitAnd_type; -static PyTypeObject *FloorDiv_type; -static PyTypeObject *unaryop_type; -static PyObject *Invert_singleton, *Not_singleton, *UAdd_singleton, -*USub_singleton; -static PyObject* ast2obj_unaryop(unaryop_ty); -static PyTypeObject *Invert_type; -static PyTypeObject *Not_type; -static PyTypeObject *UAdd_type; -static PyTypeObject *USub_type; -static PyTypeObject *cmpop_type; -static PyObject *Eq_singleton, *NotEq_singleton, *Lt_singleton, *LtE_singleton, -*Gt_singleton, *GtE_singleton, *Is_singleton, *IsNot_singleton, *In_singleton, -*NotIn_singleton; -static PyObject* ast2obj_cmpop(cmpop_ty); -static PyTypeObject *Eq_type; -static PyTypeObject *NotEq_type; -static PyTypeObject *Lt_type; -static PyTypeObject *LtE_type; -static PyTypeObject *Gt_type; -static PyTypeObject *GtE_type; -static PyTypeObject *Is_type; -static PyTypeObject *IsNot_type; -static PyTypeObject *In_type; -static PyTypeObject *NotIn_type; -static PyTypeObject *comprehension_type; -static PyObject* ast2obj_comprehension(void*); -static char *comprehension_fields[]={ - "target", - "iter", - "ifs", -}; -static PyTypeObject *excepthandler_type; -static PyObject* ast2obj_excepthandler(void*); -static char *excepthandler_fields[]={ - "type", - "name", - "body", - "lineno", - "col_offset", -}; -static PyTypeObject *arguments_type; -static PyObject* ast2obj_arguments(void*); -static char *arguments_fields[]={ - "args", - "vararg", - "kwarg", - "defaults", -}; -static PyTypeObject *keyword_type; -static PyObject* ast2obj_keyword(void*); -static char *keyword_fields[]={ - "arg", - "value", -}; -static PyTypeObject *alias_type; -static PyObject* ast2obj_alias(void*); -static char *alias_fields[]={ - "name", - "asname", -}; - - -static PyTypeObject* make_type(char *type, PyTypeObject* base, char**fields, int num_fields) -{ - PyObject *fnames, *result; - int i; - if (num_fields) { - fnames = PyTuple_New(num_fields); - if (!fnames) return NULL; - } else { - fnames = Py_None; - Py_INCREF(Py_None); - } - for(i=0; i < num_fields; i++) { - PyObject *field = PyString_FromString(fields[i]); - if (!field) { - Py_DECREF(fnames); - return NULL; - } - PyTuple_SET_ITEM(fnames, i, field); - } - result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){sOss}", - type, base, "_fields", fnames, "__module__", "_ast"); - Py_DECREF(fnames); - return (PyTypeObject*)result; -} - -static int add_attributes(PyTypeObject* type, char**attrs, int num_fields) -{ - int i, result; - PyObject *s, *l = PyList_New(num_fields); - if (!l) return 0; - for(i = 0; i < num_fields; i++) { - s = PyString_FromString(attrs[i]); - if (!s) { - Py_DECREF(l); - return 0; - } - PyList_SET_ITEM(l, i, s); - } - result = PyObject_SetAttrString((PyObject*)type, "_attributes", l) >= 0; - Py_DECREF(l); - return result; -} - -static PyObject* ast2obj_list(asdl_seq *seq, PyObject* (*func)(void*)) -{ - int i, n = asdl_seq_LEN(seq); - PyObject *result = PyList_New(n); - PyObject *value; - if (!result) - return NULL; - for (i = 0; i < n; i++) { - value = func(asdl_seq_GET(seq, i)); - if (!value) { - Py_DECREF(result); - return NULL; - } - PyList_SET_ITEM(result, i, value); - } - return result; -} - -static PyObject* ast2obj_object(void *o) -{ - if (!o) - o = Py_None; - Py_INCREF((PyObject*)o); - return (PyObject*)o; -} -#define ast2obj_identifier ast2obj_object -#define ast2obj_string ast2obj_object -static PyObject* ast2obj_bool(bool b) -{ - return PyBool_FromLong(b); -} - -static PyObject* ast2obj_int(bool b) -{ - return PyInt_FromLong(b); -} - -static int init_types(void) -{ - static int initialized; - if (initialized) return 1; - AST_type = make_type("AST", &PyBaseObject_Type, NULL, 0); - mod_type = make_type("mod", AST_type, NULL, 0); - if (!mod_type) return 0; - if (!add_attributes(mod_type, NULL, 0)) return 0; - Module_type = make_type("Module", mod_type, Module_fields, 1); - if (!Module_type) return 0; - Interactive_type = make_type("Interactive", mod_type, - Interactive_fields, 1); - if (!Interactive_type) return 0; - Expression_type = make_type("Expression", mod_type, Expression_fields, - 1); - if (!Expression_type) return 0; - Suite_type = make_type("Suite", mod_type, Suite_fields, 1); - if (!Suite_type) return 0; - stmt_type = make_type("stmt", AST_type, NULL, 0); - if (!stmt_type) return 0; - if (!add_attributes(stmt_type, stmt_attributes, 2)) return 0; - FunctionDef_type = make_type("FunctionDef", stmt_type, - FunctionDef_fields, 4); - if (!FunctionDef_type) return 0; - ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 3); - if (!ClassDef_type) return 0; - Return_type = make_type("Return", stmt_type, Return_fields, 1); - if (!Return_type) return 0; - Delete_type = make_type("Delete", stmt_type, Delete_fields, 1); - if (!Delete_type) return 0; - Assign_type = make_type("Assign", stmt_type, Assign_fields, 2); - if (!Assign_type) return 0; - AugAssign_type = make_type("AugAssign", stmt_type, AugAssign_fields, 3); - if (!AugAssign_type) return 0; - Print_type = make_type("Print", stmt_type, Print_fields, 3); - if (!Print_type) return 0; - For_type = make_type("For", stmt_type, For_fields, 4); - if (!For_type) return 0; - While_type = make_type("While", stmt_type, While_fields, 3); - if (!While_type) return 0; - If_type = make_type("If", stmt_type, If_fields, 3); - if (!If_type) return 0; - With_type = make_type("With", stmt_type, With_fields, 3); - if (!With_type) return 0; - Raise_type = make_type("Raise", stmt_type, Raise_fields, 3); - if (!Raise_type) return 0; - TryExcept_type = make_type("TryExcept", stmt_type, TryExcept_fields, 3); - if (!TryExcept_type) return 0; - TryFinally_type = make_type("TryFinally", stmt_type, TryFinally_fields, - 2); - if (!TryFinally_type) return 0; - Assert_type = make_type("Assert", stmt_type, Assert_fields, 2); - if (!Assert_type) return 0; - Import_type = make_type("Import", stmt_type, Import_fields, 1); - if (!Import_type) return 0; - ImportFrom_type = make_type("ImportFrom", stmt_type, ImportFrom_fields, - 3); - if (!ImportFrom_type) return 0; - Exec_type = make_type("Exec", stmt_type, Exec_fields, 3); - if (!Exec_type) return 0; - Global_type = make_type("Global", stmt_type, Global_fields, 1); - if (!Global_type) return 0; - Expr_type = make_type("Expr", stmt_type, Expr_fields, 1); - if (!Expr_type) return 0; - Pass_type = make_type("Pass", stmt_type, NULL, 0); - if (!Pass_type) return 0; - Break_type = make_type("Break", stmt_type, NULL, 0); - if (!Break_type) return 0; - Continue_type = make_type("Continue", stmt_type, NULL, 0); - if (!Continue_type) return 0; - expr_type = make_type("expr", AST_type, NULL, 0); - if (!expr_type) return 0; - if (!add_attributes(expr_type, expr_attributes, 2)) return 0; - BoolOp_type = make_type("BoolOp", expr_type, BoolOp_fields, 2); - if (!BoolOp_type) return 0; - BinOp_type = make_type("BinOp", expr_type, BinOp_fields, 3); - if (!BinOp_type) return 0; - UnaryOp_type = make_type("UnaryOp", expr_type, UnaryOp_fields, 2); - if (!UnaryOp_type) return 0; - Lambda_type = make_type("Lambda", expr_type, Lambda_fields, 2); - if (!Lambda_type) return 0; - IfExp_type = make_type("IfExp", expr_type, IfExp_fields, 3); - if (!IfExp_type) return 0; - Dict_type = make_type("Dict", expr_type, Dict_fields, 2); - if (!Dict_type) return 0; - ListComp_type = make_type("ListComp", expr_type, ListComp_fields, 2); - if (!ListComp_type) return 0; - GeneratorExp_type = make_type("GeneratorExp", expr_type, - GeneratorExp_fields, 2); - if (!GeneratorExp_type) return 0; - Yield_type = make_type("Yield", expr_type, Yield_fields, 1); - if (!Yield_type) return 0; - Compare_type = make_type("Compare", expr_type, Compare_fields, 3); - if (!Compare_type) return 0; - Call_type = make_type("Call", expr_type, Call_fields, 5); - if (!Call_type) return 0; - Repr_type = make_type("Repr", expr_type, Repr_fields, 1); - if (!Repr_type) return 0; - Num_type = make_type("Num", expr_type, Num_fields, 1); - if (!Num_type) return 0; - Str_type = make_type("Str", expr_type, Str_fields, 1); - if (!Str_type) return 0; - Attribute_type = make_type("Attribute", expr_type, Attribute_fields, 3); - if (!Attribute_type) return 0; - Subscript_type = make_type("Subscript", expr_type, Subscript_fields, 3); - if (!Subscript_type) return 0; - Name_type = make_type("Name", expr_type, Name_fields, 2); - if (!Name_type) return 0; - List_type = make_type("List", expr_type, List_fields, 2); - if (!List_type) return 0; - Tuple_type = make_type("Tuple", expr_type, Tuple_fields, 2); - if (!Tuple_type) return 0; - expr_context_type = make_type("expr_context", AST_type, NULL, 0); - if (!expr_context_type) return 0; - if (!add_attributes(expr_context_type, NULL, 0)) return 0; - Load_type = make_type("Load", expr_context_type, NULL, 0); - if (!Load_type) return 0; - Load_singleton = PyType_GenericNew(Load_type, NULL, NULL); - if (!Load_singleton) return 0; - Store_type = make_type("Store", expr_context_type, NULL, 0); - if (!Store_type) return 0; - Store_singleton = PyType_GenericNew(Store_type, NULL, NULL); - if (!Store_singleton) return 0; - Del_type = make_type("Del", expr_context_type, NULL, 0); - if (!Del_type) return 0; - Del_singleton = PyType_GenericNew(Del_type, NULL, NULL); - if (!Del_singleton) return 0; - AugLoad_type = make_type("AugLoad", expr_context_type, NULL, 0); - if (!AugLoad_type) return 0; - AugLoad_singleton = PyType_GenericNew(AugLoad_type, NULL, NULL); - if (!AugLoad_singleton) return 0; - AugStore_type = make_type("AugStore", expr_context_type, NULL, 0); - if (!AugStore_type) return 0; - AugStore_singleton = PyType_GenericNew(AugStore_type, NULL, NULL); - if (!AugStore_singleton) return 0; - Param_type = make_type("Param", expr_context_type, NULL, 0); - if (!Param_type) return 0; - Param_singleton = PyType_GenericNew(Param_type, NULL, NULL); - if (!Param_singleton) return 0; - slice_type = make_type("slice", AST_type, NULL, 0); - if (!slice_type) return 0; - if (!add_attributes(slice_type, NULL, 0)) return 0; - Ellipsis_type = make_type("Ellipsis", slice_type, NULL, 0); - if (!Ellipsis_type) return 0; - Slice_type = make_type("Slice", slice_type, Slice_fields, 3); - if (!Slice_type) return 0; - ExtSlice_type = make_type("ExtSlice", slice_type, ExtSlice_fields, 1); - if (!ExtSlice_type) return 0; - Index_type = make_type("Index", slice_type, Index_fields, 1); - if (!Index_type) return 0; - boolop_type = make_type("boolop", AST_type, NULL, 0); - if (!boolop_type) return 0; - if (!add_attributes(boolop_type, NULL, 0)) return 0; - And_type = make_type("And", boolop_type, NULL, 0); - if (!And_type) return 0; - And_singleton = PyType_GenericNew(And_type, NULL, NULL); - if (!And_singleton) return 0; - Or_type = make_type("Or", boolop_type, NULL, 0); - if (!Or_type) return 0; - Or_singleton = PyType_GenericNew(Or_type, NULL, NULL); - if (!Or_singleton) return 0; - operator_type = make_type("operator", AST_type, NULL, 0); - if (!operator_type) return 0; - if (!add_attributes(operator_type, NULL, 0)) return 0; - Add_type = make_type("Add", operator_type, NULL, 0); - if (!Add_type) return 0; - Add_singleton = PyType_GenericNew(Add_type, NULL, NULL); - if (!Add_singleton) return 0; - Sub_type = make_type("Sub", operator_type, NULL, 0); - if (!Sub_type) return 0; - Sub_singleton = PyType_GenericNew(Sub_type, NULL, NULL); - if (!Sub_singleton) return 0; - Mult_type = make_type("Mult", operator_type, NULL, 0); - if (!Mult_type) return 0; - Mult_singleton = PyType_GenericNew(Mult_type, NULL, NULL); - if (!Mult_singleton) return 0; - Div_type = make_type("Div", operator_type, NULL, 0); - if (!Div_type) return 0; - Div_singleton = PyType_GenericNew(Div_type, NULL, NULL); - if (!Div_singleton) return 0; - Mod_type = make_type("Mod", operator_type, NULL, 0); - if (!Mod_type) return 0; - Mod_singleton = PyType_GenericNew(Mod_type, NULL, NULL); - if (!Mod_singleton) return 0; - Pow_type = make_type("Pow", operator_type, NULL, 0); - if (!Pow_type) return 0; - Pow_singleton = PyType_GenericNew(Pow_type, NULL, NULL); - if (!Pow_singleton) return 0; - LShift_type = make_type("LShift", operator_type, NULL, 0); - if (!LShift_type) return 0; - LShift_singleton = PyType_GenericNew(LShift_type, NULL, NULL); - if (!LShift_singleton) return 0; - RShift_type = make_type("RShift", operator_type, NULL, 0); - if (!RShift_type) return 0; - RShift_singleton = PyType_GenericNew(RShift_type, NULL, NULL); - if (!RShift_singleton) return 0; - BitOr_type = make_type("BitOr", operator_type, NULL, 0); - if (!BitOr_type) return 0; - BitOr_singleton = PyType_GenericNew(BitOr_type, NULL, NULL); - if (!BitOr_singleton) return 0; - BitXor_type = make_type("BitXor", operator_type, NULL, 0); - if (!BitXor_type) return 0; - BitXor_singleton = PyType_GenericNew(BitXor_type, NULL, NULL); - if (!BitXor_singleton) return 0; - BitAnd_type = make_type("BitAnd", operator_type, NULL, 0); - if (!BitAnd_type) return 0; - BitAnd_singleton = PyType_GenericNew(BitAnd_type, NULL, NULL); - if (!BitAnd_singleton) return 0; - FloorDiv_type = make_type("FloorDiv", operator_type, NULL, 0); - if (!FloorDiv_type) return 0; - FloorDiv_singleton = PyType_GenericNew(FloorDiv_type, NULL, NULL); - if (!FloorDiv_singleton) return 0; - unaryop_type = make_type("unaryop", AST_type, NULL, 0); - if (!unaryop_type) return 0; - if (!add_attributes(unaryop_type, NULL, 0)) return 0; - Invert_type = make_type("Invert", unaryop_type, NULL, 0); - if (!Invert_type) return 0; - Invert_singleton = PyType_GenericNew(Invert_type, NULL, NULL); - if (!Invert_singleton) return 0; - Not_type = make_type("Not", unaryop_type, NULL, 0); - if (!Not_type) return 0; - Not_singleton = PyType_GenericNew(Not_type, NULL, NULL); - if (!Not_singleton) return 0; - UAdd_type = make_type("UAdd", unaryop_type, NULL, 0); - if (!UAdd_type) return 0; - UAdd_singleton = PyType_GenericNew(UAdd_type, NULL, NULL); - if (!UAdd_singleton) return 0; - USub_type = make_type("USub", unaryop_type, NULL, 0); - if (!USub_type) return 0; - USub_singleton = PyType_GenericNew(USub_type, NULL, NULL); - if (!USub_singleton) return 0; - cmpop_type = make_type("cmpop", AST_type, NULL, 0); - if (!cmpop_type) return 0; - if (!add_attributes(cmpop_type, NULL, 0)) return 0; - Eq_type = make_type("Eq", cmpop_type, NULL, 0); - if (!Eq_type) return 0; - Eq_singleton = PyType_GenericNew(Eq_type, NULL, NULL); - if (!Eq_singleton) return 0; - NotEq_type = make_type("NotEq", cmpop_type, NULL, 0); - if (!NotEq_type) return 0; - NotEq_singleton = PyType_GenericNew(NotEq_type, NULL, NULL); - if (!NotEq_singleton) return 0; - Lt_type = make_type("Lt", cmpop_type, NULL, 0); - if (!Lt_type) return 0; - Lt_singleton = PyType_GenericNew(Lt_type, NULL, NULL); - if (!Lt_singleton) return 0; - LtE_type = make_type("LtE", cmpop_type, NULL, 0); - if (!LtE_type) return 0; - LtE_singleton = PyType_GenericNew(LtE_type, NULL, NULL); - if (!LtE_singleton) return 0; - Gt_type = make_type("Gt", cmpop_type, NULL, 0); - if (!Gt_type) return 0; - Gt_singleton = PyType_GenericNew(Gt_type, NULL, NULL); - if (!Gt_singleton) return 0; - GtE_type = make_type("GtE", cmpop_type, NULL, 0); - if (!GtE_type) return 0; - GtE_singleton = PyType_GenericNew(GtE_type, NULL, NULL); - if (!GtE_singleton) return 0; - Is_type = make_type("Is", cmpop_type, NULL, 0); - if (!Is_type) return 0; - Is_singleton = PyType_GenericNew(Is_type, NULL, NULL); - if (!Is_singleton) return 0; - IsNot_type = make_type("IsNot", cmpop_type, NULL, 0); - if (!IsNot_type) return 0; - IsNot_singleton = PyType_GenericNew(IsNot_type, NULL, NULL); - if (!IsNot_singleton) return 0; - In_type = make_type("In", cmpop_type, NULL, 0); - if (!In_type) return 0; - In_singleton = PyType_GenericNew(In_type, NULL, NULL); - if (!In_singleton) return 0; - NotIn_type = make_type("NotIn", cmpop_type, NULL, 0); - if (!NotIn_type) return 0; - NotIn_singleton = PyType_GenericNew(NotIn_type, NULL, NULL); - if (!NotIn_singleton) return 0; - comprehension_type = make_type("comprehension", AST_type, - comprehension_fields, 3); - if (!comprehension_type) return 0; - excepthandler_type = make_type("excepthandler", AST_type, - excepthandler_fields, 5); - if (!excepthandler_type) return 0; - arguments_type = make_type("arguments", AST_type, arguments_fields, 4); - if (!arguments_type) return 0; - keyword_type = make_type("keyword", AST_type, keyword_fields, 2); - if (!keyword_type) return 0; - alias_type = make_type("alias", AST_type, alias_fields, 2); - if (!alias_type) return 0; - initialized = 1; - return 1; -} - -mod_ty -Module(asdl_seq * body, PyArena *arena) -{ - mod_ty p; - p = (mod_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Module_kind; - p->v.Module.body = body; - return p; -} - -mod_ty -Interactive(asdl_seq * body, PyArena *arena) -{ - mod_ty p; - p = (mod_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Interactive_kind; - p->v.Interactive.body = body; - return p; -} - -mod_ty -Expression(expr_ty body, PyArena *arena) -{ - mod_ty p; - if (!body) { - PyErr_SetString(PyExc_ValueError, - "field body is required for Expression"); - return NULL; - } - p = (mod_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Expression_kind; - p->v.Expression.body = body; - return p; -} - -mod_ty -Suite(asdl_seq * body, PyArena *arena) -{ - mod_ty p; - p = (mod_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Suite_kind; - p->v.Suite.body = body; - return p; -} - -stmt_ty -FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq * - decorators, int lineno, int col_offset, PyArena *arena) -{ - stmt_ty p; - if (!name) { - PyErr_SetString(PyExc_ValueError, - "field name is required for FunctionDef"); - return NULL; - } - if (!args) { - PyErr_SetString(PyExc_ValueError, - "field args is required for FunctionDef"); - return NULL; - } - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = FunctionDef_kind; - p->v.FunctionDef.name = name; - p->v.FunctionDef.args = args; - p->v.FunctionDef.body = body; - p->v.FunctionDef.decorators = decorators; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -ClassDef(identifier name, asdl_seq * bases, asdl_seq * body, int lineno, int - col_offset, PyArena *arena) -{ - stmt_ty p; - if (!name) { - PyErr_SetString(PyExc_ValueError, - "field name is required for ClassDef"); - return NULL; - } - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = ClassDef_kind; - p->v.ClassDef.name = name; - p->v.ClassDef.bases = bases; - p->v.ClassDef.body = body; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -Return(expr_ty value, int lineno, int col_offset, PyArena *arena) -{ - stmt_ty p; - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Return_kind; - p->v.Return.value = value; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -Delete(asdl_seq * targets, int lineno, int col_offset, PyArena *arena) -{ - stmt_ty p; - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Delete_kind; - p->v.Delete.targets = targets; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -Assign(asdl_seq * targets, expr_ty value, int lineno, int col_offset, PyArena - *arena) -{ - stmt_ty p; - if (!value) { - PyErr_SetString(PyExc_ValueError, - "field value is required for Assign"); - return NULL; - } - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Assign_kind; - p->v.Assign.targets = targets; - p->v.Assign.value = value; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -AugAssign(expr_ty target, operator_ty op, expr_ty value, int lineno, int - col_offset, PyArena *arena) -{ - stmt_ty p; - if (!target) { - PyErr_SetString(PyExc_ValueError, - "field target is required for AugAssign"); - return NULL; - } - if (!op) { - PyErr_SetString(PyExc_ValueError, - "field op is required for AugAssign"); - return NULL; - } - if (!value) { - PyErr_SetString(PyExc_ValueError, - "field value is required for AugAssign"); - return NULL; - } - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = AugAssign_kind; - p->v.AugAssign.target = target; - p->v.AugAssign.op = op; - p->v.AugAssign.value = value; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -Print(expr_ty dest, asdl_seq * values, bool nl, int lineno, int col_offset, - PyArena *arena) -{ - stmt_ty p; - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Print_kind; - p->v.Print.dest = dest; - p->v.Print.values = values; - p->v.Print.nl = nl; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -For(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse, int - lineno, int col_offset, PyArena *arena) -{ - stmt_ty p; - if (!target) { - PyErr_SetString(PyExc_ValueError, - "field target is required for For"); - return NULL; - } - if (!iter) { - PyErr_SetString(PyExc_ValueError, - "field iter is required for For"); - return NULL; - } - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = For_kind; - p->v.For.target = target; - p->v.For.iter = iter; - p->v.For.body = body; - p->v.For.orelse = orelse; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -While(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, int - col_offset, PyArena *arena) -{ - stmt_ty p; - if (!test) { - PyErr_SetString(PyExc_ValueError, - "field test is required for While"); - return NULL; - } - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = While_kind; - p->v.While.test = test; - p->v.While.body = body; - p->v.While.orelse = orelse; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -If(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, int - col_offset, PyArena *arena) -{ - stmt_ty p; - if (!test) { - PyErr_SetString(PyExc_ValueError, - "field test is required for If"); - return NULL; - } - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = If_kind; - p->v.If.test = test; - p->v.If.body = body; - p->v.If.orelse = orelse; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -With(expr_ty context_expr, expr_ty optional_vars, asdl_seq * body, int lineno, - int col_offset, PyArena *arena) -{ - stmt_ty p; - if (!context_expr) { - PyErr_SetString(PyExc_ValueError, - "field context_expr is required for With"); - return NULL; - } - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = With_kind; - p->v.With.context_expr = context_expr; - p->v.With.optional_vars = optional_vars; - p->v.With.body = body; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -Raise(expr_ty type, expr_ty inst, expr_ty tback, int lineno, int col_offset, - PyArena *arena) -{ - stmt_ty p; - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Raise_kind; - p->v.Raise.type = type; - p->v.Raise.inst = inst; - p->v.Raise.tback = tback; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -TryExcept(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse, int lineno, - int col_offset, PyArena *arena) -{ - stmt_ty p; - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = TryExcept_kind; - p->v.TryExcept.body = body; - p->v.TryExcept.handlers = handlers; - p->v.TryExcept.orelse = orelse; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -TryFinally(asdl_seq * body, asdl_seq * finalbody, int lineno, int col_offset, - PyArena *arena) -{ - stmt_ty p; - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = TryFinally_kind; - p->v.TryFinally.body = body; - p->v.TryFinally.finalbody = finalbody; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -Assert(expr_ty test, expr_ty msg, int lineno, int col_offset, PyArena *arena) -{ - stmt_ty p; - if (!test) { - PyErr_SetString(PyExc_ValueError, - "field test is required for Assert"); - return NULL; - } - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Assert_kind; - p->v.Assert.test = test; - p->v.Assert.msg = msg; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -Import(asdl_seq * names, int lineno, int col_offset, PyArena *arena) -{ - stmt_ty p; - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Import_kind; - p->v.Import.names = names; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -ImportFrom(identifier module, asdl_seq * names, int level, int lineno, int - col_offset, PyArena *arena) -{ - stmt_ty p; - if (!module) { - PyErr_SetString(PyExc_ValueError, - "field module is required for ImportFrom"); - return NULL; - } - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = ImportFrom_kind; - p->v.ImportFrom.module = module; - p->v.ImportFrom.names = names; - p->v.ImportFrom.level = level; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -Exec(expr_ty body, expr_ty globals, expr_ty locals, int lineno, int col_offset, - PyArena *arena) -{ - stmt_ty p; - if (!body) { - PyErr_SetString(PyExc_ValueError, - "field body is required for Exec"); - return NULL; - } - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Exec_kind; - p->v.Exec.body = body; - p->v.Exec.globals = globals; - p->v.Exec.locals = locals; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -Global(asdl_seq * names, int lineno, int col_offset, PyArena *arena) -{ - stmt_ty p; - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Global_kind; - p->v.Global.names = names; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -Expr(expr_ty value, int lineno, int col_offset, PyArena *arena) -{ - stmt_ty p; - if (!value) { - PyErr_SetString(PyExc_ValueError, - "field value is required for Expr"); - return NULL; - } - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Expr_kind; - p->v.Expr.value = value; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -Pass(int lineno, int col_offset, PyArena *arena) -{ - stmt_ty p; - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Pass_kind; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -Break(int lineno, int col_offset, PyArena *arena) -{ - stmt_ty p; - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Break_kind; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -Continue(int lineno, int col_offset, PyArena *arena) -{ - stmt_ty p; - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Continue_kind; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -BoolOp(boolop_ty op, asdl_seq * values, int lineno, int col_offset, PyArena - *arena) -{ - expr_ty p; - if (!op) { - PyErr_SetString(PyExc_ValueError, - "field op is required for BoolOp"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = BoolOp_kind; - p->v.BoolOp.op = op; - p->v.BoolOp.values = values; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -BinOp(expr_ty left, operator_ty op, expr_ty right, int lineno, int col_offset, - PyArena *arena) -{ - expr_ty p; - if (!left) { - PyErr_SetString(PyExc_ValueError, - "field left is required for BinOp"); - return NULL; - } - if (!op) { - PyErr_SetString(PyExc_ValueError, - "field op is required for BinOp"); - return NULL; - } - if (!right) { - PyErr_SetString(PyExc_ValueError, - "field right is required for BinOp"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = BinOp_kind; - p->v.BinOp.left = left; - p->v.BinOp.op = op; - p->v.BinOp.right = right; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -UnaryOp(unaryop_ty op, expr_ty operand, int lineno, int col_offset, PyArena - *arena) -{ - expr_ty p; - if (!op) { - PyErr_SetString(PyExc_ValueError, - "field op is required for UnaryOp"); - return NULL; - } - if (!operand) { - PyErr_SetString(PyExc_ValueError, - "field operand is required for UnaryOp"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = UnaryOp_kind; - p->v.UnaryOp.op = op; - p->v.UnaryOp.operand = operand; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -Lambda(arguments_ty args, expr_ty body, int lineno, int col_offset, PyArena - *arena) -{ - expr_ty p; - if (!args) { - PyErr_SetString(PyExc_ValueError, - "field args is required for Lambda"); - return NULL; - } - if (!body) { - PyErr_SetString(PyExc_ValueError, - "field body is required for Lambda"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Lambda_kind; - p->v.Lambda.args = args; - p->v.Lambda.body = body; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -IfExp(expr_ty test, expr_ty body, expr_ty orelse, int lineno, int col_offset, - PyArena *arena) -{ - expr_ty p; - if (!test) { - PyErr_SetString(PyExc_ValueError, - "field test is required for IfExp"); - return NULL; - } - if (!body) { - PyErr_SetString(PyExc_ValueError, - "field body is required for IfExp"); - return NULL; - } - if (!orelse) { - PyErr_SetString(PyExc_ValueError, - "field orelse is required for IfExp"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = IfExp_kind; - p->v.IfExp.test = test; - p->v.IfExp.body = body; - p->v.IfExp.orelse = orelse; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -Dict(asdl_seq * keys, asdl_seq * values, int lineno, int col_offset, PyArena - *arena) -{ - expr_ty p; - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Dict_kind; - p->v.Dict.keys = keys; - p->v.Dict.values = values; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -ListComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, - PyArena *arena) -{ - expr_ty p; - if (!elt) { - PyErr_SetString(PyExc_ValueError, - "field elt is required for ListComp"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = ListComp_kind; - p->v.ListComp.elt = elt; - p->v.ListComp.generators = generators; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, - PyArena *arena) -{ - expr_ty p; - if (!elt) { - PyErr_SetString(PyExc_ValueError, - "field elt is required for GeneratorExp"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = GeneratorExp_kind; - p->v.GeneratorExp.elt = elt; - p->v.GeneratorExp.generators = generators; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -Yield(expr_ty value, int lineno, int col_offset, PyArena *arena) -{ - expr_ty p; - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Yield_kind; - p->v.Yield.value = value; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators, int lineno, - int col_offset, PyArena *arena) -{ - expr_ty p; - if (!left) { - PyErr_SetString(PyExc_ValueError, - "field left is required for Compare"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Compare_kind; - p->v.Compare.left = left; - p->v.Compare.ops = ops; - p->v.Compare.comparators = comparators; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, expr_ty starargs, - expr_ty kwargs, int lineno, int col_offset, PyArena *arena) -{ - expr_ty p; - if (!func) { - PyErr_SetString(PyExc_ValueError, - "field func is required for Call"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Call_kind; - p->v.Call.func = func; - p->v.Call.args = args; - p->v.Call.keywords = keywords; - p->v.Call.starargs = starargs; - p->v.Call.kwargs = kwargs; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -Repr(expr_ty value, int lineno, int col_offset, PyArena *arena) -{ - expr_ty p; - if (!value) { - PyErr_SetString(PyExc_ValueError, - "field value is required for Repr"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Repr_kind; - p->v.Repr.value = value; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -Num(object n, int lineno, int col_offset, PyArena *arena) -{ - expr_ty p; - if (!n) { - PyErr_SetString(PyExc_ValueError, - "field n is required for Num"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Num_kind; - p->v.Num.n = n; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -Str(string s, int lineno, int col_offset, PyArena *arena) -{ - expr_ty p; - if (!s) { - PyErr_SetString(PyExc_ValueError, - "field s is required for Str"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Str_kind; - p->v.Str.s = s; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -Attribute(expr_ty value, identifier attr, expr_context_ty ctx, int lineno, int - col_offset, PyArena *arena) -{ - expr_ty p; - if (!value) { - PyErr_SetString(PyExc_ValueError, - "field value is required for Attribute"); - return NULL; - } - if (!attr) { - PyErr_SetString(PyExc_ValueError, - "field attr is required for Attribute"); - return NULL; - } - if (!ctx) { - PyErr_SetString(PyExc_ValueError, - "field ctx is required for Attribute"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Attribute_kind; - p->v.Attribute.value = value; - p->v.Attribute.attr = attr; - p->v.Attribute.ctx = ctx; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -Subscript(expr_ty value, slice_ty slice, expr_context_ty ctx, int lineno, int - col_offset, PyArena *arena) -{ - expr_ty p; - if (!value) { - PyErr_SetString(PyExc_ValueError, - "field value is required for Subscript"); - return NULL; - } - if (!slice) { - PyErr_SetString(PyExc_ValueError, - "field slice is required for Subscript"); - return NULL; - } - if (!ctx) { - PyErr_SetString(PyExc_ValueError, - "field ctx is required for Subscript"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Subscript_kind; - p->v.Subscript.value = value; - p->v.Subscript.slice = slice; - p->v.Subscript.ctx = ctx; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -Name(identifier id, expr_context_ty ctx, int lineno, int col_offset, PyArena - *arena) -{ - expr_ty p; - if (!id) { - PyErr_SetString(PyExc_ValueError, - "field id is required for Name"); - return NULL; - } - if (!ctx) { - PyErr_SetString(PyExc_ValueError, - "field ctx is required for Name"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Name_kind; - p->v.Name.id = id; - p->v.Name.ctx = ctx; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -List(asdl_seq * elts, expr_context_ty ctx, int lineno, int col_offset, PyArena - *arena) -{ - expr_ty p; - if (!ctx) { - PyErr_SetString(PyExc_ValueError, - "field ctx is required for List"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = List_kind; - p->v.List.elts = elts; - p->v.List.ctx = ctx; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -expr_ty -Tuple(asdl_seq * elts, expr_context_ty ctx, int lineno, int col_offset, PyArena - *arena) -{ - expr_ty p; - if (!ctx) { - PyErr_SetString(PyExc_ValueError, - "field ctx is required for Tuple"); - return NULL; - } - p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Tuple_kind; - p->v.Tuple.elts = elts; - p->v.Tuple.ctx = ctx; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -slice_ty -Ellipsis(PyArena *arena) -{ - slice_ty p; - p = (slice_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Ellipsis_kind; - return p; -} - -slice_ty -Slice(expr_ty lower, expr_ty upper, expr_ty step, PyArena *arena) -{ - slice_ty p; - p = (slice_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Slice_kind; - p->v.Slice.lower = lower; - p->v.Slice.upper = upper; - p->v.Slice.step = step; - return p; -} - -slice_ty -ExtSlice(asdl_seq * dims, PyArena *arena) -{ - slice_ty p; - p = (slice_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = ExtSlice_kind; - p->v.ExtSlice.dims = dims; - return p; -} - -slice_ty -Index(expr_ty value, PyArena *arena) -{ - slice_ty p; - if (!value) { - PyErr_SetString(PyExc_ValueError, - "field value is required for Index"); - return NULL; - } - p = (slice_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->kind = Index_kind; - p->v.Index.value = value; - return p; -} - -comprehension_ty -comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs, PyArena *arena) -{ - comprehension_ty p; - if (!target) { - PyErr_SetString(PyExc_ValueError, - "field target is required for comprehension"); - return NULL; - } - if (!iter) { - PyErr_SetString(PyExc_ValueError, - "field iter is required for comprehension"); - return NULL; - } - p = (comprehension_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->target = target; - p->iter = iter; - p->ifs = ifs; - return p; -} - -excepthandler_ty -excepthandler(expr_ty type, expr_ty name, asdl_seq * body, int lineno, int - col_offset, PyArena *arena) -{ - excepthandler_ty p; - p = (excepthandler_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->type = type; - p->name = name; - p->body = body; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -arguments_ty -arguments(asdl_seq * args, identifier vararg, identifier kwarg, asdl_seq * - defaults, PyArena *arena) -{ - arguments_ty p; - p = (arguments_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->args = args; - p->vararg = vararg; - p->kwarg = kwarg; - p->defaults = defaults; - return p; -} - -keyword_ty -keyword(identifier arg, expr_ty value, PyArena *arena) -{ - keyword_ty p; - if (!arg) { - PyErr_SetString(PyExc_ValueError, - "field arg is required for keyword"); - return NULL; - } - if (!value) { - PyErr_SetString(PyExc_ValueError, - "field value is required for keyword"); - return NULL; - } - p = (keyword_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->arg = arg; - p->value = value; - return p; -} - -alias_ty -alias(identifier name, identifier asname, PyArena *arena) -{ - alias_ty p; - if (!name) { - PyErr_SetString(PyExc_ValueError, - "field name is required for alias"); - return NULL; - } - p = (alias_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) { - PyErr_NoMemory(); - return NULL; - } - p->name = name; - p->asname = asname; - return p; -} - - -PyObject* -ast2obj_mod(void* _o) -{ - mod_ty o = (mod_ty)_o; - PyObject *result = NULL, *value = NULL; - if (!o) { - Py_INCREF(Py_None); - return Py_None; - } - - switch (o->kind) { - case Module_kind: - result = PyType_GenericNew(Module_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_list(o->v.Module.body, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Interactive_kind: - result = PyType_GenericNew(Interactive_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_list(o->v.Interactive.body, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Expression_kind: - result = PyType_GenericNew(Expression_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.Expression.body); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Suite_kind: - result = PyType_GenericNew(Suite_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_list(o->v.Suite.body, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - break; - } - return result; -failed: - Py_XDECREF(value); - Py_XDECREF(result); - return NULL; -} - -PyObject* -ast2obj_stmt(void* _o) -{ - stmt_ty o = (stmt_ty)_o; - PyObject *result = NULL, *value = NULL; - if (!o) { - Py_INCREF(Py_None); - return Py_None; - } - - switch (o->kind) { - case FunctionDef_kind: - result = PyType_GenericNew(FunctionDef_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_identifier(o->v.FunctionDef.name); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "name", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_arguments(o->v.FunctionDef.args); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "args", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.FunctionDef.body, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.FunctionDef.decorators, ast2obj_expr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "decorators", value) == -1) - goto failed; - Py_DECREF(value); - break; - case ClassDef_kind: - result = PyType_GenericNew(ClassDef_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_identifier(o->v.ClassDef.name); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "name", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.ClassDef.bases, ast2obj_expr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "bases", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.ClassDef.body, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Return_kind: - result = PyType_GenericNew(Return_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.Return.value); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Delete_kind: - result = PyType_GenericNew(Delete_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_list(o->v.Delete.targets, ast2obj_expr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "targets", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Assign_kind: - result = PyType_GenericNew(Assign_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_list(o->v.Assign.targets, ast2obj_expr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "targets", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.Assign.value); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) - goto failed; - Py_DECREF(value); - break; - case AugAssign_kind: - result = PyType_GenericNew(AugAssign_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.AugAssign.target); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "target", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_operator(o->v.AugAssign.op); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "op", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.AugAssign.value); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Print_kind: - result = PyType_GenericNew(Print_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.Print.dest); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "dest", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.Print.values, ast2obj_expr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "values", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_bool(o->v.Print.nl); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "nl", value) == -1) - goto failed; - Py_DECREF(value); - break; - case For_kind: - result = PyType_GenericNew(For_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.For.target); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "target", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.For.iter); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "iter", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.For.body, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.For.orelse, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "orelse", value) == -1) - goto failed; - Py_DECREF(value); - break; - case While_kind: - result = PyType_GenericNew(While_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.While.test); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "test", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.While.body, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.While.orelse, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "orelse", value) == -1) - goto failed; - Py_DECREF(value); - break; - case If_kind: - result = PyType_GenericNew(If_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.If.test); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "test", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.If.body, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.If.orelse, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "orelse", value) == -1) - goto failed; - Py_DECREF(value); - break; - case With_kind: - result = PyType_GenericNew(With_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.With.context_expr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "context_expr", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.With.optional_vars); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "optional_vars", value) == - -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.With.body, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Raise_kind: - result = PyType_GenericNew(Raise_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.Raise.type); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "type", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.Raise.inst); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "inst", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.Raise.tback); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "tback", value) == -1) - goto failed; - Py_DECREF(value); - break; - case TryExcept_kind: - result = PyType_GenericNew(TryExcept_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_list(o->v.TryExcept.body, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.TryExcept.handlers, - ast2obj_excepthandler); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "handlers", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.TryExcept.orelse, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "orelse", value) == -1) - goto failed; - Py_DECREF(value); - break; - case TryFinally_kind: - result = PyType_GenericNew(TryFinally_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_list(o->v.TryFinally.body, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.TryFinally.finalbody, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "finalbody", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Assert_kind: - result = PyType_GenericNew(Assert_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.Assert.test); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "test", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.Assert.msg); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "msg", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Import_kind: - result = PyType_GenericNew(Import_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_list(o->v.Import.names, ast2obj_alias); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "names", value) == -1) - goto failed; - Py_DECREF(value); - break; - case ImportFrom_kind: - result = PyType_GenericNew(ImportFrom_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_identifier(o->v.ImportFrom.module); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "module", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.ImportFrom.names, ast2obj_alias); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "names", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_int(o->v.ImportFrom.level); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "level", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Exec_kind: - result = PyType_GenericNew(Exec_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.Exec.body); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.Exec.globals); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "globals", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.Exec.locals); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "locals", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Global_kind: - result = PyType_GenericNew(Global_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_list(o->v.Global.names, ast2obj_identifier); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "names", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Expr_kind: - result = PyType_GenericNew(Expr_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.Expr.value); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Pass_kind: - result = PyType_GenericNew(Pass_type, NULL, NULL); - if (!result) goto failed; - break; - case Break_kind: - result = PyType_GenericNew(Break_type, NULL, NULL); - if (!result) goto failed; - break; - case Continue_kind: - result = PyType_GenericNew(Continue_type, NULL, NULL); - if (!result) goto failed; - break; - } - value = ast2obj_int(o->lineno); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "lineno", value) < 0) - goto failed; - Py_DECREF(value); - value = ast2obj_int(o->col_offset); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "col_offset", value) < 0) - goto failed; - Py_DECREF(value); - return result; -failed: - Py_XDECREF(value); - Py_XDECREF(result); - return NULL; -} - -PyObject* -ast2obj_expr(void* _o) -{ - expr_ty o = (expr_ty)_o; - PyObject *result = NULL, *value = NULL; - if (!o) { - Py_INCREF(Py_None); - return Py_None; - } - - switch (o->kind) { - case BoolOp_kind: - result = PyType_GenericNew(BoolOp_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_boolop(o->v.BoolOp.op); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "op", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.BoolOp.values, ast2obj_expr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "values", value) == -1) - goto failed; - Py_DECREF(value); - break; - case BinOp_kind: - result = PyType_GenericNew(BinOp_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.BinOp.left); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "left", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_operator(o->v.BinOp.op); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "op", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.BinOp.right); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "right", value) == -1) - goto failed; - Py_DECREF(value); - break; - case UnaryOp_kind: - result = PyType_GenericNew(UnaryOp_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_unaryop(o->v.UnaryOp.op); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "op", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.UnaryOp.operand); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "operand", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Lambda_kind: - result = PyType_GenericNew(Lambda_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_arguments(o->v.Lambda.args); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "args", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.Lambda.body); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - break; - case IfExp_kind: - result = PyType_GenericNew(IfExp_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.IfExp.test); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "test", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.IfExp.body); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.IfExp.orelse); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "orelse", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Dict_kind: - result = PyType_GenericNew(Dict_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_list(o->v.Dict.keys, ast2obj_expr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "keys", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.Dict.values, ast2obj_expr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "values", value) == -1) - goto failed; - Py_DECREF(value); - break; - case ListComp_kind: - result = PyType_GenericNew(ListComp_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.ListComp.elt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "elt", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.ListComp.generators, - ast2obj_comprehension); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "generators", value) == -1) - goto failed; - Py_DECREF(value); - break; - case GeneratorExp_kind: - result = PyType_GenericNew(GeneratorExp_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.GeneratorExp.elt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "elt", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.GeneratorExp.generators, - ast2obj_comprehension); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "generators", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Yield_kind: - result = PyType_GenericNew(Yield_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.Yield.value); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Compare_kind: - result = PyType_GenericNew(Compare_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.Compare.left); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "left", value) == -1) - goto failed; - Py_DECREF(value); - { - int i, n = asdl_seq_LEN(o->v.Compare.ops); - value = PyList_New(n); - if (!value) goto failed; - for(i = 0; i < n; i++) - PyList_SET_ITEM(value, i, ast2obj_cmpop((cmpop_ty)asdl_seq_GET(o->v.Compare.ops, i))); - } - if (!value) goto failed; - if (PyObject_SetAttrString(result, "ops", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.Compare.comparators, ast2obj_expr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "comparators", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Call_kind: - result = PyType_GenericNew(Call_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.Call.func); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "func", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.Call.args, ast2obj_expr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "args", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.Call.keywords, ast2obj_keyword); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "keywords", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.Call.starargs); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "starargs", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.Call.kwargs); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "kwargs", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Repr_kind: - result = PyType_GenericNew(Repr_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.Repr.value); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Num_kind: - result = PyType_GenericNew(Num_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_object(o->v.Num.n); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "n", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Str_kind: - result = PyType_GenericNew(Str_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_string(o->v.Str.s); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "s", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Attribute_kind: - result = PyType_GenericNew(Attribute_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.Attribute.value); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_identifier(o->v.Attribute.attr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "attr", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr_context(o->v.Attribute.ctx); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "ctx", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Subscript_kind: - result = PyType_GenericNew(Subscript_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.Subscript.value); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_slice(o->v.Subscript.slice); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "slice", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr_context(o->v.Subscript.ctx); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "ctx", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Name_kind: - result = PyType_GenericNew(Name_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_identifier(o->v.Name.id); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "id", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr_context(o->v.Name.ctx); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "ctx", value) == -1) - goto failed; - Py_DECREF(value); - break; - case List_kind: - result = PyType_GenericNew(List_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_list(o->v.List.elts, ast2obj_expr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "elts", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr_context(o->v.List.ctx); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "ctx", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Tuple_kind: - result = PyType_GenericNew(Tuple_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_list(o->v.Tuple.elts, ast2obj_expr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "elts", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr_context(o->v.Tuple.ctx); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "ctx", value) == -1) - goto failed; - Py_DECREF(value); - break; - } - value = ast2obj_int(o->lineno); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "lineno", value) < 0) - goto failed; - Py_DECREF(value); - value = ast2obj_int(o->col_offset); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "col_offset", value) < 0) - goto failed; - Py_DECREF(value); - return result; -failed: - Py_XDECREF(value); - Py_XDECREF(result); - return NULL; -} - -PyObject* ast2obj_expr_context(expr_context_ty o) -{ - switch(o) { - case Load: - Py_INCREF(Load_singleton); - return Load_singleton; - case Store: - Py_INCREF(Store_singleton); - return Store_singleton; - case Del: - Py_INCREF(Del_singleton); - return Del_singleton; - case AugLoad: - Py_INCREF(AugLoad_singleton); - return AugLoad_singleton; - case AugStore: - Py_INCREF(AugStore_singleton); - return AugStore_singleton; - case Param: - Py_INCREF(Param_singleton); - return Param_singleton; - } - return NULL; /* cannot happen */ -} -PyObject* -ast2obj_slice(void* _o) -{ - slice_ty o = (slice_ty)_o; - PyObject *result = NULL, *value = NULL; - if (!o) { - Py_INCREF(Py_None); - return Py_None; - } - - switch (o->kind) { - case Ellipsis_kind: - result = PyType_GenericNew(Ellipsis_type, NULL, NULL); - if (!result) goto failed; - break; - case Slice_kind: - result = PyType_GenericNew(Slice_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.Slice.lower); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "lower", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.Slice.upper); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "upper", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.Slice.step); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "step", value) == -1) - goto failed; - Py_DECREF(value); - break; - case ExtSlice_kind: - result = PyType_GenericNew(ExtSlice_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_list(o->v.ExtSlice.dims, ast2obj_slice); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "dims", value) == -1) - goto failed; - Py_DECREF(value); - break; - case Index_kind: - result = PyType_GenericNew(Index_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_expr(o->v.Index.value); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) - goto failed; - Py_DECREF(value); - break; - } - return result; -failed: - Py_XDECREF(value); - Py_XDECREF(result); - return NULL; -} - -PyObject* ast2obj_boolop(boolop_ty o) -{ - switch(o) { - case And: - Py_INCREF(And_singleton); - return And_singleton; - case Or: - Py_INCREF(Or_singleton); - return Or_singleton; - } - return NULL; /* cannot happen */ -} -PyObject* ast2obj_operator(operator_ty o) -{ - switch(o) { - case Add: - Py_INCREF(Add_singleton); - return Add_singleton; - case Sub: - Py_INCREF(Sub_singleton); - return Sub_singleton; - case Mult: - Py_INCREF(Mult_singleton); - return Mult_singleton; - case Div: - Py_INCREF(Div_singleton); - return Div_singleton; - case Mod: - Py_INCREF(Mod_singleton); - return Mod_singleton; - case Pow: - Py_INCREF(Pow_singleton); - return Pow_singleton; - case LShift: - Py_INCREF(LShift_singleton); - return LShift_singleton; - case RShift: - Py_INCREF(RShift_singleton); - return RShift_singleton; - case BitOr: - Py_INCREF(BitOr_singleton); - return BitOr_singleton; - case BitXor: - Py_INCREF(BitXor_singleton); - return BitXor_singleton; - case BitAnd: - Py_INCREF(BitAnd_singleton); - return BitAnd_singleton; - case FloorDiv: - Py_INCREF(FloorDiv_singleton); - return FloorDiv_singleton; - } - return NULL; /* cannot happen */ -} -PyObject* ast2obj_unaryop(unaryop_ty o) -{ - switch(o) { - case Invert: - Py_INCREF(Invert_singleton); - return Invert_singleton; - case Not: - Py_INCREF(Not_singleton); - return Not_singleton; - case UAdd: - Py_INCREF(UAdd_singleton); - return UAdd_singleton; - case USub: - Py_INCREF(USub_singleton); - return USub_singleton; - } - return NULL; /* cannot happen */ -} -PyObject* ast2obj_cmpop(cmpop_ty o) -{ - switch(o) { - case Eq: - Py_INCREF(Eq_singleton); - return Eq_singleton; - case NotEq: - Py_INCREF(NotEq_singleton); - return NotEq_singleton; - case Lt: - Py_INCREF(Lt_singleton); - return Lt_singleton; - case LtE: - Py_INCREF(LtE_singleton); - return LtE_singleton; - case Gt: - Py_INCREF(Gt_singleton); - return Gt_singleton; - case GtE: - Py_INCREF(GtE_singleton); - return GtE_singleton; - case Is: - Py_INCREF(Is_singleton); - return Is_singleton; - case IsNot: - Py_INCREF(IsNot_singleton); - return IsNot_singleton; - case In: - Py_INCREF(In_singleton); - return In_singleton; - case NotIn: - Py_INCREF(NotIn_singleton); - return NotIn_singleton; - } - return NULL; /* cannot happen */ -} -PyObject* -ast2obj_comprehension(void* _o) -{ - comprehension_ty o = (comprehension_ty)_o; - PyObject *result = NULL, *value = NULL; - if (!o) { - Py_INCREF(Py_None); - return Py_None; - } - - result = PyType_GenericNew(comprehension_type, NULL, NULL); - if (!result) return NULL; - value = ast2obj_expr(o->target); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "target", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->iter); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "iter", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->ifs, ast2obj_expr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "ifs", value) == -1) - goto failed; - Py_DECREF(value); - return result; -failed: - Py_XDECREF(value); - Py_XDECREF(result); - return NULL; -} - -PyObject* -ast2obj_excepthandler(void* _o) -{ - excepthandler_ty o = (excepthandler_ty)_o; - PyObject *result = NULL, *value = NULL; - if (!o) { - Py_INCREF(Py_None); - return Py_None; - } - - result = PyType_GenericNew(excepthandler_type, NULL, NULL); - if (!result) return NULL; - value = ast2obj_expr(o->type); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "type", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->name); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "name", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->body, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_int(o->lineno); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "lineno", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_int(o->col_offset); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "col_offset", value) == -1) - goto failed; - Py_DECREF(value); - return result; -failed: - Py_XDECREF(value); - Py_XDECREF(result); - return NULL; -} - -PyObject* -ast2obj_arguments(void* _o) -{ - arguments_ty o = (arguments_ty)_o; - PyObject *result = NULL, *value = NULL; - if (!o) { - Py_INCREF(Py_None); - return Py_None; - } - - result = PyType_GenericNew(arguments_type, NULL, NULL); - if (!result) return NULL; - value = ast2obj_list(o->args, ast2obj_expr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "args", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_identifier(o->vararg); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "vararg", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_identifier(o->kwarg); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "kwarg", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->defaults, ast2obj_expr); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "defaults", value) == -1) - goto failed; - Py_DECREF(value); - return result; -failed: - Py_XDECREF(value); - Py_XDECREF(result); - return NULL; -} - -PyObject* -ast2obj_keyword(void* _o) -{ - keyword_ty o = (keyword_ty)_o; - PyObject *result = NULL, *value = NULL; - if (!o) { - Py_INCREF(Py_None); - return Py_None; - } - - result = PyType_GenericNew(keyword_type, NULL, NULL); - if (!result) return NULL; - value = ast2obj_identifier(o->arg); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "arg", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->value); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) - goto failed; - Py_DECREF(value); - return result; -failed: - Py_XDECREF(value); - Py_XDECREF(result); - return NULL; -} - -PyObject* -ast2obj_alias(void* _o) -{ - alias_ty o = (alias_ty)_o; - PyObject *result = NULL, *value = NULL; - if (!o) { - Py_INCREF(Py_None); - return Py_None; - } - - result = PyType_GenericNew(alias_type, NULL, NULL); - if (!result) return NULL; - value = ast2obj_identifier(o->name); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "name", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_identifier(o->asname); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "asname", value) == -1) - goto failed; - Py_DECREF(value); - return result; -failed: - Py_XDECREF(value); - Py_XDECREF(result); - return NULL; -} - - -PyMODINIT_FUNC -init_ast(void) -{ - PyObject *m, *d; - if (!init_types()) return; - m = Py_InitModule3("_ast", NULL, NULL); - if (!m) return; - d = PyModule_GetDict(m); - if (PyDict_SetItemString(d, "AST", (PyObject*)AST_type) < 0) return; - if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) - return; - if (PyModule_AddStringConstant(m, "__version__", "43614") < 0) - return; - if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return; - if (PyDict_SetItemString(d, "Module", (PyObject*)Module_type) < 0) - return; - if (PyDict_SetItemString(d, "Interactive", (PyObject*)Interactive_type) - < 0) return; - if (PyDict_SetItemString(d, "Expression", (PyObject*)Expression_type) < - 0) return; - if (PyDict_SetItemString(d, "Suite", (PyObject*)Suite_type) < 0) return; - if (PyDict_SetItemString(d, "stmt", (PyObject*)stmt_type) < 0) return; - if (PyDict_SetItemString(d, "FunctionDef", (PyObject*)FunctionDef_type) - < 0) return; - if (PyDict_SetItemString(d, "ClassDef", (PyObject*)ClassDef_type) < 0) - return; - if (PyDict_SetItemString(d, "Return", (PyObject*)Return_type) < 0) - return; - if (PyDict_SetItemString(d, "Delete", (PyObject*)Delete_type) < 0) - return; - if (PyDict_SetItemString(d, "Assign", (PyObject*)Assign_type) < 0) - return; - if (PyDict_SetItemString(d, "AugAssign", (PyObject*)AugAssign_type) < - 0) return; - if (PyDict_SetItemString(d, "Print", (PyObject*)Print_type) < 0) return; - if (PyDict_SetItemString(d, "For", (PyObject*)For_type) < 0) return; - if (PyDict_SetItemString(d, "While", (PyObject*)While_type) < 0) return; - if (PyDict_SetItemString(d, "If", (PyObject*)If_type) < 0) return; - if (PyDict_SetItemString(d, "With", (PyObject*)With_type) < 0) return; - if (PyDict_SetItemString(d, "Raise", (PyObject*)Raise_type) < 0) return; - if (PyDict_SetItemString(d, "TryExcept", (PyObject*)TryExcept_type) < - 0) return; - if (PyDict_SetItemString(d, "TryFinally", (PyObject*)TryFinally_type) < - 0) return; - if (PyDict_SetItemString(d, "Assert", (PyObject*)Assert_type) < 0) - return; - if (PyDict_SetItemString(d, "Import", (PyObject*)Import_type) < 0) - return; - if (PyDict_SetItemString(d, "ImportFrom", (PyObject*)ImportFrom_type) < - 0) return; - if (PyDict_SetItemString(d, "Exec", (PyObject*)Exec_type) < 0) return; - if (PyDict_SetItemString(d, "Global", (PyObject*)Global_type) < 0) - return; - if (PyDict_SetItemString(d, "Expr", (PyObject*)Expr_type) < 0) return; - if (PyDict_SetItemString(d, "Pass", (PyObject*)Pass_type) < 0) return; - if (PyDict_SetItemString(d, "Break", (PyObject*)Break_type) < 0) return; - if (PyDict_SetItemString(d, "Continue", (PyObject*)Continue_type) < 0) - return; - if (PyDict_SetItemString(d, "expr", (PyObject*)expr_type) < 0) return; - if (PyDict_SetItemString(d, "BoolOp", (PyObject*)BoolOp_type) < 0) - return; - if (PyDict_SetItemString(d, "BinOp", (PyObject*)BinOp_type) < 0) return; - if (PyDict_SetItemString(d, "UnaryOp", (PyObject*)UnaryOp_type) < 0) - return; - if (PyDict_SetItemString(d, "Lambda", (PyObject*)Lambda_type) < 0) - return; - if (PyDict_SetItemString(d, "IfExp", (PyObject*)IfExp_type) < 0) return; - if (PyDict_SetItemString(d, "Dict", (PyObject*)Dict_type) < 0) return; - if (PyDict_SetItemString(d, "ListComp", (PyObject*)ListComp_type) < 0) - return; - if (PyDict_SetItemString(d, "GeneratorExp", - (PyObject*)GeneratorExp_type) < 0) return; - if (PyDict_SetItemString(d, "Yield", (PyObject*)Yield_type) < 0) return; - if (PyDict_SetItemString(d, "Compare", (PyObject*)Compare_type) < 0) - return; - if (PyDict_SetItemString(d, "Call", (PyObject*)Call_type) < 0) return; - if (PyDict_SetItemString(d, "Repr", (PyObject*)Repr_type) < 0) return; - if (PyDict_SetItemString(d, "Num", (PyObject*)Num_type) < 0) return; - if (PyDict_SetItemString(d, "Str", (PyObject*)Str_type) < 0) return; - if (PyDict_SetItemString(d, "Attribute", (PyObject*)Attribute_type) < - 0) return; - if (PyDict_SetItemString(d, "Subscript", (PyObject*)Subscript_type) < - 0) return; - if (PyDict_SetItemString(d, "Name", (PyObject*)Name_type) < 0) return; - if (PyDict_SetItemString(d, "List", (PyObject*)List_type) < 0) return; - if (PyDict_SetItemString(d, "Tuple", (PyObject*)Tuple_type) < 0) return; - if (PyDict_SetItemString(d, "expr_context", - (PyObject*)expr_context_type) < 0) return; - if (PyDict_SetItemString(d, "Load", (PyObject*)Load_type) < 0) return; - if (PyDict_SetItemString(d, "Store", (PyObject*)Store_type) < 0) return; - if (PyDict_SetItemString(d, "Del", (PyObject*)Del_type) < 0) return; - if (PyDict_SetItemString(d, "AugLoad", (PyObject*)AugLoad_type) < 0) - return; - if (PyDict_SetItemString(d, "AugStore", (PyObject*)AugStore_type) < 0) - return; - if (PyDict_SetItemString(d, "Param", (PyObject*)Param_type) < 0) return; - if (PyDict_SetItemString(d, "slice", (PyObject*)slice_type) < 0) return; - if (PyDict_SetItemString(d, "Ellipsis", (PyObject*)Ellipsis_type) < 0) - return; - if (PyDict_SetItemString(d, "Slice", (PyObject*)Slice_type) < 0) return; - if (PyDict_SetItemString(d, "ExtSlice", (PyObject*)ExtSlice_type) < 0) - return; - if (PyDict_SetItemString(d, "Index", (PyObject*)Index_type) < 0) return; - if (PyDict_SetItemString(d, "boolop", (PyObject*)boolop_type) < 0) - return; - if (PyDict_SetItemString(d, "And", (PyObject*)And_type) < 0) return; - if (PyDict_SetItemString(d, "Or", (PyObject*)Or_type) < 0) return; - if (PyDict_SetItemString(d, "operator", (PyObject*)operator_type) < 0) - return; - if (PyDict_SetItemString(d, "Add", (PyObject*)Add_type) < 0) return; - if (PyDict_SetItemString(d, "Sub", (PyObject*)Sub_type) < 0) return; - if (PyDict_SetItemString(d, "Mult", (PyObject*)Mult_type) < 0) return; - if (PyDict_SetItemString(d, "Div", (PyObject*)Div_type) < 0) return; - if (PyDict_SetItemString(d, "Mod", (PyObject*)Mod_type) < 0) return; - if (PyDict_SetItemString(d, "Pow", (PyObject*)Pow_type) < 0) return; - if (PyDict_SetItemString(d, "LShift", (PyObject*)LShift_type) < 0) - return; - if (PyDict_SetItemString(d, "RShift", (PyObject*)RShift_type) < 0) - return; - if (PyDict_SetItemString(d, "BitOr", (PyObject*)BitOr_type) < 0) return; - if (PyDict_SetItemString(d, "BitXor", (PyObject*)BitXor_type) < 0) - return; - if (PyDict_SetItemString(d, "BitAnd", (PyObject*)BitAnd_type) < 0) - return; - if (PyDict_SetItemString(d, "FloorDiv", (PyObject*)FloorDiv_type) < 0) - return; - if (PyDict_SetItemString(d, "unaryop", (PyObject*)unaryop_type) < 0) - return; - if (PyDict_SetItemString(d, "Invert", (PyObject*)Invert_type) < 0) - return; - if (PyDict_SetItemString(d, "Not", (PyObject*)Not_type) < 0) return; - if (PyDict_SetItemString(d, "UAdd", (PyObject*)UAdd_type) < 0) return; - if (PyDict_SetItemString(d, "USub", (PyObject*)USub_type) < 0) return; - if (PyDict_SetItemString(d, "cmpop", (PyObject*)cmpop_type) < 0) return; - if (PyDict_SetItemString(d, "Eq", (PyObject*)Eq_type) < 0) return; - if (PyDict_SetItemString(d, "NotEq", (PyObject*)NotEq_type) < 0) return; - if (PyDict_SetItemString(d, "Lt", (PyObject*)Lt_type) < 0) return; - if (PyDict_SetItemString(d, "LtE", (PyObject*)LtE_type) < 0) return; - if (PyDict_SetItemString(d, "Gt", (PyObject*)Gt_type) < 0) return; - if (PyDict_SetItemString(d, "GtE", (PyObject*)GtE_type) < 0) return; - if (PyDict_SetItemString(d, "Is", (PyObject*)Is_type) < 0) return; - if (PyDict_SetItemString(d, "IsNot", (PyObject*)IsNot_type) < 0) return; - if (PyDict_SetItemString(d, "In", (PyObject*)In_type) < 0) return; - if (PyDict_SetItemString(d, "NotIn", (PyObject*)NotIn_type) < 0) return; - if (PyDict_SetItemString(d, "comprehension", - (PyObject*)comprehension_type) < 0) return; - if (PyDict_SetItemString(d, "excepthandler", - (PyObject*)excepthandler_type) < 0) return; - if (PyDict_SetItemString(d, "arguments", (PyObject*)arguments_type) < - 0) return; - if (PyDict_SetItemString(d, "keyword", (PyObject*)keyword_type) < 0) - return; - if (PyDict_SetItemString(d, "alias", (PyObject*)alias_type) < 0) return; -} - - -PyObject* PyAST_mod2obj(mod_ty t) -{ - init_types(); - return ast2obj_mod(t); -} - - diff --git a/sys/src/cmd/python/Python/asdl.c b/sys/src/cmd/python/Python/asdl.c deleted file mode 100644 index 72329b9d2..000000000 --- a/sys/src/cmd/python/Python/asdl.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "Python.h" -#include "asdl.h" - -asdl_seq * -asdl_seq_new(int size, PyArena *arena) -{ - asdl_seq *seq = NULL; - size_t n = sizeof(asdl_seq) + - (size ? (sizeof(void *) * (size - 1)) : 0); - - seq = (asdl_seq *)PyArena_Malloc(arena, n); - if (!seq) { - PyErr_NoMemory(); - return NULL; - } - memset(seq, 0, n); - seq->size = size; - return seq; -} - -asdl_int_seq * -asdl_int_seq_new(int size, PyArena *arena) -{ - asdl_int_seq *seq = NULL; - size_t n = sizeof(asdl_seq) + - (size ? (sizeof(int) * (size - 1)) : 0); - - seq = (asdl_int_seq *)PyArena_Malloc(arena, n); - if (!seq) { - PyErr_NoMemory(); - return NULL; - } - memset(seq, 0, n); - seq->size = size; - return seq; -} diff --git a/sys/src/cmd/python/Python/ast.c b/sys/src/cmd/python/Python/ast.c deleted file mode 100644 index 67f45ed06..000000000 --- a/sys/src/cmd/python/Python/ast.c +++ /dev/null @@ -1,3292 +0,0 @@ -/* - * This file includes functions to transform a concrete syntax tree (CST) to - * an abstract syntax tree (AST). The main function is PyAST_FromNode(). - * - */ -#include "Python.h" -#include "Python-ast.h" -#include "grammar.h" -#include "node.h" -#include "pyarena.h" -#include "ast.h" -#include "token.h" -#include "parsetok.h" -#include "graminit.h" - -#include <assert.h> - -/* XXX TO DO - - re-indent this file (should be done) - - internal error checking (freeing memory, etc.) - - syntax errors -*/ - -/* Data structure used internally */ -struct compiling { - char *c_encoding; /* source encoding */ - PyArena *c_arena; /* arena for allocating memeory */ -}; - -static asdl_seq *seq_for_testlist(struct compiling *, const node *); -static expr_ty ast_for_expr(struct compiling *, const node *); -static stmt_ty ast_for_stmt(struct compiling *, const node *); -static asdl_seq *ast_for_suite(struct compiling *, const node *); -static asdl_seq *ast_for_exprlist(struct compiling *, const node *, expr_context_ty); -static expr_ty ast_for_testlist(struct compiling *, const node *); -static expr_ty ast_for_testlist_gexp(struct compiling *, const node *); - -/* Note different signature for ast_for_call */ -static expr_ty ast_for_call(struct compiling *, const node *, expr_ty); - -static PyObject *parsenumber(const char *); -static PyObject *parsestr(const char *s, const char *encoding); -static PyObject *parsestrplus(struct compiling *, const node *n); - -#ifndef LINENO -#define LINENO(n) ((n)->n_lineno) -#endif - -static identifier -new_identifier(const char* n, PyArena *arena) { - PyObject* id = PyString_InternFromString(n); - PyArena_AddPyObject(arena, id); - return id; -} - -#define NEW_IDENTIFIER(n) new_identifier(STR(n), c->c_arena) - -/* This routine provides an invalid object for the syntax error. - The outermost routine must unpack this error and create the - proper object. We do this so that we don't have to pass - the filename to everything function. - - XXX Maybe we should just pass the filename... -*/ - -static int -ast_error(const node *n, const char *errstr) -{ - PyObject *u = Py_BuildValue("zi", errstr, LINENO(n)); - if (!u) - return 0; - PyErr_SetObject(PyExc_SyntaxError, u); - Py_DECREF(u); - return 0; -} - -static void -ast_error_finish(const char *filename) -{ - PyObject *type, *value, *tback, *errstr, *loc, *tmp; - long lineno; - - assert(PyErr_Occurred()); - if (!PyErr_ExceptionMatches(PyExc_SyntaxError)) - return; - - PyErr_Fetch(&type, &value, &tback); - errstr = PyTuple_GetItem(value, 0); - if (!errstr) - return; - Py_INCREF(errstr); - lineno = PyInt_AsLong(PyTuple_GetItem(value, 1)); - if (lineno == -1) { - Py_DECREF(errstr); - return; - } - Py_DECREF(value); - - loc = PyErr_ProgramText(filename, lineno); - if (!loc) { - Py_INCREF(Py_None); - loc = Py_None; - } - tmp = Py_BuildValue("(zlOO)", filename, lineno, Py_None, loc); - Py_DECREF(loc); - if (!tmp) { - Py_DECREF(errstr); - return; - } - value = PyTuple_Pack(2, errstr, tmp); - Py_DECREF(errstr); - Py_DECREF(tmp); - if (!value) - return; - PyErr_Restore(type, value, tback); -} - -/* num_stmts() returns number of contained statements. - - Use this routine to determine how big a sequence is needed for - the statements in a parse tree. Its raison d'etre is this bit of - grammar: - - stmt: simple_stmt | compound_stmt - simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE - - A simple_stmt can contain multiple small_stmt elements joined - by semicolons. If the arg is a simple_stmt, the number of - small_stmt elements is returned. -*/ - -static int -num_stmts(const node *n) -{ - int i, l; - node *ch; - - switch (TYPE(n)) { - case single_input: - if (TYPE(CHILD(n, 0)) == NEWLINE) - return 0; - else - return num_stmts(CHILD(n, 0)); - case file_input: - l = 0; - for (i = 0; i < NCH(n); i++) { - ch = CHILD(n, i); - if (TYPE(ch) == stmt) - l += num_stmts(ch); - } - return l; - case stmt: - return num_stmts(CHILD(n, 0)); - case compound_stmt: - return 1; - case simple_stmt: - return NCH(n) / 2; /* Divide by 2 to remove count of semi-colons */ - case suite: - if (NCH(n) == 1) - return num_stmts(CHILD(n, 0)); - else { - l = 0; - for (i = 2; i < (NCH(n) - 1); i++) - l += num_stmts(CHILD(n, i)); - return l; - } - default: { - char buf[128]; - - sprintf(buf, "Non-statement found: %d %d\n", - TYPE(n), NCH(n)); - Py_FatalError(buf); - } - } - assert(0); - return 0; -} - -/* Transform the CST rooted at node * to the appropriate AST -*/ - -mod_ty -PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename, - PyArena *arena) -{ - int i, j, k, num; - asdl_seq *stmts = NULL; - stmt_ty s; - node *ch; - struct compiling c; - - if (flags && flags->cf_flags & PyCF_SOURCE_IS_UTF8) { - c.c_encoding = "utf-8"; - if (TYPE(n) == encoding_decl) { - ast_error(n, "encoding declaration in Unicode string"); - goto error; - } - } else if (TYPE(n) == encoding_decl) { - c.c_encoding = STR(n); - n = CHILD(n, 0); - } else { - c.c_encoding = NULL; - } - c.c_arena = arena; - - k = 0; - switch (TYPE(n)) { - case file_input: - stmts = asdl_seq_new(num_stmts(n), arena); - if (!stmts) - return NULL; - for (i = 0; i < NCH(n) - 1; i++) { - ch = CHILD(n, i); - if (TYPE(ch) == NEWLINE) - continue; - REQ(ch, stmt); - num = num_stmts(ch); - if (num == 1) { - s = ast_for_stmt(&c, ch); - if (!s) - goto error; - asdl_seq_SET(stmts, k++, s); - } - else { - ch = CHILD(ch, 0); - REQ(ch, simple_stmt); - for (j = 0; j < num; j++) { - s = ast_for_stmt(&c, CHILD(ch, j * 2)); - if (!s) - goto error; - asdl_seq_SET(stmts, k++, s); - } - } - } - return Module(stmts, arena); - case eval_input: { - expr_ty testlist_ast; - - /* XXX Why not gen_for here? */ - testlist_ast = ast_for_testlist(&c, CHILD(n, 0)); - if (!testlist_ast) - goto error; - return Expression(testlist_ast, arena); - } - case single_input: - if (TYPE(CHILD(n, 0)) == NEWLINE) { - stmts = asdl_seq_new(1, arena); - if (!stmts) - goto error; - asdl_seq_SET(stmts, 0, Pass(n->n_lineno, n->n_col_offset, - arena)); - return Interactive(stmts, arena); - } - else { - n = CHILD(n, 0); - num = num_stmts(n); - stmts = asdl_seq_new(num, arena); - if (!stmts) - goto error; - if (num == 1) { - s = ast_for_stmt(&c, n); - if (!s) - goto error; - asdl_seq_SET(stmts, 0, s); - } - else { - /* Only a simple_stmt can contain multiple statements. */ - REQ(n, simple_stmt); - for (i = 0; i < NCH(n); i += 2) { - if (TYPE(CHILD(n, i)) == NEWLINE) - break; - s = ast_for_stmt(&c, CHILD(n, i)); - if (!s) - goto error; - asdl_seq_SET(stmts, i / 2, s); - } - } - - return Interactive(stmts, arena); - } - default: - goto error; - } - error: - ast_error_finish(filename); - return NULL; -} - -/* Return the AST repr. of the operator represented as syntax (|, ^, etc.) -*/ - -static operator_ty -get_operator(const node *n) -{ - switch (TYPE(n)) { - case VBAR: - return BitOr; - case CIRCUMFLEX: - return BitXor; - case AMPER: - return BitAnd; - case LEFTSHIFT: - return LShift; - case RIGHTSHIFT: - return RShift; - case PLUS: - return Add; - case MINUS: - return Sub; - case STAR: - return Mult; - case SLASH: - return Div; - case DOUBLESLASH: - return FloorDiv; - case PERCENT: - return Mod; - default: - return (operator_ty)0; - } -} - -/* Set the context ctx for expr_ty e, recursively traversing e. - - Only sets context for expr kinds that "can appear in assignment context" - (according to ../Parser/Python.asdl). For other expr kinds, it sets - an appropriate syntax error and returns false. -*/ - -static int -set_context(expr_ty e, expr_context_ty ctx, const node *n) -{ - asdl_seq *s = NULL; - /* If a particular expression type can't be used for assign / delete, - set expr_name to its name and an error message will be generated. - */ - const char* expr_name = NULL; - - /* The ast defines augmented store and load contexts, but the - implementation here doesn't actually use them. The code may be - a little more complex than necessary as a result. It also means - that expressions in an augmented assignment have a Store context. - Consider restructuring so that augmented assignment uses - set_context(), too. - */ - assert(ctx != AugStore && ctx != AugLoad); - - switch (e->kind) { - case Attribute_kind: - if (ctx == Store && - !strcmp(PyString_AS_STRING(e->v.Attribute.attr), "None")) { - return ast_error(n, "assignment to None"); - } - e->v.Attribute.ctx = ctx; - break; - case Subscript_kind: - e->v.Subscript.ctx = ctx; - break; - case Name_kind: - if (ctx == Store && - !strcmp(PyString_AS_STRING(e->v.Name.id), "None")) { - return ast_error(n, "assignment to None"); - } - e->v.Name.ctx = ctx; - break; - case List_kind: - e->v.List.ctx = ctx; - s = e->v.List.elts; - break; - case Tuple_kind: - if (asdl_seq_LEN(e->v.Tuple.elts) == 0) - return ast_error(n, "can't assign to ()"); - e->v.Tuple.ctx = ctx; - s = e->v.Tuple.elts; - break; - case Lambda_kind: - expr_name = "lambda"; - break; - case Call_kind: - expr_name = "function call"; - break; - case BoolOp_kind: - case BinOp_kind: - case UnaryOp_kind: - expr_name = "operator"; - break; - case GeneratorExp_kind: - expr_name = "generator expression"; - break; - case Yield_kind: - expr_name = "yield expression"; - break; - case ListComp_kind: - expr_name = "list comprehension"; - break; - case Dict_kind: - case Num_kind: - case Str_kind: - expr_name = "literal"; - break; - case Compare_kind: - expr_name = "comparison"; - break; - case Repr_kind: - expr_name = "repr"; - break; - case IfExp_kind: - expr_name = "conditional expression"; - break; - default: - PyErr_Format(PyExc_SystemError, - "unexpected expression in assignment %d (line %d)", - e->kind, e->lineno); - return 0; - } - /* Check for error string set by switch */ - if (expr_name) { - char buf[300]; - PyOS_snprintf(buf, sizeof(buf), - "can't %s %s", - ctx == Store ? "assign to" : "delete", - expr_name); - return ast_error(n, buf); - } - - /* If the LHS is a list or tuple, we need to set the assignment - context for all the contained elements. - */ - if (s) { - int i; - - for (i = 0; i < asdl_seq_LEN(s); i++) { - if (!set_context((expr_ty)asdl_seq_GET(s, i), ctx, n)) - return 0; - } - } - return 1; -} - -static operator_ty -ast_for_augassign(const node *n) -{ - REQ(n, augassign); - n = CHILD(n, 0); - switch (STR(n)[0]) { - case '+': - return Add; - case '-': - return Sub; - case '/': - if (STR(n)[1] == '/') - return FloorDiv; - else - return Div; - case '%': - return Mod; - case '<': - return LShift; - case '>': - return RShift; - case '&': - return BitAnd; - case '^': - return BitXor; - case '|': - return BitOr; - case '*': - if (STR(n)[1] == '*') - return Pow; - else - return Mult; - default: - PyErr_Format(PyExc_SystemError, "invalid augassign: %s", STR(n)); - return (operator_ty)0; - } -} - -static cmpop_ty -ast_for_comp_op(const node *n) -{ - /* comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is' - |'is' 'not' - */ - REQ(n, comp_op); - if (NCH(n) == 1) { - n = CHILD(n, 0); - switch (TYPE(n)) { - case LESS: - return Lt; - case GREATER: - return Gt; - case EQEQUAL: /* == */ - return Eq; - case LESSEQUAL: - return LtE; - case GREATEREQUAL: - return GtE; - case NOTEQUAL: - return NotEq; - case NAME: - if (strcmp(STR(n), "in") == 0) - return In; - if (strcmp(STR(n), "is") == 0) - return Is; - default: - PyErr_Format(PyExc_SystemError, "invalid comp_op: %s", - STR(n)); - return (cmpop_ty)0; - } - } - else if (NCH(n) == 2) { - /* handle "not in" and "is not" */ - switch (TYPE(CHILD(n, 0))) { - case NAME: - if (strcmp(STR(CHILD(n, 1)), "in") == 0) - return NotIn; - if (strcmp(STR(CHILD(n, 0)), "is") == 0) - return IsNot; - default: - PyErr_Format(PyExc_SystemError, "invalid comp_op: %s %s", - STR(CHILD(n, 0)), STR(CHILD(n, 1))); - return (cmpop_ty)0; - } - } - PyErr_Format(PyExc_SystemError, "invalid comp_op: has %d children", - NCH(n)); - return (cmpop_ty)0; -} - -static asdl_seq * -seq_for_testlist(struct compiling *c, const node *n) -{ - /* testlist: test (',' test)* [','] */ - asdl_seq *seq; - expr_ty expression; - int i; - assert(TYPE(n) == testlist - || TYPE(n) == listmaker - || TYPE(n) == testlist_gexp - || TYPE(n) == testlist_safe - || TYPE(n) == testlist1 - ); - - seq = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena); - if (!seq) - return NULL; - - for (i = 0; i < NCH(n); i += 2) { - assert(TYPE(CHILD(n, i)) == test || TYPE(CHILD(n, i)) == old_test); - - expression = ast_for_expr(c, CHILD(n, i)); - if (!expression) - return NULL; - - assert(i / 2 < seq->size); - asdl_seq_SET(seq, i / 2, expression); - } - return seq; -} - -static expr_ty -compiler_complex_args(struct compiling *c, const node *n) -{ - int i, len = (NCH(n) + 1) / 2; - expr_ty result; - asdl_seq *args = asdl_seq_new(len, c->c_arena); - if (!args) - return NULL; - - /* fpdef: NAME | '(' fplist ')' - fplist: fpdef (',' fpdef)* [','] - */ - REQ(n, fplist); - for (i = 0; i < len; i++) { - const node *fpdef_node = CHILD(n, 2*i); - const node *child; - expr_ty arg; -set_name: - /* fpdef_node is either a NAME or an fplist */ - child = CHILD(fpdef_node, 0); - if (TYPE(child) == NAME) { - if (!strcmp(STR(child), "None")) { - ast_error(child, "assignment to None"); - return NULL; - } - arg = Name(NEW_IDENTIFIER(child), Store, LINENO(child), - child->n_col_offset, c->c_arena); - } - else { - assert(TYPE(fpdef_node) == fpdef); - /* fpdef_node[0] is not a name, so it must be a '(', get CHILD[1] */ - child = CHILD(fpdef_node, 1); - assert(TYPE(child) == fplist); - /* NCH == 1 means we have (x), we need to elide the extra parens */ - if (NCH(child) == 1) { - fpdef_node = CHILD(child, 0); - assert(TYPE(fpdef_node) == fpdef); - goto set_name; - } - arg = compiler_complex_args(c, child); - } - asdl_seq_SET(args, i, arg); - } - - result = Tuple(args, Store, LINENO(n), n->n_col_offset, c->c_arena); - if (!set_context(result, Store, n)) - return NULL; - return result; -} - - -/* Create AST for argument list. */ - -static arguments_ty -ast_for_arguments(struct compiling *c, const node *n) -{ - /* parameters: '(' [varargslist] ')' - varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] - | '**' NAME) | fpdef ['=' test] (',' fpdef ['=' test])* [','] - */ - int i, j, k, n_args = 0, n_defaults = 0, found_default = 0; - asdl_seq *args, *defaults; - identifier vararg = NULL, kwarg = NULL; - node *ch; - - if (TYPE(n) == parameters) { - if (NCH(n) == 2) /* () as argument list */ - return arguments(NULL, NULL, NULL, NULL, c->c_arena); - n = CHILD(n, 1); - } - REQ(n, varargslist); - - /* first count the number of normal args & defaults */ - for (i = 0; i < NCH(n); i++) { - ch = CHILD(n, i); - if (TYPE(ch) == fpdef) - n_args++; - if (TYPE(ch) == EQUAL) - n_defaults++; - } - args = (n_args ? asdl_seq_new(n_args, c->c_arena) : NULL); - if (!args && n_args) - return NULL; /* Don't need to goto error; no objects allocated */ - defaults = (n_defaults ? asdl_seq_new(n_defaults, c->c_arena) : NULL); - if (!defaults && n_defaults) - return NULL; /* Don't need to goto error; no objects allocated */ - - /* fpdef: NAME | '(' fplist ')' - fplist: fpdef (',' fpdef)* [','] - */ - i = 0; - j = 0; /* index for defaults */ - k = 0; /* index for args */ - while (i < NCH(n)) { - ch = CHILD(n, i); - switch (TYPE(ch)) { - case fpdef: - handle_fpdef: - /* XXX Need to worry about checking if TYPE(CHILD(n, i+1)) is - anything other than EQUAL or a comma? */ - /* XXX Should NCH(n) check be made a separate check? */ - if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) { - expr_ty expression = ast_for_expr(c, CHILD(n, i + 2)); - if (!expression) - goto error; - assert(defaults != NULL); - asdl_seq_SET(defaults, j++, expression); - i += 2; - found_default = 1; - } - else if (found_default) { - ast_error(n, - "non-default argument follows default argument"); - goto error; - } - if (NCH(ch) == 3) { - ch = CHILD(ch, 1); - /* def foo((x)): is not complex, special case. */ - if (NCH(ch) != 1) { - /* We have complex arguments, setup for unpacking. */ - asdl_seq_SET(args, k++, compiler_complex_args(c, ch)); - } else { - /* def foo((x)): setup for checking NAME below. */ - /* Loop because there can be many parens and tuple - upacking mixed in. */ - ch = CHILD(ch, 0); - assert(TYPE(ch) == fpdef); - goto handle_fpdef; - } - } - if (TYPE(CHILD(ch, 0)) == NAME) { - expr_ty name; - if (!strcmp(STR(CHILD(ch, 0)), "None")) { - ast_error(CHILD(ch, 0), "assignment to None"); - goto error; - } - name = Name(NEW_IDENTIFIER(CHILD(ch, 0)), - Param, LINENO(ch), ch->n_col_offset, - c->c_arena); - if (!name) - goto error; - asdl_seq_SET(args, k++, name); - - } - i += 2; /* the name and the comma */ - break; - case STAR: - if (!strcmp(STR(CHILD(n, i+1)), "None")) { - ast_error(CHILD(n, i+1), "assignment to None"); - goto error; - } - vararg = NEW_IDENTIFIER(CHILD(n, i+1)); - i += 3; - break; - case DOUBLESTAR: - if (!strcmp(STR(CHILD(n, i+1)), "None")) { - ast_error(CHILD(n, i+1), "assignment to None"); - goto error; - } - kwarg = NEW_IDENTIFIER(CHILD(n, i+1)); - i += 3; - break; - default: - PyErr_Format(PyExc_SystemError, - "unexpected node in varargslist: %d @ %d", - TYPE(ch), i); - goto error; - } - } - - return arguments(args, vararg, kwarg, defaults, c->c_arena); - - error: - Py_XDECREF(vararg); - Py_XDECREF(kwarg); - return NULL; -} - -static expr_ty -ast_for_dotted_name(struct compiling *c, const node *n) -{ - expr_ty e; - identifier id; - int lineno, col_offset; - int i; - - REQ(n, dotted_name); - - lineno = LINENO(n); - col_offset = n->n_col_offset; - - id = NEW_IDENTIFIER(CHILD(n, 0)); - if (!id) - return NULL; - e = Name(id, Load, lineno, col_offset, c->c_arena); - if (!e) - return NULL; - - for (i = 2; i < NCH(n); i+=2) { - id = NEW_IDENTIFIER(CHILD(n, i)); - if (!id) - return NULL; - e = Attribute(e, id, Load, lineno, col_offset, c->c_arena); - if (!e) - return NULL; - } - - return e; -} - -static expr_ty -ast_for_decorator(struct compiling *c, const node *n) -{ - /* decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE */ - expr_ty d = NULL; - expr_ty name_expr; - - REQ(n, decorator); - REQ(CHILD(n, 0), AT); - REQ(RCHILD(n, -1), NEWLINE); - - name_expr = ast_for_dotted_name(c, CHILD(n, 1)); - if (!name_expr) - return NULL; - - if (NCH(n) == 3) { /* No arguments */ - d = name_expr; - name_expr = NULL; - } - else if (NCH(n) == 5) { /* Call with no arguments */ - d = Call(name_expr, NULL, NULL, NULL, NULL, LINENO(n), - n->n_col_offset, c->c_arena); - if (!d) - return NULL; - name_expr = NULL; - } - else { - d = ast_for_call(c, CHILD(n, 3), name_expr); - if (!d) - return NULL; - name_expr = NULL; - } - - return d; -} - -static asdl_seq* -ast_for_decorators(struct compiling *c, const node *n) -{ - asdl_seq* decorator_seq; - expr_ty d; - int i; - - REQ(n, decorators); - decorator_seq = asdl_seq_new(NCH(n), c->c_arena); - if (!decorator_seq) - return NULL; - - for (i = 0; i < NCH(n); i++) { - d = ast_for_decorator(c, CHILD(n, i)); - if (!d) - return NULL; - asdl_seq_SET(decorator_seq, i, d); - } - return decorator_seq; -} - -static stmt_ty -ast_for_funcdef(struct compiling *c, const node *n) -{ - /* funcdef: 'def' [decorators] NAME parameters ':' suite */ - identifier name; - arguments_ty args; - asdl_seq *body; - asdl_seq *decorator_seq = NULL; - int name_i; - - REQ(n, funcdef); - - if (NCH(n) == 6) { /* decorators are present */ - decorator_seq = ast_for_decorators(c, CHILD(n, 0)); - if (!decorator_seq) - return NULL; - name_i = 2; - } - else { - name_i = 1; - } - - name = NEW_IDENTIFIER(CHILD(n, name_i)); - if (!name) - return NULL; - else if (!strcmp(STR(CHILD(n, name_i)), "None")) { - ast_error(CHILD(n, name_i), "assignment to None"); - return NULL; - } - args = ast_for_arguments(c, CHILD(n, name_i + 1)); - if (!args) - return NULL; - body = ast_for_suite(c, CHILD(n, name_i + 3)); - if (!body) - return NULL; - - return FunctionDef(name, args, body, decorator_seq, LINENO(n), - n->n_col_offset, c->c_arena); -} - -static expr_ty -ast_for_lambdef(struct compiling *c, const node *n) -{ - /* lambdef: 'lambda' [varargslist] ':' test */ - arguments_ty args; - expr_ty expression; - - if (NCH(n) == 3) { - args = arguments(NULL, NULL, NULL, NULL, c->c_arena); - if (!args) - return NULL; - expression = ast_for_expr(c, CHILD(n, 2)); - if (!expression) - return NULL; - } - else { - args = ast_for_arguments(c, CHILD(n, 1)); - if (!args) - return NULL; - expression = ast_for_expr(c, CHILD(n, 3)); - if (!expression) - return NULL; - } - - return Lambda(args, expression, LINENO(n), n->n_col_offset, c->c_arena); -} - -static expr_ty -ast_for_ifexpr(struct compiling *c, const node *n) -{ - /* test: or_test 'if' or_test 'else' test */ - expr_ty expression, body, orelse; - - assert(NCH(n) == 5); - body = ast_for_expr(c, CHILD(n, 0)); - if (!body) - return NULL; - expression = ast_for_expr(c, CHILD(n, 2)); - if (!expression) - return NULL; - orelse = ast_for_expr(c, CHILD(n, 4)); - if (!orelse) - return NULL; - return IfExp(expression, body, orelse, LINENO(n), n->n_col_offset, - c->c_arena); -} - -/* Count the number of 'for' loop in a list comprehension. - - Helper for ast_for_listcomp(). -*/ - -static int -count_list_fors(const node *n) -{ - int n_fors = 0; - node *ch = CHILD(n, 1); - - count_list_for: - n_fors++; - REQ(ch, list_for); - if (NCH(ch) == 5) - ch = CHILD(ch, 4); - else - return n_fors; - count_list_iter: - REQ(ch, list_iter); - ch = CHILD(ch, 0); - if (TYPE(ch) == list_for) - goto count_list_for; - else if (TYPE(ch) == list_if) { - if (NCH(ch) == 3) { - ch = CHILD(ch, 2); - goto count_list_iter; - } - else - return n_fors; - } - - /* Should never be reached */ - PyErr_SetString(PyExc_SystemError, "logic error in count_list_fors"); - return -1; -} - -/* Count the number of 'if' statements in a list comprehension. - - Helper for ast_for_listcomp(). -*/ - -static int -count_list_ifs(const node *n) -{ - int n_ifs = 0; - - count_list_iter: - REQ(n, list_iter); - if (TYPE(CHILD(n, 0)) == list_for) - return n_ifs; - n = CHILD(n, 0); - REQ(n, list_if); - n_ifs++; - if (NCH(n) == 2) - return n_ifs; - n = CHILD(n, 2); - goto count_list_iter; -} - -static expr_ty -ast_for_listcomp(struct compiling *c, const node *n) -{ - /* listmaker: test ( list_for | (',' test)* [','] ) - list_for: 'for' exprlist 'in' testlist_safe [list_iter] - list_iter: list_for | list_if - list_if: 'if' test [list_iter] - testlist_safe: test [(',' test)+ [',']] - */ - expr_ty elt; - asdl_seq *listcomps; - int i, n_fors; - node *ch; - - REQ(n, listmaker); - assert(NCH(n) > 1); - - elt = ast_for_expr(c, CHILD(n, 0)); - if (!elt) - return NULL; - - n_fors = count_list_fors(n); - if (n_fors == -1) - return NULL; - - listcomps = asdl_seq_new(n_fors, c->c_arena); - if (!listcomps) - return NULL; - - ch = CHILD(n, 1); - for (i = 0; i < n_fors; i++) { - comprehension_ty lc; - asdl_seq *t; - expr_ty expression; - node *for_ch; - - REQ(ch, list_for); - - for_ch = CHILD(ch, 1); - t = ast_for_exprlist(c, for_ch, Store); - if (!t) - return NULL; - expression = ast_for_testlist(c, CHILD(ch, 3)); - if (!expression) - return NULL; - - /* Check the # of children rather than the length of t, since - [x for x, in ... ] has 1 element in t, but still requires a Tuple. */ - if (NCH(for_ch) == 1) - lc = comprehension((expr_ty)asdl_seq_GET(t, 0), expression, NULL, - c->c_arena); - else - lc = comprehension(Tuple(t, Store, LINENO(ch), ch->n_col_offset, - c->c_arena), - expression, NULL, c->c_arena); - if (!lc) - return NULL; - - if (NCH(ch) == 5) { - int j, n_ifs; - asdl_seq *ifs; - expr_ty list_for_expr; - - ch = CHILD(ch, 4); - n_ifs = count_list_ifs(ch); - if (n_ifs == -1) - return NULL; - - ifs = asdl_seq_new(n_ifs, c->c_arena); - if (!ifs) - return NULL; - - for (j = 0; j < n_ifs; j++) { - REQ(ch, list_iter); - ch = CHILD(ch, 0); - REQ(ch, list_if); - - list_for_expr = ast_for_expr(c, CHILD(ch, 1)); - if (!list_for_expr) - return NULL; - - asdl_seq_SET(ifs, j, list_for_expr); - if (NCH(ch) == 3) - ch = CHILD(ch, 2); - } - /* on exit, must guarantee that ch is a list_for */ - if (TYPE(ch) == list_iter) - ch = CHILD(ch, 0); - lc->ifs = ifs; - } - asdl_seq_SET(listcomps, i, lc); - } - - return ListComp(elt, listcomps, LINENO(n), n->n_col_offset, c->c_arena); -} - -/* - Count the number of 'for' loops in a generator expression. - - Helper for ast_for_genexp(). -*/ - -static int -count_gen_fors(const node *n) -{ - int n_fors = 0; - node *ch = CHILD(n, 1); - - count_gen_for: - n_fors++; - REQ(ch, gen_for); - if (NCH(ch) == 5) - ch = CHILD(ch, 4); - else - return n_fors; - count_gen_iter: - REQ(ch, gen_iter); - ch = CHILD(ch, 0); - if (TYPE(ch) == gen_for) - goto count_gen_for; - else if (TYPE(ch) == gen_if) { - if (NCH(ch) == 3) { - ch = CHILD(ch, 2); - goto count_gen_iter; - } - else - return n_fors; - } - - /* Should never be reached */ - PyErr_SetString(PyExc_SystemError, - "logic error in count_gen_fors"); - return -1; -} - -/* Count the number of 'if' statements in a generator expression. - - Helper for ast_for_genexp(). -*/ - -static int -count_gen_ifs(const node *n) -{ - int n_ifs = 0; - - while (1) { - REQ(n, gen_iter); - if (TYPE(CHILD(n, 0)) == gen_for) - return n_ifs; - n = CHILD(n, 0); - REQ(n, gen_if); - n_ifs++; - if (NCH(n) == 2) - return n_ifs; - n = CHILD(n, 2); - } -} - -/* TODO(jhylton): Combine with list comprehension code? */ -static expr_ty -ast_for_genexp(struct compiling *c, const node *n) -{ - /* testlist_gexp: test ( gen_for | (',' test)* [','] ) - argument: [test '='] test [gen_for] # Really [keyword '='] test */ - expr_ty elt; - asdl_seq *genexps; - int i, n_fors; - node *ch; - - assert(TYPE(n) == (testlist_gexp) || TYPE(n) == (argument)); - assert(NCH(n) > 1); - - elt = ast_for_expr(c, CHILD(n, 0)); - if (!elt) - return NULL; - - n_fors = count_gen_fors(n); - if (n_fors == -1) - return NULL; - - genexps = asdl_seq_new(n_fors, c->c_arena); - if (!genexps) - return NULL; - - ch = CHILD(n, 1); - for (i = 0; i < n_fors; i++) { - comprehension_ty ge; - asdl_seq *t; - expr_ty expression; - node *for_ch; - - REQ(ch, gen_for); - - for_ch = CHILD(ch, 1); - t = ast_for_exprlist(c, for_ch, Store); - if (!t) - return NULL; - expression = ast_for_expr(c, CHILD(ch, 3)); - if (!expression) - return NULL; - - /* Check the # of children rather than the length of t, since - (x for x, in ...) has 1 element in t, but still requires a Tuple. */ - if (NCH(for_ch) == 1) - ge = comprehension((expr_ty)asdl_seq_GET(t, 0), expression, - NULL, c->c_arena); - else - ge = comprehension(Tuple(t, Store, LINENO(ch), ch->n_col_offset, - c->c_arena), - expression, NULL, c->c_arena); - - if (!ge) - return NULL; - - if (NCH(ch) == 5) { - int j, n_ifs; - asdl_seq *ifs; - - ch = CHILD(ch, 4); - n_ifs = count_gen_ifs(ch); - if (n_ifs == -1) - return NULL; - - ifs = asdl_seq_new(n_ifs, c->c_arena); - if (!ifs) - return NULL; - - for (j = 0; j < n_ifs; j++) { - REQ(ch, gen_iter); - ch = CHILD(ch, 0); - REQ(ch, gen_if); - - expression = ast_for_expr(c, CHILD(ch, 1)); - if (!expression) - return NULL; - asdl_seq_SET(ifs, j, expression); - if (NCH(ch) == 3) - ch = CHILD(ch, 2); - } - /* on exit, must guarantee that ch is a gen_for */ - if (TYPE(ch) == gen_iter) - ch = CHILD(ch, 0); - ge->ifs = ifs; - } - asdl_seq_SET(genexps, i, ge); - } - - return GeneratorExp(elt, genexps, LINENO(n), n->n_col_offset, c->c_arena); -} - -static expr_ty -ast_for_atom(struct compiling *c, const node *n) -{ - /* atom: '(' [yield_expr|testlist_gexp] ')' | '[' [listmaker] ']' - | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+ - */ - node *ch = CHILD(n, 0); - - switch (TYPE(ch)) { - case NAME: - /* All names start in Load context, but may later be - changed. */ - return Name(NEW_IDENTIFIER(ch), Load, LINENO(n), n->n_col_offset, c->c_arena); - case STRING: { - PyObject *str = parsestrplus(c, n); - if (!str) - return NULL; - - PyArena_AddPyObject(c->c_arena, str); - return Str(str, LINENO(n), n->n_col_offset, c->c_arena); - } - case NUMBER: { - PyObject *pynum = parsenumber(STR(ch)); - if (!pynum) - return NULL; - - PyArena_AddPyObject(c->c_arena, pynum); - return Num(pynum, LINENO(n), n->n_col_offset, c->c_arena); - } - case LPAR: /* some parenthesized expressions */ - ch = CHILD(n, 1); - - if (TYPE(ch) == RPAR) - return Tuple(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena); - - if (TYPE(ch) == yield_expr) - return ast_for_expr(c, ch); - - if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == gen_for)) - return ast_for_genexp(c, ch); - - return ast_for_testlist_gexp(c, ch); - case LSQB: /* list (or list comprehension) */ - ch = CHILD(n, 1); - - if (TYPE(ch) == RSQB) - return List(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena); - - REQ(ch, listmaker); - if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) { - asdl_seq *elts = seq_for_testlist(c, ch); - if (!elts) - return NULL; - - return List(elts, Load, LINENO(n), n->n_col_offset, c->c_arena); - } - else - return ast_for_listcomp(c, ch); - case LBRACE: { - /* dictmaker: test ':' test (',' test ':' test)* [','] */ - int i, size; - asdl_seq *keys, *values; - - ch = CHILD(n, 1); - size = (NCH(ch) + 1) / 4; /* +1 in case no trailing comma */ - keys = asdl_seq_new(size, c->c_arena); - if (!keys) - return NULL; - - values = asdl_seq_new(size, c->c_arena); - if (!values) - return NULL; - - for (i = 0; i < NCH(ch); i += 4) { - expr_ty expression; - - expression = ast_for_expr(c, CHILD(ch, i)); - if (!expression) - return NULL; - - asdl_seq_SET(keys, i / 4, expression); - - expression = ast_for_expr(c, CHILD(ch, i + 2)); - if (!expression) - return NULL; - - asdl_seq_SET(values, i / 4, expression); - } - return Dict(keys, values, LINENO(n), n->n_col_offset, c->c_arena); - } - case BACKQUOTE: { /* repr */ - expr_ty expression = ast_for_testlist(c, CHILD(n, 1)); - if (!expression) - return NULL; - - return Repr(expression, LINENO(n), n->n_col_offset, c->c_arena); - } - default: - PyErr_Format(PyExc_SystemError, "unhandled atom %d", TYPE(ch)); - return NULL; - } -} - -static slice_ty -ast_for_slice(struct compiling *c, const node *n) -{ - node *ch; - expr_ty lower = NULL, upper = NULL, step = NULL; - - REQ(n, subscript); - - /* - subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] - sliceop: ':' [test] - */ - ch = CHILD(n, 0); - if (TYPE(ch) == DOT) - return Ellipsis(c->c_arena); - - if (NCH(n) == 1 && TYPE(ch) == test) { - /* 'step' variable hold no significance in terms of being used over - other vars */ - step = ast_for_expr(c, ch); - if (!step) - return NULL; - - return Index(step, c->c_arena); - } - - if (TYPE(ch) == test) { - lower = ast_for_expr(c, ch); - if (!lower) - return NULL; - } - - /* If there's an upper bound it's in the second or third position. */ - if (TYPE(ch) == COLON) { - if (NCH(n) > 1) { - node *n2 = CHILD(n, 1); - - if (TYPE(n2) == test) { - upper = ast_for_expr(c, n2); - if (!upper) - return NULL; - } - } - } else if (NCH(n) > 2) { - node *n2 = CHILD(n, 2); - - if (TYPE(n2) == test) { - upper = ast_for_expr(c, n2); - if (!upper) - return NULL; - } - } - - ch = CHILD(n, NCH(n) - 1); - if (TYPE(ch) == sliceop) { - if (NCH(ch) == 1) { - /* No expression, so step is None */ - ch = CHILD(ch, 0); - step = Name(new_identifier("None", c->c_arena), Load, - LINENO(ch), ch->n_col_offset, c->c_arena); - if (!step) - return NULL; - } else { - ch = CHILD(ch, 1); - if (TYPE(ch) == test) { - step = ast_for_expr(c, ch); - if (!step) - return NULL; - } - } - } - - return Slice(lower, upper, step, c->c_arena); -} - -static expr_ty -ast_for_binop(struct compiling *c, const node *n) -{ - /* Must account for a sequence of expressions. - How should A op B op C by represented? - BinOp(BinOp(A, op, B), op, C). - */ - - int i, nops; - expr_ty expr1, expr2, result; - operator_ty newoperator; - - expr1 = ast_for_expr(c, CHILD(n, 0)); - if (!expr1) - return NULL; - - expr2 = ast_for_expr(c, CHILD(n, 2)); - if (!expr2) - return NULL; - - newoperator = get_operator(CHILD(n, 1)); - if (!newoperator) - return NULL; - - result = BinOp(expr1, newoperator, expr2, LINENO(n), n->n_col_offset, - c->c_arena); - if (!result) - return NULL; - - nops = (NCH(n) - 1) / 2; - for (i = 1; i < nops; i++) { - expr_ty tmp_result, tmp; - const node* next_oper = CHILD(n, i * 2 + 1); - - newoperator = get_operator(next_oper); - if (!newoperator) - return NULL; - - tmp = ast_for_expr(c, CHILD(n, i * 2 + 2)); - if (!tmp) - return NULL; - - tmp_result = BinOp(result, newoperator, tmp, - LINENO(next_oper), next_oper->n_col_offset, - c->c_arena); - if (!tmp) - return NULL; - result = tmp_result; - } - return result; -} - -static expr_ty -ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr) -{ - /* trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME - subscriptlist: subscript (',' subscript)* [','] - subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] - */ - REQ(n, trailer); - if (TYPE(CHILD(n, 0)) == LPAR) { - if (NCH(n) == 2) - return Call(left_expr, NULL, NULL, NULL, NULL, LINENO(n), - n->n_col_offset, c->c_arena); - else - return ast_for_call(c, CHILD(n, 1), left_expr); - } - else if (TYPE(CHILD(n, 0)) == DOT ) { - return Attribute(left_expr, NEW_IDENTIFIER(CHILD(n, 1)), Load, - LINENO(n), n->n_col_offset, c->c_arena); - } - else { - REQ(CHILD(n, 0), LSQB); - REQ(CHILD(n, 2), RSQB); - n = CHILD(n, 1); - if (NCH(n) == 1) { - slice_ty slc = ast_for_slice(c, CHILD(n, 0)); - if (!slc) - return NULL; - return Subscript(left_expr, slc, Load, LINENO(n), n->n_col_offset, - c->c_arena); - } - else { - /* The grammar is ambiguous here. The ambiguity is resolved - by treating the sequence as a tuple literal if there are - no slice features. - */ - int j; - slice_ty slc; - expr_ty e; - bool simple = true; - asdl_seq *slices, *elts; - slices = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena); - if (!slices) - return NULL; - for (j = 0; j < NCH(n); j += 2) { - slc = ast_for_slice(c, CHILD(n, j)); - if (!slc) - return NULL; - if (slc->kind != Index_kind) - simple = false; - asdl_seq_SET(slices, j / 2, slc); - } - if (!simple) { - return Subscript(left_expr, ExtSlice(slices, c->c_arena), - Load, LINENO(n), n->n_col_offset, c->c_arena); - } - /* extract Index values and put them in a Tuple */ - elts = asdl_seq_new(asdl_seq_LEN(slices), c->c_arena); - if (!elts) - return NULL; - for (j = 0; j < asdl_seq_LEN(slices); ++j) { - slc = (slice_ty)asdl_seq_GET(slices, j); - assert(slc->kind == Index_kind && slc->v.Index.value); - asdl_seq_SET(elts, j, slc->v.Index.value); - } - e = Tuple(elts, Load, LINENO(n), n->n_col_offset, c->c_arena); - if (!e) - return NULL; - return Subscript(left_expr, Index(e, c->c_arena), - Load, LINENO(n), n->n_col_offset, c->c_arena); - } - } -} - -static expr_ty -ast_for_factor(struct compiling *c, const node *n) -{ - node *pfactor, *ppower, *patom, *pnum; - expr_ty expression; - - /* If the unary - operator is applied to a constant, don't generate - a UNARY_NEGATIVE opcode. Just store the approriate value as a - constant. The peephole optimizer already does something like - this but it doesn't handle the case where the constant is - (sys.maxint - 1). In that case, we want a PyIntObject, not a - PyLongObject. - */ - if (TYPE(CHILD(n, 0)) == MINUS - && NCH(n) == 2 - && TYPE((pfactor = CHILD(n, 1))) == factor - && NCH(pfactor) == 1 - && TYPE((ppower = CHILD(pfactor, 0))) == power - && NCH(ppower) == 1 - && TYPE((patom = CHILD(ppower, 0))) == atom - && TYPE((pnum = CHILD(patom, 0))) == NUMBER) { - char *s = PyObject_MALLOC(strlen(STR(pnum)) + 2); - if (s == NULL) - return NULL; - s[0] = '-'; - strcpy(s + 1, STR(pnum)); - PyObject_FREE(STR(pnum)); - STR(pnum) = s; - return ast_for_atom(c, patom); - } - - expression = ast_for_expr(c, CHILD(n, 1)); - if (!expression) - return NULL; - - switch (TYPE(CHILD(n, 0))) { - case PLUS: - return UnaryOp(UAdd, expression, LINENO(n), n->n_col_offset, - c->c_arena); - case MINUS: - return UnaryOp(USub, expression, LINENO(n), n->n_col_offset, - c->c_arena); - case TILDE: - return UnaryOp(Invert, expression, LINENO(n), - n->n_col_offset, c->c_arena); - } - PyErr_Format(PyExc_SystemError, "unhandled factor: %d", - TYPE(CHILD(n, 0))); - return NULL; -} - -static expr_ty -ast_for_power(struct compiling *c, const node *n) -{ - /* power: atom trailer* ('**' factor)* - */ - int i; - expr_ty e, tmp; - REQ(n, power); - e = ast_for_atom(c, CHILD(n, 0)); - if (!e) - return NULL; - if (NCH(n) == 1) - return e; - for (i = 1; i < NCH(n); i++) { - node *ch = CHILD(n, i); - if (TYPE(ch) != trailer) - break; - tmp = ast_for_trailer(c, ch, e); - if (!tmp) - return NULL; - tmp->lineno = e->lineno; - tmp->col_offset = e->col_offset; - e = tmp; - } - if (TYPE(CHILD(n, NCH(n) - 1)) == factor) { - expr_ty f = ast_for_expr(c, CHILD(n, NCH(n) - 1)); - if (!f) - return NULL; - tmp = BinOp(e, Pow, f, LINENO(n), n->n_col_offset, c->c_arena); - if (!tmp) - return NULL; - e = tmp; - } - return e; -} - -/* Do not name a variable 'expr'! Will cause a compile error. -*/ - -static expr_ty -ast_for_expr(struct compiling *c, const node *n) -{ - /* handle the full range of simple expressions - test: or_test ['if' or_test 'else' test] | lambdef - or_test: and_test ('or' and_test)* - and_test: not_test ('and' not_test)* - not_test: 'not' not_test | comparison - comparison: expr (comp_op expr)* - expr: xor_expr ('|' xor_expr)* - xor_expr: and_expr ('^' and_expr)* - and_expr: shift_expr ('&' shift_expr)* - shift_expr: arith_expr (('<<'|'>>') arith_expr)* - arith_expr: term (('+'|'-') term)* - term: factor (('*'|'/'|'%'|'//') factor)* - factor: ('+'|'-'|'~') factor | power - power: atom trailer* ('**' factor)* - - As well as modified versions that exist for backward compatibility, - to explicitly allow: - [ x for x in lambda: 0, lambda: 1 ] - (which would be ambiguous without these extra rules) - - old_test: or_test | old_lambdef - old_lambdef: 'lambda' [vararglist] ':' old_test - - */ - - asdl_seq *seq; - int i; - - loop: - switch (TYPE(n)) { - case test: - case old_test: - if (TYPE(CHILD(n, 0)) == lambdef || - TYPE(CHILD(n, 0)) == old_lambdef) - return ast_for_lambdef(c, CHILD(n, 0)); - else if (NCH(n) > 1) - return ast_for_ifexpr(c, n); - /* Fallthrough */ - case or_test: - case and_test: - if (NCH(n) == 1) { - n = CHILD(n, 0); - goto loop; - } - seq = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena); - if (!seq) - return NULL; - for (i = 0; i < NCH(n); i += 2) { - expr_ty e = ast_for_expr(c, CHILD(n, i)); - if (!e) - return NULL; - asdl_seq_SET(seq, i / 2, e); - } - if (!strcmp(STR(CHILD(n, 1)), "and")) - return BoolOp(And, seq, LINENO(n), n->n_col_offset, - c->c_arena); - assert(!strcmp(STR(CHILD(n, 1)), "or")); - return BoolOp(Or, seq, LINENO(n), n->n_col_offset, c->c_arena); - case not_test: - if (NCH(n) == 1) { - n = CHILD(n, 0); - goto loop; - } - else { - expr_ty expression = ast_for_expr(c, CHILD(n, 1)); - if (!expression) - return NULL; - - return UnaryOp(Not, expression, LINENO(n), n->n_col_offset, - c->c_arena); - } - case comparison: - if (NCH(n) == 1) { - n = CHILD(n, 0); - goto loop; - } - else { - expr_ty expression; - asdl_int_seq *ops; - asdl_seq *cmps; - ops = asdl_int_seq_new(NCH(n) / 2, c->c_arena); - if (!ops) - return NULL; - cmps = asdl_seq_new(NCH(n) / 2, c->c_arena); - if (!cmps) { - return NULL; - } - for (i = 1; i < NCH(n); i += 2) { - cmpop_ty newoperator; - - newoperator = ast_for_comp_op(CHILD(n, i)); - if (!newoperator) { - return NULL; - } - - expression = ast_for_expr(c, CHILD(n, i + 1)); - if (!expression) { - return NULL; - } - - asdl_seq_SET(ops, i / 2, newoperator); - asdl_seq_SET(cmps, i / 2, expression); - } - expression = ast_for_expr(c, CHILD(n, 0)); - if (!expression) { - return NULL; - } - - return Compare(expression, ops, cmps, LINENO(n), - n->n_col_offset, c->c_arena); - } - break; - - /* The next five cases all handle BinOps. The main body of code - is the same in each case, but the switch turned inside out to - reuse the code for each type of operator. - */ - case expr: - case xor_expr: - case and_expr: - case shift_expr: - case arith_expr: - case term: - if (NCH(n) == 1) { - n = CHILD(n, 0); - goto loop; - } - return ast_for_binop(c, n); - case yield_expr: { - expr_ty exp = NULL; - if (NCH(n) == 2) { - exp = ast_for_testlist(c, CHILD(n, 1)); - if (!exp) - return NULL; - } - return Yield(exp, LINENO(n), n->n_col_offset, c->c_arena); - } - case factor: - if (NCH(n) == 1) { - n = CHILD(n, 0); - goto loop; - } - return ast_for_factor(c, n); - case power: - return ast_for_power(c, n); - default: - PyErr_Format(PyExc_SystemError, "unhandled expr: %d", TYPE(n)); - return NULL; - } - /* should never get here unless if error is set */ - return NULL; -} - -static expr_ty -ast_for_call(struct compiling *c, const node *n, expr_ty func) -{ - /* - arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] - | '**' test) - argument: [test '='] test [gen_for] # Really [keyword '='] test - */ - - int i, nargs, nkeywords, ngens; - asdl_seq *args; - asdl_seq *keywords; - expr_ty vararg = NULL, kwarg = NULL; - - REQ(n, arglist); - - nargs = 0; - nkeywords = 0; - ngens = 0; - for (i = 0; i < NCH(n); i++) { - node *ch = CHILD(n, i); - if (TYPE(ch) == argument) { - if (NCH(ch) == 1) - nargs++; - else if (TYPE(CHILD(ch, 1)) == gen_for) - ngens++; - else - nkeywords++; - } - } - if (ngens > 1 || (ngens && (nargs || nkeywords))) { - ast_error(n, "Generator expression must be parenthesized " - "if not sole argument"); - return NULL; - } - - if (nargs + nkeywords + ngens > 255) { - ast_error(n, "more than 255 arguments"); - return NULL; - } - - args = asdl_seq_new(nargs + ngens, c->c_arena); - if (!args) - return NULL; - keywords = asdl_seq_new(nkeywords, c->c_arena); - if (!keywords) - return NULL; - nargs = 0; - nkeywords = 0; - for (i = 0; i < NCH(n); i++) { - node *ch = CHILD(n, i); - if (TYPE(ch) == argument) { - expr_ty e; - if (NCH(ch) == 1) { - if (nkeywords) { - ast_error(CHILD(ch, 0), - "non-keyword arg after keyword arg"); - return NULL; - } - e = ast_for_expr(c, CHILD(ch, 0)); - if (!e) - return NULL; - asdl_seq_SET(args, nargs++, e); - } - else if (TYPE(CHILD(ch, 1)) == gen_for) { - e = ast_for_genexp(c, ch); - if (!e) - return NULL; - asdl_seq_SET(args, nargs++, e); - } - else { - keyword_ty kw; - identifier key; - - /* CHILD(ch, 0) is test, but must be an identifier? */ - e = ast_for_expr(c, CHILD(ch, 0)); - if (!e) - return NULL; - /* f(lambda x: x[0] = 3) ends up getting parsed with - * LHS test = lambda x: x[0], and RHS test = 3. - * SF bug 132313 points out that complaining about a keyword - * then is very confusing. - */ - if (e->kind == Lambda_kind) { - ast_error(CHILD(ch, 0), "lambda cannot contain assignment"); - return NULL; - } else if (e->kind != Name_kind) { - ast_error(CHILD(ch, 0), "keyword can't be an expression"); - return NULL; - } - key = e->v.Name.id; - e = ast_for_expr(c, CHILD(ch, 2)); - if (!e) - return NULL; - kw = keyword(key, e, c->c_arena); - if (!kw) - return NULL; - asdl_seq_SET(keywords, nkeywords++, kw); - } - } - else if (TYPE(ch) == STAR) { - vararg = ast_for_expr(c, CHILD(n, i+1)); - i++; - } - else if (TYPE(ch) == DOUBLESTAR) { - kwarg = ast_for_expr(c, CHILD(n, i+1)); - i++; - } - } - - return Call(func, args, keywords, vararg, kwarg, func->lineno, func->col_offset, c->c_arena); -} - -static expr_ty -ast_for_testlist(struct compiling *c, const node* n) -{ - /* testlist_gexp: test (',' test)* [','] */ - /* testlist: test (',' test)* [','] */ - /* testlist_safe: test (',' test)+ [','] */ - /* testlist1: test (',' test)* */ - assert(NCH(n) > 0); - if (TYPE(n) == testlist_gexp) { - if (NCH(n) > 1) - assert(TYPE(CHILD(n, 1)) != gen_for); - } - else { - assert(TYPE(n) == testlist || - TYPE(n) == testlist_safe || - TYPE(n) == testlist1); - } - if (NCH(n) == 1) - return ast_for_expr(c, CHILD(n, 0)); - else { - asdl_seq *tmp = seq_for_testlist(c, n); - if (!tmp) - return NULL; - return Tuple(tmp, Load, LINENO(n), n->n_col_offset, c->c_arena); - } -} - -static expr_ty -ast_for_testlist_gexp(struct compiling *c, const node* n) -{ - /* testlist_gexp: test ( gen_for | (',' test)* [','] ) */ - /* argument: test [ gen_for ] */ - assert(TYPE(n) == testlist_gexp || TYPE(n) == argument); - if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == gen_for) - return ast_for_genexp(c, n); - return ast_for_testlist(c, n); -} - -/* like ast_for_testlist() but returns a sequence */ -static asdl_seq* -ast_for_class_bases(struct compiling *c, const node* n) -{ - /* testlist: test (',' test)* [','] */ - assert(NCH(n) > 0); - REQ(n, testlist); - if (NCH(n) == 1) { - expr_ty base; - asdl_seq *bases = asdl_seq_new(1, c->c_arena); - if (!bases) - return NULL; - base = ast_for_expr(c, CHILD(n, 0)); - if (!base) - return NULL; - asdl_seq_SET(bases, 0, base); - return bases; - } - - return seq_for_testlist(c, n); -} - -static stmt_ty -ast_for_expr_stmt(struct compiling *c, const node *n) -{ - REQ(n, expr_stmt); - /* expr_stmt: testlist (augassign (yield_expr|testlist) - | ('=' (yield_expr|testlist))*) - testlist: test (',' test)* [','] - augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' - | '<<=' | '>>=' | '**=' | '//=' - test: ... here starts the operator precendence dance - */ - - if (NCH(n) == 1) { - expr_ty e = ast_for_testlist(c, CHILD(n, 0)); - if (!e) - return NULL; - - return Expr(e, LINENO(n), n->n_col_offset, c->c_arena); - } - else if (TYPE(CHILD(n, 1)) == augassign) { - expr_ty expr1, expr2; - operator_ty newoperator; - node *ch = CHILD(n, 0); - - expr1 = ast_for_testlist(c, ch); - if (!expr1) - return NULL; - /* TODO(nas): Remove duplicated error checks (set_context does it) */ - switch (expr1->kind) { - case GeneratorExp_kind: - ast_error(ch, "augmented assignment to generator " - "expression not possible"); - return NULL; - case Yield_kind: - ast_error(ch, "augmented assignment to yield " - "expression not possible"); - return NULL; - case Name_kind: { - const char *var_name = PyString_AS_STRING(expr1->v.Name.id); - if (var_name[0] == 'N' && !strcmp(var_name, "None")) { - ast_error(ch, "assignment to None"); - return NULL; - } - break; - } - case Attribute_kind: - case Subscript_kind: - break; - default: - ast_error(ch, "illegal expression for augmented " - "assignment"); - return NULL; - } - if (!set_context(expr1, Store, ch)) - return NULL; - - ch = CHILD(n, 2); - if (TYPE(ch) == testlist) - expr2 = ast_for_testlist(c, ch); - else - expr2 = ast_for_expr(c, ch); - if (!expr2) - return NULL; - - newoperator = ast_for_augassign(CHILD(n, 1)); - if (!newoperator) - return NULL; - - return AugAssign(expr1, newoperator, expr2, LINENO(n), n->n_col_offset, c->c_arena); - } - else { - int i; - asdl_seq *targets; - node *value; - expr_ty expression; - - /* a normal assignment */ - REQ(CHILD(n, 1), EQUAL); - targets = asdl_seq_new(NCH(n) / 2, c->c_arena); - if (!targets) - return NULL; - for (i = 0; i < NCH(n) - 2; i += 2) { - expr_ty e; - node *ch = CHILD(n, i); - if (TYPE(ch) == yield_expr) { - ast_error(ch, "assignment to yield expression not possible"); - return NULL; - } - e = ast_for_testlist(c, ch); - - /* set context to assign */ - if (!e) - return NULL; - - if (!set_context(e, Store, CHILD(n, i))) - return NULL; - - asdl_seq_SET(targets, i / 2, e); - } - value = CHILD(n, NCH(n) - 1); - if (TYPE(value) == testlist) - expression = ast_for_testlist(c, value); - else - expression = ast_for_expr(c, value); - if (!expression) - return NULL; - return Assign(targets, expression, LINENO(n), n->n_col_offset, c->c_arena); - } -} - -static stmt_ty -ast_for_print_stmt(struct compiling *c, const node *n) -{ - /* print_stmt: 'print' ( [ test (',' test)* [','] ] - | '>>' test [ (',' test)+ [','] ] ) - */ - expr_ty dest = NULL, expression; - asdl_seq *seq; - bool nl; - int i, j, start = 1; - - REQ(n, print_stmt); - if (NCH(n) >= 2 && TYPE(CHILD(n, 1)) == RIGHTSHIFT) { - dest = ast_for_expr(c, CHILD(n, 2)); - if (!dest) - return NULL; - start = 4; - } - seq = asdl_seq_new((NCH(n) + 1 - start) / 2, c->c_arena); - if (!seq) - return NULL; - for (i = start, j = 0; i < NCH(n); i += 2, ++j) { - expression = ast_for_expr(c, CHILD(n, i)); - if (!expression) - return NULL; - asdl_seq_SET(seq, j, expression); - } - nl = (TYPE(CHILD(n, NCH(n) - 1)) == COMMA) ? false : true; - return Print(dest, seq, nl, LINENO(n), n->n_col_offset, c->c_arena); -} - -static asdl_seq * -ast_for_exprlist(struct compiling *c, const node *n, expr_context_ty context) -{ - asdl_seq *seq; - int i; - expr_ty e; - - REQ(n, exprlist); - - seq = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena); - if (!seq) - return NULL; - for (i = 0; i < NCH(n); i += 2) { - e = ast_for_expr(c, CHILD(n, i)); - if (!e) - return NULL; - asdl_seq_SET(seq, i / 2, e); - if (context && !set_context(e, context, CHILD(n, i))) - return NULL; - } - return seq; -} - -static stmt_ty -ast_for_del_stmt(struct compiling *c, const node *n) -{ - asdl_seq *expr_list; - - /* del_stmt: 'del' exprlist */ - REQ(n, del_stmt); - - expr_list = ast_for_exprlist(c, CHILD(n, 1), Del); - if (!expr_list) - return NULL; - return Delete(expr_list, LINENO(n), n->n_col_offset, c->c_arena); -} - -static stmt_ty -ast_for_flow_stmt(struct compiling *c, const node *n) -{ - /* - flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt - | yield_stmt - break_stmt: 'break' - continue_stmt: 'continue' - return_stmt: 'return' [testlist] - yield_stmt: yield_expr - yield_expr: 'yield' testlist - raise_stmt: 'raise' [test [',' test [',' test]]] - */ - node *ch; - - REQ(n, flow_stmt); - ch = CHILD(n, 0); - switch (TYPE(ch)) { - case break_stmt: - return Break(LINENO(n), n->n_col_offset, c->c_arena); - case continue_stmt: - return Continue(LINENO(n), n->n_col_offset, c->c_arena); - case yield_stmt: { /* will reduce to yield_expr */ - expr_ty exp = ast_for_expr(c, CHILD(ch, 0)); - if (!exp) - return NULL; - return Expr(exp, LINENO(n), n->n_col_offset, c->c_arena); - } - case return_stmt: - if (NCH(ch) == 1) - return Return(NULL, LINENO(n), n->n_col_offset, c->c_arena); - else { - expr_ty expression = ast_for_testlist(c, CHILD(ch, 1)); - if (!expression) - return NULL; - return Return(expression, LINENO(n), n->n_col_offset, c->c_arena); - } - case raise_stmt: - if (NCH(ch) == 1) - return Raise(NULL, NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena); - else if (NCH(ch) == 2) { - expr_ty expression = ast_for_expr(c, CHILD(ch, 1)); - if (!expression) - return NULL; - return Raise(expression, NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena); - } - else if (NCH(ch) == 4) { - expr_ty expr1, expr2; - - expr1 = ast_for_expr(c, CHILD(ch, 1)); - if (!expr1) - return NULL; - expr2 = ast_for_expr(c, CHILD(ch, 3)); - if (!expr2) - return NULL; - - return Raise(expr1, expr2, NULL, LINENO(n), n->n_col_offset, c->c_arena); - } - else if (NCH(ch) == 6) { - expr_ty expr1, expr2, expr3; - - expr1 = ast_for_expr(c, CHILD(ch, 1)); - if (!expr1) - return NULL; - expr2 = ast_for_expr(c, CHILD(ch, 3)); - if (!expr2) - return NULL; - expr3 = ast_for_expr(c, CHILD(ch, 5)); - if (!expr3) - return NULL; - - return Raise(expr1, expr2, expr3, LINENO(n), n->n_col_offset, c->c_arena); - } - default: - PyErr_Format(PyExc_SystemError, - "unexpected flow_stmt: %d", TYPE(ch)); - return NULL; - } - - PyErr_SetString(PyExc_SystemError, "unhandled flow statement"); - return NULL; -} - -static alias_ty -alias_for_import_name(struct compiling *c, const node *n) -{ - /* - import_as_name: NAME ['as' NAME] - dotted_as_name: dotted_name ['as' NAME] - dotted_name: NAME ('.' NAME)* - */ - PyObject *str; - - loop: - switch (TYPE(n)) { - case import_as_name: - str = NULL; - if (NCH(n) == 3) { - if (strcmp(STR(CHILD(n, 1)), "as") != 0) { - ast_error(n, "must use 'as' in import"); - return NULL; - } - str = NEW_IDENTIFIER(CHILD(n, 2)); - } - return alias(NEW_IDENTIFIER(CHILD(n, 0)), str, c->c_arena); - case dotted_as_name: - if (NCH(n) == 1) { - n = CHILD(n, 0); - goto loop; - } - else { - alias_ty a = alias_for_import_name(c, CHILD(n, 0)); - if (!a) - return NULL; - if (strcmp(STR(CHILD(n, 1)), "as") != 0) { - ast_error(n, "must use 'as' in import"); - return NULL; - } - assert(!a->asname); - a->asname = NEW_IDENTIFIER(CHILD(n, 2)); - return a; - } - break; - case dotted_name: - if (NCH(n) == 1) - return alias(NEW_IDENTIFIER(CHILD(n, 0)), NULL, c->c_arena); - else { - /* Create a string of the form "a.b.c" */ - int i; - size_t len; - char *s; - - len = 0; - for (i = 0; i < NCH(n); i += 2) - /* length of string plus one for the dot */ - len += strlen(STR(CHILD(n, i))) + 1; - len--; /* the last name doesn't have a dot */ - str = PyString_FromStringAndSize(NULL, len); - if (!str) - return NULL; - s = PyString_AS_STRING(str); - if (!s) - return NULL; - for (i = 0; i < NCH(n); i += 2) { - char *sch = STR(CHILD(n, i)); - strcpy(s, STR(CHILD(n, i))); - s += strlen(sch); - *s++ = '.'; - } - --s; - *s = '\0'; - PyString_InternInPlace(&str); - PyArena_AddPyObject(c->c_arena, str); - return alias(str, NULL, c->c_arena); - } - break; - case STAR: - str = PyString_InternFromString("*"); - PyArena_AddPyObject(c->c_arena, str); - return alias(str, NULL, c->c_arena); - default: - PyErr_Format(PyExc_SystemError, - "unexpected import name: %d", TYPE(n)); - return NULL; - } - - PyErr_SetString(PyExc_SystemError, "unhandled import name condition"); - return NULL; -} - -static stmt_ty -ast_for_import_stmt(struct compiling *c, const node *n) -{ - /* - import_stmt: import_name | import_from - import_name: 'import' dotted_as_names - import_from: 'from' ('.'* dotted_name | '.') 'import' - ('*' | '(' import_as_names ')' | import_as_names) - */ - int lineno; - int col_offset; - int i; - asdl_seq *aliases; - - REQ(n, import_stmt); - lineno = LINENO(n); - col_offset = n->n_col_offset; - n = CHILD(n, 0); - if (TYPE(n) == import_name) { - n = CHILD(n, 1); - REQ(n, dotted_as_names); - aliases = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena); - if (!aliases) - return NULL; - for (i = 0; i < NCH(n); i += 2) { - alias_ty import_alias = alias_for_import_name(c, CHILD(n, i)); - if (!import_alias) - return NULL; - asdl_seq_SET(aliases, i / 2, import_alias); - } - return Import(aliases, lineno, col_offset, c->c_arena); - } - else if (TYPE(n) == import_from) { - int n_children; - int idx, ndots = 0; - alias_ty mod = NULL; - identifier modname; - - /* Count the number of dots (for relative imports) and check for the - optional module name */ - for (idx = 1; idx < NCH(n); idx++) { - if (TYPE(CHILD(n, idx)) == dotted_name) { - mod = alias_for_import_name(c, CHILD(n, idx)); - idx++; - break; - } else if (TYPE(CHILD(n, idx)) != DOT) { - break; - } - ndots++; - } - idx++; /* skip over the 'import' keyword */ - switch (TYPE(CHILD(n, idx))) { - case STAR: - /* from ... import * */ - n = CHILD(n, idx); - n_children = 1; - if (ndots) { - ast_error(n, "'import *' not allowed with 'from .'"); - return NULL; - } - break; - case LPAR: - /* from ... import (x, y, z) */ - n = CHILD(n, idx + 1); - n_children = NCH(n); - break; - case import_as_names: - /* from ... import x, y, z */ - n = CHILD(n, idx); - n_children = NCH(n); - if (n_children % 2 == 0) { - ast_error(n, "trailing comma not allowed without" - " surrounding parentheses"); - return NULL; - } - break; - default: - ast_error(n, "Unexpected node-type in from-import"); - return NULL; - } - - aliases = asdl_seq_new((n_children + 1) / 2, c->c_arena); - if (!aliases) - return NULL; - - /* handle "from ... import *" special b/c there's no children */ - if (TYPE(n) == STAR) { - alias_ty import_alias = alias_for_import_name(c, n); - if (!import_alias) - return NULL; - asdl_seq_SET(aliases, 0, import_alias); - } - else { - for (i = 0; i < NCH(n); i += 2) { - alias_ty import_alias = alias_for_import_name(c, CHILD(n, i)); - if (!import_alias) - return NULL; - asdl_seq_SET(aliases, i / 2, import_alias); - } - } - if (mod != NULL) - modname = mod->name; - else - modname = new_identifier("", c->c_arena); - return ImportFrom(modname, aliases, ndots, lineno, col_offset, - c->c_arena); - } - PyErr_Format(PyExc_SystemError, - "unknown import statement: starts with command '%s'", - STR(CHILD(n, 0))); - return NULL; -} - -static stmt_ty -ast_for_global_stmt(struct compiling *c, const node *n) -{ - /* global_stmt: 'global' NAME (',' NAME)* */ - identifier name; - asdl_seq *s; - int i; - - REQ(n, global_stmt); - s = asdl_seq_new(NCH(n) / 2, c->c_arena); - if (!s) - return NULL; - for (i = 1; i < NCH(n); i += 2) { - name = NEW_IDENTIFIER(CHILD(n, i)); - if (!name) - return NULL; - asdl_seq_SET(s, i / 2, name); - } - return Global(s, LINENO(n), n->n_col_offset, c->c_arena); -} - -static stmt_ty -ast_for_exec_stmt(struct compiling *c, const node *n) -{ - expr_ty expr1, globals = NULL, locals = NULL; - int n_children = NCH(n); - if (n_children != 2 && n_children != 4 && n_children != 6) { - PyErr_Format(PyExc_SystemError, - "poorly formed 'exec' statement: %d parts to statement", - n_children); - return NULL; - } - - /* exec_stmt: 'exec' expr ['in' test [',' test]] */ - REQ(n, exec_stmt); - expr1 = ast_for_expr(c, CHILD(n, 1)); - if (!expr1) - return NULL; - if (n_children >= 4) { - globals = ast_for_expr(c, CHILD(n, 3)); - if (!globals) - return NULL; - } - if (n_children == 6) { - locals = ast_for_expr(c, CHILD(n, 5)); - if (!locals) - return NULL; - } - - return Exec(expr1, globals, locals, LINENO(n), n->n_col_offset, c->c_arena); -} - -static stmt_ty -ast_for_assert_stmt(struct compiling *c, const node *n) -{ - /* assert_stmt: 'assert' test [',' test] */ - REQ(n, assert_stmt); - if (NCH(n) == 2) { - expr_ty expression = ast_for_expr(c, CHILD(n, 1)); - if (!expression) - return NULL; - return Assert(expression, NULL, LINENO(n), n->n_col_offset, c->c_arena); - } - else if (NCH(n) == 4) { - expr_ty expr1, expr2; - - expr1 = ast_for_expr(c, CHILD(n, 1)); - if (!expr1) - return NULL; - expr2 = ast_for_expr(c, CHILD(n, 3)); - if (!expr2) - return NULL; - - return Assert(expr1, expr2, LINENO(n), n->n_col_offset, c->c_arena); - } - PyErr_Format(PyExc_SystemError, - "improper number of parts to 'assert' statement: %d", - NCH(n)); - return NULL; -} - -static asdl_seq * -ast_for_suite(struct compiling *c, const node *n) -{ - /* suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT */ - asdl_seq *seq; - stmt_ty s; - int i, total, num, end, pos = 0; - node *ch; - - REQ(n, suite); - - total = num_stmts(n); - seq = asdl_seq_new(total, c->c_arena); - if (!seq) - return NULL; - if (TYPE(CHILD(n, 0)) == simple_stmt) { - n = CHILD(n, 0); - /* simple_stmt always ends with a NEWLINE, - and may have a trailing SEMI - */ - end = NCH(n) - 1; - if (TYPE(CHILD(n, end - 1)) == SEMI) - end--; - /* loop by 2 to skip semi-colons */ - for (i = 0; i < end; i += 2) { - ch = CHILD(n, i); - s = ast_for_stmt(c, ch); - if (!s) - return NULL; - asdl_seq_SET(seq, pos++, s); - } - } - else { - for (i = 2; i < (NCH(n) - 1); i++) { - ch = CHILD(n, i); - REQ(ch, stmt); - num = num_stmts(ch); - if (num == 1) { - /* small_stmt or compound_stmt with only one child */ - s = ast_for_stmt(c, ch); - if (!s) - return NULL; - asdl_seq_SET(seq, pos++, s); - } - else { - int j; - ch = CHILD(ch, 0); - REQ(ch, simple_stmt); - for (j = 0; j < NCH(ch); j += 2) { - /* statement terminates with a semi-colon ';' */ - if (NCH(CHILD(ch, j)) == 0) { - assert((j + 1) == NCH(ch)); - break; - } - s = ast_for_stmt(c, CHILD(ch, j)); - if (!s) - return NULL; - asdl_seq_SET(seq, pos++, s); - } - } - } - } - assert(pos == seq->size); - return seq; -} - -static stmt_ty -ast_for_if_stmt(struct compiling *c, const node *n) -{ - /* if_stmt: 'if' test ':' suite ('elif' test ':' suite)* - ['else' ':' suite] - */ - char *s; - - REQ(n, if_stmt); - - if (NCH(n) == 4) { - expr_ty expression; - asdl_seq *suite_seq; - - expression = ast_for_expr(c, CHILD(n, 1)); - if (!expression) - return NULL; - suite_seq = ast_for_suite(c, CHILD(n, 3)); - if (!suite_seq) - return NULL; - - return If(expression, suite_seq, NULL, LINENO(n), n->n_col_offset, c->c_arena); - } - - s = STR(CHILD(n, 4)); - /* s[2], the third character in the string, will be - 's' for el_s_e, or - 'i' for el_i_f - */ - if (s[2] == 's') { - expr_ty expression; - asdl_seq *seq1, *seq2; - - expression = ast_for_expr(c, CHILD(n, 1)); - if (!expression) - return NULL; - seq1 = ast_for_suite(c, CHILD(n, 3)); - if (!seq1) - return NULL; - seq2 = ast_for_suite(c, CHILD(n, 6)); - if (!seq2) - return NULL; - - return If(expression, seq1, seq2, LINENO(n), n->n_col_offset, c->c_arena); - } - else if (s[2] == 'i') { - int i, n_elif, has_else = 0; - expr_ty expression; - asdl_seq *suite_seq; - asdl_seq *orelse = NULL; - n_elif = NCH(n) - 4; - /* must reference the child n_elif+1 since 'else' token is third, - not fourth, child from the end. */ - if (TYPE(CHILD(n, (n_elif + 1))) == NAME - && STR(CHILD(n, (n_elif + 1)))[2] == 's') { - has_else = 1; - n_elif -= 3; - } - n_elif /= 4; - - if (has_else) { - asdl_seq *suite_seq2; - - orelse = asdl_seq_new(1, c->c_arena); - if (!orelse) - return NULL; - expression = ast_for_expr(c, CHILD(n, NCH(n) - 6)); - if (!expression) - return NULL; - suite_seq = ast_for_suite(c, CHILD(n, NCH(n) - 4)); - if (!suite_seq) - return NULL; - suite_seq2 = ast_for_suite(c, CHILD(n, NCH(n) - 1)); - if (!suite_seq2) - return NULL; - - asdl_seq_SET(orelse, 0, If(expression, suite_seq, suite_seq2, - LINENO(CHILD(n, NCH(n) - 6)), CHILD(n, NCH(n) - 6)->n_col_offset, - c->c_arena)); - /* the just-created orelse handled the last elif */ - n_elif--; - } - - for (i = 0; i < n_elif; i++) { - int off = 5 + (n_elif - i - 1) * 4; - asdl_seq *newobj = asdl_seq_new(1, c->c_arena); - if (!newobj) - return NULL; - expression = ast_for_expr(c, CHILD(n, off)); - if (!expression) - return NULL; - suite_seq = ast_for_suite(c, CHILD(n, off + 2)); - if (!suite_seq) - return NULL; - - asdl_seq_SET(newobj, 0, - If(expression, suite_seq, orelse, - LINENO(CHILD(n, off)), CHILD(n, off)->n_col_offset, c->c_arena)); - orelse = newobj; - } - expression = ast_for_expr(c, CHILD(n, 1)); - if (!expression) - return NULL; - suite_seq = ast_for_suite(c, CHILD(n, 3)); - if (!suite_seq) - return NULL; - return If(expression, suite_seq, orelse, - LINENO(n), n->n_col_offset, c->c_arena); - } - - PyErr_Format(PyExc_SystemError, - "unexpected token in 'if' statement: %s", s); - return NULL; -} - -static stmt_ty -ast_for_while_stmt(struct compiling *c, const node *n) -{ - /* while_stmt: 'while' test ':' suite ['else' ':' suite] */ - REQ(n, while_stmt); - - if (NCH(n) == 4) { - expr_ty expression; - asdl_seq *suite_seq; - - expression = ast_for_expr(c, CHILD(n, 1)); - if (!expression) - return NULL; - suite_seq = ast_for_suite(c, CHILD(n, 3)); - if (!suite_seq) - return NULL; - return While(expression, suite_seq, NULL, LINENO(n), n->n_col_offset, c->c_arena); - } - else if (NCH(n) == 7) { - expr_ty expression; - asdl_seq *seq1, *seq2; - - expression = ast_for_expr(c, CHILD(n, 1)); - if (!expression) - return NULL; - seq1 = ast_for_suite(c, CHILD(n, 3)); - if (!seq1) - return NULL; - seq2 = ast_for_suite(c, CHILD(n, 6)); - if (!seq2) - return NULL; - - return While(expression, seq1, seq2, LINENO(n), n->n_col_offset, c->c_arena); - } - - PyErr_Format(PyExc_SystemError, - "wrong number of tokens for 'while' statement: %d", - NCH(n)); - return NULL; -} - -static stmt_ty -ast_for_for_stmt(struct compiling *c, const node *n) -{ - asdl_seq *_target, *seq = NULL, *suite_seq; - expr_ty expression; - expr_ty target; - const node *node_target; - /* for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] */ - REQ(n, for_stmt); - - if (NCH(n) == 9) { - seq = ast_for_suite(c, CHILD(n, 8)); - if (!seq) - return NULL; - } - - node_target = CHILD(n, 1); - _target = ast_for_exprlist(c, node_target, Store); - if (!_target) - return NULL; - /* Check the # of children rather than the length of _target, since - for x, in ... has 1 element in _target, but still requires a Tuple. */ - if (NCH(node_target) == 1) - target = (expr_ty)asdl_seq_GET(_target, 0); - else - target = Tuple(_target, Store, LINENO(n), n->n_col_offset, c->c_arena); - - expression = ast_for_testlist(c, CHILD(n, 3)); - if (!expression) - return NULL; - suite_seq = ast_for_suite(c, CHILD(n, 5)); - if (!suite_seq) - return NULL; - - return For(target, expression, suite_seq, seq, LINENO(n), n->n_col_offset, - c->c_arena); -} - -static excepthandler_ty -ast_for_except_clause(struct compiling *c, const node *exc, node *body) -{ - /* except_clause: 'except' [test [',' test]] */ - REQ(exc, except_clause); - REQ(body, suite); - - if (NCH(exc) == 1) { - asdl_seq *suite_seq = ast_for_suite(c, body); - if (!suite_seq) - return NULL; - - return excepthandler(NULL, NULL, suite_seq, LINENO(exc), - exc->n_col_offset, c->c_arena); - } - else if (NCH(exc) == 2) { - expr_ty expression; - asdl_seq *suite_seq; - - expression = ast_for_expr(c, CHILD(exc, 1)); - if (!expression) - return NULL; - suite_seq = ast_for_suite(c, body); - if (!suite_seq) - return NULL; - - return excepthandler(expression, NULL, suite_seq, LINENO(exc), - exc->n_col_offset, c->c_arena); - } - else if (NCH(exc) == 4) { - asdl_seq *suite_seq; - expr_ty expression; - expr_ty e = ast_for_expr(c, CHILD(exc, 3)); - if (!e) - return NULL; - if (!set_context(e, Store, CHILD(exc, 3))) - return NULL; - expression = ast_for_expr(c, CHILD(exc, 1)); - if (!expression) - return NULL; - suite_seq = ast_for_suite(c, body); - if (!suite_seq) - return NULL; - - return excepthandler(expression, e, suite_seq, LINENO(exc), - exc->n_col_offset, c->c_arena); - } - - PyErr_Format(PyExc_SystemError, - "wrong number of children for 'except' clause: %d", - NCH(exc)); - return NULL; -} - -static stmt_ty -ast_for_try_stmt(struct compiling *c, const node *n) -{ - const int nch = NCH(n); - int n_except = (nch - 3)/3; - asdl_seq *body, *orelse = NULL, *finally = NULL; - - REQ(n, try_stmt); - - body = ast_for_suite(c, CHILD(n, 2)); - if (body == NULL) - return NULL; - - if (TYPE(CHILD(n, nch - 3)) == NAME) { - if (strcmp(STR(CHILD(n, nch - 3)), "finally") == 0) { - if (nch >= 9 && TYPE(CHILD(n, nch - 6)) == NAME) { - /* we can assume it's an "else", - because nch >= 9 for try-else-finally and - it would otherwise have a type of except_clause */ - orelse = ast_for_suite(c, CHILD(n, nch - 4)); - if (orelse == NULL) - return NULL; - n_except--; - } - - finally = ast_for_suite(c, CHILD(n, nch - 1)); - if (finally == NULL) - return NULL; - n_except--; - } - else { - /* we can assume it's an "else", - otherwise it would have a type of except_clause */ - orelse = ast_for_suite(c, CHILD(n, nch - 1)); - if (orelse == NULL) - return NULL; - n_except--; - } - } - else if (TYPE(CHILD(n, nch - 3)) != except_clause) { - ast_error(n, "malformed 'try' statement"); - return NULL; - } - - if (n_except > 0) { - int i; - stmt_ty except_st; - /* process except statements to create a try ... except */ - asdl_seq *handlers = asdl_seq_new(n_except, c->c_arena); - if (handlers == NULL) - return NULL; - - for (i = 0; i < n_except; i++) { - excepthandler_ty e = ast_for_except_clause(c, CHILD(n, 3 + i * 3), - CHILD(n, 5 + i * 3)); - if (!e) - return NULL; - asdl_seq_SET(handlers, i, e); - } - - except_st = TryExcept(body, handlers, orelse, LINENO(n), - n->n_col_offset, c->c_arena); - if (!finally) - return except_st; - - /* if a 'finally' is present too, we nest the TryExcept within a - TryFinally to emulate try ... except ... finally */ - body = asdl_seq_new(1, c->c_arena); - if (body == NULL) - return NULL; - asdl_seq_SET(body, 0, except_st); - } - - /* must be a try ... finally (except clauses are in body, if any exist) */ - assert(finally != NULL); - return TryFinally(body, finally, LINENO(n), n->n_col_offset, c->c_arena); -} - -static expr_ty -ast_for_with_var(struct compiling *c, const node *n) -{ - REQ(n, with_var); - if (strcmp(STR(CHILD(n, 0)), "as") != 0) { - ast_error(n, "expected \"with [expr] as [var]\""); - return NULL; - } - return ast_for_expr(c, CHILD(n, 1)); -} - -/* with_stmt: 'with' test [ with_var ] ':' suite */ -static stmt_ty -ast_for_with_stmt(struct compiling *c, const node *n) -{ - expr_ty context_expr, optional_vars = NULL; - int suite_index = 3; /* skip 'with', test, and ':' */ - asdl_seq *suite_seq; - - assert(TYPE(n) == with_stmt); - context_expr = ast_for_expr(c, CHILD(n, 1)); - if (!context_expr) - return NULL; - if (TYPE(CHILD(n, 2)) == with_var) { - optional_vars = ast_for_with_var(c, CHILD(n, 2)); - - if (!optional_vars) { - return NULL; - } - if (!set_context(optional_vars, Store, n)) { - return NULL; - } - suite_index = 4; - } - - suite_seq = ast_for_suite(c, CHILD(n, suite_index)); - if (!suite_seq) { - return NULL; - } - return With(context_expr, optional_vars, suite_seq, LINENO(n), - n->n_col_offset, c->c_arena); -} - -static stmt_ty -ast_for_classdef(struct compiling *c, const node *n) -{ - /* classdef: 'class' NAME ['(' testlist ')'] ':' suite */ - asdl_seq *bases, *s; - - REQ(n, classdef); - - if (!strcmp(STR(CHILD(n, 1)), "None")) { - ast_error(n, "assignment to None"); - return NULL; - } - - if (NCH(n) == 4) { - s = ast_for_suite(c, CHILD(n, 3)); - if (!s) - return NULL; - return ClassDef(NEW_IDENTIFIER(CHILD(n, 1)), NULL, s, LINENO(n), - n->n_col_offset, c->c_arena); - } - /* check for empty base list */ - if (TYPE(CHILD(n,3)) == RPAR) { - s = ast_for_suite(c, CHILD(n,5)); - if (!s) - return NULL; - return ClassDef(NEW_IDENTIFIER(CHILD(n, 1)), NULL, s, LINENO(n), - n->n_col_offset, c->c_arena); - } - - /* else handle the base class list */ - bases = ast_for_class_bases(c, CHILD(n, 3)); - if (!bases) - return NULL; - - s = ast_for_suite(c, CHILD(n, 6)); - if (!s) - return NULL; - return ClassDef(NEW_IDENTIFIER(CHILD(n, 1)), bases, s, LINENO(n), - n->n_col_offset, c->c_arena); -} - -static stmt_ty -ast_for_stmt(struct compiling *c, const node *n) -{ - if (TYPE(n) == stmt) { - assert(NCH(n) == 1); - n = CHILD(n, 0); - } - if (TYPE(n) == simple_stmt) { - assert(num_stmts(n) == 1); - n = CHILD(n, 0); - } - if (TYPE(n) == small_stmt) { - REQ(n, small_stmt); - n = CHILD(n, 0); - /* small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt - | flow_stmt | import_stmt | global_stmt | exec_stmt - | assert_stmt - */ - switch (TYPE(n)) { - case expr_stmt: - return ast_for_expr_stmt(c, n); - case print_stmt: - return ast_for_print_stmt(c, n); - case del_stmt: - return ast_for_del_stmt(c, n); - case pass_stmt: - return Pass(LINENO(n), n->n_col_offset, c->c_arena); - case flow_stmt: - return ast_for_flow_stmt(c, n); - case import_stmt: - return ast_for_import_stmt(c, n); - case global_stmt: - return ast_for_global_stmt(c, n); - case exec_stmt: - return ast_for_exec_stmt(c, n); - case assert_stmt: - return ast_for_assert_stmt(c, n); - default: - PyErr_Format(PyExc_SystemError, - "unhandled small_stmt: TYPE=%d NCH=%d\n", - TYPE(n), NCH(n)); - return NULL; - } - } - else { - /* compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt - | funcdef | classdef - */ - node *ch = CHILD(n, 0); - REQ(n, compound_stmt); - switch (TYPE(ch)) { - case if_stmt: - return ast_for_if_stmt(c, ch); - case while_stmt: - return ast_for_while_stmt(c, ch); - case for_stmt: - return ast_for_for_stmt(c, ch); - case try_stmt: - return ast_for_try_stmt(c, ch); - case with_stmt: - return ast_for_with_stmt(c, ch); - case funcdef: - return ast_for_funcdef(c, ch); - case classdef: - return ast_for_classdef(c, ch); - default: - PyErr_Format(PyExc_SystemError, - "unhandled small_stmt: TYPE=%d NCH=%d\n", - TYPE(n), NCH(n)); - return NULL; - } - } -} - -static PyObject * -parsenumber(const char *s) -{ - const char *end; - long x; - double dx; -#ifndef WITHOUT_COMPLEX - Py_complex c; - int imflag; -#endif - - errno = 0; - end = s + strlen(s) - 1; -#ifndef WITHOUT_COMPLEX - imflag = *end == 'j' || *end == 'J'; -#endif - if (*end == 'l' || *end == 'L') - return PyLong_FromString((char *)s, (char **)0, 0); - if (s[0] == '0') { - x = (long) PyOS_strtoul((char *)s, (char **)&end, 0); - if (x < 0 && errno == 0) { - return PyLong_FromString((char *)s, - (char **)0, - 0); - } - } - else - x = PyOS_strtol((char *)s, (char **)&end, 0); - if (*end == '\0') { - if (errno != 0) - return PyLong_FromString((char *)s, (char **)0, 0); - return PyInt_FromLong(x); - } - /* XXX Huge floats may silently fail */ -#ifndef WITHOUT_COMPLEX - if (imflag) { - c.real = 0.; - PyFPE_START_PROTECT("atof", return 0) - c.imag = PyOS_ascii_atof(s); - PyFPE_END_PROTECT(c) - return PyComplex_FromCComplex(c); - } - else -#endif - { - PyFPE_START_PROTECT("atof", return 0) - dx = PyOS_ascii_atof(s); - PyFPE_END_PROTECT(dx) - return PyFloat_FromDouble(dx); - } -} - -static PyObject * -decode_utf8(const char **sPtr, const char *end, char* encoding) -{ -#ifndef Py_USING_UNICODE - Py_FatalError("decode_utf8 should not be called in this build."); - return NULL; -#else - PyObject *u, *v; - char *s, *t; - t = s = (char *)*sPtr; - /* while (s < end && *s != '\\') s++; */ /* inefficient for u".." */ - while (s < end && (*s & 0x80)) s++; - *sPtr = s; - u = PyUnicode_DecodeUTF8(t, s - t, NULL); - if (u == NULL) - return NULL; - v = PyUnicode_AsEncodedString(u, encoding, NULL); - Py_DECREF(u); - return v; -#endif -} - -static PyObject * -decode_unicode(const char *s, size_t len, int rawmode, const char *encoding) -{ - PyObject *v, *u; - char *buf; - char *p; - const char *end; - if (encoding == NULL) { - buf = (char *)s; - u = NULL; - } else if (strcmp(encoding, "iso-8859-1") == 0) { - buf = (char *)s; - u = NULL; - } else { - /* "\XX" may become "\u005c\uHHLL" (12 bytes) */ - u = PyString_FromStringAndSize((char *)NULL, len * 4); - if (u == NULL) - return NULL; - p = buf = PyString_AsString(u); - end = s + len; - while (s < end) { - if (*s == '\\') { - *p++ = *s++; - if (*s & 0x80) { - strcpy(p, "u005c"); - p += 5; - } - } - if (*s & 0x80) { /* XXX inefficient */ - PyObject *w; - char *r; - Py_ssize_t rn, i; - w = decode_utf8(&s, end, "utf-16-be"); - if (w == NULL) { - Py_DECREF(u); - return NULL; - } - r = PyString_AsString(w); - rn = PyString_Size(w); - assert(rn % 2 == 0); - for (i = 0; i < rn; i += 2) { - sprintf(p, "\\u%02x%02x", - r[i + 0] & 0xFF, - r[i + 1] & 0xFF); - p += 6; - } - Py_DECREF(w); - } else { - *p++ = *s++; - } - } - len = p - buf; - s = buf; - } - if (rawmode) - v = PyUnicode_DecodeRawUnicodeEscape(s, len, NULL); - else - v = PyUnicode_DecodeUnicodeEscape(s, len, NULL); - Py_XDECREF(u); - return v; -} - -/* s is a Python string literal, including the bracketing quote characters, - * and r &/or u prefixes (if any), and embedded escape sequences (if any). - * parsestr parses it, and returns the decoded Python string object. - */ -static PyObject * -parsestr(const char *s, const char *encoding) -{ - size_t len; - int quote = Py_CHARMASK(*s); - int rawmode = 0; - int need_encoding; - int unicode = 0; - - if (isalpha(quote) || quote == '_') { - if (quote == 'u' || quote == 'U') { - quote = *++s; - unicode = 1; - } - if (quote == 'r' || quote == 'R') { - quote = *++s; - rawmode = 1; - } - } - if (quote != '\'' && quote != '\"') { - PyErr_BadInternalCall(); - return NULL; - } - s++; - len = strlen(s); - if (len > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "string to parse is too long"); - return NULL; - } - if (s[--len] != quote) { - PyErr_BadInternalCall(); - return NULL; - } - if (len >= 4 && s[0] == quote && s[1] == quote) { - s += 2; - len -= 2; - if (s[--len] != quote || s[--len] != quote) { - PyErr_BadInternalCall(); - return NULL; - } - } -#ifdef Py_USING_UNICODE - if (unicode || Py_UnicodeFlag) { - return decode_unicode(s, len, rawmode, encoding); - } -#endif - need_encoding = (encoding != NULL && - strcmp(encoding, "utf-8") != 0 && - strcmp(encoding, "iso-8859-1") != 0); - if (rawmode || strchr(s, '\\') == NULL) { - if (need_encoding) { -#ifndef Py_USING_UNICODE - /* This should not happen - we never see any other - encoding. */ - Py_FatalError( - "cannot deal with encodings in this build."); -#else - PyObject *v, *u = PyUnicode_DecodeUTF8(s, len, NULL); - if (u == NULL) - return NULL; - v = PyUnicode_AsEncodedString(u, encoding, NULL); - Py_DECREF(u); - return v; -#endif - } else { - return PyString_FromStringAndSize(s, len); - } - } - - return PyString_DecodeEscape(s, len, NULL, unicode, - need_encoding ? encoding : NULL); -} - -/* Build a Python string object out of a STRING atom. This takes care of - * compile-time literal catenation, calling parsestr() on each piece, and - * pasting the intermediate results together. - */ -static PyObject * -parsestrplus(struct compiling *c, const node *n) -{ - PyObject *v; - int i; - REQ(CHILD(n, 0), STRING); - if ((v = parsestr(STR(CHILD(n, 0)), c->c_encoding)) != NULL) { - /* String literal concatenation */ - for (i = 1; i < NCH(n); i++) { - PyObject *s; - s = parsestr(STR(CHILD(n, i)), c->c_encoding); - if (s == NULL) - goto onError; - if (PyString_Check(v) && PyString_Check(s)) { - PyString_ConcatAndDel(&v, s); - if (v == NULL) - goto onError; - } -#ifdef Py_USING_UNICODE - else { - PyObject *temp = PyUnicode_Concat(v, s); - Py_DECREF(s); - Py_DECREF(v); - v = temp; - if (v == NULL) - goto onError; - } -#endif - } - } - return v; - - onError: - Py_XDECREF(v); - return NULL; -} diff --git a/sys/src/cmd/python/Python/atof.c b/sys/src/cmd/python/Python/atof.c deleted file mode 100644 index 8fbde3847..000000000 --- a/sys/src/cmd/python/Python/atof.c +++ /dev/null @@ -1,50 +0,0 @@ - -/* Just in case you haven't got an atof() around... - This one doesn't check for bad syntax or overflow, - and is slow and inaccurate. - But it's good enough for the occasional string literal... */ - -#include "pyconfig.h" - -#include <ctype.h> - -double atof(char *s) -{ - double a = 0.0; - int e = 0; - int c; - while ((c = *s++) != '\0' && isdigit(c)) { - a = a*10.0 + (c - '0'); - } - if (c == '.') { - while ((c = *s++) != '\0' && isdigit(c)) { - a = a*10.0 + (c - '0'); - e = e-1; - } - } - if (c == 'e' || c == 'E') { - int sign = 1; - int i = 0; - c = *s++; - if (c == '+') - c = *s++; - else if (c == '-') { - c = *s++; - sign = -1; - } - while (isdigit(c)) { - i = i*10 + (c - '0'); - c = *s++; - } - e += i*sign; - } - while (e > 0) { - a *= 10.0; - e--; - } - while (e < 0) { - a *= 0.1; - e++; - } - return a; -} diff --git a/sys/src/cmd/python/Python/bltinmodule.c b/sys/src/cmd/python/Python/bltinmodule.c deleted file mode 100644 index ceb2fc77f..000000000 --- a/sys/src/cmd/python/Python/bltinmodule.c +++ /dev/null @@ -1,2620 +0,0 @@ -/* Built-in functions */ - -#include "Python.h" - -#include "node.h" -#include "code.h" -#include "eval.h" - -#include <ctype.h> - -#ifdef RISCOS -#include "unixstuff.h" -#endif - -/* The default encoding used by the platform file system APIs - Can remain NULL for all platforms that don't have such a concept -*/ -#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T) -const char *Py_FileSystemDefaultEncoding = "mbcs"; -#elif defined(__APPLE__) -const char *Py_FileSystemDefaultEncoding = "utf-8"; -#else -const char *Py_FileSystemDefaultEncoding = NULL; /* use default */ -#endif - -/* Forward */ -static PyObject *filterstring(PyObject *, PyObject *); -#ifdef Py_USING_UNICODE -static PyObject *filterunicode(PyObject *, PyObject *); -#endif -static PyObject *filtertuple (PyObject *, PyObject *); - -static PyObject * -builtin___import__(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", "globals", "locals", "fromlist", - "level", 0}; - char *name; - PyObject *globals = NULL; - PyObject *locals = NULL; - PyObject *fromlist = NULL; - int level = -1; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|OOOi:__import__", - kwlist, &name, &globals, &locals, &fromlist, &level)) - return NULL; - return PyImport_ImportModuleLevel(name, globals, locals, - fromlist, level); -} - -PyDoc_STRVAR(import_doc, -"__import__(name, globals={}, locals={}, fromlist=[], level=-1) -> module\n\ -\n\ -Import a module. The globals are only used to determine the context;\n\ -they are not modified. The locals are currently unused. The fromlist\n\ -should be a list of names to emulate ``from name import ...'', or an\n\ -empty list to emulate ``import name''.\n\ -When importing a module from a package, note that __import__('A.B', ...)\n\ -returns package A when fromlist is empty, but its submodule B when\n\ -fromlist is not empty. Level is used to determine whether to perform \n\ -absolute or relative imports. -1 is the original strategy of attempting\n\ -both absolute and relative imports, 0 is absolute, a positive number\n\ -is the number of parent directories to search relative to the current module."); - - -static PyObject * -builtin_abs(PyObject *self, PyObject *v) -{ - return PyNumber_Absolute(v); -} - -PyDoc_STRVAR(abs_doc, -"abs(number) -> number\n\ -\n\ -Return the absolute value of the argument."); - -static PyObject * -builtin_all(PyObject *self, PyObject *v) -{ - PyObject *it, *item; - - it = PyObject_GetIter(v); - if (it == NULL) - return NULL; - - while ((item = PyIter_Next(it)) != NULL) { - int cmp = PyObject_IsTrue(item); - Py_DECREF(item); - if (cmp < 0) { - Py_DECREF(it); - return NULL; - } - if (cmp == 0) { - Py_DECREF(it); - Py_RETURN_FALSE; - } - } - Py_DECREF(it); - if (PyErr_Occurred()) - return NULL; - Py_RETURN_TRUE; -} - -PyDoc_STRVAR(all_doc, -"all(iterable) -> bool\n\ -\n\ -Return True if bool(x) is True for all values x in the iterable."); - -static PyObject * -builtin_any(PyObject *self, PyObject *v) -{ - PyObject *it, *item; - - it = PyObject_GetIter(v); - if (it == NULL) - return NULL; - - while ((item = PyIter_Next(it)) != NULL) { - int cmp = PyObject_IsTrue(item); - Py_DECREF(item); - if (cmp < 0) { - Py_DECREF(it); - return NULL; - } - if (cmp == 1) { - Py_DECREF(it); - Py_RETURN_TRUE; - } - } - Py_DECREF(it); - if (PyErr_Occurred()) - return NULL; - Py_RETURN_FALSE; -} - -PyDoc_STRVAR(any_doc, -"any(iterable) -> bool\n\ -\n\ -Return True if bool(x) is True for any x in the iterable."); - -static PyObject * -builtin_apply(PyObject *self, PyObject *args) -{ - PyObject *func, *alist = NULL, *kwdict = NULL; - PyObject *t = NULL, *retval = NULL; - - if (!PyArg_UnpackTuple(args, "apply", 1, 3, &func, &alist, &kwdict)) - return NULL; - if (alist != NULL) { - if (!PyTuple_Check(alist)) { - if (!PySequence_Check(alist)) { - PyErr_Format(PyExc_TypeError, - "apply() arg 2 expected sequence, found %s", - alist->ob_type->tp_name); - return NULL; - } - t = PySequence_Tuple(alist); - if (t == NULL) - return NULL; - alist = t; - } - } - if (kwdict != NULL && !PyDict_Check(kwdict)) { - PyErr_Format(PyExc_TypeError, - "apply() arg 3 expected dictionary, found %s", - kwdict->ob_type->tp_name); - goto finally; - } - retval = PyEval_CallObjectWithKeywords(func, alist, kwdict); - finally: - Py_XDECREF(t); - return retval; -} - -PyDoc_STRVAR(apply_doc, -"apply(object[, args[, kwargs]]) -> value\n\ -\n\ -Call a callable object with positional arguments taken from the tuple args,\n\ -and keyword arguments taken from the optional dictionary kwargs.\n\ -Note that classes are callable, as are instances with a __call__() method.\n\ -\n\ -Deprecated since release 2.3. Instead, use the extended call syntax:\n\ - function(*args, **keywords)."); - - -static PyObject * -builtin_callable(PyObject *self, PyObject *v) -{ - return PyBool_FromLong((long)PyCallable_Check(v)); -} - -PyDoc_STRVAR(callable_doc, -"callable(object) -> bool\n\ -\n\ -Return whether the object is callable (i.e., some kind of function).\n\ -Note that classes are callable, as are instances with a __call__() method."); - - -static PyObject * -builtin_filter(PyObject *self, PyObject *args) -{ - PyObject *func, *seq, *result, *it, *arg; - Py_ssize_t len; /* guess for result list size */ - register Py_ssize_t j; - - if (!PyArg_UnpackTuple(args, "filter", 2, 2, &func, &seq)) - return NULL; - - /* Strings and tuples return a result of the same type. */ - if (PyString_Check(seq)) - return filterstring(func, seq); -#ifdef Py_USING_UNICODE - if (PyUnicode_Check(seq)) - return filterunicode(func, seq); -#endif - if (PyTuple_Check(seq)) - return filtertuple(func, seq); - - /* Pre-allocate argument list tuple. */ - arg = PyTuple_New(1); - if (arg == NULL) - return NULL; - - /* Get iterator. */ - it = PyObject_GetIter(seq); - if (it == NULL) - goto Fail_arg; - - /* Guess a result list size. */ - len = _PyObject_LengthHint(seq); - if (len < 0) { - if (!PyErr_ExceptionMatches(PyExc_TypeError) && - !PyErr_ExceptionMatches(PyExc_AttributeError)) { - goto Fail_it; - } - PyErr_Clear(); - len = 8; /* arbitrary */ - } - - /* Get a result list. */ - if (PyList_Check(seq) && seq->ob_refcnt == 1) { - /* Eww - can modify the list in-place. */ - Py_INCREF(seq); - result = seq; - } - else { - result = PyList_New(len); - if (result == NULL) - goto Fail_it; - } - - /* Build the result list. */ - j = 0; - for (;;) { - PyObject *item; - int ok; - - item = PyIter_Next(it); - if (item == NULL) { - if (PyErr_Occurred()) - goto Fail_result_it; - break; - } - - if (func == (PyObject *)&PyBool_Type || func == Py_None) { - ok = PyObject_IsTrue(item); - } - else { - PyObject *good; - PyTuple_SET_ITEM(arg, 0, item); - good = PyObject_Call(func, arg, NULL); - PyTuple_SET_ITEM(arg, 0, NULL); - if (good == NULL) { - Py_DECREF(item); - goto Fail_result_it; - } - ok = PyObject_IsTrue(good); - Py_DECREF(good); - } - if (ok) { - if (j < len) - PyList_SET_ITEM(result, j, item); - else { - int status = PyList_Append(result, item); - Py_DECREF(item); - if (status < 0) - goto Fail_result_it; - } - ++j; - } - else - Py_DECREF(item); - } - - - /* Cut back result list if len is too big. */ - if (j < len && PyList_SetSlice(result, j, len, NULL) < 0) - goto Fail_result_it; - - Py_DECREF(it); - Py_DECREF(arg); - return result; - -Fail_result_it: - Py_DECREF(result); -Fail_it: - Py_DECREF(it); -Fail_arg: - Py_DECREF(arg); - return NULL; -} - -PyDoc_STRVAR(filter_doc, -"filter(function or None, sequence) -> list, tuple, or string\n" -"\n" -"Return those items of sequence for which function(item) is true. If\n" -"function is None, return the items that are true. If sequence is a tuple\n" -"or string, return the same type, else return a list."); - -static PyObject * -builtin_chr(PyObject *self, PyObject *args) -{ - long x; - char s[1]; - - if (!PyArg_ParseTuple(args, "l:chr", &x)) - return NULL; - if (x < 0 || x >= 256) { - PyErr_SetString(PyExc_ValueError, - "chr() arg not in range(256)"); - return NULL; - } - s[0] = (char)x; - return PyString_FromStringAndSize(s, 1); -} - -PyDoc_STRVAR(chr_doc, -"chr(i) -> character\n\ -\n\ -Return a string of one character with ordinal i; 0 <= i < 256."); - - -#ifdef Py_USING_UNICODE -static PyObject * -builtin_unichr(PyObject *self, PyObject *args) -{ - long x; - - if (!PyArg_ParseTuple(args, "l:unichr", &x)) - return NULL; - - return PyUnicode_FromOrdinal(x); -} - -PyDoc_STRVAR(unichr_doc, -"unichr(i) -> Unicode character\n\ -\n\ -Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff."); -#endif - - -static PyObject * -builtin_cmp(PyObject *self, PyObject *args) -{ - PyObject *a, *b; - int c; - - if (!PyArg_UnpackTuple(args, "cmp", 2, 2, &a, &b)) - return NULL; - if (PyObject_Cmp(a, b, &c) < 0) - return NULL; - return PyInt_FromLong((long)c); -} - -PyDoc_STRVAR(cmp_doc, -"cmp(x, y) -> integer\n\ -\n\ -Return negative if x<y, zero if x==y, positive if x>y."); - - -static PyObject * -builtin_coerce(PyObject *self, PyObject *args) -{ - PyObject *v, *w; - PyObject *res; - - if (!PyArg_UnpackTuple(args, "coerce", 2, 2, &v, &w)) - return NULL; - if (PyNumber_Coerce(&v, &w) < 0) - return NULL; - res = PyTuple_Pack(2, v, w); - Py_DECREF(v); - Py_DECREF(w); - return res; -} - -PyDoc_STRVAR(coerce_doc, -"coerce(x, y) -> (x1, y1)\n\ -\n\ -Return a tuple consisting of the two numeric arguments converted to\n\ -a common type, using the same rules as used by arithmetic operations.\n\ -If coercion is not possible, raise TypeError."); - -static PyObject * -builtin_compile(PyObject *self, PyObject *args) -{ - char *str; - char *filename; - char *startstr; - int start; - int dont_inherit = 0; - int supplied_flags = 0; - PyCompilerFlags cf; - PyObject *result = NULL, *cmd, *tmp = NULL; - Py_ssize_t length; - - if (!PyArg_ParseTuple(args, "Oss|ii:compile", &cmd, &filename, - &startstr, &supplied_flags, &dont_inherit)) - return NULL; - - cf.cf_flags = supplied_flags; - -#ifdef Py_USING_UNICODE - if (PyUnicode_Check(cmd)) { - tmp = PyUnicode_AsUTF8String(cmd); - if (tmp == NULL) - return NULL; - cmd = tmp; - cf.cf_flags |= PyCF_SOURCE_IS_UTF8; - } -#endif - if (PyObject_AsReadBuffer(cmd, (const void **)&str, &length)) - return NULL; - if ((size_t)length != strlen(str)) { - PyErr_SetString(PyExc_TypeError, - "compile() expected string without null bytes"); - goto cleanup; - } - - if (strcmp(startstr, "exec") == 0) - start = Py_file_input; - else if (strcmp(startstr, "eval") == 0) - start = Py_eval_input; - else if (strcmp(startstr, "single") == 0) - start = Py_single_input; - else { - PyErr_SetString(PyExc_ValueError, - "compile() arg 3 must be 'exec' or 'eval' or 'single'"); - goto cleanup; - } - - if (supplied_flags & - ~(PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_DONT_IMPLY_DEDENT | PyCF_ONLY_AST)) - { - PyErr_SetString(PyExc_ValueError, - "compile(): unrecognised flags"); - goto cleanup; - } - /* XXX Warn if (supplied_flags & PyCF_MASK_OBSOLETE) != 0? */ - - if (!dont_inherit) { - PyEval_MergeCompilerFlags(&cf); - } - result = Py_CompileStringFlags(str, filename, start, &cf); -cleanup: - Py_XDECREF(tmp); - return result; -} - -PyDoc_STRVAR(compile_doc, -"compile(source, filename, mode[, flags[, dont_inherit]]) -> code object\n\ -\n\ -Compile the source string (a Python module, statement or expression)\n\ -into a code object that can be executed by the exec statement or eval().\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 non-zero, stops the compilation inheriting\n\ -the effects of any future statements in effect in the code calling\n\ -compile; if absent or zero these statements do influence the compilation,\n\ -in addition to any features explicitly specified."); - -static PyObject * -builtin_dir(PyObject *self, PyObject *args) -{ - PyObject *arg = NULL; - - if (!PyArg_UnpackTuple(args, "dir", 0, 1, &arg)) - return NULL; - return PyObject_Dir(arg); -} - -PyDoc_STRVAR(dir_doc, -"dir([object]) -> list of strings\n" -"\n" -"Return an alphabetized list of names comprising (some of) the attributes\n" -"of the given object, and of attributes reachable from it:\n" -"\n" -"No argument: the names in the current scope.\n" -"Module object: the module attributes.\n" -"Type or class object: its attributes, and recursively the attributes of\n" -" its bases.\n" -"Otherwise: its attributes, its class's attributes, and recursively the\n" -" attributes of its class's base classes."); - -static PyObject * -builtin_divmod(PyObject *self, PyObject *args) -{ - PyObject *v, *w; - - if (!PyArg_UnpackTuple(args, "divmod", 2, 2, &v, &w)) - return NULL; - return PyNumber_Divmod(v, w); -} - -PyDoc_STRVAR(divmod_doc, -"divmod(x, y) -> (div, mod)\n\ -\n\ -Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x."); - - -static PyObject * -builtin_eval(PyObject *self, PyObject *args) -{ - PyObject *cmd, *result, *tmp = NULL; - PyObject *globals = Py_None, *locals = Py_None; - char *str; - PyCompilerFlags cf; - - if (!PyArg_UnpackTuple(args, "eval", 1, 3, &cmd, &globals, &locals)) - return NULL; - if (locals != Py_None && !PyMapping_Check(locals)) { - PyErr_SetString(PyExc_TypeError, "locals must be a mapping"); - return NULL; - } - if (globals != Py_None && !PyDict_Check(globals)) { - PyErr_SetString(PyExc_TypeError, PyMapping_Check(globals) ? - "globals must be a real dict; try eval(expr, {}, mapping)" - : "globals must be a dict"); - return NULL; - } - if (globals == Py_None) { - globals = PyEval_GetGlobals(); - if (locals == Py_None) - locals = PyEval_GetLocals(); - } - else if (locals == Py_None) - locals = globals; - - if (globals == NULL || locals == NULL) { - PyErr_SetString(PyExc_TypeError, - "eval must be given globals and locals " - "when called without a frame"); - return NULL; - } - - if (PyDict_GetItemString(globals, "__builtins__") == NULL) { - if (PyDict_SetItemString(globals, "__builtins__", - PyEval_GetBuiltins()) != 0) - return NULL; - } - - if (PyCode_Check(cmd)) { - if (PyCode_GetNumFree((PyCodeObject *)cmd) > 0) { - PyErr_SetString(PyExc_TypeError, - "code object passed to eval() may not contain free variables"); - return NULL; - } - return PyEval_EvalCode((PyCodeObject *) cmd, globals, locals); - } - - if (!PyString_Check(cmd) && - !PyUnicode_Check(cmd)) { - PyErr_SetString(PyExc_TypeError, - "eval() arg 1 must be a string or code object"); - return NULL; - } - cf.cf_flags = 0; - -#ifdef Py_USING_UNICODE - if (PyUnicode_Check(cmd)) { - tmp = PyUnicode_AsUTF8String(cmd); - if (tmp == NULL) - return NULL; - cmd = tmp; - cf.cf_flags |= PyCF_SOURCE_IS_UTF8; - } -#endif - if (PyString_AsStringAndSize(cmd, &str, NULL)) { - Py_XDECREF(tmp); - return NULL; - } - while (*str == ' ' || *str == '\t') - str++; - - (void)PyEval_MergeCompilerFlags(&cf); - result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf); - Py_XDECREF(tmp); - return result; -} - -PyDoc_STRVAR(eval_doc, -"eval(source[, globals[, locals]]) -> value\n\ -\n\ -Evaluate the source in the context of globals and locals.\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.\n"); - - -static PyObject * -builtin_execfile(PyObject *self, PyObject *args) -{ - char *filename; - PyObject *globals = Py_None, *locals = Py_None; - PyObject *res; - FILE* fp = NULL; - PyCompilerFlags cf; - int exists; - - if (!PyArg_ParseTuple(args, "s|O!O:execfile", - &filename, - &PyDict_Type, &globals, - &locals)) - return NULL; - if (locals != Py_None && !PyMapping_Check(locals)) { - PyErr_SetString(PyExc_TypeError, "locals must be a mapping"); - return NULL; - } - if (globals == Py_None) { - globals = PyEval_GetGlobals(); - if (locals == Py_None) - locals = PyEval_GetLocals(); - } - else if (locals == Py_None) - locals = globals; - if (PyDict_GetItemString(globals, "__builtins__") == NULL) { - if (PyDict_SetItemString(globals, "__builtins__", - PyEval_GetBuiltins()) != 0) - return NULL; - } - - exists = 0; - /* Test for existence or directory. */ -#if defined(PLAN9) - { - Dir *d; - - if ((d = dirstat(filename))!=nil) { - if(d->mode & DMDIR) - werrstr("is a directory"); - else - exists = 1; - free(d); - } - } -#elif defined(RISCOS) - if (object_exists(filename)) { - if (isdir(filename)) - errno = EISDIR; - else - exists = 1; - } -#else /* standard Posix */ - { - struct stat s; - if (stat(filename, &s) == 0) { - if (S_ISDIR(s.st_mode)) -# if defined(PYOS_OS2) && defined(PYCC_VACPP) - errno = EOS2ERR; -# else - errno = EISDIR; -# endif - else - exists = 1; - } - } -#endif - - if (exists) { - Py_BEGIN_ALLOW_THREADS - fp = fopen(filename, "r" PY_STDIOTEXTMODE); - Py_END_ALLOW_THREADS - - if (fp == NULL) { - exists = 0; - } - } - - if (!exists) { - PyErr_SetFromErrnoWithFilename(PyExc_IOError, filename); - return NULL; - } - cf.cf_flags = 0; - if (PyEval_MergeCompilerFlags(&cf)) - res = PyRun_FileExFlags(fp, filename, Py_file_input, globals, - locals, 1, &cf); - else - res = PyRun_FileEx(fp, filename, Py_file_input, globals, - locals, 1); - return res; -} - -PyDoc_STRVAR(execfile_doc, -"execfile(filename[, globals[, locals]])\n\ -\n\ -Read and execute a Python script from a file.\n\ -The globals and locals are dictionaries, defaulting to the current\n\ -globals and locals. If only globals is given, locals defaults to it."); - - -static PyObject * -builtin_getattr(PyObject *self, PyObject *args) -{ - PyObject *v, *result, *dflt = NULL; - PyObject *name; - - if (!PyArg_UnpackTuple(args, "getattr", 2, 3, &v, &name, &dflt)) - return NULL; -#ifdef Py_USING_UNICODE - if (PyUnicode_Check(name)) { - name = _PyUnicode_AsDefaultEncodedString(name, NULL); - if (name == NULL) - return NULL; - } -#endif - - if (!PyString_Check(name)) { - PyErr_SetString(PyExc_TypeError, - "getattr(): attribute name must be string"); - return NULL; - } - result = PyObject_GetAttr(v, name); - if (result == NULL && dflt != NULL && - PyErr_ExceptionMatches(PyExc_AttributeError)) - { - PyErr_Clear(); - Py_INCREF(dflt); - result = dflt; - } - return result; -} - -PyDoc_STRVAR(getattr_doc, -"getattr(object, name[, default]) -> value\n\ -\n\ -Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.\n\ -When a default argument is given, it is returned when the attribute doesn't\n\ -exist; without it, an exception is raised in that case."); - - -static PyObject * -builtin_globals(PyObject *self) -{ - PyObject *d; - - d = PyEval_GetGlobals(); - Py_XINCREF(d); - return d; -} - -PyDoc_STRVAR(globals_doc, -"globals() -> dictionary\n\ -\n\ -Return the dictionary containing the current scope's global variables."); - - -static PyObject * -builtin_hasattr(PyObject *self, PyObject *args) -{ - PyObject *v; - PyObject *name; - - if (!PyArg_UnpackTuple(args, "hasattr", 2, 2, &v, &name)) - return NULL; -#ifdef Py_USING_UNICODE - if (PyUnicode_Check(name)) { - name = _PyUnicode_AsDefaultEncodedString(name, NULL); - if (name == NULL) - return NULL; - } -#endif - - if (!PyString_Check(name)) { - PyErr_SetString(PyExc_TypeError, - "hasattr(): attribute name must be string"); - return NULL; - } - v = PyObject_GetAttr(v, name); - if (v == NULL) { - PyErr_Clear(); - Py_INCREF(Py_False); - return Py_False; - } - Py_DECREF(v); - Py_INCREF(Py_True); - return Py_True; -} - -PyDoc_STRVAR(hasattr_doc, -"hasattr(object, name) -> bool\n\ -\n\ -Return whether the object has an attribute with the given name.\n\ -(This is done by calling getattr(object, name) and catching exceptions.)"); - - -static PyObject * -builtin_id(PyObject *self, PyObject *v) -{ - return PyLong_FromVoidPtr(v); -} - -PyDoc_STRVAR(id_doc, -"id(object) -> integer\n\ -\n\ -Return the identity of an object. This is guaranteed to be unique among\n\ -simultaneously existing objects. (Hint: it's the object's memory address.)"); - - -static PyObject * -builtin_map(PyObject *self, PyObject *args) -{ - typedef struct { - PyObject *it; /* the iterator object */ - int saw_StopIteration; /* bool: did the iterator end? */ - } sequence; - - PyObject *func, *result; - sequence *seqs = NULL, *sqp; - Py_ssize_t n, len; - register int i, j; - - n = PyTuple_Size(args); - if (n < 2) { - PyErr_SetString(PyExc_TypeError, - "map() requires at least two args"); - return NULL; - } - - func = PyTuple_GetItem(args, 0); - n--; - - if (func == Py_None && n == 1) { - /* map(None, S) is the same as list(S). */ - return PySequence_List(PyTuple_GetItem(args, 1)); - } - - /* Get space for sequence descriptors. Must NULL out the iterator - * pointers so that jumping to Fail_2 later doesn't see trash. - */ - if ((seqs = PyMem_NEW(sequence, n)) == NULL) { - PyErr_NoMemory(); - return NULL; - } - for (i = 0; i < n; ++i) { - seqs[i].it = (PyObject*)NULL; - seqs[i].saw_StopIteration = 0; - } - - /* Do a first pass to obtain iterators for the arguments, and set len - * to the largest of their lengths. - */ - len = 0; - for (i = 0, sqp = seqs; i < n; ++i, ++sqp) { - PyObject *curseq; - Py_ssize_t curlen; - - /* Get iterator. */ - curseq = PyTuple_GetItem(args, i+1); - sqp->it = PyObject_GetIter(curseq); - if (sqp->it == NULL) { - static char errmsg[] = - "argument %d to map() must support iteration"; - char errbuf[sizeof(errmsg) + 25]; - PyOS_snprintf(errbuf, sizeof(errbuf), errmsg, i+2); - PyErr_SetString(PyExc_TypeError, errbuf); - goto Fail_2; - } - - /* Update len. */ - curlen = _PyObject_LengthHint(curseq); - if (curlen < 0) { - if (!PyErr_ExceptionMatches(PyExc_TypeError) && - !PyErr_ExceptionMatches(PyExc_AttributeError)) { - goto Fail_2; - } - PyErr_Clear(); - curlen = 8; /* arbitrary */ - } - if (curlen > len) - len = curlen; - } - - /* Get space for the result list. */ - if ((result = (PyObject *) PyList_New(len)) == NULL) - goto Fail_2; - - /* Iterate over the sequences until all have stopped. */ - for (i = 0; ; ++i) { - PyObject *alist, *item=NULL, *value; - int numactive = 0; - - if (func == Py_None && n == 1) - alist = NULL; - else if ((alist = PyTuple_New(n)) == NULL) - goto Fail_1; - - for (j = 0, sqp = seqs; j < n; ++j, ++sqp) { - if (sqp->saw_StopIteration) { - Py_INCREF(Py_None); - item = Py_None; - } - else { - item = PyIter_Next(sqp->it); - if (item) - ++numactive; - else { - if (PyErr_Occurred()) { - Py_XDECREF(alist); - goto Fail_1; - } - Py_INCREF(Py_None); - item = Py_None; - sqp->saw_StopIteration = 1; - } - } - if (alist) - PyTuple_SET_ITEM(alist, j, item); - else - break; - } - - if (!alist) - alist = item; - - if (numactive == 0) { - Py_DECREF(alist); - break; - } - - if (func == Py_None) - value = alist; - else { - value = PyEval_CallObject(func, alist); - Py_DECREF(alist); - if (value == NULL) - goto Fail_1; - } - if (i >= len) { - int status = PyList_Append(result, value); - Py_DECREF(value); - if (status < 0) - goto Fail_1; - } - else if (PyList_SetItem(result, i, value) < 0) - goto Fail_1; - } - - if (i < len && PyList_SetSlice(result, i, len, NULL) < 0) - goto Fail_1; - - goto Succeed; - -Fail_1: - Py_DECREF(result); -Fail_2: - result = NULL; -Succeed: - assert(seqs); - for (i = 0; i < n; ++i) - Py_XDECREF(seqs[i].it); - PyMem_DEL(seqs); - return result; -} - -PyDoc_STRVAR(map_doc, -"map(function, sequence[, sequence, ...]) -> list\n\ -\n\ -Return a list of the results of applying the function to the items of\n\ -the argument sequence(s). If more than one sequence is given, the\n\ -function is called with an argument list consisting of the corresponding\n\ -item of each sequence, substituting None for missing values when not all\n\ -sequences have the same length. If the function is None, return a list of\n\ -the items of the sequence (or a list of tuples if more than one sequence)."); - - -static PyObject * -builtin_setattr(PyObject *self, PyObject *args) -{ - PyObject *v; - PyObject *name; - PyObject *value; - - if (!PyArg_UnpackTuple(args, "setattr", 3, 3, &v, &name, &value)) - return NULL; - if (PyObject_SetAttr(v, name, value) != 0) - return NULL; - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(setattr_doc, -"setattr(object, name, value)\n\ -\n\ -Set a named attribute on an object; setattr(x, 'y', v) is equivalent to\n\ -``x.y = v''."); - - -static PyObject * -builtin_delattr(PyObject *self, PyObject *args) -{ - PyObject *v; - PyObject *name; - - if (!PyArg_UnpackTuple(args, "delattr", 2, 2, &v, &name)) - return NULL; - if (PyObject_SetAttr(v, name, (PyObject *)NULL) != 0) - return NULL; - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(delattr_doc, -"delattr(object, name)\n\ -\n\ -Delete a named attribute on an object; delattr(x, 'y') is equivalent to\n\ -``del x.y''."); - - -static PyObject * -builtin_hash(PyObject *self, PyObject *v) -{ - long x; - - x = PyObject_Hash(v); - if (x == -1) - return NULL; - return PyInt_FromLong(x); -} - -PyDoc_STRVAR(hash_doc, -"hash(object) -> integer\n\ -\n\ -Return a hash value for the object. Two objects with the same value have\n\ -the same hash value. The reverse is not necessarily true, but likely."); - - -static PyObject * -builtin_hex(PyObject *self, PyObject *v) -{ - PyNumberMethods *nb; - PyObject *res; - - if ((nb = v->ob_type->tp_as_number) == NULL || - nb->nb_hex == NULL) { - PyErr_SetString(PyExc_TypeError, - "hex() argument can't be converted to hex"); - return NULL; - } - res = (*nb->nb_hex)(v); - if (res && !PyString_Check(res)) { - PyErr_Format(PyExc_TypeError, - "__hex__ returned non-string (type %.200s)", - res->ob_type->tp_name); - Py_DECREF(res); - return NULL; - } - return res; -} - -PyDoc_STRVAR(hex_doc, -"hex(number) -> string\n\ -\n\ -Return the hexadecimal representation of an integer or long integer."); - - -static PyObject *builtin_raw_input(PyObject *, PyObject *); - -static PyObject * -builtin_input(PyObject *self, PyObject *args) -{ - PyObject *line; - char *str; - PyObject *res; - PyObject *globals, *locals; - PyCompilerFlags cf; - - line = builtin_raw_input(self, args); - if (line == NULL) - return line; - if (!PyArg_Parse(line, "s;embedded '\\0' in input line", &str)) - return NULL; - while (*str == ' ' || *str == '\t') - str++; - globals = PyEval_GetGlobals(); - locals = PyEval_GetLocals(); - if (PyDict_GetItemString(globals, "__builtins__") == NULL) { - if (PyDict_SetItemString(globals, "__builtins__", - PyEval_GetBuiltins()) != 0) - return NULL; - } - cf.cf_flags = 0; - PyEval_MergeCompilerFlags(&cf); - res = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf); - Py_DECREF(line); - return res; -} - -PyDoc_STRVAR(input_doc, -"input([prompt]) -> value\n\ -\n\ -Equivalent to eval(raw_input(prompt))."); - - -static PyObject * -builtin_intern(PyObject *self, PyObject *args) -{ - PyObject *s; - if (!PyArg_ParseTuple(args, "S:intern", &s)) - return NULL; - if (!PyString_CheckExact(s)) { - PyErr_SetString(PyExc_TypeError, - "can't intern subclass of string"); - return NULL; - } - Py_INCREF(s); - PyString_InternInPlace(&s); - return s; -} - -PyDoc_STRVAR(intern_doc, -"intern(string) -> string\n\ -\n\ -``Intern'' the given string. This enters the string in the (global)\n\ -table of interned strings whose purpose is to speed up dictionary lookups.\n\ -Return the string itself or the previously interned string object with the\n\ -same value."); - - -static PyObject * -builtin_iter(PyObject *self, PyObject *args) -{ - PyObject *v, *w = NULL; - - if (!PyArg_UnpackTuple(args, "iter", 1, 2, &v, &w)) - return NULL; - if (w == NULL) - return PyObject_GetIter(v); - if (!PyCallable_Check(v)) { - PyErr_SetString(PyExc_TypeError, - "iter(v, w): v must be callable"); - return NULL; - } - return PyCallIter_New(v, w); -} - -PyDoc_STRVAR(iter_doc, -"iter(collection) -> iterator\n\ -iter(callable, sentinel) -> iterator\n\ -\n\ -Get an iterator from an object. In the first form, the argument must\n\ -supply its own iterator, or be a sequence.\n\ -In the second form, the callable is called until it returns the sentinel."); - - -static PyObject * -builtin_len(PyObject *self, PyObject *v) -{ - Py_ssize_t res; - - res = PyObject_Size(v); - if (res < 0 && PyErr_Occurred()) - return NULL; - return PyInt_FromSsize_t(res); -} - -PyDoc_STRVAR(len_doc, -"len(object) -> integer\n\ -\n\ -Return the number of items of a sequence or mapping."); - - -static PyObject * -builtin_locals(PyObject *self) -{ - PyObject *d; - - d = PyEval_GetLocals(); - Py_XINCREF(d); - return d; -} - -PyDoc_STRVAR(locals_doc, -"locals() -> dictionary\n\ -\n\ -Update and return a dictionary containing the current scope's local variables."); - - -static PyObject * -min_max(PyObject *args, PyObject *kwds, int op) -{ - PyObject *v, *it, *item, *val, *maxitem, *maxval, *keyfunc=NULL; - const char *name = op == Py_LT ? "min" : "max"; - - if (PyTuple_Size(args) > 1) - v = args; - else if (!PyArg_UnpackTuple(args, (char *)name, 1, 1, &v)) - return NULL; - - if (kwds != NULL && PyDict_Check(kwds) && PyDict_Size(kwds)) { - keyfunc = PyDict_GetItemString(kwds, "key"); - if (PyDict_Size(kwds)!=1 || keyfunc == NULL) { - PyErr_Format(PyExc_TypeError, - "%s() got an unexpected keyword argument", name); - return NULL; - } - } - - it = PyObject_GetIter(v); - if (it == NULL) - return NULL; - - maxitem = NULL; /* the result */ - maxval = NULL; /* the value associated with the result */ - while (( item = PyIter_Next(it) )) { - /* get the value from the key function */ - if (keyfunc != NULL) { - val = PyObject_CallFunctionObjArgs(keyfunc, item, NULL); - if (val == NULL) - goto Fail_it_item; - } - /* no key function; the value is the item */ - else { - val = item; - Py_INCREF(val); - } - - /* maximum value and item are unset; set them */ - if (maxval == NULL) { - maxitem = item; - maxval = val; - } - /* maximum value and item are set; update them as necessary */ - else { - int cmp = PyObject_RichCompareBool(val, maxval, op); - if (cmp < 0) - goto Fail_it_item_and_val; - else if (cmp > 0) { - Py_DECREF(maxval); - Py_DECREF(maxitem); - maxval = val; - maxitem = item; - } - else { - Py_DECREF(item); - Py_DECREF(val); - } - } - } - if (PyErr_Occurred()) - goto Fail_it; - if (maxval == NULL) { - PyErr_Format(PyExc_ValueError, - "%s() arg is an empty sequence", name); - assert(maxitem == NULL); - } - else - Py_DECREF(maxval); - Py_DECREF(it); - return maxitem; - -Fail_it_item_and_val: - Py_DECREF(val); -Fail_it_item: - Py_DECREF(item); -Fail_it: - Py_XDECREF(maxval); - Py_XDECREF(maxitem); - Py_DECREF(it); - return NULL; -} - -static PyObject * -builtin_min(PyObject *self, PyObject *args, PyObject *kwds) -{ - return min_max(args, kwds, Py_LT); -} - -PyDoc_STRVAR(min_doc, -"min(iterable[, key=func]) -> value\n\ -min(a, b, c, ...[, key=func]) -> value\n\ -\n\ -With a single iterable argument, return its smallest item.\n\ -With two or more arguments, return the smallest argument."); - - -static PyObject * -builtin_max(PyObject *self, PyObject *args, PyObject *kwds) -{ - return min_max(args, kwds, Py_GT); -} - -PyDoc_STRVAR(max_doc, -"max(iterable[, key=func]) -> value\n\ -max(a, b, c, ...[, key=func]) -> value\n\ -\n\ -With a single iterable argument, return its largest item.\n\ -With two or more arguments, return the largest argument."); - - -static PyObject * -builtin_oct(PyObject *self, PyObject *v) -{ - PyNumberMethods *nb; - PyObject *res; - - if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL || - nb->nb_oct == NULL) { - PyErr_SetString(PyExc_TypeError, - "oct() argument can't be converted to oct"); - return NULL; - } - res = (*nb->nb_oct)(v); - if (res && !PyString_Check(res)) { - PyErr_Format(PyExc_TypeError, - "__oct__ returned non-string (type %.200s)", - res->ob_type->tp_name); - Py_DECREF(res); - return NULL; - } - return res; -} - -PyDoc_STRVAR(oct_doc, -"oct(number) -> string\n\ -\n\ -Return the octal representation of an integer or long integer."); - - -static PyObject * -builtin_open(PyObject *self, PyObject *args, PyObject *kwds) -{ - return PyObject_Call((PyObject*)&PyFile_Type, args, kwds); -} - -PyDoc_STRVAR(open_doc, -"open(name[, mode[, buffering]]) -> file object\n\ -\n\ -Open a file using the file() type, returns a file object."); - - -static PyObject * -builtin_ord(PyObject *self, PyObject* obj) -{ - long ord; - Py_ssize_t size; - - if (PyString_Check(obj)) { - size = PyString_GET_SIZE(obj); - if (size == 1) { - ord = (long)((unsigned char)*PyString_AS_STRING(obj)); - return PyInt_FromLong(ord); - } -#ifdef Py_USING_UNICODE - } else if (PyUnicode_Check(obj)) { - size = PyUnicode_GET_SIZE(obj); - if (size == 1) { - ord = (long)*PyUnicode_AS_UNICODE(obj); - return PyInt_FromLong(ord); - } -#endif - } else { - PyErr_Format(PyExc_TypeError, - "ord() expected string of length 1, but " \ - "%.200s found", obj->ob_type->tp_name); - return NULL; - } - - PyErr_Format(PyExc_TypeError, - "ord() expected a character, " - "but string of length %zd found", - size); - return NULL; -} - -PyDoc_STRVAR(ord_doc, -"ord(c) -> integer\n\ -\n\ -Return the integer ordinal of a one-character string."); - - -static PyObject * -builtin_pow(PyObject *self, PyObject *args) -{ - PyObject *v, *w, *z = Py_None; - - if (!PyArg_UnpackTuple(args, "pow", 2, 3, &v, &w, &z)) - return NULL; - return PyNumber_Power(v, w, z); -} - -PyDoc_STRVAR(pow_doc, -"pow(x, y[, z]) -> number\n\ -\n\ -With two arguments, equivalent to x**y. With three arguments,\n\ -equivalent to (x**y) % z, but may be more efficient (e.g. for longs)."); - - - -/* Return number of items in range (lo, hi, step), when arguments are - * PyInt or PyLong objects. step > 0 required. Return a value < 0 if - * & only if the true value is too large to fit in a signed long. - * Arguments MUST return 1 with either PyInt_Check() or - * PyLong_Check(). Return -1 when there is an error. - */ -static long -get_len_of_range_longs(PyObject *lo, PyObject *hi, PyObject *step) -{ - /* ------------------------------------------------------------- - Algorithm is equal to that of get_len_of_range(), but it operates - on PyObjects (which are assumed to be PyLong or PyInt objects). - ---------------------------------------------------------------*/ - long n; - PyObject *diff = NULL; - PyObject *one = NULL; - PyObject *tmp1 = NULL, *tmp2 = NULL, *tmp3 = NULL; - /* holds sub-expression evaluations */ - - /* if (lo >= hi), return length of 0. */ - if (PyObject_Compare(lo, hi) >= 0) - return 0; - - if ((one = PyLong_FromLong(1L)) == NULL) - goto Fail; - - if ((tmp1 = PyNumber_Subtract(hi, lo)) == NULL) - goto Fail; - - if ((diff = PyNumber_Subtract(tmp1, one)) == NULL) - goto Fail; - - if ((tmp2 = PyNumber_FloorDivide(diff, step)) == NULL) - goto Fail; - - if ((tmp3 = PyNumber_Add(tmp2, one)) == NULL) - goto Fail; - - n = PyLong_AsLong(tmp3); - if (PyErr_Occurred()) { /* Check for Overflow */ - PyErr_Clear(); - goto Fail; - } - - Py_DECREF(tmp3); - Py_DECREF(tmp2); - Py_DECREF(diff); - Py_DECREF(tmp1); - Py_DECREF(one); - return n; - - Fail: - Py_XDECREF(tmp3); - Py_XDECREF(tmp2); - Py_XDECREF(diff); - Py_XDECREF(tmp1); - Py_XDECREF(one); - return -1; -} - -/* An extension of builtin_range() that handles the case when PyLong - * arguments are given. */ -static PyObject * -handle_range_longs(PyObject *self, PyObject *args) -{ - PyObject *ilow; - PyObject *ihigh = NULL; - PyObject *istep = NULL; - - PyObject *curnum = NULL; - PyObject *v = NULL; - long bign; - int i, n; - int cmp_result; - - PyObject *zero = PyLong_FromLong(0); - - if (zero == NULL) - return NULL; - - if (!PyArg_UnpackTuple(args, "range", 1, 3, &ilow, &ihigh, &istep)) { - Py_DECREF(zero); - return NULL; - } - - /* Figure out which way we were called, supply defaults, and be - * sure to incref everything so that the decrefs at the end - * are correct. - */ - assert(ilow != NULL); - if (ihigh == NULL) { - /* only 1 arg -- it's the upper limit */ - ihigh = ilow; - ilow = NULL; - } - assert(ihigh != NULL); - Py_INCREF(ihigh); - - /* ihigh correct now; do ilow */ - if (ilow == NULL) - ilow = zero; - Py_INCREF(ilow); - - /* ilow and ihigh correct now; do istep */ - if (istep == NULL) { - istep = PyLong_FromLong(1L); - if (istep == NULL) - goto Fail; - } - else { - Py_INCREF(istep); - } - - if (!PyInt_Check(ilow) && !PyLong_Check(ilow)) { - PyErr_Format(PyExc_TypeError, - "range() integer start argument expected, got %s.", - ilow->ob_type->tp_name); - goto Fail; - } - - if (!PyInt_Check(ihigh) && !PyLong_Check(ihigh)) { - PyErr_Format(PyExc_TypeError, - "range() integer end argument expected, got %s.", - ihigh->ob_type->tp_name); - goto Fail; - } - - if (!PyInt_Check(istep) && !PyLong_Check(istep)) { - PyErr_Format(PyExc_TypeError, - "range() integer step argument expected, got %s.", - istep->ob_type->tp_name); - goto Fail; - } - - if (PyObject_Cmp(istep, zero, &cmp_result) == -1) - goto Fail; - if (cmp_result == 0) { - PyErr_SetString(PyExc_ValueError, - "range() step argument must not be zero"); - goto Fail; - } - - if (cmp_result > 0) - bign = get_len_of_range_longs(ilow, ihigh, istep); - else { - PyObject *neg_istep = PyNumber_Negative(istep); - if (neg_istep == NULL) - goto Fail; - bign = get_len_of_range_longs(ihigh, ilow, neg_istep); - Py_DECREF(neg_istep); - } - - n = (int)bign; - if (bign < 0 || (long)n != bign) { - PyErr_SetString(PyExc_OverflowError, - "range() result has too many items"); - goto Fail; - } - - v = PyList_New(n); - if (v == NULL) - goto Fail; - - curnum = ilow; - Py_INCREF(curnum); - - for (i = 0; i < n; i++) { - PyObject *w = PyNumber_Long(curnum); - PyObject *tmp_num; - if (w == NULL) - goto Fail; - - PyList_SET_ITEM(v, i, w); - - tmp_num = PyNumber_Add(curnum, istep); - if (tmp_num == NULL) - goto Fail; - - Py_DECREF(curnum); - curnum = tmp_num; - } - Py_DECREF(ilow); - Py_DECREF(ihigh); - Py_DECREF(istep); - Py_DECREF(zero); - Py_DECREF(curnum); - return v; - - Fail: - Py_DECREF(ilow); - Py_DECREF(ihigh); - Py_XDECREF(istep); - Py_DECREF(zero); - Py_XDECREF(curnum); - Py_XDECREF(v); - return NULL; -} - -/* Return number of items in range/xrange (lo, hi, step). step > 0 - * required. Return a value < 0 if & only if the true value is too - * large to fit in a signed long. - */ -static long -get_len_of_range(long lo, long hi, long step) -{ - /* ------------------------------------------------------------- - If lo >= hi, the range is empty. - Else if n values are in the range, the last one is - lo + (n-1)*step, which must be <= hi-1. Rearranging, - n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives - the proper value. Since lo < hi in this case, hi-lo-1 >= 0, so - the RHS is non-negative and so truncation is the same as the - floor. Letting M be the largest positive long, the worst case - for the RHS numerator is hi=M, lo=-M-1, and then - hi-lo-1 = M-(-M-1)-1 = 2*M. Therefore unsigned long has enough - precision to compute the RHS exactly. - ---------------------------------------------------------------*/ - long n = 0; - if (lo < hi) { - unsigned long uhi = (unsigned long)hi; - unsigned long ulo = (unsigned long)lo; - unsigned long diff = uhi - ulo - 1; - n = (long)(diff / (unsigned long)step + 1); - } - return n; -} - -static PyObject * -builtin_range(PyObject *self, PyObject *args) -{ - long ilow = 0, ihigh = 0, istep = 1; - long bign; - int i, n; - - PyObject *v; - - if (PyTuple_Size(args) <= 1) { - if (!PyArg_ParseTuple(args, - "l;range() requires 1-3 int arguments", - &ihigh)) { - PyErr_Clear(); - return handle_range_longs(self, args); - } - } - else { - if (!PyArg_ParseTuple(args, - "ll|l;range() requires 1-3 int arguments", - &ilow, &ihigh, &istep)) { - PyErr_Clear(); - return handle_range_longs(self, args); - } - } - if (istep == 0) { - PyErr_SetString(PyExc_ValueError, - "range() step argument must not be zero"); - return NULL; - } - if (istep > 0) - bign = get_len_of_range(ilow, ihigh, istep); - else - bign = get_len_of_range(ihigh, ilow, -istep); - n = (int)bign; - if (bign < 0 || (long)n != bign) { - PyErr_SetString(PyExc_OverflowError, - "range() result has too many items"); - return NULL; - } - v = PyList_New(n); - if (v == NULL) - return NULL; - for (i = 0; i < n; i++) { - PyObject *w = PyInt_FromLong(ilow); - if (w == NULL) { - Py_DECREF(v); - return NULL; - } - PyList_SET_ITEM(v, i, w); - ilow += istep; - } - return v; -} - -PyDoc_STRVAR(range_doc, -"range([start,] stop[, step]) -> list of integers\n\ -\n\ -Return a list containing an arithmetic progression of integers.\n\ -range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.\n\ -When step is given, it specifies the increment (or decrement).\n\ -For example, range(4) returns [0, 1, 2, 3]. The end point is omitted!\n\ -These are exactly the valid indices for a list of 4 elements."); - - -static PyObject * -builtin_raw_input(PyObject *self, PyObject *args) -{ - PyObject *v = NULL; - PyObject *fin = PySys_GetObject("stdin"); - PyObject *fout = PySys_GetObject("stdout"); - - if (!PyArg_UnpackTuple(args, "[raw_]input", 0, 1, &v)) - return NULL; - - if (fin == NULL) { - PyErr_SetString(PyExc_RuntimeError, "[raw_]input: lost sys.stdin"); - return NULL; - } - if (fout == NULL) { - PyErr_SetString(PyExc_RuntimeError, "[raw_]input: lost sys.stdout"); - return NULL; - } - if (PyFile_SoftSpace(fout, 0)) { - if (PyFile_WriteString(" ", fout) != 0) - return NULL; - } - if (PyFile_AsFile(fin) && PyFile_AsFile(fout) - && isatty(fileno(PyFile_AsFile(fin))) - && isatty(fileno(PyFile_AsFile(fout)))) { - PyObject *po; - char *prompt; - char *s; - PyObject *result; - if (v != NULL) { - po = PyObject_Str(v); - if (po == NULL) - return NULL; - prompt = PyString_AsString(po); - if (prompt == NULL) - return NULL; - } - else { - po = NULL; - prompt = ""; - } - s = PyOS_Readline(PyFile_AsFile(fin), PyFile_AsFile(fout), - prompt); - Py_XDECREF(po); - if (s == NULL) { - if (!PyErr_Occurred()) - PyErr_SetNone(PyExc_KeyboardInterrupt); - return NULL; - } - if (*s == '\0') { - PyErr_SetNone(PyExc_EOFError); - result = NULL; - } - else { /* strip trailing '\n' */ - size_t len = strlen(s); - if (len > PY_SSIZE_T_MAX) { - PyErr_SetString(PyExc_OverflowError, - "[raw_]input: input too long"); - result = NULL; - } - else { - result = PyString_FromStringAndSize(s, len-1); - } - } - PyMem_FREE(s); - return result; - } - if (v != NULL) { - if (PyFile_WriteObject(v, fout, Py_PRINT_RAW) != 0) - return NULL; - } - return PyFile_GetLine(fin, -1); -} - -PyDoc_STRVAR(raw_input_doc, -"raw_input([prompt]) -> string\n\ -\n\ -Read a string from standard input. The trailing newline is stripped.\n\ -If the user hits EOF (Unix: Ctl-D, Windows: Ctl-Z+Return), raise EOFError.\n\ -On Unix, GNU readline is used if enabled. The prompt string, if given,\n\ -is printed without a trailing newline before reading."); - - -static PyObject * -builtin_reduce(PyObject *self, PyObject *args) -{ - PyObject *seq, *func, *result = NULL, *it; - - if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result)) - return NULL; - if (result != NULL) - Py_INCREF(result); - - it = PyObject_GetIter(seq); - if (it == NULL) { - PyErr_SetString(PyExc_TypeError, - "reduce() arg 2 must support iteration"); - Py_XDECREF(result); - return NULL; - } - - if ((args = PyTuple_New(2)) == NULL) - goto Fail; - - for (;;) { - PyObject *op2; - - if (args->ob_refcnt > 1) { - Py_DECREF(args); - if ((args = PyTuple_New(2)) == NULL) - goto Fail; - } - - op2 = PyIter_Next(it); - if (op2 == NULL) { - if (PyErr_Occurred()) - goto Fail; - break; - } - - if (result == NULL) - result = op2; - else { - PyTuple_SetItem(args, 0, result); - PyTuple_SetItem(args, 1, op2); - if ((result = PyEval_CallObject(func, args)) == NULL) - goto Fail; - } - } - - Py_DECREF(args); - - if (result == NULL) - PyErr_SetString(PyExc_TypeError, - "reduce() of empty sequence with no initial value"); - - Py_DECREF(it); - return result; - -Fail: - Py_XDECREF(args); - Py_XDECREF(result); - Py_DECREF(it); - return NULL; -} - -PyDoc_STRVAR(reduce_doc, -"reduce(function, sequence[, initial]) -> value\n\ -\n\ -Apply a function of two arguments cumulatively to the items of a sequence,\n\ -from left to right, so as to reduce the sequence to a single value.\n\ -For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\ -((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\ -of the sequence in the calculation, and serves as a default when the\n\ -sequence is empty."); - - -static PyObject * -builtin_reload(PyObject *self, PyObject *v) -{ - return PyImport_ReloadModule(v); -} - -PyDoc_STRVAR(reload_doc, -"reload(module) -> module\n\ -\n\ -Reload the module. The module must have been successfully imported before."); - - -static PyObject * -builtin_repr(PyObject *self, PyObject *v) -{ - return PyObject_Repr(v); -} - -PyDoc_STRVAR(repr_doc, -"repr(object) -> string\n\ -\n\ -Return the canonical string representation of the object.\n\ -For most object types, eval(repr(object)) == object."); - - -static PyObject * -builtin_round(PyObject *self, PyObject *args, PyObject *kwds) -{ - double number; - double f; - int ndigits = 0; - int i; - static char *kwlist[] = {"number", "ndigits", 0}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "d|i:round", - kwlist, &number, &ndigits)) - return NULL; - f = 1.0; - i = abs(ndigits); - while (--i >= 0) - f = f*10.0; - if (ndigits < 0) - number /= f; - else - number *= f; - if (number >= 0.0) - number = floor(number + 0.5); - else - number = ceil(number - 0.5); - if (ndigits < 0) - number *= f; - else - number /= f; - return PyFloat_FromDouble(number); -} - -PyDoc_STRVAR(round_doc, -"round(number[, ndigits]) -> floating point number\n\ -\n\ -Round a number to a given precision in decimal digits (default 0 digits).\n\ -This always returns a floating point number. Precision may be negative."); - -static PyObject * -builtin_sorted(PyObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *newlist, *v, *seq, *compare=NULL, *keyfunc=NULL, *newargs; - PyObject *callable; - static char *kwlist[] = {"iterable", "cmp", "key", "reverse", 0}; - int reverse; - - /* args 1-4 should match listsort in Objects/listobject.c */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOi:sorted", - kwlist, &seq, &compare, &keyfunc, &reverse)) - return NULL; - - newlist = PySequence_List(seq); - if (newlist == NULL) - return NULL; - - callable = PyObject_GetAttrString(newlist, "sort"); - if (callable == NULL) { - Py_DECREF(newlist); - return NULL; - } - - newargs = PyTuple_GetSlice(args, 1, 4); - if (newargs == NULL) { - Py_DECREF(newlist); - Py_DECREF(callable); - return NULL; - } - - v = PyObject_Call(callable, newargs, kwds); - Py_DECREF(newargs); - Py_DECREF(callable); - if (v == NULL) { - Py_DECREF(newlist); - return NULL; - } - Py_DECREF(v); - return newlist; -} - -PyDoc_STRVAR(sorted_doc, -"sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list"); - -static PyObject * -builtin_vars(PyObject *self, PyObject *args) -{ - PyObject *v = NULL; - PyObject *d; - - if (!PyArg_UnpackTuple(args, "vars", 0, 1, &v)) - return NULL; - if (v == NULL) { - d = PyEval_GetLocals(); - if (d == NULL) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_SystemError, - "vars(): no locals!?"); - } - else - Py_INCREF(d); - } - else { - d = PyObject_GetAttrString(v, "__dict__"); - if (d == NULL) { - PyErr_SetString(PyExc_TypeError, - "vars() argument must have __dict__ attribute"); - return NULL; - } - } - return d; -} - -PyDoc_STRVAR(vars_doc, -"vars([object]) -> dictionary\n\ -\n\ -Without arguments, equivalent to locals().\n\ -With an argument, equivalent to object.__dict__."); - - -static PyObject* -builtin_sum(PyObject *self, PyObject *args) -{ - PyObject *seq; - PyObject *result = NULL; - PyObject *temp, *item, *iter; - - if (!PyArg_UnpackTuple(args, "sum", 1, 2, &seq, &result)) - return NULL; - - iter = PyObject_GetIter(seq); - if (iter == NULL) - return NULL; - - if (result == NULL) { - result = PyInt_FromLong(0); - if (result == NULL) { - Py_DECREF(iter); - return NULL; - } - } else { - /* reject string values for 'start' parameter */ - if (PyObject_TypeCheck(result, &PyBaseString_Type)) { - PyErr_SetString(PyExc_TypeError, - "sum() can't sum strings [use ''.join(seq) instead]"); - Py_DECREF(iter); - return NULL; - } - Py_INCREF(result); - } - - for(;;) { - item = PyIter_Next(iter); - if (item == NULL) { - /* error, or end-of-sequence */ - if (PyErr_Occurred()) { - Py_DECREF(result); - result = NULL; - } - break; - } - temp = PyNumber_Add(result, item); - Py_DECREF(result); - Py_DECREF(item); - result = temp; - if (result == NULL) - break; - } - Py_DECREF(iter); - return result; -} - -PyDoc_STRVAR(sum_doc, -"sum(sequence, start=0) -> value\n\ -\n\ -Returns the sum of a sequence of numbers (NOT strings) plus the value\n\ -of parameter 'start'. When the sequence is empty, returns start."); - - -static PyObject * -builtin_isinstance(PyObject *self, PyObject *args) -{ - PyObject *inst; - PyObject *cls; - int retval; - - if (!PyArg_UnpackTuple(args, "isinstance", 2, 2, &inst, &cls)) - return NULL; - - retval = PyObject_IsInstance(inst, cls); - if (retval < 0) - return NULL; - return PyBool_FromLong(retval); -} - -PyDoc_STRVAR(isinstance_doc, -"isinstance(object, class-or-type-or-tuple) -> bool\n\ -\n\ -Return whether an object is an instance of a class or of a subclass thereof.\n\ -With a type as second argument, return whether that is the object's type.\n\ -The form using a tuple, isinstance(x, (A, B, ...)), is a shortcut for\n\ -isinstance(x, A) or isinstance(x, B) or ... (etc.)."); - - -static PyObject * -builtin_issubclass(PyObject *self, PyObject *args) -{ - PyObject *derived; - PyObject *cls; - int retval; - - if (!PyArg_UnpackTuple(args, "issubclass", 2, 2, &derived, &cls)) - return NULL; - - retval = PyObject_IsSubclass(derived, cls); - if (retval < 0) - return NULL; - return PyBool_FromLong(retval); -} - -PyDoc_STRVAR(issubclass_doc, -"issubclass(C, B) -> bool\n\ -\n\ -Return whether class C is a subclass (i.e., a derived class) of class B.\n\ -When using a tuple as the second argument issubclass(X, (A, B, ...)),\n\ -is a shortcut for issubclass(X, A) or issubclass(X, B) or ... (etc.)."); - - -static PyObject* -builtin_zip(PyObject *self, PyObject *args) -{ - PyObject *ret; - const Py_ssize_t itemsize = PySequence_Length(args); - Py_ssize_t i; - PyObject *itlist; /* tuple of iterators */ - Py_ssize_t len; /* guess at result length */ - - if (itemsize == 0) - return PyList_New(0); - - /* args must be a tuple */ - assert(PyTuple_Check(args)); - - /* Guess at result length: the shortest of the input lengths. - If some argument refuses to say, we refuse to guess too, lest - an argument like xrange(sys.maxint) lead us astray.*/ - len = -1; /* unknown */ - for (i = 0; i < itemsize; ++i) { - PyObject *item = PyTuple_GET_ITEM(args, i); - Py_ssize_t thislen = _PyObject_LengthHint(item); - if (thislen < 0) { - if (!PyErr_ExceptionMatches(PyExc_TypeError) && - !PyErr_ExceptionMatches(PyExc_AttributeError)) { - return NULL; - } - PyErr_Clear(); - len = -1; - break; - } - else if (len < 0 || thislen < len) - len = thislen; - } - - /* allocate result list */ - if (len < 0) - len = 10; /* arbitrary */ - if ((ret = PyList_New(len)) == NULL) - return NULL; - - /* obtain iterators */ - itlist = PyTuple_New(itemsize); - if (itlist == NULL) - goto Fail_ret; - for (i = 0; i < itemsize; ++i) { - PyObject *item = PyTuple_GET_ITEM(args, i); - PyObject *it = PyObject_GetIter(item); - if (it == NULL) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_Format(PyExc_TypeError, - "zip argument #%zd must support iteration", - i+1); - goto Fail_ret_itlist; - } - PyTuple_SET_ITEM(itlist, i, it); - } - - /* build result into ret list */ - for (i = 0; ; ++i) { - int j; - PyObject *next = PyTuple_New(itemsize); - if (!next) - goto Fail_ret_itlist; - - for (j = 0; j < itemsize; j++) { - PyObject *it = PyTuple_GET_ITEM(itlist, j); - PyObject *item = PyIter_Next(it); - if (!item) { - if (PyErr_Occurred()) { - Py_DECREF(ret); - ret = NULL; - } - Py_DECREF(next); - Py_DECREF(itlist); - goto Done; - } - PyTuple_SET_ITEM(next, j, item); - } - - if (i < len) - PyList_SET_ITEM(ret, i, next); - else { - int status = PyList_Append(ret, next); - Py_DECREF(next); - ++len; - if (status < 0) - goto Fail_ret_itlist; - } - } - -Done: - if (ret != NULL && i < len) { - /* The list is too big. */ - if (PyList_SetSlice(ret, i, len, NULL) < 0) - return NULL; - } - return ret; - -Fail_ret_itlist: - Py_DECREF(itlist); -Fail_ret: - Py_DECREF(ret); - return NULL; -} - - -PyDoc_STRVAR(zip_doc, -"zip(seq1 [, seq2 [...]]) -> [(seq1[0], seq2[0] ...), (...)]\n\ -\n\ -Return a list of tuples, where each tuple contains the i-th element\n\ -from each of the argument sequences. The returned list is truncated\n\ -in length to the length of the shortest argument sequence."); - - -static PyMethodDef builtin_methods[] = { - {"__import__", (PyCFunction)builtin___import__, METH_VARARGS | METH_KEYWORDS, import_doc}, - {"abs", builtin_abs, METH_O, abs_doc}, - {"all", builtin_all, METH_O, all_doc}, - {"any", builtin_any, METH_O, any_doc}, - {"apply", builtin_apply, METH_VARARGS, apply_doc}, - {"callable", builtin_callable, METH_O, callable_doc}, - {"chr", builtin_chr, METH_VARARGS, chr_doc}, - {"cmp", builtin_cmp, METH_VARARGS, cmp_doc}, - {"coerce", builtin_coerce, METH_VARARGS, coerce_doc}, - {"compile", builtin_compile, METH_VARARGS, compile_doc}, - {"delattr", builtin_delattr, METH_VARARGS, delattr_doc}, - {"dir", builtin_dir, METH_VARARGS, dir_doc}, - {"divmod", builtin_divmod, METH_VARARGS, divmod_doc}, - {"eval", builtin_eval, METH_VARARGS, eval_doc}, - {"execfile", builtin_execfile, METH_VARARGS, execfile_doc}, - {"filter", builtin_filter, METH_VARARGS, filter_doc}, - {"getattr", builtin_getattr, METH_VARARGS, getattr_doc}, - {"globals", (PyCFunction)builtin_globals, METH_NOARGS, globals_doc}, - {"hasattr", builtin_hasattr, METH_VARARGS, hasattr_doc}, - {"hash", builtin_hash, METH_O, hash_doc}, - {"hex", builtin_hex, METH_O, hex_doc}, - {"id", builtin_id, METH_O, id_doc}, - {"input", builtin_input, METH_VARARGS, input_doc}, - {"intern", builtin_intern, METH_VARARGS, intern_doc}, - {"isinstance", builtin_isinstance, METH_VARARGS, isinstance_doc}, - {"issubclass", builtin_issubclass, METH_VARARGS, issubclass_doc}, - {"iter", builtin_iter, METH_VARARGS, iter_doc}, - {"len", builtin_len, METH_O, len_doc}, - {"locals", (PyCFunction)builtin_locals, METH_NOARGS, locals_doc}, - {"map", builtin_map, METH_VARARGS, map_doc}, - {"max", (PyCFunction)builtin_max, METH_VARARGS | METH_KEYWORDS, max_doc}, - {"min", (PyCFunction)builtin_min, METH_VARARGS | METH_KEYWORDS, min_doc}, - {"oct", builtin_oct, METH_O, oct_doc}, - {"open", (PyCFunction)builtin_open, METH_VARARGS | METH_KEYWORDS, open_doc}, - {"ord", builtin_ord, METH_O, ord_doc}, - {"pow", builtin_pow, METH_VARARGS, pow_doc}, - {"range", builtin_range, METH_VARARGS, range_doc}, - {"raw_input", builtin_raw_input, METH_VARARGS, raw_input_doc}, - {"reduce", builtin_reduce, METH_VARARGS, reduce_doc}, - {"reload", builtin_reload, METH_O, reload_doc}, - {"repr", builtin_repr, METH_O, repr_doc}, - {"round", (PyCFunction)builtin_round, METH_VARARGS | METH_KEYWORDS, round_doc}, - {"setattr", builtin_setattr, METH_VARARGS, setattr_doc}, - {"sorted", (PyCFunction)builtin_sorted, METH_VARARGS | METH_KEYWORDS, sorted_doc}, - {"sum", builtin_sum, METH_VARARGS, sum_doc}, -#ifdef Py_USING_UNICODE - {"unichr", builtin_unichr, METH_VARARGS, unichr_doc}, -#endif - {"vars", builtin_vars, METH_VARARGS, vars_doc}, - {"zip", builtin_zip, METH_VARARGS, zip_doc}, - {NULL, NULL}, -}; - -PyDoc_STRVAR(builtin_doc, -"Built-in functions, exceptions, and other objects.\n\ -\n\ -Noteworthy: None is the `nil' object; Ellipsis represents `...' in slices."); - -PyObject * -_PyBuiltin_Init(void) -{ - PyObject *mod, *dict, *debug; - mod = Py_InitModule4("__builtin__", builtin_methods, - builtin_doc, (PyObject *)NULL, - PYTHON_API_VERSION); - if (mod == NULL) - return NULL; - dict = PyModule_GetDict(mod); - -#ifdef Py_TRACE_REFS - /* __builtin__ exposes a number of statically allocated objects - * that, before this code was added in 2.3, never showed up in - * the list of "all objects" maintained by Py_TRACE_REFS. As a - * result, programs leaking references to None and False (etc) - * couldn't be diagnosed by examining sys.getobjects(0). - */ -#define ADD_TO_ALL(OBJECT) _Py_AddToAllObjects((PyObject *)(OBJECT), 0) -#else -#define ADD_TO_ALL(OBJECT) (void)0 -#endif - -#define SETBUILTIN(NAME, OBJECT) \ - if (PyDict_SetItemString(dict, NAME, (PyObject *)OBJECT) < 0) \ - return NULL; \ - ADD_TO_ALL(OBJECT) - - SETBUILTIN("None", Py_None); - SETBUILTIN("Ellipsis", Py_Ellipsis); - SETBUILTIN("NotImplemented", Py_NotImplemented); - SETBUILTIN("False", Py_False); - SETBUILTIN("True", Py_True); - SETBUILTIN("basestring", &PyBaseString_Type); - SETBUILTIN("bool", &PyBool_Type); - SETBUILTIN("buffer", &PyBuffer_Type); - SETBUILTIN("classmethod", &PyClassMethod_Type); -#ifndef WITHOUT_COMPLEX - SETBUILTIN("complex", &PyComplex_Type); -#endif - SETBUILTIN("dict", &PyDict_Type); - SETBUILTIN("enumerate", &PyEnum_Type); - SETBUILTIN("file", &PyFile_Type); - SETBUILTIN("float", &PyFloat_Type); - SETBUILTIN("frozenset", &PyFrozenSet_Type); - SETBUILTIN("property", &PyProperty_Type); - SETBUILTIN("int", &PyInt_Type); - SETBUILTIN("list", &PyList_Type); - SETBUILTIN("long", &PyLong_Type); - SETBUILTIN("object", &PyBaseObject_Type); - SETBUILTIN("reversed", &PyReversed_Type); - SETBUILTIN("set", &PySet_Type); - SETBUILTIN("slice", &PySlice_Type); - SETBUILTIN("staticmethod", &PyStaticMethod_Type); - SETBUILTIN("str", &PyString_Type); - SETBUILTIN("super", &PySuper_Type); - SETBUILTIN("tuple", &PyTuple_Type); - SETBUILTIN("type", &PyType_Type); - SETBUILTIN("xrange", &PyRange_Type); -#ifdef Py_USING_UNICODE - SETBUILTIN("unicode", &PyUnicode_Type); -#endif - debug = PyBool_FromLong(Py_OptimizeFlag == 0); - if (PyDict_SetItemString(dict, "__debug__", debug) < 0) { - Py_XDECREF(debug); - return NULL; - } - Py_XDECREF(debug); - - return mod; -#undef ADD_TO_ALL -#undef SETBUILTIN -} - -/* Helper for filter(): filter a tuple through a function */ - -static PyObject * -filtertuple(PyObject *func, PyObject *tuple) -{ - PyObject *result; - Py_ssize_t i, j; - Py_ssize_t len = PyTuple_Size(tuple); - - if (len == 0) { - if (PyTuple_CheckExact(tuple)) - Py_INCREF(tuple); - else - tuple = PyTuple_New(0); - return tuple; - } - - if ((result = PyTuple_New(len)) == NULL) - return NULL; - - for (i = j = 0; i < len; ++i) { - PyObject *item, *good; - int ok; - - if (tuple->ob_type->tp_as_sequence && - tuple->ob_type->tp_as_sequence->sq_item) { - item = tuple->ob_type->tp_as_sequence->sq_item(tuple, i); - if (item == NULL) - goto Fail_1; - } else { - PyErr_SetString(PyExc_TypeError, "filter(): unsubscriptable tuple"); - goto Fail_1; - } - if (func == Py_None) { - Py_INCREF(item); - good = item; - } - else { - PyObject *arg = PyTuple_Pack(1, item); - if (arg == NULL) { - Py_DECREF(item); - goto Fail_1; - } - good = PyEval_CallObject(func, arg); - Py_DECREF(arg); - if (good == NULL) { - Py_DECREF(item); - goto Fail_1; - } - } - ok = PyObject_IsTrue(good); - Py_DECREF(good); - if (ok) { - if (PyTuple_SetItem(result, j++, item) < 0) - goto Fail_1; - } - else - Py_DECREF(item); - } - - if (_PyTuple_Resize(&result, j) < 0) - return NULL; - - return result; - -Fail_1: - Py_DECREF(result); - return NULL; -} - - -/* Helper for filter(): filter a string through a function */ - -static PyObject * -filterstring(PyObject *func, PyObject *strobj) -{ - PyObject *result; - Py_ssize_t i, j; - Py_ssize_t len = PyString_Size(strobj); - Py_ssize_t outlen = len; - - if (func == Py_None) { - /* If it's a real string we can return the original, - * as no character is ever false and __getitem__ - * does return this character. If it's a subclass - * we must go through the __getitem__ loop */ - if (PyString_CheckExact(strobj)) { - Py_INCREF(strobj); - return strobj; - } - } - if ((result = PyString_FromStringAndSize(NULL, len)) == NULL) - return NULL; - - for (i = j = 0; i < len; ++i) { - PyObject *item; - int ok; - - item = (*strobj->ob_type->tp_as_sequence->sq_item)(strobj, i); - if (item == NULL) - goto Fail_1; - if (func==Py_None) { - ok = 1; - } else { - PyObject *arg, *good; - arg = PyTuple_Pack(1, item); - if (arg == NULL) { - Py_DECREF(item); - goto Fail_1; - } - good = PyEval_CallObject(func, arg); - Py_DECREF(arg); - if (good == NULL) { - Py_DECREF(item); - goto Fail_1; - } - ok = PyObject_IsTrue(good); - Py_DECREF(good); - } - if (ok) { - Py_ssize_t reslen; - if (!PyString_Check(item)) { - PyErr_SetString(PyExc_TypeError, "can't filter str to str:" - " __getitem__ returned different type"); - Py_DECREF(item); - goto Fail_1; - } - reslen = PyString_GET_SIZE(item); - if (reslen == 1) { - PyString_AS_STRING(result)[j++] = - PyString_AS_STRING(item)[0]; - } else { - /* do we need more space? */ - Py_ssize_t need = j + reslen + len-i-1; - if (need > outlen) { - /* overallocate, to avoid reallocations */ - if (need<2*outlen) - need = 2*outlen; - if (_PyString_Resize(&result, need)) { - Py_DECREF(item); - return NULL; - } - outlen = need; - } - memcpy( - PyString_AS_STRING(result) + j, - PyString_AS_STRING(item), - reslen - ); - j += reslen; - } - } - Py_DECREF(item); - } - - if (j < outlen) - _PyString_Resize(&result, j); - - return result; - -Fail_1: - Py_DECREF(result); - return NULL; -} - -#ifdef Py_USING_UNICODE -/* Helper for filter(): filter a Unicode object through a function */ - -static PyObject * -filterunicode(PyObject *func, PyObject *strobj) -{ - PyObject *result; - register Py_ssize_t i, j; - Py_ssize_t len = PyUnicode_GetSize(strobj); - Py_ssize_t outlen = len; - - if (func == Py_None) { - /* If it's a real string we can return the original, - * as no character is ever false and __getitem__ - * does return this character. If it's a subclass - * we must go through the __getitem__ loop */ - if (PyUnicode_CheckExact(strobj)) { - Py_INCREF(strobj); - return strobj; - } - } - if ((result = PyUnicode_FromUnicode(NULL, len)) == NULL) - return NULL; - - for (i = j = 0; i < len; ++i) { - PyObject *item, *arg, *good; - int ok; - - item = (*strobj->ob_type->tp_as_sequence->sq_item)(strobj, i); - if (item == NULL) - goto Fail_1; - if (func == Py_None) { - ok = 1; - } else { - arg = PyTuple_Pack(1, item); - if (arg == NULL) { - Py_DECREF(item); - goto Fail_1; - } - good = PyEval_CallObject(func, arg); - Py_DECREF(arg); - if (good == NULL) { - Py_DECREF(item); - goto Fail_1; - } - ok = PyObject_IsTrue(good); - Py_DECREF(good); - } - if (ok) { - Py_ssize_t reslen; - if (!PyUnicode_Check(item)) { - PyErr_SetString(PyExc_TypeError, - "can't filter unicode to unicode:" - " __getitem__ returned different type"); - Py_DECREF(item); - goto Fail_1; - } - reslen = PyUnicode_GET_SIZE(item); - if (reslen == 1) - PyUnicode_AS_UNICODE(result)[j++] = - PyUnicode_AS_UNICODE(item)[0]; - else { - /* do we need more space? */ - Py_ssize_t need = j + reslen + len - i - 1; - if (need > outlen) { - /* overallocate, - to avoid reallocations */ - if (need < 2 * outlen) - need = 2 * outlen; - if (PyUnicode_Resize( - &result, need) < 0) { - Py_DECREF(item); - goto Fail_1; - } - outlen = need; - } - memcpy(PyUnicode_AS_UNICODE(result) + j, - PyUnicode_AS_UNICODE(item), - reslen*sizeof(Py_UNICODE)); - j += reslen; - } - } - Py_DECREF(item); - } - - if (j < outlen) - PyUnicode_Resize(&result, j); - - return result; - -Fail_1: - Py_DECREF(result); - return NULL; -} -#endif diff --git a/sys/src/cmd/python/Python/ceval.c b/sys/src/cmd/python/Python/ceval.c deleted file mode 100644 index 597ae481f..000000000 --- a/sys/src/cmd/python/Python/ceval.c +++ /dev/null @@ -1,4351 +0,0 @@ - -/* Execute compiled code */ - -/* XXX TO DO: - XXX speed up searching for keywords by using a dictionary - XXX document it! - */ - -/* enable more aggressive intra-module optimizations, where available */ -#define PY_LOCAL_AGGRESSIVE - -#include "Python.h" - -#include "code.h" -#include "frameobject.h" -#include "eval.h" -#include "opcode.h" -#include "structmember.h" - -#include <ctype.h> - -#ifndef WITH_TSC - -#define READ_TIMESTAMP(var) - -#else - -typedef unsigned long long uint64; - -#if defined(__ppc__) /* <- Don't know if this is the correct symbol; this - section should work for GCC on any PowerPC platform, - irrespective of OS. POWER? Who knows :-) */ - -#define READ_TIMESTAMP(var) ppc_getcounter(&var) - -static void -ppc_getcounter(uint64 *v) -{ - register unsigned long tbu, tb, tbu2; - - loop: - asm volatile ("mftbu %0" : "=r" (tbu) ); - asm volatile ("mftb %0" : "=r" (tb) ); - asm volatile ("mftbu %0" : "=r" (tbu2)); - if (__builtin_expect(tbu != tbu2, 0)) goto loop; - - /* The slightly peculiar way of writing the next lines is - compiled better by GCC than any other way I tried. */ - ((long*)(v))[0] = tbu; - ((long*)(v))[1] = tb; -} - -#else /* this is for linux/x86 (and probably any other GCC/x86 combo) */ - -#define READ_TIMESTAMP(val) \ - __asm__ __volatile__("rdtsc" : "=A" (val)) - -#endif - -void dump_tsc(int opcode, int ticked, uint64 inst0, uint64 inst1, - uint64 loop0, uint64 loop1, uint64 intr0, uint64 intr1) -{ - uint64 intr, inst, loop; - PyThreadState *tstate = PyThreadState_Get(); - if (!tstate->interp->tscdump) - return; - intr = intr1 - intr0; - inst = inst1 - inst0 - intr; - loop = loop1 - loop0 - intr; - fprintf(stderr, "opcode=%03d t=%d inst=%06lld loop=%06lld\n", - opcode, ticked, inst, loop); -} - -#endif - -/* Turn this on if your compiler chokes on the big switch: */ -/* #define CASE_TOO_BIG 1 */ - -#ifdef Py_DEBUG -/* For debugging the interpreter: */ -#define LLTRACE 1 /* Low-level trace feature */ -#define CHECKEXC 1 /* Double-check exception checking */ -#endif - -typedef PyObject *(*callproc)(PyObject *, PyObject *, PyObject *); - -/* Forward declarations */ -#ifdef WITH_TSC -static PyObject * call_function(PyObject ***, int, uint64*, uint64*); -#else -static PyObject * call_function(PyObject ***, int); -#endif -static PyObject * fast_function(PyObject *, PyObject ***, int, int, int); -static PyObject * do_call(PyObject *, PyObject ***, int, int); -static PyObject * ext_do_call(PyObject *, PyObject ***, int, int, int); -static PyObject * update_keyword_args(PyObject *, int, PyObject ***,PyObject *); -static PyObject * update_star_args(int, int, PyObject *, PyObject ***); -static PyObject * load_args(PyObject ***, int); -#define CALL_FLAG_VAR 1 -#define CALL_FLAG_KW 2 - -#ifdef LLTRACE -static int lltrace; -static int prtrace(PyObject *, char *); -#endif -static int call_trace(Py_tracefunc, PyObject *, PyFrameObject *, - int, PyObject *); -static void call_trace_protected(Py_tracefunc, PyObject *, - PyFrameObject *, int, PyObject *); -static void call_exc_trace(Py_tracefunc, PyObject *, PyFrameObject *); -static int maybe_call_line_trace(Py_tracefunc, PyObject *, - PyFrameObject *, int *, int *, int *); - -static PyObject * apply_slice(PyObject *, PyObject *, PyObject *); -static int assign_slice(PyObject *, PyObject *, - PyObject *, PyObject *); -static PyObject * cmp_outcome(int, PyObject *, PyObject *); -static PyObject * import_from(PyObject *, PyObject *); -static int import_all_from(PyObject *, PyObject *); -static PyObject * build_class(PyObject *, PyObject *, PyObject *); -static int exec_statement(PyFrameObject *, - PyObject *, PyObject *, PyObject *); -static void set_exc_info(PyThreadState *, PyObject *, PyObject *, PyObject *); -static void reset_exc_info(PyThreadState *); -static void format_exc_check_arg(PyObject *, char *, PyObject *); -static PyObject * string_concatenate(PyObject *, PyObject *, - PyFrameObject *, unsigned char *); - -#define NAME_ERROR_MSG \ - "name '%.200s' is not defined" -#define GLOBAL_NAME_ERROR_MSG \ - "global name '%.200s' is not defined" -#define UNBOUNDLOCAL_ERROR_MSG \ - "local variable '%.200s' referenced before assignment" -#define UNBOUNDFREE_ERROR_MSG \ - "free variable '%.200s' referenced before assignment" \ - " in enclosing scope" - -/* Dynamic execution profile */ -#ifdef DYNAMIC_EXECUTION_PROFILE -#ifdef DXPAIRS -static long dxpairs[257][256]; -#define dxp dxpairs[256] -#else -static long dxp[256]; -#endif -#endif - -/* Function call profile */ -#ifdef CALL_PROFILE -#define PCALL_NUM 11 -static int pcall[PCALL_NUM]; - -#define PCALL_ALL 0 -#define PCALL_FUNCTION 1 -#define PCALL_FAST_FUNCTION 2 -#define PCALL_FASTER_FUNCTION 3 -#define PCALL_METHOD 4 -#define PCALL_BOUND_METHOD 5 -#define PCALL_CFUNCTION 6 -#define PCALL_TYPE 7 -#define PCALL_GENERATOR 8 -#define PCALL_OTHER 9 -#define PCALL_POP 10 - -/* Notes about the statistics - - PCALL_FAST stats - - FAST_FUNCTION means no argument tuple needs to be created. - FASTER_FUNCTION means that the fast-path frame setup code is used. - - If there is a method call where the call can be optimized by changing - the argument tuple and calling the function directly, it gets recorded - twice. - - As a result, the relationship among the statistics appears to be - PCALL_ALL == PCALL_FUNCTION + PCALL_METHOD - PCALL_BOUND_METHOD + - PCALL_CFUNCTION + PCALL_TYPE + PCALL_GENERATOR + PCALL_OTHER - PCALL_FUNCTION > PCALL_FAST_FUNCTION > PCALL_FASTER_FUNCTION - PCALL_METHOD > PCALL_BOUND_METHOD -*/ - -#define PCALL(POS) pcall[POS]++ - -PyObject * -PyEval_GetCallStats(PyObject *self) -{ - return Py_BuildValue("iiiiiiiiiii", - pcall[0], pcall[1], pcall[2], pcall[3], - pcall[4], pcall[5], pcall[6], pcall[7], - pcall[8], pcall[9], pcall[10]); -} -#else -#define PCALL(O) - -PyObject * -PyEval_GetCallStats(PyObject *self) -{ - Py_INCREF(Py_None); - return Py_None; -} -#endif - - -#ifdef WITH_THREAD - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#include "pythread.h" - -static PyThread_type_lock interpreter_lock = 0; /* This is the GIL */ -static long main_thread = 0; - -int -PyEval_ThreadsInitialized(void) -{ - return interpreter_lock != 0; -} - -void -PyEval_InitThreads(void) -{ - if (interpreter_lock) - return; - interpreter_lock = PyThread_allocate_lock(); - PyThread_acquire_lock(interpreter_lock, 1); - main_thread = PyThread_get_thread_ident(); -} - -void -PyEval_AcquireLock(void) -{ - PyThread_acquire_lock(interpreter_lock, 1); -} - -void -PyEval_ReleaseLock(void) -{ - PyThread_release_lock(interpreter_lock); -} - -void -PyEval_AcquireThread(PyThreadState *tstate) -{ - if (tstate == NULL) - Py_FatalError("PyEval_AcquireThread: NULL new thread state"); - /* Check someone has called PyEval_InitThreads() to create the lock */ - assert(interpreter_lock); - PyThread_acquire_lock(interpreter_lock, 1); - if (PyThreadState_Swap(tstate) != NULL) - Py_FatalError( - "PyEval_AcquireThread: non-NULL old thread state"); -} - -void -PyEval_ReleaseThread(PyThreadState *tstate) -{ - if (tstate == NULL) - Py_FatalError("PyEval_ReleaseThread: NULL thread state"); - if (PyThreadState_Swap(NULL) != tstate) - Py_FatalError("PyEval_ReleaseThread: wrong thread state"); - PyThread_release_lock(interpreter_lock); -} - -/* This function is called from PyOS_AfterFork to ensure that newly - created child processes don't hold locks referring to threads which - are not running in the child process. (This could also be done using - pthread_atfork mechanism, at least for the pthreads implementation.) */ - -void -PyEval_ReInitThreads(void) -{ - if (!interpreter_lock) - return; - /*XXX Can't use PyThread_free_lock here because it does too - much error-checking. Doing this cleanly would require - adding a new function to each thread_*.h. Instead, just - create a new lock and waste a little bit of memory */ - interpreter_lock = PyThread_allocate_lock(); - PyThread_acquire_lock(interpreter_lock, 1); - main_thread = PyThread_get_thread_ident(); -} -#endif - -/* Functions save_thread and restore_thread are always defined so - dynamically loaded modules needn't be compiled separately for use - with and without threads: */ - -PyThreadState * -PyEval_SaveThread(void) -{ - PyThreadState *tstate = PyThreadState_Swap(NULL); - if (tstate == NULL) - Py_FatalError("PyEval_SaveThread: NULL tstate"); -#ifdef WITH_THREAD - if (interpreter_lock) - PyThread_release_lock(interpreter_lock); -#endif - return tstate; -} - -void -PyEval_RestoreThread(PyThreadState *tstate) -{ - if (tstate == NULL) - Py_FatalError("PyEval_RestoreThread: NULL tstate"); -#ifdef WITH_THREAD - if (interpreter_lock) { - int err = errno; - PyThread_acquire_lock(interpreter_lock, 1); - errno = err; - } -#endif - PyThreadState_Swap(tstate); -} - - -/* Mechanism whereby asynchronously executing callbacks (e.g. UNIX - signal handlers or Mac I/O completion routines) can schedule calls - to a function to be called synchronously. - The synchronous function is called with one void* argument. - It should return 0 for success or -1 for failure -- failure should - be accompanied by an exception. - - If registry succeeds, the registry function returns 0; if it fails - (e.g. due to too many pending calls) it returns -1 (without setting - an exception condition). - - Note that because registry may occur from within signal handlers, - or other asynchronous events, calling malloc() is unsafe! - -#ifdef WITH_THREAD - Any thread can schedule pending calls, but only the main thread - will execute them. -#endif - - XXX WARNING! ASYNCHRONOUSLY EXECUTING CODE! - There are two possible race conditions: - (1) nested asynchronous registry calls; - (2) registry calls made while pending calls are being processed. - While (1) is very unlikely, (2) is a real possibility. - The current code is safe against (2), but not against (1). - The safety against (2) is derived from the fact that only one - thread (the main thread) ever takes things out of the queue. - - XXX Darn! With the advent of thread state, we should have an array - of pending calls per thread in the thread state! Later... -*/ - -#define NPENDINGCALLS 32 -static struct { - int (*func)(void *); - void *arg; -} pendingcalls[NPENDINGCALLS]; -static volatile int pendingfirst = 0; -static volatile int pendinglast = 0; -static volatile int things_to_do = 0; - -int -Py_AddPendingCall(int (*func)(void *), void *arg) -{ - static int busy = 0; - int i, j; - /* XXX Begin critical section */ - /* XXX If you want this to be safe against nested - XXX asynchronous calls, you'll have to work harder! */ - if (busy) - return -1; - busy = 1; - i = pendinglast; - j = (i + 1) % NPENDINGCALLS; - if (j == pendingfirst) { - busy = 0; - return -1; /* Queue full */ - } - pendingcalls[i].func = func; - pendingcalls[i].arg = arg; - pendinglast = j; - - _Py_Ticker = 0; - things_to_do = 1; /* Signal main loop */ - busy = 0; - /* XXX End critical section */ - return 0; -} - -int -Py_MakePendingCalls(void) -{ - static int busy = 0; -#ifdef WITH_THREAD - if (main_thread && PyThread_get_thread_ident() != main_thread) - return 0; -#endif - if (busy) - return 0; - busy = 1; - things_to_do = 0; - for (;;) { - int i; - int (*func)(void *); - void *arg; - i = pendingfirst; - if (i == pendinglast) - break; /* Queue empty */ - func = pendingcalls[i].func; - arg = pendingcalls[i].arg; - pendingfirst = (i + 1) % NPENDINGCALLS; - if (func(arg) < 0) { - busy = 0; - things_to_do = 1; /* We're not done yet */ - return -1; - } - } - busy = 0; - return 0; -} - - -/* The interpreter's recursion limit */ - -#ifndef Py_DEFAULT_RECURSION_LIMIT -#define Py_DEFAULT_RECURSION_LIMIT 1000 -#endif -static int recursion_limit = Py_DEFAULT_RECURSION_LIMIT; -int _Py_CheckRecursionLimit = Py_DEFAULT_RECURSION_LIMIT; - -int -Py_GetRecursionLimit(void) -{ - return recursion_limit; -} - -void -Py_SetRecursionLimit(int new_limit) -{ - recursion_limit = new_limit; - _Py_CheckRecursionLimit = recursion_limit; -} - -/* the macro Py_EnterRecursiveCall() only calls _Py_CheckRecursiveCall() - if the recursion_depth reaches _Py_CheckRecursionLimit. - If USE_STACKCHECK, the macro decrements _Py_CheckRecursionLimit - to guarantee that _Py_CheckRecursiveCall() is regularly called. - Without USE_STACKCHECK, there is no need for this. */ -int -_Py_CheckRecursiveCall(char *where) -{ - PyThreadState *tstate = PyThreadState_GET(); - -#ifdef USE_STACKCHECK - if (PyOS_CheckStack()) { - --tstate->recursion_depth; - PyErr_SetString(PyExc_MemoryError, "Stack overflow"); - return -1; - } -#endif - if (tstate->recursion_depth > recursion_limit) { - --tstate->recursion_depth; - PyErr_Format(PyExc_RuntimeError, - "maximum recursion depth exceeded%s", - where); - return -1; - } - _Py_CheckRecursionLimit = recursion_limit; - return 0; -} - -/* Status code for main loop (reason for stack unwind) */ -enum why_code { - WHY_NOT = 0x0001, /* No error */ - WHY_EXCEPTION = 0x0002, /* Exception occurred */ - WHY_RERAISE = 0x0004, /* Exception re-raised by 'finally' */ - WHY_RETURN = 0x0008, /* 'return' statement */ - WHY_BREAK = 0x0010, /* 'break' statement */ - WHY_CONTINUE = 0x0020, /* 'continue' statement */ - WHY_YIELD = 0x0040 /* 'yield' operator */ -}; - -static enum why_code do_raise(PyObject *, PyObject *, PyObject *); -static int unpack_iterable(PyObject *, int, PyObject **); - -/* for manipulating the thread switch and periodic "stuff" - used to be - per thread, now just a pair o' globals */ -int _Py_CheckInterval = 100; -volatile int _Py_Ticker = 100; - -PyObject * -PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals) -{ - /* XXX raise SystemError if globals is NULL */ - return PyEval_EvalCodeEx(co, - globals, locals, - (PyObject **)NULL, 0, - (PyObject **)NULL, 0, - (PyObject **)NULL, 0, - NULL); -} - - -/* Interpreter main loop */ - -PyObject * -PyEval_EvalFrame(PyFrameObject *f) { - /* This is for backward compatibility with extension modules that - used this API; core interpreter code should call PyEval_EvalFrameEx() */ - return PyEval_EvalFrameEx(f, 0); -} - -PyObject * -PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) -{ -#ifdef DXPAIRS - int lastopcode = 0; -#endif - register PyObject **stack_pointer; /* Next free slot in value stack */ - register unsigned char *next_instr; - register int opcode; /* Current opcode */ - register int oparg; /* Current opcode argument, if any */ - register enum why_code why; /* Reason for block stack unwind */ - register int err; /* Error status -- nonzero if error */ - register PyObject *x; /* Result object -- NULL if error */ - register PyObject *v; /* Temporary objects popped off stack */ - register PyObject *w; - register PyObject *u; - register PyObject *t; - register PyObject *stream = NULL; /* for PRINT opcodes */ - register PyObject **fastlocals, **freevars; - PyObject *retval = NULL; /* Return value */ - PyThreadState *tstate = PyThreadState_GET(); - PyCodeObject *co; - - /* when tracing we set things up so that - - not (instr_lb <= current_bytecode_offset < instr_ub) - - is true when the line being executed has changed. The - initial values are such as to make this false the first - time it is tested. */ - int instr_ub = -1, instr_lb = 0, instr_prev = -1; - - unsigned char *first_instr; - PyObject *names; - PyObject *consts; -#if defined(Py_DEBUG) || defined(LLTRACE) - /* Make it easier to find out where we are with a debugger */ - char *filename; -#endif - -/* Tuple access macros */ - -#ifndef Py_DEBUG -#define GETITEM(v, i) PyTuple_GET_ITEM((PyTupleObject *)(v), (i)) -#else -#define GETITEM(v, i) PyTuple_GetItem((v), (i)) -#endif - -#ifdef WITH_TSC -/* Use Pentium timestamp counter to mark certain events: - inst0 -- beginning of switch statement for opcode dispatch - inst1 -- end of switch statement (may be skipped) - loop0 -- the top of the mainloop - loop1 -- place where control returns again to top of mainloop - (may be skipped) - intr1 -- beginning of long interruption - intr2 -- end of long interruption - - Many opcodes call out to helper C functions. In some cases, the - time in those functions should be counted towards the time for the - opcode, but not in all cases. For example, a CALL_FUNCTION opcode - calls another Python function; there's no point in charge all the - bytecode executed by the called function to the caller. - - It's hard to make a useful judgement statically. In the presence - of operator overloading, it's impossible to tell if a call will - execute new Python code or not. - - It's a case-by-case judgement. I'll use intr1 for the following - cases: - - EXEC_STMT - IMPORT_STAR - IMPORT_FROM - CALL_FUNCTION (and friends) - - */ - uint64 inst0, inst1, loop0, loop1, intr0 = 0, intr1 = 0; - int ticked = 0; - - READ_TIMESTAMP(inst0); - READ_TIMESTAMP(inst1); - READ_TIMESTAMP(loop0); - READ_TIMESTAMP(loop1); - - /* shut up the compiler */ - opcode = 0; -#endif - -/* Code access macros */ - -#define INSTR_OFFSET() ((int)(next_instr - first_instr)) -#define NEXTOP() (*next_instr++) -#define NEXTARG() (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2]) -#define PEEKARG() ((next_instr[2]<<8) + next_instr[1]) -#define JUMPTO(x) (next_instr = first_instr + (x)) -#define JUMPBY(x) (next_instr += (x)) - -/* OpCode prediction macros - Some opcodes tend to come in pairs thus making it possible to predict - the second code when the first is run. For example, COMPARE_OP is often - followed by JUMP_IF_FALSE or JUMP_IF_TRUE. And, those opcodes are often - followed by a POP_TOP. - - Verifying the prediction costs a single high-speed test of register - variable against a constant. If the pairing was good, then the - processor has a high likelihood of making its own successful branch - prediction which results in a nearly zero overhead transition to the - next opcode. - - A successful prediction saves a trip through the eval-loop including - its two unpredictable branches, the HASARG test and the switch-case. - - If collecting opcode statistics, turn off prediction so that - statistics are accurately maintained (the predictions bypass - the opcode frequency counter updates). -*/ - -#ifdef DYNAMIC_EXECUTION_PROFILE -#define PREDICT(op) if (0) goto PRED_##op -#else -#define PREDICT(op) if (*next_instr == op) goto PRED_##op -#endif - -#define PREDICTED(op) PRED_##op: next_instr++ -#define PREDICTED_WITH_ARG(op) PRED_##op: oparg = PEEKARG(); next_instr += 3 - -/* Stack manipulation macros */ - -/* The stack can grow at most MAXINT deep, as co_nlocals and - co_stacksize are ints. */ -#define STACK_LEVEL() ((int)(stack_pointer - f->f_valuestack)) -#define EMPTY() (STACK_LEVEL() == 0) -#define TOP() (stack_pointer[-1]) -#define SECOND() (stack_pointer[-2]) -#define THIRD() (stack_pointer[-3]) -#define FOURTH() (stack_pointer[-4]) -#define SET_TOP(v) (stack_pointer[-1] = (v)) -#define SET_SECOND(v) (stack_pointer[-2] = (v)) -#define SET_THIRD(v) (stack_pointer[-3] = (v)) -#define SET_FOURTH(v) (stack_pointer[-4] = (v)) -#define BASIC_STACKADJ(n) (stack_pointer += n) -#define BASIC_PUSH(v) (*stack_pointer++ = (v)) -#define BASIC_POP() (*--stack_pointer) - -#ifdef LLTRACE -#define PUSH(v) { (void)(BASIC_PUSH(v), \ - lltrace && prtrace(TOP(), "push")); \ - assert(STACK_LEVEL() <= co->co_stacksize); } -#define POP() ((void)(lltrace && prtrace(TOP(), "pop")), BASIC_POP()) -#define STACKADJ(n) { (void)(BASIC_STACKADJ(n), \ - lltrace && prtrace(TOP(), "stackadj")); \ - assert(STACK_LEVEL() <= co->co_stacksize); } -#define EXT_POP(STACK_POINTER) (lltrace && prtrace(*(STACK_POINTER), "ext_pop"), *--(STACK_POINTER)) -#else -#define PUSH(v) BASIC_PUSH(v) -#define POP() BASIC_POP() -#define STACKADJ(n) BASIC_STACKADJ(n) -#define EXT_POP(STACK_POINTER) (*--(STACK_POINTER)) -#endif - -/* Local variable macros */ - -#define GETLOCAL(i) (fastlocals[i]) - -/* The SETLOCAL() macro must not DECREF the local variable in-place and - then store the new value; it must copy the old value to a temporary - value, then store the new value, and then DECREF the temporary value. - This is because it is possible that during the DECREF the frame is - accessed by other code (e.g. a __del__ method or gc.collect()) and the - variable would be pointing to already-freed memory. */ -#define SETLOCAL(i, value) do { PyObject *tmp = GETLOCAL(i); \ - GETLOCAL(i) = value; \ - Py_XDECREF(tmp); } while (0) - -/* Start of code */ - - if (f == NULL) - return NULL; - - /* push frame */ - if (Py_EnterRecursiveCall("")) - return NULL; - - tstate->frame = f; - - if (tstate->use_tracing) { - if (tstate->c_tracefunc != NULL) { - /* tstate->c_tracefunc, if defined, is a - function that will be called on *every* entry - to a code block. Its return value, if not - None, is a function that will be called at - the start of each executed line of code. - (Actually, the function must return itself - in order to continue tracing.) The trace - functions are called with three arguments: - a pointer to the current frame, a string - indicating why the function is called, and - an argument which depends on the situation. - The global trace function is also called - whenever an exception is detected. */ - if (call_trace(tstate->c_tracefunc, tstate->c_traceobj, - f, PyTrace_CALL, Py_None)) { - /* Trace function raised an error */ - goto exit_eval_frame; - } - } - if (tstate->c_profilefunc != NULL) { - /* Similar for c_profilefunc, except it needn't - return itself and isn't called for "line" events */ - if (call_trace(tstate->c_profilefunc, - tstate->c_profileobj, - f, PyTrace_CALL, Py_None)) { - /* Profile function raised an error */ - goto exit_eval_frame; - } - } - } - - co = f->f_code; - names = co->co_names; - consts = co->co_consts; - fastlocals = f->f_localsplus; - freevars = f->f_localsplus + co->co_nlocals; - first_instr = (unsigned char*) PyString_AS_STRING(co->co_code); - /* An explanation is in order for the next line. - - f->f_lasti now refers to the index of the last instruction - executed. You might think this was obvious from the name, but - this wasn't always true before 2.3! PyFrame_New now sets - f->f_lasti to -1 (i.e. the index *before* the first instruction) - and YIELD_VALUE doesn't fiddle with f_lasti any more. So this - does work. Promise. */ - next_instr = first_instr + f->f_lasti + 1; - stack_pointer = f->f_stacktop; - assert(stack_pointer != NULL); - f->f_stacktop = NULL; /* remains NULL unless yield suspends frame */ - -#ifdef LLTRACE - lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL; -#endif -#if defined(Py_DEBUG) || defined(LLTRACE) - filename = PyString_AsString(co->co_filename); -#endif - - why = WHY_NOT; - err = 0; - x = Py_None; /* Not a reference, just anything non-NULL */ - w = NULL; - - if (throwflag) { /* support for generator.throw() */ - why = WHY_EXCEPTION; - goto on_error; - } - - for (;;) { -#ifdef WITH_TSC - if (inst1 == 0) { - /* Almost surely, the opcode executed a break - or a continue, preventing inst1 from being set - on the way out of the loop. - */ - READ_TIMESTAMP(inst1); - loop1 = inst1; - } - dump_tsc(opcode, ticked, inst0, inst1, loop0, loop1, - intr0, intr1); - ticked = 0; - inst1 = 0; - intr0 = 0; - intr1 = 0; - READ_TIMESTAMP(loop0); -#endif - assert(stack_pointer >= f->f_valuestack); /* else underflow */ - assert(STACK_LEVEL() <= co->co_stacksize); /* else overflow */ - - /* Do periodic things. Doing this every time through - the loop would add too much overhead, so we do it - only every Nth instruction. We also do it if - ``things_to_do'' is set, i.e. when an asynchronous - event needs attention (e.g. a signal handler or - async I/O handler); see Py_AddPendingCall() and - Py_MakePendingCalls() above. */ - - if (--_Py_Ticker < 0) { - if (*next_instr == SETUP_FINALLY) { - /* Make the last opcode before - a try: finally: block uninterruptable. */ - goto fast_next_opcode; - } - _Py_Ticker = _Py_CheckInterval; - tstate->tick_counter++; -#ifdef WITH_TSC - ticked = 1; -#endif - if (things_to_do) { - if (Py_MakePendingCalls() < 0) { - why = WHY_EXCEPTION; - goto on_error; - } - if (things_to_do) - /* MakePendingCalls() didn't succeed. - Force early re-execution of this - "periodic" code, possibly after - a thread switch */ - _Py_Ticker = 0; - } -#ifdef WITH_THREAD - if (interpreter_lock) { - /* Give another thread a chance */ - - if (PyThreadState_Swap(NULL) != tstate) - Py_FatalError("ceval: tstate mix-up"); - PyThread_release_lock(interpreter_lock); - - /* Other threads may run now */ - - PyThread_acquire_lock(interpreter_lock, 1); - if (PyThreadState_Swap(tstate) != NULL) - Py_FatalError("ceval: orphan tstate"); - - /* Check for thread interrupts */ - - if (tstate->async_exc != NULL) { - x = tstate->async_exc; - tstate->async_exc = NULL; - PyErr_SetNone(x); - Py_DECREF(x); - why = WHY_EXCEPTION; - goto on_error; - } - } -#endif - } - - fast_next_opcode: - f->f_lasti = INSTR_OFFSET(); - - /* line-by-line tracing support */ - - if (tstate->c_tracefunc != NULL && !tstate->tracing) { - /* see maybe_call_line_trace - for expository comments */ - f->f_stacktop = stack_pointer; - - err = maybe_call_line_trace(tstate->c_tracefunc, - tstate->c_traceobj, - f, &instr_lb, &instr_ub, - &instr_prev); - /* Reload possibly changed frame fields */ - JUMPTO(f->f_lasti); - if (f->f_stacktop != NULL) { - stack_pointer = f->f_stacktop; - f->f_stacktop = NULL; - } - if (err) { - /* trace function raised an exception */ - goto on_error; - } - } - - /* Extract opcode and argument */ - - opcode = NEXTOP(); - oparg = 0; /* allows oparg to be stored in a register because - it doesn't have to be remembered across a full loop */ - if (HAS_ARG(opcode)) - oparg = NEXTARG(); - dispatch_opcode: -#ifdef DYNAMIC_EXECUTION_PROFILE -#ifdef DXPAIRS - dxpairs[lastopcode][opcode]++; - lastopcode = opcode; -#endif - dxp[opcode]++; -#endif - -#ifdef LLTRACE - /* Instruction tracing */ - - if (lltrace) { - if (HAS_ARG(opcode)) { - printf("%d: %d, %d\n", - f->f_lasti, opcode, oparg); - } - else { - printf("%d: %d\n", - f->f_lasti, opcode); - } - } -#endif - - /* Main switch on opcode */ - READ_TIMESTAMP(inst0); - - switch (opcode) { - - /* BEWARE! - It is essential that any operation that fails sets either - x to NULL, err to nonzero, or why to anything but WHY_NOT, - and that no operation that succeeds does this! */ - - /* case STOP_CODE: this is an error! */ - - case NOP: - goto fast_next_opcode; - - case LOAD_FAST: - x = GETLOCAL(oparg); - if (x != NULL) { - Py_INCREF(x); - PUSH(x); - goto fast_next_opcode; - } - format_exc_check_arg(PyExc_UnboundLocalError, - UNBOUNDLOCAL_ERROR_MSG, - PyTuple_GetItem(co->co_varnames, oparg)); - break; - - case LOAD_CONST: - x = GETITEM(consts, oparg); - Py_INCREF(x); - PUSH(x); - goto fast_next_opcode; - - PREDICTED_WITH_ARG(STORE_FAST); - case STORE_FAST: - v = POP(); - SETLOCAL(oparg, v); - goto fast_next_opcode; - - PREDICTED(POP_TOP); - case POP_TOP: - v = POP(); - Py_DECREF(v); - goto fast_next_opcode; - - case ROT_TWO: - v = TOP(); - w = SECOND(); - SET_TOP(w); - SET_SECOND(v); - goto fast_next_opcode; - - case ROT_THREE: - v = TOP(); - w = SECOND(); - x = THIRD(); - SET_TOP(w); - SET_SECOND(x); - SET_THIRD(v); - goto fast_next_opcode; - - case ROT_FOUR: - u = TOP(); - v = SECOND(); - w = THIRD(); - x = FOURTH(); - SET_TOP(v); - SET_SECOND(w); - SET_THIRD(x); - SET_FOURTH(u); - goto fast_next_opcode; - - case DUP_TOP: - v = TOP(); - Py_INCREF(v); - PUSH(v); - goto fast_next_opcode; - - case DUP_TOPX: - if (oparg == 2) { - x = TOP(); - Py_INCREF(x); - w = SECOND(); - Py_INCREF(w); - STACKADJ(2); - SET_TOP(x); - SET_SECOND(w); - goto fast_next_opcode; - } else if (oparg == 3) { - x = TOP(); - Py_INCREF(x); - w = SECOND(); - Py_INCREF(w); - v = THIRD(); - Py_INCREF(v); - STACKADJ(3); - SET_TOP(x); - SET_SECOND(w); - SET_THIRD(v); - goto fast_next_opcode; - } - Py_FatalError("invalid argument to DUP_TOPX" - " (bytecode corruption?)"); - break; - - case UNARY_POSITIVE: - v = TOP(); - x = PyNumber_Positive(v); - Py_DECREF(v); - SET_TOP(x); - if (x != NULL) continue; - break; - - case UNARY_NEGATIVE: - v = TOP(); - x = PyNumber_Negative(v); - Py_DECREF(v); - SET_TOP(x); - if (x != NULL) continue; - break; - - case UNARY_NOT: - v = TOP(); - err = PyObject_IsTrue(v); - Py_DECREF(v); - if (err == 0) { - Py_INCREF(Py_True); - SET_TOP(Py_True); - continue; - } - else if (err > 0) { - Py_INCREF(Py_False); - SET_TOP(Py_False); - err = 0; - continue; - } - STACKADJ(-1); - break; - - case UNARY_CONVERT: - v = TOP(); - x = PyObject_Repr(v); - Py_DECREF(v); - SET_TOP(x); - if (x != NULL) continue; - break; - - case UNARY_INVERT: - v = TOP(); - x = PyNumber_Invert(v); - Py_DECREF(v); - SET_TOP(x); - if (x != NULL) continue; - break; - - case BINARY_POWER: - w = POP(); - v = TOP(); - x = PyNumber_Power(v, w, Py_None); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case BINARY_MULTIPLY: - w = POP(); - v = TOP(); - x = PyNumber_Multiply(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case BINARY_DIVIDE: - if (!_Py_QnewFlag) { - w = POP(); - v = TOP(); - x = PyNumber_Divide(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - } - /* -Qnew is in effect: fall through to - BINARY_TRUE_DIVIDE */ - case BINARY_TRUE_DIVIDE: - w = POP(); - v = TOP(); - x = PyNumber_TrueDivide(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case BINARY_FLOOR_DIVIDE: - w = POP(); - v = TOP(); - x = PyNumber_FloorDivide(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case BINARY_MODULO: - w = POP(); - v = TOP(); - x = PyNumber_Remainder(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case BINARY_ADD: - w = POP(); - v = TOP(); - if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) { - /* INLINE: int + int */ - register long a, b, i; - a = PyInt_AS_LONG(v); - b = PyInt_AS_LONG(w); - i = a + b; - if ((i^a) < 0 && (i^b) < 0) - goto slow_add; - x = PyInt_FromLong(i); - } - else if (PyString_CheckExact(v) && - PyString_CheckExact(w)) { - x = string_concatenate(v, w, f, next_instr); - /* string_concatenate consumed the ref to v */ - goto skip_decref_vx; - } - else { - slow_add: - x = PyNumber_Add(v, w); - } - Py_DECREF(v); - skip_decref_vx: - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case BINARY_SUBTRACT: - w = POP(); - v = TOP(); - if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) { - /* INLINE: int - int */ - register long a, b, i; - a = PyInt_AS_LONG(v); - b = PyInt_AS_LONG(w); - i = a - b; - if ((i^a) < 0 && (i^~b) < 0) - goto slow_sub; - x = PyInt_FromLong(i); - } - else { - slow_sub: - x = PyNumber_Subtract(v, w); - } - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case BINARY_SUBSCR: - w = POP(); - v = TOP(); - if (PyList_CheckExact(v) && PyInt_CheckExact(w)) { - /* INLINE: list[int] */ - Py_ssize_t i = PyInt_AsSsize_t(w); - if (i < 0) - i += PyList_GET_SIZE(v); - if (i >= 0 && i < PyList_GET_SIZE(v)) { - x = PyList_GET_ITEM(v, i); - Py_INCREF(x); - } - else - goto slow_get; - } - else - slow_get: - x = PyObject_GetItem(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case BINARY_LSHIFT: - w = POP(); - v = TOP(); - x = PyNumber_Lshift(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case BINARY_RSHIFT: - w = POP(); - v = TOP(); - x = PyNumber_Rshift(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case BINARY_AND: - w = POP(); - v = TOP(); - x = PyNumber_And(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case BINARY_XOR: - w = POP(); - v = TOP(); - x = PyNumber_Xor(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case BINARY_OR: - w = POP(); - v = TOP(); - x = PyNumber_Or(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case LIST_APPEND: - w = POP(); - v = POP(); - err = PyList_Append(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (err == 0) { - PREDICT(JUMP_ABSOLUTE); - continue; - } - break; - - case INPLACE_POWER: - w = POP(); - v = TOP(); - x = PyNumber_InPlacePower(v, w, Py_None); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case INPLACE_MULTIPLY: - w = POP(); - v = TOP(); - x = PyNumber_InPlaceMultiply(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case INPLACE_DIVIDE: - if (!_Py_QnewFlag) { - w = POP(); - v = TOP(); - x = PyNumber_InPlaceDivide(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - } - /* -Qnew is in effect: fall through to - INPLACE_TRUE_DIVIDE */ - case INPLACE_TRUE_DIVIDE: - w = POP(); - v = TOP(); - x = PyNumber_InPlaceTrueDivide(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case INPLACE_FLOOR_DIVIDE: - w = POP(); - v = TOP(); - x = PyNumber_InPlaceFloorDivide(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case INPLACE_MODULO: - w = POP(); - v = TOP(); - x = PyNumber_InPlaceRemainder(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case INPLACE_ADD: - w = POP(); - v = TOP(); - if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) { - /* INLINE: int + int */ - register long a, b, i; - a = PyInt_AS_LONG(v); - b = PyInt_AS_LONG(w); - i = a + b; - if ((i^a) < 0 && (i^b) < 0) - goto slow_iadd; - x = PyInt_FromLong(i); - } - else if (PyString_CheckExact(v) && - PyString_CheckExact(w)) { - x = string_concatenate(v, w, f, next_instr); - /* string_concatenate consumed the ref to v */ - goto skip_decref_v; - } - else { - slow_iadd: - x = PyNumber_InPlaceAdd(v, w); - } - Py_DECREF(v); - skip_decref_v: - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case INPLACE_SUBTRACT: - w = POP(); - v = TOP(); - if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) { - /* INLINE: int - int */ - register long a, b, i; - a = PyInt_AS_LONG(v); - b = PyInt_AS_LONG(w); - i = a - b; - if ((i^a) < 0 && (i^~b) < 0) - goto slow_isub; - x = PyInt_FromLong(i); - } - else { - slow_isub: - x = PyNumber_InPlaceSubtract(v, w); - } - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case INPLACE_LSHIFT: - w = POP(); - v = TOP(); - x = PyNumber_InPlaceLshift(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case INPLACE_RSHIFT: - w = POP(); - v = TOP(); - x = PyNumber_InPlaceRshift(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case INPLACE_AND: - w = POP(); - v = TOP(); - x = PyNumber_InPlaceAnd(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case INPLACE_XOR: - w = POP(); - v = TOP(); - x = PyNumber_InPlaceXor(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case INPLACE_OR: - w = POP(); - v = TOP(); - x = PyNumber_InPlaceOr(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case SLICE+0: - case SLICE+1: - case SLICE+2: - case SLICE+3: - if ((opcode-SLICE) & 2) - w = POP(); - else - w = NULL; - if ((opcode-SLICE) & 1) - v = POP(); - else - v = NULL; - u = TOP(); - x = apply_slice(u, v, w); - Py_DECREF(u); - Py_XDECREF(v); - Py_XDECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case STORE_SLICE+0: - case STORE_SLICE+1: - case STORE_SLICE+2: - case STORE_SLICE+3: - if ((opcode-STORE_SLICE) & 2) - w = POP(); - else - w = NULL; - if ((opcode-STORE_SLICE) & 1) - v = POP(); - else - v = NULL; - u = POP(); - t = POP(); - err = assign_slice(u, v, w, t); /* u[v:w] = t */ - Py_DECREF(t); - Py_DECREF(u); - Py_XDECREF(v); - Py_XDECREF(w); - if (err == 0) continue; - break; - - case DELETE_SLICE+0: - case DELETE_SLICE+1: - case DELETE_SLICE+2: - case DELETE_SLICE+3: - if ((opcode-DELETE_SLICE) & 2) - w = POP(); - else - w = NULL; - if ((opcode-DELETE_SLICE) & 1) - v = POP(); - else - v = NULL; - u = POP(); - err = assign_slice(u, v, w, (PyObject *)NULL); - /* del u[v:w] */ - Py_DECREF(u); - Py_XDECREF(v); - Py_XDECREF(w); - if (err == 0) continue; - break; - - case STORE_SUBSCR: - w = TOP(); - v = SECOND(); - u = THIRD(); - STACKADJ(-3); - /* v[w] = u */ - err = PyObject_SetItem(v, w, u); - Py_DECREF(u); - Py_DECREF(v); - Py_DECREF(w); - if (err == 0) continue; - break; - - case DELETE_SUBSCR: - w = TOP(); - v = SECOND(); - STACKADJ(-2); - /* del v[w] */ - err = PyObject_DelItem(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (err == 0) continue; - break; - - case PRINT_EXPR: - v = POP(); - w = PySys_GetObject("displayhook"); - if (w == NULL) { - PyErr_SetString(PyExc_RuntimeError, - "lost sys.displayhook"); - err = -1; - x = NULL; - } - if (err == 0) { - x = PyTuple_Pack(1, v); - if (x == NULL) - err = -1; - } - if (err == 0) { - w = PyEval_CallObject(w, x); - Py_XDECREF(w); - if (w == NULL) - err = -1; - } - Py_DECREF(v); - Py_XDECREF(x); - break; - - case PRINT_ITEM_TO: - w = stream = POP(); - /* fall through to PRINT_ITEM */ - - case PRINT_ITEM: - v = POP(); - if (stream == NULL || stream == Py_None) { - w = PySys_GetObject("stdout"); - if (w == NULL) { - PyErr_SetString(PyExc_RuntimeError, - "lost sys.stdout"); - err = -1; - } - } - /* PyFile_SoftSpace() can exececute arbitrary code - if sys.stdout is an instance with a __getattr__. - If __getattr__ raises an exception, w will - be freed, so we need to prevent that temporarily. */ - Py_XINCREF(w); - if (w != NULL && PyFile_SoftSpace(w, 0)) - err = PyFile_WriteString(" ", w); - if (err == 0) - err = PyFile_WriteObject(v, w, Py_PRINT_RAW); - if (err == 0) { - /* XXX move into writeobject() ? */ - if (PyString_Check(v)) { - char *s = PyString_AS_STRING(v); - Py_ssize_t len = PyString_GET_SIZE(v); - if (len == 0 || - !isspace(Py_CHARMASK(s[len-1])) || - s[len-1] == ' ') - PyFile_SoftSpace(w, 1); - } -#ifdef Py_USING_UNICODE - else if (PyUnicode_Check(v)) { - Py_UNICODE *s = PyUnicode_AS_UNICODE(v); - Py_ssize_t len = PyUnicode_GET_SIZE(v); - if (len == 0 || - !Py_UNICODE_ISSPACE(s[len-1]) || - s[len-1] == ' ') - PyFile_SoftSpace(w, 1); - } -#endif - else - PyFile_SoftSpace(w, 1); - } - Py_XDECREF(w); - Py_DECREF(v); - Py_XDECREF(stream); - stream = NULL; - if (err == 0) - continue; - break; - - case PRINT_NEWLINE_TO: - w = stream = POP(); - /* fall through to PRINT_NEWLINE */ - - case PRINT_NEWLINE: - if (stream == NULL || stream == Py_None) { - w = PySys_GetObject("stdout"); - if (w == NULL) - PyErr_SetString(PyExc_RuntimeError, - "lost sys.stdout"); - } - if (w != NULL) { - err = PyFile_WriteString("\n", w); - if (err == 0) - PyFile_SoftSpace(w, 0); - } - Py_XDECREF(stream); - stream = NULL; - break; - - -#ifdef CASE_TOO_BIG - default: switch (opcode) { -#endif - case RAISE_VARARGS: - u = v = w = NULL; - switch (oparg) { - case 3: - u = POP(); /* traceback */ - /* Fallthrough */ - case 2: - v = POP(); /* value */ - /* Fallthrough */ - case 1: - w = POP(); /* exc */ - case 0: /* Fallthrough */ - why = do_raise(w, v, u); - break; - default: - PyErr_SetString(PyExc_SystemError, - "bad RAISE_VARARGS oparg"); - why = WHY_EXCEPTION; - break; - } - break; - - case LOAD_LOCALS: - if ((x = f->f_locals) != NULL) { - Py_INCREF(x); - PUSH(x); - continue; - } - PyErr_SetString(PyExc_SystemError, "no locals"); - break; - - case RETURN_VALUE: - retval = POP(); - why = WHY_RETURN; - goto fast_block_end; - - case YIELD_VALUE: - retval = POP(); - f->f_stacktop = stack_pointer; - why = WHY_YIELD; - goto fast_yield; - - case EXEC_STMT: - w = TOP(); - v = SECOND(); - u = THIRD(); - STACKADJ(-3); - READ_TIMESTAMP(intr0); - err = exec_statement(f, u, v, w); - READ_TIMESTAMP(intr1); - Py_DECREF(u); - Py_DECREF(v); - Py_DECREF(w); - break; - - case POP_BLOCK: - { - PyTryBlock *b = PyFrame_BlockPop(f); - while (STACK_LEVEL() > b->b_level) { - v = POP(); - Py_DECREF(v); - } - } - continue; - - case END_FINALLY: - v = POP(); - if (PyInt_Check(v)) { - why = (enum why_code) PyInt_AS_LONG(v); - assert(why != WHY_YIELD); - if (why == WHY_RETURN || - why == WHY_CONTINUE) - retval = POP(); - } - else if (PyExceptionClass_Check(v) || PyString_Check(v)) { - w = POP(); - u = POP(); - PyErr_Restore(v, w, u); - why = WHY_RERAISE; - break; - } - else if (v != Py_None) { - PyErr_SetString(PyExc_SystemError, - "'finally' pops bad exception"); - why = WHY_EXCEPTION; - } - Py_DECREF(v); - break; - - case BUILD_CLASS: - u = TOP(); - v = SECOND(); - w = THIRD(); - STACKADJ(-2); - x = build_class(u, v, w); - SET_TOP(x); - Py_DECREF(u); - Py_DECREF(v); - Py_DECREF(w); - break; - - case STORE_NAME: - w = GETITEM(names, oparg); - v = POP(); - if ((x = f->f_locals) != NULL) { - if (PyDict_CheckExact(x)) - err = PyDict_SetItem(x, w, v); - else - err = PyObject_SetItem(x, w, v); - Py_DECREF(v); - if (err == 0) continue; - break; - } - PyErr_Format(PyExc_SystemError, - "no locals found when storing %s", - PyObject_REPR(w)); - break; - - case DELETE_NAME: - w = GETITEM(names, oparg); - if ((x = f->f_locals) != NULL) { - if ((err = PyObject_DelItem(x, w)) != 0) - format_exc_check_arg(PyExc_NameError, - NAME_ERROR_MSG ,w); - break; - } - PyErr_Format(PyExc_SystemError, - "no locals when deleting %s", - PyObject_REPR(w)); - break; - - PREDICTED_WITH_ARG(UNPACK_SEQUENCE); - case UNPACK_SEQUENCE: - v = POP(); - if (PyTuple_CheckExact(v) && PyTuple_GET_SIZE(v) == oparg) { - PyObject **items = ((PyTupleObject *)v)->ob_item; - while (oparg--) { - w = items[oparg]; - Py_INCREF(w); - PUSH(w); - } - Py_DECREF(v); - continue; - } else if (PyList_CheckExact(v) && PyList_GET_SIZE(v) == oparg) { - PyObject **items = ((PyListObject *)v)->ob_item; - while (oparg--) { - w = items[oparg]; - Py_INCREF(w); - PUSH(w); - } - } else if (unpack_iterable(v, oparg, - stack_pointer + oparg)) { - stack_pointer += oparg; - } else { - /* unpack_iterable() raised an exception */ - why = WHY_EXCEPTION; - } - Py_DECREF(v); - break; - - case STORE_ATTR: - w = GETITEM(names, oparg); - v = TOP(); - u = SECOND(); - STACKADJ(-2); - err = PyObject_SetAttr(v, w, u); /* v.w = u */ - Py_DECREF(v); - Py_DECREF(u); - if (err == 0) continue; - break; - - case DELETE_ATTR: - w = GETITEM(names, oparg); - v = POP(); - err = PyObject_SetAttr(v, w, (PyObject *)NULL); - /* del v.w */ - Py_DECREF(v); - break; - - case STORE_GLOBAL: - w = GETITEM(names, oparg); - v = POP(); - err = PyDict_SetItem(f->f_globals, w, v); - Py_DECREF(v); - if (err == 0) continue; - break; - - case DELETE_GLOBAL: - w = GETITEM(names, oparg); - if ((err = PyDict_DelItem(f->f_globals, w)) != 0) - format_exc_check_arg( - PyExc_NameError, GLOBAL_NAME_ERROR_MSG, w); - break; - - case LOAD_NAME: - w = GETITEM(names, oparg); - if ((v = f->f_locals) == NULL) { - PyErr_Format(PyExc_SystemError, - "no locals when loading %s", - PyObject_REPR(w)); - break; - } - if (PyDict_CheckExact(v)) { - x = PyDict_GetItem(v, w); - Py_XINCREF(x); - } - else { - x = PyObject_GetItem(v, w); - if (x == NULL && PyErr_Occurred()) { - if (!PyErr_ExceptionMatches(PyExc_KeyError)) - break; - PyErr_Clear(); - } - } - if (x == NULL) { - x = PyDict_GetItem(f->f_globals, w); - if (x == NULL) { - x = PyDict_GetItem(f->f_builtins, w); - if (x == NULL) { - format_exc_check_arg( - PyExc_NameError, - NAME_ERROR_MSG ,w); - break; - } - } - Py_INCREF(x); - } - PUSH(x); - continue; - - case LOAD_GLOBAL: - w = GETITEM(names, oparg); - if (PyString_CheckExact(w)) { - /* Inline the PyDict_GetItem() calls. - WARNING: this is an extreme speed hack. - Do not try this at home. */ - long hash = ((PyStringObject *)w)->ob_shash; - if (hash != -1) { - PyDictObject *d; - PyDictEntry *e; - d = (PyDictObject *)(f->f_globals); - e = d->ma_lookup(d, w, hash); - if (e == NULL) { - x = NULL; - break; - } - x = e->me_value; - if (x != NULL) { - Py_INCREF(x); - PUSH(x); - continue; - } - d = (PyDictObject *)(f->f_builtins); - e = d->ma_lookup(d, w, hash); - if (e == NULL) { - x = NULL; - break; - } - x = e->me_value; - if (x != NULL) { - Py_INCREF(x); - PUSH(x); - continue; - } - goto load_global_error; - } - } - /* This is the un-inlined version of the code above */ - x = PyDict_GetItem(f->f_globals, w); - if (x == NULL) { - x = PyDict_GetItem(f->f_builtins, w); - if (x == NULL) { - load_global_error: - format_exc_check_arg( - PyExc_NameError, - GLOBAL_NAME_ERROR_MSG, w); - break; - } - } - Py_INCREF(x); - PUSH(x); - continue; - - case DELETE_FAST: - x = GETLOCAL(oparg); - if (x != NULL) { - SETLOCAL(oparg, NULL); - continue; - } - format_exc_check_arg( - PyExc_UnboundLocalError, - UNBOUNDLOCAL_ERROR_MSG, - PyTuple_GetItem(co->co_varnames, oparg) - ); - break; - - case LOAD_CLOSURE: - x = freevars[oparg]; - Py_INCREF(x); - PUSH(x); - if (x != NULL) continue; - break; - - case LOAD_DEREF: - x = freevars[oparg]; - w = PyCell_Get(x); - if (w != NULL) { - PUSH(w); - continue; - } - err = -1; - /* Don't stomp existing exception */ - if (PyErr_Occurred()) - break; - if (oparg < PyTuple_GET_SIZE(co->co_cellvars)) { - v = PyTuple_GET_ITEM(co->co_cellvars, - oparg); - format_exc_check_arg( - PyExc_UnboundLocalError, - UNBOUNDLOCAL_ERROR_MSG, - v); - } else { - v = PyTuple_GET_ITEM( - co->co_freevars, - oparg - PyTuple_GET_SIZE(co->co_cellvars)); - format_exc_check_arg( - PyExc_NameError, - UNBOUNDFREE_ERROR_MSG, - v); - } - break; - - case STORE_DEREF: - w = POP(); - x = freevars[oparg]; - PyCell_Set(x, w); - Py_DECREF(w); - continue; - - case BUILD_TUPLE: - x = PyTuple_New(oparg); - if (x != NULL) { - for (; --oparg >= 0;) { - w = POP(); - PyTuple_SET_ITEM(x, oparg, w); - } - PUSH(x); - continue; - } - break; - - case BUILD_LIST: - x = PyList_New(oparg); - if (x != NULL) { - for (; --oparg >= 0;) { - w = POP(); - PyList_SET_ITEM(x, oparg, w); - } - PUSH(x); - continue; - } - break; - - case BUILD_MAP: - x = PyDict_New(); - PUSH(x); - if (x != NULL) continue; - break; - - case LOAD_ATTR: - w = GETITEM(names, oparg); - v = TOP(); - x = PyObject_GetAttr(v, w); - Py_DECREF(v); - SET_TOP(x); - if (x != NULL) continue; - break; - - case COMPARE_OP: - w = POP(); - v = TOP(); - if (PyInt_CheckExact(w) && PyInt_CheckExact(v)) { - /* INLINE: cmp(int, int) */ - register long a, b; - register int res; - a = PyInt_AS_LONG(v); - b = PyInt_AS_LONG(w); - switch (oparg) { - case PyCmp_LT: res = a < b; break; - case PyCmp_LE: res = a <= b; break; - case PyCmp_EQ: res = a == b; break; - case PyCmp_NE: res = a != b; break; - case PyCmp_GT: res = a > b; break; - case PyCmp_GE: res = a >= b; break; - case PyCmp_IS: res = v == w; break; - case PyCmp_IS_NOT: res = v != w; break; - default: goto slow_compare; - } - x = res ? Py_True : Py_False; - Py_INCREF(x); - } - else { - slow_compare: - x = cmp_outcome(oparg, v, w); - } - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x == NULL) break; - PREDICT(JUMP_IF_FALSE); - PREDICT(JUMP_IF_TRUE); - continue; - - case IMPORT_NAME: - w = GETITEM(names, oparg); - x = PyDict_GetItemString(f->f_builtins, "__import__"); - if (x == NULL) { - PyErr_SetString(PyExc_ImportError, - "__import__ not found"); - break; - } - v = POP(); - u = TOP(); - if (PyInt_AsLong(u) != -1 || PyErr_Occurred()) - w = PyTuple_Pack(5, - w, - f->f_globals, - f->f_locals == NULL ? - Py_None : f->f_locals, - v, - u); - else - w = PyTuple_Pack(4, - w, - f->f_globals, - f->f_locals == NULL ? - Py_None : f->f_locals, - v); - Py_DECREF(v); - Py_DECREF(u); - if (w == NULL) { - u = POP(); - x = NULL; - break; - } - READ_TIMESTAMP(intr0); - x = PyEval_CallObject(x, w); - READ_TIMESTAMP(intr1); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case IMPORT_STAR: - v = POP(); - PyFrame_FastToLocals(f); - if ((x = f->f_locals) == NULL) { - PyErr_SetString(PyExc_SystemError, - "no locals found during 'import *'"); - break; - } - READ_TIMESTAMP(intr0); - err = import_all_from(x, v); - READ_TIMESTAMP(intr1); - PyFrame_LocalsToFast(f, 0); - Py_DECREF(v); - if (err == 0) continue; - break; - - case IMPORT_FROM: - w = GETITEM(names, oparg); - v = TOP(); - READ_TIMESTAMP(intr0); - x = import_from(v, w); - READ_TIMESTAMP(intr1); - PUSH(x); - if (x != NULL) continue; - break; - - case JUMP_FORWARD: - JUMPBY(oparg); - goto fast_next_opcode; - - PREDICTED_WITH_ARG(JUMP_IF_FALSE); - case JUMP_IF_FALSE: - w = TOP(); - if (w == Py_True) { - PREDICT(POP_TOP); - goto fast_next_opcode; - } - if (w == Py_False) { - JUMPBY(oparg); - goto fast_next_opcode; - } - err = PyObject_IsTrue(w); - if (err > 0) - err = 0; - else if (err == 0) - JUMPBY(oparg); - else - break; - continue; - - PREDICTED_WITH_ARG(JUMP_IF_TRUE); - case JUMP_IF_TRUE: - w = TOP(); - if (w == Py_False) { - PREDICT(POP_TOP); - goto fast_next_opcode; - } - if (w == Py_True) { - JUMPBY(oparg); - goto fast_next_opcode; - } - err = PyObject_IsTrue(w); - if (err > 0) { - err = 0; - JUMPBY(oparg); - } - else if (err == 0) - ; - else - break; - continue; - - PREDICTED_WITH_ARG(JUMP_ABSOLUTE); - case JUMP_ABSOLUTE: - JUMPTO(oparg); - continue; - - case GET_ITER: - /* before: [obj]; after [getiter(obj)] */ - v = TOP(); - x = PyObject_GetIter(v); - Py_DECREF(v); - if (x != NULL) { - SET_TOP(x); - PREDICT(FOR_ITER); - continue; - } - STACKADJ(-1); - break; - - PREDICTED_WITH_ARG(FOR_ITER); - case FOR_ITER: - /* before: [iter]; after: [iter, iter()] *or* [] */ - v = TOP(); - x = (*v->ob_type->tp_iternext)(v); - if (x != NULL) { - PUSH(x); - PREDICT(STORE_FAST); - PREDICT(UNPACK_SEQUENCE); - continue; - } - if (PyErr_Occurred()) { - if (!PyErr_ExceptionMatches(PyExc_StopIteration)) - break; - PyErr_Clear(); - } - /* iterator ended normally */ - x = v = POP(); - Py_DECREF(v); - JUMPBY(oparg); - continue; - - case BREAK_LOOP: - why = WHY_BREAK; - goto fast_block_end; - - case CONTINUE_LOOP: - retval = PyInt_FromLong(oparg); - if (!retval) { - x = NULL; - break; - } - why = WHY_CONTINUE; - goto fast_block_end; - - case SETUP_LOOP: - case SETUP_EXCEPT: - case SETUP_FINALLY: - /* NOTE: If you add any new block-setup opcodes that are not try/except/finally - handlers, you may need to update the PyGen_NeedsFinalizing() function. */ - - PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg, - STACK_LEVEL()); - continue; - - case WITH_CLEANUP: - { - /* TOP is the context.__exit__ bound method. - Below that are 1-3 values indicating how/why - we entered the finally clause: - - SECOND = None - - (SECOND, THIRD) = (WHY_{RETURN,CONTINUE}), retval - - SECOND = WHY_*; no retval below it - - (SECOND, THIRD, FOURTH) = exc_info() - In the last case, we must call - TOP(SECOND, THIRD, FOURTH) - otherwise we must call - TOP(None, None, None) - - In addition, if the stack represents an exception, - *and* the function call returns a 'true' value, we - "zap" this information, to prevent END_FINALLY from - re-raising the exception. (But non-local gotos - should still be resumed.) - */ - - x = TOP(); - u = SECOND(); - if (PyInt_Check(u) || u == Py_None) { - u = v = w = Py_None; - } - else { - v = THIRD(); - w = FOURTH(); - } - /* XXX Not the fastest way to call it... */ - x = PyObject_CallFunctionObjArgs(x, u, v, w, NULL); - if (x == NULL) - break; /* Go to error exit */ - if (u != Py_None && PyObject_IsTrue(x)) { - /* There was an exception and a true return */ - Py_DECREF(x); - x = TOP(); /* Again */ - STACKADJ(-3); - Py_INCREF(Py_None); - SET_TOP(Py_None); - Py_DECREF(x); - Py_DECREF(u); - Py_DECREF(v); - Py_DECREF(w); - } else { - /* Let END_FINALLY do its thing */ - Py_DECREF(x); - x = POP(); - Py_DECREF(x); - } - break; - } - - case CALL_FUNCTION: - { - PyObject **sp; - PCALL(PCALL_ALL); - sp = stack_pointer; -#ifdef WITH_TSC - x = call_function(&sp, oparg, &intr0, &intr1); -#else - x = call_function(&sp, oparg); -#endif - stack_pointer = sp; - PUSH(x); - if (x != NULL) - continue; - break; - } - - case CALL_FUNCTION_VAR: - case CALL_FUNCTION_KW: - case CALL_FUNCTION_VAR_KW: - { - int na = oparg & 0xff; - int nk = (oparg>>8) & 0xff; - int flags = (opcode - CALL_FUNCTION) & 3; - int n = na + 2 * nk; - PyObject **pfunc, *func, **sp; - PCALL(PCALL_ALL); - if (flags & CALL_FLAG_VAR) - n++; - if (flags & CALL_FLAG_KW) - n++; - pfunc = stack_pointer - n - 1; - func = *pfunc; - - if (PyMethod_Check(func) - && PyMethod_GET_SELF(func) != NULL) { - PyObject *self = PyMethod_GET_SELF(func); - Py_INCREF(self); - func = PyMethod_GET_FUNCTION(func); - Py_INCREF(func); - Py_DECREF(*pfunc); - *pfunc = self; - na++; - n++; - } else - Py_INCREF(func); - sp = stack_pointer; - READ_TIMESTAMP(intr0); - x = ext_do_call(func, &sp, flags, na, nk); - READ_TIMESTAMP(intr1); - stack_pointer = sp; - Py_DECREF(func); - - while (stack_pointer > pfunc) { - w = POP(); - Py_DECREF(w); - } - PUSH(x); - if (x != NULL) - continue; - break; - } - - case MAKE_FUNCTION: - v = POP(); /* code object */ - x = PyFunction_New(v, f->f_globals); - Py_DECREF(v); - /* XXX Maybe this should be a separate opcode? */ - if (x != NULL && oparg > 0) { - v = PyTuple_New(oparg); - if (v == NULL) { - Py_DECREF(x); - x = NULL; - break; - } - while (--oparg >= 0) { - w = POP(); - PyTuple_SET_ITEM(v, oparg, w); - } - err = PyFunction_SetDefaults(x, v); - Py_DECREF(v); - } - PUSH(x); - break; - - case MAKE_CLOSURE: - { - v = POP(); /* code object */ - x = PyFunction_New(v, f->f_globals); - Py_DECREF(v); - if (x != NULL) { - v = POP(); - err = PyFunction_SetClosure(x, v); - Py_DECREF(v); - } - if (x != NULL && oparg > 0) { - v = PyTuple_New(oparg); - if (v == NULL) { - Py_DECREF(x); - x = NULL; - break; - } - while (--oparg >= 0) { - w = POP(); - PyTuple_SET_ITEM(v, oparg, w); - } - err = PyFunction_SetDefaults(x, v); - Py_DECREF(v); - } - PUSH(x); - break; - } - - case BUILD_SLICE: - if (oparg == 3) - w = POP(); - else - w = NULL; - v = POP(); - u = TOP(); - x = PySlice_New(u, v, w); - Py_DECREF(u); - Py_DECREF(v); - Py_XDECREF(w); - SET_TOP(x); - if (x != NULL) continue; - break; - - case EXTENDED_ARG: - opcode = NEXTOP(); - oparg = oparg<<16 | NEXTARG(); - goto dispatch_opcode; - - default: - fprintf(stderr, - "XXX lineno: %d, opcode: %d\n", - PyCode_Addr2Line(f->f_code, f->f_lasti), - opcode); - PyErr_SetString(PyExc_SystemError, "unknown opcode"); - why = WHY_EXCEPTION; - break; - -#ifdef CASE_TOO_BIG - } -#endif - - } /* switch */ - - on_error: - - READ_TIMESTAMP(inst1); - - /* Quickly continue if no error occurred */ - - if (why == WHY_NOT) { - if (err == 0 && x != NULL) { -#ifdef CHECKEXC - /* This check is expensive! */ - if (PyErr_Occurred()) - fprintf(stderr, - "XXX undetected error\n"); - else { -#endif - READ_TIMESTAMP(loop1); - continue; /* Normal, fast path */ -#ifdef CHECKEXC - } -#endif - } - why = WHY_EXCEPTION; - x = Py_None; - err = 0; - } - - /* Double-check exception status */ - - if (why == WHY_EXCEPTION || why == WHY_RERAISE) { - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_SystemError, - "error return without exception set"); - why = WHY_EXCEPTION; - } - } -#ifdef CHECKEXC - else { - /* This check is expensive! */ - if (PyErr_Occurred()) { - char buf[1024]; - sprintf(buf, "Stack unwind with exception " - "set and why=%d", why); - Py_FatalError(buf); - } - } -#endif - - /* Log traceback info if this is a real exception */ - - if (why == WHY_EXCEPTION) { - PyTraceBack_Here(f); - - if (tstate->c_tracefunc != NULL) - call_exc_trace(tstate->c_tracefunc, - tstate->c_traceobj, f); - } - - /* For the rest, treat WHY_RERAISE as WHY_EXCEPTION */ - - if (why == WHY_RERAISE) - why = WHY_EXCEPTION; - - /* Unwind stacks if a (pseudo) exception occurred */ - -fast_block_end: - while (why != WHY_NOT && f->f_iblock > 0) { - PyTryBlock *b = PyFrame_BlockPop(f); - - assert(why != WHY_YIELD); - if (b->b_type == SETUP_LOOP && why == WHY_CONTINUE) { - /* For a continue inside a try block, - don't pop the block for the loop. */ - PyFrame_BlockSetup(f, b->b_type, b->b_handler, - b->b_level); - why = WHY_NOT; - JUMPTO(PyInt_AS_LONG(retval)); - Py_DECREF(retval); - break; - } - - while (STACK_LEVEL() > b->b_level) { - v = POP(); - Py_XDECREF(v); - } - if (b->b_type == SETUP_LOOP && why == WHY_BREAK) { - why = WHY_NOT; - JUMPTO(b->b_handler); - break; - } - if (b->b_type == SETUP_FINALLY || - (b->b_type == SETUP_EXCEPT && - why == WHY_EXCEPTION)) { - if (why == WHY_EXCEPTION) { - PyObject *exc, *val, *tb; - PyErr_Fetch(&exc, &val, &tb); - if (val == NULL) { - val = Py_None; - Py_INCREF(val); - } - /* Make the raw exception data - available to the handler, - so a program can emulate the - Python main loop. Don't do - this for 'finally'. */ - if (b->b_type == SETUP_EXCEPT) { - PyErr_NormalizeException( - &exc, &val, &tb); - set_exc_info(tstate, - exc, val, tb); - } - if (tb == NULL) { - Py_INCREF(Py_None); - PUSH(Py_None); - } else - PUSH(tb); - PUSH(val); - PUSH(exc); - } - else { - if (why & (WHY_RETURN | WHY_CONTINUE)) - PUSH(retval); - v = PyInt_FromLong((long)why); - PUSH(v); - } - why = WHY_NOT; - JUMPTO(b->b_handler); - break; - } - } /* unwind stack */ - - /* End the loop if we still have an error (or return) */ - - if (why != WHY_NOT) - break; - READ_TIMESTAMP(loop1); - - } /* main loop */ - - assert(why != WHY_YIELD); - /* Pop remaining stack entries. */ - while (!EMPTY()) { - v = POP(); - Py_XDECREF(v); - } - - if (why != WHY_RETURN) - retval = NULL; - -fast_yield: - if (tstate->use_tracing) { - if (tstate->c_tracefunc) { - if (why == WHY_RETURN || why == WHY_YIELD) { - if (call_trace(tstate->c_tracefunc, - tstate->c_traceobj, f, - PyTrace_RETURN, retval)) { - Py_XDECREF(retval); - retval = NULL; - why = WHY_EXCEPTION; - } - } - else if (why == WHY_EXCEPTION) { - call_trace_protected(tstate->c_tracefunc, - tstate->c_traceobj, f, - PyTrace_RETURN, NULL); - } - } - if (tstate->c_profilefunc) { - if (why == WHY_EXCEPTION) - call_trace_protected(tstate->c_profilefunc, - tstate->c_profileobj, f, - PyTrace_RETURN, NULL); - else if (call_trace(tstate->c_profilefunc, - tstate->c_profileobj, f, - PyTrace_RETURN, retval)) { - Py_XDECREF(retval); - retval = NULL; - why = WHY_EXCEPTION; - } - } - } - - if (tstate->frame->f_exc_type != NULL) - reset_exc_info(tstate); - else { - assert(tstate->frame->f_exc_value == NULL); - assert(tstate->frame->f_exc_traceback == NULL); - } - - /* pop frame */ - exit_eval_frame: - Py_LeaveRecursiveCall(); - tstate->frame = f->f_back; - - return retval; -} - -/* This is gonna seem *real weird*, but if you put some other code between - PyEval_EvalFrame() and PyEval_EvalCodeEx() you will need to adjust - the test in the if statements in Misc/gdbinit (pystack and pystackv). */ - -PyObject * -PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals, - PyObject **args, int argcount, PyObject **kws, int kwcount, - PyObject **defs, int defcount, PyObject *closure) -{ - register PyFrameObject *f; - register PyObject *retval = NULL; - register PyObject **fastlocals, **freevars; - PyThreadState *tstate = PyThreadState_GET(); - PyObject *x, *u; - - if (globals == NULL) { - PyErr_SetString(PyExc_SystemError, - "PyEval_EvalCodeEx: NULL globals"); - return NULL; - } - - assert(tstate != NULL); - assert(globals != NULL); - f = PyFrame_New(tstate, co, globals, locals); - if (f == NULL) - return NULL; - - fastlocals = f->f_localsplus; - freevars = f->f_localsplus + co->co_nlocals; - - if (co->co_argcount > 0 || - co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) { - int i; - int n = argcount; - PyObject *kwdict = NULL; - if (co->co_flags & CO_VARKEYWORDS) { - kwdict = PyDict_New(); - if (kwdict == NULL) - goto fail; - i = co->co_argcount; - if (co->co_flags & CO_VARARGS) - i++; - SETLOCAL(i, kwdict); - } - if (argcount > co->co_argcount) { - if (!(co->co_flags & CO_VARARGS)) { - PyErr_Format(PyExc_TypeError, - "%.200s() takes %s %d " - "%sargument%s (%d given)", - PyString_AsString(co->co_name), - defcount ? "at most" : "exactly", - co->co_argcount, - kwcount ? "non-keyword " : "", - co->co_argcount == 1 ? "" : "s", - argcount); - goto fail; - } - n = co->co_argcount; - } - for (i = 0; i < n; i++) { - x = args[i]; - Py_INCREF(x); - SETLOCAL(i, x); - } - if (co->co_flags & CO_VARARGS) { - u = PyTuple_New(argcount - n); - if (u == NULL) - goto fail; - SETLOCAL(co->co_argcount, u); - for (i = n; i < argcount; i++) { - x = args[i]; - Py_INCREF(x); - PyTuple_SET_ITEM(u, i-n, x); - } - } - for (i = 0; i < kwcount; i++) { - PyObject *keyword = kws[2*i]; - PyObject *value = kws[2*i + 1]; - int j; - if (keyword == NULL || !PyString_Check(keyword)) { - PyErr_Format(PyExc_TypeError, - "%.200s() keywords must be strings", - PyString_AsString(co->co_name)); - goto fail; - } - /* XXX slow -- speed up using dictionary? */ - for (j = 0; j < co->co_argcount; j++) { - PyObject *nm = PyTuple_GET_ITEM( - co->co_varnames, j); - int cmp = PyObject_RichCompareBool( - keyword, nm, Py_EQ); - if (cmp > 0) - break; - else if (cmp < 0) - goto fail; - } - /* Check errors from Compare */ - if (PyErr_Occurred()) - goto fail; - if (j >= co->co_argcount) { - if (kwdict == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s() got an unexpected " - "keyword argument '%.400s'", - PyString_AsString(co->co_name), - PyString_AsString(keyword)); - goto fail; - } - PyDict_SetItem(kwdict, keyword, value); - } - else { - if (GETLOCAL(j) != NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s() got multiple " - "values for keyword " - "argument '%.400s'", - PyString_AsString(co->co_name), - PyString_AsString(keyword)); - goto fail; - } - Py_INCREF(value); - SETLOCAL(j, value); - } - } - if (argcount < co->co_argcount) { - int m = co->co_argcount - defcount; - for (i = argcount; i < m; i++) { - if (GETLOCAL(i) == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s() takes %s %d " - "%sargument%s (%d given)", - PyString_AsString(co->co_name), - ((co->co_flags & CO_VARARGS) || - defcount) ? "at least" - : "exactly", - m, kwcount ? "non-keyword " : "", - m == 1 ? "" : "s", i); - goto fail; - } - } - if (n > m) - i = n - m; - else - i = 0; - for (; i < defcount; i++) { - if (GETLOCAL(m+i) == NULL) { - PyObject *def = defs[i]; - Py_INCREF(def); - SETLOCAL(m+i, def); - } - } - } - } - else { - if (argcount > 0 || kwcount > 0) { - PyErr_Format(PyExc_TypeError, - "%.200s() takes no arguments (%d given)", - PyString_AsString(co->co_name), - argcount + kwcount); - goto fail; - } - } - /* Allocate and initialize storage for cell vars, and copy free - vars into frame. This isn't too efficient right now. */ - if (PyTuple_GET_SIZE(co->co_cellvars)) { - int i, j, nargs, found; - char *cellname, *argname; - PyObject *c; - - nargs = co->co_argcount; - if (co->co_flags & CO_VARARGS) - nargs++; - if (co->co_flags & CO_VARKEYWORDS) - nargs++; - - /* Initialize each cell var, taking into account - cell vars that are initialized from arguments. - - Should arrange for the compiler to put cellvars - that are arguments at the beginning of the cellvars - list so that we can march over it more efficiently? - */ - for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) { - cellname = PyString_AS_STRING( - PyTuple_GET_ITEM(co->co_cellvars, i)); - found = 0; - for (j = 0; j < nargs; j++) { - argname = PyString_AS_STRING( - PyTuple_GET_ITEM(co->co_varnames, j)); - if (strcmp(cellname, argname) == 0) { - c = PyCell_New(GETLOCAL(j)); - if (c == NULL) - goto fail; - GETLOCAL(co->co_nlocals + i) = c; - found = 1; - break; - } - } - if (found == 0) { - c = PyCell_New(NULL); - if (c == NULL) - goto fail; - SETLOCAL(co->co_nlocals + i, c); - } - } - } - if (PyTuple_GET_SIZE(co->co_freevars)) { - int i; - for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) { - PyObject *o = PyTuple_GET_ITEM(closure, i); - Py_INCREF(o); - freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o; - } - } - - if (co->co_flags & CO_GENERATOR) { - /* Don't need to keep the reference to f_back, it will be set - * when the generator is resumed. */ - Py_XDECREF(f->f_back); - f->f_back = NULL; - - PCALL(PCALL_GENERATOR); - - /* Create a new generator that owns the ready to run frame - * and return that as the value. */ - return PyGen_New(f); - } - - retval = PyEval_EvalFrameEx(f,0); - - fail: /* Jump here from prelude on failure */ - - /* decref'ing the frame can cause __del__ methods to get invoked, - which can call back into Python. While we're done with the - current Python frame (f), the associated C stack is still in use, - so recursion_depth must be boosted for the duration. - */ - assert(tstate != NULL); - ++tstate->recursion_depth; - Py_DECREF(f); - --tstate->recursion_depth; - return retval; -} - - -/* Implementation notes for set_exc_info() and reset_exc_info(): - -- Below, 'exc_ZZZ' stands for 'exc_type', 'exc_value' and - 'exc_traceback'. These always travel together. - -- tstate->curexc_ZZZ is the "hot" exception that is set by - PyErr_SetString(), cleared by PyErr_Clear(), and so on. - -- Once an exception is caught by an except clause, it is transferred - from tstate->curexc_ZZZ to tstate->exc_ZZZ, from which sys.exc_info() - can pick it up. This is the primary task of set_exc_info(). - XXX That can't be right: set_exc_info() doesn't look at tstate->curexc_ZZZ. - -- Now let me explain the complicated dance with frame->f_exc_ZZZ. - - Long ago, when none of this existed, there were just a few globals: - one set corresponding to the "hot" exception, and one set - corresponding to sys.exc_ZZZ. (Actually, the latter weren't C - globals; they were simply stored as sys.exc_ZZZ. For backwards - compatibility, they still are!) The problem was that in code like - this: - - try: - "something that may fail" - except "some exception": - "do something else first" - "print the exception from sys.exc_ZZZ." - - if "do something else first" invoked something that raised and caught - an exception, sys.exc_ZZZ were overwritten. That was a frequent - cause of subtle bugs. I fixed this by changing the semantics as - follows: - - - Within one frame, sys.exc_ZZZ will hold the last exception caught - *in that frame*. - - - But initially, and as long as no exception is caught in a given - frame, sys.exc_ZZZ will hold the last exception caught in the - previous frame (or the frame before that, etc.). - - The first bullet fixed the bug in the above example. The second - bullet was for backwards compatibility: it was (and is) common to - have a function that is called when an exception is caught, and to - have that function access the caught exception via sys.exc_ZZZ. - (Example: traceback.print_exc()). - - At the same time I fixed the problem that sys.exc_ZZZ weren't - thread-safe, by introducing sys.exc_info() which gets it from tstate; - but that's really a separate improvement. - - The reset_exc_info() function in ceval.c restores the tstate->exc_ZZZ - variables to what they were before the current frame was called. The - set_exc_info() function saves them on the frame so that - reset_exc_info() can restore them. The invariant is that - frame->f_exc_ZZZ is NULL iff the current frame never caught an - exception (where "catching" an exception applies only to successful - except clauses); and if the current frame ever caught an exception, - frame->f_exc_ZZZ is the exception that was stored in tstate->exc_ZZZ - at the start of the current frame. - -*/ - -static void -set_exc_info(PyThreadState *tstate, - PyObject *type, PyObject *value, PyObject *tb) -{ - PyFrameObject *frame = tstate->frame; - PyObject *tmp_type, *tmp_value, *tmp_tb; - - assert(type != NULL); - assert(frame != NULL); - if (frame->f_exc_type == NULL) { - assert(frame->f_exc_value == NULL); - assert(frame->f_exc_traceback == NULL); - /* This frame didn't catch an exception before. */ - /* Save previous exception of this thread in this frame. */ - if (tstate->exc_type == NULL) { - /* XXX Why is this set to Py_None? */ - Py_INCREF(Py_None); - tstate->exc_type = Py_None; - } - Py_INCREF(tstate->exc_type); - Py_XINCREF(tstate->exc_value); - Py_XINCREF(tstate->exc_traceback); - frame->f_exc_type = tstate->exc_type; - frame->f_exc_value = tstate->exc_value; - frame->f_exc_traceback = tstate->exc_traceback; - } - /* Set new exception for this thread. */ - tmp_type = tstate->exc_type; - tmp_value = tstate->exc_value; - tmp_tb = tstate->exc_traceback; - Py_INCREF(type); - Py_XINCREF(value); - Py_XINCREF(tb); - tstate->exc_type = type; - tstate->exc_value = value; - tstate->exc_traceback = tb; - Py_XDECREF(tmp_type); - Py_XDECREF(tmp_value); - Py_XDECREF(tmp_tb); - /* For b/w compatibility */ - PySys_SetObject("exc_type", type); - PySys_SetObject("exc_value", value); - PySys_SetObject("exc_traceback", tb); -} - -static void -reset_exc_info(PyThreadState *tstate) -{ - PyFrameObject *frame; - PyObject *tmp_type, *tmp_value, *tmp_tb; - - /* It's a precondition that the thread state's frame caught an - * exception -- verify in a debug build. - */ - assert(tstate != NULL); - frame = tstate->frame; - assert(frame != NULL); - assert(frame->f_exc_type != NULL); - - /* Copy the frame's exception info back to the thread state. */ - tmp_type = tstate->exc_type; - tmp_value = tstate->exc_value; - tmp_tb = tstate->exc_traceback; - Py_INCREF(frame->f_exc_type); - Py_XINCREF(frame->f_exc_value); - Py_XINCREF(frame->f_exc_traceback); - tstate->exc_type = frame->f_exc_type; - tstate->exc_value = frame->f_exc_value; - tstate->exc_traceback = frame->f_exc_traceback; - Py_XDECREF(tmp_type); - Py_XDECREF(tmp_value); - Py_XDECREF(tmp_tb); - - /* For b/w compatibility */ - PySys_SetObject("exc_type", frame->f_exc_type); - PySys_SetObject("exc_value", frame->f_exc_value); - PySys_SetObject("exc_traceback", frame->f_exc_traceback); - - /* Clear the frame's exception info. */ - tmp_type = frame->f_exc_type; - tmp_value = frame->f_exc_value; - tmp_tb = frame->f_exc_traceback; - frame->f_exc_type = NULL; - frame->f_exc_value = NULL; - frame->f_exc_traceback = NULL; - Py_DECREF(tmp_type); - Py_XDECREF(tmp_value); - Py_XDECREF(tmp_tb); -} - -/* Logic for the raise statement (too complicated for inlining). - This *consumes* a reference count to each of its arguments. */ -static enum why_code -do_raise(PyObject *type, PyObject *value, PyObject *tb) -{ - if (type == NULL) { - /* Reraise */ - PyThreadState *tstate = PyThreadState_GET(); - type = tstate->exc_type == NULL ? Py_None : tstate->exc_type; - value = tstate->exc_value; - tb = tstate->exc_traceback; - Py_XINCREF(type); - Py_XINCREF(value); - Py_XINCREF(tb); - } - - /* We support the following forms of raise: - raise <class>, <classinstance> - raise <class>, <argument tuple> - raise <class>, None - raise <class>, <argument> - raise <classinstance>, None - raise <string>, <object> - raise <string>, None - - An omitted second argument is the same as None. - - In addition, raise <tuple>, <anything> is the same as - raising the tuple's first item (and it better have one!); - this rule is applied recursively. - - Finally, an optional third argument can be supplied, which - gives the traceback to be substituted (useful when - re-raising an exception after examining it). */ - - /* First, check the traceback argument, replacing None with - NULL. */ - if (tb == Py_None) { - Py_DECREF(tb); - tb = NULL; - } - else if (tb != NULL && !PyTraceBack_Check(tb)) { - PyErr_SetString(PyExc_TypeError, - "raise: arg 3 must be a traceback or None"); - goto raise_error; - } - - /* Next, replace a missing value with None */ - if (value == NULL) { - value = Py_None; - Py_INCREF(value); - } - - /* Next, repeatedly, replace a tuple exception with its first item */ - while (PyTuple_Check(type) && PyTuple_Size(type) > 0) { - PyObject *tmp = type; - type = PyTuple_GET_ITEM(type, 0); - Py_INCREF(type); - Py_DECREF(tmp); - } - - if (PyString_CheckExact(type)) { - /* Raising builtin string is deprecated but still allowed -- - * do nothing. Raising an instance of a new-style str - * subclass is right out. */ - if (PyErr_Warn(PyExc_DeprecationWarning, - "raising a string exception is deprecated")) - goto raise_error; - } - else if (PyExceptionClass_Check(type)) - PyErr_NormalizeException(&type, &value, &tb); - - else if (PyExceptionInstance_Check(type)) { - /* Raising an instance. The value should be a dummy. */ - if (value != Py_None) { - PyErr_SetString(PyExc_TypeError, - "instance exception may not have a separate value"); - goto raise_error; - } - else { - /* Normalize to raise <class>, <instance> */ - Py_DECREF(value); - value = type; - type = PyExceptionInstance_Class(type); - Py_INCREF(type); - } - } - else { - /* Not something you can raise. You get an exception - anyway, just not what you specified :-) */ - PyErr_Format(PyExc_TypeError, - "exceptions must be classes, instances, or " - "strings (deprecated), not %s", - type->ob_type->tp_name); - goto raise_error; - } - PyErr_Restore(type, value, tb); - if (tb == NULL) - return WHY_EXCEPTION; - else - return WHY_RERAISE; - raise_error: - Py_XDECREF(value); - Py_XDECREF(type); - Py_XDECREF(tb); - return WHY_EXCEPTION; -} - -/* Iterate v argcnt times and store the results on the stack (via decreasing - sp). Return 1 for success, 0 if error. */ - -static int -unpack_iterable(PyObject *v, int argcnt, PyObject **sp) -{ - int i = 0; - PyObject *it; /* iter(v) */ - PyObject *w; - - assert(v != NULL); - - it = PyObject_GetIter(v); - if (it == NULL) - goto Error; - - for (; i < argcnt; i++) { - w = PyIter_Next(it); - if (w == NULL) { - /* Iterator done, via error or exhaustion. */ - if (!PyErr_Occurred()) { - PyErr_Format(PyExc_ValueError, - "need more than %d value%s to unpack", - i, i == 1 ? "" : "s"); - } - goto Error; - } - *--sp = w; - } - - /* We better have exhausted the iterator now. */ - w = PyIter_Next(it); - if (w == NULL) { - if (PyErr_Occurred()) - goto Error; - Py_DECREF(it); - return 1; - } - Py_DECREF(w); - PyErr_SetString(PyExc_ValueError, "too many values to unpack"); - /* fall through */ -Error: - for (; i > 0; i--, sp++) - Py_DECREF(*sp); - Py_XDECREF(it); - return 0; -} - - -#ifdef LLTRACE -static int -prtrace(PyObject *v, char *str) -{ - printf("%s ", str); - if (PyObject_Print(v, stdout, 0) != 0) - PyErr_Clear(); /* Don't know what else to do */ - printf("\n"); - return 1; -} -#endif - -static void -call_exc_trace(Py_tracefunc func, PyObject *self, PyFrameObject *f) -{ - PyObject *type, *value, *traceback, *arg; - int err; - PyErr_Fetch(&type, &value, &traceback); - if (value == NULL) { - value = Py_None; - Py_INCREF(value); - } - arg = PyTuple_Pack(3, type, value, traceback); - if (arg == NULL) { - PyErr_Restore(type, value, traceback); - return; - } - err = call_trace(func, self, f, PyTrace_EXCEPTION, arg); - Py_DECREF(arg); - if (err == 0) - PyErr_Restore(type, value, traceback); - else { - Py_XDECREF(type); - Py_XDECREF(value); - Py_XDECREF(traceback); - } -} - -static void -call_trace_protected(Py_tracefunc func, PyObject *obj, PyFrameObject *frame, - int what, PyObject *arg) -{ - PyObject *type, *value, *traceback; - int err; - PyErr_Fetch(&type, &value, &traceback); - err = call_trace(func, obj, frame, what, arg); - if (err == 0) - PyErr_Restore(type, value, traceback); - else { - Py_XDECREF(type); - Py_XDECREF(value); - Py_XDECREF(traceback); - } -} - -static int -call_trace(Py_tracefunc func, PyObject *obj, PyFrameObject *frame, - int what, PyObject *arg) -{ - register PyThreadState *tstate = frame->f_tstate; - int result; - if (tstate->tracing) - return 0; - tstate->tracing++; - tstate->use_tracing = 0; - result = func(obj, frame, what, arg); - tstate->use_tracing = ((tstate->c_tracefunc != NULL) - || (tstate->c_profilefunc != NULL)); - tstate->tracing--; - return result; -} - -PyObject * -_PyEval_CallTracing(PyObject *func, PyObject *args) -{ - PyFrameObject *frame = PyEval_GetFrame(); - PyThreadState *tstate = frame->f_tstate; - int save_tracing = tstate->tracing; - int save_use_tracing = tstate->use_tracing; - PyObject *result; - - tstate->tracing = 0; - tstate->use_tracing = ((tstate->c_tracefunc != NULL) - || (tstate->c_profilefunc != NULL)); - result = PyObject_Call(func, args, NULL); - tstate->tracing = save_tracing; - tstate->use_tracing = save_use_tracing; - return result; -} - -static int -maybe_call_line_trace(Py_tracefunc func, PyObject *obj, - PyFrameObject *frame, int *instr_lb, int *instr_ub, - int *instr_prev) -{ - int result = 0; - - /* If the last instruction executed isn't in the current - instruction window, reset the window. If the last - instruction happens to fall at the start of a line or if it - represents a jump backwards, call the trace function. - */ - if ((frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub)) { - int line; - PyAddrPair bounds; - - line = PyCode_CheckLineNumber(frame->f_code, frame->f_lasti, - &bounds); - if (line >= 0) { - frame->f_lineno = line; - result = call_trace(func, obj, frame, - PyTrace_LINE, Py_None); - } - *instr_lb = bounds.ap_lower; - *instr_ub = bounds.ap_upper; - } - else if (frame->f_lasti <= *instr_prev) { - result = call_trace(func, obj, frame, PyTrace_LINE, Py_None); - } - *instr_prev = frame->f_lasti; - return result; -} - -void -PyEval_SetProfile(Py_tracefunc func, PyObject *arg) -{ - PyThreadState *tstate = PyThreadState_GET(); - PyObject *temp = tstate->c_profileobj; - Py_XINCREF(arg); - tstate->c_profilefunc = NULL; - tstate->c_profileobj = NULL; - /* Must make sure that tracing is not ignored if 'temp' is freed */ - tstate->use_tracing = tstate->c_tracefunc != NULL; - Py_XDECREF(temp); - tstate->c_profilefunc = func; - tstate->c_profileobj = arg; - /* Flag that tracing or profiling is turned on */ - tstate->use_tracing = (func != NULL) || (tstate->c_tracefunc != NULL); -} - -void -PyEval_SetTrace(Py_tracefunc func, PyObject *arg) -{ - PyThreadState *tstate = PyThreadState_GET(); - PyObject *temp = tstate->c_traceobj; - Py_XINCREF(arg); - tstate->c_tracefunc = NULL; - tstate->c_traceobj = NULL; - /* Must make sure that profiling is not ignored if 'temp' is freed */ - tstate->use_tracing = tstate->c_profilefunc != NULL; - Py_XDECREF(temp); - tstate->c_tracefunc = func; - tstate->c_traceobj = arg; - /* Flag that tracing or profiling is turned on */ - tstate->use_tracing = ((func != NULL) - || (tstate->c_profilefunc != NULL)); -} - -PyObject * -PyEval_GetBuiltins(void) -{ - PyFrameObject *current_frame = PyEval_GetFrame(); - if (current_frame == NULL) - return PyThreadState_GET()->interp->builtins; - else - return current_frame->f_builtins; -} - -PyObject * -PyEval_GetLocals(void) -{ - PyFrameObject *current_frame = PyEval_GetFrame(); - if (current_frame == NULL) - return NULL; - PyFrame_FastToLocals(current_frame); - return current_frame->f_locals; -} - -PyObject * -PyEval_GetGlobals(void) -{ - PyFrameObject *current_frame = PyEval_GetFrame(); - if (current_frame == NULL) - return NULL; - else - return current_frame->f_globals; -} - -PyFrameObject * -PyEval_GetFrame(void) -{ - PyThreadState *tstate = PyThreadState_GET(); - return _PyThreadState_GetFrame(tstate); -} - -int -PyEval_GetRestricted(void) -{ - PyFrameObject *current_frame = PyEval_GetFrame(); - return current_frame == NULL ? 0 : PyFrame_IsRestricted(current_frame); -} - -int -PyEval_MergeCompilerFlags(PyCompilerFlags *cf) -{ - PyFrameObject *current_frame = PyEval_GetFrame(); - int result = cf->cf_flags != 0; - - if (current_frame != NULL) { - const int codeflags = current_frame->f_code->co_flags; - const int compilerflags = codeflags & PyCF_MASK; - if (compilerflags) { - result = 1; - cf->cf_flags |= compilerflags; - } -#if 0 /* future keyword */ - if (codeflags & CO_GENERATOR_ALLOWED) { - result = 1; - cf->cf_flags |= CO_GENERATOR_ALLOWED; - } -#endif - } - return result; -} - -int -Py_FlushLine(void) -{ - PyObject *f = PySys_GetObject("stdout"); - if (f == NULL) - return 0; - if (!PyFile_SoftSpace(f, 0)) - return 0; - return PyFile_WriteString("\n", f); -} - - -/* External interface to call any callable object. - The arg must be a tuple or NULL. */ - -#undef PyEval_CallObject -/* for backward compatibility: export this interface */ - -PyObject * -PyEval_CallObject(PyObject *func, PyObject *arg) -{ - return PyEval_CallObjectWithKeywords(func, arg, (PyObject *)NULL); -} -#define PyEval_CallObject(func,arg) \ - PyEval_CallObjectWithKeywords(func, arg, (PyObject *)NULL) - -PyObject * -PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw) -{ - PyObject *result; - - if (arg == NULL) { - arg = PyTuple_New(0); - if (arg == NULL) - return NULL; - } - else if (!PyTuple_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "argument list must be a tuple"); - return NULL; - } - else - Py_INCREF(arg); - - if (kw != NULL && !PyDict_Check(kw)) { - PyErr_SetString(PyExc_TypeError, - "keyword list must be a dictionary"); - Py_DECREF(arg); - return NULL; - } - - result = PyObject_Call(func, arg, kw); - Py_DECREF(arg); - return result; -} - -const char * -PyEval_GetFuncName(PyObject *func) -{ - if (PyMethod_Check(func)) - return PyEval_GetFuncName(PyMethod_GET_FUNCTION(func)); - else if (PyFunction_Check(func)) - return PyString_AsString(((PyFunctionObject*)func)->func_name); - else if (PyCFunction_Check(func)) - return ((PyCFunctionObject*)func)->m_ml->ml_name; - else if (PyClass_Check(func)) - return PyString_AsString(((PyClassObject*)func)->cl_name); - else if (PyInstance_Check(func)) { - return PyString_AsString( - ((PyInstanceObject*)func)->in_class->cl_name); - } else { - return func->ob_type->tp_name; - } -} - -const char * -PyEval_GetFuncDesc(PyObject *func) -{ - if (PyMethod_Check(func)) - return "()"; - else if (PyFunction_Check(func)) - return "()"; - else if (PyCFunction_Check(func)) - return "()"; - else if (PyClass_Check(func)) - return " constructor"; - else if (PyInstance_Check(func)) { - return " instance"; - } else { - return " object"; - } -} - -static void -err_args(PyObject *func, int flags, int nargs) -{ - if (flags & METH_NOARGS) - PyErr_Format(PyExc_TypeError, - "%.200s() takes no arguments (%d given)", - ((PyCFunctionObject *)func)->m_ml->ml_name, - nargs); - else - PyErr_Format(PyExc_TypeError, - "%.200s() takes exactly one argument (%d given)", - ((PyCFunctionObject *)func)->m_ml->ml_name, - nargs); -} - -#define C_TRACE(x, call) \ -if (tstate->use_tracing && tstate->c_profilefunc) { \ - if (call_trace(tstate->c_profilefunc, \ - tstate->c_profileobj, \ - tstate->frame, PyTrace_C_CALL, \ - func)) { \ - x = NULL; \ - } \ - else { \ - x = call; \ - if (tstate->c_profilefunc != NULL) { \ - if (x == NULL) { \ - call_trace_protected(tstate->c_profilefunc, \ - tstate->c_profileobj, \ - tstate->frame, PyTrace_C_EXCEPTION, \ - func); \ - /* XXX should pass (type, value, tb) */ \ - } else { \ - if (call_trace(tstate->c_profilefunc, \ - tstate->c_profileobj, \ - tstate->frame, PyTrace_C_RETURN, \ - func)) { \ - Py_DECREF(x); \ - x = NULL; \ - } \ - } \ - } \ - } \ -} else { \ - x = call; \ - } - -static PyObject * -call_function(PyObject ***pp_stack, int oparg -#ifdef WITH_TSC - , uint64* pintr0, uint64* pintr1 -#endif - ) -{ - int na = oparg & 0xff; - int nk = (oparg>>8) & 0xff; - int n = na + 2 * nk; - PyObject **pfunc = (*pp_stack) - n - 1; - PyObject *func = *pfunc; - PyObject *x, *w; - - /* Always dispatch PyCFunction first, because these are - presumed to be the most frequent callable object. - */ - if (PyCFunction_Check(func) && nk == 0) { - int flags = PyCFunction_GET_FLAGS(func); - PyThreadState *tstate = PyThreadState_GET(); - - PCALL(PCALL_CFUNCTION); - if (flags & (METH_NOARGS | METH_O)) { - PyCFunction meth = PyCFunction_GET_FUNCTION(func); - PyObject *self = PyCFunction_GET_SELF(func); - if (flags & METH_NOARGS && na == 0) { - C_TRACE(x, (*meth)(self,NULL)); - } - else if (flags & METH_O && na == 1) { - PyObject *arg = EXT_POP(*pp_stack); - C_TRACE(x, (*meth)(self,arg)); - Py_DECREF(arg); - } - else { - err_args(func, flags, na); - x = NULL; - } - } - else { - PyObject *callargs; - callargs = load_args(pp_stack, na); - READ_TIMESTAMP(*pintr0); - C_TRACE(x, PyCFunction_Call(func,callargs,NULL)); - READ_TIMESTAMP(*pintr1); - Py_XDECREF(callargs); - } - } else { - if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) { - /* optimize access to bound methods */ - PyObject *self = PyMethod_GET_SELF(func); - PCALL(PCALL_METHOD); - PCALL(PCALL_BOUND_METHOD); - Py_INCREF(self); - func = PyMethod_GET_FUNCTION(func); - Py_INCREF(func); - Py_DECREF(*pfunc); - *pfunc = self; - na++; - n++; - } else - Py_INCREF(func); - READ_TIMESTAMP(*pintr0); - if (PyFunction_Check(func)) - x = fast_function(func, pp_stack, n, na, nk); - else - x = do_call(func, pp_stack, na, nk); - READ_TIMESTAMP(*pintr1); - Py_DECREF(func); - } - - /* Clear the stack of the function object. Also removes - the arguments in case they weren't consumed already - (fast_function() and err_args() leave them on the stack). - */ - while ((*pp_stack) > pfunc) { - w = EXT_POP(*pp_stack); - Py_DECREF(w); - PCALL(PCALL_POP); - } - return x; -} - -/* The fast_function() function optimize calls for which no argument - tuple is necessary; the objects are passed directly from the stack. - For the simplest case -- a function that takes only positional - arguments and is called with only positional arguments -- it - inlines the most primitive frame setup code from - PyEval_EvalCodeEx(), which vastly reduces the checks that must be - done before evaluating the frame. -*/ - -static PyObject * -fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk) -{ - PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); - PyObject *globals = PyFunction_GET_GLOBALS(func); - PyObject *argdefs = PyFunction_GET_DEFAULTS(func); - PyObject **d = NULL; - int nd = 0; - - PCALL(PCALL_FUNCTION); - PCALL(PCALL_FAST_FUNCTION); - if (argdefs == NULL && co->co_argcount == n && nk==0 && - co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { - PyFrameObject *f; - PyObject *retval = NULL; - PyThreadState *tstate = PyThreadState_GET(); - PyObject **fastlocals, **stack; - int i; - - PCALL(PCALL_FASTER_FUNCTION); - assert(globals != NULL); - /* XXX Perhaps we should create a specialized - PyFrame_New() that doesn't take locals, but does - take builtins without sanity checking them. - */ - assert(tstate != NULL); - f = PyFrame_New(tstate, co, globals, NULL); - if (f == NULL) - return NULL; - - fastlocals = f->f_localsplus; - stack = (*pp_stack) - n; - - for (i = 0; i < n; i++) { - Py_INCREF(*stack); - fastlocals[i] = *stack++; - } - retval = PyEval_EvalFrameEx(f,0); - ++tstate->recursion_depth; - Py_DECREF(f); - --tstate->recursion_depth; - return retval; - } - if (argdefs != NULL) { - d = &PyTuple_GET_ITEM(argdefs, 0); - nd = ((PyTupleObject *)argdefs)->ob_size; - } - return PyEval_EvalCodeEx(co, globals, - (PyObject *)NULL, (*pp_stack)-n, na, - (*pp_stack)-2*nk, nk, d, nd, - PyFunction_GET_CLOSURE(func)); -} - -static PyObject * -update_keyword_args(PyObject *orig_kwdict, int nk, PyObject ***pp_stack, - PyObject *func) -{ - PyObject *kwdict = NULL; - if (orig_kwdict == NULL) - kwdict = PyDict_New(); - else { - kwdict = PyDict_Copy(orig_kwdict); - Py_DECREF(orig_kwdict); - } - if (kwdict == NULL) - return NULL; - while (--nk >= 0) { - int err; - PyObject *value = EXT_POP(*pp_stack); - PyObject *key = EXT_POP(*pp_stack); - if (PyDict_GetItem(kwdict, key) != NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s%s got multiple values " - "for keyword argument '%.200s'", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func), - PyString_AsString(key)); - Py_DECREF(key); - Py_DECREF(value); - Py_DECREF(kwdict); - return NULL; - } - err = PyDict_SetItem(kwdict, key, value); - Py_DECREF(key); - Py_DECREF(value); - if (err) { - Py_DECREF(kwdict); - return NULL; - } - } - return kwdict; -} - -static PyObject * -update_star_args(int nstack, int nstar, PyObject *stararg, - PyObject ***pp_stack) -{ - PyObject *callargs, *w; - - callargs = PyTuple_New(nstack + nstar); - if (callargs == NULL) { - return NULL; - } - if (nstar) { - int i; - for (i = 0; i < nstar; i++) { - PyObject *a = PyTuple_GET_ITEM(stararg, i); - Py_INCREF(a); - PyTuple_SET_ITEM(callargs, nstack + i, a); - } - } - while (--nstack >= 0) { - w = EXT_POP(*pp_stack); - PyTuple_SET_ITEM(callargs, nstack, w); - } - return callargs; -} - -static PyObject * -load_args(PyObject ***pp_stack, int na) -{ - PyObject *args = PyTuple_New(na); - PyObject *w; - - if (args == NULL) - return NULL; - while (--na >= 0) { - w = EXT_POP(*pp_stack); - PyTuple_SET_ITEM(args, na, w); - } - return args; -} - -static PyObject * -do_call(PyObject *func, PyObject ***pp_stack, int na, int nk) -{ - PyObject *callargs = NULL; - PyObject *kwdict = NULL; - PyObject *result = NULL; - - if (nk > 0) { - kwdict = update_keyword_args(NULL, nk, pp_stack, func); - if (kwdict == NULL) - goto call_fail; - } - callargs = load_args(pp_stack, na); - if (callargs == NULL) - goto call_fail; -#ifdef CALL_PROFILE - /* At this point, we have to look at the type of func to - update the call stats properly. Do it here so as to avoid - exposing the call stats machinery outside ceval.c - */ - if (PyFunction_Check(func)) - PCALL(PCALL_FUNCTION); - else if (PyMethod_Check(func)) - PCALL(PCALL_METHOD); - else if (PyType_Check(func)) - PCALL(PCALL_TYPE); - else - PCALL(PCALL_OTHER); -#endif - result = PyObject_Call(func, callargs, kwdict); - call_fail: - Py_XDECREF(callargs); - Py_XDECREF(kwdict); - return result; -} - -static PyObject * -ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk) -{ - int nstar = 0; - PyObject *callargs = NULL; - PyObject *stararg = NULL; - PyObject *kwdict = NULL; - PyObject *result = NULL; - - if (flags & CALL_FLAG_KW) { - kwdict = EXT_POP(*pp_stack); - if (!(kwdict && PyDict_Check(kwdict))) { - PyErr_Format(PyExc_TypeError, - "%s%s argument after ** " - "must be a dictionary", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func)); - goto ext_call_fail; - } - } - if (flags & CALL_FLAG_VAR) { - stararg = EXT_POP(*pp_stack); - if (!PyTuple_Check(stararg)) { - PyObject *t = NULL; - t = PySequence_Tuple(stararg); - if (t == NULL) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) { - PyErr_Format(PyExc_TypeError, - "%s%s argument after * " - "must be a sequence", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func)); - } - goto ext_call_fail; - } - Py_DECREF(stararg); - stararg = t; - } - nstar = PyTuple_GET_SIZE(stararg); - } - if (nk > 0) { - kwdict = update_keyword_args(kwdict, nk, pp_stack, func); - if (kwdict == NULL) - goto ext_call_fail; - } - callargs = update_star_args(na, nstar, stararg, pp_stack); - if (callargs == NULL) - goto ext_call_fail; -#ifdef CALL_PROFILE - /* At this point, we have to look at the type of func to - update the call stats properly. Do it here so as to avoid - exposing the call stats machinery outside ceval.c - */ - if (PyFunction_Check(func)) - PCALL(PCALL_FUNCTION); - else if (PyMethod_Check(func)) - PCALL(PCALL_METHOD); - else if (PyType_Check(func)) - PCALL(PCALL_TYPE); - else - PCALL(PCALL_OTHER); -#endif - result = PyObject_Call(func, callargs, kwdict); - ext_call_fail: - Py_XDECREF(callargs); - Py_XDECREF(kwdict); - Py_XDECREF(stararg); - return result; -} - -/* Extract a slice index from a PyInt or PyLong or an object with the - nb_index slot defined, and store in *pi. - Silently reduce values larger than PY_SSIZE_T_MAX to PY_SSIZE_T_MAX, - and silently boost values less than -PY_SSIZE_T_MAX-1 to -PY_SSIZE_T_MAX-1. - Return 0 on error, 1 on success. -*/ -/* Note: If v is NULL, return success without storing into *pi. This - is because_PyEval_SliceIndex() is called by apply_slice(), which can be - called by the SLICE opcode with v and/or w equal to NULL. -*/ -int -_PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi) -{ - if (v != NULL) { - Py_ssize_t x; - if (PyInt_Check(v)) { - /* XXX(nnorwitz): I think PyInt_AS_LONG is correct, - however, it looks like it should be AsSsize_t. - There should be a comment here explaining why. - */ - x = PyInt_AS_LONG(v); - } - else if (PyIndex_Check(v)) { - x = PyNumber_AsSsize_t(v, NULL); - if (x == -1 && PyErr_Occurred()) - return 0; - } - else { - PyErr_SetString(PyExc_TypeError, - "slice indices must be integers or " - "None or have an __index__ method"); - return 0; - } - *pi = x; - } - return 1; -} - -#undef ISINDEX -#define ISINDEX(x) ((x) == NULL || \ - PyInt_Check(x) || PyLong_Check(x) || PyIndex_Check(x)) - -static PyObject * -apply_slice(PyObject *u, PyObject *v, PyObject *w) /* return u[v:w] */ -{ - PyTypeObject *tp = u->ob_type; - PySequenceMethods *sq = tp->tp_as_sequence; - - if (sq && sq->sq_slice && ISINDEX(v) && ISINDEX(w)) { - Py_ssize_t ilow = 0, ihigh = PY_SSIZE_T_MAX; - if (!_PyEval_SliceIndex(v, &ilow)) - return NULL; - if (!_PyEval_SliceIndex(w, &ihigh)) - return NULL; - return PySequence_GetSlice(u, ilow, ihigh); - } - else { - PyObject *slice = PySlice_New(v, w, NULL); - if (slice != NULL) { - PyObject *res = PyObject_GetItem(u, slice); - Py_DECREF(slice); - return res; - } - else - return NULL; - } -} - -static int -assign_slice(PyObject *u, PyObject *v, PyObject *w, PyObject *x) - /* u[v:w] = x */ -{ - PyTypeObject *tp = u->ob_type; - PySequenceMethods *sq = tp->tp_as_sequence; - - if (sq && sq->sq_ass_slice && ISINDEX(v) && ISINDEX(w)) { - Py_ssize_t ilow = 0, ihigh = PY_SSIZE_T_MAX; - if (!_PyEval_SliceIndex(v, &ilow)) - return -1; - if (!_PyEval_SliceIndex(w, &ihigh)) - return -1; - if (x == NULL) - return PySequence_DelSlice(u, ilow, ihigh); - else - return PySequence_SetSlice(u, ilow, ihigh, x); - } - else { - PyObject *slice = PySlice_New(v, w, NULL); - if (slice != NULL) { - int res; - if (x != NULL) - res = PyObject_SetItem(u, slice, x); - else - res = PyObject_DelItem(u, slice); - Py_DECREF(slice); - return res; - } - else - return -1; - } -} - -static PyObject * -cmp_outcome(int op, register PyObject *v, register PyObject *w) -{ - int res = 0; - switch (op) { - case PyCmp_IS: - res = (v == w); - break; - case PyCmp_IS_NOT: - res = (v != w); - break; - case PyCmp_IN: - res = PySequence_Contains(w, v); - if (res < 0) - return NULL; - break; - case PyCmp_NOT_IN: - res = PySequence_Contains(w, v); - if (res < 0) - return NULL; - res = !res; - break; - case PyCmp_EXC_MATCH: - res = PyErr_GivenExceptionMatches(v, w); - break; - default: - return PyObject_RichCompare(v, w, op); - } - v = res ? Py_True : Py_False; - Py_INCREF(v); - return v; -} - -static PyObject * -import_from(PyObject *v, PyObject *name) -{ - PyObject *x; - - x = PyObject_GetAttr(v, name); - if (x == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Format(PyExc_ImportError, - "cannot import name %.230s", - PyString_AsString(name)); - } - return x; -} - -static int -import_all_from(PyObject *locals, PyObject *v) -{ - PyObject *all = PyObject_GetAttrString(v, "__all__"); - PyObject *dict, *name, *value; - int skip_leading_underscores = 0; - int pos, err; - - if (all == NULL) { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) - return -1; /* Unexpected error */ - PyErr_Clear(); - dict = PyObject_GetAttrString(v, "__dict__"); - if (dict == NULL) { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) - return -1; - PyErr_SetString(PyExc_ImportError, - "from-import-* object has no __dict__ and no __all__"); - return -1; - } - all = PyMapping_Keys(dict); - Py_DECREF(dict); - if (all == NULL) - return -1; - skip_leading_underscores = 1; - } - - for (pos = 0, err = 0; ; pos++) { - name = PySequence_GetItem(all, pos); - if (name == NULL) { - if (!PyErr_ExceptionMatches(PyExc_IndexError)) - err = -1; - else - PyErr_Clear(); - break; - } - if (skip_leading_underscores && - PyString_Check(name) && - PyString_AS_STRING(name)[0] == '_') - { - Py_DECREF(name); - continue; - } - value = PyObject_GetAttr(v, name); - if (value == NULL) - err = -1; - else if (PyDict_CheckExact(locals)) - err = PyDict_SetItem(locals, name, value); - else - err = PyObject_SetItem(locals, name, value); - Py_DECREF(name); - Py_XDECREF(value); - if (err != 0) - break; - } - Py_DECREF(all); - return err; -} - -static PyObject * -build_class(PyObject *methods, PyObject *bases, PyObject *name) -{ - PyObject *metaclass = NULL, *result, *base; - - if (PyDict_Check(methods)) - metaclass = PyDict_GetItemString(methods, "__metaclass__"); - if (metaclass != NULL) - Py_INCREF(metaclass); - else if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) { - base = PyTuple_GET_ITEM(bases, 0); - metaclass = PyObject_GetAttrString(base, "__class__"); - if (metaclass == NULL) { - PyErr_Clear(); - metaclass = (PyObject *)base->ob_type; - Py_INCREF(metaclass); - } - } - else { - PyObject *g = PyEval_GetGlobals(); - if (g != NULL && PyDict_Check(g)) - metaclass = PyDict_GetItemString(g, "__metaclass__"); - if (metaclass == NULL) - metaclass = (PyObject *) &PyClass_Type; - Py_INCREF(metaclass); - } - result = PyObject_CallFunctionObjArgs(metaclass, name, bases, methods, NULL); - Py_DECREF(metaclass); - if (result == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) { - /* A type error here likely means that the user passed - in a base that was not a class (such the random module - instead of the random.random type). Help them out with - by augmenting the error message with more information.*/ - - PyObject *ptype, *pvalue, *ptraceback; - - PyErr_Fetch(&ptype, &pvalue, &ptraceback); - if (PyString_Check(pvalue)) { - PyObject *newmsg; - newmsg = PyString_FromFormat( - "Error when calling the metaclass bases\n %s", - PyString_AS_STRING(pvalue)); - if (newmsg != NULL) { - Py_DECREF(pvalue); - pvalue = newmsg; - } - } - PyErr_Restore(ptype, pvalue, ptraceback); - } - return result; -} - -static int -exec_statement(PyFrameObject *f, PyObject *prog, PyObject *globals, - PyObject *locals) -{ - int n; - PyObject *v; - int plain = 0; - - if (PyTuple_Check(prog) && globals == Py_None && locals == Py_None && - ((n = PyTuple_Size(prog)) == 2 || n == 3)) { - /* Backward compatibility hack */ - globals = PyTuple_GetItem(prog, 1); - if (n == 3) - locals = PyTuple_GetItem(prog, 2); - prog = PyTuple_GetItem(prog, 0); - } - if (globals == Py_None) { - globals = PyEval_GetGlobals(); - if (locals == Py_None) { - locals = PyEval_GetLocals(); - plain = 1; - } - if (!globals || !locals) { - PyErr_SetString(PyExc_SystemError, - "globals and locals cannot be NULL"); - return -1; - } - } - else if (locals == Py_None) - locals = globals; - if (!PyString_Check(prog) && - !PyUnicode_Check(prog) && - !PyCode_Check(prog) && - !PyFile_Check(prog)) { - PyErr_SetString(PyExc_TypeError, - "exec: arg 1 must be a string, file, or code object"); - return -1; - } - if (!PyDict_Check(globals)) { - PyErr_SetString(PyExc_TypeError, - "exec: arg 2 must be a dictionary or None"); - return -1; - } - if (!PyMapping_Check(locals)) { - PyErr_SetString(PyExc_TypeError, - "exec: arg 3 must be a mapping or None"); - return -1; - } - if (PyDict_GetItemString(globals, "__builtins__") == NULL) - PyDict_SetItemString(globals, "__builtins__", f->f_builtins); - if (PyCode_Check(prog)) { - if (PyCode_GetNumFree((PyCodeObject *)prog) > 0) { - PyErr_SetString(PyExc_TypeError, - "code object passed to exec may not contain free variables"); - return -1; - } - v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals); - } - else if (PyFile_Check(prog)) { - FILE *fp = PyFile_AsFile(prog); - char *name = PyString_AsString(PyFile_Name(prog)); - PyCompilerFlags cf; - if (name == NULL) - return -1; - cf.cf_flags = 0; - if (PyEval_MergeCompilerFlags(&cf)) - v = PyRun_FileFlags(fp, name, Py_file_input, globals, - locals, &cf); - else - v = PyRun_File(fp, name, Py_file_input, globals, - locals); - } - else { - PyObject *tmp = NULL; - char *str; - PyCompilerFlags cf; - cf.cf_flags = 0; -#ifdef Py_USING_UNICODE - if (PyUnicode_Check(prog)) { - tmp = PyUnicode_AsUTF8String(prog); - if (tmp == NULL) - return -1; - prog = tmp; - cf.cf_flags |= PyCF_SOURCE_IS_UTF8; - } -#endif - if (PyString_AsStringAndSize(prog, &str, NULL)) - return -1; - if (PyEval_MergeCompilerFlags(&cf)) - v = PyRun_StringFlags(str, Py_file_input, globals, - locals, &cf); - else - v = PyRun_String(str, Py_file_input, globals, locals); - Py_XDECREF(tmp); - } - if (plain) - PyFrame_LocalsToFast(f, 0); - if (v == NULL) - return -1; - Py_DECREF(v); - return 0; -} - -static void -format_exc_check_arg(PyObject *exc, char *format_str, PyObject *obj) -{ - char *obj_str; - - if (!obj) - return; - - obj_str = PyString_AsString(obj); - if (!obj_str) - return; - - PyErr_Format(exc, format_str, obj_str); -} - -static PyObject * -string_concatenate(PyObject *v, PyObject *w, - PyFrameObject *f, unsigned char *next_instr) -{ - /* This function implements 'variable += expr' when both arguments - are strings. */ - Py_ssize_t v_len = PyString_GET_SIZE(v); - Py_ssize_t w_len = PyString_GET_SIZE(w); - Py_ssize_t new_len = v_len + w_len; - if (new_len < 0) { - PyErr_SetString(PyExc_OverflowError, - "strings are too large to concat"); - return NULL; - } - - if (v->ob_refcnt == 2) { - /* In the common case, there are 2 references to the value - * stored in 'variable' when the += is performed: one on the - * value stack (in 'v') and one still stored in the 'variable'. - * We try to delete the variable now to reduce the refcnt to 1. - */ - switch (*next_instr) { - case STORE_FAST: - { - int oparg = PEEKARG(); - PyObject **fastlocals = f->f_localsplus; - if (GETLOCAL(oparg) == v) - SETLOCAL(oparg, NULL); - break; - } - case STORE_DEREF: - { - PyObject **freevars = f->f_localsplus + f->f_code->co_nlocals; - PyObject *c = freevars[PEEKARG()]; - if (PyCell_GET(c) == v) - PyCell_Set(c, NULL); - break; - } - case STORE_NAME: - { - PyObject *names = f->f_code->co_names; - PyObject *name = GETITEM(names, PEEKARG()); - PyObject *locals = f->f_locals; - if (PyDict_CheckExact(locals) && - PyDict_GetItem(locals, name) == v) { - if (PyDict_DelItem(locals, name) != 0) { - PyErr_Clear(); - } - } - break; - } - } - } - - if (v->ob_refcnt == 1 && !PyString_CHECK_INTERNED(v)) { - /* Now we own the last reference to 'v', so we can resize it - * in-place. - */ - if (_PyString_Resize(&v, new_len) != 0) { - /* XXX if _PyString_Resize() fails, 'v' has been - * deallocated so it cannot be put back into 'variable'. - * The MemoryError is raised when there is no value in - * 'variable', which might (very remotely) be a cause - * of incompatibilities. - */ - return NULL; - } - /* copy 'w' into the newly allocated area of 'v' */ - memcpy(PyString_AS_STRING(v) + v_len, - PyString_AS_STRING(w), w_len); - return v; - } - else { - /* When in-place resizing is not an option. */ - PyString_Concat(&v, w); - return v; - } -} - -#ifdef DYNAMIC_EXECUTION_PROFILE - -static PyObject * -getarray(long a[256]) -{ - int i; - PyObject *l = PyList_New(256); - if (l == NULL) return NULL; - for (i = 0; i < 256; i++) { - PyObject *x = PyInt_FromLong(a[i]); - if (x == NULL) { - Py_DECREF(l); - return NULL; - } - PyList_SetItem(l, i, x); - } - for (i = 0; i < 256; i++) - a[i] = 0; - return l; -} - -PyObject * -_Py_GetDXProfile(PyObject *self, PyObject *args) -{ -#ifndef DXPAIRS - return getarray(dxp); -#else - int i; - PyObject *l = PyList_New(257); - if (l == NULL) return NULL; - for (i = 0; i < 257; i++) { - PyObject *x = getarray(dxpairs[i]); - if (x == NULL) { - Py_DECREF(l); - return NULL; - } - PyList_SetItem(l, i, x); - } - return l; -#endif -} - -#endif diff --git a/sys/src/cmd/python/Python/codecs.c b/sys/src/cmd/python/Python/codecs.c deleted file mode 100644 index 4b0f4cb0d..000000000 --- a/sys/src/cmd/python/Python/codecs.c +++ /dev/null @@ -1,860 +0,0 @@ -/* ------------------------------------------------------------------------ - - Python Codec Registry and support functions - -Written by Marc-Andre Lemburg (mal@lemburg.com). - -Copyright (c) Corporation for National Research Initiatives. - - ------------------------------------------------------------------------ */ - -#include "Python.h" -#include <ctype.h> - -/* --- Codec Registry ----------------------------------------------------- */ - -/* Import the standard encodings package which will register the first - codec search function. - - This is done in a lazy way so that the Unicode implementation does - not downgrade startup time of scripts not needing it. - - ImportErrors are silently ignored by this function. Only one try is - made. - -*/ - -static int _PyCodecRegistry_Init(void); /* Forward */ - -int PyCodec_Register(PyObject *search_function) -{ - PyInterpreterState *interp = PyThreadState_GET()->interp; - if (interp->codec_search_path == NULL && _PyCodecRegistry_Init()) - goto onError; - if (search_function == NULL) { - PyErr_BadArgument(); - goto onError; - } - if (!PyCallable_Check(search_function)) { - PyErr_SetString(PyExc_TypeError, "argument must be callable"); - goto onError; - } - return PyList_Append(interp->codec_search_path, search_function); - - onError: - return -1; -} - -/* Convert a string to a normalized Python string: all characters are - converted to lower case, spaces are replaced with underscores. */ - -static -PyObject *normalizestring(const char *string) -{ - register size_t i; - size_t len = strlen(string); - char *p; - PyObject *v; - - if (len > PY_SSIZE_T_MAX) { - PyErr_SetString(PyExc_OverflowError, "string is too large"); - return NULL; - } - - v = PyString_FromStringAndSize(NULL, len); - if (v == NULL) - return NULL; - p = PyString_AS_STRING(v); - for (i = 0; i < len; i++) { - register char ch = string[i]; - if (ch == ' ') - ch = '-'; - else - ch = tolower(Py_CHARMASK(ch)); - p[i] = ch; - } - return v; -} - -/* Lookup the given encoding and return a tuple providing the codec - facilities. - - The encoding string is looked up converted to all lower-case - characters. This makes encodings looked up through this mechanism - effectively case-insensitive. - - If no codec is found, a LookupError is set and NULL returned. - - As side effect, this tries to load the encodings package, if not - yet done. This is part of the lazy load strategy for the encodings - package. - -*/ - -PyObject *_PyCodec_Lookup(const char *encoding) -{ - PyInterpreterState *interp; - PyObject *result, *args = NULL, *v; - Py_ssize_t i, len; - - if (encoding == NULL) { - PyErr_BadArgument(); - goto onError; - } - - interp = PyThreadState_GET()->interp; - if (interp->codec_search_path == NULL && _PyCodecRegistry_Init()) - goto onError; - - /* Convert the encoding to a normalized Python string: all - characters are converted to lower case, spaces and hyphens are - replaced with underscores. */ - v = normalizestring(encoding); - if (v == NULL) - goto onError; - PyString_InternInPlace(&v); - - /* First, try to lookup the name in the registry dictionary */ - result = PyDict_GetItem(interp->codec_search_cache, v); - if (result != NULL) { - Py_INCREF(result); - Py_DECREF(v); - return result; - } - - /* Next, scan the search functions in order of registration */ - args = PyTuple_New(1); - if (args == NULL) - goto onError; - PyTuple_SET_ITEM(args,0,v); - - len = PyList_Size(interp->codec_search_path); - if (len < 0) - goto onError; - if (len == 0) { - PyErr_SetString(PyExc_LookupError, - "no codec search functions registered: " - "can't find encoding"); - goto onError; - } - - for (i = 0; i < len; i++) { - PyObject *func; - - func = PyList_GetItem(interp->codec_search_path, i); - if (func == NULL) - goto onError; - result = PyEval_CallObject(func, args); - if (result == NULL) - goto onError; - if (result == Py_None) { - Py_DECREF(result); - continue; - } - if (!PyTuple_Check(result) || PyTuple_GET_SIZE(result) != 4) { - PyErr_SetString(PyExc_TypeError, - "codec search functions must return 4-tuples"); - Py_DECREF(result); - goto onError; - } - break; - } - if (i == len) { - /* XXX Perhaps we should cache misses too ? */ - PyErr_Format(PyExc_LookupError, - "unknown encoding: %s", encoding); - goto onError; - } - - /* Cache and return the result */ - PyDict_SetItem(interp->codec_search_cache, v, result); - Py_DECREF(args); - return result; - - onError: - Py_XDECREF(args); - return NULL; -} - -static -PyObject *args_tuple(PyObject *object, - const char *errors) -{ - PyObject *args; - - args = PyTuple_New(1 + (errors != NULL)); - if (args == NULL) - return NULL; - Py_INCREF(object); - PyTuple_SET_ITEM(args,0,object); - if (errors) { - PyObject *v; - - v = PyString_FromString(errors); - if (v == NULL) { - Py_DECREF(args); - return NULL; - } - PyTuple_SET_ITEM(args, 1, v); - } - return args; -} - -/* Helper function to get a codec item */ - -static -PyObject *codec_getitem(const char *encoding, int index) -{ - PyObject *codecs; - PyObject *v; - - codecs = _PyCodec_Lookup(encoding); - if (codecs == NULL) - return NULL; - v = PyTuple_GET_ITEM(codecs, index); - Py_DECREF(codecs); - Py_INCREF(v); - return v; -} - -/* Helper function to create an incremental codec. */ - -static -PyObject *codec_getincrementalcodec(const char *encoding, - const char *errors, - const char *attrname) -{ - PyObject *codecs, *ret, *inccodec; - - codecs = _PyCodec_Lookup(encoding); - if (codecs == NULL) - return NULL; - inccodec = PyObject_GetAttrString(codecs, attrname); - Py_DECREF(codecs); - if (inccodec == NULL) - return NULL; - if (errors) - ret = PyObject_CallFunction(inccodec, "s", errors); - else - ret = PyObject_CallFunction(inccodec, NULL); - Py_DECREF(inccodec); - return ret; -} - -/* Helper function to create a stream codec. */ - -static -PyObject *codec_getstreamcodec(const char *encoding, - PyObject *stream, - const char *errors, - const int index) -{ - PyObject *codecs, *streamcodec, *codeccls; - - codecs = _PyCodec_Lookup(encoding); - if (codecs == NULL) - return NULL; - - codeccls = PyTuple_GET_ITEM(codecs, index); - if (errors != NULL) - streamcodec = PyObject_CallFunction(codeccls, "Os", stream, errors); - else - streamcodec = PyObject_CallFunction(codeccls, "O", stream); - Py_DECREF(codecs); - return streamcodec; -} - -/* Convenience APIs to query the Codec registry. - - All APIs return a codec object with incremented refcount. - - */ - -PyObject *PyCodec_Encoder(const char *encoding) -{ - return codec_getitem(encoding, 0); -} - -PyObject *PyCodec_Decoder(const char *encoding) -{ - return codec_getitem(encoding, 1); -} - -PyObject *PyCodec_IncrementalEncoder(const char *encoding, - const char *errors) -{ - return codec_getincrementalcodec(encoding, errors, "incrementalencoder"); -} - -PyObject *PyCodec_IncrementalDecoder(const char *encoding, - const char *errors) -{ - return codec_getincrementalcodec(encoding, errors, "incrementaldecoder"); -} - -PyObject *PyCodec_StreamReader(const char *encoding, - PyObject *stream, - const char *errors) -{ - return codec_getstreamcodec(encoding, stream, errors, 2); -} - -PyObject *PyCodec_StreamWriter(const char *encoding, - PyObject *stream, - const char *errors) -{ - return codec_getstreamcodec(encoding, stream, errors, 3); -} - -/* Encode an object (e.g. an Unicode object) using the given encoding - and return the resulting encoded object (usually a Python string). - - errors is passed to the encoder factory as argument if non-NULL. */ - -PyObject *PyCodec_Encode(PyObject *object, - const char *encoding, - const char *errors) -{ - PyObject *encoder = NULL; - PyObject *args = NULL, *result = NULL; - PyObject *v; - - encoder = PyCodec_Encoder(encoding); - if (encoder == NULL) - goto onError; - - args = args_tuple(object, errors); - if (args == NULL) - goto onError; - - result = PyEval_CallObject(encoder,args); - if (result == NULL) - goto onError; - - if (!PyTuple_Check(result) || - PyTuple_GET_SIZE(result) != 2) { - PyErr_SetString(PyExc_TypeError, - "encoder must return a tuple (object,integer)"); - goto onError; - } - v = PyTuple_GET_ITEM(result,0); - Py_INCREF(v); - /* We don't check or use the second (integer) entry. */ - - Py_DECREF(args); - Py_DECREF(encoder); - Py_DECREF(result); - return v; - - onError: - Py_XDECREF(result); - Py_XDECREF(args); - Py_XDECREF(encoder); - return NULL; -} - -/* Decode an object (usually a Python string) using the given encoding - and return an equivalent object (e.g. an Unicode object). - - errors is passed to the decoder factory as argument if non-NULL. */ - -PyObject *PyCodec_Decode(PyObject *object, - const char *encoding, - const char *errors) -{ - PyObject *decoder = NULL; - PyObject *args = NULL, *result = NULL; - PyObject *v; - - decoder = PyCodec_Decoder(encoding); - if (decoder == NULL) - goto onError; - - args = args_tuple(object, errors); - if (args == NULL) - goto onError; - - result = PyEval_CallObject(decoder,args); - if (result == NULL) - goto onError; - if (!PyTuple_Check(result) || - PyTuple_GET_SIZE(result) != 2) { - PyErr_SetString(PyExc_TypeError, - "decoder must return a tuple (object,integer)"); - goto onError; - } - v = PyTuple_GET_ITEM(result,0); - Py_INCREF(v); - /* We don't check or use the second (integer) entry. */ - - Py_DECREF(args); - Py_DECREF(decoder); - Py_DECREF(result); - return v; - - onError: - Py_XDECREF(args); - Py_XDECREF(decoder); - Py_XDECREF(result); - return NULL; -} - -/* Register the error handling callback function error under the name - name. This function will be called by the codec when it encounters - an unencodable characters/undecodable bytes and doesn't know the - callback name, when name is specified as the error parameter - in the call to the encode/decode function. - Return 0 on success, -1 on error */ -int PyCodec_RegisterError(const char *name, PyObject *error) -{ - PyInterpreterState *interp = PyThreadState_GET()->interp; - if (interp->codec_search_path == NULL && _PyCodecRegistry_Init()) - return -1; - if (!PyCallable_Check(error)) { - PyErr_SetString(PyExc_TypeError, "handler must be callable"); - return -1; - } - return PyDict_SetItemString(interp->codec_error_registry, - (char *)name, error); -} - -/* Lookup the error handling callback function registered under the - name error. As a special case NULL can be passed, in which case - the error handling callback for strict encoding will be returned. */ -PyObject *PyCodec_LookupError(const char *name) -{ - PyObject *handler = NULL; - - PyInterpreterState *interp = PyThreadState_GET()->interp; - if (interp->codec_search_path == NULL && _PyCodecRegistry_Init()) - return NULL; - - if (name==NULL) - name = "strict"; - handler = PyDict_GetItemString(interp->codec_error_registry, (char *)name); - if (!handler) - PyErr_Format(PyExc_LookupError, "unknown error handler name '%.400s'", name); - else - Py_INCREF(handler); - return handler; -} - -static void wrong_exception_type(PyObject *exc) -{ - PyObject *type = PyObject_GetAttrString(exc, "__class__"); - if (type != NULL) { - PyObject *name = PyObject_GetAttrString(type, "__name__"); - Py_DECREF(type); - if (name != NULL) { - PyObject *string = PyObject_Str(name); - Py_DECREF(name); - if (string != NULL) { - PyErr_Format(PyExc_TypeError, - "don't know how to handle %.400s in error callback", - PyString_AS_STRING(string)); - Py_DECREF(string); - } - } - } -} - -PyObject *PyCodec_StrictErrors(PyObject *exc) -{ - if (PyExceptionInstance_Check(exc)) - PyErr_SetObject(PyExceptionInstance_Class(exc), exc); - else - PyErr_SetString(PyExc_TypeError, "codec must pass exception instance"); - return NULL; -} - - -#ifdef Py_USING_UNICODE -PyObject *PyCodec_IgnoreErrors(PyObject *exc) -{ - Py_ssize_t end; - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { - if (PyUnicodeEncodeError_GetEnd(exc, &end)) - return NULL; - } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { - if (PyUnicodeDecodeError_GetEnd(exc, &end)) - return NULL; - } - else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { - if (PyUnicodeTranslateError_GetEnd(exc, &end)) - return NULL; - } - else { - wrong_exception_type(exc); - return NULL; - } - /* ouch: passing NULL, 0, pos gives None instead of u'' */ - return Py_BuildValue("(u#n)", &end, 0, end); -} - - -PyObject *PyCodec_ReplaceErrors(PyObject *exc) -{ - PyObject *restuple; - Py_ssize_t start; - Py_ssize_t end; - Py_ssize_t i; - - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { - PyObject *res; - Py_UNICODE *p; - if (PyUnicodeEncodeError_GetStart(exc, &start)) - return NULL; - if (PyUnicodeEncodeError_GetEnd(exc, &end)) - return NULL; - res = PyUnicode_FromUnicode(NULL, end-start); - if (res == NULL) - return NULL; - for (p = PyUnicode_AS_UNICODE(res), i = start; - i<end; ++p, ++i) - *p = '?'; - restuple = Py_BuildValue("(On)", res, end); - Py_DECREF(res); - return restuple; - } - else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { - Py_UNICODE res = Py_UNICODE_REPLACEMENT_CHARACTER; - if (PyUnicodeDecodeError_GetEnd(exc, &end)) - return NULL; - return Py_BuildValue("(u#n)", &res, 1, end); - } - else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { - PyObject *res; - Py_UNICODE *p; - if (PyUnicodeTranslateError_GetStart(exc, &start)) - return NULL; - if (PyUnicodeTranslateError_GetEnd(exc, &end)) - return NULL; - res = PyUnicode_FromUnicode(NULL, end-start); - if (res == NULL) - return NULL; - for (p = PyUnicode_AS_UNICODE(res), i = start; - i<end; ++p, ++i) - *p = Py_UNICODE_REPLACEMENT_CHARACTER; - restuple = Py_BuildValue("(On)", res, end); - Py_DECREF(res); - return restuple; - } - else { - wrong_exception_type(exc); - return NULL; - } -} - -PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc) -{ - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { - PyObject *restuple; - PyObject *object; - Py_ssize_t start; - Py_ssize_t end; - PyObject *res; - Py_UNICODE *p; - Py_UNICODE *startp; - Py_UNICODE *outp; - int ressize; - if (PyUnicodeEncodeError_GetStart(exc, &start)) - return NULL; - if (PyUnicodeEncodeError_GetEnd(exc, &end)) - return NULL; - if (!(object = PyUnicodeEncodeError_GetObject(exc))) - return NULL; - startp = PyUnicode_AS_UNICODE(object); - for (p = startp+start, ressize = 0; p < startp+end; ++p) { - if (*p<10) - ressize += 2+1+1; - else if (*p<100) - ressize += 2+2+1; - else if (*p<1000) - ressize += 2+3+1; - else if (*p<10000) - ressize += 2+4+1; -#ifndef Py_UNICODE_WIDE - else - ressize += 2+5+1; -#else - else if (*p<100000) - ressize += 2+5+1; - else if (*p<1000000) - ressize += 2+6+1; - else - ressize += 2+7+1; -#endif - } - /* allocate replacement */ - res = PyUnicode_FromUnicode(NULL, ressize); - if (res == NULL) { - Py_DECREF(object); - return NULL; - } - /* generate replacement */ - for (p = startp+start, outp = PyUnicode_AS_UNICODE(res); - p < startp+end; ++p) { - Py_UNICODE c = *p; - int digits; - int base; - *outp++ = '&'; - *outp++ = '#'; - if (*p<10) { - digits = 1; - base = 1; - } - else if (*p<100) { - digits = 2; - base = 10; - } - else if (*p<1000) { - digits = 3; - base = 100; - } - else if (*p<10000) { - digits = 4; - base = 1000; - } -#ifndef Py_UNICODE_WIDE - else { - digits = 5; - base = 10000; - } -#else - else if (*p<100000) { - digits = 5; - base = 10000; - } - else if (*p<1000000) { - digits = 6; - base = 100000; - } - else { - digits = 7; - base = 1000000; - } -#endif - while (digits-->0) { - *outp++ = '0' + c/base; - c %= base; - base /= 10; - } - *outp++ = ';'; - } - restuple = Py_BuildValue("(On)", res, end); - Py_DECREF(res); - Py_DECREF(object); - return restuple; - } - else { - wrong_exception_type(exc); - return NULL; - } -} - -static Py_UNICODE hexdigits[] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' -}; - -PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc) -{ - if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { - PyObject *restuple; - PyObject *object; - Py_ssize_t start; - Py_ssize_t end; - PyObject *res; - Py_UNICODE *p; - Py_UNICODE *startp; - Py_UNICODE *outp; - int ressize; - if (PyUnicodeEncodeError_GetStart(exc, &start)) - return NULL; - if (PyUnicodeEncodeError_GetEnd(exc, &end)) - return NULL; - if (!(object = PyUnicodeEncodeError_GetObject(exc))) - return NULL; - startp = PyUnicode_AS_UNICODE(object); - for (p = startp+start, ressize = 0; p < startp+end; ++p) { -#ifdef Py_UNICODE_WIDE - if (*p >= 0x00010000) - ressize += 1+1+8; - else -#endif - if (*p >= 0x100) { - ressize += 1+1+4; - } - else - ressize += 1+1+2; - } - res = PyUnicode_FromUnicode(NULL, ressize); - if (res==NULL) - return NULL; - for (p = startp+start, outp = PyUnicode_AS_UNICODE(res); - p < startp+end; ++p) { - Py_UNICODE c = *p; - *outp++ = '\\'; -#ifdef Py_UNICODE_WIDE - if (c >= 0x00010000) { - *outp++ = 'U'; - *outp++ = hexdigits[(c>>28)&0xf]; - *outp++ = hexdigits[(c>>24)&0xf]; - *outp++ = hexdigits[(c>>20)&0xf]; - *outp++ = hexdigits[(c>>16)&0xf]; - *outp++ = hexdigits[(c>>12)&0xf]; - *outp++ = hexdigits[(c>>8)&0xf]; - } - else -#endif - if (c >= 0x100) { - *outp++ = 'u'; - *outp++ = hexdigits[(c>>12)&0xf]; - *outp++ = hexdigits[(c>>8)&0xf]; - } - else - *outp++ = 'x'; - *outp++ = hexdigits[(c>>4)&0xf]; - *outp++ = hexdigits[c&0xf]; - } - - restuple = Py_BuildValue("(On)", res, end); - Py_DECREF(res); - Py_DECREF(object); - return restuple; - } - else { - wrong_exception_type(exc); - return NULL; - } -} -#endif - -static PyObject *strict_errors(PyObject *self, PyObject *exc) -{ - return PyCodec_StrictErrors(exc); -} - - -#ifdef Py_USING_UNICODE -static PyObject *ignore_errors(PyObject *self, PyObject *exc) -{ - return PyCodec_IgnoreErrors(exc); -} - - -static PyObject *replace_errors(PyObject *self, PyObject *exc) -{ - return PyCodec_ReplaceErrors(exc); -} - - -static PyObject *xmlcharrefreplace_errors(PyObject *self, PyObject *exc) -{ - return PyCodec_XMLCharRefReplaceErrors(exc); -} - - -static PyObject *backslashreplace_errors(PyObject *self, PyObject *exc) -{ - return PyCodec_BackslashReplaceErrors(exc); -} -#endif - -static int _PyCodecRegistry_Init(void) -{ - static struct { - char *name; - PyMethodDef def; - } methods[] = - { - { - "strict", - { - "strict_errors", - strict_errors, - METH_O - } - }, -#ifdef Py_USING_UNICODE - { - "ignore", - { - "ignore_errors", - ignore_errors, - METH_O - } - }, - { - "replace", - { - "replace_errors", - replace_errors, - METH_O - } - }, - { - "xmlcharrefreplace", - { - "xmlcharrefreplace_errors", - xmlcharrefreplace_errors, - METH_O - } - }, - { - "backslashreplace", - { - "backslashreplace_errors", - backslashreplace_errors, - METH_O - } - } -#endif - }; - - PyInterpreterState *interp = PyThreadState_GET()->interp; - PyObject *mod; - unsigned i; - - if (interp->codec_search_path != NULL) - return 0; - - interp->codec_search_path = PyList_New(0); - interp->codec_search_cache = PyDict_New(); - interp->codec_error_registry = PyDict_New(); - - if (interp->codec_error_registry) { - for (i = 0; i < sizeof(methods)/sizeof(methods[0]); ++i) { - PyObject *func = PyCFunction_New(&methods[i].def, NULL); - int res; - if (!func) - Py_FatalError("can't initialize codec error registry"); - res = PyCodec_RegisterError(methods[i].name, func); - Py_DECREF(func); - if (res) - Py_FatalError("can't initialize codec error registry"); - } - } - - if (interp->codec_search_path == NULL || - interp->codec_search_cache == NULL || - interp->codec_error_registry == NULL) - Py_FatalError("can't initialize codec registry"); - - mod = PyImport_ImportModuleLevel("encodings", NULL, NULL, NULL, 0); - if (mod == NULL) { - if (PyErr_ExceptionMatches(PyExc_ImportError)) { - /* Ignore ImportErrors... this is done so that - distributions can disable the encodings package. Note - that other errors are not masked, e.g. SystemErrors - raised to inform the user of an error in the Python - configuration are still reported back to the user. */ - PyErr_Clear(); - return 0; - } - return -1; - } - Py_DECREF(mod); - return 0; -} diff --git a/sys/src/cmd/python/Python/compile.c b/sys/src/cmd/python/Python/compile.c deleted file mode 100644 index e493beb6c..000000000 --- a/sys/src/cmd/python/Python/compile.c +++ /dev/null @@ -1,4570 +0,0 @@ -/* - * This file compiles an abstract syntax tree (AST) into Python bytecode. - * - * The primary entry point is PyAST_Compile(), which returns a - * PyCodeObject. The compiler makes several passes to build the code - * object: - * 1. Checks for future statements. See future.c - * 2. Builds a symbol table. See symtable.c. - * 3. Generate code for basic blocks. See compiler_mod() in this file. - * 4. Assemble the basic blocks into final code. See assemble() in - * this file. - * - * Note that compiler_mod() suggests module, but the module ast type - * (mod_ty) has cases for expressions and interactive statements. - * - * CAUTION: The VISIT_* macros abort the current function when they - * encounter a problem. So don't invoke them when there is memory - * which needs to be released. Code blocks are OK, as the compiler - * structure takes care of releasing those. - */ - -#include "Python.h" - -#include "Python-ast.h" -#include "node.h" -#include "pyarena.h" -#include "ast.h" -#include "code.h" -#include "compile.h" -#include "symtable.h" -#include "opcode.h" - -int Py_OptimizeFlag = 0; - -/* - ISSUES: - - opcode_stack_effect() function should be reviewed since stack depth bugs - could be really hard to find later. - - Dead code is being generated (i.e. after unconditional jumps). - XXX(nnorwitz): not sure this is still true -*/ - -#define DEFAULT_BLOCK_SIZE 16 -#define DEFAULT_BLOCKS 8 -#define DEFAULT_CODE_SIZE 128 -#define DEFAULT_LNOTAB_SIZE 16 - -struct instr { - unsigned i_jabs : 1; - unsigned i_jrel : 1; - unsigned i_hasarg : 1; - unsigned char i_opcode; - int i_oparg; - struct basicblock_ *i_target; /* target block (if jump instruction) */ - int i_lineno; -}; - -typedef struct basicblock_ { - /* Each basicblock in a compilation unit is linked via b_list in the - reverse order that the block are allocated. b_list points to the next - block, not to be confused with b_next, which is next by control flow. */ - struct basicblock_ *b_list; - /* number of instructions used */ - int b_iused; - /* length of instruction array (b_instr) */ - int b_ialloc; - /* pointer to an array of instructions, initially NULL */ - struct instr *b_instr; - /* If b_next is non-NULL, it is a pointer to the next - block reached by normal control flow. */ - struct basicblock_ *b_next; - /* b_seen is used to perform a DFS of basicblocks. */ - unsigned b_seen : 1; - /* b_return is true if a RETURN_VALUE opcode is inserted. */ - unsigned b_return : 1; - /* depth of stack upon entry of block, computed by stackdepth() */ - int b_startdepth; - /* instruction offset for block, computed by assemble_jump_offsets() */ - int b_offset; -} basicblock; - -/* fblockinfo tracks the current frame block. - -A frame block is used to handle loops, try/except, and try/finally. -It's called a frame block to distinguish it from a basic block in the -compiler IR. -*/ - -enum fblocktype { LOOP, EXCEPT, FINALLY_TRY, FINALLY_END }; - -struct fblockinfo { - enum fblocktype fb_type; - basicblock *fb_block; -}; - -/* The following items change on entry and exit of code blocks. - They must be saved and restored when returning to a block. -*/ -struct compiler_unit { - PySTEntryObject *u_ste; - - PyObject *u_name; - /* The following fields are dicts that map objects to - the index of them in co_XXX. The index is used as - the argument for opcodes that refer to those collections. - */ - PyObject *u_consts; /* all constants */ - PyObject *u_names; /* all names */ - PyObject *u_varnames; /* local variables */ - PyObject *u_cellvars; /* cell variables */ - PyObject *u_freevars; /* free variables */ - - PyObject *u_private; /* for private name mangling */ - - int u_argcount; /* number of arguments for block */ - /* Pointer to the most recently allocated block. By following b_list - members, you can reach all early allocated blocks. */ - basicblock *u_blocks; - basicblock *u_curblock; /* pointer to current block */ - int u_tmpname; /* temporary variables for list comps */ - - int u_nfblocks; - struct fblockinfo u_fblock[CO_MAXBLOCKS]; - - int u_firstlineno; /* the first lineno of the block */ - int u_lineno; /* the lineno for the current stmt */ - bool u_lineno_set; /* boolean to indicate whether instr - has been generated with current lineno */ -}; - -/* This struct captures the global state of a compilation. - -The u pointer points to the current compilation unit, while units -for enclosing blocks are stored in c_stack. The u and c_stack are -managed by compiler_enter_scope() and compiler_exit_scope(). -*/ - -struct compiler { - const char *c_filename; - struct symtable *c_st; - PyFutureFeatures *c_future; /* pointer to module's __future__ */ - PyCompilerFlags *c_flags; - - int c_interactive; /* true if in interactive mode */ - int c_nestlevel; - - struct compiler_unit *u; /* compiler state for current block */ - PyObject *c_stack; /* Python list holding compiler_unit ptrs */ - char *c_encoding; /* source encoding (a borrowed reference) */ - PyArena *c_arena; /* pointer to memory allocation arena */ -}; - -struct assembler { - PyObject *a_bytecode; /* string containing bytecode */ - int a_offset; /* offset into bytecode */ - int a_nblocks; /* number of reachable blocks */ - basicblock **a_postorder; /* list of blocks in dfs postorder */ - PyObject *a_lnotab; /* string containing lnotab */ - int a_lnotab_off; /* offset into lnotab */ - int a_lineno; /* last lineno of emitted instruction */ - int a_lineno_off; /* bytecode offset of last lineno */ -}; - -static int compiler_enter_scope(struct compiler *, identifier, void *, int); -static void compiler_free(struct compiler *); -static basicblock *compiler_new_block(struct compiler *); -static int compiler_next_instr(struct compiler *, basicblock *); -static int compiler_addop(struct compiler *, int); -static int compiler_addop_o(struct compiler *, int, PyObject *, PyObject *); -static int compiler_addop_i(struct compiler *, int, int); -static int compiler_addop_j(struct compiler *, int, basicblock *, int); -static basicblock *compiler_use_new_block(struct compiler *); -static int compiler_error(struct compiler *, const char *); -static int compiler_nameop(struct compiler *, identifier, expr_context_ty); - -static PyCodeObject *compiler_mod(struct compiler *, mod_ty); -static int compiler_visit_stmt(struct compiler *, stmt_ty); -static int compiler_visit_keyword(struct compiler *, keyword_ty); -static int compiler_visit_expr(struct compiler *, expr_ty); -static int compiler_augassign(struct compiler *, stmt_ty); -static int compiler_visit_slice(struct compiler *, slice_ty, - expr_context_ty); - -static int compiler_push_fblock(struct compiler *, enum fblocktype, - basicblock *); -static void compiler_pop_fblock(struct compiler *, enum fblocktype, - basicblock *); -/* Returns true if there is a loop on the fblock stack. */ -static int compiler_in_loop(struct compiler *); - -static int inplace_binop(struct compiler *, operator_ty); -static int expr_constant(expr_ty e); - -static int compiler_with(struct compiler *, stmt_ty); - -static PyCodeObject *assemble(struct compiler *, int addNone); -static PyObject *__doc__; - -PyObject * -_Py_Mangle(PyObject *privateobj, PyObject *ident) -{ - /* Name mangling: __private becomes _classname__private. - This is independent from how the name is used. */ - const char *p, *name = PyString_AsString(ident); - char *buffer; - size_t nlen, plen; - if (privateobj == NULL || !PyString_Check(privateobj) || - name == NULL || name[0] != '_' || name[1] != '_') { - Py_INCREF(ident); - return ident; - } - p = PyString_AsString(privateobj); - nlen = strlen(name); - if (name[nlen-1] == '_' && name[nlen-2] == '_') { - Py_INCREF(ident); - return ident; /* Don't mangle __whatever__ */ - } - /* Strip leading underscores from class name */ - while (*p == '_') - p++; - if (*p == '\0') { - Py_INCREF(ident); - return ident; /* Don't mangle if class is just underscores */ - } - plen = strlen(p); - ident = PyString_FromStringAndSize(NULL, 1 + nlen + plen); - if (!ident) - return 0; - /* ident = "_" + p[:plen] + name # i.e. 1+plen+nlen bytes */ - buffer = PyString_AS_STRING(ident); - buffer[0] = '_'; - strncpy(buffer+1, p, plen); - strcpy(buffer+1+plen, name); - return ident; -} - -static int -compiler_init(struct compiler *c) -{ - memset(c, 0, sizeof(struct compiler)); - - c->c_stack = PyList_New(0); - if (!c->c_stack) - return 0; - - return 1; -} - -PyCodeObject * -PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags, - PyArena *arena) -{ - struct compiler c; - PyCodeObject *co = NULL; - PyCompilerFlags local_flags; - int merged; - - if (!__doc__) { - __doc__ = PyString_InternFromString("__doc__"); - if (!__doc__) - return NULL; - } - - if (!compiler_init(&c)) - return NULL; - c.c_filename = filename; - c.c_arena = arena; - c.c_future = PyFuture_FromAST(mod, filename); - if (c.c_future == NULL) - goto finally; - if (!flags) { - local_flags.cf_flags = 0; - flags = &local_flags; - } - merged = c.c_future->ff_features | flags->cf_flags; - c.c_future->ff_features = merged; - flags->cf_flags = merged; - c.c_flags = flags; - c.c_nestlevel = 0; - - c.c_st = PySymtable_Build(mod, filename, c.c_future); - if (c.c_st == NULL) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_SystemError, "no symtable"); - goto finally; - } - - /* XXX initialize to NULL for now, need to handle */ - c.c_encoding = NULL; - - co = compiler_mod(&c, mod); - - finally: - compiler_free(&c); - assert(co || PyErr_Occurred()); - return co; -} - -PyCodeObject * -PyNode_Compile(struct _node *n, const char *filename) -{ - PyCodeObject *co = NULL; - mod_ty mod; - PyArena *arena = PyArena_New(); - if (!arena) - return NULL; - mod = PyAST_FromNode(n, NULL, filename, arena); - if (mod) - co = PyAST_Compile(mod, filename, NULL, arena); - PyArena_Free(arena); - return co; -} - -static void -compiler_free(struct compiler *c) -{ - if (c->c_st) - PySymtable_Free(c->c_st); - if (c->c_future) - PyObject_Free(c->c_future); - Py_DECREF(c->c_stack); -} - -static PyObject * -list2dict(PyObject *list) -{ - Py_ssize_t i, n; - PyObject *v, *k; - PyObject *dict = PyDict_New(); - if (!dict) return NULL; - - n = PyList_Size(list); - for (i = 0; i < n; i++) { - v = PyInt_FromLong(i); - if (!v) { - Py_DECREF(dict); - return NULL; - } - k = PyList_GET_ITEM(list, i); - k = PyTuple_Pack(2, k, k->ob_type); - if (k == NULL || PyDict_SetItem(dict, k, v) < 0) { - Py_XDECREF(k); - Py_DECREF(v); - Py_DECREF(dict); - return NULL; - } - Py_DECREF(k); - Py_DECREF(v); - } - return dict; -} - -/* Return new dict containing names from src that match scope(s). - -src is a symbol table dictionary. If the scope of a name matches -either scope_type or flag is set, insert it into the new dict. The -values are integers, starting at offset and increasing by one for -each key. -*/ - -static PyObject * -dictbytype(PyObject *src, int scope_type, int flag, int offset) -{ - Py_ssize_t pos = 0, i = offset, scope; - PyObject *k, *v, *dest = PyDict_New(); - - assert(offset >= 0); - if (dest == NULL) - return NULL; - - while (PyDict_Next(src, &pos, &k, &v)) { - /* XXX this should probably be a macro in symtable.h */ - assert(PyInt_Check(v)); - scope = (PyInt_AS_LONG(v) >> SCOPE_OFF) & SCOPE_MASK; - - if (scope == scope_type || PyInt_AS_LONG(v) & flag) { - PyObject *tuple, *item = PyInt_FromLong(i); - if (item == NULL) { - Py_DECREF(dest); - return NULL; - } - i++; - tuple = PyTuple_Pack(2, k, k->ob_type); - if (!tuple || PyDict_SetItem(dest, tuple, item) < 0) { - Py_DECREF(item); - Py_DECREF(dest); - Py_XDECREF(tuple); - return NULL; - } - Py_DECREF(item); - Py_DECREF(tuple); - } - } - return dest; -} - -/* Begin: Peephole optimizations ----------------------------------------- */ - -#define GETARG(arr, i) ((int)((arr[i+2]<<8) + arr[i+1])) -#define UNCONDITIONAL_JUMP(op) (op==JUMP_ABSOLUTE || op==JUMP_FORWARD) -#define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE || op==CONTINUE_LOOP) -#define GETJUMPTGT(arr, i) (GETARG(arr,i) + (ABSOLUTE_JUMP(arr[i]) ? 0 : i+3)) -#define SETARG(arr, i, val) arr[i+2] = val>>8; arr[i+1] = val & 255 -#define CODESIZE(op) (HAS_ARG(op) ? 3 : 1) -#define ISBASICBLOCK(blocks, start, bytes) \ - (blocks[start]==blocks[start+bytes-1]) - -/* Replace LOAD_CONST c1. LOAD_CONST c2 ... LOAD_CONST cn BUILD_TUPLE n - with LOAD_CONST (c1, c2, ... cn). - The consts table must still be in list form so that the - new constant (c1, c2, ... cn) can be appended. - Called with codestr pointing to the first LOAD_CONST. - Bails out with no change if one or more of the LOAD_CONSTs is missing. - Also works for BUILD_LIST when followed by an "in" or "not in" test. -*/ -static int -tuple_of_constants(unsigned char *codestr, int n, PyObject *consts) -{ - PyObject *newconst, *constant; - Py_ssize_t i, arg, len_consts; - - /* Pre-conditions */ - assert(PyList_CheckExact(consts)); - assert(codestr[n*3] == BUILD_TUPLE || codestr[n*3] == BUILD_LIST); - assert(GETARG(codestr, (n*3)) == n); - for (i=0 ; i<n ; i++) - assert(codestr[i*3] == LOAD_CONST); - - /* Buildup new tuple of constants */ - newconst = PyTuple_New(n); - if (newconst == NULL) - return 0; - len_consts = PyList_GET_SIZE(consts); - for (i=0 ; i<n ; i++) { - arg = GETARG(codestr, (i*3)); - assert(arg < len_consts); - constant = PyList_GET_ITEM(consts, arg); - Py_INCREF(constant); - PyTuple_SET_ITEM(newconst, i, constant); - } - - /* Append folded constant onto consts */ - if (PyList_Append(consts, newconst)) { - Py_DECREF(newconst); - return 0; - } - Py_DECREF(newconst); - - /* Write NOPs over old LOAD_CONSTS and - add a new LOAD_CONST newconst on top of the BUILD_TUPLE n */ - memset(codestr, NOP, n*3); - codestr[n*3] = LOAD_CONST; - SETARG(codestr, (n*3), len_consts); - return 1; -} - -/* Replace LOAD_CONST c1. LOAD_CONST c2 BINOP - with LOAD_CONST binop(c1,c2) - The consts table must still be in list form so that the - new constant can be appended. - Called with codestr pointing to the first LOAD_CONST. - Abandons the transformation if the folding fails (i.e. 1+'a'). - If the new constant is a sequence, only folds when the size - is below a threshold value. That keeps pyc files from - becoming large in the presence of code like: (None,)*1000. -*/ -static int -fold_binops_on_constants(unsigned char *codestr, PyObject *consts) -{ - PyObject *newconst, *v, *w; - Py_ssize_t len_consts, size; - int opcode; - - /* Pre-conditions */ - assert(PyList_CheckExact(consts)); - assert(codestr[0] == LOAD_CONST); - assert(codestr[3] == LOAD_CONST); - - /* Create new constant */ - v = PyList_GET_ITEM(consts, GETARG(codestr, 0)); - w = PyList_GET_ITEM(consts, GETARG(codestr, 3)); - opcode = codestr[6]; - switch (opcode) { - case BINARY_POWER: - newconst = PyNumber_Power(v, w, Py_None); - break; - case BINARY_MULTIPLY: - newconst = PyNumber_Multiply(v, w); - break; - case BINARY_DIVIDE: - /* Cannot fold this operation statically since - the result can depend on the run-time presence - of the -Qnew flag */ - return 0; - case BINARY_TRUE_DIVIDE: - newconst = PyNumber_TrueDivide(v, w); - break; - case BINARY_FLOOR_DIVIDE: - newconst = PyNumber_FloorDivide(v, w); - break; - case BINARY_MODULO: - newconst = PyNumber_Remainder(v, w); - break; - case BINARY_ADD: - newconst = PyNumber_Add(v, w); - break; - case BINARY_SUBTRACT: - newconst = PyNumber_Subtract(v, w); - break; - case BINARY_SUBSCR: - newconst = PyObject_GetItem(v, w); - break; - case BINARY_LSHIFT: - newconst = PyNumber_Lshift(v, w); - break; - case BINARY_RSHIFT: - newconst = PyNumber_Rshift(v, w); - break; - case BINARY_AND: - newconst = PyNumber_And(v, w); - break; - case BINARY_XOR: - newconst = PyNumber_Xor(v, w); - break; - case BINARY_OR: - newconst = PyNumber_Or(v, w); - break; - default: - /* Called with an unknown opcode */ - PyErr_Format(PyExc_SystemError, - "unexpected binary operation %d on a constant", - opcode); - return 0; - } - if (newconst == NULL) { - PyErr_Clear(); - return 0; - } - size = PyObject_Size(newconst); - if (size == -1) - PyErr_Clear(); - else if (size > 20) { - Py_DECREF(newconst); - return 0; - } - - /* Append folded constant into consts table */ - len_consts = PyList_GET_SIZE(consts); - if (PyList_Append(consts, newconst)) { - Py_DECREF(newconst); - return 0; - } - Py_DECREF(newconst); - - /* Write NOP NOP NOP NOP LOAD_CONST newconst */ - memset(codestr, NOP, 4); - codestr[4] = LOAD_CONST; - SETARG(codestr, 4, len_consts); - return 1; -} - -static int -fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts) -{ - PyObject *newconst=NULL, *v; - Py_ssize_t len_consts; - int opcode; - - /* Pre-conditions */ - assert(PyList_CheckExact(consts)); - assert(codestr[0] == LOAD_CONST); - - /* Create new constant */ - v = PyList_GET_ITEM(consts, GETARG(codestr, 0)); - opcode = codestr[3]; - switch (opcode) { - case UNARY_NEGATIVE: - /* Preserve the sign of -0.0 */ - if (PyObject_IsTrue(v) == 1) - newconst = PyNumber_Negative(v); - break; - case UNARY_CONVERT: - newconst = PyObject_Repr(v); - break; - case UNARY_INVERT: - newconst = PyNumber_Invert(v); - break; - default: - /* Called with an unknown opcode */ - PyErr_Format(PyExc_SystemError, - "unexpected unary operation %d on a constant", - opcode); - return 0; - } - if (newconst == NULL) { - PyErr_Clear(); - return 0; - } - - /* Append folded constant into consts table */ - len_consts = PyList_GET_SIZE(consts); - if (PyList_Append(consts, newconst)) { - Py_DECREF(newconst); - return 0; - } - Py_DECREF(newconst); - - /* Write NOP LOAD_CONST newconst */ - codestr[0] = NOP; - codestr[1] = LOAD_CONST; - SETARG(codestr, 1, len_consts); - return 1; -} - -static unsigned int * -markblocks(unsigned char *code, int len) -{ - unsigned int *blocks = (unsigned int *)PyMem_Malloc(len*sizeof(int)); - int i,j, opcode, blockcnt = 0; - - if (blocks == NULL) { - PyErr_NoMemory(); - return NULL; - } - memset(blocks, 0, len*sizeof(int)); - - /* Mark labels in the first pass */ - for (i=0 ; i<len ; i+=CODESIZE(opcode)) { - opcode = code[i]; - switch (opcode) { - case FOR_ITER: - case JUMP_FORWARD: - case JUMP_IF_FALSE: - case JUMP_IF_TRUE: - case JUMP_ABSOLUTE: - case CONTINUE_LOOP: - case SETUP_LOOP: - case SETUP_EXCEPT: - case SETUP_FINALLY: - j = GETJUMPTGT(code, i); - blocks[j] = 1; - break; - } - } - /* Build block numbers in the second pass */ - for (i=0 ; i<len ; i++) { - blockcnt += blocks[i]; /* increment blockcnt over labels */ - blocks[i] = blockcnt; - } - return blocks; -} - -/* Perform basic peephole optimizations to components of a code object. - The consts object should still be in list form to allow new constants - to be appended. - - To keep the optimizer simple, it bails out (does nothing) for code - containing extended arguments or that has a length over 32,700. That - allows us to avoid overflow and sign issues. Likewise, it bails when - the lineno table has complex encoding for gaps >= 255. - - Optimizations are restricted to simple transformations occuring within a - single basic block. All transformations keep the code size the same or - smaller. For those that reduce size, the gaps are initially filled with - NOPs. Later those NOPs are removed and the jump addresses retargeted in - a single pass. Line numbering is adjusted accordingly. */ - -static PyObject * -optimize_code(PyObject *code, PyObject* consts, PyObject *names, - PyObject *lineno_obj) -{ - Py_ssize_t i, j, codelen; - int nops, h, adj; - int tgt, tgttgt, opcode; - unsigned char *codestr = NULL; - unsigned char *lineno; - int *addrmap = NULL; - int new_line, cum_orig_line, last_line, tabsiz; - int cumlc=0, lastlc=0; /* Count runs of consecutive LOAD_CONSTs */ - unsigned int *blocks = NULL; - char *name; - - /* Bail out if an exception is set */ - if (PyErr_Occurred()) - goto exitUnchanged; - - /* Bypass optimization when the lineno table is too complex */ - assert(PyString_Check(lineno_obj)); - lineno = (unsigned char*)PyString_AS_STRING(lineno_obj); - tabsiz = PyString_GET_SIZE(lineno_obj); - if (memchr(lineno, 255, tabsiz) != NULL) - goto exitUnchanged; - - /* Avoid situations where jump retargeting could overflow */ - assert(PyString_Check(code)); - codelen = PyString_Size(code); - if (codelen > 32700) - goto exitUnchanged; - - /* Make a modifiable copy of the code string */ - codestr = (unsigned char *)PyMem_Malloc(codelen); - if (codestr == NULL) - goto exitUnchanged; - codestr = (unsigned char *)memcpy(codestr, - PyString_AS_STRING(code), codelen); - - /* Verify that RETURN_VALUE terminates the codestring. This allows - the various transformation patterns to look ahead several - instructions without additional checks to make sure they are not - looking beyond the end of the code string. - */ - if (codestr[codelen-1] != RETURN_VALUE) - goto exitUnchanged; - - /* Mapping to new jump targets after NOPs are removed */ - addrmap = (int *)PyMem_Malloc(codelen * sizeof(int)); - if (addrmap == NULL) - goto exitUnchanged; - - blocks = markblocks(codestr, codelen); - if (blocks == NULL) - goto exitUnchanged; - assert(PyList_Check(consts)); - - for (i=0 ; i<codelen ; i += CODESIZE(codestr[i])) { - opcode = codestr[i]; - - lastlc = cumlc; - cumlc = 0; - - switch (opcode) { - - /* Replace UNARY_NOT JUMP_IF_FALSE POP_TOP with - with JUMP_IF_TRUE POP_TOP */ - case UNARY_NOT: - if (codestr[i+1] != JUMP_IF_FALSE || - codestr[i+4] != POP_TOP || - !ISBASICBLOCK(blocks,i,5)) - continue; - tgt = GETJUMPTGT(codestr, (i+1)); - if (codestr[tgt] != POP_TOP) - continue; - j = GETARG(codestr, i+1) + 1; - codestr[i] = JUMP_IF_TRUE; - SETARG(codestr, i, j); - codestr[i+3] = POP_TOP; - codestr[i+4] = NOP; - break; - - /* not a is b --> a is not b - not a in b --> a not in b - not a is not b --> a is b - not a not in b --> a in b - */ - case COMPARE_OP: - j = GETARG(codestr, i); - if (j < 6 || j > 9 || - codestr[i+3] != UNARY_NOT || - !ISBASICBLOCK(blocks,i,4)) - continue; - SETARG(codestr, i, (j^1)); - codestr[i+3] = NOP; - break; - - /* Replace LOAD_GLOBAL/LOAD_NAME None - with LOAD_CONST None */ - case LOAD_NAME: - case LOAD_GLOBAL: - j = GETARG(codestr, i); - name = PyString_AsString(PyTuple_GET_ITEM(names, j)); - if (name == NULL || strcmp(name, "None") != 0) - continue; - for (j=0 ; j < PyList_GET_SIZE(consts) ; j++) { - if (PyList_GET_ITEM(consts, j) == Py_None) - break; - } - if (j == PyList_GET_SIZE(consts)) { - if (PyList_Append(consts, Py_None) == -1) - goto exitUnchanged; - } - assert(PyList_GET_ITEM(consts, j) == Py_None); - codestr[i] = LOAD_CONST; - SETARG(codestr, i, j); - cumlc = lastlc + 1; - break; - - /* Skip over LOAD_CONST trueconst - JUMP_IF_FALSE xx POP_TOP */ - case LOAD_CONST: - cumlc = lastlc + 1; - j = GETARG(codestr, i); - if (codestr[i+3] != JUMP_IF_FALSE || - codestr[i+6] != POP_TOP || - !ISBASICBLOCK(blocks,i,7) || - !PyObject_IsTrue(PyList_GET_ITEM(consts, j))) - continue; - memset(codestr+i, NOP, 7); - cumlc = 0; - break; - - /* Try to fold tuples of constants (includes a case for lists - which are only used for "in" and "not in" tests). - Skip over BUILD_SEQN 1 UNPACK_SEQN 1. - Replace BUILD_SEQN 2 UNPACK_SEQN 2 with ROT2. - Replace BUILD_SEQN 3 UNPACK_SEQN 3 with ROT3 ROT2. */ - case BUILD_TUPLE: - case BUILD_LIST: - j = GETARG(codestr, i); - h = i - 3 * j; - if (h >= 0 && - j <= lastlc && - ((opcode == BUILD_TUPLE && - ISBASICBLOCK(blocks, h, 3*(j+1))) || - (opcode == BUILD_LIST && - codestr[i+3]==COMPARE_OP && - ISBASICBLOCK(blocks, h, 3*(j+2)) && - (GETARG(codestr,i+3)==6 || - GETARG(codestr,i+3)==7))) && - tuple_of_constants(&codestr[h], j, consts)) { - assert(codestr[i] == LOAD_CONST); - cumlc = 1; - break; - } - if (codestr[i+3] != UNPACK_SEQUENCE || - !ISBASICBLOCK(blocks,i,6) || - j != GETARG(codestr, i+3)) - continue; - if (j == 1) { - memset(codestr+i, NOP, 6); - } else if (j == 2) { - codestr[i] = ROT_TWO; - memset(codestr+i+1, NOP, 5); - } else if (j == 3) { - codestr[i] = ROT_THREE; - codestr[i+1] = ROT_TWO; - memset(codestr+i+2, NOP, 4); - } - break; - - /* Fold binary ops on constants. - LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */ - case BINARY_POWER: - case BINARY_MULTIPLY: - case BINARY_TRUE_DIVIDE: - case BINARY_FLOOR_DIVIDE: - case BINARY_MODULO: - case BINARY_ADD: - case BINARY_SUBTRACT: - case BINARY_SUBSCR: - case BINARY_LSHIFT: - case BINARY_RSHIFT: - case BINARY_AND: - case BINARY_XOR: - case BINARY_OR: - if (lastlc >= 2 && - ISBASICBLOCK(blocks, i-6, 7) && - fold_binops_on_constants(&codestr[i-6], consts)) { - i -= 2; - assert(codestr[i] == LOAD_CONST); - cumlc = 1; - } - break; - - /* Fold unary ops on constants. - LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */ - case UNARY_NEGATIVE: - case UNARY_CONVERT: - case UNARY_INVERT: - if (lastlc >= 1 && - ISBASICBLOCK(blocks, i-3, 4) && - fold_unaryops_on_constants(&codestr[i-3], consts)) { - i -= 2; - assert(codestr[i] == LOAD_CONST); - cumlc = 1; - } - break; - - /* Simplify conditional jump to conditional jump where the - result of the first test implies the success of a similar - test or the failure of the opposite test. - Arises in code like: - "if a and b:" - "if a or b:" - "a and b or c" - "(a and b) and c" - x:JUMP_IF_FALSE y y:JUMP_IF_FALSE z --> x:JUMP_IF_FALSE z - x:JUMP_IF_FALSE y y:JUMP_IF_TRUE z --> x:JUMP_IF_FALSE y+3 - where y+3 is the instruction following the second test. - */ - case JUMP_IF_FALSE: - case JUMP_IF_TRUE: - tgt = GETJUMPTGT(codestr, i); - j = codestr[tgt]; - if (j == JUMP_IF_FALSE || j == JUMP_IF_TRUE) { - if (j == opcode) { - tgttgt = GETJUMPTGT(codestr, tgt) - i - 3; - SETARG(codestr, i, tgttgt); - } else { - tgt -= i; - SETARG(codestr, i, tgt); - } - break; - } - /* Intentional fallthrough */ - - /* Replace jumps to unconditional jumps */ - case FOR_ITER: - case JUMP_FORWARD: - case JUMP_ABSOLUTE: - case CONTINUE_LOOP: - case SETUP_LOOP: - case SETUP_EXCEPT: - case SETUP_FINALLY: - tgt = GETJUMPTGT(codestr, i); - if (!UNCONDITIONAL_JUMP(codestr[tgt])) - continue; - tgttgt = GETJUMPTGT(codestr, tgt); - if (opcode == JUMP_FORWARD) /* JMP_ABS can go backwards */ - opcode = JUMP_ABSOLUTE; - if (!ABSOLUTE_JUMP(opcode)) - tgttgt -= i + 3; /* Calc relative jump addr */ - if (tgttgt < 0) /* No backward relative jumps */ - continue; - codestr[i] = opcode; - SETARG(codestr, i, tgttgt); - break; - - case EXTENDED_ARG: - goto exitUnchanged; - - /* Replace RETURN LOAD_CONST None RETURN with just RETURN */ - case RETURN_VALUE: - if (i+4 >= codelen || - codestr[i+4] != RETURN_VALUE || - !ISBASICBLOCK(blocks,i,5)) - continue; - memset(codestr+i+1, NOP, 4); - break; - } - } - - /* Fixup linenotab */ - for (i=0, nops=0 ; i<codelen ; i += CODESIZE(codestr[i])) { - addrmap[i] = i - nops; - if (codestr[i] == NOP) - nops++; - } - cum_orig_line = 0; - last_line = 0; - for (i=0 ; i < tabsiz ; i+=2) { - cum_orig_line += lineno[i]; - new_line = addrmap[cum_orig_line]; - assert (new_line - last_line < 255); - lineno[i] =((unsigned char)(new_line - last_line)); - last_line = new_line; - } - - /* Remove NOPs and fixup jump targets */ - for (i=0, h=0 ; i<codelen ; ) { - opcode = codestr[i]; - switch (opcode) { - case NOP: - i++; - continue; - - case JUMP_ABSOLUTE: - case CONTINUE_LOOP: - j = addrmap[GETARG(codestr, i)]; - SETARG(codestr, i, j); - break; - - case FOR_ITER: - case JUMP_FORWARD: - case JUMP_IF_FALSE: - case JUMP_IF_TRUE: - case SETUP_LOOP: - case SETUP_EXCEPT: - case SETUP_FINALLY: - j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3; - SETARG(codestr, i, j); - break; - } - adj = CODESIZE(opcode); - while (adj--) - codestr[h++] = codestr[i++]; - } - assert(h + nops == codelen); - - code = PyString_FromStringAndSize((char *)codestr, h); - PyMem_Free(addrmap); - PyMem_Free(codestr); - PyMem_Free(blocks); - return code; - - exitUnchanged: - if (blocks != NULL) - PyMem_Free(blocks); - if (addrmap != NULL) - PyMem_Free(addrmap); - if (codestr != NULL) - PyMem_Free(codestr); - Py_INCREF(code); - return code; -} - -/* End: Peephole optimizations ----------------------------------------- */ - -/* - -Leave this debugging code for just a little longer. - -static void -compiler_display_symbols(PyObject *name, PyObject *symbols) -{ -PyObject *key, *value; -int flags; -Py_ssize_t pos = 0; - -fprintf(stderr, "block %s\n", PyString_AS_STRING(name)); -while (PyDict_Next(symbols, &pos, &key, &value)) { -flags = PyInt_AsLong(value); -fprintf(stderr, "var %s:", PyString_AS_STRING(key)); -if (flags & DEF_GLOBAL) -fprintf(stderr, " declared_global"); -if (flags & DEF_LOCAL) -fprintf(stderr, " local"); -if (flags & DEF_PARAM) -fprintf(stderr, " param"); -if (flags & DEF_STAR) -fprintf(stderr, " stararg"); -if (flags & DEF_DOUBLESTAR) -fprintf(stderr, " starstar"); -if (flags & DEF_INTUPLE) -fprintf(stderr, " tuple"); -if (flags & DEF_FREE) -fprintf(stderr, " free"); -if (flags & DEF_FREE_GLOBAL) -fprintf(stderr, " global"); -if (flags & DEF_FREE_CLASS) -fprintf(stderr, " free/class"); -if (flags & DEF_IMPORT) -fprintf(stderr, " import"); -fprintf(stderr, "\n"); -} - fprintf(stderr, "\n"); -} -*/ - -static void -compiler_unit_check(struct compiler_unit *u) -{ - basicblock *block; - for (block = u->u_blocks; block != NULL; block = block->b_list) { - assert(block != (void *)0xcbcbcbcb); - assert(block != (void *)0xfbfbfbfb); - assert(block != (void *)0xdbdbdbdb); - if (block->b_instr != NULL) { - assert(block->b_ialloc > 0); - assert(block->b_iused > 0); - assert(block->b_ialloc >= block->b_iused); - } - else { - assert (block->b_iused == 0); - assert (block->b_ialloc == 0); - } - } -} - -static void -compiler_unit_free(struct compiler_unit *u) -{ - basicblock *b, *next; - - compiler_unit_check(u); - b = u->u_blocks; - while (b != NULL) { - if (b->b_instr) - PyObject_Free((void *)b->b_instr); - next = b->b_list; - PyObject_Free((void *)b); - b = next; - } - Py_CLEAR(u->u_ste); - Py_CLEAR(u->u_name); - Py_CLEAR(u->u_consts); - Py_CLEAR(u->u_names); - Py_CLEAR(u->u_varnames); - Py_CLEAR(u->u_freevars); - Py_CLEAR(u->u_cellvars); - Py_CLEAR(u->u_private); - PyObject_Free(u); -} - -static int -compiler_enter_scope(struct compiler *c, identifier name, void *key, - int lineno) -{ - struct compiler_unit *u; - - u = (struct compiler_unit *)PyObject_Malloc(sizeof( - struct compiler_unit)); - if (!u) { - PyErr_NoMemory(); - return 0; - } - memset(u, 0, sizeof(struct compiler_unit)); - u->u_argcount = 0; - u->u_ste = PySymtable_Lookup(c->c_st, key); - if (!u->u_ste) { - compiler_unit_free(u); - return 0; - } - Py_INCREF(name); - u->u_name = name; - u->u_varnames = list2dict(u->u_ste->ste_varnames); - u->u_cellvars = dictbytype(u->u_ste->ste_symbols, CELL, 0, 0); - if (!u->u_varnames || !u->u_cellvars) { - compiler_unit_free(u); - return 0; - } - - u->u_freevars = dictbytype(u->u_ste->ste_symbols, FREE, DEF_FREE_CLASS, - PyDict_Size(u->u_cellvars)); - if (!u->u_freevars) { - compiler_unit_free(u); - return 0; - } - - u->u_blocks = NULL; - u->u_tmpname = 0; - u->u_nfblocks = 0; - u->u_firstlineno = lineno; - u->u_lineno = 0; - u->u_lineno_set = false; - u->u_consts = PyDict_New(); - if (!u->u_consts) { - compiler_unit_free(u); - return 0; - } - u->u_names = PyDict_New(); - if (!u->u_names) { - compiler_unit_free(u); - return 0; - } - - u->u_private = NULL; - - /* Push the old compiler_unit on the stack. */ - if (c->u) { - PyObject *wrapper = PyCObject_FromVoidPtr(c->u, NULL); - if (!wrapper || PyList_Append(c->c_stack, wrapper) < 0) { - Py_XDECREF(wrapper); - compiler_unit_free(u); - return 0; - } - Py_DECREF(wrapper); - u->u_private = c->u->u_private; - Py_XINCREF(u->u_private); - } - c->u = u; - - c->c_nestlevel++; - if (compiler_use_new_block(c) == NULL) - return 0; - - return 1; -} - -static void -compiler_exit_scope(struct compiler *c) -{ - int n; - PyObject *wrapper; - - c->c_nestlevel--; - compiler_unit_free(c->u); - /* Restore c->u to the parent unit. */ - n = PyList_GET_SIZE(c->c_stack) - 1; - if (n >= 0) { - wrapper = PyList_GET_ITEM(c->c_stack, n); - c->u = (struct compiler_unit *)PyCObject_AsVoidPtr(wrapper); - /* we are deleting from a list so this really shouldn't fail */ - if (PySequence_DelItem(c->c_stack, n) < 0) - Py_FatalError("compiler_exit_scope()"); - compiler_unit_check(c->u); - } - else - c->u = NULL; - -} - -/* Allocate a new "anonymous" local variable. - Used by list comprehensions and with statements. -*/ - -static PyObject * -compiler_new_tmpname(struct compiler *c) -{ - char tmpname[256]; - PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", ++c->u->u_tmpname); - return PyString_FromString(tmpname); -} - -/* Allocate a new block and return a pointer to it. - Returns NULL on error. -*/ - -static basicblock * -compiler_new_block(struct compiler *c) -{ - basicblock *b; - struct compiler_unit *u; - - u = c->u; - b = (basicblock *)PyObject_Malloc(sizeof(basicblock)); - if (b == NULL) { - PyErr_NoMemory(); - return NULL; - } - memset((void *)b, 0, sizeof(basicblock)); - /* Extend the singly linked list of blocks with new block. */ - b->b_list = u->u_blocks; - u->u_blocks = b; - return b; -} - -static basicblock * -compiler_use_new_block(struct compiler *c) -{ - basicblock *block = compiler_new_block(c); - if (block == NULL) - return NULL; - c->u->u_curblock = block; - return block; -} - -static basicblock * -compiler_next_block(struct compiler *c) -{ - basicblock *block = compiler_new_block(c); - if (block == NULL) - return NULL; - c->u->u_curblock->b_next = block; - c->u->u_curblock = block; - return block; -} - -static basicblock * -compiler_use_next_block(struct compiler *c, basicblock *block) -{ - assert(block != NULL); - c->u->u_curblock->b_next = block; - c->u->u_curblock = block; - return block; -} - -/* Returns the offset of the next instruction in the current block's - b_instr array. Resizes the b_instr as necessary. - Returns -1 on failure. - */ - -static int -compiler_next_instr(struct compiler *c, basicblock *b) -{ - assert(b != NULL); - if (b->b_instr == NULL) { - b->b_instr = (struct instr *)PyObject_Malloc( - sizeof(struct instr) * DEFAULT_BLOCK_SIZE); - if (b->b_instr == NULL) { - PyErr_NoMemory(); - return -1; - } - b->b_ialloc = DEFAULT_BLOCK_SIZE; - memset((char *)b->b_instr, 0, - sizeof(struct instr) * DEFAULT_BLOCK_SIZE); - } - else if (b->b_iused == b->b_ialloc) { - struct instr *tmp; - size_t oldsize, newsize; - oldsize = b->b_ialloc * sizeof(struct instr); - newsize = oldsize << 1; - if (newsize == 0) { - PyErr_NoMemory(); - return -1; - } - b->b_ialloc <<= 1; - tmp = (struct instr *)PyObject_Realloc( - (void *)b->b_instr, newsize); - if (tmp == NULL) { - PyErr_NoMemory(); - return -1; - } - b->b_instr = tmp; - memset((char *)b->b_instr + oldsize, 0, newsize - oldsize); - } - return b->b_iused++; -} - -/* Set the i_lineno member of the instruction at offse off if the - line number for the current expression/statement (?) has not - already been set. If it has been set, the call has no effect. - - Every time a new node is b - */ - -static void -compiler_set_lineno(struct compiler *c, int off) -{ - basicblock *b; - if (c->u->u_lineno_set) - return; - c->u->u_lineno_set = true; - b = c->u->u_curblock; - b->b_instr[off].i_lineno = c->u->u_lineno; -} - -static int -opcode_stack_effect(int opcode, int oparg) -{ - switch (opcode) { - case POP_TOP: - return -1; - case ROT_TWO: - case ROT_THREE: - return 0; - case DUP_TOP: - return 1; - case ROT_FOUR: - return 0; - - case UNARY_POSITIVE: - case UNARY_NEGATIVE: - case UNARY_NOT: - case UNARY_CONVERT: - case UNARY_INVERT: - return 0; - - case LIST_APPEND: - return -2; - - case BINARY_POWER: - case BINARY_MULTIPLY: - case BINARY_DIVIDE: - case BINARY_MODULO: - case BINARY_ADD: - case BINARY_SUBTRACT: - case BINARY_SUBSCR: - case BINARY_FLOOR_DIVIDE: - case BINARY_TRUE_DIVIDE: - return -1; - case INPLACE_FLOOR_DIVIDE: - case INPLACE_TRUE_DIVIDE: - return -1; - - case SLICE+0: - return 1; - case SLICE+1: - return 0; - case SLICE+2: - return 0; - case SLICE+3: - return -1; - - case STORE_SLICE+0: - return -2; - case STORE_SLICE+1: - return -3; - case STORE_SLICE+2: - return -3; - case STORE_SLICE+3: - return -4; - - case DELETE_SLICE+0: - return -1; - case DELETE_SLICE+1: - return -2; - case DELETE_SLICE+2: - return -2; - case DELETE_SLICE+3: - return -3; - - case INPLACE_ADD: - case INPLACE_SUBTRACT: - case INPLACE_MULTIPLY: - case INPLACE_DIVIDE: - case INPLACE_MODULO: - return -1; - case STORE_SUBSCR: - return -3; - case DELETE_SUBSCR: - return -2; - - case BINARY_LSHIFT: - case BINARY_RSHIFT: - case BINARY_AND: - case BINARY_XOR: - case BINARY_OR: - return -1; - case INPLACE_POWER: - return -1; - case GET_ITER: - return 0; - - case PRINT_EXPR: - return -1; - case PRINT_ITEM: - return -1; - case PRINT_NEWLINE: - return 0; - case PRINT_ITEM_TO: - return -2; - case PRINT_NEWLINE_TO: - return -1; - case INPLACE_LSHIFT: - case INPLACE_RSHIFT: - case INPLACE_AND: - case INPLACE_XOR: - case INPLACE_OR: - return -1; - case BREAK_LOOP: - return 0; - case WITH_CLEANUP: - return -1; /* XXX Sometimes more */ - case LOAD_LOCALS: - return 1; - case RETURN_VALUE: - return -1; - case IMPORT_STAR: - return -1; - case EXEC_STMT: - return -3; - case YIELD_VALUE: - return 0; - - case POP_BLOCK: - return 0; - case END_FINALLY: - return -1; /* or -2 or -3 if exception occurred */ - case BUILD_CLASS: - return -2; - - case STORE_NAME: - return -1; - case DELETE_NAME: - return 0; - case UNPACK_SEQUENCE: - return oparg-1; - case FOR_ITER: - return 1; - - case STORE_ATTR: - return -2; - case DELETE_ATTR: - return -1; - case STORE_GLOBAL: - return -1; - case DELETE_GLOBAL: - return 0; - case DUP_TOPX: - return oparg; - case LOAD_CONST: - return 1; - case LOAD_NAME: - return 1; - case BUILD_TUPLE: - case BUILD_LIST: - return 1-oparg; - case BUILD_MAP: - return 1; - case LOAD_ATTR: - return 0; - case COMPARE_OP: - return -1; - case IMPORT_NAME: - return 0; - case IMPORT_FROM: - return 1; - - case JUMP_FORWARD: - case JUMP_IF_FALSE: - case JUMP_IF_TRUE: - case JUMP_ABSOLUTE: - return 0; - - case LOAD_GLOBAL: - return 1; - - case CONTINUE_LOOP: - return 0; - case SETUP_LOOP: - return 0; - case SETUP_EXCEPT: - case SETUP_FINALLY: - return 3; /* actually pushed by an exception */ - - case LOAD_FAST: - return 1; - case STORE_FAST: - return -1; - case DELETE_FAST: - return 0; - - case RAISE_VARARGS: - return -oparg; -#define NARGS(o) (((o) % 256) + 2*((o) / 256)) - case CALL_FUNCTION: - return -NARGS(oparg); - case CALL_FUNCTION_VAR: - case CALL_FUNCTION_KW: - return -NARGS(oparg)-1; - case CALL_FUNCTION_VAR_KW: - return -NARGS(oparg)-2; -#undef NARGS - case MAKE_FUNCTION: - return -oparg; - case BUILD_SLICE: - if (oparg == 3) - return -2; - else - return -1; - - case MAKE_CLOSURE: - return -oparg; - case LOAD_CLOSURE: - return 1; - case LOAD_DEREF: - return 1; - case STORE_DEREF: - return -1; - default: - fprintf(stderr, "opcode = %d\n", opcode); - Py_FatalError("opcode_stack_effect()"); - - } - return 0; /* not reachable */ -} - -/* Add an opcode with no argument. - Returns 0 on failure, 1 on success. -*/ - -static int -compiler_addop(struct compiler *c, int opcode) -{ - basicblock *b; - struct instr *i; - int off; - off = compiler_next_instr(c, c->u->u_curblock); - if (off < 0) - return 0; - b = c->u->u_curblock; - i = &b->b_instr[off]; - i->i_opcode = opcode; - i->i_hasarg = 0; - if (opcode == RETURN_VALUE) - b->b_return = 1; - compiler_set_lineno(c, off); - return 1; -} - -static int -compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) -{ - PyObject *t, *v; - Py_ssize_t arg; - - /* necessary to make sure types aren't coerced (e.g., int and long) */ - t = PyTuple_Pack(2, o, o->ob_type); - if (t == NULL) - return -1; - - v = PyDict_GetItem(dict, t); - if (!v) { - arg = PyDict_Size(dict); - v = PyInt_FromLong(arg); - if (!v) { - Py_DECREF(t); - return -1; - } - if (PyDict_SetItem(dict, t, v) < 0) { - Py_DECREF(t); - Py_DECREF(v); - return -1; - } - Py_DECREF(v); - } - else - arg = PyInt_AsLong(v); - Py_DECREF(t); - return arg; -} - -static int -compiler_addop_o(struct compiler *c, int opcode, PyObject *dict, - PyObject *o) -{ - int arg = compiler_add_o(c, dict, o); - if (arg < 0) - return 0; - return compiler_addop_i(c, opcode, arg); -} - -static int -compiler_addop_name(struct compiler *c, int opcode, PyObject *dict, - PyObject *o) -{ - int arg; - PyObject *mangled = _Py_Mangle(c->u->u_private, o); - if (!mangled) - return 0; - arg = compiler_add_o(c, dict, mangled); - Py_DECREF(mangled); - if (arg < 0) - return 0; - return compiler_addop_i(c, opcode, arg); -} - -/* Add an opcode with an integer argument. - Returns 0 on failure, 1 on success. -*/ - -static int -compiler_addop_i(struct compiler *c, int opcode, int oparg) -{ - struct instr *i; - int off; - off = compiler_next_instr(c, c->u->u_curblock); - if (off < 0) - return 0; - i = &c->u->u_curblock->b_instr[off]; - i->i_opcode = opcode; - i->i_oparg = oparg; - i->i_hasarg = 1; - compiler_set_lineno(c, off); - return 1; -} - -static int -compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) -{ - struct instr *i; - int off; - - assert(b != NULL); - off = compiler_next_instr(c, c->u->u_curblock); - if (off < 0) - return 0; - i = &c->u->u_curblock->b_instr[off]; - i->i_opcode = opcode; - i->i_target = b; - i->i_hasarg = 1; - if (absolute) - i->i_jabs = 1; - else - i->i_jrel = 1; - compiler_set_lineno(c, off); - return 1; -} - -/* The distinction between NEW_BLOCK and NEXT_BLOCK is subtle. (I'd - like to find better names.) NEW_BLOCK() creates a new block and sets - it as the current block. NEXT_BLOCK() also creates an implicit jump - from the current block to the new block. -*/ - -/* XXX The returns inside these macros make it impossible to decref - objects created in the local function. -*/ - - -#define NEW_BLOCK(C) { \ - if (compiler_use_new_block((C)) == NULL) \ - return 0; \ -} - -#define NEXT_BLOCK(C) { \ - if (compiler_next_block((C)) == NULL) \ - return 0; \ -} - -#define ADDOP(C, OP) { \ - if (!compiler_addop((C), (OP))) \ - return 0; \ -} - -#define ADDOP_IN_SCOPE(C, OP) { \ - if (!compiler_addop((C), (OP))) { \ - compiler_exit_scope(c); \ - return 0; \ - } \ -} - -#define ADDOP_O(C, OP, O, TYPE) { \ - if (!compiler_addop_o((C), (OP), (C)->u->u_ ## TYPE, (O))) \ - return 0; \ -} - -#define ADDOP_NAME(C, OP, O, TYPE) { \ - if (!compiler_addop_name((C), (OP), (C)->u->u_ ## TYPE, (O))) \ - return 0; \ -} - -#define ADDOP_I(C, OP, O) { \ - if (!compiler_addop_i((C), (OP), (O))) \ - return 0; \ -} - -#define ADDOP_JABS(C, OP, O) { \ - if (!compiler_addop_j((C), (OP), (O), 1)) \ - return 0; \ -} - -#define ADDOP_JREL(C, OP, O) { \ - if (!compiler_addop_j((C), (OP), (O), 0)) \ - return 0; \ -} - -/* VISIT and VISIT_SEQ takes an ASDL type as their second argument. They use - the ASDL name to synthesize the name of the C type and the visit function. -*/ - -#define VISIT(C, TYPE, V) {\ - if (!compiler_visit_ ## TYPE((C), (V))) \ - return 0; \ -} - -#define VISIT_IN_SCOPE(C, TYPE, V) {\ - if (!compiler_visit_ ## TYPE((C), (V))) { \ - compiler_exit_scope(c); \ - return 0; \ - } \ -} - -#define VISIT_SLICE(C, V, CTX) {\ - if (!compiler_visit_slice((C), (V), (CTX))) \ - return 0; \ -} - -#define VISIT_SEQ(C, TYPE, SEQ) { \ - int _i; \ - asdl_seq *seq = (SEQ); /* avoid variable capture */ \ - for (_i = 0; _i < asdl_seq_LEN(seq); _i++) { \ - TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, _i); \ - if (!compiler_visit_ ## TYPE((C), elt)) \ - return 0; \ - } \ -} - -#define VISIT_SEQ_IN_SCOPE(C, TYPE, SEQ) { \ - int _i; \ - asdl_seq *seq = (SEQ); /* avoid variable capture */ \ - for (_i = 0; _i < asdl_seq_LEN(seq); _i++) { \ - TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, _i); \ - if (!compiler_visit_ ## TYPE((C), elt)) { \ - compiler_exit_scope(c); \ - return 0; \ - } \ - } \ -} - -static int -compiler_isdocstring(stmt_ty s) -{ - if (s->kind != Expr_kind) - return 0; - return s->v.Expr.value->kind == Str_kind; -} - -/* Compile a sequence of statements, checking for a docstring. */ - -static int -compiler_body(struct compiler *c, asdl_seq *stmts) -{ - int i = 0; - stmt_ty st; - - if (!asdl_seq_LEN(stmts)) - return 1; - st = (stmt_ty)asdl_seq_GET(stmts, 0); - if (compiler_isdocstring(st)) { - i = 1; - VISIT(c, expr, st->v.Expr.value); - if (!compiler_nameop(c, __doc__, Store)) - return 0; - } - for (; i < asdl_seq_LEN(stmts); i++) - VISIT(c, stmt, (stmt_ty)asdl_seq_GET(stmts, i)); - return 1; -} - -static PyCodeObject * -compiler_mod(struct compiler *c, mod_ty mod) -{ - PyCodeObject *co; - int addNone = 1; - static PyObject *module; - if (!module) { - module = PyString_FromString("<module>"); - if (!module) - return NULL; - } - /* Use 0 for firstlineno initially, will fixup in assemble(). */ - if (!compiler_enter_scope(c, module, mod, 0)) - return NULL; - switch (mod->kind) { - case Module_kind: - if (!compiler_body(c, mod->v.Module.body)) { - compiler_exit_scope(c); - return 0; - } - break; - case Interactive_kind: - c->c_interactive = 1; - VISIT_SEQ_IN_SCOPE(c, stmt, - mod->v.Interactive.body); - break; - case Expression_kind: - VISIT_IN_SCOPE(c, expr, mod->v.Expression.body); - addNone = 0; - break; - case Suite_kind: - PyErr_SetString(PyExc_SystemError, - "suite should not be possible"); - return 0; - default: - PyErr_Format(PyExc_SystemError, - "module kind %d should not be possible", - mod->kind); - return 0; - } - co = assemble(c, addNone); - compiler_exit_scope(c); - return co; -} - -/* The test for LOCAL must come before the test for FREE in order to - handle classes where name is both local and free. The local var is - a method and the free var is a free var referenced within a method. -*/ - -static int -get_ref_type(struct compiler *c, PyObject *name) -{ - int scope = PyST_GetScope(c->u->u_ste, name); - if (scope == 0) { - char buf[350]; - PyOS_snprintf(buf, sizeof(buf), - "unknown scope for %.100s in %.100s(%s) in %s\n" - "symbols: %s\nlocals: %s\nglobals: %s\n", - PyString_AS_STRING(name), - PyString_AS_STRING(c->u->u_name), - PyObject_REPR(c->u->u_ste->ste_id), - c->c_filename, - PyObject_REPR(c->u->u_ste->ste_symbols), - PyObject_REPR(c->u->u_varnames), - PyObject_REPR(c->u->u_names) - ); - Py_FatalError(buf); - } - - return scope; -} - -static int -compiler_lookup_arg(PyObject *dict, PyObject *name) -{ - PyObject *k, *v; - k = PyTuple_Pack(2, name, name->ob_type); - if (k == NULL) - return -1; - v = PyDict_GetItem(dict, k); - Py_DECREF(k); - if (v == NULL) - return -1; - return PyInt_AS_LONG(v); -} - -static int -compiler_make_closure(struct compiler *c, PyCodeObject *co, int args) -{ - int i, free = PyCode_GetNumFree(co); - if (free == 0) { - ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts); - ADDOP_I(c, MAKE_FUNCTION, args); - return 1; - } - for (i = 0; i < free; ++i) { - /* Bypass com_addop_varname because it will generate - LOAD_DEREF but LOAD_CLOSURE is needed. - */ - PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i); - int arg, reftype; - - /* Special case: If a class contains a method with a - free variable that has the same name as a method, - the name will be considered free *and* local in the - class. It should be handled by the closure, as - well as by the normal name loookup logic. - */ - reftype = get_ref_type(c, name); - if (reftype == CELL) - arg = compiler_lookup_arg(c->u->u_cellvars, name); - else /* (reftype == FREE) */ - arg = compiler_lookup_arg(c->u->u_freevars, name); - if (arg == -1) { - printf("lookup %s in %s %d %d\n" - "freevars of %s: %s\n", - PyObject_REPR(name), - PyString_AS_STRING(c->u->u_name), - reftype, arg, - PyString_AS_STRING(co->co_name), - PyObject_REPR(co->co_freevars)); - Py_FatalError("compiler_make_closure()"); - } - ADDOP_I(c, LOAD_CLOSURE, arg); - } - ADDOP_I(c, BUILD_TUPLE, free); - ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts); - ADDOP_I(c, MAKE_CLOSURE, args); - return 1; -} - -static int -compiler_decorators(struct compiler *c, asdl_seq* decos) -{ - int i; - - if (!decos) - return 1; - - for (i = 0; i < asdl_seq_LEN(decos); i++) { - VISIT(c, expr, (expr_ty)asdl_seq_GET(decos, i)); - } - return 1; -} - -static int -compiler_arguments(struct compiler *c, arguments_ty args) -{ - int i; - int n = asdl_seq_LEN(args->args); - /* Correctly handle nested argument lists */ - for (i = 0; i < n; i++) { - expr_ty arg = (expr_ty)asdl_seq_GET(args->args, i); - if (arg->kind == Tuple_kind) { - PyObject *id = PyString_FromFormat(".%d", i); - if (id == NULL) { - return 0; - } - if (!compiler_nameop(c, id, Load)) { - Py_DECREF(id); - return 0; - } - Py_DECREF(id); - VISIT(c, expr, arg); - } - } - return 1; -} - -static int -compiler_function(struct compiler *c, stmt_ty s) -{ - PyCodeObject *co; - PyObject *first_const = Py_None; - arguments_ty args = s->v.FunctionDef.args; - asdl_seq* decos = s->v.FunctionDef.decorators; - stmt_ty st; - int i, n, docstring; - - assert(s->kind == FunctionDef_kind); - - if (!compiler_decorators(c, decos)) - return 0; - if (args->defaults) - VISIT_SEQ(c, expr, args->defaults); - if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s, - s->lineno)) - return 0; - - st = (stmt_ty)asdl_seq_GET(s->v.FunctionDef.body, 0); - docstring = compiler_isdocstring(st); - if (docstring) - first_const = st->v.Expr.value->v.Str.s; - if (compiler_add_o(c, c->u->u_consts, first_const) < 0) { - compiler_exit_scope(c); - return 0; - } - - /* unpack nested arguments */ - compiler_arguments(c, args); - - c->u->u_argcount = asdl_seq_LEN(args->args); - n = asdl_seq_LEN(s->v.FunctionDef.body); - /* if there was a docstring, we need to skip the first statement */ - for (i = docstring; i < n; i++) { - st = (stmt_ty)asdl_seq_GET(s->v.FunctionDef.body, i); - VISIT_IN_SCOPE(c, stmt, st); - } - co = assemble(c, 1); - compiler_exit_scope(c); - if (co == NULL) - return 0; - - compiler_make_closure(c, co, asdl_seq_LEN(args->defaults)); - Py_DECREF(co); - - for (i = 0; i < asdl_seq_LEN(decos); i++) { - ADDOP_I(c, CALL_FUNCTION, 1); - } - - return compiler_nameop(c, s->v.FunctionDef.name, Store); -} - -static int -compiler_class(struct compiler *c, stmt_ty s) -{ - int n; - PyCodeObject *co; - PyObject *str; - /* push class name on stack, needed by BUILD_CLASS */ - ADDOP_O(c, LOAD_CONST, s->v.ClassDef.name, consts); - /* push the tuple of base classes on the stack */ - n = asdl_seq_LEN(s->v.ClassDef.bases); - if (n > 0) - VISIT_SEQ(c, expr, s->v.ClassDef.bases); - ADDOP_I(c, BUILD_TUPLE, n); - if (!compiler_enter_scope(c, s->v.ClassDef.name, (void *)s, - s->lineno)) - return 0; - c->u->u_private = s->v.ClassDef.name; - Py_INCREF(c->u->u_private); - str = PyString_InternFromString("__name__"); - if (!str || !compiler_nameop(c, str, Load)) { - Py_XDECREF(str); - compiler_exit_scope(c); - return 0; - } - - Py_DECREF(str); - str = PyString_InternFromString("__module__"); - if (!str || !compiler_nameop(c, str, Store)) { - Py_XDECREF(str); - compiler_exit_scope(c); - return 0; - } - Py_DECREF(str); - - if (!compiler_body(c, s->v.ClassDef.body)) { - compiler_exit_scope(c); - return 0; - } - - ADDOP_IN_SCOPE(c, LOAD_LOCALS); - ADDOP_IN_SCOPE(c, RETURN_VALUE); - co = assemble(c, 1); - compiler_exit_scope(c); - if (co == NULL) - return 0; - - compiler_make_closure(c, co, 0); - Py_DECREF(co); - - ADDOP_I(c, CALL_FUNCTION, 0); - ADDOP(c, BUILD_CLASS); - if (!compiler_nameop(c, s->v.ClassDef.name, Store)) - return 0; - return 1; -} - -static int -compiler_ifexp(struct compiler *c, expr_ty e) -{ - basicblock *end, *next; - - assert(e->kind == IfExp_kind); - end = compiler_new_block(c); - if (end == NULL) - return 0; - next = compiler_new_block(c); - if (next == NULL) - return 0; - VISIT(c, expr, e->v.IfExp.test); - ADDOP_JREL(c, JUMP_IF_FALSE, next); - ADDOP(c, POP_TOP); - VISIT(c, expr, e->v.IfExp.body); - ADDOP_JREL(c, JUMP_FORWARD, end); - compiler_use_next_block(c, next); - ADDOP(c, POP_TOP); - VISIT(c, expr, e->v.IfExp.orelse); - compiler_use_next_block(c, end); - return 1; -} - -static int -compiler_lambda(struct compiler *c, expr_ty e) -{ - PyCodeObject *co; - static identifier name; - arguments_ty args = e->v.Lambda.args; - assert(e->kind == Lambda_kind); - - if (!name) { - name = PyString_InternFromString("<lambda>"); - if (!name) - return 0; - } - - if (args->defaults) - VISIT_SEQ(c, expr, args->defaults); - if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) - return 0; - - /* unpack nested arguments */ - compiler_arguments(c, args); - - c->u->u_argcount = asdl_seq_LEN(args->args); - VISIT_IN_SCOPE(c, expr, e->v.Lambda.body); - ADDOP_IN_SCOPE(c, RETURN_VALUE); - co = assemble(c, 1); - compiler_exit_scope(c); - if (co == NULL) - return 0; - - compiler_make_closure(c, co, asdl_seq_LEN(args->defaults)); - Py_DECREF(co); - - return 1; -} - -static int -compiler_print(struct compiler *c, stmt_ty s) -{ - int i, n; - bool dest; - - assert(s->kind == Print_kind); - n = asdl_seq_LEN(s->v.Print.values); - dest = false; - if (s->v.Print.dest) { - VISIT(c, expr, s->v.Print.dest); - dest = true; - } - for (i = 0; i < n; i++) { - expr_ty e = (expr_ty)asdl_seq_GET(s->v.Print.values, i); - if (dest) { - ADDOP(c, DUP_TOP); - VISIT(c, expr, e); - ADDOP(c, ROT_TWO); - ADDOP(c, PRINT_ITEM_TO); - } - else { - VISIT(c, expr, e); - ADDOP(c, PRINT_ITEM); - } - } - if (s->v.Print.nl) { - if (dest) - ADDOP(c, PRINT_NEWLINE_TO) - else - ADDOP(c, PRINT_NEWLINE) - } - else if (dest) - ADDOP(c, POP_TOP); - return 1; -} - -static int -compiler_if(struct compiler *c, stmt_ty s) -{ - basicblock *end, *next; - int constant; - assert(s->kind == If_kind); - end = compiler_new_block(c); - if (end == NULL) - return 0; - next = compiler_new_block(c); - if (next == NULL) - return 0; - - constant = expr_constant(s->v.If.test); - /* constant = 0: "if 0" - * constant = 1: "if 1", "if 2", ... - * constant = -1: rest */ - if (constant == 0) { - if (s->v.If.orelse) - VISIT_SEQ(c, stmt, s->v.If.orelse); - } else if (constant == 1) { - VISIT_SEQ(c, stmt, s->v.If.body); - } else { - VISIT(c, expr, s->v.If.test); - ADDOP_JREL(c, JUMP_IF_FALSE, next); - ADDOP(c, POP_TOP); - VISIT_SEQ(c, stmt, s->v.If.body); - ADDOP_JREL(c, JUMP_FORWARD, end); - compiler_use_next_block(c, next); - ADDOP(c, POP_TOP); - if (s->v.If.orelse) - VISIT_SEQ(c, stmt, s->v.If.orelse); - } - compiler_use_next_block(c, end); - return 1; -} - -static int -compiler_for(struct compiler *c, stmt_ty s) -{ - basicblock *start, *cleanup, *end; - - start = compiler_new_block(c); - cleanup = compiler_new_block(c); - end = compiler_new_block(c); - if (start == NULL || end == NULL || cleanup == NULL) - return 0; - ADDOP_JREL(c, SETUP_LOOP, end); - if (!compiler_push_fblock(c, LOOP, start)) - return 0; - VISIT(c, expr, s->v.For.iter); - ADDOP(c, GET_ITER); - compiler_use_next_block(c, start); - /* XXX(nnorwitz): is there a better way to handle this? - for loops are special, we want to be able to trace them - each time around, so we need to set an extra line number. */ - c->u->u_lineno_set = false; - ADDOP_JREL(c, FOR_ITER, cleanup); - VISIT(c, expr, s->v.For.target); - VISIT_SEQ(c, stmt, s->v.For.body); - ADDOP_JABS(c, JUMP_ABSOLUTE, start); - compiler_use_next_block(c, cleanup); - ADDOP(c, POP_BLOCK); - compiler_pop_fblock(c, LOOP, start); - VISIT_SEQ(c, stmt, s->v.For.orelse); - compiler_use_next_block(c, end); - return 1; -} - -static int -compiler_while(struct compiler *c, stmt_ty s) -{ - basicblock *loop, *orelse, *end, *anchor = NULL; - int constant = expr_constant(s->v.While.test); - - if (constant == 0) - return 1; - loop = compiler_new_block(c); - end = compiler_new_block(c); - if (constant == -1) { - anchor = compiler_new_block(c); - if (anchor == NULL) - return 0; - } - if (loop == NULL || end == NULL) - return 0; - if (s->v.While.orelse) { - orelse = compiler_new_block(c); - if (orelse == NULL) - return 0; - } - else - orelse = NULL; - - ADDOP_JREL(c, SETUP_LOOP, end); - compiler_use_next_block(c, loop); - if (!compiler_push_fblock(c, LOOP, loop)) - return 0; - if (constant == -1) { - VISIT(c, expr, s->v.While.test); - ADDOP_JREL(c, JUMP_IF_FALSE, anchor); - ADDOP(c, POP_TOP); - } - VISIT_SEQ(c, stmt, s->v.While.body); - ADDOP_JABS(c, JUMP_ABSOLUTE, loop); - - /* XXX should the two POP instructions be in a separate block - if there is no else clause ? - */ - - if (constant == -1) { - compiler_use_next_block(c, anchor); - ADDOP(c, POP_TOP); - ADDOP(c, POP_BLOCK); - } - compiler_pop_fblock(c, LOOP, loop); - if (orelse != NULL) /* what if orelse is just pass? */ - VISIT_SEQ(c, stmt, s->v.While.orelse); - compiler_use_next_block(c, end); - - return 1; -} - -static int -compiler_continue(struct compiler *c) -{ - static const char LOOP_ERROR_MSG[] = "'continue' not properly in loop"; - static const char IN_FINALLY_ERROR_MSG[] = - "'continue' not supported inside 'finally' clause"; - int i; - - if (!c->u->u_nfblocks) - return compiler_error(c, LOOP_ERROR_MSG); - i = c->u->u_nfblocks - 1; - switch (c->u->u_fblock[i].fb_type) { - case LOOP: - ADDOP_JABS(c, JUMP_ABSOLUTE, c->u->u_fblock[i].fb_block); - break; - case EXCEPT: - case FINALLY_TRY: - while (--i >= 0 && c->u->u_fblock[i].fb_type != LOOP) { - /* Prevent try: ... finally: - try: continue ... or - try: ... except: continue */ - if (c->u->u_fblock[i].fb_type == FINALLY_END) - return compiler_error(c, IN_FINALLY_ERROR_MSG); - } - if (i == -1) - return compiler_error(c, LOOP_ERROR_MSG); - ADDOP_JABS(c, CONTINUE_LOOP, c->u->u_fblock[i].fb_block); - break; - case FINALLY_END: - return compiler_error(c, IN_FINALLY_ERROR_MSG); - } - - return 1; -} - -/* Code generated for "try: <body> finally: <finalbody>" is as follows: - - SETUP_FINALLY L - <code for body> - POP_BLOCK - LOAD_CONST <None> - L: <code for finalbody> - END_FINALLY - - The special instructions use the block stack. Each block - stack entry contains the instruction that created it (here - SETUP_FINALLY), the level of the value stack at the time the - block stack entry was created, and a label (here L). - - SETUP_FINALLY: - Pushes the current value stack level and the label - onto the block stack. - POP_BLOCK: - Pops en entry from the block stack, and pops the value - stack until its level is the same as indicated on the - block stack. (The label is ignored.) - END_FINALLY: - Pops a variable number of entries from the *value* stack - and re-raises the exception they specify. The number of - entries popped depends on the (pseudo) exception type. - - The block stack is unwound when an exception is raised: - when a SETUP_FINALLY entry is found, the exception is pushed - onto the value stack (and the exception condition is cleared), - and the interpreter jumps to the label gotten from the block - stack. -*/ - -static int -compiler_try_finally(struct compiler *c, stmt_ty s) -{ - basicblock *body, *end; - body = compiler_new_block(c); - end = compiler_new_block(c); - if (body == NULL || end == NULL) - return 0; - - ADDOP_JREL(c, SETUP_FINALLY, end); - compiler_use_next_block(c, body); - if (!compiler_push_fblock(c, FINALLY_TRY, body)) - return 0; - VISIT_SEQ(c, stmt, s->v.TryFinally.body); - ADDOP(c, POP_BLOCK); - compiler_pop_fblock(c, FINALLY_TRY, body); - - ADDOP_O(c, LOAD_CONST, Py_None, consts); - compiler_use_next_block(c, end); - if (!compiler_push_fblock(c, FINALLY_END, end)) - return 0; - VISIT_SEQ(c, stmt, s->v.TryFinally.finalbody); - ADDOP(c, END_FINALLY); - compiler_pop_fblock(c, FINALLY_END, end); - - return 1; -} - -/* - Code generated for "try: S except E1, V1: S1 except E2, V2: S2 ...": - (The contents of the value stack is shown in [], with the top - at the right; 'tb' is trace-back info, 'val' the exception's - associated value, and 'exc' the exception.) - - Value stack Label Instruction Argument - [] SETUP_EXCEPT L1 - [] <code for S> - [] POP_BLOCK - [] JUMP_FORWARD L0 - - [tb, val, exc] L1: DUP ) - [tb, val, exc, exc] <evaluate E1> ) - [tb, val, exc, exc, E1] COMPARE_OP EXC_MATCH ) only if E1 - [tb, val, exc, 1-or-0] JUMP_IF_FALSE L2 ) - [tb, val, exc, 1] POP ) - [tb, val, exc] POP - [tb, val] <assign to V1> (or POP if no V1) - [tb] POP - [] <code for S1> - JUMP_FORWARD L0 - - [tb, val, exc, 0] L2: POP - [tb, val, exc] DUP - .............................etc....................... - - [tb, val, exc, 0] Ln+1: POP - [tb, val, exc] END_FINALLY # re-raise exception - - [] L0: <next statement> - - Of course, parts are not generated if Vi or Ei is not present. -*/ -static int -compiler_try_except(struct compiler *c, stmt_ty s) -{ - basicblock *body, *orelse, *except, *end; - int i, n; - - body = compiler_new_block(c); - except = compiler_new_block(c); - orelse = compiler_new_block(c); - end = compiler_new_block(c); - if (body == NULL || except == NULL || orelse == NULL || end == NULL) - return 0; - ADDOP_JREL(c, SETUP_EXCEPT, except); - compiler_use_next_block(c, body); - if (!compiler_push_fblock(c, EXCEPT, body)) - return 0; - VISIT_SEQ(c, stmt, s->v.TryExcept.body); - ADDOP(c, POP_BLOCK); - compiler_pop_fblock(c, EXCEPT, body); - ADDOP_JREL(c, JUMP_FORWARD, orelse); - n = asdl_seq_LEN(s->v.TryExcept.handlers); - compiler_use_next_block(c, except); - for (i = 0; i < n; i++) { - excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( - s->v.TryExcept.handlers, i); - if (!handler->type && i < n-1) - return compiler_error(c, "default 'except:' must be last"); - c->u->u_lineno_set = false; - c->u->u_lineno = handler->lineno; - except = compiler_new_block(c); - if (except == NULL) - return 0; - if (handler->type) { - ADDOP(c, DUP_TOP); - VISIT(c, expr, handler->type); - ADDOP_I(c, COMPARE_OP, PyCmp_EXC_MATCH); - ADDOP_JREL(c, JUMP_IF_FALSE, except); - ADDOP(c, POP_TOP); - } - ADDOP(c, POP_TOP); - if (handler->name) { - VISIT(c, expr, handler->name); - } - else { - ADDOP(c, POP_TOP); - } - ADDOP(c, POP_TOP); - VISIT_SEQ(c, stmt, handler->body); - ADDOP_JREL(c, JUMP_FORWARD, end); - compiler_use_next_block(c, except); - if (handler->type) - ADDOP(c, POP_TOP); - } - ADDOP(c, END_FINALLY); - compiler_use_next_block(c, orelse); - VISIT_SEQ(c, stmt, s->v.TryExcept.orelse); - compiler_use_next_block(c, end); - return 1; -} - -static int -compiler_import_as(struct compiler *c, identifier name, identifier asname) -{ - /* The IMPORT_NAME opcode was already generated. This function - merely needs to bind the result to a name. - - If there is a dot in name, we need to split it and emit a - LOAD_ATTR for each name. - */ - const char *src = PyString_AS_STRING(name); - const char *dot = strchr(src, '.'); - if (dot) { - /* Consume the base module name to get the first attribute */ - src = dot + 1; - while (dot) { - /* NB src is only defined when dot != NULL */ - PyObject *attr; - dot = strchr(src, '.'); - attr = PyString_FromStringAndSize(src, - dot ? dot - src : strlen(src)); - if (!attr) - return -1; - ADDOP_O(c, LOAD_ATTR, attr, names); - Py_DECREF(attr); - src = dot + 1; - } - } - return compiler_nameop(c, asname, Store); -} - -static int -compiler_import(struct compiler *c, stmt_ty s) -{ - /* The Import node stores a module name like a.b.c as a single - string. This is convenient for all cases except - import a.b.c as d - where we need to parse that string to extract the individual - module names. - XXX Perhaps change the representation to make this case simpler? - */ - int i, n = asdl_seq_LEN(s->v.Import.names); - - for (i = 0; i < n; i++) { - alias_ty alias = (alias_ty)asdl_seq_GET(s->v.Import.names, i); - int r; - PyObject *level; - - if (c->c_flags && (c->c_flags->cf_flags & CO_FUTURE_ABSOLUTE_IMPORT)) - level = PyInt_FromLong(0); - else - level = PyInt_FromLong(-1); - - if (level == NULL) - return 0; - - ADDOP_O(c, LOAD_CONST, level, consts); - Py_DECREF(level); - ADDOP_O(c, LOAD_CONST, Py_None, consts); - ADDOP_NAME(c, IMPORT_NAME, alias->name, names); - - if (alias->asname) { - r = compiler_import_as(c, alias->name, alias->asname); - if (!r) - return r; - } - else { - identifier tmp = alias->name; - const char *base = PyString_AS_STRING(alias->name); - char *dot = strchr(base, '.'); - if (dot) - tmp = PyString_FromStringAndSize(base, - dot - base); - r = compiler_nameop(c, tmp, Store); - if (dot) { - Py_DECREF(tmp); - } - if (!r) - return r; - } - } - return 1; -} - -static int -compiler_from_import(struct compiler *c, stmt_ty s) -{ - int i, n = asdl_seq_LEN(s->v.ImportFrom.names); - - PyObject *names = PyTuple_New(n); - PyObject *level; - - if (!names) - return 0; - - if (s->v.ImportFrom.level == 0 && c->c_flags && - !(c->c_flags->cf_flags & CO_FUTURE_ABSOLUTE_IMPORT)) - level = PyInt_FromLong(-1); - else - level = PyInt_FromLong(s->v.ImportFrom.level); - - if (!level) { - Py_DECREF(names); - return 0; - } - - /* build up the names */ - for (i = 0; i < n; i++) { - alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i); - Py_INCREF(alias->name); - PyTuple_SET_ITEM(names, i, alias->name); - } - - if (s->lineno > c->c_future->ff_lineno) { - if (!strcmp(PyString_AS_STRING(s->v.ImportFrom.module), - "__future__")) { - Py_DECREF(level); - Py_DECREF(names); - return compiler_error(c, - "from __future__ imports must occur " - "at the beginning of the file"); - - } - } - - ADDOP_O(c, LOAD_CONST, level, consts); - Py_DECREF(level); - ADDOP_O(c, LOAD_CONST, names, consts); - Py_DECREF(names); - ADDOP_NAME(c, IMPORT_NAME, s->v.ImportFrom.module, names); - for (i = 0; i < n; i++) { - alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i); - identifier store_name; - - if (i == 0 && *PyString_AS_STRING(alias->name) == '*') { - assert(n == 1); - ADDOP(c, IMPORT_STAR); - return 1; - } - - ADDOP_NAME(c, IMPORT_FROM, alias->name, names); - store_name = alias->name; - if (alias->asname) - store_name = alias->asname; - - if (!compiler_nameop(c, store_name, Store)) { - Py_DECREF(names); - return 0; - } - } - /* remove imported module */ - ADDOP(c, POP_TOP); - return 1; -} - -static int -compiler_assert(struct compiler *c, stmt_ty s) -{ - static PyObject *assertion_error = NULL; - basicblock *end; - - if (Py_OptimizeFlag) - return 1; - if (assertion_error == NULL) { - assertion_error = PyString_FromString("AssertionError"); - if (assertion_error == NULL) - return 0; - } - VISIT(c, expr, s->v.Assert.test); - end = compiler_new_block(c); - if (end == NULL) - return 0; - ADDOP_JREL(c, JUMP_IF_TRUE, end); - ADDOP(c, POP_TOP); - ADDOP_O(c, LOAD_GLOBAL, assertion_error, names); - if (s->v.Assert.msg) { - VISIT(c, expr, s->v.Assert.msg); - ADDOP_I(c, RAISE_VARARGS, 2); - } - else { - ADDOP_I(c, RAISE_VARARGS, 1); - } - compiler_use_next_block(c, end); - ADDOP(c, POP_TOP); - return 1; -} - -static int -compiler_visit_stmt(struct compiler *c, stmt_ty s) -{ - int i, n; - - /* Always assign a lineno to the next instruction for a stmt. */ - c->u->u_lineno = s->lineno; - c->u->u_lineno_set = false; - - switch (s->kind) { - case FunctionDef_kind: - return compiler_function(c, s); - case ClassDef_kind: - return compiler_class(c, s); - case Return_kind: - if (c->u->u_ste->ste_type != FunctionBlock) - return compiler_error(c, "'return' outside function"); - if (s->v.Return.value) { - VISIT(c, expr, s->v.Return.value); - } - else - ADDOP_O(c, LOAD_CONST, Py_None, consts); - ADDOP(c, RETURN_VALUE); - break; - case Delete_kind: - VISIT_SEQ(c, expr, s->v.Delete.targets) - break; - case Assign_kind: - n = asdl_seq_LEN(s->v.Assign.targets); - VISIT(c, expr, s->v.Assign.value); - for (i = 0; i < n; i++) { - if (i < n - 1) - ADDOP(c, DUP_TOP); - VISIT(c, expr, - (expr_ty)asdl_seq_GET(s->v.Assign.targets, i)); - } - break; - case AugAssign_kind: - return compiler_augassign(c, s); - case Print_kind: - return compiler_print(c, s); - case For_kind: - return compiler_for(c, s); - case While_kind: - return compiler_while(c, s); - case If_kind: - return compiler_if(c, s); - case Raise_kind: - n = 0; - if (s->v.Raise.type) { - VISIT(c, expr, s->v.Raise.type); - n++; - if (s->v.Raise.inst) { - VISIT(c, expr, s->v.Raise.inst); - n++; - if (s->v.Raise.tback) { - VISIT(c, expr, s->v.Raise.tback); - n++; - } - } - } - ADDOP_I(c, RAISE_VARARGS, n); - break; - case TryExcept_kind: - return compiler_try_except(c, s); - case TryFinally_kind: - return compiler_try_finally(c, s); - case Assert_kind: - return compiler_assert(c, s); - case Import_kind: - return compiler_import(c, s); - case ImportFrom_kind: - return compiler_from_import(c, s); - case Exec_kind: - VISIT(c, expr, s->v.Exec.body); - if (s->v.Exec.globals) { - VISIT(c, expr, s->v.Exec.globals); - if (s->v.Exec.locals) { - VISIT(c, expr, s->v.Exec.locals); - } else { - ADDOP(c, DUP_TOP); - } - } else { - ADDOP_O(c, LOAD_CONST, Py_None, consts); - ADDOP(c, DUP_TOP); - } - ADDOP(c, EXEC_STMT); - break; - case Global_kind: - break; - case Expr_kind: - if (c->c_interactive && c->c_nestlevel <= 1) { - VISIT(c, expr, s->v.Expr.value); - ADDOP(c, PRINT_EXPR); - } - else if (s->v.Expr.value->kind != Str_kind && - s->v.Expr.value->kind != Num_kind) { - VISIT(c, expr, s->v.Expr.value); - ADDOP(c, POP_TOP); - } - break; - case Pass_kind: - break; - case Break_kind: - if (!compiler_in_loop(c)) - return compiler_error(c, "'break' outside loop"); - ADDOP(c, BREAK_LOOP); - break; - case Continue_kind: - return compiler_continue(c); - case With_kind: - return compiler_with(c, s); - } - return 1; -} - -static int -unaryop(unaryop_ty op) -{ - switch (op) { - case Invert: - return UNARY_INVERT; - case Not: - return UNARY_NOT; - case UAdd: - return UNARY_POSITIVE; - case USub: - return UNARY_NEGATIVE; - } - return 0; -} - -static int -binop(struct compiler *c, operator_ty op) -{ - switch (op) { - case Add: - return BINARY_ADD; - case Sub: - return BINARY_SUBTRACT; - case Mult: - return BINARY_MULTIPLY; - case Div: - if (c->c_flags && c->c_flags->cf_flags & CO_FUTURE_DIVISION) - return BINARY_TRUE_DIVIDE; - else - return BINARY_DIVIDE; - case Mod: - return BINARY_MODULO; - case Pow: - return BINARY_POWER; - case LShift: - return BINARY_LSHIFT; - case RShift: - return BINARY_RSHIFT; - case BitOr: - return BINARY_OR; - case BitXor: - return BINARY_XOR; - case BitAnd: - return BINARY_AND; - case FloorDiv: - return BINARY_FLOOR_DIVIDE; - } - return 0; -} - -static int -cmpop(cmpop_ty op) -{ - switch (op) { - case Eq: - return PyCmp_EQ; - case NotEq: - return PyCmp_NE; - case Lt: - return PyCmp_LT; - case LtE: - return PyCmp_LE; - case Gt: - return PyCmp_GT; - case GtE: - return PyCmp_GE; - case Is: - return PyCmp_IS; - case IsNot: - return PyCmp_IS_NOT; - case In: - return PyCmp_IN; - case NotIn: - return PyCmp_NOT_IN; - } - return PyCmp_BAD; -} - -static int -inplace_binop(struct compiler *c, operator_ty op) -{ - switch (op) { - case Add: - return INPLACE_ADD; - case Sub: - return INPLACE_SUBTRACT; - case Mult: - return INPLACE_MULTIPLY; - case Div: - if (c->c_flags && c->c_flags->cf_flags & CO_FUTURE_DIVISION) - return INPLACE_TRUE_DIVIDE; - else - return INPLACE_DIVIDE; - case Mod: - return INPLACE_MODULO; - case Pow: - return INPLACE_POWER; - case LShift: - return INPLACE_LSHIFT; - case RShift: - return INPLACE_RSHIFT; - case BitOr: - return INPLACE_OR; - case BitXor: - return INPLACE_XOR; - case BitAnd: - return INPLACE_AND; - case FloorDiv: - return INPLACE_FLOOR_DIVIDE; - } - PyErr_Format(PyExc_SystemError, - "inplace binary op %d should not be possible", op); - return 0; -} - -static int -compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) -{ - int op, scope, arg; - enum { OP_FAST, OP_GLOBAL, OP_DEREF, OP_NAME } optype; - - PyObject *dict = c->u->u_names; - PyObject *mangled; - /* XXX AugStore isn't used anywhere! */ - - /* First check for assignment to __debug__. Param? */ - if ((ctx == Store || ctx == AugStore || ctx == Del) - && !strcmp(PyString_AS_STRING(name), "__debug__")) { - return compiler_error(c, "can not assign to __debug__"); - } - - mangled = _Py_Mangle(c->u->u_private, name); - if (!mangled) - return 0; - - op = 0; - optype = OP_NAME; - scope = PyST_GetScope(c->u->u_ste, mangled); - switch (scope) { - case FREE: - dict = c->u->u_freevars; - optype = OP_DEREF; - break; - case CELL: - dict = c->u->u_cellvars; - optype = OP_DEREF; - break; - case LOCAL: - if (c->u->u_ste->ste_type == FunctionBlock) - optype = OP_FAST; - break; - case GLOBAL_IMPLICIT: - if (c->u->u_ste->ste_type == FunctionBlock && - !c->u->u_ste->ste_unoptimized) - optype = OP_GLOBAL; - break; - case GLOBAL_EXPLICIT: - optype = OP_GLOBAL; - break; - default: - /* scope can be 0 */ - break; - } - - /* XXX Leave assert here, but handle __doc__ and the like better */ - assert(scope || PyString_AS_STRING(name)[0] == '_'); - - switch (optype) { - case OP_DEREF: - switch (ctx) { - case Load: op = LOAD_DEREF; break; - case Store: op = STORE_DEREF; break; - case AugLoad: - case AugStore: - break; - case Del: - PyErr_Format(PyExc_SyntaxError, - "can not delete variable '%s' referenced " - "in nested scope", - PyString_AS_STRING(name)); - Py_DECREF(mangled); - return 0; - case Param: - default: - PyErr_SetString(PyExc_SystemError, - "param invalid for deref variable"); - return 0; - } - break; - case OP_FAST: - switch (ctx) { - case Load: op = LOAD_FAST; break; - case Store: op = STORE_FAST; break; - case Del: op = DELETE_FAST; break; - case AugLoad: - case AugStore: - break; - case Param: - default: - PyErr_SetString(PyExc_SystemError, - "param invalid for local variable"); - return 0; - } - ADDOP_O(c, op, mangled, varnames); - Py_DECREF(mangled); - return 1; - case OP_GLOBAL: - switch (ctx) { - case Load: op = LOAD_GLOBAL; break; - case Store: op = STORE_GLOBAL; break; - case Del: op = DELETE_GLOBAL; break; - case AugLoad: - case AugStore: - break; - case Param: - default: - PyErr_SetString(PyExc_SystemError, - "param invalid for global variable"); - return 0; - } - break; - case OP_NAME: - switch (ctx) { - case Load: op = LOAD_NAME; break; - case Store: op = STORE_NAME; break; - case Del: op = DELETE_NAME; break; - case AugLoad: - case AugStore: - break; - case Param: - default: - PyErr_SetString(PyExc_SystemError, - "param invalid for name variable"); - return 0; - } - break; - } - - assert(op); - arg = compiler_add_o(c, dict, mangled); - Py_DECREF(mangled); - if (arg < 0) - return 0; - return compiler_addop_i(c, op, arg); -} - -static int -compiler_boolop(struct compiler *c, expr_ty e) -{ - basicblock *end; - int jumpi, i, n; - asdl_seq *s; - - assert(e->kind == BoolOp_kind); - if (e->v.BoolOp.op == And) - jumpi = JUMP_IF_FALSE; - else - jumpi = JUMP_IF_TRUE; - end = compiler_new_block(c); - if (end == NULL) - return 0; - s = e->v.BoolOp.values; - n = asdl_seq_LEN(s) - 1; - assert(n >= 0); - for (i = 0; i < n; ++i) { - VISIT(c, expr, (expr_ty)asdl_seq_GET(s, i)); - ADDOP_JREL(c, jumpi, end); - ADDOP(c, POP_TOP) - } - VISIT(c, expr, (expr_ty)asdl_seq_GET(s, n)); - compiler_use_next_block(c, end); - return 1; -} - -static int -compiler_list(struct compiler *c, expr_ty e) -{ - int n = asdl_seq_LEN(e->v.List.elts); - if (e->v.List.ctx == Store) { - ADDOP_I(c, UNPACK_SEQUENCE, n); - } - VISIT_SEQ(c, expr, e->v.List.elts); - if (e->v.List.ctx == Load) { - ADDOP_I(c, BUILD_LIST, n); - } - return 1; -} - -static int -compiler_tuple(struct compiler *c, expr_ty e) -{ - int n = asdl_seq_LEN(e->v.Tuple.elts); - if (e->v.Tuple.ctx == Store) { - ADDOP_I(c, UNPACK_SEQUENCE, n); - } - VISIT_SEQ(c, expr, e->v.Tuple.elts); - if (e->v.Tuple.ctx == Load) { - ADDOP_I(c, BUILD_TUPLE, n); - } - return 1; -} - -static int -compiler_compare(struct compiler *c, expr_ty e) -{ - int i, n; - basicblock *cleanup = NULL; - - /* XXX the logic can be cleaned up for 1 or multiple comparisons */ - VISIT(c, expr, e->v.Compare.left); - n = asdl_seq_LEN(e->v.Compare.ops); - assert(n > 0); - if (n > 1) { - cleanup = compiler_new_block(c); - if (cleanup == NULL) - return 0; - VISIT(c, expr, - (expr_ty)asdl_seq_GET(e->v.Compare.comparators, 0)); - } - for (i = 1; i < n; i++) { - ADDOP(c, DUP_TOP); - ADDOP(c, ROT_THREE); - ADDOP_I(c, COMPARE_OP, - cmpop((cmpop_ty)(asdl_seq_GET( - e->v.Compare.ops, i - 1)))); - ADDOP_JREL(c, JUMP_IF_FALSE, cleanup); - NEXT_BLOCK(c); - ADDOP(c, POP_TOP); - if (i < (n - 1)) - VISIT(c, expr, - (expr_ty)asdl_seq_GET(e->v.Compare.comparators, i)); - } - VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n - 1)); - ADDOP_I(c, COMPARE_OP, - cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, n - 1)))); - if (n > 1) { - basicblock *end = compiler_new_block(c); - if (end == NULL) - return 0; - ADDOP_JREL(c, JUMP_FORWARD, end); - compiler_use_next_block(c, cleanup); - ADDOP(c, ROT_TWO); - ADDOP(c, POP_TOP); - compiler_use_next_block(c, end); - } - return 1; -} -#undef CMPCAST - -static int -compiler_call(struct compiler *c, expr_ty e) -{ - int n, code = 0; - - VISIT(c, expr, e->v.Call.func); - n = asdl_seq_LEN(e->v.Call.args); - VISIT_SEQ(c, expr, e->v.Call.args); - if (e->v.Call.keywords) { - VISIT_SEQ(c, keyword, e->v.Call.keywords); - n |= asdl_seq_LEN(e->v.Call.keywords) << 8; - } - if (e->v.Call.starargs) { - VISIT(c, expr, e->v.Call.starargs); - code |= 1; - } - if (e->v.Call.kwargs) { - VISIT(c, expr, e->v.Call.kwargs); - code |= 2; - } - switch (code) { - case 0: - ADDOP_I(c, CALL_FUNCTION, n); - break; - case 1: - ADDOP_I(c, CALL_FUNCTION_VAR, n); - break; - case 2: - ADDOP_I(c, CALL_FUNCTION_KW, n); - break; - case 3: - ADDOP_I(c, CALL_FUNCTION_VAR_KW, n); - break; - } - return 1; -} - -static int -compiler_listcomp_generator(struct compiler *c, PyObject *tmpname, - asdl_seq *generators, int gen_index, - expr_ty elt) -{ - /* generate code for the iterator, then each of the ifs, - and then write to the element */ - - comprehension_ty l; - basicblock *start, *anchor, *skip, *if_cleanup; - int i, n; - - start = compiler_new_block(c); - skip = compiler_new_block(c); - if_cleanup = compiler_new_block(c); - anchor = compiler_new_block(c); - - if (start == NULL || skip == NULL || if_cleanup == NULL || - anchor == NULL) - return 0; - - l = (comprehension_ty)asdl_seq_GET(generators, gen_index); - VISIT(c, expr, l->iter); - ADDOP(c, GET_ITER); - compiler_use_next_block(c, start); - ADDOP_JREL(c, FOR_ITER, anchor); - NEXT_BLOCK(c); - VISIT(c, expr, l->target); - - /* XXX this needs to be cleaned up...a lot! */ - n = asdl_seq_LEN(l->ifs); - for (i = 0; i < n; i++) { - expr_ty e = (expr_ty)asdl_seq_GET(l->ifs, i); - VISIT(c, expr, e); - ADDOP_JREL(c, JUMP_IF_FALSE, if_cleanup); - NEXT_BLOCK(c); - ADDOP(c, POP_TOP); - } - - if (++gen_index < asdl_seq_LEN(generators)) - if (!compiler_listcomp_generator(c, tmpname, - generators, gen_index, elt)) - return 0; - - /* only append after the last for generator */ - if (gen_index >= asdl_seq_LEN(generators)) { - if (!compiler_nameop(c, tmpname, Load)) - return 0; - VISIT(c, expr, elt); - ADDOP(c, LIST_APPEND); - - compiler_use_next_block(c, skip); - } - for (i = 0; i < n; i++) { - ADDOP_I(c, JUMP_FORWARD, 1); - if (i == 0) - compiler_use_next_block(c, if_cleanup); - ADDOP(c, POP_TOP); - } - ADDOP_JABS(c, JUMP_ABSOLUTE, start); - compiler_use_next_block(c, anchor); - /* delete the append method added to locals */ - if (gen_index == 1) - if (!compiler_nameop(c, tmpname, Del)) - return 0; - - return 1; -} - -static int -compiler_listcomp(struct compiler *c, expr_ty e) -{ - identifier tmp; - int rc = 0; - static identifier append; - asdl_seq *generators = e->v.ListComp.generators; - - assert(e->kind == ListComp_kind); - if (!append) { - append = PyString_InternFromString("append"); - if (!append) - return 0; - } - tmp = compiler_new_tmpname(c); - if (!tmp) - return 0; - ADDOP_I(c, BUILD_LIST, 0); - ADDOP(c, DUP_TOP); - if (compiler_nameop(c, tmp, Store)) - rc = compiler_listcomp_generator(c, tmp, generators, 0, - e->v.ListComp.elt); - Py_DECREF(tmp); - return rc; -} - -static int -compiler_genexp_generator(struct compiler *c, - asdl_seq *generators, int gen_index, - expr_ty elt) -{ - /* generate code for the iterator, then each of the ifs, - and then write to the element */ - - comprehension_ty ge; - basicblock *start, *anchor, *skip, *if_cleanup, *end; - int i, n; - - start = compiler_new_block(c); - skip = compiler_new_block(c); - if_cleanup = compiler_new_block(c); - anchor = compiler_new_block(c); - end = compiler_new_block(c); - - if (start == NULL || skip == NULL || if_cleanup == NULL || - anchor == NULL || end == NULL) - return 0; - - ge = (comprehension_ty)asdl_seq_GET(generators, gen_index); - ADDOP_JREL(c, SETUP_LOOP, end); - if (!compiler_push_fblock(c, LOOP, start)) - return 0; - - if (gen_index == 0) { - /* Receive outermost iter as an implicit argument */ - c->u->u_argcount = 1; - ADDOP_I(c, LOAD_FAST, 0); - } - else { - /* Sub-iter - calculate on the fly */ - VISIT(c, expr, ge->iter); - ADDOP(c, GET_ITER); - } - compiler_use_next_block(c, start); - ADDOP_JREL(c, FOR_ITER, anchor); - NEXT_BLOCK(c); - VISIT(c, expr, ge->target); - - /* XXX this needs to be cleaned up...a lot! */ - n = asdl_seq_LEN(ge->ifs); - for (i = 0; i < n; i++) { - expr_ty e = (expr_ty)asdl_seq_GET(ge->ifs, i); - VISIT(c, expr, e); - ADDOP_JREL(c, JUMP_IF_FALSE, if_cleanup); - NEXT_BLOCK(c); - ADDOP(c, POP_TOP); - } - - if (++gen_index < asdl_seq_LEN(generators)) - if (!compiler_genexp_generator(c, generators, gen_index, elt)) - return 0; - - /* only append after the last 'for' generator */ - if (gen_index >= asdl_seq_LEN(generators)) { - VISIT(c, expr, elt); - ADDOP(c, YIELD_VALUE); - ADDOP(c, POP_TOP); - - compiler_use_next_block(c, skip); - } - for (i = 0; i < n; i++) { - ADDOP_I(c, JUMP_FORWARD, 1); - if (i == 0) - compiler_use_next_block(c, if_cleanup); - - ADDOP(c, POP_TOP); - } - ADDOP_JABS(c, JUMP_ABSOLUTE, start); - compiler_use_next_block(c, anchor); - ADDOP(c, POP_BLOCK); - compiler_pop_fblock(c, LOOP, start); - compiler_use_next_block(c, end); - - return 1; -} - -static int -compiler_genexp(struct compiler *c, expr_ty e) -{ - static identifier name; - PyCodeObject *co; - expr_ty outermost_iter = ((comprehension_ty) - (asdl_seq_GET(e->v.GeneratorExp.generators, - 0)))->iter; - - if (!name) { - name = PyString_FromString("<genexpr>"); - if (!name) - return 0; - } - - if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) - return 0; - compiler_genexp_generator(c, e->v.GeneratorExp.generators, 0, - e->v.GeneratorExp.elt); - co = assemble(c, 1); - compiler_exit_scope(c); - if (co == NULL) - return 0; - - compiler_make_closure(c, co, 0); - Py_DECREF(co); - - VISIT(c, expr, outermost_iter); - ADDOP(c, GET_ITER); - ADDOP_I(c, CALL_FUNCTION, 1); - - return 1; -} - -static int -compiler_visit_keyword(struct compiler *c, keyword_ty k) -{ - ADDOP_O(c, LOAD_CONST, k->arg, consts); - VISIT(c, expr, k->value); - return 1; -} - -/* Test whether expression is constant. For constants, report - whether they are true or false. - - Return values: 1 for true, 0 for false, -1 for non-constant. - */ - -static int -expr_constant(expr_ty e) -{ - switch (e->kind) { - case Num_kind: - return PyObject_IsTrue(e->v.Num.n); - case Str_kind: - return PyObject_IsTrue(e->v.Str.s); - case Name_kind: - /* __debug__ is not assignable, so we can optimize - * it away in if and while statements */ - if (strcmp(PyString_AS_STRING(e->v.Name.id), - "__debug__") == 0) - return ! Py_OptimizeFlag; - /* fall through */ - default: - return -1; - } -} - -/* - Implements the with statement from PEP 343. - - The semantics outlined in that PEP are as follows: - - with EXPR as VAR: - BLOCK - - It is implemented roughly as: - - context = EXPR - exit = context.__exit__ # not calling it - value = context.__enter__() - try: - VAR = value # if VAR present in the syntax - BLOCK - finally: - if an exception was raised: - exc = copy of (exception, instance, traceback) - else: - exc = (None, None, None) - exit(*exc) - */ -static int -compiler_with(struct compiler *c, stmt_ty s) -{ - static identifier enter_attr, exit_attr; - basicblock *block, *finally; - identifier tmpexit, tmpvalue = NULL; - - assert(s->kind == With_kind); - - if (!enter_attr) { - enter_attr = PyString_InternFromString("__enter__"); - if (!enter_attr) - return 0; - } - if (!exit_attr) { - exit_attr = PyString_InternFromString("__exit__"); - if (!exit_attr) - return 0; - } - - block = compiler_new_block(c); - finally = compiler_new_block(c); - if (!block || !finally) - return 0; - - /* Create a temporary variable to hold context.__exit__ */ - tmpexit = compiler_new_tmpname(c); - if (tmpexit == NULL) - return 0; - PyArena_AddPyObject(c->c_arena, tmpexit); - - if (s->v.With.optional_vars) { - /* Create a temporary variable to hold context.__enter__(). - We need to do this rather than preserving it on the stack - because SETUP_FINALLY remembers the stack level. - We need to do the assignment *inside* the try/finally - so that context.__exit__() is called when the assignment - fails. But we need to call context.__enter__() *before* - the try/finally so that if it fails we won't call - context.__exit__(). - */ - tmpvalue = compiler_new_tmpname(c); - if (tmpvalue == NULL) - return 0; - PyArena_AddPyObject(c->c_arena, tmpvalue); - } - - /* Evaluate EXPR */ - VISIT(c, expr, s->v.With.context_expr); - - /* Squirrel away context.__exit__ */ - ADDOP(c, DUP_TOP); - ADDOP_O(c, LOAD_ATTR, exit_attr, names); - if (!compiler_nameop(c, tmpexit, Store)) - return 0; - - /* Call context.__enter__() */ - ADDOP_O(c, LOAD_ATTR, enter_attr, names); - ADDOP_I(c, CALL_FUNCTION, 0); - - if (s->v.With.optional_vars) { - /* Store it in tmpvalue */ - if (!compiler_nameop(c, tmpvalue, Store)) - return 0; - } - else { - /* Discard result from context.__enter__() */ - ADDOP(c, POP_TOP); - } - - /* Start the try block */ - ADDOP_JREL(c, SETUP_FINALLY, finally); - - compiler_use_next_block(c, block); - if (!compiler_push_fblock(c, FINALLY_TRY, block)) { - return 0; - } - - if (s->v.With.optional_vars) { - /* Bind saved result of context.__enter__() to VAR */ - if (!compiler_nameop(c, tmpvalue, Load) || - !compiler_nameop(c, tmpvalue, Del)) - return 0; - VISIT(c, expr, s->v.With.optional_vars); - } - - /* BLOCK code */ - VISIT_SEQ(c, stmt, s->v.With.body); - - /* End of try block; start the finally block */ - ADDOP(c, POP_BLOCK); - compiler_pop_fblock(c, FINALLY_TRY, block); - - ADDOP_O(c, LOAD_CONST, Py_None, consts); - compiler_use_next_block(c, finally); - if (!compiler_push_fblock(c, FINALLY_END, finally)) - return 0; - - /* Finally block starts; push tmpexit and issue our magic opcode. */ - if (!compiler_nameop(c, tmpexit, Load) || - !compiler_nameop(c, tmpexit, Del)) - return 0; - ADDOP(c, WITH_CLEANUP); - - /* Finally block ends. */ - ADDOP(c, END_FINALLY); - compiler_pop_fblock(c, FINALLY_END, finally); - return 1; -} - -static int -compiler_visit_expr(struct compiler *c, expr_ty e) -{ - int i, n; - - /* If expr e has a different line number than the last expr/stmt, - set a new line number for the next instruction. - */ - if (e->lineno > c->u->u_lineno) { - c->u->u_lineno = e->lineno; - c->u->u_lineno_set = false; - } - switch (e->kind) { - case BoolOp_kind: - return compiler_boolop(c, e); - case BinOp_kind: - VISIT(c, expr, e->v.BinOp.left); - VISIT(c, expr, e->v.BinOp.right); - ADDOP(c, binop(c, e->v.BinOp.op)); - break; - case UnaryOp_kind: - VISIT(c, expr, e->v.UnaryOp.operand); - ADDOP(c, unaryop(e->v.UnaryOp.op)); - break; - case Lambda_kind: - return compiler_lambda(c, e); - case IfExp_kind: - return compiler_ifexp(c, e); - case Dict_kind: - /* XXX get rid of arg? */ - ADDOP_I(c, BUILD_MAP, 0); - n = asdl_seq_LEN(e->v.Dict.values); - /* We must arrange things just right for STORE_SUBSCR. - It wants the stack to look like (value) (dict) (key) */ - for (i = 0; i < n; i++) { - ADDOP(c, DUP_TOP); - VISIT(c, expr, - (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); - ADDOP(c, ROT_TWO); - VISIT(c, expr, - (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); - ADDOP(c, STORE_SUBSCR); - } - break; - case ListComp_kind: - return compiler_listcomp(c, e); - case GeneratorExp_kind: - return compiler_genexp(c, e); - case Yield_kind: - if (c->u->u_ste->ste_type != FunctionBlock) - return compiler_error(c, "'yield' outside function"); - /* - for (i = 0; i < c->u->u_nfblocks; i++) { - if (c->u->u_fblock[i].fb_type == FINALLY_TRY) - return compiler_error( - c, "'yield' not allowed in a 'try' " - "block with a 'finally' clause"); - } - */ - if (e->v.Yield.value) { - VISIT(c, expr, e->v.Yield.value); - } - else { - ADDOP_O(c, LOAD_CONST, Py_None, consts); - } - ADDOP(c, YIELD_VALUE); - break; - case Compare_kind: - return compiler_compare(c, e); - case Call_kind: - return compiler_call(c, e); - case Repr_kind: - VISIT(c, expr, e->v.Repr.value); - ADDOP(c, UNARY_CONVERT); - break; - case Num_kind: - ADDOP_O(c, LOAD_CONST, e->v.Num.n, consts); - break; - case Str_kind: - ADDOP_O(c, LOAD_CONST, e->v.Str.s, consts); - break; - /* The following exprs can be assignment targets. */ - case Attribute_kind: - if (e->v.Attribute.ctx != AugStore) - VISIT(c, expr, e->v.Attribute.value); - switch (e->v.Attribute.ctx) { - case AugLoad: - ADDOP(c, DUP_TOP); - /* Fall through to load */ - case Load: - ADDOP_NAME(c, LOAD_ATTR, e->v.Attribute.attr, names); - break; - case AugStore: - ADDOP(c, ROT_TWO); - /* Fall through to save */ - case Store: - ADDOP_NAME(c, STORE_ATTR, e->v.Attribute.attr, names); - break; - case Del: - ADDOP_NAME(c, DELETE_ATTR, e->v.Attribute.attr, names); - break; - case Param: - default: - PyErr_SetString(PyExc_SystemError, - "param invalid in attribute expression"); - return 0; - } - break; - case Subscript_kind: - switch (e->v.Subscript.ctx) { - case AugLoad: - VISIT(c, expr, e->v.Subscript.value); - VISIT_SLICE(c, e->v.Subscript.slice, AugLoad); - break; - case Load: - VISIT(c, expr, e->v.Subscript.value); - VISIT_SLICE(c, e->v.Subscript.slice, Load); - break; - case AugStore: - VISIT_SLICE(c, e->v.Subscript.slice, AugStore); - break; - case Store: - VISIT(c, expr, e->v.Subscript.value); - VISIT_SLICE(c, e->v.Subscript.slice, Store); - break; - case Del: - VISIT(c, expr, e->v.Subscript.value); - VISIT_SLICE(c, e->v.Subscript.slice, Del); - break; - case Param: - default: - PyErr_SetString(PyExc_SystemError, - "param invalid in subscript expression"); - return 0; - } - break; - case Name_kind: - return compiler_nameop(c, e->v.Name.id, e->v.Name.ctx); - /* child nodes of List and Tuple will have expr_context set */ - case List_kind: - return compiler_list(c, e); - case Tuple_kind: - return compiler_tuple(c, e); - } - return 1; -} - -static int -compiler_augassign(struct compiler *c, stmt_ty s) -{ - expr_ty e = s->v.AugAssign.target; - expr_ty auge; - - assert(s->kind == AugAssign_kind); - - switch (e->kind) { - case Attribute_kind: - auge = Attribute(e->v.Attribute.value, e->v.Attribute.attr, - AugLoad, e->lineno, e->col_offset, c->c_arena); - if (auge == NULL) - return 0; - VISIT(c, expr, auge); - VISIT(c, expr, s->v.AugAssign.value); - ADDOP(c, inplace_binop(c, s->v.AugAssign.op)); - auge->v.Attribute.ctx = AugStore; - VISIT(c, expr, auge); - break; - case Subscript_kind: - auge = Subscript(e->v.Subscript.value, e->v.Subscript.slice, - AugLoad, e->lineno, e->col_offset, c->c_arena); - if (auge == NULL) - return 0; - VISIT(c, expr, auge); - VISIT(c, expr, s->v.AugAssign.value); - ADDOP(c, inplace_binop(c, s->v.AugAssign.op)); - auge->v.Subscript.ctx = AugStore; - VISIT(c, expr, auge); - break; - case Name_kind: - if (!compiler_nameop(c, e->v.Name.id, Load)) - return 0; - VISIT(c, expr, s->v.AugAssign.value); - ADDOP(c, inplace_binop(c, s->v.AugAssign.op)); - return compiler_nameop(c, e->v.Name.id, Store); - default: - PyErr_Format(PyExc_SystemError, - "invalid node type (%d) for augmented assignment", - e->kind); - return 0; - } - return 1; -} - -static int -compiler_push_fblock(struct compiler *c, enum fblocktype t, basicblock *b) -{ - struct fblockinfo *f; - if (c->u->u_nfblocks >= CO_MAXBLOCKS) { - PyErr_SetString(PyExc_SystemError, - "too many statically nested blocks"); - return 0; - } - f = &c->u->u_fblock[c->u->u_nfblocks++]; - f->fb_type = t; - f->fb_block = b; - return 1; -} - -static void -compiler_pop_fblock(struct compiler *c, enum fblocktype t, basicblock *b) -{ - struct compiler_unit *u = c->u; - assert(u->u_nfblocks > 0); - u->u_nfblocks--; - assert(u->u_fblock[u->u_nfblocks].fb_type == t); - assert(u->u_fblock[u->u_nfblocks].fb_block == b); -} - -static int -compiler_in_loop(struct compiler *c) { - int i; - struct compiler_unit *u = c->u; - for (i = 0; i < u->u_nfblocks; ++i) { - if (u->u_fblock[i].fb_type == LOOP) - return 1; - } - return 0; -} -/* Raises a SyntaxError and returns 0. - If something goes wrong, a different exception may be raised. -*/ - -static int -compiler_error(struct compiler *c, const char *errstr) -{ - PyObject *loc; - PyObject *u = NULL, *v = NULL; - - loc = PyErr_ProgramText(c->c_filename, c->u->u_lineno); - if (!loc) { - Py_INCREF(Py_None); - loc = Py_None; - } - u = Py_BuildValue("(ziOO)", c->c_filename, c->u->u_lineno, - Py_None, loc); - if (!u) - goto exit; - v = Py_BuildValue("(zO)", errstr, u); - if (!v) - goto exit; - PyErr_SetObject(PyExc_SyntaxError, v); - exit: - Py_DECREF(loc); - Py_XDECREF(u); - Py_XDECREF(v); - return 0; -} - -static int -compiler_handle_subscr(struct compiler *c, const char *kind, - expr_context_ty ctx) -{ - int op = 0; - - /* XXX this code is duplicated */ - switch (ctx) { - case AugLoad: /* fall through to Load */ - case Load: op = BINARY_SUBSCR; break; - case AugStore:/* fall through to Store */ - case Store: op = STORE_SUBSCR; break; - case Del: op = DELETE_SUBSCR; break; - case Param: - PyErr_Format(PyExc_SystemError, - "invalid %s kind %d in subscript\n", - kind, ctx); - return 0; - } - if (ctx == AugLoad) { - ADDOP_I(c, DUP_TOPX, 2); - } - else if (ctx == AugStore) { - ADDOP(c, ROT_THREE); - } - ADDOP(c, op); - return 1; -} - -static int -compiler_slice(struct compiler *c, slice_ty s, expr_context_ty ctx) -{ - int n = 2; - assert(s->kind == Slice_kind); - - /* only handles the cases where BUILD_SLICE is emitted */ - if (s->v.Slice.lower) { - VISIT(c, expr, s->v.Slice.lower); - } - else { - ADDOP_O(c, LOAD_CONST, Py_None, consts); - } - - if (s->v.Slice.upper) { - VISIT(c, expr, s->v.Slice.upper); - } - else { - ADDOP_O(c, LOAD_CONST, Py_None, consts); - } - - if (s->v.Slice.step) { - n++; - VISIT(c, expr, s->v.Slice.step); - } - ADDOP_I(c, BUILD_SLICE, n); - return 1; -} - -static int -compiler_simple_slice(struct compiler *c, slice_ty s, expr_context_ty ctx) -{ - int op = 0, slice_offset = 0, stack_count = 0; - - assert(s->v.Slice.step == NULL); - if (s->v.Slice.lower) { - slice_offset++; - stack_count++; - if (ctx != AugStore) - VISIT(c, expr, s->v.Slice.lower); - } - if (s->v.Slice.upper) { - slice_offset += 2; - stack_count++; - if (ctx != AugStore) - VISIT(c, expr, s->v.Slice.upper); - } - - if (ctx == AugLoad) { - switch (stack_count) { - case 0: ADDOP(c, DUP_TOP); break; - case 1: ADDOP_I(c, DUP_TOPX, 2); break; - case 2: ADDOP_I(c, DUP_TOPX, 3); break; - } - } - else if (ctx == AugStore) { - switch (stack_count) { - case 0: ADDOP(c, ROT_TWO); break; - case 1: ADDOP(c, ROT_THREE); break; - case 2: ADDOP(c, ROT_FOUR); break; - } - } - - switch (ctx) { - case AugLoad: /* fall through to Load */ - case Load: op = SLICE; break; - case AugStore:/* fall through to Store */ - case Store: op = STORE_SLICE; break; - case Del: op = DELETE_SLICE; break; - case Param: - default: - PyErr_SetString(PyExc_SystemError, - "param invalid in simple slice"); - return 0; - } - - ADDOP(c, op + slice_offset); - return 1; -} - -static int -compiler_visit_nested_slice(struct compiler *c, slice_ty s, - expr_context_ty ctx) -{ - switch (s->kind) { - case Ellipsis_kind: - ADDOP_O(c, LOAD_CONST, Py_Ellipsis, consts); - break; - case Slice_kind: - return compiler_slice(c, s, ctx); - case Index_kind: - VISIT(c, expr, s->v.Index.value); - break; - case ExtSlice_kind: - default: - PyErr_SetString(PyExc_SystemError, - "extended slice invalid in nested slice"); - return 0; - } - return 1; -} - - -static int -compiler_visit_slice(struct compiler *c, slice_ty s, expr_context_ty ctx) -{ - char * kindname = NULL; - switch (s->kind) { - case Index_kind: - kindname = "index"; - if (ctx != AugStore) { - VISIT(c, expr, s->v.Index.value); - } - break; - case Ellipsis_kind: - kindname = "ellipsis"; - if (ctx != AugStore) { - ADDOP_O(c, LOAD_CONST, Py_Ellipsis, consts); - } - break; - case Slice_kind: - kindname = "slice"; - if (!s->v.Slice.step) - return compiler_simple_slice(c, s, ctx); - if (ctx != AugStore) { - if (!compiler_slice(c, s, ctx)) - return 0; - } - break; - case ExtSlice_kind: - kindname = "extended slice"; - if (ctx != AugStore) { - int i, n = asdl_seq_LEN(s->v.ExtSlice.dims); - for (i = 0; i < n; i++) { - slice_ty sub = (slice_ty)asdl_seq_GET( - s->v.ExtSlice.dims, i); - if (!compiler_visit_nested_slice(c, sub, ctx)) - return 0; - } - ADDOP_I(c, BUILD_TUPLE, n); - } - break; - default: - PyErr_Format(PyExc_SystemError, - "invalid subscript kind %d", s->kind); - return 0; - } - return compiler_handle_subscr(c, kindname, ctx); -} - -/* do depth-first search of basic block graph, starting with block. - post records the block indices in post-order. - - XXX must handle implicit jumps from one block to next -*/ - -static void -dfs(struct compiler *c, basicblock *b, struct assembler *a) -{ - int i; - struct instr *instr = NULL; - - if (b->b_seen) - return; - b->b_seen = 1; - if (b->b_next != NULL) - dfs(c, b->b_next, a); - for (i = 0; i < b->b_iused; i++) { - instr = &b->b_instr[i]; - if (instr->i_jrel || instr->i_jabs) - dfs(c, instr->i_target, a); - } - a->a_postorder[a->a_nblocks++] = b; -} - -static int -stackdepth_walk(struct compiler *c, basicblock *b, int depth, int maxdepth) -{ - int i; - struct instr *instr; - if (b->b_seen || b->b_startdepth >= depth) - return maxdepth; - b->b_seen = 1; - b->b_startdepth = depth; - for (i = 0; i < b->b_iused; i++) { - instr = &b->b_instr[i]; - depth += opcode_stack_effect(instr->i_opcode, instr->i_oparg); - if (depth > maxdepth) - maxdepth = depth; - assert(depth >= 0); /* invalid code or bug in stackdepth() */ - if (instr->i_jrel || instr->i_jabs) { - maxdepth = stackdepth_walk(c, instr->i_target, - depth, maxdepth); - if (instr->i_opcode == JUMP_ABSOLUTE || - instr->i_opcode == JUMP_FORWARD) { - goto out; /* remaining code is dead */ - } - } - } - if (b->b_next) - maxdepth = stackdepth_walk(c, b->b_next, depth, maxdepth); -out: - b->b_seen = 0; - return maxdepth; -} - -/* Find the flow path that needs the largest stack. We assume that - * cycles in the flow graph have no net effect on the stack depth. - */ -static int -stackdepth(struct compiler *c) -{ - basicblock *b, *entryblock; - entryblock = NULL; - for (b = c->u->u_blocks; b != NULL; b = b->b_list) { - b->b_seen = 0; - b->b_startdepth = INT_MIN; - entryblock = b; - } - if (!entryblock) - return 0; - return stackdepth_walk(c, entryblock, 0, 0); -} - -static int -assemble_init(struct assembler *a, int nblocks, int firstlineno) -{ - memset(a, 0, sizeof(struct assembler)); - a->a_lineno = firstlineno; - a->a_bytecode = PyString_FromStringAndSize(NULL, DEFAULT_CODE_SIZE); - if (!a->a_bytecode) - return 0; - a->a_lnotab = PyString_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE); - if (!a->a_lnotab) - return 0; - a->a_postorder = (basicblock **)PyObject_Malloc( - sizeof(basicblock *) * nblocks); - if (!a->a_postorder) { - PyErr_NoMemory(); - return 0; - } - return 1; -} - -static void -assemble_free(struct assembler *a) -{ - Py_XDECREF(a->a_bytecode); - Py_XDECREF(a->a_lnotab); - if (a->a_postorder) - PyObject_Free(a->a_postorder); -} - -/* Return the size of a basic block in bytes. */ - -static int -instrsize(struct instr *instr) -{ - if (!instr->i_hasarg) - return 1; - if (instr->i_oparg > 0xffff) - return 6; - return 3; -} - -static int -blocksize(basicblock *b) -{ - int i; - int size = 0; - - for (i = 0; i < b->b_iused; i++) - size += instrsize(&b->b_instr[i]); - return size; -} - -/* All about a_lnotab. - -c_lnotab is an array of unsigned bytes disguised as a Python string. -It is used to map bytecode offsets to source code line #s (when needed -for tracebacks). - -The array is conceptually a list of - (bytecode offset increment, line number increment) -pairs. The details are important and delicate, best illustrated by example: - - byte code offset source code line number - 0 1 - 6 2 - 50 7 - 350 307 - 361 308 - -The first trick is that these numbers aren't stored, only the increments -from one row to the next (this doesn't really work, but it's a start): - - 0, 1, 6, 1, 44, 5, 300, 300, 11, 1 - -The second trick is that an unsigned byte can't hold negative values, or -values larger than 255, so (a) there's a deep assumption that byte code -offsets and their corresponding line #s both increase monotonically, and (b) -if at least one column jumps by more than 255 from one row to the next, more -than one pair is written to the table. In case #b, there's no way to know -from looking at the table later how many were written. That's the delicate -part. A user of c_lnotab desiring to find the source line number -corresponding to a bytecode address A should do something like this - - lineno = addr = 0 - for addr_incr, line_incr in c_lnotab: - addr += addr_incr - if addr > A: - return lineno - lineno += line_incr - -In order for this to work, when the addr field increments by more than 255, -the line # increment in each pair generated must be 0 until the remaining addr -increment is < 256. So, in the example above, assemble_lnotab (it used -to be called com_set_lineno) should not (as was actually done until 2.2) -expand 300, 300 to 255, 255, 45, 45, - but to 255, 0, 45, 255, 0, 45. -*/ - -static int -assemble_lnotab(struct assembler *a, struct instr *i) -{ - int d_bytecode, d_lineno; - int len; - unsigned char *lnotab; - - d_bytecode = a->a_offset - a->a_lineno_off; - d_lineno = i->i_lineno - a->a_lineno; - - assert(d_bytecode >= 0); - assert(d_lineno >= 0); - - /* XXX(nnorwitz): is there a better way to handle this? - for loops are special, we want to be able to trace them - each time around, so we need to set an extra line number. */ - if (d_lineno == 0 && i->i_opcode != FOR_ITER) - return 1; - - if (d_bytecode > 255) { - int j, nbytes, ncodes = d_bytecode / 255; - nbytes = a->a_lnotab_off + 2 * ncodes; - len = PyString_GET_SIZE(a->a_lnotab); - if (nbytes >= len) { - if (len * 2 < nbytes) - len = nbytes; - else - len *= 2; - if (_PyString_Resize(&a->a_lnotab, len) < 0) - return 0; - } - lnotab = (unsigned char *) - PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off; - for (j = 0; j < ncodes; j++) { - *lnotab++ = 255; - *lnotab++ = 0; - } - d_bytecode -= ncodes * 255; - a->a_lnotab_off += ncodes * 2; - } - assert(d_bytecode <= 255); - if (d_lineno > 255) { - int j, nbytes, ncodes = d_lineno / 255; - nbytes = a->a_lnotab_off + 2 * ncodes; - len = PyString_GET_SIZE(a->a_lnotab); - if (nbytes >= len) { - if (len * 2 < nbytes) - len = nbytes; - else - len *= 2; - if (_PyString_Resize(&a->a_lnotab, len) < 0) - return 0; - } - lnotab = (unsigned char *) - PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off; - *lnotab++ = d_bytecode; - *lnotab++ = 255; - d_bytecode = 0; - for (j = 1; j < ncodes; j++) { - *lnotab++ = 0; - *lnotab++ = 255; - } - d_lineno -= ncodes * 255; - a->a_lnotab_off += ncodes * 2; - } - - len = PyString_GET_SIZE(a->a_lnotab); - if (a->a_lnotab_off + 2 >= len) { - if (_PyString_Resize(&a->a_lnotab, len * 2) < 0) - return 0; - } - lnotab = (unsigned char *) - PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off; - - a->a_lnotab_off += 2; - if (d_bytecode) { - *lnotab++ = d_bytecode; - *lnotab++ = d_lineno; - } - else { /* First line of a block; def stmt, etc. */ - *lnotab++ = 0; - *lnotab++ = d_lineno; - } - a->a_lineno = i->i_lineno; - a->a_lineno_off = a->a_offset; - return 1; -} - -/* assemble_emit() - Extend the bytecode with a new instruction. - Update lnotab if necessary. -*/ - -static int -assemble_emit(struct assembler *a, struct instr *i) -{ - int size, arg = 0, ext = 0; - Py_ssize_t len = PyString_GET_SIZE(a->a_bytecode); - char *code; - - size = instrsize(i); - if (i->i_hasarg) { - arg = i->i_oparg; - ext = arg >> 16; - } - if (i->i_lineno && !assemble_lnotab(a, i)) - return 0; - if (a->a_offset + size >= len) { - if (_PyString_Resize(&a->a_bytecode, len * 2) < 0) - return 0; - } - code = PyString_AS_STRING(a->a_bytecode) + a->a_offset; - a->a_offset += size; - if (size == 6) { - assert(i->i_hasarg); - *code++ = (char)EXTENDED_ARG; - *code++ = ext & 0xff; - *code++ = ext >> 8; - arg &= 0xffff; - } - *code++ = i->i_opcode; - if (i->i_hasarg) { - assert(size == 3 || size == 6); - *code++ = arg & 0xff; - *code++ = arg >> 8; - } - return 1; -} - -static void -assemble_jump_offsets(struct assembler *a, struct compiler *c) -{ - basicblock *b; - int bsize, totsize, extended_arg_count, last_extended_arg_count = 0; - int i; - - /* Compute the size of each block and fixup jump args. - Replace block pointer with position in bytecode. */ -start: - totsize = 0; - for (i = a->a_nblocks - 1; i >= 0; i--) { - b = a->a_postorder[i]; - bsize = blocksize(b); - b->b_offset = totsize; - totsize += bsize; - } - extended_arg_count = 0; - for (b = c->u->u_blocks; b != NULL; b = b->b_list) { - bsize = b->b_offset; - for (i = 0; i < b->b_iused; i++) { - struct instr *instr = &b->b_instr[i]; - /* Relative jumps are computed relative to - the instruction pointer after fetching - the jump instruction. - */ - bsize += instrsize(instr); - if (instr->i_jabs) - instr->i_oparg = instr->i_target->b_offset; - else if (instr->i_jrel) { - int delta = instr->i_target->b_offset - bsize; - instr->i_oparg = delta; - } - else - continue; - if (instr->i_oparg > 0xffff) - extended_arg_count++; - } - } - - /* XXX: This is an awful hack that could hurt performance, but - on the bright side it should work until we come up - with a better solution. - - In the meantime, should the goto be dropped in favor - of a loop? - - The issue is that in the first loop blocksize() is called - which calls instrsize() which requires i_oparg be set - appropriately. There is a bootstrap problem because - i_oparg is calculated in the second loop above. - - So we loop until we stop seeing new EXTENDED_ARGs. - The only EXTENDED_ARGs that could be popping up are - ones in jump instructions. So this should converge - fairly quickly. - */ - if (last_extended_arg_count != extended_arg_count) { - last_extended_arg_count = extended_arg_count; - goto start; - } -} - -static PyObject * -dict_keys_inorder(PyObject *dict, int offset) -{ - PyObject *tuple, *k, *v; - Py_ssize_t i, pos = 0, size = PyDict_Size(dict); - - tuple = PyTuple_New(size); - if (tuple == NULL) - return NULL; - while (PyDict_Next(dict, &pos, &k, &v)) { - i = PyInt_AS_LONG(v); - k = PyTuple_GET_ITEM(k, 0); - Py_INCREF(k); - assert((i - offset) < size); - assert((i - offset) >= 0); - PyTuple_SET_ITEM(tuple, i - offset, k); - } - return tuple; -} - -static int -compute_code_flags(struct compiler *c) -{ - PySTEntryObject *ste = c->u->u_ste; - int flags = 0, n; - if (ste->ste_type != ModuleBlock) - flags |= CO_NEWLOCALS; - if (ste->ste_type == FunctionBlock) { - if (!ste->ste_unoptimized) - flags |= CO_OPTIMIZED; - if (ste->ste_nested) - flags |= CO_NESTED; - if (ste->ste_generator) - flags |= CO_GENERATOR; - } - if (ste->ste_varargs) - flags |= CO_VARARGS; - if (ste->ste_varkeywords) - flags |= CO_VARKEYWORDS; - if (ste->ste_generator) - flags |= CO_GENERATOR; - - /* (Only) inherit compilerflags in PyCF_MASK */ - flags |= (c->c_flags->cf_flags & PyCF_MASK); - - n = PyDict_Size(c->u->u_freevars); - if (n < 0) - return -1; - if (n == 0) { - n = PyDict_Size(c->u->u_cellvars); - if (n < 0) - return -1; - if (n == 0) { - flags |= CO_NOFREE; - } - } - - return flags; -} - -static PyCodeObject * -makecode(struct compiler *c, struct assembler *a) -{ - PyObject *tmp; - PyCodeObject *co = NULL; - PyObject *consts = NULL; - PyObject *names = NULL; - PyObject *varnames = NULL; - PyObject *filename = NULL; - PyObject *name = NULL; - PyObject *freevars = NULL; - PyObject *cellvars = NULL; - PyObject *bytecode = NULL; - int nlocals, flags; - - tmp = dict_keys_inorder(c->u->u_consts, 0); - if (!tmp) - goto error; - consts = PySequence_List(tmp); /* optimize_code requires a list */ - Py_DECREF(tmp); - - names = dict_keys_inorder(c->u->u_names, 0); - varnames = dict_keys_inorder(c->u->u_varnames, 0); - if (!consts || !names || !varnames) - goto error; - - cellvars = dict_keys_inorder(c->u->u_cellvars, 0); - if (!cellvars) - goto error; - freevars = dict_keys_inorder(c->u->u_freevars, PyTuple_Size(cellvars)); - if (!freevars) - goto error; - filename = PyString_FromString(c->c_filename); - if (!filename) - goto error; - - nlocals = PyDict_Size(c->u->u_varnames); - flags = compute_code_flags(c); - if (flags < 0) - goto error; - - bytecode = optimize_code(a->a_bytecode, consts, names, a->a_lnotab); - if (!bytecode) - goto error; - - tmp = PyList_AsTuple(consts); /* PyCode_New requires a tuple */ - if (!tmp) - goto error; - Py_DECREF(consts); - consts = tmp; - - co = PyCode_New(c->u->u_argcount, nlocals, stackdepth(c), flags, - bytecode, consts, names, varnames, - freevars, cellvars, - filename, c->u->u_name, - c->u->u_firstlineno, - a->a_lnotab); - error: - Py_XDECREF(consts); - Py_XDECREF(names); - Py_XDECREF(varnames); - Py_XDECREF(filename); - Py_XDECREF(name); - Py_XDECREF(freevars); - Py_XDECREF(cellvars); - Py_XDECREF(bytecode); - return co; -} - - -/* For debugging purposes only */ -#if 0 -static void -dump_instr(const struct instr *i) -{ - const char *jrel = i->i_jrel ? "jrel " : ""; - const char *jabs = i->i_jabs ? "jabs " : ""; - char arg[128]; - - *arg = '\0'; - if (i->i_hasarg) - sprintf(arg, "arg: %d ", i->i_oparg); - - fprintf(stderr, "line: %d, opcode: %d %s%s%s\n", - i->i_lineno, i->i_opcode, arg, jabs, jrel); -} - -static void -dump_basicblock(const basicblock *b) -{ - const char *seen = b->b_seen ? "seen " : ""; - const char *b_return = b->b_return ? "return " : ""; - fprintf(stderr, "used: %d, depth: %d, offset: %d %s%s\n", - b->b_iused, b->b_startdepth, b->b_offset, seen, b_return); - if (b->b_instr) { - int i; - for (i = 0; i < b->b_iused; i++) { - fprintf(stderr, " [%02d] ", i); - dump_instr(b->b_instr + i); - } - } -} -#endif - -static PyCodeObject * -assemble(struct compiler *c, int addNone) -{ - basicblock *b, *entryblock; - struct assembler a; - int i, j, nblocks; - PyCodeObject *co = NULL; - - /* Make sure every block that falls off the end returns None. - XXX NEXT_BLOCK() isn't quite right, because if the last - block ends with a jump or return b_next shouldn't set. - */ - if (!c->u->u_curblock->b_return) { - NEXT_BLOCK(c); - if (addNone) - ADDOP_O(c, LOAD_CONST, Py_None, consts); - ADDOP(c, RETURN_VALUE); - } - - nblocks = 0; - entryblock = NULL; - for (b = c->u->u_blocks; b != NULL; b = b->b_list) { - nblocks++; - entryblock = b; - } - - /* Set firstlineno if it wasn't explicitly set. */ - if (!c->u->u_firstlineno) { - if (entryblock && entryblock->b_instr) - c->u->u_firstlineno = entryblock->b_instr->i_lineno; - else - c->u->u_firstlineno = 1; - } - if (!assemble_init(&a, nblocks, c->u->u_firstlineno)) - goto error; - dfs(c, entryblock, &a); - - /* Can't modify the bytecode after computing jump offsets. */ - assemble_jump_offsets(&a, c); - - /* Emit code in reverse postorder from dfs. */ - for (i = a.a_nblocks - 1; i >= 0; i--) { - b = a.a_postorder[i]; - for (j = 0; j < b->b_iused; j++) - if (!assemble_emit(&a, &b->b_instr[j])) - goto error; - } - - if (_PyString_Resize(&a.a_lnotab, a.a_lnotab_off) < 0) - goto error; - if (_PyString_Resize(&a.a_bytecode, a.a_offset) < 0) - goto error; - - co = makecode(c, &a); - error: - assemble_free(&a); - return co; -} diff --git a/sys/src/cmd/python/Python/dup2.c b/sys/src/cmd/python/Python/dup2.c deleted file mode 100644 index ba7413a0c..000000000 --- a/sys/src/cmd/python/Python/dup2.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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> - -#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; -} diff --git a/sys/src/cmd/python/Python/dynload_aix.c b/sys/src/cmd/python/Python/dynload_aix.c deleted file mode 100644 index 7a604f223..000000000 --- a/sys/src/cmd/python/Python/dynload_aix.c +++ /dev/null @@ -1,183 +0,0 @@ - -/* Support for dynamic loading of extension modules */ - -#include "Python.h" -#include "importdl.h" - -#include <ctype.h> /* for isdigit() */ -#include <errno.h> /* for global errno */ -#include <string.h> /* for strerror() */ -#include <stdlib.h> /* for malloc(), free() */ -#include <sys/ldr.h> - - -#ifdef AIX_GENUINE_CPLUSPLUS -#include "/usr/lpp/xlC/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 struct filedescr _PyImport_DynLoadFiletab[] = { - {".so", "rb", C_EXTENSION}, - {"module.so", "rb", C_EXTENSION}, - {0, 0} -}; - -static int -aix_getoldmodules(void **modlistptr) -{ - register ModulePtr modptr, prevmodptr; - register struct ld_info *ldiptr; - register char *ldibuf; - register int errflag, bufsize = 1024; - register unsigned int offset; - char *progname = Py_GetProgramName(); - - /* - -- Get the list of loaded modules into ld_info structures. - */ - if ((ldibuf = malloc(bufsize)) == NULL) { - PyErr_SetString(PyExc_ImportError, strerror(errno)); - return -1; - } - while ((errflag = loadquery(L_GETINFO, ldibuf, bufsize)) == -1 - && errno == ENOMEM) { - free(ldibuf); - bufsize += 1024; - if ((ldibuf = malloc(bufsize)) == NULL) { - PyErr_SetString(PyExc_ImportError, strerror(errno)); - return -1; - } - } - if (errflag == -1) { - PyErr_SetString(PyExc_ImportError, strerror(errno)); - return -1; - } - /* - -- Make the modules list from the ld_info structures. - */ - ldiptr = (struct ld_info *)ldibuf; - prevmodptr = NULL; - do { - if (strstr(progname, ldiptr->ldinfo_filename) == NULL && - strstr(ldiptr->ldinfo_filename, "python") == NULL) { - /* - -- Extract only the modules belonging to the main - -- executable + those containing "python" as a - -- substring (like the "python[version]" binary or - -- "libpython[version].a" in case it's a shared lib). - */ - offset = (unsigned int)ldiptr->ldinfo_next; - ldiptr = (struct ld_info *)((char*)ldiptr + offset); - continue; - } - if ((modptr = (ModulePtr)malloc(sizeof(Module))) == NULL) { - PyErr_SetString(PyExc_ImportError, strerror(errno)); - while (*modlistptr) { - modptr = (ModulePtr)*modlistptr; - *modlistptr = (void *)modptr->next; - free(modptr); - } - return -1; - } - modptr->entry = ldiptr->ldinfo_dataorg; - modptr->next = NULL; - if (prevmodptr == NULL) - *modlistptr = (void *)modptr; - else - prevmodptr->next = modptr; - prevmodptr = modptr; - offset = (unsigned int)ldiptr->ldinfo_next; - ldiptr = (struct ld_info *)((char*)ldiptr + offset); - } while (offset); - free(ldibuf); - return 0; -} - - -static void -aix_loaderror(const char *pathname) -{ - - char *message[1024], errbuf[1024]; - register int i,j; - - struct errtab { - int errNo; - char *errstr; - } load_errtab[] = { - {L_ERROR_TOOMANY, "too many errors, rest skipped."}, - {L_ERROR_NOLIB, "can't load library:"}, - {L_ERROR_UNDEF, "can't find symbol in library:"}, - {L_ERROR_RLDBAD, - "RLD index out of range or bad relocation type:"}, - {L_ERROR_FORMAT, "not a valid, executable xcoff file:"}, - {L_ERROR_MEMBER, - "file not an archive or does not contain requested member:"}, - {L_ERROR_TYPE, "symbol table mismatch:"}, - {L_ERROR_ALIGN, "text alignment in file is wrong."}, - {L_ERROR_SYSTEM, "System error:"}, - {L_ERROR_ERRNO, NULL} - }; - -#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0])) -#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1) - - PyOS_snprintf(errbuf, sizeof(errbuf), "from module %.200s ", pathname); - - if (!loadquery(L_GETMESSAGES, &message[0], sizeof(message))) { - ERRBUF_APPEND(strerror(errno)); - ERRBUF_APPEND("\n"); - } - for(i = 0; message[i] && *message[i]; i++) { - int nerr = atoi(message[i]); - for (j=0; j<LOAD_ERRTAB_LEN ; j++) { - if (nerr == load_errtab[j].errNo && load_errtab[j].errstr) - ERRBUF_APPEND(load_errtab[j].errstr); - } - while (isdigit(Py_CHARMASK(*message[i]))) message[i]++ ; - ERRBUF_APPEND(message[i]); - ERRBUF_APPEND("\n"); - } - errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */ - PyErr_SetString(PyExc_ImportError, errbuf); - return; -} - - -dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, - const char *pathname, FILE *fp) -{ - 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; -} diff --git a/sys/src/cmd/python/Python/dynload_atheos.c b/sys/src/cmd/python/Python/dynload_atheos.c deleted file mode 100644 index 6f4df73c3..000000000 --- a/sys/src/cmd/python/Python/dynload_atheos.c +++ /dev/null @@ -1,47 +0,0 @@ - -/* Support for dynamic loading of extension modules */ - -#include <atheos/image.h> -#include <errno.h> - -#include "Python.h" -#include "importdl.h" - - -const struct filedescr _PyImport_DynLoadFiletab[] = { - {".so", "rb", C_EXTENSION}, - {"module.so", "rb", C_EXTENSION}, - {0, 0} -}; - -dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, - const char *pathname, FILE *fp) -{ - void *p; - int lib; - char funcname[258]; - - if (Py_VerboseFlag) - printf("load_library %s\n", pathname); - - lib = load_library(pathname, 0); - if (lib < 0) { - char buf[512]; - if (Py_VerboseFlag) - perror(pathname); - PyOS_snprintf(buf, sizeof(buf), "Failed to load %.200s: %.200s", - pathname, strerror(errno)); - PyErr_SetString(PyExc_ImportError, buf); - return NULL; - } - PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname); - if (Py_VerboseFlag) - printf("get_symbol_address %s\n", funcname); - if (get_symbol_address(lib, funcname, -1, &p) < 0) { - p = NULL; - if (Py_VerboseFlag) - perror(funcname); - } - - return (dl_funcptr) p; -} diff --git a/sys/src/cmd/python/Python/dynload_beos.c b/sys/src/cmd/python/Python/dynload_beos.c deleted file mode 100644 index 5b05d6b73..000000000 --- a/sys/src/cmd/python/Python/dynload_beos.c +++ /dev/null @@ -1,254 +0,0 @@ - -/* Support for dynamic loading of extension modules */ - -#include <kernel/image.h> -#include <kernel/OS.h> -#include <stdlib.h> - -#include "Python.h" -#include "importdl.h" - -const struct filedescr _PyImport_DynLoadFiletab[] = { - {".so", "rb", C_EXTENSION}, - {"module.so", "rb", C_EXTENSION}, - {0, 0} -}; - -#if defined(MAXPATHLEN) && !defined(_SYS_PARAM_H) -#undef MAXPATHLEN -#endif - -#ifdef WITH_THREAD -#include "pythread.h" -static PyThread_type_lock beos_dyn_lock; -#endif - -static PyObject *beos_dyn_images = NULL; - -/* ---------------------------------------------------------------------- - * BeOS dynamic loading support - * - * This uses shared libraries, but BeOS has its own way of doing things - * (much easier than dlfnc.h, from the look of things). We'll use a - * Python Dictionary object to store the images_ids so we can be very - * nice and unload them when we exit. - * - * Note that this is thread-safe. Probably irrelevent, because of losing - * systems... Python probably disables threads while loading modules. - * Note the use of "probably"! Better to be safe than sorry. [chrish] - * - * As of 1.5.1 this should also work properly when you've configured - * Python without thread support; the 1.5 version required it, which wasn't - * very friendly. Note that I haven't tested it without threading... why - * would you want to avoid threads on BeOS? [chrish] - * - * As of 1.5.2, the PyImport_BeImageID() function has been removed; Donn - * tells me it's not necessary anymore because of PyCObject_Import(). - * [chrish] - */ - -/* Whack an item; the item is an image_id in disguise, so we'll call - * unload_add_on() for it. - */ -static void beos_nuke_dyn( PyObject *item ) -{ - status_t retval; - - if( item ) { - image_id id = (image_id)PyInt_AsLong( item ); - - retval = unload_add_on( id ); - } -} - -/* atexit() handler that'll call unload_add_on() for every item in the - * dictionary. - */ -static void beos_cleanup_dyn( void ) -{ - if( beos_dyn_images ) { - int idx; - int list_size; - PyObject *id_list; - -#ifdef WITH_THREAD - PyThread_acquire_lock( beos_dyn_lock, 1 ); -#endif - - id_list = PyDict_Values( beos_dyn_images ); - - list_size = PyList_Size( id_list ); - for( idx = 0; idx < list_size; idx++ ) { - PyObject *the_item; - - the_item = PyList_GetItem( id_list, idx ); - beos_nuke_dyn( the_item ); - } - - PyDict_Clear( beos_dyn_images ); - -#ifdef WITH_THREAD - PyThread_free_lock( beos_dyn_lock ); -#endif - } -} - -/* - * Initialize our dictionary, and the dictionary mutex. - */ -static void beos_init_dyn( void ) -{ - /* We're protected from a race condition here by the atomic init_count - * variable. - */ - static int32 init_count = 0; - int32 val; - - val = atomic_add( &init_count, 1 ); - if( beos_dyn_images == NULL && val == 0 ) { - beos_dyn_images = PyDict_New(); -#ifdef WITH_THREAD - beos_dyn_lock = PyThread_allocate_lock(); -#endif - atexit( beos_cleanup_dyn ); - } -} - -/* - * Add an image_id to the dictionary; the module name of the loaded image - * is the key. Note that if the key is already in the dict, we unload - * that image; this should allow reload() to work on dynamically loaded - * modules (super-keen!). - */ -static void beos_add_dyn( char *name, image_id id ) -{ - int retval; - PyObject *py_id; - - if( beos_dyn_images == NULL ) { - beos_init_dyn(); - } - -#ifdef WITH_THREAD - retval = PyThread_acquire_lock( beos_dyn_lock, 1 ); -#endif - - /* If there's already an object with this key in the dictionary, - * we're doing a reload(), so let's nuke it. - */ - py_id = PyDict_GetItemString( beos_dyn_images, name ); - if( py_id ) { - beos_nuke_dyn( py_id ); - retval = PyDict_DelItemString( beos_dyn_images, name ); - } - - py_id = PyInt_FromLong( (long)id ); - if( py_id ) { - retval = PyDict_SetItemString( beos_dyn_images, name, py_id ); - } - -#ifdef WITH_THREAD - PyThread_release_lock( beos_dyn_lock ); -#endif -} - - - -dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, - const char *pathname, FILE *fp) -{ - dl_funcptr p; - image_id the_id; - status_t retval; - char fullpath[PATH_MAX]; - char funcname[258]; - - if( Py_VerboseFlag ) { - printf( "load_add_on( %s )\n", pathname ); - } - - /* Hmm, this old bug appears to have regenerated itself; if the - * path isn't absolute, load_add_on() will fail. Reported to Be - * April 21, 1998. - */ - if( pathname[0] != '/' ) { - (void)getcwd( fullpath, PATH_MAX ); - (void)strncat( fullpath, "/", PATH_MAX ); - (void)strncat( fullpath, pathname, PATH_MAX ); - - if( Py_VerboseFlag ) { - printf( "load_add_on( %s )\n", fullpath ); - } - } else { - (void)strcpy( fullpath, pathname ); - } - - the_id = load_add_on( fullpath ); - if( the_id < B_NO_ERROR ) { - /* It's too bad load_add_on() doesn't set errno or something... - */ - char buff[256]; /* hate hard-coded string sizes... */ - - if( Py_VerboseFlag ) { - printf( "load_add_on( %s ) failed", fullpath ); - } - - if( the_id == B_ERROR ) - PyOS_snprintf( buff, sizeof(buff), - "BeOS: Failed to load %.200s", - fullpath ); - else - PyOS_snprintf( buff, sizeof(buff), - "Unknown error loading %.200s", - fullpath ); - - PyErr_SetString( PyExc_ImportError, buff ); - return NULL; - } - - PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname); - if( Py_VerboseFlag ) { - printf( "get_image_symbol( %s )\n", funcname ); - } - - retval = get_image_symbol( the_id, funcname, B_SYMBOL_TYPE_TEXT, &p ); - if( retval != B_NO_ERROR || p == NULL ) { - /* That's bad, we can't find that symbol in the module... - */ - char buff[256]; /* hate hard-coded string sizes... */ - - if( Py_VerboseFlag ) { - printf( "get_image_symbol( %s ) failed", funcname ); - } - - switch( retval ) { - case B_BAD_IMAGE_ID: - PyOS_snprintf( buff, sizeof(buff), - "can't load init function for dynamic module: " - "Invalid image ID for %.180s", fullpath ); - break; - case B_BAD_INDEX: - PyOS_snprintf( buff, sizeof(buff), - "can't load init function for dynamic module: " - "Bad index for %.180s", funcname ); - break; - default: - PyOS_snprintf( buff, sizeof(buff), - "can't load init function for dynamic module: " - "Unknown error looking up %.180s", funcname ); - break; - } - - retval = unload_add_on( the_id ); - - PyErr_SetString( PyExc_ImportError, buff ); - return NULL; - } - - /* Save the module name and image ID for later so we can clean up - * gracefully. - */ - beos_add_dyn( fqname, the_id ); - - return p; -} diff --git a/sys/src/cmd/python/Python/dynload_dl.c b/sys/src/cmd/python/Python/dynload_dl.c deleted file mode 100644 index 4675a6722..000000000 --- a/sys/src/cmd/python/Python/dynload_dl.c +++ /dev/null @@ -1,26 +0,0 @@ - -/* Support for dynamic loading of extension modules */ - -#include "dl.h" - -#include "Python.h" -#include "importdl.h" - - -extern char *Py_GetProgramName(void); - -const struct filedescr _PyImport_DynLoadFiletab[] = { - {".o", "rb", C_EXTENSION}, - {"module.o", "rb", C_EXTENSION}, - {0, 0} -}; - - -dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, - const char *pathname, FILE *fp) -{ - char funcname[258]; - - PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname); - return dl_loadmod(Py_GetProgramName(), pathname, funcname); -} diff --git a/sys/src/cmd/python/Python/dynload_hpux.c b/sys/src/cmd/python/Python/dynload_hpux.c deleted file mode 100644 index fec0826ca..000000000 --- a/sys/src/cmd/python/Python/dynload_hpux.c +++ /dev/null @@ -1,58 +0,0 @@ - -/* 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 "_init%.200s" -#else -#define FUNCNAME_PATTERN "init%.200s" -#endif - -const struct filedescr _PyImport_DynLoadFiletab[] = { - {SHLIB_EXT, "rb", C_EXTENSION}, - {"module"SHLIB_EXT, "rb", C_EXTENSION}, - {0, 0} -}; - -dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, - const char *pathname, FILE *fp) -{ - dl_funcptr p; - shl_t lib; - int flags; - char funcname[258]; - - flags = BIND_FIRST | BIND_DEFERRED; - if (Py_VerboseFlag) { - flags = BIND_FIRST | BIND_IMMEDIATE | - BIND_NONFATAL | BIND_VERBOSE; - printf("shl_load %s\n",pathname); - } - lib = shl_load(pathname, flags, 0); - /* XXX Chuck Blake once wrote that 0 should be BIND_NOSTART? */ - if (lib == NULL) { - char buf[256]; - if (Py_VerboseFlag) - perror(pathname); - PyOS_snprintf(buf, sizeof(buf), "Failed to load %.200s", - pathname); - PyErr_SetString(PyExc_ImportError, buf); - return NULL; - } - PyOS_snprintf(funcname, sizeof(funcname), FUNCNAME_PATTERN, shortname); - if (Py_VerboseFlag) - printf("shl_findsym %s\n", funcname); - if (shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p) == -1) { - shl_unload(lib); - p = NULL; - } - if (p == NULL && Py_VerboseFlag) - perror(funcname); - - return p; -} diff --git a/sys/src/cmd/python/Python/dynload_next.c b/sys/src/cmd/python/Python/dynload_next.c deleted file mode 100644 index 27df35696..000000000 --- a/sys/src/cmd/python/Python/dynload_next.c +++ /dev/null @@ -1,114 +0,0 @@ - -/* Support for dynamic loading of extension modules on Mac OS X -** All references to "NeXT" are for historical reasons. -*/ - -#include "Python.h" -#include "importdl.h" - -#include <mach-o/dyld.h> - -const struct filedescr _PyImport_DynLoadFiletab[] = { - {".so", "rb", C_EXTENSION}, - {"module.so", "rb", C_EXTENSION}, - {0, 0} -}; - -/* -** Python modules are Mach-O MH_BUNDLE files. The best way to load these -** is each in a private namespace, so you can load, say, a module bar and a -** module foo.bar. If we load everything in the global namespace the two -** initbar() symbols will conflict. -** However, it seems some extension packages depend upon being able to access -** each others' global symbols. There seems to be no way to eat our cake and -** have it, so the USE_DYLD_GLOBAL_NAMESPACE define determines which behaviour -** you get. -*/ - -#ifdef USE_DYLD_GLOBAL_NAMESPACE -#define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW|NSLINKMODULE_OPTION_RETURN_ON_ERROR -#else -#define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW| \ - NSLINKMODULE_OPTION_RETURN_ON_ERROR|NSLINKMODULE_OPTION_PRIVATE -#endif -dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, - const char *pathname, FILE *fp) -{ - dl_funcptr p = NULL; - char funcname[258]; - NSObjectFileImageReturnCode rc; - NSObjectFileImage image; - NSModule newModule; - NSSymbol theSym; - const char *errString; - char errBuf[512]; - - PyOS_snprintf(funcname, sizeof(funcname), "_init%.200s", shortname); - -#ifdef USE_DYLD_GLOBAL_NAMESPACE - if (NSIsSymbolNameDefined(funcname)) { - theSym = NSLookupAndBindSymbol(funcname); - p = (dl_funcptr)NSAddressOfSymbol(theSym); - return p; - } -#endif - rc = NSCreateObjectFileImageFromFile(pathname, &image); - switch(rc) { - default: - case NSObjectFileImageFailure: - case NSObjectFileImageFormat: - /* for these a message is printed on stderr by dyld */ - errString = "Can't create object file image"; - break; - case NSObjectFileImageSuccess: - errString = NULL; - break; - case NSObjectFileImageInappropriateFile: - errString = "Inappropriate file type for dynamic loading"; - break; - case NSObjectFileImageArch: - errString = "Wrong CPU type in object file"; - break; - case NSObjectFileImageAccess: - errString = "Can't read object file (no access)"; - break; - } - if (errString == NULL) { - newModule = NSLinkModule(image, pathname, LINKOPTIONS); - if (newModule == NULL) { - int errNo; - const char *fileName, *moreErrorStr; - NSLinkEditErrors c; - NSLinkEditError( &c, &errNo, &fileName, &moreErrorStr ); - PyOS_snprintf(errBuf, 512, "Failure linking new module: %s: %s", - fileName, moreErrorStr); - errString = errBuf; - } - } - if (errString != NULL) { - PyErr_SetString(PyExc_ImportError, errString); - return NULL; - } -#ifdef USE_DYLD_GLOBAL_NAMESPACE - if (!NSIsSymbolNameDefined(funcname)) { - /* UnlinkModule() isn't implemented in current versions, but calling it does no harm */ - /* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */ - PyErr_Format(PyExc_ImportError, - "Loaded module does not contain symbol %.200s", - funcname); - return NULL; - } - theSym = NSLookupAndBindSymbol(funcname); -#else - theSym = NSLookupSymbolInModule(newModule, funcname); - if ( theSym == NULL ) { - /* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */ - PyErr_Format(PyExc_ImportError, - "Loaded module does not contain symbol %.200s", - funcname); - return NULL; - } -#endif - p = (dl_funcptr)NSAddressOfSymbol(theSym); - return p; -} diff --git a/sys/src/cmd/python/Python/dynload_os2.c b/sys/src/cmd/python/Python/dynload_os2.c deleted file mode 100644 index d660e2750..000000000 --- a/sys/src/cmd/python/Python/dynload_os2.c +++ /dev/null @@ -1,46 +0,0 @@ - -/* Support for dynamic loading of extension modules */ - -#define INCL_DOSERRORS -#define INCL_DOSMODULEMGR -#include <os2.h> - -#include "Python.h" -#include "importdl.h" - - -const struct filedescr _PyImport_DynLoadFiletab[] = { - {".pyd", "rb", C_EXTENSION}, - {".dll", "rb", C_EXTENSION}, - {0, 0} -}; - -dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, - const char *pathname, FILE *fp) -{ - dl_funcptr p; - APIRET rc; - HMODULE hDLL; - char failreason[256]; - char funcname[258]; - - rc = DosLoadModule(failreason, - sizeof(failreason), - pathname, - &hDLL); - - if (rc != NO_ERROR) { - char errBuf[256]; - PyOS_snprintf(errBuf, sizeof(errBuf), - "DLL load failed, rc = %d: %.200s", - rc, failreason); - PyErr_SetString(PyExc_ImportError, errBuf); - return NULL; - } - - PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname); - rc = DosQueryProcAddr(hDLL, 0L, funcname, &p); - if (rc != NO_ERROR) - p = NULL; /* Signify Failure to Acquire Entrypoint */ - return p; -} diff --git a/sys/src/cmd/python/Python/dynload_shlib.c b/sys/src/cmd/python/Python/dynload_shlib.c deleted file mode 100644 index f12a93cb5..000000000 --- a/sys/src/cmd/python/Python/dynload_shlib.c +++ /dev/null @@ -1,143 +0,0 @@ - -/* Support for dynamic loading of extension modules */ - -#include "Python.h" -#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> -#else -#if defined(PYOS_OS2) && defined(PYCC_GCC) -#include "dlfcn.h" -#endif -#endif - -#if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__) -#define LEAD_UNDERSCORE "_" -#else -#define LEAD_UNDERSCORE "" -#endif - - -const struct filedescr _PyImport_DynLoadFiletab[] = { -#ifdef __CYGWIN__ - {".dll", "rb", C_EXTENSION}, - {"module.dll", "rb", C_EXTENSION}, -#else -#if defined(PYOS_OS2) && defined(PYCC_GCC) - {".pyd", "rb", C_EXTENSION}, - {".dll", "rb", C_EXTENSION}, -#else -#ifdef __VMS - {".exe", "rb", C_EXTENSION}, - {".EXE", "rb", C_EXTENSION}, - {"module.exe", "rb", C_EXTENSION}, - {"MODULE.EXE", "rb", C_EXTENSION}, -#else - {".so", "rb", C_EXTENSION}, - {"module.so", "rb", C_EXTENSION}, -#endif -#endif -#endif - {0, 0} -}; - -static struct { - dev_t dev; -#ifdef __VMS - ino_t ino[3]; -#else - ino_t ino; -#endif - void *handle; -} handles[128]; -static int nhandles = 0; - - -dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, 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 "init%.200s", shortname); - - if (fp != NULL) { - int i; - struct stat statb; - fstat(fileno(fp), &statb); - for (i = 0; i < nhandles; i++) { - if (statb.st_dev == handles[i].dev && - statb.st_ino == handles[i].ino) { - p = (dl_funcptr) dlsym(handles[i].handle, - funcname); - return p; - } - } - if (nhandles < 128) { - handles[nhandles].dev = statb.st_dev; -#ifdef __VMS - handles[nhandles].ino[0] = statb.st_ino[0]; - handles[nhandles].ino[1] = statb.st_ino[1]; - handles[nhandles].ino[2] = statb.st_ino[2]; -#else - handles[nhandles].ino = statb.st_ino; -#endif - } - } - -#if !(defined(PYOS_OS2) && defined(PYCC_GCC)) - dlopenflags = PyThreadState_GET()->interp->dlopenflags; -#endif - - if (Py_VerboseFlag) - PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname, - dlopenflags); - -#ifdef __VMS - /* VMS currently don't allow a pathname, use a logical name instead */ - /* Concatenate 'python_module_' and shortname */ - /* so "import vms.bar" will use the logical python_module_bar */ - /* As C module use only one name space this is probably not a */ - /* important limitation */ - PyOS_snprintf(pathbuf, sizeof(pathbuf), "python_module_%-.200s", - shortname); - pathname = pathbuf; -#endif - - handle = dlopen(pathname, dlopenflags); - - if (handle == NULL) { - const char *error = dlerror(); - if (error == NULL) - error = "unknown dlopen() error"; - PyErr_SetString(PyExc_ImportError, error); - return NULL; - } - if (fp != NULL && nhandles < 128) - handles[nhandles++].handle = handle; - p = (dl_funcptr) dlsym(handle, funcname); - return p; -} diff --git a/sys/src/cmd/python/Python/dynload_stub.c b/sys/src/cmd/python/Python/dynload_stub.c deleted file mode 100644 index 69f8b450b..000000000 --- a/sys/src/cmd/python/Python/dynload_stub.c +++ /dev/null @@ -1,11 +0,0 @@ - -/* This module provides the necessary stubs for when dynamic loading is - not present. */ - -#include "Python.h" -#include "importdl.h" - - -const struct filedescr _PyImport_DynLoadFiletab[] = { - {0, 0} -}; diff --git a/sys/src/cmd/python/Python/dynload_win.c b/sys/src/cmd/python/Python/dynload_win.c deleted file mode 100644 index 37d6d2ee3..000000000 --- a/sys/src/cmd/python/Python/dynload_win.c +++ /dev/null @@ -1,263 +0,0 @@ - -/* Support for dynamic loading of extension modules */ - -#include <windows.h> -#ifdef HAVE_DIRECT_H -#include <direct.h> -#endif -#include <ctype.h> - -#include "Python.h" -#include "importdl.h" - -const struct filedescr _PyImport_DynLoadFiletab[] = { -#ifdef _DEBUG - {"_d.pyd", "rb", C_EXTENSION}, - /* Temporarily disable .dll, to avoid conflicts between sqlite3.dll - and the sqlite3 package. If this needs to be reverted for 2.5, - some other solution for the naming conflict must be found. - {"_d.dll", "rb", C_EXTENSION}, - */ -#else - {".pyd", "rb", C_EXTENSION}, - /* Likewise - {".dll", "rb", C_EXTENSION}, - */ -#endif - {0, 0} -}; - - -/* Case insensitive string compare, to avoid any dependencies on particular - C RTL implementations */ - -static int strcasecmp (char *string1, char *string2) -{ - int first, second; - - do { - first = tolower(*string1); - second = tolower(*string2); - string1++; - string2++; - } while (first && first == second); - - return (first - second); -} - - -/* 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; - - /* 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_GetDynLoadFunc(const char *fqname, const char *shortname, - const char *pathname, FILE *fp) -{ - dl_funcptr p; - char funcname[258], *import_python; - - PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname); - - { - HINSTANCE hDLL = NULL; - char pathbuf[260]; - LPTSTR dummy; - /* We use LoadLibraryEx so Windows looks for dependent DLLs - in directory of pathname first. However, Windows95 - can sometimes not work correctly unless the absolute - path is used. If GetFullPathName() fails, the LoadLibrary - will certainly fail too, so use its error code */ - if (GetFullPathName(pathname, - sizeof(pathbuf), - pathbuf, - &dummy)) - /* XXX This call doesn't exist in Windows CE */ - hDLL = LoadLibraryEx(pathname, NULL, - LOAD_WITH_ALTERED_SEARCH_PATH); - if (hDLL==NULL){ - char errBuf[256]; - unsigned int errorCode; - - /* Get an error string from Win32 error code */ - char theInfo[256]; /* Pointer to error text - from system */ - int theLength; /* Length of error text */ - - errorCode = GetLastError(); - - theLength = FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM, /* flags */ - NULL, /* message source */ - errorCode, /* the message (error) ID */ - 0, /* default language environment */ - (LPTSTR) theInfo, /* the buffer */ - sizeof(theInfo), /* the buffer size */ - NULL); /* no additional format args. */ - - /* Problem: could not get the error message. - This should not happen if called correctly. */ - if (theLength == 0) { - PyOS_snprintf(errBuf, sizeof(errBuf), - "DLL load failed with error code %d", - errorCode); - } else { - size_t len; - /* 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'; - } - strcpy(errBuf, "DLL load failed: "); - len = strlen(errBuf); - strncpy(errBuf+len, theInfo, - sizeof(errBuf)-len); - errBuf[sizeof(errBuf)-1] = '\0'; - } - PyErr_SetString(PyExc_ImportError, errBuf); - return NULL; - } else { - char buffer[256]; - -#ifdef _DEBUG - PyOS_snprintf(buffer, sizeof(buffer), "python%d%d_d.dll", -#else - PyOS_snprintf(buffer, sizeof(buffer), "python%d%d.dll", -#endif - PY_MAJOR_VERSION,PY_MINOR_VERSION); - import_python = GetPythonImport(hDLL); - - if (import_python && - strcasecmp(buffer,import_python)) { - PyOS_snprintf(buffer, sizeof(buffer), - "Module use of %.150s conflicts " - "with this version of Python.", - import_python); - PyErr_SetString(PyExc_ImportError,buffer); - FreeLibrary(hDLL); - return NULL; - } - } - p = GetProcAddress(hDLL, funcname); - } - - return p; -} diff --git a/sys/src/cmd/python/Python/errors.c b/sys/src/cmd/python/Python/errors.c deleted file mode 100644 index bc77c3c1b..000000000 --- a/sys/src/cmd/python/Python/errors.c +++ /dev/null @@ -1,822 +0,0 @@ - -/* Error handling */ - -#include "Python.h" - -#ifndef __STDC__ -#ifndef MS_WINDOWS -extern char *strerror(int); -#endif -#endif - -#ifdef MS_WINDOWS -#include "windows.h" -#include "winbase.h" -#endif - -#include <ctype.h> - -#ifdef __cplusplus -extern "C" { -#endif - - -void -PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback) -{ - PyThreadState *tstate = PyThreadState_GET(); - PyObject *oldtype, *oldvalue, *oldtraceback; - - if (traceback != NULL && !PyTraceBack_Check(traceback)) { - /* XXX Should never happen -- fatal error instead? */ - /* Well, it could be None. */ - Py_DECREF(traceback); - traceback = NULL; - } - - /* Save these in locals to safeguard against recursive - invocation through Py_XDECREF */ - oldtype = tstate->curexc_type; - oldvalue = tstate->curexc_value; - oldtraceback = tstate->curexc_traceback; - - tstate->curexc_type = type; - tstate->curexc_value = value; - tstate->curexc_traceback = traceback; - - Py_XDECREF(oldtype); - Py_XDECREF(oldvalue); - Py_XDECREF(oldtraceback); -} - -void -PyErr_SetObject(PyObject *exception, PyObject *value) -{ - Py_XINCREF(exception); - Py_XINCREF(value); - PyErr_Restore(exception, value, (PyObject *)NULL); -} - -void -PyErr_SetNone(PyObject *exception) -{ - PyErr_SetObject(exception, (PyObject *)NULL); -} - -void -PyErr_SetString(PyObject *exception, const char *string) -{ - PyObject *value = PyString_FromString(string); - PyErr_SetObject(exception, value); - Py_XDECREF(value); -} - - -PyObject * -PyErr_Occurred(void) -{ - PyThreadState *tstate = PyThreadState_GET(); - - return tstate->curexc_type; -} - - -int -PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc) -{ - if (err == NULL || exc == NULL) { - /* maybe caused by "import exceptions" that failed early on */ - return 0; - } - if (PyTuple_Check(exc)) { - Py_ssize_t i, n; - n = PyTuple_Size(exc); - for (i = 0; i < n; i++) { - /* Test recursively */ - if (PyErr_GivenExceptionMatches( - err, PyTuple_GET_ITEM(exc, i))) - { - return 1; - } - } - return 0; - } - /* err might be an instance, so check its class. */ - if (PyExceptionInstance_Check(err)) - err = PyExceptionInstance_Class(err); - - if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) { - /* problems here!? not sure PyObject_IsSubclass expects to - be called with an exception pending... */ - return PyObject_IsSubclass(err, exc); - } - - return err == exc; -} - - -int -PyErr_ExceptionMatches(PyObject *exc) -{ - return PyErr_GivenExceptionMatches(PyErr_Occurred(), exc); -} - - -/* Used in many places to normalize a raised exception, including in - eval_code2(), do_raise(), and PyErr_Print() -*/ -void -PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb) -{ - PyObject *type = *exc; - PyObject *value = *val; - PyObject *inclass = NULL; - PyObject *initial_tb = NULL; - - if (type == NULL) { - /* There was no exception, so nothing to do. */ - return; - } - - /* If PyErr_SetNone() was used, the value will have been actually - set to NULL. - */ - if (!value) { - value = Py_None; - Py_INCREF(value); - } - - if (PyExceptionInstance_Check(value)) - inclass = PyExceptionInstance_Class(value); - - /* Normalize the exception so that if the type is a class, the - value will be an instance. - */ - if (PyExceptionClass_Check(type)) { - /* if the value was not an instance, or is not an instance - whose class is (or is derived from) type, then use the - value as an argument to instantiation of the type - class. - */ - if (!inclass || !PyObject_IsSubclass(inclass, type)) { - PyObject *args, *res; - - if (value == Py_None) - args = PyTuple_New(0); - else if (PyTuple_Check(value)) { - Py_INCREF(value); - args = value; - } - else - args = PyTuple_Pack(1, value); - - if (args == NULL) - goto finally; - res = PyEval_CallObject(type, args); - Py_DECREF(args); - if (res == NULL) - goto finally; - Py_DECREF(value); - value = res; - } - /* if the class of the instance doesn't exactly match the - class of the type, believe the instance - */ - else if (inclass != type) { - Py_DECREF(type); - type = inclass; - Py_INCREF(type); - } - } - *exc = type; - *val = value; - return; -finally: - Py_DECREF(type); - Py_DECREF(value); - /* If the new exception doesn't set a traceback and the old - exception had a traceback, use the old traceback for the - new exception. It's better than nothing. - */ - initial_tb = *tb; - PyErr_Fetch(exc, val, tb); - if (initial_tb != NULL) { - if (*tb == NULL) - *tb = initial_tb; - else - Py_DECREF(initial_tb); - } - /* normalize recursively */ - PyErr_NormalizeException(exc, val, tb); -} - - -void -PyErr_Fetch(PyObject **p_type, PyObject **p_value, PyObject **p_traceback) -{ - PyThreadState *tstate = PyThreadState_GET(); - - *p_type = tstate->curexc_type; - *p_value = tstate->curexc_value; - *p_traceback = tstate->curexc_traceback; - - tstate->curexc_type = NULL; - tstate->curexc_value = NULL; - tstate->curexc_traceback = NULL; -} - -void -PyErr_Clear(void) -{ - PyErr_Restore(NULL, NULL, NULL); -} - -/* Convenience functions to set a type error exception and return 0 */ - -int -PyErr_BadArgument(void) -{ - PyErr_SetString(PyExc_TypeError, - "bad argument type for built-in operation"); - return 0; -} - -PyObject * -PyErr_NoMemory(void) -{ - if (PyErr_ExceptionMatches(PyExc_MemoryError)) - /* already current */ - return NULL; - - /* raise the pre-allocated instance if it still exists */ - if (PyExc_MemoryErrorInst) - PyErr_SetObject(PyExc_MemoryError, PyExc_MemoryErrorInst); - else - /* this will probably fail since there's no memory and hee, - hee, we have to instantiate this class - */ - PyErr_SetNone(PyExc_MemoryError); - - return NULL; -} - -PyObject * -PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject) -{ - PyObject *v; - char *s; - int i = errno; -#ifdef PLAN9 - char errbuf[ERRMAX]; -#endif -#ifdef MS_WINDOWS - char *s_buf = NULL; - char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */ -#endif -#ifdef EINTR - if (i == EINTR && PyErr_CheckSignals()) - return NULL; -#endif -#ifdef PLAN9 - rerrstr(errbuf, sizeof errbuf); - s = errbuf; -#else - if (i == 0) - s = "Error"; /* Sometimes errno didn't get set */ - else -#ifndef MS_WINDOWS - s = strerror(i); -#else - { - /* Note that the Win32 errors do not lineup with the - errno error. So if the error is in the MSVC error - table, we use it, otherwise we assume it really _is_ - a Win32 error code - */ - if (i > 0 && i < _sys_nerr) { - s = _sys_errlist[i]; - } - else { - int len = FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, /* no message source */ - i, - MAKELANGID(LANG_NEUTRAL, - SUBLANG_DEFAULT), - /* Default language */ - (LPTSTR) &s_buf, - 0, /* size not used */ - NULL); /* no args */ - if (len==0) { - /* Only ever seen this in out-of-mem - situations */ - sprintf(s_small_buf, "Windows Error 0x%X", i); - s = s_small_buf; - s_buf = NULL; - } else { - s = s_buf; - /* remove trailing cr/lf and dots */ - while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.')) - s[--len] = '\0'; - } - } - } -#endif /* Unix/Windows */ -#endif /* PLAN 9*/ - if (filenameObject != NULL) - v = Py_BuildValue("(isO)", i, s, filenameObject); - else - v = Py_BuildValue("(is)", i, s); - if (v != NULL) { - PyErr_SetObject(exc, v); - Py_DECREF(v); - } -#ifdef MS_WINDOWS - LocalFree(s_buf); -#endif - return NULL; -} - - -PyObject * -PyErr_SetFromErrnoWithFilename(PyObject *exc, char *filename) -{ - PyObject *name = filename ? PyString_FromString(filename) : NULL; - PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); - Py_XDECREF(name); - return result; -} - -#ifdef Py_WIN_WIDE_FILENAMES -PyObject * -PyErr_SetFromErrnoWithUnicodeFilename(PyObject *exc, Py_UNICODE *filename) -{ - PyObject *name = filename ? - PyUnicode_FromUnicode(filename, wcslen(filename)) : - NULL; - PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); - Py_XDECREF(name); - return result; -} -#endif /* Py_WIN_WIDE_FILENAMES */ - -PyObject * -PyErr_SetFromErrno(PyObject *exc) -{ - return PyErr_SetFromErrnoWithFilenameObject(exc, NULL); -} - -#ifdef MS_WINDOWS -/* Windows specific error code handling */ -PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject( - PyObject *exc, - int ierr, - PyObject *filenameObject) -{ - int len; - char *s; - char *s_buf = NULL; /* Free via LocalFree */ - char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */ - PyObject *v; - DWORD err = (DWORD)ierr; - if (err==0) err = GetLastError(); - len = FormatMessage( - /* Error API error */ - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, /* no message source */ - err, - MAKELANGID(LANG_NEUTRAL, - SUBLANG_DEFAULT), /* Default language */ - (LPTSTR) &s_buf, - 0, /* size not used */ - NULL); /* no args */ - if (len==0) { - /* Only seen this in out of mem situations */ - sprintf(s_small_buf, "Windows Error 0x%X", err); - s = s_small_buf; - s_buf = NULL; - } else { - s = s_buf; - /* remove trailing cr/lf and dots */ - while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.')) - s[--len] = '\0'; - } - if (filenameObject != NULL) - v = Py_BuildValue("(isO)", err, s, filenameObject); - else - v = Py_BuildValue("(is)", err, s); - if (v != NULL) { - PyErr_SetObject(exc, v); - Py_DECREF(v); - } - LocalFree(s_buf); - return NULL; -} - -PyObject *PyErr_SetExcFromWindowsErrWithFilename( - PyObject *exc, - int ierr, - const char *filename) -{ - PyObject *name = filename ? PyString_FromString(filename) : NULL; - PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, - ierr, - name); - Py_XDECREF(name); - return ret; -} - -#ifdef Py_WIN_WIDE_FILENAMES -PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilename( - PyObject *exc, - int ierr, - const Py_UNICODE *filename) -{ - PyObject *name = filename ? - PyUnicode_FromUnicode(filename, wcslen(filename)) : - NULL; - PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, - ierr, - name); - Py_XDECREF(name); - return ret; -} -#endif /* Py_WIN_WIDE_FILENAMES */ - -PyObject *PyErr_SetExcFromWindowsErr(PyObject *exc, int ierr) -{ - return PyErr_SetExcFromWindowsErrWithFilename(exc, ierr, NULL); -} - -PyObject *PyErr_SetFromWindowsErr(int ierr) -{ - return PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError, - ierr, NULL); -} -PyObject *PyErr_SetFromWindowsErrWithFilename( - int ierr, - const char *filename) -{ - PyObject *name = filename ? PyString_FromString(filename) : NULL; - PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( - PyExc_WindowsError, - ierr, name); - Py_XDECREF(name); - return result; -} - -#ifdef Py_WIN_WIDE_FILENAMES -PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename( - int ierr, - const Py_UNICODE *filename) -{ - PyObject *name = filename ? - PyUnicode_FromUnicode(filename, wcslen(filename)) : - NULL; - PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( - PyExc_WindowsError, - ierr, name); - Py_XDECREF(name); - return result; -} -#endif /* Py_WIN_WIDE_FILENAMES */ -#endif /* MS_WINDOWS */ - -void -_PyErr_BadInternalCall(char *filename, int lineno) -{ - PyErr_Format(PyExc_SystemError, - "%s:%d: bad argument to internal function", - filename, lineno); -} - -/* Remove the preprocessor macro for PyErr_BadInternalCall() so that we can - export the entry point for existing object code: */ -#undef PyErr_BadInternalCall -void -PyErr_BadInternalCall(void) -{ - PyErr_Format(PyExc_SystemError, - "bad argument to internal function"); -} -#define PyErr_BadInternalCall() _PyErr_BadInternalCall(__FILE__, __LINE__) - - - -PyObject * -PyErr_Format(PyObject *exception, const char *format, ...) -{ - va_list vargs; - PyObject* string; - -#ifdef HAVE_STDARG_PROTOTYPES - va_start(vargs, format); -#else - va_start(vargs); -#endif - - string = PyString_FromFormatV(format, vargs); - PyErr_SetObject(exception, string); - Py_XDECREF(string); - va_end(vargs); - return NULL; -} - - - -PyObject * -PyErr_NewException(char *name, PyObject *base, PyObject *dict) -{ - char *dot; - PyObject *modulename = NULL; - PyObject *classname = NULL; - PyObject *mydict = NULL; - PyObject *bases = NULL; - PyObject *result = NULL; - dot = strrchr(name, '.'); - if (dot == NULL) { - PyErr_SetString(PyExc_SystemError, - "PyErr_NewException: name must be module.class"); - return NULL; - } - if (base == NULL) - base = PyExc_Exception; - if (dict == NULL) { - dict = mydict = PyDict_New(); - if (dict == NULL) - goto failure; - } - if (PyDict_GetItemString(dict, "__module__") == NULL) { - modulename = PyString_FromStringAndSize(name, - (Py_ssize_t)(dot-name)); - if (modulename == NULL) - goto failure; - if (PyDict_SetItemString(dict, "__module__", modulename) != 0) - goto failure; - } - if (PyTuple_Check(base)) { - bases = base; - /* INCREF as we create a new ref in the else branch */ - Py_INCREF(bases); - } else { - bases = PyTuple_Pack(1, base); - if (bases == NULL) - goto failure; - } - /* Create a real new-style class. */ - result = PyObject_CallFunction((PyObject *)&PyType_Type, "sOO", - dot+1, bases, dict); - failure: - Py_XDECREF(bases); - Py_XDECREF(mydict); - Py_XDECREF(classname); - Py_XDECREF(modulename); - return result; -} - -/* Call when an exception has occurred but there is no way for Python - to handle it. Examples: exception in __del__ or during GC. */ -void -PyErr_WriteUnraisable(PyObject *obj) -{ - PyObject *f, *t, *v, *tb; - PyErr_Fetch(&t, &v, &tb); - f = PySys_GetObject("stderr"); - if (f != NULL) { - PyFile_WriteString("Exception ", f); - if (t) { - PyObject* moduleName; - char* className = NULL; - if (PyExceptionClass_Check(t)) - className = PyExceptionClass_Name(t); - else if (PyString_Check(t)) - className = PyString_AS_STRING(t); - - if (className != NULL) { - char *dot = strrchr(className, '.'); - if (dot != NULL) - className = dot+1; - } - - moduleName = PyObject_GetAttrString(t, "__module__"); - if (moduleName == NULL) - PyFile_WriteString("<unknown>", f); - else { - char* modstr = PyString_AsString(moduleName); - if (modstr) - { - PyFile_WriteString(modstr, f); - PyFile_WriteString(".", f); - } - } - if (className == NULL) - PyFile_WriteString("<unknown>", f); - else - PyFile_WriteString(className, f); - if (v && v != Py_None) { - PyFile_WriteString(": ", f); - PyFile_WriteObject(v, f, 0); - } - Py_XDECREF(moduleName); - } - PyFile_WriteString(" in ", f); - PyFile_WriteObject(obj, f, 0); - PyFile_WriteString(" ignored\n", f); - PyErr_Clear(); /* Just in case */ - } - Py_XDECREF(t); - Py_XDECREF(v); - Py_XDECREF(tb); -} - -extern PyObject *PyModule_GetWarningsModule(void); - -/* Function to issue a warning message; may raise an exception. */ -int -PyErr_WarnEx(PyObject *category, const char *message, Py_ssize_t stack_level) -{ - PyObject *dict, *func = NULL; - PyObject *warnings_module = PyModule_GetWarningsModule(); - - if (warnings_module != NULL) { - dict = PyModule_GetDict(warnings_module); - if (dict != NULL) - func = PyDict_GetItemString(dict, "warn"); - } - if (func == NULL) { - PySys_WriteStderr("warning: %s\n", message); - return 0; - } - else { - PyObject *res; - - if (category == NULL) - category = PyExc_RuntimeWarning; - res = PyObject_CallFunction(func, "sOn", - message, category, stack_level); - if (res == NULL) - return -1; - Py_DECREF(res); - return 0; - } -} - -/* PyErr_Warn is only for backwards compatability and will be removed. - Use PyErr_WarnEx instead. */ - -#undef PyErr_Warn - -PyAPI_FUNC(int) -PyErr_Warn(PyObject *category, char *message) -{ - return PyErr_WarnEx(category, message, 1); -} - -/* Warning with explicit origin */ -int -PyErr_WarnExplicit(PyObject *category, const char *message, - const char *filename, int lineno, - const char *module, PyObject *registry) -{ - PyObject *mod, *dict, *func = NULL; - - mod = PyImport_ImportModule("warnings"); - if (mod != NULL) { - dict = PyModule_GetDict(mod); - func = PyDict_GetItemString(dict, "warn_explicit"); - Py_DECREF(mod); - } - if (func == NULL) { - PySys_WriteStderr("warning: %s\n", message); - return 0; - } - else { - PyObject *res; - - if (category == NULL) - category = PyExc_RuntimeWarning; - if (registry == NULL) - registry = Py_None; - res = PyObject_CallFunction(func, "sOsizO", message, category, - filename, lineno, module, registry); - if (res == NULL) - return -1; - Py_DECREF(res); - return 0; - } -} - - -/* Set file and line information for the current exception. - If the exception is not a SyntaxError, also sets additional attributes - to make printing of exceptions believe it is a syntax error. */ - -void -PyErr_SyntaxLocation(const char *filename, int lineno) -{ - PyObject *exc, *v, *tb, *tmp; - - /* add attributes for the line number and filename for the error */ - PyErr_Fetch(&exc, &v, &tb); - PyErr_NormalizeException(&exc, &v, &tb); - /* XXX check that it is, indeed, a syntax error. It might not - * be, though. */ - tmp = PyInt_FromLong(lineno); - if (tmp == NULL) - PyErr_Clear(); - else { - if (PyObject_SetAttrString(v, "lineno", tmp)) - PyErr_Clear(); - Py_DECREF(tmp); - } - if (filename != NULL) { - tmp = PyString_FromString(filename); - if (tmp == NULL) - PyErr_Clear(); - else { - if (PyObject_SetAttrString(v, "filename", tmp)) - PyErr_Clear(); - Py_DECREF(tmp); - } - - tmp = PyErr_ProgramText(filename, lineno); - if (tmp) { - if (PyObject_SetAttrString(v, "text", tmp)) - PyErr_Clear(); - Py_DECREF(tmp); - } - } - if (PyObject_SetAttrString(v, "offset", Py_None)) { - PyErr_Clear(); - } - if (exc != PyExc_SyntaxError) { - if (!PyObject_HasAttrString(v, "msg")) { - tmp = PyObject_Str(v); - if (tmp) { - if (PyObject_SetAttrString(v, "msg", tmp)) - PyErr_Clear(); - Py_DECREF(tmp); - } else { - PyErr_Clear(); - } - } - if (!PyObject_HasAttrString(v, "print_file_and_line")) { - if (PyObject_SetAttrString(v, "print_file_and_line", - Py_None)) - PyErr_Clear(); - } - } - PyErr_Restore(exc, v, tb); -} - -/* com_fetch_program_text will attempt to load the line of text that - the exception refers to. If it fails, it will return NULL but will - not set an exception. - - XXX The functionality of this function is quite similar to the - functionality in tb_displayline() in traceback.c. -*/ - -PyObject * -PyErr_ProgramText(const char *filename, int lineno) -{ - FILE *fp; - int i; - char linebuf[1000]; - - if (filename == NULL || *filename == '\0' || lineno <= 0) - return NULL; - fp = fopen(filename, "r" PY_STDIOTEXTMODE); - if (fp == NULL) - return NULL; - for (i = 0; i < lineno; i++) { - char *pLastChar = &linebuf[sizeof(linebuf) - 2]; - do { - *pLastChar = '\0'; - if (Py_UniversalNewlineFgets(linebuf, sizeof linebuf, fp, NULL) == NULL) - break; - /* fgets read *something*; if it didn't get as - far as pLastChar, it must have found a newline - or hit the end of the file; if pLastChar is \n, - it obviously found a newline; else we haven't - yet seen a newline, so must continue */ - } while (*pLastChar != '\0' && *pLastChar != '\n'); - } - fclose(fp); - if (i == lineno) { - char *p = linebuf; - while (*p == ' ' || *p == '\t' || *p == '\014') - p++; - return PyString_FromString(p); - } - return NULL; -} - -#ifdef __cplusplus -} -#endif - diff --git a/sys/src/cmd/python/Python/fmod.c b/sys/src/cmd/python/Python/fmod.c deleted file mode 100644 index 919c6cc74..000000000 --- a/sys/src/cmd/python/Python/fmod.c +++ /dev/null @@ -1,27 +0,0 @@ - -/* Portable fmod(x, y) implementation for systems that don't have it */ - -#include "pyconfig.h" - -#include "pyport.h" -#include <errno.h> - -double -fmod(double x, double y) -{ - double i, f; - - if (y == 0.0) { - errno = EDOM; - return 0.0; - } - - /* return f such that x = i*y + f for some integer i - such that |f| < |y| and f has the same sign as x */ - - i = floor(x/y); - f = x - i*y; - if ((x < 0.0) != (y < 0.0)) - f = f-y; - return f; -} diff --git a/sys/src/cmd/python/Python/frozen.c b/sys/src/cmd/python/Python/frozen.c deleted file mode 100644 index 946d626bd..000000000 --- a/sys/src/cmd/python/Python/frozen.c +++ /dev/null @@ -1,38 +0,0 @@ - -/* Dummy frozen modules initializer */ - -#include "Python.h" - -/* In order to test the support for frozen modules, by default we - define a single frozen module, __hello__. Loading it will print - some famous words... */ - -/* To regenerate this data after the bytecode or marshal format has changed, - go to ../Tools/freeze/ and freeze the hello.py file; then copy and paste - the appropriate bytes from M___main__.c. */ - -static unsigned char M___hello__[] = { - 99,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, - 0,115,9,0,0,0,100,0,0,71,72,100,1,0,83,40, - 2,0,0,0,115,14,0,0,0,72,101,108,108,111,32,119, - 111,114,108,100,46,46,46,78,40,0,0,0,0,40,0,0, - 0,0,40,0,0,0,0,40,0,0,0,0,115,8,0,0, - 0,104,101,108,108,111,46,112,121,115,1,0,0,0,63,1, - 0,0,0,115,0,0,0,0, -}; - -#define SIZE (int)sizeof(M___hello__) - -static struct _frozen _PyImport_FrozenModules[] = { - /* Test module */ - {"__hello__", M___hello__, SIZE}, - /* Test package (negative size indicates package-ness) */ - {"__phello__", M___hello__, -SIZE}, - {"__phello__.spam", M___hello__, SIZE}, - {0, 0, 0} /* sentinel */ -}; - -/* Embedding apps may change this pointer to point to their favorite - collection of frozen modules: */ - -struct _frozen *PyImport_FrozenModules = _PyImport_FrozenModules; diff --git a/sys/src/cmd/python/Python/frozenmain.c b/sys/src/cmd/python/Python/frozenmain.c deleted file mode 100644 index 397f0465c..000000000 --- a/sys/src/cmd/python/Python/frozenmain.c +++ /dev/null @@ -1,68 +0,0 @@ - -/* Python interpreter main program for frozen scripts */ - -#include "Python.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) -{ - char *p; - int n, sts; - int inspect = 0; - int unbuffered = 0; - - Py_FrozenFlag = 1; /* Suppress errors from getpath.c */ - - if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') - inspect = 1; - if ((p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0') - unbuffered = 1; - - if (unbuffered) { - setbuf(stdin, (char *)NULL); - setbuf(stdout, (char *)NULL); - setbuf(stderr, (char *)NULL); - } - -#ifdef MS_WINDOWS - PyInitFrozenExtensions(); -#endif /* MS_WINDOWS */ - Py_SetProgramName(argv[0]); - Py_Initialize(); -#ifdef MS_WINDOWS - PyWinFreeze_ExeInit(); -#endif - - if (Py_VerboseFlag) - fprintf(stderr, "Python %s\n%s\n", - Py_GetVersion(), Py_GetCopyright()); - - PySys_SetArgv(argc, argv); - - n = PyImport_ImportFrozenModule("__main__"); - if (n == 0) - Py_FatalError("__main__ not frozen"); - if (n < 0) { - PyErr_Print(); - sts = 1; - } - else - sts = 0; - - if (inspect && isatty((int)fileno(stdin))) - sts = PyRun_AnyFile(stdin, "<stdin>") != 0; - -#ifdef MS_WINDOWS - PyWinFreeze_ExeTerm(); -#endif - Py_Finalize(); - return sts; -} diff --git a/sys/src/cmd/python/Python/future.c b/sys/src/cmd/python/Python/future.c deleted file mode 100644 index 3b3ca1d7b..000000000 --- a/sys/src/cmd/python/Python/future.c +++ /dev/null @@ -1,136 +0,0 @@ -#include "Python.h" -#include "Python-ast.h" -#include "node.h" -#include "token.h" -#include "graminit.h" -#include "code.h" -#include "compile.h" -#include "symtable.h" - -#define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined" - -static int -future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename) -{ - int i; - asdl_seq *names; - - assert(s->kind == ImportFrom_kind); - - names = s->v.ImportFrom.names; - for (i = 0; i < asdl_seq_LEN(names); i++) { - alias_ty name = (alias_ty)asdl_seq_GET(names, i); - const char *feature = PyString_AsString(name->name); - if (!feature) - return 0; - if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) { - continue; - } else if (strcmp(feature, FUTURE_GENERATORS) == 0) { - continue; - } else if (strcmp(feature, FUTURE_DIVISION) == 0) { - ff->ff_features |= CO_FUTURE_DIVISION; - } else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) { - ff->ff_features |= CO_FUTURE_ABSOLUTE_IMPORT; - } else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) { - ff->ff_features |= CO_FUTURE_WITH_STATEMENT; - } else if (strcmp(feature, "braces") == 0) { - PyErr_SetString(PyExc_SyntaxError, - "not a chance"); - PyErr_SyntaxLocation(filename, s->lineno); - return 0; - } else { - PyErr_Format(PyExc_SyntaxError, - UNDEFINED_FUTURE_FEATURE, feature); - PyErr_SyntaxLocation(filename, s->lineno); - return 0; - } - } - return 1; -} - -static int -future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename) -{ - int i, found_docstring = 0, done = 0, prev_line = 0; - - static PyObject *future; - if (!future) { - future = PyString_InternFromString("__future__"); - if (!future) - return 0; - } - - if (!(mod->kind == Module_kind || mod->kind == Interactive_kind)) - return 1; - - /* A subsequent pass will detect future imports that don't - appear at the beginning of the file. There's one case, - however, that is easier to handl here: A series of imports - joined by semi-colons, where the first import is a future - statement but some subsequent import has the future form - but is preceded by a regular import. - */ - - - for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) { - stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i); - - if (done && s->lineno > prev_line) - return 1; - prev_line = s->lineno; - - /* The tests below will return from this function unless it is - still possible to find a future statement. The only things - that can precede a future statement are another future - statement and a doc string. - */ - - if (s->kind == ImportFrom_kind) { - if (s->v.ImportFrom.module == future) { - if (done) { - PyErr_SetString(PyExc_SyntaxError, - ERR_LATE_FUTURE); - PyErr_SyntaxLocation(filename, - s->lineno); - return 0; - } - if (!future_check_features(ff, s, filename)) - return 0; - ff->ff_lineno = s->lineno; - } - else - done = 1; - } - else if (s->kind == Expr_kind && !found_docstring) { - expr_ty e = s->v.Expr.value; - if (e->kind != Str_kind) - done = 1; - else - found_docstring = 1; - } - else - done = 1; - } - return 1; -} - - -PyFutureFeatures * -PyFuture_FromAST(mod_ty mod, const char *filename) -{ - PyFutureFeatures *ff; - - 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; -} diff --git a/sys/src/cmd/python/Python/getargs.c b/sys/src/cmd/python/Python/getargs.c deleted file mode 100644 index d62559863..000000000 --- a/sys/src/cmd/python/Python/getargs.c +++ /dev/null @@ -1,1771 +0,0 @@ - -/* New getargs implementation */ - -#include "Python.h" - -#include <ctype.h> - - -#ifdef __cplusplus -extern "C" { -#endif -int PyArg_Parse(PyObject *, const char *, ...); -int PyArg_ParseTuple(PyObject *, const char *, ...); -int PyArg_VaParse(PyObject *, const char *, va_list); - -int PyArg_ParseTupleAndKeywords(PyObject *, PyObject *, - const char *, char **, ...); -int PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *, - const char *, char **, va_list); - -#ifdef HAVE_DECLSPEC_DLL -/* Export functions */ -PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, char *, ...); -PyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, char *, ...); -PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywords_SizeT(PyObject *, PyObject *, - const char *, char **, ...); -PyAPI_FUNC(PyObject *) _Py_BuildValue_SizeT(const char *, ...); -PyAPI_FUNC(int) _PyArg_VaParse_SizeT(PyObject *, char *, va_list); -PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *, PyObject *, - const char *, char **, va_list); -#endif - -#define FLAG_COMPAT 1 -#define FLAG_SIZE_T 2 - - -/* Forward */ -static int vgetargs1(PyObject *, const char *, va_list *, int); -static void seterror(int, const char *, int *, const char *, const char *); -static char *convertitem(PyObject *, const char **, va_list *, int, int *, - char *, size_t, PyObject **); -static char *converttuple(PyObject *, const char **, va_list *, int, - int *, char *, size_t, int, PyObject **); -static char *convertsimple(PyObject *, const char **, va_list *, int, char *, - size_t, PyObject **); -static Py_ssize_t convertbuffer(PyObject *, void **p, char **); - -static int vgetargskeywords(PyObject *, PyObject *, - const char *, char **, va_list *, int); -static char *skipitem(const char **, va_list *, int); - -int -PyArg_Parse(PyObject *args, const char *format, ...) -{ - int retval; - va_list va; - - va_start(va, format); - retval = vgetargs1(args, format, &va, FLAG_COMPAT); - va_end(va); - return retval; -} - -int -_PyArg_Parse_SizeT(PyObject *args, char *format, ...) -{ - int retval; - va_list va; - - va_start(va, format); - retval = vgetargs1(args, format, &va, FLAG_COMPAT|FLAG_SIZE_T); - va_end(va); - return retval; -} - - -int -PyArg_ParseTuple(PyObject *args, const char *format, ...) -{ - int retval; - va_list va; - - va_start(va, format); - retval = vgetargs1(args, format, &va, 0); - va_end(va); - return retval; -} - -int -_PyArg_ParseTuple_SizeT(PyObject *args, char *format, ...) -{ - int retval; - va_list va; - - va_start(va, format); - retval = vgetargs1(args, format, &va, FLAG_SIZE_T); - va_end(va); - return retval; -} - - -int -PyArg_VaParse(PyObject *args, const char *format, va_list va) -{ - va_list lva; - -#ifdef VA_LIST_IS_ARRAY - memcpy(lva, va, sizeof(va_list)); -#else -#ifdef __va_copy - __va_copy(lva, va); -#else - lva = va; -#endif -#endif - - return vgetargs1(args, format, &lva, 0); -} - -int -_PyArg_VaParse_SizeT(PyObject *args, char *format, va_list va) -{ - va_list lva; - -#ifdef VA_LIST_IS_ARRAY - memcpy(lva, va, sizeof(va_list)); -#else -#ifdef __va_copy - __va_copy(lva, va); -#else - lva = va; -#endif -#endif - - return vgetargs1(args, format, &lva, FLAG_SIZE_T); -} - - -/* Handle cleanup of allocated memory in case of exception */ - -static int -addcleanup(void *ptr, PyObject **freelist) -{ - PyObject *cobj; - if (!*freelist) { - *freelist = PyList_New(0); - if (!*freelist) { - PyMem_FREE(ptr); - return -1; - } - } - cobj = PyCObject_FromVoidPtr(ptr, NULL); - if (!cobj) { - PyMem_FREE(ptr); - return -1; - } - if(PyList_Append(*freelist, cobj)) { - PyMem_FREE(ptr); - Py_DECREF(cobj); - return -1; - } - Py_DECREF(cobj); - return 0; -} - -static int -cleanreturn(int retval, PyObject *freelist) -{ - if(freelist) { - if((retval) == 0) { - Py_ssize_t len = PyList_GET_SIZE(freelist), i; - for (i = 0; i < len; i++) - PyMem_FREE(PyCObject_AsVoidPtr( - PyList_GET_ITEM(freelist, i))); - } - Py_DECREF(freelist); - } - return retval; -} - - -static int -vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) -{ - char msgbuf[256]; - int levels[32]; - const char *fname = NULL; - const char *message = NULL; - int min = -1; - int max = 0; - int level = 0; - int endfmt = 0; - const char *formatsave = format; - Py_ssize_t i, len; - char *msg; - PyObject *freelist = NULL; - int compat = flags & FLAG_COMPAT; - - assert(compat || (args != (PyObject*)NULL)); - flags = flags & ~FLAG_COMPAT; - - while (endfmt == 0) { - int c = *format++; - switch (c) { - case '(': - if (level == 0) - max++; - level++; - if (level >= 30) - Py_FatalError("too many tuple nesting levels " - "in argument format string"); - break; - case ')': - if (level == 0) - Py_FatalError("excess ')' in getargs format"); - else - level--; - break; - case '\0': - endfmt = 1; - break; - case ':': - fname = format; - endfmt = 1; - break; - case ';': - message = format; - endfmt = 1; - break; - default: - if (level == 0) { - if (c == 'O') - max++; - else if (isalpha(Py_CHARMASK(c))) { - if (c != 'e') /* skip encoded */ - max++; - } else if (c == '|') - min = max; - } - break; - } - } - - if (level != 0) - Py_FatalError(/* '(' */ "missing ')' in getargs format"); - - if (min < 0) - min = max; - - format = formatsave; - - if (compat) { - if (max == 0) { - if (args == NULL) - return 1; - PyOS_snprintf(msgbuf, sizeof(msgbuf), - "%.200s%s takes no arguments", - fname==NULL ? "function" : fname, - fname==NULL ? "" : "()"); - PyErr_SetString(PyExc_TypeError, msgbuf); - return 0; - } - else if (min == 1 && max == 1) { - if (args == NULL) { - PyOS_snprintf(msgbuf, sizeof(msgbuf), - "%.200s%s takes at least one argument", - fname==NULL ? "function" : fname, - fname==NULL ? "" : "()"); - PyErr_SetString(PyExc_TypeError, msgbuf); - return 0; - } - msg = convertitem(args, &format, p_va, flags, levels, - msgbuf, sizeof(msgbuf), &freelist); - if (msg == NULL) - return cleanreturn(1, freelist); - seterror(levels[0], msg, levels+1, fname, message); - return cleanreturn(0, freelist); - } - else { - PyErr_SetString(PyExc_SystemError, - "old style getargs format uses new features"); - return 0; - } - } - - if (!PyTuple_Check(args)) { - PyErr_SetString(PyExc_SystemError, - "new style getargs format but argument is not a tuple"); - return 0; - } - - len = PyTuple_GET_SIZE(args); - - if (len < min || max < len) { - if (message == NULL) { - PyOS_snprintf(msgbuf, sizeof(msgbuf), - "%.150s%s takes %s %d argument%s " - "(%ld given)", - fname==NULL ? "function" : fname, - fname==NULL ? "" : "()", - min==max ? "exactly" - : len < min ? "at least" : "at most", - len < min ? min : max, - (len < min ? min : max) == 1 ? "" : "s", - Py_SAFE_DOWNCAST(len, Py_ssize_t, long)); - message = msgbuf; - } - PyErr_SetString(PyExc_TypeError, message); - return 0; - } - - for (i = 0; i < len; i++) { - if (*format == '|') - format++; - msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va, - flags, levels, msgbuf, - sizeof(msgbuf), &freelist); - if (msg) { - seterror(i+1, msg, levels, fname, message); - return cleanreturn(0, freelist); - } - } - - if (*format != '\0' && !isalpha(Py_CHARMASK(*format)) && - *format != '(' && - *format != '|' && *format != ':' && *format != ';') { - PyErr_Format(PyExc_SystemError, - "bad format string: %.200s", formatsave); - return cleanreturn(0, freelist); - } - - return cleanreturn(1, freelist); -} - - - -static void -seterror(int iarg, const char *msg, int *levels, const char *fname, - const char *message) -{ - char buf[512]; - int i; - char *p = buf; - - if (PyErr_Occurred()) - return; - else if (message == NULL) { - if (fname != NULL) { - PyOS_snprintf(p, sizeof(buf), "%.200s() ", fname); - p += strlen(p); - } - if (iarg != 0) { - PyOS_snprintf(p, sizeof(buf) - (p - buf), - "argument %d", iarg); - i = 0; - p += strlen(p); - while (levels[i] > 0 && i < 32 && (int)(p-buf) < 220) { - PyOS_snprintf(p, sizeof(buf) - (p - buf), - ", item %d", levels[i]-1); - p += strlen(p); - i++; - } - } - else { - PyOS_snprintf(p, sizeof(buf) - (p - buf), "argument"); - p += strlen(p); - } - PyOS_snprintf(p, sizeof(buf) - (p - buf), " %.256s", msg); - message = buf; - } - PyErr_SetString(PyExc_TypeError, message); -} - - -/* Convert a tuple argument. - On entry, *p_format points to the character _after_ the opening '('. - On successful exit, *p_format points to the closing ')'. - If successful: - *p_format and *p_va are updated, - *levels and *msgbuf are untouched, - and NULL is returned. - If the argument is invalid: - *p_format is unchanged, - *p_va is undefined, - *levels is a 0-terminated list of item numbers, - *msgbuf contains an error message, whose format is: - "must be <typename1>, not <typename2>", where: - <typename1> is the name of the expected type, and - <typename2> is the name of the actual type, - and msgbuf is returned. -*/ - -static char * -converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, - int *levels, char *msgbuf, size_t bufsize, int toplevel, - PyObject **freelist) -{ - int level = 0; - int n = 0; - const char *format = *p_format; - int i; - - for (;;) { - int c = *format++; - if (c == '(') { - if (level == 0) - n++; - level++; - } - else if (c == ')') { - if (level == 0) - break; - level--; - } - else if (c == ':' || c == ';' || c == '\0') - break; - else if (level == 0 && isalpha(Py_CHARMASK(c))) - n++; - } - - if (!PySequence_Check(arg) || PyString_Check(arg)) { - levels[0] = 0; - PyOS_snprintf(msgbuf, bufsize, - toplevel ? "expected %d arguments, not %.50s" : - "must be %d-item sequence, not %.50s", - n, - arg == Py_None ? "None" : arg->ob_type->tp_name); - return msgbuf; - } - - if ((i = PySequence_Size(arg)) != n) { - levels[0] = 0; - PyOS_snprintf(msgbuf, bufsize, - toplevel ? "expected %d arguments, not %d" : - "must be sequence of length %d, not %d", - n, i); - return msgbuf; - } - - format = *p_format; - for (i = 0; i < n; i++) { - char *msg; - PyObject *item; - item = PySequence_GetItem(arg, i); - if (item == NULL) { - PyErr_Clear(); - levels[0] = i+1; - levels[1] = 0; - strncpy(msgbuf, "is not retrievable", bufsize); - return msgbuf; - } - msg = convertitem(item, &format, p_va, flags, levels+1, - msgbuf, bufsize, freelist); - /* PySequence_GetItem calls tp->sq_item, which INCREFs */ - Py_XDECREF(item); - if (msg != NULL) { - levels[0] = i+1; - return msg; - } - } - - *p_format = format; - return NULL; -} - - -/* Convert a single item. */ - -static char * -convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, - int *levels, char *msgbuf, size_t bufsize, PyObject **freelist) -{ - char *msg; - const char *format = *p_format; - - if (*format == '(' /* ')' */) { - format++; - msg = converttuple(arg, &format, p_va, flags, levels, msgbuf, - bufsize, 0, freelist); - if (msg == NULL) - format++; - } - else { - msg = convertsimple(arg, &format, p_va, flags, - msgbuf, bufsize, freelist); - if (msg != NULL) - levels[0] = 0; - } - if (msg == NULL) - *p_format = format; - return msg; -} - - - -#define UNICODE_DEFAULT_ENCODING(arg) \ - _PyUnicode_AsDefaultEncodedString(arg, NULL) - -/* Format an error message generated by convertsimple(). */ - -static char * -converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize) -{ - assert(expected != NULL); - assert(arg != NULL); - PyOS_snprintf(msgbuf, bufsize, - "must be %.50s, not %.50s", expected, - arg == Py_None ? "None" : arg->ob_type->tp_name); - return msgbuf; -} - -#define CONV_UNICODE "(unicode conversion error)" - -/* explicitly check for float arguments when integers are expected. For now - * signal a warning. Returns true if an exception was raised. */ -static int -float_argument_error(PyObject *arg) -{ - if (PyFloat_Check(arg) && - PyErr_Warn(PyExc_DeprecationWarning, - "integer argument expected, got float" )) - return 1; - else - return 0; -} - -/* Convert a non-tuple argument. Return NULL if conversion went OK, - or a string with a message describing the failure. The message is - formatted as "must be <desired type>, not <actual type>". - When failing, an exception may or may not have been raised. - Don't call if a tuple is expected. - - When you add new format codes, please don't forget poor skipitem() below. -*/ - -static char * -convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, - char *msgbuf, size_t bufsize, PyObject **freelist) -{ - /* For # codes */ -#define FETCH_SIZE int *q=NULL;Py_ssize_t *q2=NULL;\ - if (flags & FLAG_SIZE_T) q2=va_arg(*p_va, Py_ssize_t*); \ - else q=va_arg(*p_va, int*); -#define STORE_SIZE(s) if (flags & FLAG_SIZE_T) *q2=s; else *q=s; -#define BUFFER_LEN ((flags & FLAG_SIZE_T) ? *q2:*q) - - const char *format = *p_format; - char c = *format++; -#ifdef Py_USING_UNICODE - PyObject *uarg; -#endif - - switch (c) { - - case 'b': { /* unsigned byte -- very short int */ - char *p = va_arg(*p_va, char *); - long ival; - if (float_argument_error(arg)) - return converterr("integer<b>", arg, msgbuf, bufsize); - ival = PyInt_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer<b>", arg, msgbuf, bufsize); - else if (ival < 0) { - PyErr_SetString(PyExc_OverflowError, - "unsigned byte integer is less than minimum"); - return converterr("integer<b>", arg, msgbuf, bufsize); - } - else if (ival > UCHAR_MAX) { - PyErr_SetString(PyExc_OverflowError, - "unsigned byte integer is greater than maximum"); - return converterr("integer<b>", arg, msgbuf, bufsize); - } - else - *p = (unsigned char) ival; - break; - } - - case 'B': {/* byte sized bitfield - both signed and unsigned - values allowed */ - char *p = va_arg(*p_va, char *); - long ival; - if (float_argument_error(arg)) - return converterr("integer<B>", arg, msgbuf, bufsize); - ival = PyInt_AsUnsignedLongMask(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer<B>", arg, msgbuf, bufsize); - else - *p = (unsigned char) ival; - break; - } - - case 'h': {/* signed short int */ - short *p = va_arg(*p_va, short *); - long ival; - if (float_argument_error(arg)) - return converterr("integer<h>", arg, msgbuf, bufsize); - ival = PyInt_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer<h>", arg, msgbuf, bufsize); - else if (ival < SHRT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - return converterr("integer<h>", arg, msgbuf, bufsize); - } - else if (ival > SHRT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - return converterr("integer<h>", arg, msgbuf, bufsize); - } - else - *p = (short) ival; - break; - } - - case 'H': { /* short int sized bitfield, both signed and - unsigned allowed */ - unsigned short *p = va_arg(*p_va, unsigned short *); - long ival; - if (float_argument_error(arg)) - return converterr("integer<H>", arg, msgbuf, bufsize); - ival = PyInt_AsUnsignedLongMask(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer<H>", arg, msgbuf, bufsize); - else - *p = (unsigned short) ival; - break; - } - - case 'i': {/* signed int */ - int *p = va_arg(*p_va, int *); - long ival; - if (float_argument_error(arg)) - return converterr("integer<i>", arg, msgbuf, bufsize); - ival = PyInt_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer<i>", arg, msgbuf, bufsize); - else if (ival > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed integer is greater than maximum"); - return converterr("integer<i>", arg, msgbuf, bufsize); - } - else if (ival < INT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed integer is less than minimum"); - return converterr("integer<i>", arg, msgbuf, bufsize); - } - else - *p = ival; - break; - } - - case 'I': { /* int sized bitfield, both signed and - unsigned allowed */ - unsigned int *p = va_arg(*p_va, unsigned int *); - unsigned int ival; - if (float_argument_error(arg)) - return converterr("integer<I>", arg, msgbuf, bufsize); - ival = (unsigned int)PyInt_AsUnsignedLongMask(arg); - if (ival == (unsigned int)-1 && PyErr_Occurred()) - return converterr("integer<I>", arg, msgbuf, bufsize); - else - *p = ival; - break; - } - - case 'n': /* Py_ssize_t */ -#if SIZEOF_SIZE_T != SIZEOF_LONG - { - Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *); - Py_ssize_t ival; - if (float_argument_error(arg)) - return converterr("integer<n>", arg, msgbuf, bufsize); - ival = PyInt_AsSsize_t(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer<n>", arg, msgbuf, bufsize); - *p = ival; - break; - } -#endif - /* Fall through from 'n' to 'l' if Py_ssize_t is int */ - case 'l': {/* long int */ - long *p = va_arg(*p_va, long *); - long ival; - if (float_argument_error(arg)) - return converterr("integer<l>", arg, msgbuf, bufsize); - ival = PyInt_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) - return converterr("integer<l>", arg, msgbuf, bufsize); - else - *p = ival; - break; - } - - case 'k': { /* long sized bitfield */ - unsigned long *p = va_arg(*p_va, unsigned long *); - unsigned long ival; - if (PyInt_Check(arg)) - ival = PyInt_AsUnsignedLongMask(arg); - else if (PyLong_Check(arg)) - ival = PyLong_AsUnsignedLongMask(arg); - else - return converterr("integer<k>", arg, msgbuf, bufsize); - *p = ival; - break; - } - -#ifdef HAVE_LONG_LONG - case 'L': {/* PY_LONG_LONG */ - PY_LONG_LONG *p = va_arg( *p_va, PY_LONG_LONG * ); - PY_LONG_LONG ival = PyLong_AsLongLong( arg ); - if( ival == (PY_LONG_LONG)-1 && PyErr_Occurred() ) { - return converterr("long<L>", arg, msgbuf, bufsize); - } else { - *p = ival; - } - break; - } - - case 'K': { /* long long sized bitfield */ - unsigned PY_LONG_LONG *p = va_arg(*p_va, unsigned PY_LONG_LONG *); - unsigned PY_LONG_LONG ival; - if (PyInt_Check(arg)) - ival = PyInt_AsUnsignedLongMask(arg); - else if (PyLong_Check(arg)) - ival = PyLong_AsUnsignedLongLongMask(arg); - else - return converterr("integer<K>", arg, msgbuf, bufsize); - *p = ival; - break; - } -#endif - - case 'f': {/* float */ - float *p = va_arg(*p_va, float *); - double dval = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) - return converterr("float<f>", arg, msgbuf, bufsize); - else - *p = (float) dval; - break; - } - - case 'd': {/* double */ - double *p = va_arg(*p_va, double *); - double dval = PyFloat_AsDouble(arg); - if (PyErr_Occurred()) - return converterr("float<d>", arg, msgbuf, bufsize); - else - *p = dval; - break; - } - -#ifndef WITHOUT_COMPLEX - case 'D': {/* complex double */ - Py_complex *p = va_arg(*p_va, Py_complex *); - Py_complex cval; - cval = PyComplex_AsCComplex(arg); - if (PyErr_Occurred()) - return converterr("complex<D>", arg, msgbuf, bufsize); - else - *p = cval; - break; - } -#endif /* WITHOUT_COMPLEX */ - - case 'c': {/* char */ - char *p = va_arg(*p_va, char *); - if (PyString_Check(arg) && PyString_Size(arg) == 1) - *p = PyString_AS_STRING(arg)[0]; - else - return converterr("char", arg, msgbuf, bufsize); - break; - } - - case 's': {/* string */ - if (*format == '#') { - void **p = (void **)va_arg(*p_va, char **); - FETCH_SIZE; - - if (PyString_Check(arg)) { - *p = PyString_AS_STRING(arg); - STORE_SIZE(PyString_GET_SIZE(arg)); - } -#ifdef Py_USING_UNICODE - else if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyString_AS_STRING(uarg); - STORE_SIZE(PyString_GET_SIZE(uarg)); - } -#endif - else { /* any buffer-like object */ - char *buf; - Py_ssize_t count = convertbuffer(arg, p, &buf); - if (count < 0) - return converterr(buf, arg, msgbuf, bufsize); - STORE_SIZE(count); - } - format++; - } else { - char **p = va_arg(*p_va, char **); - - if (PyString_Check(arg)) - *p = PyString_AS_STRING(arg); -#ifdef Py_USING_UNICODE - else if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyString_AS_STRING(uarg); - } -#endif - else - return converterr("string", arg, msgbuf, bufsize); - if ((Py_ssize_t)strlen(*p) != PyString_Size(arg)) - return converterr("string without null bytes", - arg, msgbuf, bufsize); - } - break; - } - - case 'z': {/* string, may be NULL (None) */ - if (*format == '#') { /* any buffer-like object */ - void **p = (void **)va_arg(*p_va, char **); - FETCH_SIZE; - - if (arg == Py_None) { - *p = 0; - STORE_SIZE(0); - } - else if (PyString_Check(arg)) { - *p = PyString_AS_STRING(arg); - STORE_SIZE(PyString_GET_SIZE(arg)); - } -#ifdef Py_USING_UNICODE - else if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyString_AS_STRING(uarg); - STORE_SIZE(PyString_GET_SIZE(uarg)); - } -#endif - else { /* any buffer-like object */ - char *buf; - Py_ssize_t count = convertbuffer(arg, p, &buf); - if (count < 0) - return converterr(buf, arg, msgbuf, bufsize); - STORE_SIZE(count); - } - format++; - } else { - char **p = va_arg(*p_va, char **); - - if (arg == Py_None) - *p = 0; - else if (PyString_Check(arg)) - *p = PyString_AS_STRING(arg); -#ifdef Py_USING_UNICODE - else if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = PyString_AS_STRING(uarg); - } -#endif - else - return converterr("string or None", - arg, msgbuf, bufsize); - if (*format == '#') { - FETCH_SIZE; - assert(0); /* XXX redundant with if-case */ - if (arg == Py_None) - *q = 0; - else - *q = PyString_Size(arg); - format++; - } - else if (*p != NULL && - (Py_ssize_t)strlen(*p) != PyString_Size(arg)) - return converterr( - "string without null bytes or None", - arg, msgbuf, bufsize); - } - break; - } - - case 'e': {/* encoded string */ - char **buffer; - const char *encoding; - PyObject *s; - int size, recode_strings; - - /* Get 'e' parameter: the encoding name */ - encoding = (const char *)va_arg(*p_va, const char *); -#ifdef Py_USING_UNICODE - if (encoding == NULL) - encoding = PyUnicode_GetDefaultEncoding(); -#endif - - /* Get output buffer parameter: - 's' (recode all objects via Unicode) or - 't' (only recode non-string objects) - */ - if (*format == 's') - recode_strings = 1; - else if (*format == 't') - recode_strings = 0; - else - return converterr( - "(unknown parser marker combination)", - arg, msgbuf, bufsize); - buffer = (char **)va_arg(*p_va, char **); - format++; - if (buffer == NULL) - return converterr("(buffer is NULL)", - arg, msgbuf, bufsize); - - /* Encode object */ - if (!recode_strings && PyString_Check(arg)) { - s = arg; - Py_INCREF(s); - } - else { -#ifdef Py_USING_UNICODE - PyObject *u; - - /* Convert object to Unicode */ - u = PyUnicode_FromObject(arg); - if (u == NULL) - return converterr( - "string or unicode or text buffer", - arg, msgbuf, bufsize); - - /* Encode object; use default error handling */ - s = PyUnicode_AsEncodedString(u, - encoding, - NULL); - Py_DECREF(u); - if (s == NULL) - return converterr("(encoding failed)", - arg, msgbuf, bufsize); - if (!PyString_Check(s)) { - Py_DECREF(s); - return converterr( - "(encoder failed to return a string)", - arg, msgbuf, bufsize); - } -#else - return converterr("string<e>", arg, msgbuf, bufsize); -#endif - } - size = PyString_GET_SIZE(s); - - /* Write output; output is guaranteed to be 0-terminated */ - if (*format == '#') { - /* Using buffer length parameter '#': - - - if *buffer is NULL, a new buffer of the - needed size is allocated and the data - copied into it; *buffer is updated to point - to the new buffer; the caller is - responsible for PyMem_Free()ing it after - usage - - - if *buffer is not NULL, the data is - copied to *buffer; *buffer_len has to be - set to the size of the buffer on input; - buffer overflow is signalled with an error; - buffer has to provide enough room for the - encoded string plus the trailing 0-byte - - - in both cases, *buffer_len is updated to - the size of the buffer /excluding/ the - trailing 0-byte - - */ - FETCH_SIZE; - - format++; - if (q == NULL && q2 == NULL) { - Py_DECREF(s); - return converterr( - "(buffer_len is NULL)", - arg, msgbuf, bufsize); - } - if (*buffer == NULL) { - *buffer = PyMem_NEW(char, size + 1); - if (*buffer == NULL) { - Py_DECREF(s); - return converterr( - "(memory error)", - arg, msgbuf, bufsize); - } - if(addcleanup(*buffer, freelist)) { - Py_DECREF(s); - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - } else { - if (size + 1 > BUFFER_LEN) { - Py_DECREF(s); - return converterr( - "(buffer overflow)", - arg, msgbuf, bufsize); - } - } - memcpy(*buffer, - PyString_AS_STRING(s), - size + 1); - STORE_SIZE(size); - } else { - /* Using a 0-terminated buffer: - - - the encoded string has to be 0-terminated - for this variant to work; if it is not, an - error raised - - - a new buffer of the needed size is - allocated and the data copied into it; - *buffer is updated to point to the new - buffer; the caller is responsible for - PyMem_Free()ing it after usage - - */ - if ((Py_ssize_t)strlen(PyString_AS_STRING(s)) - != size) { - Py_DECREF(s); - return converterr( - "(encoded string without NULL bytes)", - arg, msgbuf, bufsize); - } - *buffer = PyMem_NEW(char, size + 1); - if (*buffer == NULL) { - Py_DECREF(s); - return converterr("(memory error)", - arg, msgbuf, bufsize); - } - if(addcleanup(*buffer, freelist)) { - Py_DECREF(s); - return converterr("(cleanup problem)", - arg, msgbuf, bufsize); - } - memcpy(*buffer, - PyString_AS_STRING(s), - size + 1); - } - Py_DECREF(s); - break; - } - -#ifdef Py_USING_UNICODE - case 'u': {/* raw unicode buffer (Py_UNICODE *) */ - if (*format == '#') { /* any buffer-like object */ - void **p = (void **)va_arg(*p_va, char **); - FETCH_SIZE; - if (PyUnicode_Check(arg)) { - *p = PyUnicode_AS_UNICODE(arg); - STORE_SIZE(PyUnicode_GET_SIZE(arg)); - } - else { - return converterr("cannot convert raw buffers", - arg, msgbuf, bufsize); - } - format++; - } else { - Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); - if (PyUnicode_Check(arg)) - *p = PyUnicode_AS_UNICODE(arg); - else - return converterr("unicode", arg, msgbuf, bufsize); - } - break; - } -#endif - - case 'S': { /* string object */ - PyObject **p = va_arg(*p_va, PyObject **); - if (PyString_Check(arg)) - *p = arg; - else - return converterr("string", arg, msgbuf, bufsize); - break; - } - -#ifdef Py_USING_UNICODE - case 'U': { /* Unicode object */ - PyObject **p = va_arg(*p_va, PyObject **); - if (PyUnicode_Check(arg)) - *p = arg; - else - return converterr("unicode", arg, msgbuf, bufsize); - break; - } -#endif - - case 'O': { /* object */ - PyTypeObject *type; - PyObject **p; - if (*format == '!') { - type = va_arg(*p_va, PyTypeObject*); - p = va_arg(*p_va, PyObject **); - format++; - if (PyType_IsSubtype(arg->ob_type, type)) - *p = arg; - else - return converterr(type->tp_name, arg, msgbuf, bufsize); - - } - else if (*format == '?') { - inquiry pred = va_arg(*p_va, inquiry); - p = va_arg(*p_va, PyObject **); - format++; - if ((*pred)(arg)) - *p = arg; - else - return converterr("(unspecified)", - arg, msgbuf, bufsize); - - } - else if (*format == '&') { - typedef int (*converter)(PyObject *, void *); - converter convert = va_arg(*p_va, converter); - void *addr = va_arg(*p_va, void *); - format++; - if (! (*convert)(arg, addr)) - return converterr("(unspecified)", - arg, msgbuf, bufsize); - } - else { - p = va_arg(*p_va, PyObject **); - *p = arg; - } - break; - } - - - case 'w': { /* memory buffer, read-write access */ - void **p = va_arg(*p_va, void **); - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; - int count; - - if (pb == NULL || - pb->bf_getwritebuffer == NULL || - pb->bf_getsegcount == NULL) - return converterr("read-write buffer", arg, msgbuf, bufsize); - if ((*pb->bf_getsegcount)(arg, NULL) != 1) - return converterr("single-segment read-write buffer", - arg, msgbuf, bufsize); - if ((count = pb->bf_getwritebuffer(arg, 0, p)) < 0) - return converterr("(unspecified)", arg, msgbuf, bufsize); - if (*format == '#') { - FETCH_SIZE; - STORE_SIZE(count); - format++; - } - break; - } - - case 't': { /* 8-bit character buffer, read-only access */ - char **p = va_arg(*p_va, char **); - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; - int count; - - if (*format++ != '#') - return converterr( - "invalid use of 't' format character", - arg, msgbuf, bufsize); - if (!PyType_HasFeature(arg->ob_type, - Py_TPFLAGS_HAVE_GETCHARBUFFER) || - pb == NULL || pb->bf_getcharbuffer == NULL || - pb->bf_getsegcount == NULL) - return converterr( - "string or read-only character buffer", - arg, msgbuf, bufsize); - - if (pb->bf_getsegcount(arg, NULL) != 1) - return converterr( - "string or single-segment read-only buffer", - arg, msgbuf, bufsize); - - count = pb->bf_getcharbuffer(arg, 0, p); - if (count < 0) - return converterr("(unspecified)", arg, msgbuf, bufsize); - { - FETCH_SIZE; - STORE_SIZE(count); - } - break; - } - - default: - return converterr("impossible<bad format char>", arg, msgbuf, bufsize); - - } - - *p_format = format; - return NULL; -} - -static Py_ssize_t -convertbuffer(PyObject *arg, void **p, char **errmsg) -{ - PyBufferProcs *pb = arg->ob_type->tp_as_buffer; - Py_ssize_t count; - if (pb == NULL || - pb->bf_getreadbuffer == NULL || - pb->bf_getsegcount == NULL) { - *errmsg = "string or read-only buffer"; - return -1; - } - if ((*pb->bf_getsegcount)(arg, NULL) != 1) { - *errmsg = "string or single-segment read-only buffer"; - return -1; - } - if ((count = (*pb->bf_getreadbuffer)(arg, 0, p)) < 0) { - *errmsg = "(unspecified)"; - } - return count; -} - -/* Support for keyword arguments donated by - Geoff Philbrick <philbric@delphi.hks.com> */ - -/* Return false (0) for error, else true. */ -int -PyArg_ParseTupleAndKeywords(PyObject *args, - PyObject *keywords, - const char *format, - char **kwlist, ...) -{ - int retval; - va_list va; - - if ((args == NULL || !PyTuple_Check(args)) || - (keywords != NULL && !PyDict_Check(keywords)) || - format == NULL || - kwlist == NULL) - { - PyErr_BadInternalCall(); - return 0; - } - - va_start(va, kwlist); - retval = vgetargskeywords(args, keywords, format, kwlist, &va, 0); - va_end(va); - return retval; -} - -int -_PyArg_ParseTupleAndKeywords_SizeT(PyObject *args, - PyObject *keywords, - const char *format, - char **kwlist, ...) -{ - int retval; - va_list va; - - if ((args == NULL || !PyTuple_Check(args)) || - (keywords != NULL && !PyDict_Check(keywords)) || - format == NULL || - kwlist == NULL) - { - PyErr_BadInternalCall(); - return 0; - } - - va_start(va, kwlist); - retval = vgetargskeywords(args, keywords, format, - kwlist, &va, FLAG_SIZE_T); - va_end(va); - return retval; -} - - -int -PyArg_VaParseTupleAndKeywords(PyObject *args, - PyObject *keywords, - const char *format, - char **kwlist, va_list va) -{ - int retval; - va_list lva; - - if ((args == NULL || !PyTuple_Check(args)) || - (keywords != NULL && !PyDict_Check(keywords)) || - format == NULL || - kwlist == NULL) - { - PyErr_BadInternalCall(); - return 0; - } - -#ifdef VA_LIST_IS_ARRAY - memcpy(lva, va, sizeof(va_list)); -#else -#ifdef __va_copy - __va_copy(lva, va); -#else - lva = va; -#endif -#endif - - retval = vgetargskeywords(args, keywords, format, kwlist, &lva, 0); - return retval; -} - -int -_PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args, - PyObject *keywords, - const char *format, - char **kwlist, va_list va) -{ - int retval; - va_list lva; - - if ((args == NULL || !PyTuple_Check(args)) || - (keywords != NULL && !PyDict_Check(keywords)) || - format == NULL || - kwlist == NULL) - { - PyErr_BadInternalCall(); - return 0; - } - -#ifdef VA_LIST_IS_ARRAY - memcpy(lva, va, sizeof(va_list)); -#else -#ifdef __va_copy - __va_copy(lva, va); -#else - lva = va; -#endif -#endif - - retval = vgetargskeywords(args, keywords, format, - kwlist, &lva, FLAG_SIZE_T); - return retval; -} - - -static int -vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, - char **kwlist, va_list *p_va, int flags) -{ - char msgbuf[512]; - int levels[32]; - const char *fname, *message; - int min, max; - const char *formatsave; - int i, len, nargs, nkeywords; - const char *msg; - char **p; - PyObject *freelist = NULL; - - assert(args != NULL && PyTuple_Check(args)); - assert(keywords == NULL || PyDict_Check(keywords)); - assert(format != NULL); - assert(kwlist != NULL); - assert(p_va != NULL); - - /* Search the format: - message <- error msg, if any (else NULL). - fname <- routine name, if any (else NULL). - min <- # of required arguments, or -1 if all are required. - max <- most arguments (required + optional). - Check that kwlist has a non-NULL entry for each arg. - Raise error if a tuple arg spec is found. - */ - fname = message = NULL; - formatsave = format; - p = kwlist; - min = -1; - max = 0; - while ((i = *format++) != '\0') { - if (isalpha(Py_CHARMASK(i)) && i != 'e') { - max++; - if (*p == NULL) { - PyErr_SetString(PyExc_RuntimeError, - "more argument specifiers than " - "keyword list entries"); - return 0; - } - p++; - } - else if (i == '|') - min = max; - else if (i == ':') { - fname = format; - break; - } - else if (i == ';') { - message = format; - break; - } - else if (i == '(') { - PyErr_SetString(PyExc_RuntimeError, - "tuple found in format when using keyword " - "arguments"); - return 0; - } - } - format = formatsave; - if (*p != NULL) { - PyErr_SetString(PyExc_RuntimeError, - "more keyword list entries than " - "argument specifiers"); - return 0; - } - if (min < 0) { - /* All arguments are required. */ - min = max; - } - - nargs = PyTuple_GET_SIZE(args); - nkeywords = keywords == NULL ? 0 : PyDict_Size(keywords); - - /* make sure there are no duplicate values for an argument; - its not clear when to use the term "keyword argument vs. - keyword parameter in messages */ - if (nkeywords > 0) { - for (i = 0; i < nargs; i++) { - const char *thiskw = kwlist[i]; - if (thiskw == NULL) - break; - if (PyDict_GetItemString(keywords, thiskw)) { - PyErr_Format(PyExc_TypeError, - "keyword parameter '%s' was given " - "by position and by name", - thiskw); - return 0; - } - else if (PyErr_Occurred()) - return 0; - } - } - - /* required arguments missing from args can be supplied by keyword - arguments; set len to the number of positional arguments, and, - if that's less than the minimum required, add in the number of - required arguments that are supplied by keywords */ - len = nargs; - if (nkeywords > 0 && nargs < min) { - for (i = nargs; i < min; i++) { - if (PyDict_GetItemString(keywords, kwlist[i])) - len++; - else if (PyErr_Occurred()) - return 0; - } - } - - /* make sure we got an acceptable number of arguments; the message - is a little confusing with keywords since keyword arguments - which are supplied, but don't match the required arguments - are not included in the "%d given" part of the message - XXX and this isn't a bug!? */ - if (len < min || max < len) { - if (message == NULL) { - PyOS_snprintf(msgbuf, sizeof(msgbuf), - "%.200s%s takes %s %d argument%s " - "(%d given)", - fname==NULL ? "function" : fname, - fname==NULL ? "" : "()", - min==max ? "exactly" - : len < min ? "at least" : "at most", - len < min ? min : max, - (len < min ? min : max) == 1 ? "" : "s", - len); - message = msgbuf; - } - PyErr_SetString(PyExc_TypeError, message); - return 0; - } - - /* convert the positional arguments */ - for (i = 0; i < nargs; i++) { - if (*format == '|') - format++; - msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va, - flags, levels, msgbuf, sizeof(msgbuf), - &freelist); - if (msg) { - seterror(i+1, msg, levels, fname, message); - return cleanreturn(0, freelist); - } - } - - /* handle no keyword parameters in call */ - if (nkeywords == 0) - return cleanreturn(1, freelist); - - /* convert the keyword arguments; this uses the format - string where it was left after processing args */ - for (i = nargs; i < max; i++) { - PyObject *item; - if (*format == '|') - format++; - item = PyDict_GetItemString(keywords, kwlist[i]); - if (item != NULL) { - Py_INCREF(item); - msg = convertitem(item, &format, p_va, flags, levels, - msgbuf, sizeof(msgbuf), &freelist); - Py_DECREF(item); - if (msg) { - seterror(i+1, msg, levels, fname, message); - return cleanreturn(0, freelist); - } - --nkeywords; - if (nkeywords == 0) - break; - } - else if (PyErr_Occurred()) - return cleanreturn(0, freelist); - else { - msg = skipitem(&format, p_va, flags); - if (msg) { - levels[0] = 0; - seterror(i+1, msg, levels, fname, message); - return cleanreturn(0, freelist); - } - } - } - - /* make sure there are no extraneous keyword arguments */ - if (nkeywords > 0) { - PyObject *key, *value; - Py_ssize_t pos = 0; - while (PyDict_Next(keywords, &pos, &key, &value)) { - int match = 0; - char *ks; - if (!PyString_Check(key)) { - PyErr_SetString(PyExc_TypeError, - "keywords must be strings"); - return cleanreturn(0, freelist); - } - ks = PyString_AsString(key); - for (i = 0; i < max; i++) { - if (!strcmp(ks, kwlist[i])) { - match = 1; - break; - } - } - if (!match) { - PyErr_Format(PyExc_TypeError, - "'%s' is an invalid keyword " - "argument for this function", - ks); - return cleanreturn(0, freelist); - } - } - } - - return cleanreturn(1, freelist); -} - - -static char * -skipitem(const char **p_format, va_list *p_va, int flags) -{ - const char *format = *p_format; - char c = *format++; - - switch (c) { - - /* simple codes - * The individual types (second arg of va_arg) are irrelevant */ - - case 'b': /* byte -- very short int */ - case 'B': /* byte as bitfield */ - case 'h': /* short int */ - case 'H': /* short int as bitfield */ - case 'i': /* int */ - case 'I': /* int sized bitfield */ - case 'l': /* long int */ - case 'k': /* long int sized bitfield */ -#ifdef HAVE_LONG_LONG - case 'L': /* PY_LONG_LONG */ - case 'K': /* PY_LONG_LONG sized bitfield */ -#endif - case 'f': /* float */ - case 'd': /* double */ -#ifndef WITHOUT_COMPLEX - case 'D': /* complex double */ -#endif - case 'c': /* char */ - { - (void) va_arg(*p_va, void *); - break; - } - - case 'n': /* Py_ssize_t */ - { - (void) va_arg(*p_va, Py_ssize_t *); - break; - } - - /* string codes */ - - case 'e': /* string with encoding */ - { - (void) va_arg(*p_va, const char *); - if (!(*format == 's' || *format == 't')) - /* after 'e', only 's' and 't' is allowed */ - goto err; - format++; - /* explicit fallthrough to string cases */ - } - - case 's': /* string */ - case 'z': /* string or None */ -#ifdef Py_USING_UNICODE - case 'u': /* unicode string */ -#endif - case 't': /* buffer, read-only */ - case 'w': /* buffer, read-write */ - { - (void) va_arg(*p_va, char **); - if (*format == '#') { - if (flags & FLAG_SIZE_T) - (void) va_arg(*p_va, Py_ssize_t *); - else - (void) va_arg(*p_va, int *); - format++; - } - break; - } - - /* object codes */ - - case 'S': /* string object */ -#ifdef Py_USING_UNICODE - case 'U': /* unicode string object */ -#endif - { - (void) va_arg(*p_va, PyObject **); - break; - } - - case 'O': /* object */ - { - if (*format == '!') { - format++; - (void) va_arg(*p_va, PyTypeObject*); - (void) va_arg(*p_va, PyObject **); - } -#if 0 -/* I don't know what this is for */ - else if (*format == '?') { - inquiry pred = va_arg(*p_va, inquiry); - format++; - if ((*pred)(arg)) { - (void) va_arg(*p_va, PyObject **); - } - } -#endif - else if (*format == '&') { - typedef int (*converter)(PyObject *, void *); - (void) va_arg(*p_va, converter); - (void) va_arg(*p_va, void *); - format++; - } - else { - (void) va_arg(*p_va, PyObject **); - } - break; - } - - default: -err: - return "impossible<bad format char>"; - - } - - /* The "(...)" format code for tuples is not handled here because - * it is not allowed with keyword args. */ - - *p_format = format; - return NULL; -} - - -int -PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...) -{ - Py_ssize_t i, l; - PyObject **o; - va_list vargs; - -#ifdef HAVE_STDARG_PROTOTYPES - va_start(vargs, max); -#else - va_start(vargs); -#endif - - assert(min >= 0); - assert(min <= max); - if (!PyTuple_Check(args)) { - PyErr_SetString(PyExc_SystemError, - "PyArg_UnpackTuple() argument list is not a tuple"); - return 0; - } - l = PyTuple_GET_SIZE(args); - if (l < min) { - if (name != NULL) - PyErr_Format( - PyExc_TypeError, - "%s expected %s%zd arguments, got %zd", - name, (min == max ? "" : "at least "), min, l); - else - PyErr_Format( - PyExc_TypeError, - "unpacked tuple should have %s%zd elements," - " but has %zd", - (min == max ? "" : "at least "), min, l); - va_end(vargs); - return 0; - } - if (l > max) { - if (name != NULL) - PyErr_Format( - PyExc_TypeError, - "%s expected %s%zd arguments, got %zd", - name, (min == max ? "" : "at most "), max, l); - else - PyErr_Format( - PyExc_TypeError, - "unpacked tuple should have %s%zd elements," - " but has %zd", - (min == max ? "" : "at most "), max, l); - va_end(vargs); - return 0; - } - for (i = 0; i < l; i++) { - o = va_arg(vargs, PyObject **); - *o = PyTuple_GET_ITEM(args, i); - } - va_end(vargs); - return 1; -} - - -/* For type constructors that don't take keyword args - * - * Sets a TypeError and returns 0 if the kwds dict is - * not emtpy, returns 1 otherwise - */ -int -_PyArg_NoKeywords(const char *funcname, PyObject *kw) -{ - if (kw == NULL) - return 1; - if (!PyDict_CheckExact(kw)) { - PyErr_BadInternalCall(); - return 0; - } - if (PyDict_Size(kw) == 0) - return 1; - - PyErr_Format(PyExc_TypeError, "%s does not take keyword arguments", - funcname); - return 0; -} -#ifdef __cplusplus -}; -#endif diff --git a/sys/src/cmd/python/Python/getcompiler.c b/sys/src/cmd/python/Python/getcompiler.c deleted file mode 100644 index 0f441deb8..000000000 --- a/sys/src/cmd/python/Python/getcompiler.c +++ /dev/null @@ -1,28 +0,0 @@ - -/* Return the compiler identification, if possible. */ - -#include "Python.h" - -#ifndef COMPILER - -#ifdef __GNUC__ -#define COMPILER "\n[GCC " __VERSION__ "]" -#endif - -#endif /* !COMPILER */ - -#ifndef COMPILER - -#ifdef __cplusplus -#define COMPILER "[C++]" -#else -#define COMPILER "[C]" -#endif - -#endif /* !COMPILER */ - -const char * -Py_GetCompiler(void) -{ - return COMPILER; -} diff --git a/sys/src/cmd/python/Python/getcopyright.c b/sys/src/cmd/python/Python/getcopyright.c deleted file mode 100644 index c10aea452..000000000 --- a/sys/src/cmd/python/Python/getcopyright.c +++ /dev/null @@ -1,23 +0,0 @@ -/* Return the copyright string. This is updated manually. */ - -#include "Python.h" - -static char cprt[] = -"\ -Copyright (c) 2001-2007 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; -} diff --git a/sys/src/cmd/python/Python/getcwd.c b/sys/src/cmd/python/Python/getcwd.c deleted file mode 100644 index 967d484b3..000000000 --- a/sys/src/cmd/python/Python/getcwd.c +++ /dev/null @@ -1,83 +0,0 @@ - -/* Two PD getcwd() implementations. - Author: Guido van Rossum, CWI Amsterdam, Jan 1991, <guido@cwi.nl>. */ - -#include <stdio.h> -#include <errno.h> - -#ifdef HAVE_GETWD - -/* Version for BSD systems -- use getwd() */ - -#ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> -#endif - -#ifndef MAXPATHLEN -#if defined(PATH_MAX) && PATH_MAX > 1024 -#define MAXPATHLEN PATH_MAX -#else -#define MAXPATHLEN 1024 -#endif -#endif - -extern char *getwd(char *); - -char * -getcwd(char *buf, int size) -{ - char localbuf[MAXPATHLEN+1]; - char *ret; - - if (size <= 0) { - errno = EINVAL; - return NULL; - } - ret = getwd(localbuf); - if (ret != NULL && strlen(localbuf) >= (size_t)size) { - errno = ERANGE; - return NULL; - } - if (ret == NULL) { - errno = EACCES; /* Most likely error */ - return NULL; - } - strncpy(buf, localbuf, size); - return buf; -} - -#else /* !HAVE_GETWD */ - -/* Version for really old UNIX systems -- use pipe from pwd */ - -#ifndef PWD_CMD -#define PWD_CMD "/bin/pwd" -#endif - -char * -getcwd(char *buf, int size) -{ - FILE *fp; - char *p; - int sts; - if (size <= 0) { - errno = EINVAL; - return NULL; - } - if ((fp = popen(PWD_CMD, "r")) == NULL) - return NULL; - if (fgets(buf, size, fp) == NULL || (sts = pclose(fp)) != 0) { - errno = EACCES; /* Most likely error */ - return NULL; - } - for (p = buf; *p != '\n'; p++) { - if (*p == '\0') { - errno = ERANGE; - return NULL; - } - } - *p = '\0'; - return buf; -} - -#endif /* !HAVE_GETWD */ diff --git a/sys/src/cmd/python/Python/getmtime.c b/sys/src/cmd/python/Python/getmtime.c deleted file mode 100644 index 54edb531d..000000000 --- a/sys/src/cmd/python/Python/getmtime.c +++ /dev/null @@ -1,26 +0,0 @@ - -/* Subroutine to get the last modification time of a file */ - -/* (A separate file because this may be OS dependent) */ - -#include "Python.h" -#include "pyconfig.h" - -#ifdef __cplusplus -extern "C" { -#endif - -time_t -PyOS_GetLastModificationTime(char *path, FILE *fp) -{ - struct stat st; - if (fstat(fileno(fp), &st) != 0) - return -1; - else - return st.st_mtime; -} - -#ifdef __cplusplus -} -#endif - diff --git a/sys/src/cmd/python/Python/getopt.c b/sys/src/cmd/python/Python/getopt.c deleted file mode 100644 index 659efcfff..000000000 --- a/sys/src/cmd/python/Python/getopt.c +++ /dev/null @@ -1,115 +0,0 @@ -/*---------------------------------------------------------------------------* - * <RCS keywords> - * - * C++ Library - * - * Copyright 1992-1994, David Gottner - * - * All Rights Reserved - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted, - * provided that the above copyright notice, this permission notice and - * the following disclaimer notice appear unmodified in all copies. - * - * I DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL I - * BE LIABLE FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY - * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER - * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Nevertheless, I would like to know about bugs in this library or - * suggestions for improvment. Send bug reports and feedback to - * davegottner@delphi.com. - *---------------------------------------------------------------------------*/ - -/* Modified to support --help and --version, as well as /? on Windows - * by Georg Brandl. */ - -#include <stdio.h> -#include <string.h> - -#ifdef __cplusplus -extern "C" { -#endif - -int _PyOS_opterr = 1; /* generate error messages */ -int _PyOS_optind = 1; /* index into argv array */ -char *_PyOS_optarg = NULL; /* optional argument */ - -int _PyOS_GetOpt(int argc, char **argv, char *optstring) -{ - static char *opt_ptr = ""; - char *ptr; - int option; - - if (*opt_ptr == '\0') { - - if (_PyOS_optind >= argc) - return -1; -#ifdef MS_WINDOWS - else if (strcmp(argv[_PyOS_optind], "/?") == 0) { - ++_PyOS_optind; - return 'h'; - } -#endif - - else if (argv[_PyOS_optind][0] != '-' || - argv[_PyOS_optind][1] == '\0' /* lone dash */ ) - return -1; - - else if (strcmp(argv[_PyOS_optind], "--") == 0) { - ++_PyOS_optind; - return -1; - } - - else if (strcmp(argv[_PyOS_optind], "--help") == 0) { - ++_PyOS_optind; - return 'h'; - } - - else if (strcmp(argv[_PyOS_optind], "--version") == 0) { - ++_PyOS_optind; - return 'V'; - } - - - opt_ptr = &argv[_PyOS_optind++][1]; - } - - if ( (option = *opt_ptr++) == '\0') - return -1; - - if ((ptr = strchr(optstring, option)) == NULL) { - if (_PyOS_opterr) - fprintf(stderr, "Unknown option: -%c\n", option); - - return '_'; - } - - if (*(ptr + 1) == ':') { - if (*opt_ptr != '\0') { - _PyOS_optarg = opt_ptr; - opt_ptr = ""; - } - - else { - if (_PyOS_optind >= argc) { - if (_PyOS_opterr) - fprintf(stderr, - "Argument expected for the -%c option\n", option); - return '_'; - } - - _PyOS_optarg = argv[_PyOS_optind++]; - } - } - - return option; -} - -#ifdef __cplusplus -} -#endif - diff --git a/sys/src/cmd/python/Python/getplatform.c b/sys/src/cmd/python/Python/getplatform.c deleted file mode 100644 index 7a3c8b534..000000000 --- a/sys/src/cmd/python/Python/getplatform.c +++ /dev/null @@ -1,12 +0,0 @@ - -#include "Python.h" - -#ifndef PLATFORM -#define PLATFORM "plan9" -#endif - -const char * -Py_GetPlatform(void) -{ - return PLATFORM; -} diff --git a/sys/src/cmd/python/Python/getversion.c b/sys/src/cmd/python/Python/getversion.c deleted file mode 100644 index 7af16fc81..000000000 --- a/sys/src/cmd/python/Python/getversion.c +++ /dev/null @@ -1,15 +0,0 @@ - -/* 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; -} diff --git a/sys/src/cmd/python/Python/hypot.c b/sys/src/cmd/python/Python/hypot.c deleted file mode 100644 index 755d0c31c..000000000 --- a/sys/src/cmd/python/Python/hypot.c +++ /dev/null @@ -1,23 +0,0 @@ -/* hypot() replacement */ - -#include "pyconfig.h" -#include "pyport.h" - -double hypot(double x, double y) -{ - double yx; - - x = fabs(x); - y = fabs(y); - if (x < y) { - double temp = x; - x = y; - y = temp; - } - if (x == 0.) - return 0.; - else { - yx = y/x; - return x*sqrt(1.+yx*yx); - } -} diff --git a/sys/src/cmd/python/Python/import.c b/sys/src/cmd/python/Python/import.c deleted file mode 100644 index 7a3719f66..000000000 --- a/sys/src/cmd/python/Python/import.c +++ /dev/null @@ -1,3033 +0,0 @@ - -/* Module definition and import implementation */ - -#include "Python.h" - -#include "Python-ast.h" -#include "pyarena.h" -#include "pythonrun.h" -#include "errcode.h" -#include "marshal.h" -#include "code.h" -#include "compile.h" -#include "eval.h" -#include "osdefs.h" -#include "importdl.h" - -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#ifdef __cplusplus -extern "C" { -#endif - -extern time_t PyOS_GetLastModificationTime(char *, FILE *); - /* In getmtime.c */ - -/* Magic word to reject .pyc files generated by other Python versions. - It should change for each incompatible change to the bytecode. - - The value of CR and LF is incorporated so if you ever read or write - a .pyc file in text mode the magic number will be wrong; also, the - Apple MPW compiler swaps their values, botching string constants. - - The magic numbers must be spaced apart atleast 2 values, as the - -U interpeter flag will cause MAGIC+1 being used. They have been - odd numbers for some time now. - - There were a variety of old schemes for setting the magic number. - The current working scheme is to increment the previous value by - 10. - - Known values: - Python 1.5: 20121 - Python 1.5.1: 20121 - Python 1.5.2: 20121 - Python 1.6: 50428 - Python 2.0: 50823 - Python 2.0.1: 50823 - Python 2.1: 60202 - Python 2.1.1: 60202 - Python 2.1.2: 60202 - Python 2.2: 60717 - Python 2.3a0: 62011 - Python 2.3a0: 62021 - Python 2.3a0: 62011 (!) - Python 2.4a0: 62041 - Python 2.4a3: 62051 - Python 2.4b1: 62061 - Python 2.5a0: 62071 - Python 2.5a0: 62081 (ast-branch) - Python 2.5a0: 62091 (with) - Python 2.5a0: 62092 (changed WITH_CLEANUP opcode) - Python 2.5b3: 62101 (fix wrong code: for x, in ...) - Python 2.5b3: 62111 (fix wrong code: x += yield) - Python 2.5c1: 62121 (fix wrong lnotab with for loops and - storing constants that should have been removed) - Python 2.5c2: 62131 (fix wrong code: for x, in ... in listcomp/genexp) -. -*/ -#define MAGIC (62131 | ((long)'\r'<<16) | ((long)'\n'<<24)) - -/* Magic word as global; note that _PyImport_Init() can change the - value of this global to accommodate for alterations of how the - compiler works which are enabled by command line switches. */ -static long pyc_magic = MAGIC; - -/* See _PyImport_FixupExtension() below */ -static PyObject *extensions = NULL; - -/* This table is defined in config.c: */ -extern struct _inittab _PyImport_Inittab[]; - -struct _inittab *PyImport_Inittab = _PyImport_Inittab; - -/* these tables define the module suffixes that Python recognizes */ -struct filedescr * _PyImport_Filetab = NULL; - -#ifdef RISCOS -static const struct filedescr _PyImport_StandardFiletab[] = { - {"/py", "U", PY_SOURCE}, - {0, 0} -}; -#else -static const struct filedescr _PyImport_StandardFiletab[] = { - {".py", "U", PY_SOURCE}, - {0, 0} -}; -#endif - -static PyTypeObject NullImporterType; /* Forward reference */ - -/* Initialize things */ - -void -_PyImport_Init(void) -{ - const struct filedescr *scan; - struct filedescr *filetab; - int countD = 0; - int countS = 0; - - /* prepare _PyImport_Filetab: copy entries from - _PyImport_DynLoadFiletab and _PyImport_StandardFiletab. - */ - for (scan = _PyImport_DynLoadFiletab; scan->suffix != NULL; ++scan) - ++countD; - for (scan = _PyImport_StandardFiletab; scan->suffix != NULL; ++scan) - ++countS; - filetab = PyMem_NEW(struct filedescr, countD + countS + 1); - if (filetab == NULL) - Py_FatalError("Can't initialize import file table."); - memcpy(filetab, _PyImport_DynLoadFiletab, - countD * sizeof(struct filedescr)); - memcpy(filetab + countD, _PyImport_StandardFiletab, - countS * sizeof(struct filedescr)); - filetab[countD + countS].suffix = NULL; - - _PyImport_Filetab = filetab; - - if (Py_OptimizeFlag) { - /* Replace ".pyc" with ".pyo" in _PyImport_Filetab */ - for (; filetab->suffix != NULL; filetab++) { -#ifndef RISCOS - if (strcmp(filetab->suffix, ".pyc") == 0) - filetab->suffix = ".pyo"; -#else - if (strcmp(filetab->suffix, "/pyc") == 0) - filetab->suffix = "/pyo"; -#endif - } - } - - if (Py_UnicodeFlag) { - /* Fix the pyc_magic so that byte compiled code created - using the all-Unicode method doesn't interfere with - code created in normal operation mode. */ - pyc_magic = MAGIC + 1; - } -} - -void -_PyImportHooks_Init(void) -{ - PyObject *v, *path_hooks = NULL, *zimpimport; - int err = 0; - - /* adding sys.path_hooks and sys.path_importer_cache, setting up - zipimport */ - if (PyType_Ready(&NullImporterType) < 0) - goto error; - - if (Py_VerboseFlag) - PySys_WriteStderr("# installing zipimport hook\n"); - - v = PyList_New(0); - if (v == NULL) - goto error; - err = PySys_SetObject("meta_path", v); - Py_DECREF(v); - if (err) - goto error; - v = PyDict_New(); - if (v == NULL) - goto error; - err = PySys_SetObject("path_importer_cache", v); - Py_DECREF(v); - if (err) - goto error; - path_hooks = PyList_New(0); - if (path_hooks == NULL) - goto error; - err = PySys_SetObject("path_hooks", path_hooks); - if (err) { - error: - PyErr_Print(); - Py_FatalError("initializing sys.meta_path, sys.path_hooks, " - "path_importer_cache, or NullImporter failed" - ); - } - - zimpimport = PyImport_ImportModule("zipimport"); - if (zimpimport == NULL) { - PyErr_Clear(); /* No zip import module -- okay */ - if (Py_VerboseFlag) - PySys_WriteStderr("# can't import zipimport\n"); - } - else { - PyObject *zipimporter = PyObject_GetAttrString(zimpimport, - "zipimporter"); - Py_DECREF(zimpimport); - if (zipimporter == NULL) { - PyErr_Clear(); /* No zipimporter object -- okay */ - if (Py_VerboseFlag) - PySys_WriteStderr( - "# can't import zipimport.zipimporter\n"); - } - else { - /* sys.path_hooks.append(zipimporter) */ - err = PyList_Append(path_hooks, zipimporter); - Py_DECREF(zipimporter); - if (err) - goto error; - if (Py_VerboseFlag) - PySys_WriteStderr( - "# installed zipimport hook\n"); - } - } - Py_DECREF(path_hooks); -} - -void -_PyImport_Fini(void) -{ - Py_XDECREF(extensions); - extensions = NULL; - PyMem_DEL(_PyImport_Filetab); - _PyImport_Filetab = NULL; -} - - -/* Locking primitives to prevent parallel imports of the same module - in different threads to return with a partially loaded module. - These calls are serialized by the global interpreter lock. */ - -#ifdef WITH_THREAD - -#include "pythread.h" - -static PyThread_type_lock import_lock = 0; -static long import_lock_thread = -1; -static int import_lock_level = 0; - -static void -lock_import(void) -{ - long me = PyThread_get_thread_ident(); - if (me == -1) - return; /* Too bad */ - if (import_lock == NULL) { - import_lock = PyThread_allocate_lock(); - if (import_lock == NULL) - return; /* Nothing much we can do. */ - } - if (import_lock_thread == me) { - import_lock_level++; - return; - } - if (import_lock_thread != -1 || !PyThread_acquire_lock(import_lock, 0)) - { - PyThreadState *tstate = PyEval_SaveThread(); - PyThread_acquire_lock(import_lock, 1); - PyEval_RestoreThread(tstate); - } - import_lock_thread = me; - import_lock_level = 1; -} - -static int -unlock_import(void) -{ - long me = PyThread_get_thread_ident(); - if (me == -1 || import_lock == NULL) - return 0; /* Too bad */ - if (import_lock_thread != me) - return -1; - import_lock_level--; - if (import_lock_level == 0) { - import_lock_thread = -1; - PyThread_release_lock(import_lock); - } - return 1; -} - -/* This function is called from PyOS_AfterFork to ensure that newly - created child processes do not share locks with the parent. */ - -void -_PyImport_ReInitLock(void) -{ -#ifdef _AIX - if (import_lock != NULL) - import_lock = PyThread_allocate_lock(); -#endif -} - -#else - -#define lock_import() -#define unlock_import() 0 - -#endif - -static PyObject * -imp_lock_held(PyObject *self, PyObject *noargs) -{ -#ifdef WITH_THREAD - return PyBool_FromLong(import_lock_thread != -1); -#else - return PyBool_FromLong(0); -#endif -} - -static PyObject * -imp_acquire_lock(PyObject *self, PyObject *noargs) -{ -#ifdef WITH_THREAD - lock_import(); -#endif - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -imp_release_lock(PyObject *self, PyObject *noargs) -{ -#ifdef WITH_THREAD - if (unlock_import() < 0) { - PyErr_SetString(PyExc_RuntimeError, - "not holding the import lock"); - return NULL; - } -#endif - Py_INCREF(Py_None); - return Py_None; -} - -static void -imp_modules_reloading_clear (void) -{ - PyInterpreterState *interp = PyThreadState_Get()->interp; - if (interp->modules_reloading == NULL) - return; - PyDict_Clear(interp->modules_reloading); - return; -} - -/* Helper for sys */ - -PyObject * -PyImport_GetModuleDict(void) -{ - PyInterpreterState *interp = PyThreadState_GET()->interp; - if (interp->modules == NULL) - Py_FatalError("PyImport_GetModuleDict: no module dictionary!"); - return interp->modules; -} - - -/* List of names to clear in sys */ -static char* sys_deletes[] = { - "path", "argv", "ps1", "ps2", "exitfunc", - "exc_type", "exc_value", "exc_traceback", - "last_type", "last_value", "last_traceback", - "path_hooks", "path_importer_cache", "meta_path", - NULL -}; - -static char* sys_files[] = { - "stdin", "__stdin__", - "stdout", "__stdout__", - "stderr", "__stderr__", - NULL -}; - - -/* Un-initialize things, as good as we can */ - -void -PyImport_Cleanup(void) -{ - Py_ssize_t pos, ndone; - char *name; - PyObject *key, *value, *dict; - PyInterpreterState *interp = PyThreadState_GET()->interp; - PyObject *modules = interp->modules; - - if (modules == NULL) - return; /* Already done */ - - /* Delete some special variables first. These are common - places where user values hide and people complain when their - destructors fail. Since the modules containing them are - deleted *last* of all, they would come too late in the normal - destruction order. Sigh. */ - - value = PyDict_GetItemString(modules, "__builtin__"); - if (value != NULL && PyModule_Check(value)) { - dict = PyModule_GetDict(value); - if (Py_VerboseFlag) - PySys_WriteStderr("# clear __builtin__._\n"); - PyDict_SetItemString(dict, "_", Py_None); - } - value = PyDict_GetItemString(modules, "sys"); - if (value != NULL && PyModule_Check(value)) { - char **p; - PyObject *v; - dict = PyModule_GetDict(value); - for (p = sys_deletes; *p != NULL; p++) { - if (Py_VerboseFlag) - PySys_WriteStderr("# clear sys.%s\n", *p); - PyDict_SetItemString(dict, *p, Py_None); - } - for (p = sys_files; *p != NULL; p+=2) { - if (Py_VerboseFlag) - PySys_WriteStderr("# restore sys.%s\n", *p); - v = PyDict_GetItemString(dict, *(p+1)); - if (v == NULL) - v = Py_None; - PyDict_SetItemString(dict, *p, v); - } - } - - /* First, delete __main__ */ - value = PyDict_GetItemString(modules, "__main__"); - if (value != NULL && PyModule_Check(value)) { - if (Py_VerboseFlag) - PySys_WriteStderr("# cleanup __main__\n"); - _PyModule_Clear(value); - PyDict_SetItemString(modules, "__main__", Py_None); - } - - /* The special treatment of __builtin__ here is because even - when it's not referenced as a module, its dictionary is - referenced by almost every module's __builtins__. Since - deleting a module clears its dictionary (even if there are - references left to it), we need to delete the __builtin__ - module last. Likewise, we don't delete sys until the very - end because it is implicitly referenced (e.g. by print). - - Also note that we 'delete' modules by replacing their entry - in the modules dict with None, rather than really deleting - them; this avoids a rehash of the modules dictionary and - also marks them as "non existent" so they won't be - re-imported. */ - - /* Next, repeatedly delete modules with a reference count of - one (skipping __builtin__ and sys) and delete them */ - do { - ndone = 0; - pos = 0; - while (PyDict_Next(modules, &pos, &key, &value)) { - if (value->ob_refcnt != 1) - continue; - if (PyString_Check(key) && PyModule_Check(value)) { - name = PyString_AS_STRING(key); - if (strcmp(name, "__builtin__") == 0) - continue; - if (strcmp(name, "sys") == 0) - continue; - if (Py_VerboseFlag) - PySys_WriteStderr( - "# cleanup[1] %s\n", name); - _PyModule_Clear(value); - PyDict_SetItem(modules, key, Py_None); - ndone++; - } - } - } while (ndone > 0); - - /* Next, delete all modules (still skipping __builtin__ and sys) */ - pos = 0; - while (PyDict_Next(modules, &pos, &key, &value)) { - if (PyString_Check(key) && PyModule_Check(value)) { - name = PyString_AS_STRING(key); - if (strcmp(name, "__builtin__") == 0) - continue; - if (strcmp(name, "sys") == 0) - continue; - if (Py_VerboseFlag) - PySys_WriteStderr("# cleanup[2] %s\n", name); - _PyModule_Clear(value); - PyDict_SetItem(modules, key, Py_None); - } - } - - /* Next, delete sys and __builtin__ (in that order) */ - value = PyDict_GetItemString(modules, "sys"); - if (value != NULL && PyModule_Check(value)) { - if (Py_VerboseFlag) - PySys_WriteStderr("# cleanup sys\n"); - _PyModule_Clear(value); - PyDict_SetItemString(modules, "sys", Py_None); - } - value = PyDict_GetItemString(modules, "__builtin__"); - if (value != NULL && PyModule_Check(value)) { - if (Py_VerboseFlag) - PySys_WriteStderr("# cleanup __builtin__\n"); - _PyModule_Clear(value); - PyDict_SetItemString(modules, "__builtin__", Py_None); - } - - /* Finally, clear and delete the modules directory */ - PyDict_Clear(modules); - interp->modules = NULL; - Py_DECREF(modules); - Py_CLEAR(interp->modules_reloading); -} - - -/* Helper for pythonrun.c -- return magic number */ - -long -PyImport_GetMagicNumber(void) -{ - return pyc_magic; -} - - -/* Magic for extension modules (built-in as well as dynamically - loaded). To prevent initializing an extension module more than - once, we keep a static dictionary 'extensions' keyed by module name - (for built-in modules) or by filename (for dynamically loaded - modules), containing these modules. A copy of the module's - dictionary is stored by calling _PyImport_FixupExtension() - immediately after the module initialization function succeeds. A - copy can be retrieved from there by calling - _PyImport_FindExtension(). */ - -PyObject * -_PyImport_FixupExtension(char *name, char *filename) -{ - PyObject *modules, *mod, *dict, *copy; - if (extensions == NULL) { - extensions = PyDict_New(); - if (extensions == NULL) - return NULL; - } - modules = PyImport_GetModuleDict(); - mod = PyDict_GetItemString(modules, name); - if (mod == NULL || !PyModule_Check(mod)) { - PyErr_Format(PyExc_SystemError, - "_PyImport_FixupExtension: module %.200s not loaded", name); - return NULL; - } - dict = PyModule_GetDict(mod); - if (dict == NULL) - return NULL; - copy = PyDict_Copy(dict); - if (copy == NULL) - return NULL; - PyDict_SetItemString(extensions, filename, copy); - Py_DECREF(copy); - return copy; -} - -PyObject * -_PyImport_FindExtension(char *name, char *filename) -{ - PyObject *dict, *mod, *mdict; - if (extensions == NULL) - return NULL; - dict = PyDict_GetItemString(extensions, filename); - if (dict == NULL) - return NULL; - mod = PyImport_AddModule(name); - if (mod == NULL) - return NULL; - mdict = PyModule_GetDict(mod); - if (mdict == NULL) - return NULL; - if (PyDict_Update(mdict, dict)) - return NULL; - if (Py_VerboseFlag) - PySys_WriteStderr("import %s # previously loaded (%s)\n", - name, filename); - return mod; -} - - -/* Get the module object corresponding to a module name. - First check the modules dictionary if there's one there, - if not, create a new one and insert it in the modules dictionary. - Because the former action is most common, THIS DOES NOT RETURN A - 'NEW' REFERENCE! */ - -PyObject * -PyImport_AddModule(const char *name) -{ - PyObject *modules = PyImport_GetModuleDict(); - PyObject *m; - - if ((m = PyDict_GetItemString(modules, name)) != NULL && - PyModule_Check(m)) - return m; - m = PyModule_New(name); - if (m == NULL) - return NULL; - if (PyDict_SetItemString(modules, name, m) != 0) { - Py_DECREF(m); - return NULL; - } - Py_DECREF(m); /* Yes, it still exists, in modules! */ - - return m; -} - -/* Remove name from sys.modules, if it's there. */ -static void -_RemoveModule(const char *name) -{ - PyObject *modules = PyImport_GetModuleDict(); - if (PyDict_GetItemString(modules, name) == NULL) - return; - if (PyDict_DelItemString(modules, name) < 0) - Py_FatalError("import: deleting existing key in" - "sys.modules failed"); -} - -/* Execute a code object in a module and return the module object - * WITH INCREMENTED REFERENCE COUNT. If an error occurs, name is - * removed from sys.modules, to avoid leaving damaged module objects - * in sys.modules. The caller may wish to restore the original - * module object (if any) in this case; PyImport_ReloadModule is an - * example. - */ -PyObject * -PyImport_ExecCodeModule(char *name, PyObject *co) -{ - return PyImport_ExecCodeModuleEx(name, co, (char *)NULL); -} - -PyObject * -PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname) -{ - PyObject *modules = PyImport_GetModuleDict(); - PyObject *m, *d, *v; - - m = PyImport_AddModule(name); - if (m == NULL) - return NULL; - /* If the module is being reloaded, we get the old module back - and re-use its dict to exec the new code. */ - d = PyModule_GetDict(m); - if (PyDict_GetItemString(d, "__builtins__") == NULL) { - if (PyDict_SetItemString(d, "__builtins__", - PyEval_GetBuiltins()) != 0) - goto error; - } - /* Remember the filename as the __file__ attribute */ - v = NULL; - if (pathname != NULL) { - v = PyString_FromString(pathname); - if (v == NULL) - PyErr_Clear(); - } - if (v == NULL) { - v = ((PyCodeObject *)co)->co_filename; - Py_INCREF(v); - } - if (PyDict_SetItemString(d, "__file__", v) != 0) - PyErr_Clear(); /* Not important enough to report */ - Py_DECREF(v); - - v = PyEval_EvalCode((PyCodeObject *)co, d, d); - if (v == NULL) - goto error; - Py_DECREF(v); - - if ((m = PyDict_GetItemString(modules, name)) == NULL) { - PyErr_Format(PyExc_ImportError, - "Loaded module %.200s not found in sys.modules", - name); - return NULL; - } - - Py_INCREF(m); - - return m; - - error: - _RemoveModule(name); - return NULL; -} - - -/* Read a code object from a file and check it for validity */ - -static PyCodeObject * -read_compiled_module(char *cpathname, FILE *fp) -{ - PyObject *co; - - co = PyMarshal_ReadLastObjectFromFile(fp); - if (co == NULL) - return NULL; - if (!PyCode_Check(co)) { - PyErr_Format(PyExc_ImportError, - "Non-code object in %.200s", cpathname); - Py_DECREF(co); - return NULL; - } - return (PyCodeObject *)co; -} - - -/* Load a module from a compiled file, execute it, and return its - module object WITH INCREMENTED REFERENCE COUNT */ - -static PyObject * -load_compiled_module(char *name, char *cpathname, FILE *fp) -{ - long magic; - PyCodeObject *co; - PyObject *m; - - magic = PyMarshal_ReadLongFromFile(fp); - if (magic != pyc_magic) { - PyErr_Format(PyExc_ImportError, - "Bad magic number in %.200s", cpathname); - return NULL; - } - (void) PyMarshal_ReadLongFromFile(fp); - co = read_compiled_module(cpathname, fp); - if (co == NULL) - return NULL; - if (Py_VerboseFlag) - PySys_WriteStderr("import %s # precompiled from %s\n", - name, cpathname); - m = PyImport_ExecCodeModuleEx(name, (PyObject *)co, cpathname); - Py_DECREF(co); - - return m; -} - -/* Parse a source file and return the corresponding code object */ - -static PyCodeObject * -parse_source_module(const char *pathname, FILE *fp) -{ - PyCodeObject *co = NULL; - mod_ty mod; - PyArena *arena = PyArena_New(); - if (arena == NULL) - return NULL; - - mod = PyParser_ASTFromFile(fp, pathname, Py_file_input, 0, 0, 0, - NULL, arena); - if (mod) { - co = PyAST_Compile(mod, pathname, NULL, arena); - } - PyArena_Free(arena); - return co; -} - - -/* Helper to open a bytecode file for writing in exclusive mode */ - -static FILE * -open_exclusive(char *filename) -{ -#if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC) - /* Use O_EXCL to avoid a race condition when another process tries to - write the same file. When that happens, our open() call fails, - which is just fine (since it's only a cache). - XXX If the file exists and is writable but the directory is not - writable, the file will never be written. Oh well. - */ - int fd; - (void) unlink(filename); - fd = open(filename, O_EXCL|O_CREAT|O_WRONLY|O_TRUNC -#ifdef O_BINARY - |O_BINARY /* necessary for Windows */ -#endif -#ifdef __VMS - , 0666, "ctxt=bin", "shr=nil" -#else - , 0666 -#endif - ); - if (fd < 0) - return NULL; - return fdopen(fd, "wb"); -#else - /* Best we can do -- on Windows this can't happen anyway */ - return fopen(filename, "wb"); -#endif -} - -/* Load a source module from a given file and return its module - object WITH INCREMENTED REFERENCE COUNT. If there's a matching - byte-compiled file, use that instead. */ - -static PyObject * -load_source_module(char *name, char *pathname, FILE *fp) -{ - time_t mtime; - FILE *fpc; - char buf[MAXPATHLEN+1]; - PyCodeObject *co; - PyObject *m; - - mtime = PyOS_GetLastModificationTime(pathname, fp); - if (mtime == (time_t)(-1)) { - PyErr_Format(PyExc_RuntimeError, - "unable to get modification time from '%s'", - pathname); - return NULL; - } -#if SIZEOF_TIME_T > 4 - /* Python's .pyc timestamp handling presumes that the timestamp fits - in 4 bytes. This will be fine until sometime in the year 2038, - when a 4-byte signed time_t will overflow. - */ - if (mtime >> 32) { - PyErr_SetString(PyExc_OverflowError, - "modification time overflows a 4 byte field"); - return NULL; - } -#endif - co = parse_source_module(pathname, fp); - if (co == NULL) - return NULL; - if (Py_VerboseFlag) - PySys_WriteStderr("import %s # from %s\n", - name, pathname); - m = PyImport_ExecCodeModuleEx(name, (PyObject *)co, pathname); - Py_DECREF(co); - - return m; -} - - -/* Forward */ -static PyObject *load_module(char *, FILE *, char *, int, PyObject *); -static struct filedescr *find_module(char *, char *, PyObject *, - char *, size_t, FILE **, PyObject **); -static struct _frozen *find_frozen(char *name); - -/* Load a package and return its module object WITH INCREMENTED - REFERENCE COUNT */ - -static PyObject * -load_package(char *name, char *pathname) -{ - PyObject *m, *d; - PyObject *file = NULL; - PyObject *path = NULL; - int err; - char buf[MAXPATHLEN+1]; - FILE *fp = NULL; - struct filedescr *fdp; - - m = PyImport_AddModule(name); - if (m == NULL) - return NULL; - if (Py_VerboseFlag) - PySys_WriteStderr("import %s # directory %s\n", - name, pathname); - d = PyModule_GetDict(m); - file = PyString_FromString(pathname); - if (file == NULL) - goto error; - path = Py_BuildValue("[O]", file); - if (path == NULL) - goto error; - err = PyDict_SetItemString(d, "__file__", file); - if (err == 0) - err = PyDict_SetItemString(d, "__path__", path); - if (err != 0) - goto error; - buf[0] = '\0'; - fdp = find_module(name, "__init__", path, buf, sizeof(buf), &fp, NULL); - if (fdp == NULL) { - if (PyErr_ExceptionMatches(PyExc_ImportError)) { - PyErr_Clear(); - Py_INCREF(m); - } - else - m = NULL; - goto cleanup; - } - m = load_module(name, fp, buf, fdp->type, NULL); - if (fp != NULL) - fclose(fp); - goto cleanup; - - error: - m = NULL; - cleanup: - Py_XDECREF(path); - Py_XDECREF(file); - return m; -} - - -/* Helper to test for built-in module */ - -static int -is_builtin(char *name) -{ - int i; - for (i = 0; PyImport_Inittab[i].name != NULL; i++) { - if (strcmp(name, PyImport_Inittab[i].name) == 0) { - if (PyImport_Inittab[i].initfunc == NULL) - return -1; - else - return 1; - } - } - return 0; -} - - -/* Return an importer object for a sys.path/pkg.__path__ item 'p', - possibly by fetching it from the path_importer_cache dict. If it - wasn't yet cached, traverse path_hooks until it a hook is found - that can handle the path item. Return None if no hook could; - this tells our caller it should fall back to the builtin - import mechanism. Cache the result in path_importer_cache. - Returns a borrowed reference. */ - -static PyObject * -get_path_importer(PyObject *path_importer_cache, PyObject *path_hooks, - PyObject *p) -{ - PyObject *importer; - Py_ssize_t j, nhooks; - - /* These conditions are the caller's responsibility: */ - assert(PyList_Check(path_hooks)); - assert(PyDict_Check(path_importer_cache)); - - nhooks = PyList_Size(path_hooks); - if (nhooks < 0) - return NULL; /* Shouldn't happen */ - - importer = PyDict_GetItem(path_importer_cache, p); - if (importer != NULL) - return importer; - - /* set path_importer_cache[p] to None to avoid recursion */ - if (PyDict_SetItem(path_importer_cache, p, Py_None) != 0) - return NULL; - - for (j = 0; j < nhooks; j++) { - PyObject *hook = PyList_GetItem(path_hooks, j); - if (hook == NULL) - return NULL; - importer = PyObject_CallFunctionObjArgs(hook, p, NULL); - if (importer != NULL) - break; - - if (!PyErr_ExceptionMatches(PyExc_ImportError)) { - return NULL; - } - PyErr_Clear(); - } - if (importer == NULL) { - importer = PyObject_CallFunctionObjArgs( - (PyObject *)&NullImporterType, p, NULL - ); - if (importer == NULL) { - if (PyErr_ExceptionMatches(PyExc_ImportError)) { - PyErr_Clear(); - return Py_None; - } - } - } - if (importer != NULL) { - int err = PyDict_SetItem(path_importer_cache, p, importer); - Py_DECREF(importer); - if (err != 0) - return NULL; - } - return importer; -} - -/* Search the path (default sys.path) for a module. Return the - corresponding filedescr struct, and (via return arguments) the - pathname and an open file. Return NULL if the module is not found. */ - -#ifdef MS_COREDLL -extern FILE *PyWin_FindRegisteredModule(const char *, struct filedescr **, - char *, Py_ssize_t); -#endif - -static int case_ok(char *, Py_ssize_t, Py_ssize_t, char *); -static int find_init_module(char *); /* Forward */ -static struct filedescr importhookdescr = {"", "", IMP_HOOK}; - -static struct filedescr * -find_module(char *fullname, char *subname, PyObject *path, char *buf, - size_t buflen, FILE **p_fp, PyObject **p_loader) -{ - Py_ssize_t i, npath; - size_t len, namelen; - struct filedescr *fdp = NULL; - char *filemode; - FILE *fp = NULL; - PyObject *path_hooks, *path_importer_cache; -#ifndef RISCOS - struct stat statbuf; -#endif - static struct filedescr fd_frozen = {"", "", PY_FROZEN}; - static struct filedescr fd_builtin = {"", "", C_BUILTIN}; - static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; - char name[MAXPATHLEN+1]; -#if defined(PYOS_OS2) - size_t saved_len; - size_t saved_namelen; - char *saved_buf = NULL; -#endif - if (p_loader != NULL) - *p_loader = NULL; - - if (strlen(subname) > MAXPATHLEN) { - PyErr_SetString(PyExc_OverflowError, - "module name is too long"); - return NULL; - } - strcpy(name, subname); - - /* sys.meta_path import hook */ - if (p_loader != NULL) { - PyObject *meta_path; - - meta_path = PySys_GetObject("meta_path"); - if (meta_path == NULL || !PyList_Check(meta_path)) { - PyErr_SetString(PyExc_ImportError, - "sys.meta_path must be a list of " - "import hooks"); - return NULL; - } - Py_INCREF(meta_path); /* zap guard */ - npath = PyList_Size(meta_path); - for (i = 0; i < npath; i++) { - PyObject *loader; - PyObject *hook = PyList_GetItem(meta_path, i); - loader = PyObject_CallMethod(hook, "find_module", - "sO", fullname, - path != NULL ? - path : Py_None); - if (loader == NULL) { - Py_DECREF(meta_path); - return NULL; /* true error */ - } - if (loader != Py_None) { - /* a loader was found */ - *p_loader = loader; - Py_DECREF(meta_path); - return &importhookdescr; - } - Py_DECREF(loader); - } - Py_DECREF(meta_path); - } - - if (path != NULL && PyString_Check(path)) { - /* The only type of submodule allowed inside a "frozen" - package are other frozen modules or packages. */ - if (PyString_Size(path) + 1 + strlen(name) >= (size_t)buflen) { - PyErr_SetString(PyExc_ImportError, - "full frozen module name too long"); - return NULL; - } - strcpy(buf, PyString_AsString(path)); - strcat(buf, "."); - strcat(buf, name); - strcpy(name, buf); - if (find_frozen(name) != NULL) { - strcpy(buf, name); - return &fd_frozen; - } - PyErr_Format(PyExc_ImportError, - "No frozen submodule named %.200s", name); - return NULL; - } - if (path == NULL) { - if (is_builtin(name)) { - strcpy(buf, name); - return &fd_builtin; - } - if ((find_frozen(name)) != NULL) { - strcpy(buf, name); - return &fd_frozen; - } - -#ifdef MS_COREDLL - fp = PyWin_FindRegisteredModule(name, &fdp, buf, buflen); - if (fp != NULL) { - *p_fp = fp; - return fdp; - } -#endif - path = PySys_GetObject("path"); - } - if (path == NULL || !PyList_Check(path)) { - PyErr_SetString(PyExc_ImportError, - "sys.path must be a list of directory names"); - return NULL; - } - - path_hooks = PySys_GetObject("path_hooks"); - if (path_hooks == NULL || !PyList_Check(path_hooks)) { - PyErr_SetString(PyExc_ImportError, - "sys.path_hooks must be a list of " - "import hooks"); - return NULL; - } - path_importer_cache = PySys_GetObject("path_importer_cache"); - if (path_importer_cache == NULL || - !PyDict_Check(path_importer_cache)) { - PyErr_SetString(PyExc_ImportError, - "sys.path_importer_cache must be a dict"); - return NULL; - } - - npath = PyList_Size(path); - namelen = strlen(name); - for (i = 0; i < npath; i++) { - PyObject *copy = NULL; - PyObject *v = PyList_GetItem(path, i); - if (!v) - return NULL; -#ifdef Py_USING_UNICODE - if (PyUnicode_Check(v)) { - copy = PyUnicode_Encode(PyUnicode_AS_UNICODE(v), - PyUnicode_GET_SIZE(v), Py_FileSystemDefaultEncoding, NULL); - if (copy == NULL) - return NULL; - v = copy; - } - else -#endif - if (!PyString_Check(v)) - continue; - len = PyString_GET_SIZE(v); - if (len + 2 + namelen + MAXSUFFIXSIZE >= buflen) { - Py_XDECREF(copy); - continue; /* Too long */ - } - strcpy(buf, PyString_AS_STRING(v)); - if (strlen(buf) != len) { - Py_XDECREF(copy); - continue; /* v contains '\0' */ - } - - /* sys.path_hooks import hook */ - if (p_loader != NULL) { - PyObject *importer; - - importer = get_path_importer(path_importer_cache, - path_hooks, v); - if (importer == NULL) { - Py_XDECREF(copy); - return NULL; - } - /* Note: importer is a borrowed reference */ - if (importer != Py_None) { - PyObject *loader; - loader = PyObject_CallMethod(importer, - "find_module", - "s", fullname); - Py_XDECREF(copy); - if (loader == NULL) - return NULL; /* error */ - if (loader != Py_None) { - /* a loader was found */ - *p_loader = loader; - return &importhookdescr; - } - Py_DECREF(loader); - continue; - } - } - /* no hook was found, use builtin import */ - - if (len > 0 && buf[len-1] != SEP -#ifdef ALTSEP - && buf[len-1] != ALTSEP -#endif - ) - buf[len++] = SEP; - strcpy(buf+len, name); - len += namelen; - - /* Check for package import (buf holds a directory name, - and there's an __init__ module in that directory */ -#ifdef HAVE_STAT - if (stat(buf, &statbuf) == 0 && /* it exists */ - S_ISDIR(statbuf.st_mode) && /* it's a directory */ - case_ok(buf, len, namelen, name)) { /* case matches */ - if (find_init_module(buf)) { /* and has __init__.py */ - Py_XDECREF(copy); - return &fd_package; - } - else { - char warnstr[MAXPATHLEN+80]; - sprintf(warnstr, "Not importing directory " - "'%.*s': missing __init__.py", - MAXPATHLEN, buf); - if (PyErr_Warn(PyExc_ImportWarning, - warnstr)) { - Py_XDECREF(copy); - return NULL; - } - } - } -#else - /* XXX How are you going to test for directories? */ -#ifdef RISCOS - if (isdir(buf) && - case_ok(buf, len, namelen, name)) { - if (find_init_module(buf)) { - Py_XDECREF(copy); - return &fd_package; - } - else { - char warnstr[MAXPATHLEN+80]; - sprintf(warnstr, "Not importing directory " - "'%.*s': missing __init__.py", - MAXPATHLEN, buf); - if (PyErr_Warn(PyExc_ImportWarning, - warnstr)) { - Py_XDECREF(copy); - return NULL; - } - } -#endif -#endif -#if defined(PYOS_OS2) - /* take a snapshot of the module spec for restoration - * after the 8 character DLL hackery - */ - saved_buf = strdup(buf); - saved_len = len; - saved_namelen = namelen; -#endif /* PYOS_OS2 */ - for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) { -#if defined(PYOS_OS2) - /* OS/2 limits DLLs to 8 character names (w/o - extension) - * so if the name is longer than that and its a - * dynamically loaded module we're going to try, - * truncate the name before trying - */ - if (strlen(subname) > 8) { - /* is this an attempt to load a C extension? */ - const struct filedescr *scan; - scan = _PyImport_DynLoadFiletab; - while (scan->suffix != NULL) { - if (!strcmp(scan->suffix, fdp->suffix)) - break; - else - scan++; - } - if (scan->suffix != NULL) { - /* yes, so truncate the name */ - namelen = 8; - len -= strlen(subname) - namelen; - buf[len] = '\0'; - } - } -#endif /* PYOS_OS2 */ - strcpy(buf+len, fdp->suffix); - if (Py_VerboseFlag > 1) - PySys_WriteStderr("# trying %s\n", buf); - filemode = fdp->mode; - if (filemode[0] == 'U') - filemode = "r" PY_STDIOTEXTMODE; - fp = fopen(buf, filemode); - if (fp != NULL) { - if (case_ok(buf, len, namelen, name)) - break; - else { /* continue search */ - fclose(fp); - fp = NULL; - } - } -#if defined(PYOS_OS2) - /* restore the saved snapshot */ - strcpy(buf, saved_buf); - len = saved_len; - namelen = saved_namelen; -#endif - } -#if defined(PYOS_OS2) - /* don't need/want the module name snapshot anymore */ - if (saved_buf) - { - free(saved_buf); - saved_buf = NULL; - } -#endif - Py_XDECREF(copy); - if (fp != NULL) - break; - } - if (fp == NULL) { - PyErr_Format(PyExc_ImportError, - "No module named %.200s", name); - return NULL; - } - *p_fp = fp; - return fdp; -} - -/* Helpers for main.c - * Find the source file corresponding to a named module - */ -struct filedescr * -_PyImport_FindModule(const char *name, PyObject *path, char *buf, - size_t buflen, FILE **p_fp, PyObject **p_loader) -{ - return find_module((char *) name, (char *) name, path, - buf, buflen, p_fp, p_loader); -} - -PyAPI_FUNC(int) _PyImport_IsScript(struct filedescr * fd) -{ - return fd->type == PY_SOURCE || fd->type == PY_COMPILED; -} - -/* case_ok(char* buf, Py_ssize_t len, Py_ssize_t namelen, char* name) - * The arguments here are tricky, best shown by example: - * /a/b/c/d/e/f/g/h/i/j/k/some_long_module_name.py\0 - * ^ ^ ^ ^ - * |--------------------- buf ---------------------| - * |------------------- len ------------------| - * |------ name -------| - * |----- namelen -----| - * buf is the full path, but len only counts up to (& exclusive of) the - * extension. name is the module name, also exclusive of extension. - * - * We've already done a successful stat() or fopen() on buf, so know that - * there's some match, possibly case-insensitive. - * - * case_ok() is to return 1 if there's a case-sensitive match for - * name, else 0. case_ok() is also to return 1 if envar PYTHONCASEOK - * exists. - * - * case_ok() is used to implement case-sensitive import semantics even - * on platforms with case-insensitive filesystems. It's trivial to implement - * for case-sensitive filesystems. It's pretty much a cross-platform - * nightmare for systems with case-insensitive filesystems. - */ - -/* First we may need a pile of platform-specific header files; the sequence - * of #if's here should match the sequence in the body of case_ok(). - */ -#if defined(MS_WINDOWS) -#include <windows.h> - -#elif defined(DJGPP) -#include <dir.h> - -#elif (defined(__MACH__) && defined(__APPLE__) || defined(__CYGWIN__)) && defined(HAVE_DIRENT_H) -#include <sys/types.h> -#include <dirent.h> - -#elif defined(PYOS_OS2) -#define INCL_DOS -#define INCL_DOSERRORS -#define INCL_NOPMAPI -#include <os2.h> - -#elif defined(RISCOS) -#include "oslib/osfscontrol.h" -#endif - -static int -case_ok(char *buf, Py_ssize_t len, Py_ssize_t namelen, char *name) -{ -/* Pick a platform-specific implementation; the sequence of #if's here should - * match the sequence just above. - */ - -/* MS_WINDOWS */ -#if defined(MS_WINDOWS) - WIN32_FIND_DATA data; - HANDLE h; - - if (Py_GETENV("PYTHONCASEOK") != NULL) - return 1; - - h = FindFirstFile(buf, &data); - if (h == INVALID_HANDLE_VALUE) { - PyErr_Format(PyExc_NameError, - "Can't find file for module %.100s\n(filename %.300s)", - name, buf); - return 0; - } - FindClose(h); - return strncmp(data.cFileName, name, namelen) == 0; - -/* DJGPP */ -#elif defined(DJGPP) - struct ffblk ffblk; - int done; - - if (Py_GETENV("PYTHONCASEOK") != NULL) - return 1; - - done = findfirst(buf, &ffblk, FA_ARCH|FA_RDONLY|FA_HIDDEN|FA_DIREC); - if (done) { - PyErr_Format(PyExc_NameError, - "Can't find file for module %.100s\n(filename %.300s)", - name, buf); - return 0; - } - return strncmp(ffblk.ff_name, name, namelen) == 0; - -/* new-fangled macintosh (macosx) or Cygwin */ -#elif (defined(__MACH__) && defined(__APPLE__) || defined(__CYGWIN__)) && defined(HAVE_DIRENT_H) - DIR *dirp; - struct dirent *dp; - char dirname[MAXPATHLEN + 1]; - const int dirlen = len - namelen - 1; /* don't want trailing SEP */ - - if (Py_GETENV("PYTHONCASEOK") != NULL) - return 1; - - /* Copy the dir component into dirname; substitute "." if empty */ - if (dirlen <= 0) { - dirname[0] = '.'; - dirname[1] = '\0'; - } - else { - assert(dirlen <= MAXPATHLEN); - memcpy(dirname, buf, dirlen); - dirname[dirlen] = '\0'; - } - /* Open the directory and search the entries for an exact match. */ - dirp = opendir(dirname); - if (dirp) { - char *nameWithExt = buf + len - namelen; - while ((dp = readdir(dirp)) != NULL) { - const int thislen = -#ifdef _DIRENT_HAVE_D_NAMELEN - dp->d_namlen; -#else - strlen(dp->d_name); -#endif - if (thislen >= namelen && - strcmp(dp->d_name, nameWithExt) == 0) { - (void)closedir(dirp); - return 1; /* Found */ - } - } - (void)closedir(dirp); - } - return 0 ; /* Not found */ - -/* RISC OS */ -#elif defined(RISCOS) - char canon[MAXPATHLEN+1]; /* buffer for the canonical form of the path */ - char buf2[MAXPATHLEN+2]; - char *nameWithExt = buf+len-namelen; - int canonlen; - os_error *e; - - if (Py_GETENV("PYTHONCASEOK") != NULL) - return 1; - - /* workaround: - append wildcard, otherwise case of filename wouldn't be touched */ - strcpy(buf2, buf); - strcat(buf2, "*"); - - e = xosfscontrol_canonicalise_path(buf2,canon,0,0,MAXPATHLEN+1,&canonlen); - canonlen = MAXPATHLEN+1-canonlen; - if (e || canonlen<=0 || canonlen>(MAXPATHLEN+1) ) - return 0; - if (strcmp(nameWithExt, canon+canonlen-strlen(nameWithExt))==0) - return 1; /* match */ - - return 0; - -/* OS/2 */ -#elif defined(PYOS_OS2) - HDIR hdir = 1; - ULONG srchcnt = 1; - FILEFINDBUF3 ffbuf; - APIRET rc; - - if (getenv("PYTHONCASEOK") != NULL) - return 1; - - rc = DosFindFirst(buf, - &hdir, - FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY, - &ffbuf, sizeof(ffbuf), - &srchcnt, - FIL_STANDARD); - if (rc != NO_ERROR) - return 0; - return strncmp(ffbuf.achName, name, namelen) == 0; - -/* assuming it's a case-sensitive filesystem, so there's nothing to do! */ -#else - return 1; - -#endif -} - - -#ifdef HAVE_STAT -/* Helper to look for __init__.py or __init__.py[co] in potential package */ -static int -find_init_module(char *buf) -{ - const size_t save_len = strlen(buf); - size_t i = save_len; - char *pname; /* pointer to start of __init__ */ - struct stat statbuf; - -/* For calling case_ok(buf, len, namelen, name): - * /a/b/c/d/e/f/g/h/i/j/k/some_long_module_name.py\0 - * ^ ^ ^ ^ - * |--------------------- buf ---------------------| - * |------------------- len ------------------| - * |------ name -------| - * |----- namelen -----| - */ - if (save_len + 13 >= MAXPATHLEN) - return 0; - buf[i++] = SEP; - pname = buf + i; - strcpy(pname, "__init__.py"); - if (stat(buf, &statbuf) == 0) { - if (case_ok(buf, - save_len + 9, /* len("/__init__") */ - 8, /* len("__init__") */ - pname)) { - buf[save_len] = '\0'; - return 1; - } - } - i += strlen(pname); - strcpy(buf+i, Py_OptimizeFlag ? "o" : "c"); - if (stat(buf, &statbuf) == 0) { - if (case_ok(buf, - save_len + 9, /* len("/__init__") */ - 8, /* len("__init__") */ - pname)) { - buf[save_len] = '\0'; - return 1; - } - } - buf[save_len] = '\0'; - return 0; -} - -#else - -#ifdef RISCOS -static int -find_init_module(buf) - char *buf; -{ - int save_len = strlen(buf); - int i = save_len; - - if (save_len + 13 >= MAXPATHLEN) - return 0; - buf[i++] = SEP; - strcpy(buf+i, "__init__/py"); - if (isfile(buf)) { - buf[save_len] = '\0'; - return 1; - } - - if (Py_OptimizeFlag) - strcpy(buf+i, "o"); - else - strcpy(buf+i, "c"); - if (isfile(buf)) { - buf[save_len] = '\0'; - return 1; - } - buf[save_len] = '\0'; - return 0; -} -#endif /*RISCOS*/ - -#endif /* HAVE_STAT */ - - -static int init_builtin(char *); /* Forward */ - -/* Load an external module using the default search path and return - its module object WITH INCREMENTED REFERENCE COUNT */ - -static PyObject * -load_module(char *name, FILE *fp, char *buf, int type, PyObject *loader) -{ - PyObject *modules; - PyObject *m; - int err; - - /* First check that there's an open file (if we need one) */ - switch (type) { - case PY_SOURCE: - case PY_COMPILED: - if (fp == NULL) { - PyErr_Format(PyExc_ValueError, - "file object required for import (type code %d)", - type); - return NULL; - } - } - - switch (type) { - - case PY_SOURCE: - m = load_source_module(name, buf, fp); - break; - - case PY_COMPILED: - m = load_compiled_module(name, buf, fp); - break; - -#ifdef HAVE_DYNAMIC_LOADING - case C_EXTENSION: - m = _PyImport_LoadDynamicModule(name, buf, fp); - break; -#endif - - case PKG_DIRECTORY: - m = load_package(name, buf); - break; - - case C_BUILTIN: - case PY_FROZEN: - if (buf != NULL && buf[0] != '\0') - name = buf; - if (type == C_BUILTIN) - err = init_builtin(name); - else - err = PyImport_ImportFrozenModule(name); - if (err < 0) - return NULL; - if (err == 0) { - PyErr_Format(PyExc_ImportError, - "Purported %s module %.200s not found", - type == C_BUILTIN ? - "builtin" : "frozen", - name); - return NULL; - } - modules = PyImport_GetModuleDict(); - m = PyDict_GetItemString(modules, name); - if (m == NULL) { - PyErr_Format( - PyExc_ImportError, - "%s module %.200s not properly initialized", - type == C_BUILTIN ? - "builtin" : "frozen", - name); - return NULL; - } - Py_INCREF(m); - break; - - case IMP_HOOK: { - if (loader == NULL) { - PyErr_SetString(PyExc_ImportError, - "import hook without loader"); - return NULL; - } - m = PyObject_CallMethod(loader, "load_module", "s", name); - break; - } - - default: - PyErr_Format(PyExc_ImportError, - "Don't know how to import %.200s (type code %d)", - name, type); - m = NULL; - - } - - return m; -} - - -/* Initialize a built-in module. - Return 1 for succes, 0 if the module is not found, and -1 with - an exception set if the initialization failed. */ - -static int -init_builtin(char *name) -{ - struct _inittab *p; - - if (_PyImport_FindExtension(name, name) != NULL) - return 1; - - for (p = PyImport_Inittab; p->name != NULL; p++) { - if (strcmp(name, p->name) == 0) { - if (p->initfunc == NULL) { - PyErr_Format(PyExc_ImportError, - "Cannot re-init internal module %.200s", - name); - return -1; - } - if (Py_VerboseFlag) - PySys_WriteStderr("import %s # builtin\n", name); - (*p->initfunc)(); - if (PyErr_Occurred()) - return -1; - if (_PyImport_FixupExtension(name, name) == NULL) - return -1; - return 1; - } - } - return 0; -} - - -/* Frozen modules */ - -static struct _frozen * -find_frozen(char *name) -{ - struct _frozen *p; - - for (p = PyImport_FrozenModules; ; p++) { - if (p->name == NULL) - return NULL; - if (strcmp(p->name, name) == 0) - break; - } - return p; -} - -static PyObject * -get_frozen_object(char *name) -{ - struct _frozen *p = find_frozen(name); - int size; - - if (p == NULL) { - PyErr_Format(PyExc_ImportError, - "No such frozen object named %.200s", - name); - return NULL; - } - if (p->code == NULL) { - PyErr_Format(PyExc_ImportError, - "Excluded frozen object named %.200s", - name); - return NULL; - } - size = p->size; - if (size < 0) - size = -size; - return PyMarshal_ReadObjectFromString((char *)p->code, size); -} - -/* Initialize a frozen module. - Return 1 for succes, 0 if the module is not found, and -1 with - an exception set if the initialization failed. - This function is also used from frozenmain.c */ - -int -PyImport_ImportFrozenModule(char *name) -{ - struct _frozen *p = find_frozen(name); - PyObject *co; - PyObject *m; - int ispackage; - int size; - - if (p == NULL) - return 0; - if (p->code == NULL) { - PyErr_Format(PyExc_ImportError, - "Excluded frozen object named %.200s", - name); - return -1; - } - size = p->size; - ispackage = (size < 0); - if (ispackage) - size = -size; - if (Py_VerboseFlag) - PySys_WriteStderr("import %s # frozen%s\n", - name, ispackage ? " package" : ""); - co = PyMarshal_ReadObjectFromString((char *)p->code, size); - if (co == NULL) - return -1; - if (!PyCode_Check(co)) { - PyErr_Format(PyExc_TypeError, - "frozen object %.200s is not a code object", - name); - goto err_return; - } - if (ispackage) { - /* Set __path__ to the package name */ - PyObject *d, *s; - int err; - m = PyImport_AddModule(name); - if (m == NULL) - goto err_return; - d = PyModule_GetDict(m); - s = PyString_InternFromString(name); - if (s == NULL) - goto err_return; - err = PyDict_SetItemString(d, "__path__", s); - Py_DECREF(s); - if (err != 0) - goto err_return; - } - m = PyImport_ExecCodeModuleEx(name, co, "<frozen>"); - if (m == NULL) - goto err_return; - Py_DECREF(co); - Py_DECREF(m); - return 1; -err_return: - Py_DECREF(co); - return -1; -} - - -/* Import a module, either built-in, frozen, or external, and return - its module object WITH INCREMENTED REFERENCE COUNT */ - -PyObject * -PyImport_ImportModule(const char *name) -{ - PyObject *pname; - PyObject *result; - - pname = PyString_FromString(name); - if (pname == NULL) - return NULL; - result = PyImport_Import(pname); - Py_DECREF(pname); - return result; -} - -/* Forward declarations for helper routines */ -static PyObject *get_parent(PyObject *globals, char *buf, - Py_ssize_t *p_buflen, int level); -static PyObject *load_next(PyObject *mod, PyObject *altmod, - char **p_name, char *buf, Py_ssize_t *p_buflen); -static int mark_miss(char *name); -static int ensure_fromlist(PyObject *mod, PyObject *fromlist, - char *buf, Py_ssize_t buflen, int recursive); -static PyObject * import_submodule(PyObject *mod, char *name, char *fullname); - -/* The Magnum Opus of dotted-name import :-) */ - -static PyObject * -import_module_level(char *name, PyObject *globals, PyObject *locals, - PyObject *fromlist, int level) -{ - char buf[MAXPATHLEN+1]; - Py_ssize_t buflen = 0; - PyObject *parent, *head, *next, *tail; - - parent = get_parent(globals, buf, &buflen, level); - if (parent == NULL) - return NULL; - - head = load_next(parent, Py_None, &name, buf, &buflen); - if (head == NULL) - return NULL; - - tail = head; - Py_INCREF(tail); - while (name) { - next = load_next(tail, tail, &name, buf, &buflen); - Py_DECREF(tail); - if (next == NULL) { - Py_DECREF(head); - return NULL; - } - tail = next; - } - if (tail == Py_None) { - /* If tail is Py_None, both get_parent and load_next found - an empty module name: someone called __import__("") or - doctored faulty bytecode */ - Py_DECREF(tail); - Py_DECREF(head); - PyErr_SetString(PyExc_ValueError, - "Empty module name"); - return NULL; - } - - if (fromlist != NULL) { - if (fromlist == Py_None || !PyObject_IsTrue(fromlist)) - fromlist = NULL; - } - - if (fromlist == NULL) { - Py_DECREF(tail); - return head; - } - - Py_DECREF(head); - if (!ensure_fromlist(tail, fromlist, buf, buflen, 0)) { - Py_DECREF(tail); - return NULL; - } - - return tail; -} - -/* For DLL compatibility */ -#undef PyImport_ImportModuleEx -PyObject * -PyImport_ImportModuleEx(char *name, PyObject *globals, PyObject *locals, - PyObject *fromlist) -{ - PyObject *result; - lock_import(); - result = import_module_level(name, globals, locals, fromlist, -1); - if (unlock_import() < 0) { - Py_XDECREF(result); - PyErr_SetString(PyExc_RuntimeError, - "not holding the import lock"); - return NULL; - } - return result; -} -#define PyImport_ImportModuleEx(n, g, l, f) \ - PyImport_ImportModuleLevel(n, g, l, f, -1); - -PyObject * -PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, - PyObject *fromlist, int level) -{ - PyObject *result; - lock_import(); - result = import_module_level(name, globals, locals, fromlist, level); - if (unlock_import() < 0) { - Py_XDECREF(result); - PyErr_SetString(PyExc_RuntimeError, - "not holding the import lock"); - return NULL; - } - return result; -} - -/* Return the package that an import is being performed in. If globals comes - from the module foo.bar.bat (not itself a package), this returns the - sys.modules entry for foo.bar. If globals is from a package's __init__.py, - the package's entry in sys.modules is returned, as a borrowed reference. - - The *name* of the returned package is returned in buf, with the length of - the name in *p_buflen. - - If globals doesn't come from a package or a module in a package, or a - corresponding entry is not found in sys.modules, Py_None is returned. -*/ -static PyObject * -get_parent(PyObject *globals, char *buf, Py_ssize_t *p_buflen, int level) -{ - static PyObject *namestr = NULL; - static PyObject *pathstr = NULL; - PyObject *modname, *modpath, *modules, *parent; - - if (globals == NULL || !PyDict_Check(globals) || !level) - return Py_None; - - if (namestr == NULL) { - namestr = PyString_InternFromString("__name__"); - if (namestr == NULL) - return NULL; - } - if (pathstr == NULL) { - pathstr = PyString_InternFromString("__path__"); - if (pathstr == NULL) - return NULL; - } - - *buf = '\0'; - *p_buflen = 0; - modname = PyDict_GetItem(globals, namestr); - if (modname == NULL || !PyString_Check(modname)) - return Py_None; - - modpath = PyDict_GetItem(globals, pathstr); - if (modpath != NULL) { - Py_ssize_t len = PyString_GET_SIZE(modname); - if (len > MAXPATHLEN) { - PyErr_SetString(PyExc_ValueError, - "Module name too long"); - return NULL; - } - strcpy(buf, PyString_AS_STRING(modname)); - } - else { - char *start = PyString_AS_STRING(modname); - char *lastdot = strrchr(start, '.'); - size_t len; - if (lastdot == NULL && level > 0) { - PyErr_SetString(PyExc_ValueError, - "Attempted relative import in non-package"); - return NULL; - } - if (lastdot == NULL) - return Py_None; - len = lastdot - start; - if (len >= MAXPATHLEN) { - PyErr_SetString(PyExc_ValueError, - "Module name too long"); - return NULL; - } - strncpy(buf, start, len); - buf[len] = '\0'; - } - - while (--level > 0) { - char *dot = strrchr(buf, '.'); - if (dot == NULL) { - PyErr_SetString(PyExc_ValueError, - "Attempted relative import beyond " - "toplevel package"); - return NULL; - } - *dot = '\0'; - } - *p_buflen = strlen(buf); - - modules = PyImport_GetModuleDict(); - parent = PyDict_GetItemString(modules, buf); - if (parent == NULL) - PyErr_Format(PyExc_SystemError, - "Parent module '%.200s' not loaded", buf); - return parent; - /* We expect, but can't guarantee, if parent != None, that: - - parent.__name__ == buf - - parent.__dict__ is globals - If this is violated... Who cares? */ -} - -/* altmod is either None or same as mod */ -static PyObject * -load_next(PyObject *mod, PyObject *altmod, char **p_name, char *buf, - Py_ssize_t *p_buflen) -{ - char *name = *p_name; - char *dot = strchr(name, '.'); - size_t len; - char *p; - PyObject *result; - - if (strlen(name) == 0) { - /* completely empty module name should only happen in - 'from . import' (or '__import__("")')*/ - Py_INCREF(mod); - *p_name = NULL; - return mod; - } - - if (dot == NULL) { - *p_name = NULL; - len = strlen(name); - } - else { - *p_name = dot+1; - len = dot-name; - } - if (len == 0) { - PyErr_SetString(PyExc_ValueError, - "Empty module name"); - return NULL; - } - - p = buf + *p_buflen; - if (p != buf) - *p++ = '.'; - if (p+len-buf >= MAXPATHLEN) { - PyErr_SetString(PyExc_ValueError, - "Module name too long"); - return NULL; - } - strncpy(p, name, len); - p[len] = '\0'; - *p_buflen = p+len-buf; - - result = import_submodule(mod, p, buf); - if (result == Py_None && altmod != mod) { - Py_DECREF(result); - /* Here, altmod must be None and mod must not be None */ - result = import_submodule(altmod, p, p); - if (result != NULL && result != Py_None) { - if (mark_miss(buf) != 0) { - Py_DECREF(result); - return NULL; - } - strncpy(buf, name, len); - buf[len] = '\0'; - *p_buflen = len; - } - } - if (result == NULL) - return NULL; - - if (result == Py_None) { - Py_DECREF(result); - PyErr_Format(PyExc_ImportError, - "No module named %.200s", name); - return NULL; - } - - return result; -} - -static int -mark_miss(char *name) -{ - PyObject *modules = PyImport_GetModuleDict(); - return PyDict_SetItemString(modules, name, Py_None); -} - -static int -ensure_fromlist(PyObject *mod, PyObject *fromlist, char *buf, Py_ssize_t buflen, - int recursive) -{ - int i; - - if (!PyObject_HasAttrString(mod, "__path__")) - return 1; - - for (i = 0; ; i++) { - PyObject *item = PySequence_GetItem(fromlist, i); - int hasit; - if (item == NULL) { - if (PyErr_ExceptionMatches(PyExc_IndexError)) { - PyErr_Clear(); - return 1; - } - return 0; - } - if (!PyString_Check(item)) { - PyErr_SetString(PyExc_TypeError, - "Item in ``from list'' not a string"); - Py_DECREF(item); - return 0; - } - if (PyString_AS_STRING(item)[0] == '*') { - PyObject *all; - Py_DECREF(item); - /* See if the package defines __all__ */ - if (recursive) - continue; /* Avoid endless recursion */ - all = PyObject_GetAttrString(mod, "__all__"); - if (all == NULL) - PyErr_Clear(); - else { - int ret = ensure_fromlist(mod, all, buf, buflen, 1); - Py_DECREF(all); - if (!ret) - return 0; - } - continue; - } - hasit = PyObject_HasAttr(mod, item); - if (!hasit) { - char *subname = PyString_AS_STRING(item); - PyObject *submod; - char *p; - if (buflen + strlen(subname) >= MAXPATHLEN) { - PyErr_SetString(PyExc_ValueError, - "Module name too long"); - Py_DECREF(item); - return 0; - } - p = buf + buflen; - *p++ = '.'; - strcpy(p, subname); - submod = import_submodule(mod, subname, buf); - Py_XDECREF(submod); - if (submod == NULL) { - Py_DECREF(item); - return 0; - } - } - Py_DECREF(item); - } - - /* NOTREACHED */ -} - -static int -add_submodule(PyObject *mod, PyObject *submod, char *fullname, char *subname, - PyObject *modules) -{ - if (mod == Py_None) - return 1; - /* Irrespective of the success of this load, make a - reference to it in the parent package module. A copy gets - saved in the modules dictionary under the full name, so get a - reference from there, if need be. (The exception is when the - load failed with a SyntaxError -- then there's no trace in - sys.modules. In that case, of course, do nothing extra.) */ - if (submod == NULL) { - submod = PyDict_GetItemString(modules, fullname); - if (submod == NULL) - return 1; - } - if (PyModule_Check(mod)) { - /* We can't use setattr here since it can give a - * spurious warning if the submodule name shadows a - * builtin name */ - PyObject *dict = PyModule_GetDict(mod); - if (!dict) - return 0; - if (PyDict_SetItemString(dict, subname, submod) < 0) - return 0; - } - else { - if (PyObject_SetAttrString(mod, subname, submod) < 0) - return 0; - } - return 1; -} - -static PyObject * -import_submodule(PyObject *mod, char *subname, char *fullname) -{ - PyObject *modules = PyImport_GetModuleDict(); - PyObject *m = NULL; - - /* Require: - if mod == None: subname == fullname - else: mod.__name__ + "." + subname == fullname - */ - - if ((m = PyDict_GetItemString(modules, fullname)) != NULL) { - Py_INCREF(m); - } - else { - PyObject *path, *loader = NULL; - char buf[MAXPATHLEN+1]; - struct filedescr *fdp; - FILE *fp = NULL; - - if (mod == Py_None) - path = NULL; - else { - path = PyObject_GetAttrString(mod, "__path__"); - if (path == NULL) { - PyErr_Clear(); - Py_INCREF(Py_None); - return Py_None; - } - } - - buf[0] = '\0'; - fdp = find_module(fullname, subname, path, buf, MAXPATHLEN+1, - &fp, &loader); - Py_XDECREF(path); - if (fdp == NULL) { - if (!PyErr_ExceptionMatches(PyExc_ImportError)) - return NULL; - PyErr_Clear(); - Py_INCREF(Py_None); - return Py_None; - } - m = load_module(fullname, fp, buf, fdp->type, loader); - Py_XDECREF(loader); - if (fp) - fclose(fp); - if (!add_submodule(mod, m, fullname, subname, modules)) { - Py_XDECREF(m); - m = NULL; - } - } - - return m; -} - - -/* Re-import a module of any kind and return its module object, WITH - INCREMENTED REFERENCE COUNT */ - -PyObject * -PyImport_ReloadModule(PyObject *m) -{ - PyInterpreterState *interp = PyThreadState_Get()->interp; - PyObject *modules_reloading = interp->modules_reloading; - PyObject *modules = PyImport_GetModuleDict(); - PyObject *path = NULL, *loader = NULL, *existing_m = NULL; - char *name, *subname; - char buf[MAXPATHLEN+1]; - struct filedescr *fdp; - FILE *fp = NULL; - PyObject *newm; - - if (modules_reloading == NULL) { - Py_FatalError("PyImport_ReloadModule: " - "no modules_reloading dictionary!"); - return NULL; - } - - if (m == NULL || !PyModule_Check(m)) { - PyErr_SetString(PyExc_TypeError, - "reload() argument must be module"); - return NULL; - } - name = PyModule_GetName(m); - if (name == NULL) - return NULL; - if (m != PyDict_GetItemString(modules, name)) { - PyErr_Format(PyExc_ImportError, - "reload(): module %.200s not in sys.modules", - name); - return NULL; - } - if ((existing_m = PyDict_GetItemString(modules_reloading, name)) != NULL) { - /* Due to a recursive reload, this module is already being reloaded. */ - Py_INCREF(existing_m); - return existing_m; - } - PyDict_SetItemString(modules_reloading, name, m); - - subname = strrchr(name, '.'); - if (subname == NULL) - subname = name; - else { - PyObject *parentname, *parent; - parentname = PyString_FromStringAndSize(name, (subname-name)); - if (parentname == NULL) { - imp_modules_reloading_clear(); - return NULL; - } - parent = PyDict_GetItem(modules, parentname); - if (parent == NULL) { - PyErr_Format(PyExc_ImportError, - "reload(): parent %.200s not in sys.modules", - PyString_AS_STRING(parentname)); - Py_DECREF(parentname); - imp_modules_reloading_clear(); - return NULL; - } - Py_DECREF(parentname); - subname++; - path = PyObject_GetAttrString(parent, "__path__"); - if (path == NULL) - PyErr_Clear(); - } - buf[0] = '\0'; - fdp = find_module(name, subname, path, buf, MAXPATHLEN+1, &fp, &loader); - Py_XDECREF(path); - - if (fdp == NULL) { - Py_XDECREF(loader); - imp_modules_reloading_clear(); - return NULL; - } - - newm = load_module(name, fp, buf, fdp->type, loader); - Py_XDECREF(loader); - - if (fp) - fclose(fp); - if (newm == NULL) { - /* load_module probably removed name from modules because of - * the error. Put back the original module object. We're - * going to return NULL in this case regardless of whether - * replacing name succeeds, so the return value is ignored. - */ - PyDict_SetItemString(modules, name, m); - } - imp_modules_reloading_clear(); - return newm; -} - - -/* Higher-level import emulator which emulates the "import" statement - more accurately -- it invokes the __import__() function from the - builtins of the current globals. This means that the import is - done using whatever import hooks are installed in the current - environment, e.g. by "rexec". - A dummy list ["__doc__"] is passed as the 4th argument so that - e.g. PyImport_Import(PyString_FromString("win32com.client.gencache")) - will return <module "gencache"> instead of <module "win32com">. */ - -PyObject * -PyImport_Import(PyObject *module_name) -{ - static PyObject *silly_list = NULL; - static PyObject *builtins_str = NULL; - static PyObject *import_str = NULL; - PyObject *globals = NULL; - PyObject *import = NULL; - PyObject *builtins = NULL; - PyObject *r = NULL; - - /* Initialize constant string objects */ - if (silly_list == NULL) { - import_str = PyString_InternFromString("__import__"); - if (import_str == NULL) - return NULL; - builtins_str = PyString_InternFromString("__builtins__"); - if (builtins_str == NULL) - return NULL; - silly_list = Py_BuildValue("[s]", "__doc__"); - if (silly_list == NULL) - return NULL; - } - - /* Get the builtins from current globals */ - globals = PyEval_GetGlobals(); - if (globals != NULL) { - Py_INCREF(globals); - builtins = PyObject_GetItem(globals, builtins_str); - if (builtins == NULL) - goto err; - } - else { - /* No globals -- use standard builtins, and fake globals */ - PyErr_Clear(); - - builtins = PyImport_ImportModuleLevel("__builtin__", - NULL, NULL, NULL, 0); - if (builtins == NULL) - return NULL; - globals = Py_BuildValue("{OO}", builtins_str, builtins); - if (globals == NULL) - goto err; - } - - /* Get the __import__ function from the builtins */ - if (PyDict_Check(builtins)) { - import = PyObject_GetItem(builtins, import_str); - if (import == NULL) - PyErr_SetObject(PyExc_KeyError, import_str); - } - else - import = PyObject_GetAttr(builtins, import_str); - if (import == NULL) - goto err; - - /* Call the _import__ function with the proper argument list */ - r = PyObject_CallFunctionObjArgs(import, module_name, globals, - globals, silly_list, NULL); - - err: - Py_XDECREF(globals); - Py_XDECREF(builtins); - Py_XDECREF(import); - - return r; -} - - -/* Module 'imp' provides Python access to the primitives used for - importing modules. -*/ - -static PyObject * -imp_get_magic(PyObject *self, PyObject *noargs) -{ - char buf[4]; - - buf[0] = (char) ((pyc_magic >> 0) & 0xff); - buf[1] = (char) ((pyc_magic >> 8) & 0xff); - buf[2] = (char) ((pyc_magic >> 16) & 0xff); - buf[3] = (char) ((pyc_magic >> 24) & 0xff); - - return PyString_FromStringAndSize(buf, 4); -} - -static PyObject * -imp_get_suffixes(PyObject *self, PyObject *noargs) -{ - PyObject *list; - struct filedescr *fdp; - - list = PyList_New(0); - if (list == NULL) - return NULL; - for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) { - PyObject *item = Py_BuildValue("ssi", - fdp->suffix, fdp->mode, fdp->type); - if (item == NULL) { - Py_DECREF(list); - return NULL; - } - if (PyList_Append(list, item) < 0) { - Py_DECREF(list); - Py_DECREF(item); - return NULL; - } - Py_DECREF(item); - } - return list; -} - -static PyObject * -call_find_module(char *name, PyObject *path) -{ - extern int fclose(FILE *); - PyObject *fob, *ret; - struct filedescr *fdp; - char pathname[MAXPATHLEN+1]; - FILE *fp = NULL; - - pathname[0] = '\0'; - if (path == Py_None) - path = NULL; - fdp = find_module(NULL, name, path, pathname, MAXPATHLEN+1, &fp, NULL); - if (fdp == NULL) - return NULL; - if (fp != NULL) { - fob = PyFile_FromFile(fp, pathname, fdp->mode, fclose); - if (fob == NULL) { - fclose(fp); - return NULL; - } - } - else { - fob = Py_None; - Py_INCREF(fob); - } - ret = Py_BuildValue("Os(ssi)", - fob, pathname, fdp->suffix, fdp->mode, fdp->type); - Py_DECREF(fob); - return ret; -} - -static PyObject * -imp_find_module(PyObject *self, PyObject *args) -{ - char *name; - PyObject *path = NULL; - if (!PyArg_ParseTuple(args, "s|O:find_module", &name, &path)) - return NULL; - return call_find_module(name, path); -} - -static PyObject * -imp_init_builtin(PyObject *self, PyObject *args) -{ - char *name; - int ret; - PyObject *m; - if (!PyArg_ParseTuple(args, "s:init_builtin", &name)) - return NULL; - ret = init_builtin(name); - if (ret < 0) - return NULL; - if (ret == 0) { - Py_INCREF(Py_None); - return Py_None; - } - m = PyImport_AddModule(name); - Py_XINCREF(m); - return m; -} - -static PyObject * -imp_init_frozen(PyObject *self, PyObject *args) -{ - char *name; - int ret; - PyObject *m; - if (!PyArg_ParseTuple(args, "s:init_frozen", &name)) - return NULL; - ret = PyImport_ImportFrozenModule(name); - if (ret < 0) - return NULL; - if (ret == 0) { - Py_INCREF(Py_None); - return Py_None; - } - m = PyImport_AddModule(name); - Py_XINCREF(m); - return m; -} - -static PyObject * -imp_get_frozen_object(PyObject *self, PyObject *args) -{ - char *name; - - if (!PyArg_ParseTuple(args, "s:get_frozen_object", &name)) - return NULL; - return get_frozen_object(name); -} - -static PyObject * -imp_is_builtin(PyObject *self, PyObject *args) -{ - char *name; - if (!PyArg_ParseTuple(args, "s:is_builtin", &name)) - return NULL; - return PyInt_FromLong(is_builtin(name)); -} - -static PyObject * -imp_is_frozen(PyObject *self, PyObject *args) -{ - char *name; - struct _frozen *p; - if (!PyArg_ParseTuple(args, "s:is_frozen", &name)) - return NULL; - p = find_frozen(name); - return PyBool_FromLong((long) (p == NULL ? 0 : p->size)); -} - -static FILE * -get_file(char *pathname, PyObject *fob, char *mode) -{ - FILE *fp; - if (fob == NULL) { - if (mode[0] == 'U') - mode = "r" PY_STDIOTEXTMODE; - fp = fopen(pathname, mode); - if (fp == NULL) - PyErr_SetFromErrno(PyExc_IOError); - } - else { - fp = PyFile_AsFile(fob); - if (fp == NULL) - PyErr_SetString(PyExc_ValueError, - "bad/closed file object"); - } - return fp; -} - -static PyObject * -imp_load_compiled(PyObject *self, PyObject *args) -{ - char *name; - char *pathname; - PyObject *fob = NULL; - PyObject *m; - FILE *fp; - if (!PyArg_ParseTuple(args, "ss|O!:load_compiled", &name, &pathname, - &PyFile_Type, &fob)) - return NULL; - fp = get_file(pathname, fob, "rb"); - if (fp == NULL) - return NULL; - m = load_compiled_module(name, pathname, fp); - if (fob == NULL) - fclose(fp); - return m; -} - -#ifdef HAVE_DYNAMIC_LOADING - -static PyObject * -imp_load_dynamic(PyObject *self, PyObject *args) -{ - char *name; - char *pathname; - PyObject *fob = NULL; - PyObject *m; - FILE *fp = NULL; - if (!PyArg_ParseTuple(args, "ss|O!:load_dynamic", &name, &pathname, - &PyFile_Type, &fob)) - return NULL; - if (fob) { - fp = get_file(pathname, fob, "r"); - if (fp == NULL) - return NULL; - } - m = _PyImport_LoadDynamicModule(name, pathname, fp); - return m; -} - -#endif /* HAVE_DYNAMIC_LOADING */ - -static PyObject * -imp_load_source(PyObject *self, PyObject *args) -{ - char *name; - char *pathname; - PyObject *fob = NULL; - PyObject *m; - FILE *fp; - if (!PyArg_ParseTuple(args, "ss|O!:load_source", &name, &pathname, - &PyFile_Type, &fob)) - return NULL; - fp = get_file(pathname, fob, "r"); - if (fp == NULL) - return NULL; - m = load_source_module(name, pathname, fp); - if (fob == NULL) - fclose(fp); - return m; -} - -static PyObject * -imp_load_module(PyObject *self, PyObject *args) -{ - char *name; - PyObject *fob; - char *pathname; - char *suffix; /* Unused */ - char *mode; - int type; - FILE *fp; - - if (!PyArg_ParseTuple(args, "sOs(ssi):load_module", - &name, &fob, &pathname, - &suffix, &mode, &type)) - return NULL; - if (*mode) { - /* Mode must start with 'r' or 'U' and must not contain '+'. - Implicit in this test is the assumption that the mode - may contain other modifiers like 'b' or 't'. */ - - if (!(*mode == 'r' || *mode == 'U') || strchr(mode, '+')) { - PyErr_Format(PyExc_ValueError, - "invalid file open mode %.200s", mode); - return NULL; - } - } - if (fob == Py_None) - fp = NULL; - else { - if (!PyFile_Check(fob)) { - PyErr_SetString(PyExc_ValueError, - "load_module arg#2 should be a file or None"); - return NULL; - } - fp = get_file(pathname, fob, mode); - if (fp == NULL) - return NULL; - } - return load_module(name, fp, pathname, type, NULL); -} - -static PyObject * -imp_load_package(PyObject *self, PyObject *args) -{ - char *name; - char *pathname; - if (!PyArg_ParseTuple(args, "ss:load_package", &name, &pathname)) - return NULL; - return load_package(name, pathname); -} - -static PyObject * -imp_new_module(PyObject *self, PyObject *args) -{ - char *name; - if (!PyArg_ParseTuple(args, "s:new_module", &name)) - return NULL; - return PyModule_New(name); -} - -/* Doc strings */ - -PyDoc_STRVAR(doc_imp, -"This module provides the components needed to build your own\n\ -__import__ function. Undocumented functions are obsolete."); - -PyDoc_STRVAR(doc_find_module, -"find_module(name, [path]) -> (file, filename, (suffix, mode, type))\n\ -Search for a module. If path is omitted or None, search for a\n\ -built-in, frozen or special module and continue search in sys.path.\n\ -The module name cannot contain '.'; to search for a submodule of a\n\ -package, pass the submodule name and the package's __path__."); - -PyDoc_STRVAR(doc_load_module, -"load_module(name, file, filename, (suffix, mode, type)) -> module\n\ -Load a module, given information returned by find_module().\n\ -The module name must include the full package name, if any."); - -PyDoc_STRVAR(doc_get_magic, -"get_magic() -> string\n\ -Return the magic number for .pyc or .pyo files."); - -PyDoc_STRVAR(doc_get_suffixes, -"get_suffixes() -> [(suffix, mode, type), ...]\n\ -Return a list of (suffix, mode, type) tuples describing the files\n\ -that find_module() looks for."); - -PyDoc_STRVAR(doc_new_module, -"new_module(name) -> module\n\ -Create a new module. Do not enter it in sys.modules.\n\ -The module name must include the full package name, if any."); - -PyDoc_STRVAR(doc_lock_held, -"lock_held() -> boolean\n\ -Return True if the import lock is currently held, else False.\n\ -On platforms without threads, return False."); - -PyDoc_STRVAR(doc_acquire_lock, -"acquire_lock() -> None\n\ -Acquires the interpreter's import lock for the current thread.\n\ -This lock should be used by import hooks to ensure thread-safety\n\ -when importing modules.\n\ -On platforms without threads, this function does nothing."); - -PyDoc_STRVAR(doc_release_lock, -"release_lock() -> None\n\ -Release the interpreter's import lock.\n\ -On platforms without threads, this function does nothing."); - -static PyMethodDef imp_methods[] = { - {"find_module", imp_find_module, METH_VARARGS, doc_find_module}, - {"get_magic", imp_get_magic, METH_NOARGS, doc_get_magic}, - {"get_suffixes", imp_get_suffixes, METH_NOARGS, doc_get_suffixes}, - {"load_module", imp_load_module, METH_VARARGS, doc_load_module}, - {"new_module", imp_new_module, METH_VARARGS, doc_new_module}, - {"lock_held", imp_lock_held, METH_NOARGS, doc_lock_held}, - {"acquire_lock", imp_acquire_lock, METH_NOARGS, doc_acquire_lock}, - {"release_lock", imp_release_lock, METH_NOARGS, doc_release_lock}, - /* The rest are obsolete */ - {"get_frozen_object", imp_get_frozen_object, METH_VARARGS}, - {"init_builtin", imp_init_builtin, METH_VARARGS}, - {"init_frozen", imp_init_frozen, METH_VARARGS}, - {"is_builtin", imp_is_builtin, METH_VARARGS}, - {"is_frozen", imp_is_frozen, METH_VARARGS}, - {"load_compiled", imp_load_compiled, METH_VARARGS}, -#ifdef HAVE_DYNAMIC_LOADING - {"load_dynamic", imp_load_dynamic, METH_VARARGS}, -#endif - {"load_package", imp_load_package, METH_VARARGS}, - {"load_source", imp_load_source, METH_VARARGS}, - {NULL, NULL} /* sentinel */ -}; - -static int -setint(PyObject *d, char *name, int value) -{ - PyObject *v; - int err; - - v = PyInt_FromLong((long)value); - err = PyDict_SetItemString(d, name, v); - Py_XDECREF(v); - return err; -} - -typedef struct { - PyObject_HEAD -} NullImporter; - -static int -NullImporter_init(NullImporter *self, PyObject *args, PyObject *kwds) -{ - char *path; - - if (!_PyArg_NoKeywords("NullImporter()", kwds)) - return -1; - - if (!PyArg_ParseTuple(args, "s:NullImporter", - &path)) - return -1; - - if (strlen(path) == 0) { - PyErr_SetString(PyExc_ImportError, "empty pathname"); - return -1; - } else { -#ifndef RISCOS - struct stat statbuf; - int rv; - - rv = stat(path, &statbuf); - if (rv == 0) { - /* it exists */ - if (S_ISDIR(statbuf.st_mode)) { - /* it's a directory */ - PyErr_SetString(PyExc_ImportError, - "existing directory"); - return -1; - } - } -#else - if (object_exists(path)) { - /* it exists */ - if (isdir(path)) { - /* it's a directory */ - PyErr_SetString(PyExc_ImportError, - "existing directory"); - return -1; - } - } -#endif - } - return 0; -} - -static PyObject * -NullImporter_find_module(NullImporter *self, PyObject *args) -{ - Py_RETURN_NONE; -} - -static PyMethodDef NullImporter_methods[] = { - {"find_module", (PyCFunction)NullImporter_find_module, METH_VARARGS, - "Always return None" - }, - {NULL} /* Sentinel */ -}; - - -static PyTypeObject NullImporterType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "imp.NullImporter", /*tp_name*/ - sizeof(NullImporter), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "Null importer object", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - NullImporter_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)NullImporter_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew /* tp_new */ -}; - - -PyMODINIT_FUNC -initimp(void) -{ - PyObject *m, *d; - - if (PyType_Ready(&NullImporterType) < 0) - goto failure; - - m = Py_InitModule4("imp", imp_methods, doc_imp, - NULL, PYTHON_API_VERSION); - if (m == NULL) - goto failure; - d = PyModule_GetDict(m); - if (d == NULL) - goto failure; - - if (setint(d, "SEARCH_ERROR", SEARCH_ERROR) < 0) goto failure; - if (setint(d, "PY_SOURCE", PY_SOURCE) < 0) goto failure; - if (setint(d, "PY_COMPILED", PY_COMPILED) < 0) goto failure; - if (setint(d, "C_EXTENSION", C_EXTENSION) < 0) goto failure; - if (setint(d, "PY_RESOURCE", PY_RESOURCE) < 0) goto failure; - if (setint(d, "PKG_DIRECTORY", PKG_DIRECTORY) < 0) goto failure; - if (setint(d, "C_BUILTIN", C_BUILTIN) < 0) goto failure; - if (setint(d, "PY_FROZEN", PY_FROZEN) < 0) goto failure; - if (setint(d, "PY_CODERESOURCE", PY_CODERESOURCE) < 0) goto failure; - if (setint(d, "IMP_HOOK", IMP_HOOK) < 0) goto failure; - - Py_INCREF(&NullImporterType); - PyModule_AddObject(m, "NullImporter", (PyObject *)&NullImporterType); - failure: - ; -} - - -/* API for embedding applications that want to add their own entries - to the table of built-in modules. This should normally be called - *before* Py_Initialize(). When the table resize fails, -1 is - returned and the existing table is unchanged. - - After a similar function by Just van Rossum. */ - -int -PyImport_ExtendInittab(struct _inittab *newtab) -{ - static struct _inittab *our_copy = NULL; - struct _inittab *p; - int i, n; - - /* Count the number of entries in both tables */ - for (n = 0; newtab[n].name != NULL; n++) - ; - if (n == 0) - return 0; /* Nothing to do */ - for (i = 0; PyImport_Inittab[i].name != NULL; i++) - ; - - /* Allocate new memory for the combined table */ - p = our_copy; - PyMem_RESIZE(p, struct _inittab, i+n+1); - if (p == NULL) - return -1; - - /* Copy the tables into the new memory */ - if (our_copy != PyImport_Inittab) - memcpy(p, PyImport_Inittab, (i+1) * sizeof(struct _inittab)); - PyImport_Inittab = our_copy = p; - memcpy(p+i, newtab, (n+1) * sizeof(struct _inittab)); - - return 0; -} - -/* Shorthand to add a single entry given a name and a function */ - -int -PyImport_AppendInittab(char *name, void (*initfunc)(void)) -{ - struct _inittab newtab[2]; - - memset(newtab, '\0', sizeof newtab); - - newtab[0].name = name; - newtab[0].initfunc = initfunc; - - return PyImport_ExtendInittab(newtab); -} - -#ifdef __cplusplus -} -#endif diff --git a/sys/src/cmd/python/Python/importdl.c b/sys/src/cmd/python/Python/importdl.c deleted file mode 100644 index 9c325e447..000000000 --- a/sys/src/cmd/python/Python/importdl.c +++ /dev/null @@ -1,78 +0,0 @@ - -/* Support for dynamic loading of extension modules */ - -#include "Python.h" - -/* ./configure sets HAVE_DYNAMIC_LOADING if dynamic loading of modules is - supported on this platform. configure will then compile and link in one - of the dynload_*.c files, as appropriate. We will call a function in - those modules to get a function pointer to the module's init function. -*/ -#ifdef HAVE_DYNAMIC_LOADING - -#include "importdl.h" - -extern dl_funcptr _PyImport_GetDynLoadFunc(const char *name, - const char *shortname, - const char *pathname, FILE *fp); - - - -PyObject * -_PyImport_LoadDynamicModule(char *name, char *pathname, FILE *fp) -{ - PyObject *m; - char *lastdot, *shortname, *packagecontext, *oldcontext; - dl_funcptr p; - - if ((m = _PyImport_FindExtension(name, pathname)) != NULL) { - Py_INCREF(m); - return m; - } - lastdot = strrchr(name, '.'); - if (lastdot == NULL) { - packagecontext = NULL; - shortname = name; - } - else { - packagecontext = name; - shortname = lastdot+1; - } - - p = _PyImport_GetDynLoadFunc(name, shortname, pathname, fp); - if (PyErr_Occurred()) - return NULL; - if (p == NULL) { - PyErr_Format(PyExc_ImportError, - "dynamic module does not define init function (init%.200s)", - shortname); - return NULL; - } - oldcontext = _Py_PackageContext; - _Py_PackageContext = packagecontext; - (*p)(); - _Py_PackageContext = oldcontext; - if (PyErr_Occurred()) - return NULL; - - m = PyDict_GetItemString(PyImport_GetModuleDict(), name); - if (m == NULL) { - PyErr_SetString(PyExc_SystemError, - "dynamic module not initialized properly"); - return NULL; - } - /* Remember the filename as the __file__ attribute */ - if (PyModule_AddStringConstant(m, "__file__", pathname) < 0) - PyErr_Clear(); /* Not important enough to report */ - - if (_PyImport_FixupExtension(name, pathname) == NULL) - return NULL; - if (Py_VerboseFlag) - PySys_WriteStderr( - "import %s # dynamically loaded from %s\n", - name, pathname); - Py_INCREF(m); - return m; -} - -#endif /* HAVE_DYNAMIC_LOADING */ diff --git a/sys/src/cmd/python/Python/importdl.h b/sys/src/cmd/python/Python/importdl.h deleted file mode 100644 index 5a2d45c46..000000000 --- a/sys/src/cmd/python/Python/importdl.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef Py_IMPORTDL_H -#define Py_IMPORTDL_H - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Definitions for dynamic loading of extension modules */ -enum filetype { - SEARCH_ERROR, - PY_SOURCE, - PY_COMPILED, - C_EXTENSION, - PY_RESOURCE, /* Mac only */ - PKG_DIRECTORY, - C_BUILTIN, - PY_FROZEN, - PY_CODERESOURCE, /* Mac only */ - IMP_HOOK -}; - -struct filedescr { - char *suffix; - char *mode; - enum filetype type; -}; -extern struct filedescr * _PyImport_Filetab; -extern const struct filedescr _PyImport_DynLoadFiletab[]; - -extern PyObject *_PyImport_LoadDynamicModule(char *name, char *pathname, - FILE *); - -/* Max length of module suffix searched for -- accommodates "module.slb" */ -#define MAXSUFFIXSIZE 12 - -#ifdef MS_WINDOWS -#include <windows.h> -typedef FARPROC dl_funcptr; -#else -#if defined(PYOS_OS2) && !defined(PYCC_GCC) -#include <os2def.h> -typedef int (* APIENTRY dl_funcptr)(); -#else -typedef void (*dl_funcptr)(void); -#endif -#endif - - -#ifdef __cplusplus -} -#endif -#endif /* !Py_IMPORTDL_H */ diff --git a/sys/src/cmd/python/Python/mactoolboxglue.c b/sys/src/cmd/python/Python/mactoolboxglue.c deleted file mode 100644 index 26a13083f..000000000 --- a/sys/src/cmd/python/Python/mactoolboxglue.c +++ /dev/null @@ -1,470 +0,0 @@ -/*********************************************************** -Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam, -The Netherlands. - - 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 appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Stichting Mathematisch -Centrum or CWI not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior permission. - -STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO -THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM 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. - -******************************************************************/ - - -#include "Python.h" -#include "pymactoolbox.h" -#include <arpa/inet.h> /* for ntohl, htonl */ - - -/* Like strerror() but for Mac OS error numbers */ -char * -PyMac_StrError(int err) -{ - static char buf[256]; - PyObject *m; - PyObject *rv; - - m = PyImport_ImportModule("MacOS"); - if (!m) { - if (Py_VerboseFlag) - PyErr_Print(); - PyErr_Clear(); - rv = NULL; - } - else { - rv = PyObject_CallMethod(m, "GetErrorString", "i", err); - if (!rv) - PyErr_Clear(); - } - if (!rv) { - buf[0] = '\0'; - } - else { - char *input = PyString_AsString(rv); - if (!input) { - PyErr_Clear(); - buf[0] = '\0'; - } else { - strncpy(buf, input, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = '\0'; - } - Py_DECREF(rv); - } - Py_XDECREF(m); - return buf; -} - -/* Exception object shared by all Mac specific modules for Mac OS errors */ -PyObject *PyMac_OSErrException; - -/* Initialize and return PyMac_OSErrException */ -PyObject * -PyMac_GetOSErrException(void) -{ - if (PyMac_OSErrException == NULL) - PyMac_OSErrException = PyErr_NewException("MacOS.Error", NULL, NULL); - return PyMac_OSErrException; -} - -/* Set a MAC-specific error from errno, and return NULL; return None if no error */ -PyObject * -PyErr_Mac(PyObject *eobj, int err) -{ - char *msg; - PyObject *v; - - if (err == 0 && !PyErr_Occurred()) { - Py_INCREF(Py_None); - return Py_None; - } - if (err == -1 && PyErr_Occurred()) - return NULL; - msg = PyMac_StrError(err); - v = Py_BuildValue("(is)", err, msg); - PyErr_SetObject(eobj, v); - Py_DECREF(v); - return NULL; -} - -/* Call PyErr_Mac with PyMac_OSErrException */ -PyObject * -PyMac_Error(OSErr err) -{ - return PyErr_Mac(PyMac_GetOSErrException(), err); -} - - -OSErr -PyMac_GetFullPathname(FSSpec *fss, char *path, int len) -{ - PyObject *fs, *exc; - PyObject *rv = NULL; - char *input; - OSErr err = noErr; - - *path = '\0'; - - fs = PyMac_BuildFSSpec(fss); - if (!fs) - goto error; - - rv = PyObject_CallMethod(fs, "as_pathname", ""); - if (!rv) - goto error; - - input = PyString_AsString(rv); - if (!input) - goto error; - - strncpy(path, input, len - 1); - path[len - 1] = '\0'; - - Py_XDECREF(rv); - Py_XDECREF(fs); - return err; - - error: - exc = PyErr_Occurred(); - if (exc && PyErr_GivenExceptionMatches(exc, - PyMac_GetOSErrException())) { - PyObject *args = PyObject_GetAttrString(exc, "args"); - if (args) { - char *ignore; - PyArg_ParseTuple(args, "is", &err, &ignore); - Py_XDECREF(args); - } - } - if (err == noErr) - err = -1; - PyErr_Clear(); - Py_XDECREF(rv); - Py_XDECREF(fs); - return err; -} - -/* Convert a 4-char string object argument to an OSType value */ -int -PyMac_GetOSType(PyObject *v, OSType *pr) -{ - uint32_t tmp; - if (!PyString_Check(v) || PyString_Size(v) != 4) { - PyErr_SetString(PyExc_TypeError, - "OSType arg must be string of 4 chars"); - return 0; - } - memcpy((char *)&tmp, PyString_AsString(v), 4); - *pr = (OSType)ntohl(tmp); - return 1; -} - -/* Convert an OSType value to a 4-char string object */ -PyObject * -PyMac_BuildOSType(OSType t) -{ - uint32_t tmp = htonl((uint32_t)t); - return PyString_FromStringAndSize((char *)&tmp, 4); -} - -/* Convert an NumVersion value to a 4-element tuple */ -PyObject * -PyMac_BuildNumVersion(NumVersion t) -{ - return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev); -} - - -/* Convert a Python string object to a Str255 */ -int -PyMac_GetStr255(PyObject *v, Str255 pbuf) -{ - int len; - if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) { - PyErr_SetString(PyExc_TypeError, - "Str255 arg must be string of at most 255 chars"); - return 0; - } - pbuf[0] = len; - memcpy((char *)(pbuf+1), PyString_AsString(v), len); - return 1; -} - -/* Convert a Str255 to a Python string object */ -PyObject * -PyMac_BuildStr255(Str255 s) -{ - if ( s == NULL ) { - PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL"); - return NULL; - } - return PyString_FromStringAndSize((char *)&s[1], (int)s[0]); -} - -PyObject * -PyMac_BuildOptStr255(Str255 s) -{ - if ( s == NULL ) { - Py_INCREF(Py_None); - return Py_None; - } - return PyString_FromStringAndSize((char *)&s[1], (int)s[0]); -} - - - -/* Convert a Python object to a Rect. - The object must be a (left, top, right, bottom) tuple. - (This differs from the order in the struct but is consistent with - the arguments to SetRect(), and also with STDWIN). */ -int -PyMac_GetRect(PyObject *v, Rect *r) -{ - return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom); -} - -/* Convert a Rect to a Python object */ -PyObject * -PyMac_BuildRect(Rect *r) -{ - return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom); -} - - -/* Convert a Python object to a Point. - The object must be a (h, v) tuple. - (This differs from the order in the struct but is consistent with - the arguments to SetPoint(), and also with STDWIN). */ -int -PyMac_GetPoint(PyObject *v, Point *p) -{ - return PyArg_Parse(v, "(hh)", &p->h, &p->v); -} - -/* Convert a Point to a Python object */ -PyObject * -PyMac_BuildPoint(Point p) -{ - return Py_BuildValue("(hh)", p.h, p.v); -} - - -/* Convert a Python object to an EventRecord. - The object must be a (what, message, when, (v, h), modifiers) tuple. */ -int -PyMac_GetEventRecord(PyObject *v, EventRecord *e) -{ - return PyArg_Parse(v, "(Hkk(hh)H)", - &e->what, - &e->message, - &e->when, - &e->where.h, - &e->where.v, - &e->modifiers); -} - -/* Convert a Rect to an EventRecord object */ -PyObject * -PyMac_BuildEventRecord(EventRecord *e) -{ - return Py_BuildValue("(hll(hh)h)", - e->what, - e->message, - e->when, - e->where.h, - e->where.v, - e->modifiers); -} - -/* Convert Python object to Fixed */ -int -PyMac_GetFixed(PyObject *v, Fixed *f) -{ - double d; - - if( !PyArg_Parse(v, "d", &d)) - return 0; - *f = (Fixed)(d * 0x10000); - return 1; -} - -/* Convert a Fixed to a Python object */ -PyObject * -PyMac_BuildFixed(Fixed f) -{ - double d; - - d = f; - d = d / 0x10000; - return Py_BuildValue("d", d); -} - -/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */ -int -PyMac_Getwide(PyObject *v, wide *rv) -{ - if (PyInt_Check(v)) { - rv->hi = 0; - rv->lo = PyInt_AsLong(v); - if( rv->lo & 0x80000000 ) - rv->hi = -1; - return 1; - } - return PyArg_Parse(v, "(kk)", &rv->hi, &rv->lo); -} - - -PyObject * -PyMac_Buildwide(wide *w) -{ - if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) || - (w->hi == -1 && (w->lo & 0x80000000) ) ) - return PyInt_FromLong(w->lo); - return Py_BuildValue("(ll)", w->hi, w->lo); -} - -#ifdef USE_TOOLBOX_OBJECT_GLUE -/* -** Glue together the toolbox objects. -** -** Because toolbox modules interdepend on each other, they use each others -** object types, on MacOSX/MachO this leads to the situation that they -** cannot be dynamically loaded (or they would all have to be lumped into -** a single .so, but this would be bad for extensibility). -** -** This file defines wrappers for all the _New and _Convert functions, -** which are the Py_BuildValue and PyArg_ParseTuple helpers. The wrappers -** check an indirection function pointer, and if it isn't filled in yet -** they import the appropriate module, whose init routine should fill in -** the pointer. -*/ - -#define GLUE_NEW(object, routinename, module) \ -PyObject *(*PyMacGluePtr_##routinename)(object); \ -\ -PyObject *routinename(object cobj) { \ - if (!PyMacGluePtr_##routinename) { \ - if (!PyImport_ImportModule(module)) return NULL; \ - if (!PyMacGluePtr_##routinename) { \ - PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \ - return NULL; \ - } \ - } \ - return (*PyMacGluePtr_##routinename)(cobj); \ -} - -#define GLUE_CONVERT(object, routinename, module) \ -int (*PyMacGluePtr_##routinename)(PyObject *, object *); \ -\ -int routinename(PyObject *pyobj, object *cobj) { \ - if (!PyMacGluePtr_##routinename) { \ - if (!PyImport_ImportModule(module)) return 0; \ - if (!PyMacGluePtr_##routinename) { \ - PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \ - return 0; \ - } \ - } \ - return (*PyMacGluePtr_##routinename)(pyobj, cobj); \ -} - -GLUE_NEW(FSSpec *, PyMac_BuildFSSpec, "Carbon.File") -GLUE_CONVERT(FSSpec, PyMac_GetFSSpec, "Carbon.File") -GLUE_NEW(FSRef *, PyMac_BuildFSRef, "Carbon.File") -GLUE_CONVERT(FSRef, PyMac_GetFSRef, "Carbon.File") - -GLUE_NEW(AppleEvent *, AEDesc_New, "Carbon.AE") /* XXXX Why by address? */ -GLUE_NEW(AppleEvent *, AEDesc_NewBorrowed, "Carbon.AE") -GLUE_CONVERT(AppleEvent, AEDesc_Convert, "Carbon.AE") - -GLUE_NEW(Component, CmpObj_New, "Carbon.Cm") -GLUE_CONVERT(Component, CmpObj_Convert, "Carbon.Cm") -GLUE_NEW(ComponentInstance, CmpInstObj_New, "Carbon.Cm") -GLUE_CONVERT(ComponentInstance, CmpInstObj_Convert, "Carbon.Cm") - -GLUE_NEW(ControlHandle, CtlObj_New, "Carbon.Ctl") -GLUE_CONVERT(ControlHandle, CtlObj_Convert, "Carbon.Ctl") - -GLUE_NEW(DialogPtr, DlgObj_New, "Carbon.Dlg") -GLUE_CONVERT(DialogPtr, DlgObj_Convert, "Carbon.Dlg") -GLUE_NEW(DialogPtr, DlgObj_WhichDialog, "Carbon.Dlg") - -GLUE_NEW(DragReference, DragObj_New, "Carbon.Drag") -GLUE_CONVERT(DragReference, DragObj_Convert, "Carbon.Drag") - -GLUE_NEW(ListHandle, ListObj_New, "Carbon.List") -GLUE_CONVERT(ListHandle, ListObj_Convert, "Carbon.List") - -GLUE_NEW(MenuHandle, MenuObj_New, "Carbon.Menu") -GLUE_CONVERT(MenuHandle, MenuObj_Convert, "Carbon.Menu") - -GLUE_NEW(GrafPtr, GrafObj_New, "Carbon.Qd") -GLUE_CONVERT(GrafPtr, GrafObj_Convert, "Carbon.Qd") -GLUE_NEW(BitMapPtr, BMObj_New, "Carbon.Qd") -GLUE_CONVERT(BitMapPtr, BMObj_Convert, "Carbon.Qd") -GLUE_NEW(RGBColor *, QdRGB_New, "Carbon.Qd") /* XXXX Why? */ -GLUE_CONVERT(RGBColor, QdRGB_Convert, "Carbon.Qd") - -GLUE_NEW(GWorldPtr, GWorldObj_New, "Carbon.Qdoffs") -GLUE_CONVERT(GWorldPtr, GWorldObj_Convert, "Carbon.Qdoffs") - -GLUE_NEW(Track, TrackObj_New, "Carbon.Qt") -GLUE_CONVERT(Track, TrackObj_Convert, "Carbon.Qt") -GLUE_NEW(Movie, MovieObj_New, "Carbon.Qt") -GLUE_CONVERT(Movie, MovieObj_Convert, "Carbon.Qt") -GLUE_NEW(MovieController, MovieCtlObj_New, "Carbon.Qt") -GLUE_CONVERT(MovieController, MovieCtlObj_Convert, "Carbon.Qt") -GLUE_NEW(TimeBase, TimeBaseObj_New, "Carbon.Qt") -GLUE_CONVERT(TimeBase, TimeBaseObj_Convert, "Carbon.Qt") -GLUE_NEW(UserData, UserDataObj_New, "Carbon.Qt") -GLUE_CONVERT(UserData, UserDataObj_Convert, "Carbon.Qt") -GLUE_NEW(Media, MediaObj_New, "Carbon.Qt") -GLUE_CONVERT(Media, MediaObj_Convert, "Carbon.Qt") - -GLUE_NEW(Handle, ResObj_New, "Carbon.Res") -GLUE_CONVERT(Handle, ResObj_Convert, "Carbon.Res") -GLUE_NEW(Handle, OptResObj_New, "Carbon.Res") -GLUE_CONVERT(Handle, OptResObj_Convert, "Carbon.Res") - -GLUE_NEW(TEHandle, TEObj_New, "Carbon.TE") -GLUE_CONVERT(TEHandle, TEObj_Convert, "Carbon.TE") - -GLUE_NEW(WindowPtr, WinObj_New, "Carbon.Win") -GLUE_CONVERT(WindowPtr, WinObj_Convert, "Carbon.Win") -GLUE_NEW(WindowPtr, WinObj_WhichWindow, "Carbon.Win") - -GLUE_CONVERT(CFTypeRef, CFObj_Convert, "Carbon.CF") -GLUE_NEW(CFTypeRef, CFObj_New, "Carbon.CF") - -GLUE_CONVERT(CFTypeRef, CFTypeRefObj_Convert, "Carbon.CF") -GLUE_NEW(CFTypeRef, CFTypeRefObj_New, "Carbon.CF") - -GLUE_CONVERT(CFStringRef, CFStringRefObj_Convert, "Carbon.CF") -GLUE_NEW(CFStringRef, CFStringRefObj_New, "Carbon.CF") -GLUE_CONVERT(CFMutableStringRef, CFMutableStringRefObj_Convert, "Carbon.CF") -GLUE_NEW(CFMutableStringRef, CFMutableStringRefObj_New, "Carbon.CF") - -GLUE_CONVERT(CFArrayRef, CFArrayRefObj_Convert, "Carbon.CF") -GLUE_NEW(CFArrayRef, CFArrayRefObj_New, "Carbon.CF") -GLUE_CONVERT(CFMutableArrayRef, CFMutableArrayRefObj_Convert, "Carbon.CF") -GLUE_NEW(CFMutableArrayRef, CFMutableArrayRefObj_New, "Carbon.CF") - -GLUE_CONVERT(CFDictionaryRef, CFDictionaryRefObj_Convert, "Carbon.CF") -GLUE_NEW(CFDictionaryRef, CFDictionaryRefObj_New, "Carbon.CF") -GLUE_CONVERT(CFMutableDictionaryRef, CFMutableDictionaryRefObj_Convert, "Carbon.CF") -GLUE_NEW(CFMutableDictionaryRef, CFMutableDictionaryRefObj_New, "Carbon.CF") - -GLUE_CONVERT(CFURLRef, CFURLRefObj_Convert, "Carbon.CF") -GLUE_CONVERT(CFURLRef, OptionalCFURLRefObj_Convert, "Carbon.CF") -GLUE_NEW(CFURLRef, CFURLRefObj_New, "Carbon.CF") - -#endif /* USE_TOOLBOX_OBJECT_GLUE */ diff --git a/sys/src/cmd/python/Python/marshal.c b/sys/src/cmd/python/Python/marshal.c deleted file mode 100644 index 7940ce18a..000000000 --- a/sys/src/cmd/python/Python/marshal.c +++ /dev/null @@ -1,1155 +0,0 @@ - -/* Write Python objects to files and read them back. - This is intended for writing and reading compiled Python code only; - a true persistent storage facility would be much harder, since - it would have to take circular links and sharing into account. */ - -#define PY_SSIZE_T_CLEAN - -#include "Python.h" -#include "longintrepr.h" -#include "code.h" -#include "marshal.h" - -/* High water mark to determine when the marshalled object is dangerously deep - * and risks coring the interpreter. When the object stack gets this deep, - * raise an exception instead of continuing. - */ -#define MAX_MARSHAL_STACK_DEPTH 5000 - -#define TYPE_NULL '0' -#define TYPE_NONE 'N' -#define TYPE_FALSE 'F' -#define TYPE_TRUE 'T' -#define TYPE_STOPITER 'S' -#define TYPE_ELLIPSIS '.' -#define TYPE_INT 'i' -#define TYPE_INT64 'I' -#define TYPE_FLOAT 'f' -#define TYPE_BINARY_FLOAT 'g' -#define TYPE_COMPLEX 'x' -#define TYPE_BINARY_COMPLEX 'y' -#define TYPE_LONG 'l' -#define TYPE_STRING 's' -#define TYPE_INTERNED 't' -#define TYPE_STRINGREF 'R' -#define TYPE_TUPLE '(' -#define TYPE_LIST '[' -#define TYPE_DICT '{' -#define TYPE_CODE 'c' -#define TYPE_UNICODE 'u' -#define TYPE_UNKNOWN '?' -#define TYPE_SET '<' -#define TYPE_FROZENSET '>' - -typedef struct { - FILE *fp; - int error; - int depth; - /* If fp == NULL, the following are valid: */ - PyObject *str; - char *ptr; - char *end; - PyObject *strings; /* dict on marshal, list on unmarshal */ - int version; -} WFILE; - -#define w_byte(c, p) if (((p)->fp)) putc((c), (p)->fp); \ - else if ((p)->ptr != (p)->end) *(p)->ptr++ = (c); \ - else w_more(c, p) - -static void -w_more(int c, WFILE *p) -{ - Py_ssize_t size, newsize; - if (p->str == NULL) - return; /* An error already occurred */ - size = PyString_Size(p->str); - newsize = size + 1024; - if (_PyString_Resize(&p->str, newsize) != 0) { - p->ptr = p->end = NULL; - } - else { - p->ptr = PyString_AS_STRING((PyStringObject *)p->str) + size; - p->end = - PyString_AS_STRING((PyStringObject *)p->str) + newsize; - *p->ptr++ = Py_SAFE_DOWNCAST(c, int, char); - } -} - -static void -w_string(char *s, int n, WFILE *p) -{ - if (p->fp != NULL) { - fwrite(s, 1, n, p->fp); - } - else { - while (--n >= 0) { - w_byte(*s, p); - s++; - } - } -} - -static void -w_short(int x, WFILE *p) -{ - w_byte((char)( x & 0xff), p); - w_byte((char)((x>> 8) & 0xff), p); -} - -static void -w_long(long x, WFILE *p) -{ - w_byte((char)( x & 0xff), p); - w_byte((char)((x>> 8) & 0xff), p); - w_byte((char)((x>>16) & 0xff), p); - w_byte((char)((x>>24) & 0xff), p); -} - -#if SIZEOF_LONG > 4 -static void -w_long64(long x, WFILE *p) -{ - w_long(x, p); - w_long(x>>32, p); -} -#endif - -static void -w_object(PyObject *v, WFILE *p) -{ - Py_ssize_t i, n; - - p->depth++; - - if (p->depth > MAX_MARSHAL_STACK_DEPTH) { - p->error = 2; - } - else if (v == NULL) { - w_byte(TYPE_NULL, p); - } - else if (v == Py_None) { - w_byte(TYPE_NONE, p); - } - else if (v == PyExc_StopIteration) { - w_byte(TYPE_STOPITER, p); - } - else if (v == Py_Ellipsis) { - w_byte(TYPE_ELLIPSIS, p); - } - else if (v == Py_False) { - w_byte(TYPE_FALSE, p); - } - else if (v == Py_True) { - w_byte(TYPE_TRUE, p); - } - else if (PyInt_Check(v)) { - long x = PyInt_AS_LONG((PyIntObject *)v); -#if SIZEOF_LONG > 4 - long y = Py_ARITHMETIC_RIGHT_SHIFT(long, x, 31); - if (y && y != -1) { - w_byte(TYPE_INT64, p); - w_long64(x, p); - } - else -#endif - { - w_byte(TYPE_INT, p); - w_long(x, p); - } - } - else if (PyLong_Check(v)) { - PyLongObject *ob = (PyLongObject *)v; - w_byte(TYPE_LONG, p); - n = ob->ob_size; - w_long((long)n, p); - if (n < 0) - n = -n; - for (i = 0; i < n; i++) - w_short(ob->ob_digit[i], p); - } - else if (PyFloat_Check(v)) { - if (p->version > 1) { - unsigned char buf[8]; - if (_PyFloat_Pack8(PyFloat_AsDouble(v), - buf, 1) < 0) { - p->error = 1; - return; - } - w_byte(TYPE_BINARY_FLOAT, p); - w_string((char*)buf, 8, p); - } - else { - char buf[256]; /* Plenty to format any double */ - PyFloat_AsReprString(buf, (PyFloatObject *)v); - n = strlen(buf); - w_byte(TYPE_FLOAT, p); - w_byte((int)n, p); - w_string(buf, (int)n, p); - } - } -#ifndef WITHOUT_COMPLEX - else if (PyComplex_Check(v)) { - if (p->version > 1) { - unsigned char buf[8]; - if (_PyFloat_Pack8(PyComplex_RealAsDouble(v), - buf, 1) < 0) { - p->error = 1; - return; - } - w_byte(TYPE_BINARY_COMPLEX, p); - w_string((char*)buf, 8, p); - if (_PyFloat_Pack8(PyComplex_ImagAsDouble(v), - buf, 1) < 0) { - p->error = 1; - return; - } - w_string((char*)buf, 8, p); - } - else { - char buf[256]; /* Plenty to format any double */ - PyFloatObject *temp; - w_byte(TYPE_COMPLEX, p); - temp = (PyFloatObject*)PyFloat_FromDouble( - PyComplex_RealAsDouble(v)); - if (!temp) { - p->error = 1; - return; - } - PyFloat_AsReprString(buf, temp); - Py_DECREF(temp); - n = strlen(buf); - w_byte((int)n, p); - w_string(buf, (int)n, p); - temp = (PyFloatObject*)PyFloat_FromDouble( - PyComplex_ImagAsDouble(v)); - if (!temp) { - p->error = 1; - return; - } - PyFloat_AsReprString(buf, temp); - Py_DECREF(temp); - n = strlen(buf); - w_byte((int)n, p); - w_string(buf, (int)n, p); - } - } -#endif - else if (PyString_Check(v)) { - if (p->strings && PyString_CHECK_INTERNED(v)) { - PyObject *o = PyDict_GetItem(p->strings, v); - if (o) { - long w = PyInt_AsLong(o); - w_byte(TYPE_STRINGREF, p); - w_long(w, p); - goto exit; - } - else { - o = PyInt_FromSsize_t(PyDict_Size(p->strings)); - PyDict_SetItem(p->strings, v, o); - Py_DECREF(o); - w_byte(TYPE_INTERNED, p); - } - } - else { - w_byte(TYPE_STRING, p); - } - n = PyString_GET_SIZE(v); - if (n > INT_MAX) { - /* huge strings are not supported */ - p->depth--; - p->error = 1; - return; - } - w_long((long)n, p); - w_string(PyString_AS_STRING(v), (int)n, p); - } -#ifdef Py_USING_UNICODE - else if (PyUnicode_Check(v)) { - PyObject *utf8; - utf8 = PyUnicode_AsUTF8String(v); - if (utf8 == NULL) { - p->depth--; - p->error = 1; - return; - } - w_byte(TYPE_UNICODE, p); - n = PyString_GET_SIZE(utf8); - if (n > INT_MAX) { - p->depth--; - p->error = 1; - return; - } - w_long((long)n, p); - w_string(PyString_AS_STRING(utf8), (int)n, p); - Py_DECREF(utf8); - } -#endif - else if (PyTuple_Check(v)) { - w_byte(TYPE_TUPLE, p); - n = PyTuple_Size(v); - w_long((long)n, p); - for (i = 0; i < n; i++) { - w_object(PyTuple_GET_ITEM(v, i), p); - } - } - else if (PyList_Check(v)) { - w_byte(TYPE_LIST, p); - n = PyList_GET_SIZE(v); - w_long((long)n, p); - for (i = 0; i < n; i++) { - w_object(PyList_GET_ITEM(v, i), p); - } - } - else if (PyDict_Check(v)) { - Py_ssize_t pos; - PyObject *key, *value; - w_byte(TYPE_DICT, p); - /* This one is NULL object terminated! */ - pos = 0; - while (PyDict_Next(v, &pos, &key, &value)) { - w_object(key, p); - w_object(value, p); - } - w_object((PyObject *)NULL, p); - } - else if (PyAnySet_Check(v)) { - PyObject *value, *it; - - if (PyObject_TypeCheck(v, &PySet_Type)) - w_byte(TYPE_SET, p); - else - w_byte(TYPE_FROZENSET, p); - n = PyObject_Size(v); - if (n == -1) { - p->depth--; - p->error = 1; - return; - } - w_long((long)n, p); - it = PyObject_GetIter(v); - if (it == NULL) { - p->depth--; - p->error = 1; - return; - } - while ((value = PyIter_Next(it)) != NULL) { - w_object(value, p); - Py_DECREF(value); - } - Py_DECREF(it); - if (PyErr_Occurred()) { - p->depth--; - p->error = 1; - return; - } - } - else if (PyCode_Check(v)) { - PyCodeObject *co = (PyCodeObject *)v; - w_byte(TYPE_CODE, p); - w_long(co->co_argcount, p); - w_long(co->co_nlocals, p); - w_long(co->co_stacksize, p); - w_long(co->co_flags, p); - w_object(co->co_code, p); - w_object(co->co_consts, p); - w_object(co->co_names, p); - w_object(co->co_varnames, p); - w_object(co->co_freevars, p); - w_object(co->co_cellvars, p); - w_object(co->co_filename, p); - w_object(co->co_name, p); - w_long(co->co_firstlineno, p); - w_object(co->co_lnotab, p); - } - else if (PyObject_CheckReadBuffer(v)) { - /* Write unknown buffer-style objects as a string */ - char *s; - PyBufferProcs *pb = v->ob_type->tp_as_buffer; - w_byte(TYPE_STRING, p); - n = (*pb->bf_getreadbuffer)(v, 0, (void **)&s); - if (n > INT_MAX) { - p->depth--; - p->error = 1; - return; - } - w_long((long)n, p); - w_string(s, (int)n, p); - } - else { - w_byte(TYPE_UNKNOWN, p); - p->error = 1; - } - exit: - p->depth--; -} - -/* version currently has no effect for writing longs. */ -void -PyMarshal_WriteLongToFile(long x, FILE *fp, int version) -{ - WFILE wf; - wf.fp = fp; - wf.error = 0; - wf.depth = 0; - wf.strings = NULL; - wf.version = version; - w_long(x, &wf); -} - -void -PyMarshal_WriteObjectToFile(PyObject *x, FILE *fp, int version) -{ - WFILE wf; - wf.fp = fp; - wf.error = 0; - wf.depth = 0; - wf.strings = (version > 0) ? PyDict_New() : NULL; - wf.version = version; - w_object(x, &wf); - Py_XDECREF(wf.strings); -} - -typedef WFILE RFILE; /* Same struct with different invariants */ - -#define rs_byte(p) (((p)->ptr != (p)->end) ? (unsigned char)*(p)->ptr++ : EOF) - -#define r_byte(p) ((p)->fp ? getc((p)->fp) : rs_byte(p)) - -static int -r_string(char *s, int n, RFILE *p) -{ - if (p->fp != NULL) - /* The result fits into int because it must be <=n. */ - return (int)fread(s, 1, n, p->fp); - if (p->end - p->ptr < n) - n = (int)(p->end - p->ptr); - memcpy(s, p->ptr, n); - p->ptr += n; - return n; -} - -static int -r_short(RFILE *p) -{ - register short x; - x = r_byte(p); - x |= r_byte(p) << 8; - /* Sign-extension, in case short greater than 16 bits */ - x |= -(x & 0x8000); - return x; -} - -static long -r_long(RFILE *p) -{ - register long x; - register FILE *fp = p->fp; - if (fp) { - x = getc(fp); - x |= (long)getc(fp) << 8; - x |= (long)getc(fp) << 16; - x |= (long)getc(fp) << 24; - } - else { - x = rs_byte(p); - x |= (long)rs_byte(p) << 8; - x |= (long)rs_byte(p) << 16; - x |= (long)rs_byte(p) << 24; - } -#if SIZEOF_LONG > 4 - /* Sign extension for 64-bit machines */ - x |= -(x & 0x80000000L); -#endif - return x; -} - -/* r_long64 deals with the TYPE_INT64 code. On a machine with - sizeof(long) > 4, it returns a Python int object, else a Python long - object. Note that w_long64 writes out TYPE_INT if 32 bits is enough, - so there's no inefficiency here in returning a PyLong on 32-bit boxes - for everything written via TYPE_INT64 (i.e., if an int is written via - TYPE_INT64, it *needs* more than 32 bits). -*/ -static PyObject * -r_long64(RFILE *p) -{ - long lo4 = r_long(p); - long hi4 = r_long(p); -#if SIZEOF_LONG > 4 - long x = (hi4 << 32) | (lo4 & 0xFFFFFFFFL); - return PyInt_FromLong(x); -#else - unsigned char buf[8]; - int one = 1; - int is_little_endian = (int)*(char*)&one; - if (is_little_endian) { - memcpy(buf, &lo4, 4); - memcpy(buf+4, &hi4, 4); - } - else { - memcpy(buf, &hi4, 4); - memcpy(buf+4, &lo4, 4); - } - return _PyLong_FromByteArray(buf, 8, is_little_endian, 1); -#endif -} - -static PyObject * -r_object(RFILE *p) -{ - /* NULL is a valid return value, it does not necessarily means that - an exception is set. */ - PyObject *v, *v2, *v3; - long i, n; - int type = r_byte(p); - - switch (type) { - - case EOF: - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - return NULL; - - case TYPE_NULL: - return NULL; - - case TYPE_NONE: - Py_INCREF(Py_None); - return Py_None; - - case TYPE_STOPITER: - Py_INCREF(PyExc_StopIteration); - return PyExc_StopIteration; - - case TYPE_ELLIPSIS: - Py_INCREF(Py_Ellipsis); - return Py_Ellipsis; - - case TYPE_FALSE: - Py_INCREF(Py_False); - return Py_False; - - case TYPE_TRUE: - Py_INCREF(Py_True); - return Py_True; - - case TYPE_INT: - return PyInt_FromLong(r_long(p)); - - case TYPE_INT64: - return r_long64(p); - - case TYPE_LONG: - { - int size; - PyLongObject *ob; - n = r_long(p); - if (n < -INT_MAX || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, - "bad marshal data"); - return NULL; - } - size = n<0 ? -n : n; - ob = _PyLong_New(size); - if (ob == NULL) - return NULL; - ob->ob_size = n; - for (i = 0; i < size; i++) { - int digit = r_short(p); - if (digit < 0) { - Py_DECREF(ob); - PyErr_SetString(PyExc_ValueError, - "bad marshal data"); - return NULL; - } - ob->ob_digit[i] = digit; - } - return (PyObject *)ob; - } - - case TYPE_FLOAT: - { - char buf[256]; - double dx; - n = r_byte(p); - if (n == EOF || r_string(buf, (int)n, p) != n) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - return NULL; - } - buf[n] = '\0'; - PyFPE_START_PROTECT("atof", return 0) - dx = PyOS_ascii_atof(buf); - PyFPE_END_PROTECT(dx) - return PyFloat_FromDouble(dx); - } - - case TYPE_BINARY_FLOAT: - { - unsigned char buf[8]; - double x; - if (r_string((char*)buf, 8, p) != 8) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - return NULL; - } - x = _PyFloat_Unpack8(buf, 1); - if (x == -1.0 && PyErr_Occurred()) { - return NULL; - } - return PyFloat_FromDouble(x); - } - -#ifndef WITHOUT_COMPLEX - case TYPE_COMPLEX: - { - char buf[256]; - Py_complex c; - n = r_byte(p); - if (n == EOF || r_string(buf, (int)n, p) != n) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - return NULL; - } - buf[n] = '\0'; - PyFPE_START_PROTECT("atof", return 0) - c.real = PyOS_ascii_atof(buf); - PyFPE_END_PROTECT(c) - n = r_byte(p); - if (n == EOF || r_string(buf, (int)n, p) != n) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - return NULL; - } - buf[n] = '\0'; - PyFPE_START_PROTECT("atof", return 0) - c.imag = PyOS_ascii_atof(buf); - PyFPE_END_PROTECT(c) - return PyComplex_FromCComplex(c); - } - - case TYPE_BINARY_COMPLEX: - { - unsigned char buf[8]; - Py_complex c; - if (r_string((char*)buf, 8, p) != 8) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - return NULL; - } - c.real = _PyFloat_Unpack8(buf, 1); - if (c.real == -1.0 && PyErr_Occurred()) { - return NULL; - } - if (r_string((char*)buf, 8, p) != 8) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - return NULL; - } - c.imag = _PyFloat_Unpack8(buf, 1); - if (c.imag == -1.0 && PyErr_Occurred()) { - return NULL; - } - return PyComplex_FromCComplex(c); - } -#endif - - case TYPE_INTERNED: - case TYPE_STRING: - n = r_long(p); - if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); - return NULL; - } - v = PyString_FromStringAndSize((char *)NULL, n); - if (v == NULL) - return v; - if (r_string(PyString_AS_STRING(v), (int)n, p) != n) { - Py_DECREF(v); - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - return NULL; - } - if (type == TYPE_INTERNED) { - PyString_InternInPlace(&v); - PyList_Append(p->strings, v); - } - return v; - - case TYPE_STRINGREF: - n = r_long(p); - if (n < 0 || n >= PyList_GET_SIZE(p->strings)) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); - return NULL; - } - v = PyList_GET_ITEM(p->strings, n); - Py_INCREF(v); - return v; - -#ifdef Py_USING_UNICODE - case TYPE_UNICODE: - { - char *buffer; - - n = r_long(p); - if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); - return NULL; - } - buffer = PyMem_NEW(char, n); - if (buffer == NULL) - return PyErr_NoMemory(); - if (r_string(buffer, (int)n, p) != n) { - PyMem_DEL(buffer); - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - return NULL; - } - v = PyUnicode_DecodeUTF8(buffer, n, NULL); - PyMem_DEL(buffer); - return v; - } -#endif - - case TYPE_TUPLE: - n = r_long(p); - if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); - return NULL; - } - v = PyTuple_New((int)n); - if (v == NULL) - return v; - for (i = 0; i < n; i++) { - v2 = r_object(p); - if ( v2 == NULL ) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_TypeError, - "NULL object in marshal data"); - Py_DECREF(v); - v = NULL; - break; - } - PyTuple_SET_ITEM(v, (int)i, v2); - } - return v; - - case TYPE_LIST: - n = r_long(p); - if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); - return NULL; - } - v = PyList_New((int)n); - if (v == NULL) - return v; - for (i = 0; i < n; i++) { - v2 = r_object(p); - if ( v2 == NULL ) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_TypeError, - "NULL object in marshal data"); - Py_DECREF(v); - v = NULL; - break; - } - PyList_SetItem(v, (int)i, v2); - } - return v; - - case TYPE_DICT: - v = PyDict_New(); - if (v == NULL) - return NULL; - for (;;) { - PyObject *key, *val; - key = r_object(p); - if (key == NULL) - break; - val = r_object(p); - if (val != NULL) - PyDict_SetItem(v, key, val); - Py_DECREF(key); - Py_XDECREF(val); - } - if (PyErr_Occurred()) { - Py_DECREF(v); - v = NULL; - } - return v; - - case TYPE_SET: - case TYPE_FROZENSET: - n = r_long(p); - if (n < 0) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); - return NULL; - } - v = PyTuple_New((int)n); - if (v == NULL) - return v; - for (i = 0; i < n; i++) { - v2 = r_object(p); - if ( v2 == NULL ) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_TypeError, - "NULL object in marshal data"); - Py_DECREF(v); - v = NULL; - break; - } - PyTuple_SET_ITEM(v, (int)i, v2); - } - if (v == NULL) - return v; - if (type == TYPE_SET) - v3 = PySet_New(v); - else - v3 = PyFrozenSet_New(v); - Py_DECREF(v); - return v3; - - case TYPE_CODE: - if (PyEval_GetRestricted()) { - PyErr_SetString(PyExc_RuntimeError, - "cannot unmarshal code objects in " - "restricted execution mode"); - return NULL; - } - else { - int argcount; - int nlocals; - int stacksize; - int flags; - PyObject *code = NULL; - PyObject *consts = NULL; - PyObject *names = NULL; - PyObject *varnames = NULL; - PyObject *freevars = NULL; - PyObject *cellvars = NULL; - PyObject *filename = NULL; - PyObject *name = NULL; - int firstlineno; - PyObject *lnotab = NULL; - - v = NULL; - - /* XXX ignore long->int overflows for now */ - argcount = (int)r_long(p); - nlocals = (int)r_long(p); - stacksize = (int)r_long(p); - flags = (int)r_long(p); - code = r_object(p); - if (code == NULL) - goto code_error; - consts = r_object(p); - if (consts == NULL) - goto code_error; - names = r_object(p); - if (names == NULL) - goto code_error; - varnames = r_object(p); - if (varnames == NULL) - goto code_error; - freevars = r_object(p); - if (freevars == NULL) - goto code_error; - cellvars = r_object(p); - if (cellvars == NULL) - goto code_error; - filename = r_object(p); - if (filename == NULL) - goto code_error; - name = r_object(p); - if (name == NULL) - goto code_error; - firstlineno = (int)r_long(p); - lnotab = r_object(p); - if (lnotab == NULL) - goto code_error; - - v = (PyObject *) PyCode_New( - argcount, nlocals, stacksize, flags, - code, consts, names, varnames, - freevars, cellvars, filename, name, - firstlineno, lnotab); - - code_error: - Py_XDECREF(code); - Py_XDECREF(consts); - Py_XDECREF(names); - Py_XDECREF(varnames); - Py_XDECREF(freevars); - Py_XDECREF(cellvars); - Py_XDECREF(filename); - Py_XDECREF(name); - Py_XDECREF(lnotab); - - } - return v; - - default: - /* Bogus data got written, which isn't ideal. - This will let you keep working and recover. */ - PyErr_SetString(PyExc_ValueError, "bad marshal data"); - return NULL; - - } -} - -static PyObject * -read_object(RFILE *p) -{ - PyObject *v; - if (PyErr_Occurred()) { - fprintf(stderr, "XXX readobject called with exception set\n"); - return NULL; - } - v = r_object(p); - if (v == NULL && !PyErr_Occurred()) - PyErr_SetString(PyExc_TypeError, "NULL object in marshal data"); - return v; -} - -int -PyMarshal_ReadShortFromFile(FILE *fp) -{ - RFILE rf; - assert(fp); - rf.fp = fp; - rf.strings = NULL; - rf.end = rf.ptr = NULL; - return r_short(&rf); -} - -long -PyMarshal_ReadLongFromFile(FILE *fp) -{ - RFILE rf; - rf.fp = fp; - rf.strings = NULL; - return r_long(&rf); -} - -#ifdef HAVE_FSTAT -/* Return size of file in bytes; < 0 if unknown. */ -static off_t -getfilesize(FILE *fp) -{ - struct stat st; - if (fstat(fileno(fp), &st) != 0) - return -1; - else - return st.st_size; -} -#endif - -/* If we can get the size of the file up-front, and it's reasonably small, - * read it in one gulp and delegate to ...FromString() instead. Much quicker - * than reading a byte at a time from file; speeds .pyc imports. - * CAUTION: since this may read the entire remainder of the file, don't - * call it unless you know you're done with the file. - */ -PyObject * -PyMarshal_ReadLastObjectFromFile(FILE *fp) -{ -/* 75% of 2.1's .pyc files can exploit SMALL_FILE_LIMIT. - * REASONABLE_FILE_LIMIT is by defn something big enough for Tkinter.pyc. - */ -#define SMALL_FILE_LIMIT (1L << 14) -#define REASONABLE_FILE_LIMIT (1L << 18) -#ifdef HAVE_FSTAT - off_t filesize; -#endif -#ifdef HAVE_FSTAT - filesize = getfilesize(fp); - if (filesize > 0) { - char buf[SMALL_FILE_LIMIT]; - char* pBuf = NULL; - if (filesize <= SMALL_FILE_LIMIT) - pBuf = buf; - else if (filesize <= REASONABLE_FILE_LIMIT) - pBuf = (char *)PyMem_MALLOC((int)filesize); - if (pBuf != NULL) { - PyObject* v; - size_t n; - /* filesize must fit into an int, because it - is smaller than REASONABLE_FILE_LIMIT */ - n = fread(pBuf, 1, (int)filesize, fp); - v = PyMarshal_ReadObjectFromString(pBuf, n); - if (pBuf != buf) - PyMem_FREE(pBuf); - return v; - } - - } -#endif - /* We don't have fstat, or we do but the file is larger than - * REASONABLE_FILE_LIMIT or malloc failed -- read a byte at a time. - */ - return PyMarshal_ReadObjectFromFile(fp); - -#undef SMALL_FILE_LIMIT -#undef REASONABLE_FILE_LIMIT -} - -PyObject * -PyMarshal_ReadObjectFromFile(FILE *fp) -{ - RFILE rf; - PyObject *result; - rf.fp = fp; - rf.strings = PyList_New(0); - result = r_object(&rf); - Py_DECREF(rf.strings); - return result; -} - -PyObject * -PyMarshal_ReadObjectFromString(char *str, Py_ssize_t len) -{ - RFILE rf; - PyObject *result; - rf.fp = NULL; - rf.ptr = str; - rf.end = str + len; - rf.strings = PyList_New(0); - result = r_object(&rf); - Py_DECREF(rf.strings); - return result; -} - -PyObject * -PyMarshal_WriteObjectToString(PyObject *x, int version) -{ - WFILE wf; - wf.fp = NULL; - wf.str = PyString_FromStringAndSize((char *)NULL, 50); - if (wf.str == NULL) - return NULL; - wf.ptr = PyString_AS_STRING((PyStringObject *)wf.str); - wf.end = wf.ptr + PyString_Size(wf.str); - wf.error = 0; - wf.depth = 0; - wf.version = version; - wf.strings = (version > 0) ? PyDict_New() : NULL; - w_object(x, &wf); - Py_XDECREF(wf.strings); - if (wf.str != NULL) { - char *base = PyString_AS_STRING((PyStringObject *)wf.str); - if (wf.ptr - base > PY_SSIZE_T_MAX) { - Py_DECREF(wf.str); - PyErr_SetString(PyExc_OverflowError, - "too much marshall data for a string"); - return NULL; - } - _PyString_Resize(&wf.str, (Py_ssize_t)(wf.ptr - base)); - } - if (wf.error) { - Py_XDECREF(wf.str); - PyErr_SetString(PyExc_ValueError, - (wf.error==1)?"unmarshallable object" - :"object too deeply nested to marshal"); - return NULL; - } - return wf.str; -} - -/* And an interface for Python programs... */ - -static PyObject * -marshal_dump(PyObject *self, PyObject *args) -{ - WFILE wf; - PyObject *x; - PyObject *f; - int version = Py_MARSHAL_VERSION; - if (!PyArg_ParseTuple(args, "OO|i:dump", &x, &f, &version)) - return NULL; - if (!PyFile_Check(f)) { - PyErr_SetString(PyExc_TypeError, - "marshal.dump() 2nd arg must be file"); - return NULL; - } - wf.fp = PyFile_AsFile(f); - wf.str = NULL; - wf.ptr = wf.end = NULL; - wf.error = 0; - wf.depth = 0; - wf.strings = (version > 0) ? PyDict_New() : 0; - wf.version = version; - w_object(x, &wf); - Py_XDECREF(wf.strings); - if (wf.error) { - PyErr_SetString(PyExc_ValueError, - (wf.error==1)?"unmarshallable object" - :"object too deeply nested to marshal"); - return NULL; - } - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -marshal_load(PyObject *self, PyObject *f) -{ - RFILE rf; - PyObject *result; - if (!PyFile_Check(f)) { - PyErr_SetString(PyExc_TypeError, - "marshal.load() arg must be file"); - return NULL; - } - rf.fp = PyFile_AsFile(f); - rf.strings = PyList_New(0); - result = read_object(&rf); - Py_DECREF(rf.strings); - return result; -} - -static PyObject * -marshal_dumps(PyObject *self, PyObject *args) -{ - PyObject *x; - int version = Py_MARSHAL_VERSION; - if (!PyArg_ParseTuple(args, "O|i:dumps", &x, &version)) - return NULL; - return PyMarshal_WriteObjectToString(x, version); -} - -static PyObject * -marshal_loads(PyObject *self, PyObject *args) -{ - RFILE rf; - char *s; - Py_ssize_t n; - PyObject* result; - if (!PyArg_ParseTuple(args, "s#:loads", &s, &n)) - return NULL; - rf.fp = NULL; - rf.ptr = s; - rf.end = s + n; - rf.strings = PyList_New(0); - result = read_object(&rf); - Py_DECREF(rf.strings); - return result; -} - -static PyMethodDef marshal_methods[] = { - {"dump", marshal_dump, METH_VARARGS}, - {"load", marshal_load, METH_O}, - {"dumps", marshal_dumps, METH_VARARGS}, - {"loads", marshal_loads, METH_VARARGS}, - {NULL, NULL} /* sentinel */ -}; - -PyMODINIT_FUNC -PyMarshal_Init(void) -{ - PyObject *mod = Py_InitModule("marshal", marshal_methods); - if (mod == NULL) - return; - PyModule_AddIntConstant(mod, "version", Py_MARSHAL_VERSION); -} diff --git a/sys/src/cmd/python/Python/memmove.c b/sys/src/cmd/python/Python/memmove.c deleted file mode 100644 index 6fb0dad93..000000000 --- a/sys/src/cmd/python/Python/memmove.c +++ /dev/null @@ -1,25 +0,0 @@ - -/* A perhaps slow but I hope correct implementation of memmove */ - -extern char *memcpy(char *, char *, int); - -char * -memmove(char *dst, char *src, int n) -{ - char *realdst = dst; - if (n <= 0) - return dst; - if (src >= dst+n || dst >= src+n) - return memcpy(dst, src, n); - if (src > dst) { - while (--n >= 0) - *dst++ = *src++; - } - else if (src < dst) { - src += n; - dst += n; - while (--n >= 0) - *--dst = *--src; - } - return realdst; -} diff --git a/sys/src/cmd/python/Python/mkfile b/sys/src/cmd/python/Python/mkfile deleted file mode 100644 index 24bb56e72..000000000 --- a/sys/src/cmd/python/Python/mkfile +++ /dev/null @@ -1,62 +0,0 @@ -</$cputype/mkfile -APE=/sys/src/ape -<$APE/config - -LIB=../libpython.a$O - -OFILES=\ - Python-ast.$O\ - asdl.$O\ - ast.$O\ - bltinmodule.$O\ - ceval.$O\ - codecs.$O\ - compile.$O\ - dynload_stub.$O\ - errors.$O\ -# fmod.$O\ - frozen.$O\ - frozenmain.$O\ - future.$O\ - getargs.$O\ - getcompiler.$O\ - getcopyright.$O\ - getmtime.$O\ - getopt.$O\ - getplatform.$O\ - getversion.$O\ - import.$O\ - importdl.$O\ - marshal.$O\ - modsupport.$O\ - mysnprintf.$O\ - mystrtoul.$O\ - pyarena.$O\ - pyfpe.$O\ - pystate.$O\ - pystrtod.$O\ - pythonrun.$O\ -# sigcheck.$O\ - structmember.$O\ - symtable.$O\ - sysmodule.$O\ - thread.$O\ - traceback.$O\ - graminit.$O\ - -CLEANFILES=graminit.c graminit.h - -</sys/src/cmd/mksyslib - -CFLAGS=-c -I.. -I../Include -DT$objtype -DPy_BUILD_CORE -DNDEBUG - -ast.$O future.$O: ../Include/graminit.h - -../Include/graminit.h: graminit.h - cp graminit.h ../Include/graminit.h - -graminit.c graminit.h:D: ../Grammar/Grammar ../Parser/pgen.$cputype - ../Parser/pgen.$cputype ../Grammar/Grammar graminit.h graminit.c - -../Parser/pgen.$cputype:D: - @{cd ../Parser && objtype=$cputype mk pgen.$cputype} diff --git a/sys/src/cmd/python/Python/modsupport.c b/sys/src/cmd/python/Python/modsupport.c deleted file mode 100644 index 1aa3df285..000000000 --- a/sys/src/cmd/python/Python/modsupport.c +++ /dev/null @@ -1,631 +0,0 @@ - -/* Module support implementation */ - -#include "Python.h" - -#define FLAG_SIZE_T 1 -typedef double va_double; - -static PyObject *va_build_value(const char *, va_list, int); - -/* Package context -- the full module name for package imports */ -char *_Py_PackageContext = NULL; - -/* Py_InitModule4() parameters: - - name is the module name - - methods is the list of top-level functions - - doc is the documentation string - - passthrough is passed as self to functions defined in the module - - api_version is the value of PYTHON_API_VERSION at the time the - module was compiled - - Return value is a borrowed reference to the module object; or NULL - if an error occurred (in Python 1.4 and before, errors were fatal). - Errors may still leak memory. -*/ - -static char api_version_warning[] = -"Python C API version mismatch for module %.100s:\ - This Python has API version %d, module %.100s has version %d."; - -PyObject * -Py_InitModule4(const char *name, PyMethodDef *methods, const char *doc, - PyObject *passthrough, int module_api_version) -{ - PyObject *m, *d, *v, *n; - PyMethodDef *ml; - if (!Py_IsInitialized()) - Py_FatalError("Interpreter not initialized (version mismatch?)"); - if (module_api_version != PYTHON_API_VERSION) { - char message[512]; - PyOS_snprintf(message, sizeof(message), - api_version_warning, name, - PYTHON_API_VERSION, name, - module_api_version); - if (PyErr_Warn(PyExc_RuntimeWarning, message)) - return NULL; - } - /* Make sure name is fully qualified. - - This is a bit of a hack: when the shared library is loaded, - the module name is "package.module", but the module calls - Py_InitModule*() with just "module" for the name. The shared - library loader squirrels away the true name of the module in - _Py_PackageContext, and Py_InitModule*() will substitute this - (if the name actually matches). - */ - if (_Py_PackageContext != NULL) { - char *p = strrchr(_Py_PackageContext, '.'); - if (p != NULL && strcmp(name, p+1) == 0) { - name = _Py_PackageContext; - _Py_PackageContext = NULL; - } - } - if ((m = PyImport_AddModule(name)) == NULL) - return NULL; - d = PyModule_GetDict(m); - if (methods != NULL) { - n = PyString_FromString(name); - if (n == NULL) - return NULL; - for (ml = methods; ml->ml_name != NULL; ml++) { - if ((ml->ml_flags & METH_CLASS) || - (ml->ml_flags & METH_STATIC)) { - PyErr_SetString(PyExc_ValueError, - "module functions cannot set" - " METH_CLASS or METH_STATIC"); - Py_DECREF(n); - return NULL; - } - v = PyCFunction_NewEx(ml, passthrough, n); - if (v == NULL) { - Py_DECREF(n); - return NULL; - } - if (PyDict_SetItemString(d, ml->ml_name, v) != 0) { - Py_DECREF(v); - Py_DECREF(n); - return NULL; - } - Py_DECREF(v); - } - Py_DECREF(n); - } - if (doc != NULL) { - v = PyString_FromString(doc); - if (v == NULL || PyDict_SetItemString(d, "__doc__", v) != 0) { - Py_XDECREF(v); - return NULL; - } - Py_DECREF(v); - } - return m; -} - - -/* Helper for mkvalue() to scan the length of a format */ - -static int -countformat(const char *format, int endchar) -{ - int count = 0; - int level = 0; - while (level > 0 || *format != endchar) { - switch (*format) { - case '\0': - /* Premature end */ - PyErr_SetString(PyExc_SystemError, - "unmatched paren in format"); - return -1; - case '(': - case '[': - case '{': - if (level == 0) - count++; - level++; - break; - case ')': - case ']': - case '}': - level--; - break; - case '#': - case '&': - case ',': - case ':': - case ' ': - case '\t': - break; - default: - if (level == 0) - count++; - } - format++; - } - return count; -} - - -/* Generic function to create a value -- the inverse of getargs() */ -/* After an original idea and first implementation by Steven Miale */ - -static PyObject *do_mktuple(const char**, va_list *, int, int, int); -static PyObject *do_mklist(const char**, va_list *, int, int, int); -static PyObject *do_mkdict(const char**, va_list *, int, int, int); -static PyObject *do_mkvalue(const char**, va_list *, int); - - -static PyObject * -do_mkdict(const char **p_format, va_list *p_va, int endchar, int n, int flags) -{ - PyObject *d; - int i; - int itemfailed = 0; - if (n < 0) - return NULL; - if ((d = PyDict_New()) == NULL) - return NULL; - /* Note that we can't bail immediately on error as this will leak - refcounts on any 'N' arguments. */ - for (i = 0; i < n; i+= 2) { - PyObject *k, *v; - int err; - k = do_mkvalue(p_format, p_va, flags); - if (k == NULL) { - itemfailed = 1; - Py_INCREF(Py_None); - k = Py_None; - } - v = do_mkvalue(p_format, p_va, flags); - if (v == NULL) { - itemfailed = 1; - Py_INCREF(Py_None); - v = Py_None; - } - err = PyDict_SetItem(d, k, v); - Py_DECREF(k); - Py_DECREF(v); - if (err < 0 || itemfailed) { - Py_DECREF(d); - return NULL; - } - } - if (d != NULL && **p_format != endchar) { - Py_DECREF(d); - d = NULL; - PyErr_SetString(PyExc_SystemError, - "Unmatched paren in format"); - } - else if (endchar) - ++*p_format; - return d; -} - -static PyObject * -do_mklist(const char **p_format, va_list *p_va, int endchar, int n, int flags) -{ - PyObject *v; - int i; - int itemfailed = 0; - if (n < 0) - return NULL; - v = PyList_New(n); - if (v == NULL) - return NULL; - /* Note that we can't bail immediately on error as this will leak - refcounts on any 'N' arguments. */ - for (i = 0; i < n; i++) { - PyObject *w = do_mkvalue(p_format, p_va, flags); - if (w == NULL) { - itemfailed = 1; - Py_INCREF(Py_None); - w = Py_None; - } - PyList_SET_ITEM(v, i, w); - } - - if (itemfailed) { - /* do_mkvalue() should have already set an error */ - Py_DECREF(v); - return NULL; - } - if (**p_format != endchar) { - Py_DECREF(v); - PyErr_SetString(PyExc_SystemError, - "Unmatched paren in format"); - return NULL; - } - if (endchar) - ++*p_format; - return v; -} - -#ifdef Py_USING_UNICODE -static int -_ustrlen(Py_UNICODE *u) -{ - int i = 0; - Py_UNICODE *v = u; - while (*v != 0) { i++; v++; } - return i; -} -#endif - -static PyObject * -do_mktuple(const char **p_format, va_list *p_va, int endchar, int n, int flags) -{ - PyObject *v; - int i; - int itemfailed = 0; - if (n < 0) - return NULL; - if ((v = PyTuple_New(n)) == NULL) - return NULL; - /* Note that we can't bail immediately on error as this will leak - refcounts on any 'N' arguments. */ - for (i = 0; i < n; i++) { - PyObject *w = do_mkvalue(p_format, p_va, flags); - if (w == NULL) { - itemfailed = 1; - Py_INCREF(Py_None); - w = Py_None; - } - PyTuple_SET_ITEM(v, i, w); - } - if (itemfailed) { - /* do_mkvalue() should have already set an error */ - Py_DECREF(v); - return NULL; - } - if (**p_format != endchar) { - Py_DECREF(v); - PyErr_SetString(PyExc_SystemError, - "Unmatched paren in format"); - return NULL; - } - if (endchar) - ++*p_format; - return v; -} - -static PyObject * -do_mkvalue(const char **p_format, va_list *p_va, int flags) -{ - for (;;) { - switch (*(*p_format)++) { - case '(': - return do_mktuple(p_format, p_va, ')', - countformat(*p_format, ')'), flags); - - case '[': - return do_mklist(p_format, p_va, ']', - countformat(*p_format, ']'), flags); - - case '{': - return do_mkdict(p_format, p_va, '}', - countformat(*p_format, '}'), flags); - - case 'b': - case 'B': - case 'h': - case 'i': - return PyInt_FromLong((long)va_arg(*p_va, int)); - - case 'H': - return PyInt_FromLong((long)va_arg(*p_va, unsigned int)); - - case 'I': - { - unsigned int n; - n = va_arg(*p_va, unsigned int); - if (n > (unsigned long)PyInt_GetMax()) - return PyLong_FromUnsignedLong((unsigned long)n); - else - return PyInt_FromLong(n); - } - - case 'n': -#if SIZEOF_SIZE_T!=SIZEOF_LONG - return PyInt_FromSsize_t(va_arg(*p_va, Py_ssize_t)); -#endif - /* Fall through from 'n' to 'l' if Py_ssize_t is long */ - case 'l': - return PyInt_FromLong(va_arg(*p_va, long)); - - case 'k': - { - unsigned long n; - n = va_arg(*p_va, unsigned long); - if (n > (unsigned long)PyInt_GetMax()) - return PyLong_FromUnsignedLong(n); - else - return PyInt_FromLong(n); - } - -#ifdef HAVE_LONG_LONG - case 'L': - return PyLong_FromLongLong((PY_LONG_LONG)va_arg(*p_va, PY_LONG_LONG)); - - case 'K': - return PyLong_FromUnsignedLongLong((PY_LONG_LONG)va_arg(*p_va, unsigned PY_LONG_LONG)); -#endif -#ifdef Py_USING_UNICODE - case 'u': - { - PyObject *v; - Py_UNICODE *u = va_arg(*p_va, Py_UNICODE *); - Py_ssize_t n; - if (**p_format == '#') { - ++*p_format; - if (flags & FLAG_SIZE_T) - n = va_arg(*p_va, Py_ssize_t); - else - n = va_arg(*p_va, int); - } - else - n = -1; - if (u == NULL) { - v = Py_None; - Py_INCREF(v); - } - else { - if (n < 0) - n = _ustrlen(u); - v = PyUnicode_FromUnicode(u, n); - } - return v; - } -#endif - case 'f': - case 'd': - return PyFloat_FromDouble( - (double)va_arg(*p_va, va_double)); - -#ifndef WITHOUT_COMPLEX - case 'D': - return PyComplex_FromCComplex( - *((Py_complex *)va_arg(*p_va, Py_complex *))); -#endif /* WITHOUT_COMPLEX */ - - case 'c': - { - char p[1]; - p[0] = (char)va_arg(*p_va, int); - return PyString_FromStringAndSize(p, 1); - } - - case 's': - case 'z': - { - PyObject *v; - char *str = va_arg(*p_va, char *); - Py_ssize_t n; - if (**p_format == '#') { - ++*p_format; - if (flags & FLAG_SIZE_T) - n = va_arg(*p_va, Py_ssize_t); - else - n = va_arg(*p_va, int); - } - else - n = -1; - if (str == NULL) { - v = Py_None; - Py_INCREF(v); - } - else { - if (n < 0) { - size_t m = strlen(str); - if (m > PY_SSIZE_T_MAX) { - PyErr_SetString(PyExc_OverflowError, - "string too long for Python string"); - return NULL; - } - n = (Py_ssize_t)m; - } - v = PyString_FromStringAndSize(str, n); - } - return v; - } - - case 'N': - case 'S': - case 'O': - if (**p_format == '&') { - typedef PyObject *(*converter)(void *); - converter func = va_arg(*p_va, converter); - void *arg = va_arg(*p_va, void *); - ++*p_format; - return (*func)(arg); - } - else { - PyObject *v; - v = va_arg(*p_va, PyObject *); - if (v != NULL) { - if (*(*p_format - 1) != 'N') - Py_INCREF(v); - } - else if (!PyErr_Occurred()) - /* If a NULL was passed - * because a call that should - * have constructed a value - * failed, that's OK, and we - * pass the error on; but if - * no error occurred it's not - * clear that the caller knew - * what she was doing. */ - PyErr_SetString(PyExc_SystemError, - "NULL object passed to Py_BuildValue"); - return v; - } - - case ':': - case ',': - case ' ': - case '\t': - break; - - default: - PyErr_SetString(PyExc_SystemError, - "bad format char passed to Py_BuildValue"); - return NULL; - - } - } -} - - -PyObject * -Py_BuildValue(const char *format, ...) -{ - va_list va; - PyObject* retval; - va_start(va, format); - retval = va_build_value(format, va, 0); - va_end(va); - return retval; -} - -PyObject * -_Py_BuildValue_SizeT(const char *format, ...) -{ - va_list va; - PyObject* retval; - va_start(va, format); - retval = va_build_value(format, va, FLAG_SIZE_T); - va_end(va); - return retval; -} - -PyObject * -Py_VaBuildValue(const char *format, va_list va) -{ - return va_build_value(format, va, 0); -} - -PyObject * -_Py_VaBuildValue_SizeT(const char *format, va_list va) -{ - return va_build_value(format, va, FLAG_SIZE_T); -} - -static PyObject * -va_build_value(const char *format, va_list va, int flags) -{ - const char *f = format; - int n = countformat(f, '\0'); - va_list lva; - -#ifdef VA_LIST_IS_ARRAY - memcpy(lva, va, sizeof(va_list)); -#else -#ifdef __va_copy - __va_copy(lva, va); -#else - lva = va; -#endif -#endif - - if (n < 0) - return NULL; - if (n == 0) { - Py_INCREF(Py_None); - return Py_None; - } - if (n == 1) - return do_mkvalue(&f, &lva, flags); - return do_mktuple(&f, &lva, '\0', n, flags); -} - - -PyObject * -PyEval_CallFunction(PyObject *obj, const char *format, ...) -{ - va_list vargs; - PyObject *args; - PyObject *res; - - va_start(vargs, format); - - args = Py_VaBuildValue(format, vargs); - va_end(vargs); - - if (args == NULL) - return NULL; - - res = PyEval_CallObject(obj, args); - Py_DECREF(args); - - return res; -} - - -PyObject * -PyEval_CallMethod(PyObject *obj, const char *methodname, const char *format, ...) -{ - va_list vargs; - PyObject *meth; - PyObject *args; - PyObject *res; - - meth = PyObject_GetAttrString(obj, methodname); - if (meth == NULL) - return NULL; - - va_start(vargs, format); - - args = Py_VaBuildValue(format, vargs); - va_end(vargs); - - if (args == NULL) { - Py_DECREF(meth); - return NULL; - } - - res = PyEval_CallObject(meth, args); - Py_DECREF(meth); - Py_DECREF(args); - - return res; -} - -int -PyModule_AddObject(PyObject *m, const char *name, PyObject *o) -{ - PyObject *dict; - if (!PyModule_Check(m)) { - PyErr_SetString(PyExc_TypeError, - "PyModule_AddObject() needs module as first arg"); - return -1; - } - if (!o) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_TypeError, - "PyModule_AddObject() needs non-NULL value"); - return -1; - } - - dict = PyModule_GetDict(m); - if (dict == NULL) { - /* Internal error -- modules must have a dict! */ - PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__", - PyModule_GetName(m)); - return -1; - } - if (PyDict_SetItemString(dict, name, o)) - return -1; - Py_DECREF(o); - return 0; -} - -int -PyModule_AddIntConstant(PyObject *m, const char *name, long value) -{ - return PyModule_AddObject(m, name, PyInt_FromLong(value)); -} - -int -PyModule_AddStringConstant(PyObject *m, const char *name, const char *value) -{ - return PyModule_AddObject(m, name, PyString_FromString(value)); -} diff --git a/sys/src/cmd/python/Python/mysnprintf.c b/sys/src/cmd/python/Python/mysnprintf.c deleted file mode 100644 index 4d3770d89..000000000 --- a/sys/src/cmd/python/Python/mysnprintf.c +++ /dev/null @@ -1,93 +0,0 @@ -#include "Python.h" -#include <ctype.h> - -/* snprintf() wrappers. If the platform has vsnprintf, we use it, else we - emulate it in a half-hearted way. Even if the platform has it, we wrap - it because platforms differ in what vsnprintf does in case the buffer - is too small: C99 behavior is to return the number of characters that - would have been written had the buffer not been too small, and to set - the last byte of the buffer to \0. At least MS _vsnprintf returns a - negative value instead, and fills the entire buffer with non-\0 data. - - The wrappers ensure that str[size-1] is always \0 upon return. - - PyOS_snprintf and PyOS_vsnprintf never write more than size bytes - (including the trailing '\0') into str. - - If the platform doesn't have vsnprintf, and the buffer size needed to - avoid truncation exceeds size by more than 512, Python aborts with a - Py_FatalError. - - Return value (rv): - - When 0 <= rv < size, the output conversion was unexceptional, and - rv characters were written to str (excluding a trailing \0 byte at - str[rv]). - - When rv >= size, output conversion was truncated, and a buffer of - size rv+1 would have been needed to avoid truncation. str[size-1] - is \0 in this case. - - When rv < 0, "something bad happened". str[size-1] is \0 in this - case too, but the rest of str is unreliable. It could be that - an error in format codes was detected by libc, or on platforms - with a non-C99 vsnprintf simply that the buffer wasn't big enough - to avoid truncation, or on platforms without any vsnprintf that - PyMem_Malloc couldn't obtain space for a temp buffer. - - CAUTION: Unlike C99, str != NULL and size > 0 are required. -*/ - -int -PyOS_snprintf(char *str, size_t size, const char *format, ...) -{ - int rc; - va_list va; - - va_start(va, format); - rc = PyOS_vsnprintf(str, size, format, va); - va_end(va); - return rc; -} - -int -PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va) -{ - int len; /* # bytes written, excluding \0 */ -#ifndef HAVE_SNPRINTF - char *buffer; -#endif - assert(str != NULL); - assert(size > 0); - assert(format != NULL); - -#ifdef HAVE_SNPRINTF - len = vsnprintf(str, size, format, va); -#else - /* Emulate it. */ - buffer = PyMem_MALLOC(size + 512); - if (buffer == NULL) { - len = -666; - goto Done; - } - - len = vsprintf(buffer, format, va); - if (len < 0) - /* ignore the error */; - - else if ((size_t)len >= size + 512) - Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf"); - - else { - const size_t to_copy = (size_t)len < size ? - (size_t)len : size - 1; - assert(to_copy < size); - memcpy(str, buffer, to_copy); - str[to_copy] = '\0'; - } - PyMem_FREE(buffer); -Done: -#endif - str[size-1] = '\0'; - return len; -} diff --git a/sys/src/cmd/python/Python/mystrtoul.c b/sys/src/cmd/python/Python/mystrtoul.c deleted file mode 100644 index f0070575d..000000000 --- a/sys/src/cmd/python/Python/mystrtoul.c +++ /dev/null @@ -1,232 +0,0 @@ - -#include "Python.h" - -#if defined(__sgi) && defined(WITH_THREAD) && !defined(_SGI_MP_SOURCE) -#define _SGI_MP_SOURCE -#endif - -/* Convert a possibly signed character to a nonnegative int */ -/* XXX This assumes characters are 8 bits wide */ -#ifdef __CHAR_UNSIGNED__ -#define Py_CHARMASK(c) (c) -#else -#define Py_CHARMASK(c) ((c) & 0xff) -#endif - -/* strtol and strtoul, renamed to avoid conflicts */ - - -#include <ctype.h> -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif - -/* Static overflow check values for bases 2 through 36. - * smallmax[base] is the largest unsigned long i such that - * i * base doesn't overflow unsigned long. - */ -static unsigned long smallmax[] = { - 0, /* bases 0 and 1 are invalid */ - 0, - ULONG_MAX / 2, - ULONG_MAX / 3, - ULONG_MAX / 4, - ULONG_MAX / 5, - ULONG_MAX / 6, - ULONG_MAX / 7, - ULONG_MAX / 8, - ULONG_MAX / 9, - ULONG_MAX / 10, - ULONG_MAX / 11, - ULONG_MAX / 12, - ULONG_MAX / 13, - ULONG_MAX / 14, - ULONG_MAX / 15, - ULONG_MAX / 16, - ULONG_MAX / 17, - ULONG_MAX / 18, - ULONG_MAX / 19, - ULONG_MAX / 20, - ULONG_MAX / 21, - ULONG_MAX / 22, - ULONG_MAX / 23, - ULONG_MAX / 24, - ULONG_MAX / 25, - ULONG_MAX / 26, - ULONG_MAX / 27, - ULONG_MAX / 28, - ULONG_MAX / 29, - ULONG_MAX / 30, - ULONG_MAX / 31, - ULONG_MAX / 32, - ULONG_MAX / 33, - ULONG_MAX / 34, - ULONG_MAX / 35, - ULONG_MAX / 36, -}; - -/* maximum digits that can't ever overflow for bases 2 through 36, - * calculated by [int(math.floor(math.log(2**32, i))) for i in range(2, 37)]. - * Note that this is pessimistic if sizeof(long) > 4. - */ -#if SIZEOF_LONG == 4 -static int digitlimit[] = { - 0, 0, 32, 20, 16, 13, 12, 11, 10, 10, /* 0 - 9 */ - 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, /* 10 - 19 */ - 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, /* 20 - 29 */ - 6, 6, 6, 6, 6, 6, 6}; /* 30 - 36 */ -#elif SIZEOF_LONG == 8 -/* [int(math.floor(math.log(2**64, i))) for i in range(2, 37)] */ -static int digitlimit[] = { - 0, 0, 64, 40, 32, 27, 24, 22, 21, 20, /* 0 - 9 */ - 19, 18, 17, 17, 16, 16, 16, 15, 15, 15, /* 10 - 19 */ - 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, /* 20 - 29 */ - 13, 12, 12, 12, 12, 12, 12}; /* 30 - 36 */ -#else -#error "Need table for SIZEOF_LONG" -#endif - -/* -** strtoul -** This is a general purpose routine for converting -** an ascii string to an integer in an arbitrary base. -** Leading white space is ignored. If 'base' is zero -** it looks for a leading 0, 0x or 0X to tell which -** base. If these are absent it defaults to 10. -** Base must be 0 or between 2 and 36 (inclusive). -** If 'ptr' is non-NULL it will contain a pointer to -** the end of the scan. -** Errors due to bad pointers will probably result in -** exceptions - we don't check for them. -*/ -unsigned long -PyOS_strtoul(register char *str, char **ptr, int base) -{ - register unsigned long result = 0; /* return value of the function */ - register int c; /* current input character */ - register int ovlimit; /* required digits to overflow */ - - /* skip leading white space */ - while (*str && isspace(Py_CHARMASK(*str))) - ++str; - - /* check for leading 0 or 0x for auto-base or base 16 */ - switch (base) { - case 0: /* look for leading 0, 0x or 0X */ - if (*str == '0') { - ++str; - if (*str == 'x' || *str == 'X') { - ++str; - base = 16; - } - else - base = 8; - } - else - base = 10; - break; - - case 16: /* skip leading 0x or 0X */ - if (*str == '0') { - ++str; - if (*str == 'x' || *str == 'X') - ++str; - } - break; - } - - /* catch silly bases */ - if (base < 2 || base > 36) { - if (ptr) - *ptr = str; - return 0; - } - - /* skip leading zeroes */ - while (*str == '0') - ++str; - - /* base is guaranteed to be in [2, 36] at this point */ - ovlimit = digitlimit[base]; - - /* do the conversion until non-digit character encountered */ - while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) { - if (ovlimit > 0) /* no overflow check required */ - result = result * base + c; - else { /* requires overflow check */ - register unsigned long temp_result; - - if (ovlimit < 0) /* guaranteed overflow */ - goto overflowed; - - /* there could be an overflow */ - /* check overflow just from shifting */ - if (result > smallmax[base]) - goto overflowed; - - result *= base; - - /* check overflow from the digit's value */ - temp_result = result + c; - if (temp_result < result) - goto overflowed; - - result = temp_result; - } - - ++str; - --ovlimit; - } - - /* set pointer to point to the last character scanned */ - if (ptr) - *ptr = str; - - return result; - -overflowed: - if (ptr) { - /* spool through remaining digit characters */ - while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base) - ++str; - *ptr = str; - } - errno = ERANGE; - return (unsigned long)-1; -} - -/* Checking for overflow in PyOS_strtol is a PITA; see comments - * about PY_ABS_LONG_MIN in longobject.c. - */ -#define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN) - -long -PyOS_strtol(char *str, char **ptr, int base) -{ - long result; - unsigned long uresult; - char sign; - - while (*str && isspace(Py_CHARMASK(*str))) - str++; - - sign = *str; - if (sign == '+' || sign == '-') - str++; - - uresult = PyOS_strtoul(str, ptr, base); - - if (uresult <= (unsigned long)LONG_MAX) { - result = (long)uresult; - if (sign == '-') - result = -result; - } - else if (sign == '-' && uresult == PY_ABS_LONG_MIN) { - result = LONG_MIN; - } - else { - errno = ERANGE; - result = LONG_MAX; - } - return result; -} diff --git a/sys/src/cmd/python/Python/pyarena.c b/sys/src/cmd/python/Python/pyarena.c deleted file mode 100644 index f4cc474f4..000000000 --- a/sys/src/cmd/python/Python/pyarena.c +++ /dev/null @@ -1,220 +0,0 @@ -#include "Python.h" -#include "pyarena.h" - -/* A simple arena block structure. - - Measurements with standard library modules suggest the average - allocation is about 20 bytes and that most compiles use a single - block. - - TODO(jhylton): Think about a realloc API, maybe just for the last - allocation? -*/ - -#define DEFAULT_BLOCK_SIZE 8192 -#define ALIGNMENT 8 -#define ALIGNMENT_MASK (ALIGNMENT - 1) -#define ROUNDUP(x) (((x) + ALIGNMENT_MASK) & ~ALIGNMENT_MASK) - -typedef struct _block { - /* Total number of bytes owned by this block available to pass out. - * Read-only after initialization. The first such byte starts at - * ab_mem. - */ - size_t ab_size; - - /* Total number of bytes already passed out. The next byte available - * to pass out starts at ab_mem + ab_offset. - */ - size_t ab_offset; - - /* An arena maintains a singly-linked, NULL-terminated list of - * all blocks owned by the arena. These are linked via the - * ab_next member. - */ - struct _block *ab_next; - - /* Pointer to the first allocatable byte owned by this block. Read- - * only after initialization. - */ - void *ab_mem; -} block; - -/* The arena manages two kinds of memory, blocks of raw memory - and a list of PyObject* pointers. PyObjects are decrefed - when the arena is freed. -*/ - -struct _arena { - /* Pointer to the first block allocated for the arena, never NULL. - It is used only to find the first block when the arena is - being freed. - */ - block *a_head; - - /* Pointer to the block currently used for allocation. It's - ab_next field should be NULL. If it is not-null after a - call to block_alloc(), it means a new block has been allocated - and a_cur should be reset to point it. - */ - block *a_cur; - - /* A Python list object containing references to all the PyObject - pointers associated with this area. They will be DECREFed - when the arena is freed. - */ - PyObject *a_objects; - -#if defined(Py_DEBUG) - /* Debug output */ - size_t total_allocs; - size_t total_size; - size_t total_blocks; - size_t total_block_size; - size_t total_big_blocks; -#endif -}; - -static block * -block_new(size_t size) -{ - /* Allocate header and block as one unit. - ab_mem points just past header. */ - block *b = (block *)malloc(sizeof(block) + size); - if (!b) - return NULL; - b->ab_size = size; - b->ab_mem = (void *)(b + 1); - b->ab_next = NULL; - b->ab_offset = ROUNDUP((Py_uintptr_t)(b->ab_mem)) - - (Py_uintptr_t)(b->ab_mem); - return b; -} - -static void -block_free(block *b) { - while (b) { - block *next = b->ab_next; - free(b); - b = next; - } -} - -static void * -block_alloc(block *b, size_t size) -{ - void *p; - assert(b); - size = ROUNDUP(size); - if (b->ab_offset + size > b->ab_size) { - /* If we need to allocate more memory than will fit in - the default block, allocate a one-off block that is - exactly the right size. */ - /* TODO(jhylton): Think about space waste at end of block */ - block *newbl = block_new( - size < DEFAULT_BLOCK_SIZE ? - DEFAULT_BLOCK_SIZE : size); - if (!newbl) - return NULL; - assert(!b->ab_next); - b->ab_next = newbl; - b = newbl; - } - - assert(b->ab_offset + size <= b->ab_size); - p = (void *)(((char *)b->ab_mem) + b->ab_offset); - b->ab_offset += size; - return p; -} - -PyArena * -PyArena_New() -{ - PyArena* arena = (PyArena *)malloc(sizeof(PyArena)); - if (!arena) - return (PyArena*)PyErr_NoMemory(); - - arena->a_head = block_new(DEFAULT_BLOCK_SIZE); - arena->a_cur = arena->a_head; - if (!arena->a_head) { - free((void *)arena); - return (PyArena*)PyErr_NoMemory(); - } - arena->a_objects = PyList_New(0); - if (!arena->a_objects) { - block_free(arena->a_head); - free((void *)arena); - return (PyArena*)PyErr_NoMemory(); - } -#if defined(Py_DEBUG) - arena->total_allocs = 0; - arena->total_size = 0; - arena->total_blocks = 1; - arena->total_block_size = DEFAULT_BLOCK_SIZE; - arena->total_big_blocks = 0; -#endif - return arena; -} - -void -PyArena_Free(PyArena *arena) -{ - int r; - assert(arena); -#if defined(Py_DEBUG) - /* - fprintf(stderr, - "alloc=%d size=%d blocks=%d block_size=%d big=%d objects=%d\n", - arena->total_allocs, arena->total_size, arena->total_blocks, - arena->total_block_size, arena->total_big_blocks, - PyList_Size(arena->a_objects)); - */ -#endif - block_free(arena->a_head); - /* This property normally holds, except when the code being compiled - is sys.getobjects(0), in which case there will be two references. - assert(arena->a_objects->ob_refcnt == 1); - */ - - /* Clear all the elements from the list. This is necessary - to guarantee that they will be DECREFed. */ - r = PyList_SetSlice(arena->a_objects, - 0, PyList_GET_SIZE(arena->a_objects), NULL); - assert(r == 0); - assert(PyList_GET_SIZE(arena->a_objects) == 0); - Py_DECREF(arena->a_objects); - free(arena); -} - -void * -PyArena_Malloc(PyArena *arena, size_t size) -{ - void *p = block_alloc(arena->a_cur, size); - if (!p) - return PyErr_NoMemory(); -#if defined(Py_DEBUG) - arena->total_allocs++; - arena->total_size += size; -#endif - /* Reset cur if we allocated a new block. */ - if (arena->a_cur->ab_next) { - arena->a_cur = arena->a_cur->ab_next; -#if defined(Py_DEBUG) - arena->total_blocks++; - arena->total_block_size += arena->a_cur->ab_size; - if (arena->a_cur->ab_size > DEFAULT_BLOCK_SIZE) - ++arena->total_big_blocks; -#endif - } - return p; -} - -int -PyArena_AddPyObject(PyArena *arena, PyObject *obj) -{ - int r = PyList_Append(arena->a_objects, obj); - if (r >= 0) { - Py_DECREF(obj); - } - return r; -} diff --git a/sys/src/cmd/python/Python/pyfpe.c b/sys/src/cmd/python/Python/pyfpe.c deleted file mode 100644 index 4b7f5bae1..000000000 --- a/sys/src/cmd/python/Python/pyfpe.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "pyconfig.h" -#include "pyfpe.h" -/* - * The signal handler for SIGFPE is actually declared in an external - * module fpectl, or as preferred by the user. These variable - * definitions are required in order to compile Python without - * getting missing externals, but to actually handle SIGFPE requires - * defining a handler and enabling generation of SIGFPE. - */ - -#ifdef WANT_SIGFPE_HANDLER -jmp_buf PyFPE_jbuf; -int PyFPE_counter = 0; -#endif - -/* Have this outside the above #ifdef, since some picky ANSI compilers issue a - warning when compiling an empty file. */ - -double -PyFPE_dummy(void *dummy) -{ - return 1.0; -} diff --git a/sys/src/cmd/python/Python/pystate.c b/sys/src/cmd/python/Python/pystate.c deleted file mode 100644 index 086789d35..000000000 --- a/sys/src/cmd/python/Python/pystate.c +++ /dev/null @@ -1,632 +0,0 @@ - -/* Thread and interpreter state structures and their interfaces */ - -#include "Python.h" - -/* -------------------------------------------------------------------------- -CAUTION - -Always use malloc() and free() directly in this file. A number of these -functions are advertised as safe to call when the GIL isn't held, and in -a debug build Python redirects (e.g.) PyMem_NEW (etc) to Python's debugging -obmalloc functions. Those aren't thread-safe (they rely on the GIL to avoid -the expense of doing their own locking). --------------------------------------------------------------------------- */ - -#ifdef HAVE_DLOPEN -#ifdef HAVE_DLFCN_H -#include <dlfcn.h> -#endif -#ifndef RTLD_LAZY -#define RTLD_LAZY 1 -#endif -#endif - - -#ifdef WITH_THREAD -#include "pythread.h" -static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */ -#define HEAD_INIT() (void)(head_mutex || (head_mutex = PyThread_allocate_lock())) -#define HEAD_LOCK() PyThread_acquire_lock(head_mutex, WAIT_LOCK) -#define HEAD_UNLOCK() PyThread_release_lock(head_mutex) - -#ifdef __cplusplus -extern "C" { -#endif - -/* The single PyInterpreterState used by this process' - GILState implementation -*/ -static PyInterpreterState *autoInterpreterState = NULL; -static int autoTLSkey = 0; -#else -#define HEAD_INIT() /* Nothing */ -#define HEAD_LOCK() /* Nothing */ -#define HEAD_UNLOCK() /* Nothing */ -#endif - -static PyInterpreterState *interp_head = NULL; - -PyThreadState *_PyThreadState_Current = NULL; -PyThreadFrameGetter _PyThreadState_GetFrame = NULL; - -#ifdef WITH_THREAD -static void _PyGILState_NoteThreadState(PyThreadState* tstate); -#endif - - -PyInterpreterState * -PyInterpreterState_New(void) -{ - PyInterpreterState *interp = (PyInterpreterState *) - malloc(sizeof(PyInterpreterState)); - - if (interp != NULL) { - HEAD_INIT(); -#ifdef WITH_THREAD - if (head_mutex == NULL) - Py_FatalError("Can't initialize threads for interpreter"); -#endif - interp->modules = NULL; - interp->modules_reloading = NULL; - interp->sysdict = NULL; - interp->builtins = NULL; - interp->tstate_head = NULL; - interp->codec_search_path = NULL; - interp->codec_search_cache = NULL; - interp->codec_error_registry = NULL; -#ifdef HAVE_DLOPEN -#ifdef RTLD_NOW - interp->dlopenflags = RTLD_NOW; -#else - interp->dlopenflags = RTLD_LAZY; -#endif -#endif -#ifdef WITH_TSC - interp->tscdump = 0; -#endif - - HEAD_LOCK(); - interp->next = interp_head; - interp_head = interp; - HEAD_UNLOCK(); - } - - return interp; -} - - -void -PyInterpreterState_Clear(PyInterpreterState *interp) -{ - PyThreadState *p; - HEAD_LOCK(); - for (p = interp->tstate_head; p != NULL; p = p->next) - PyThreadState_Clear(p); - HEAD_UNLOCK(); - Py_CLEAR(interp->codec_search_path); - Py_CLEAR(interp->codec_search_cache); - Py_CLEAR(interp->codec_error_registry); - Py_CLEAR(interp->modules); - Py_CLEAR(interp->modules_reloading); - Py_CLEAR(interp->sysdict); - Py_CLEAR(interp->builtins); -} - - -static void -zapthreads(PyInterpreterState *interp) -{ - PyThreadState *p; - /* No need to lock the mutex here because this should only happen - when the threads are all really dead (XXX famous last words). */ - while ((p = interp->tstate_head) != NULL) { - PyThreadState_Delete(p); - } -} - - -void -PyInterpreterState_Delete(PyInterpreterState *interp) -{ - PyInterpreterState **p; - zapthreads(interp); - HEAD_LOCK(); - for (p = &interp_head; ; p = &(*p)->next) { - if (*p == NULL) - Py_FatalError( - "PyInterpreterState_Delete: invalid interp"); - if (*p == interp) - break; - } - if (interp->tstate_head != NULL) - Py_FatalError("PyInterpreterState_Delete: remaining threads"); - *p = interp->next; - HEAD_UNLOCK(); - free(interp); -} - - -/* Default implementation for _PyThreadState_GetFrame */ -static struct _frame * -threadstate_getframe(PyThreadState *self) -{ - return self->frame; -} - -PyThreadState * -PyThreadState_New(PyInterpreterState *interp) -{ - PyThreadState *tstate = (PyThreadState *)malloc(sizeof(PyThreadState)); - - if (_PyThreadState_GetFrame == NULL) - _PyThreadState_GetFrame = threadstate_getframe; - - if (tstate != NULL) { - tstate->interp = interp; - - tstate->frame = NULL; - tstate->recursion_depth = 0; - tstate->tracing = 0; - tstate->use_tracing = 0; - tstate->tick_counter = 0; - tstate->gilstate_counter = 0; - tstate->async_exc = NULL; -#ifdef WITH_THREAD - tstate->thread_id = PyThread_get_thread_ident(); -#else - tstate->thread_id = 0; -#endif - - tstate->dict = NULL; - - tstate->curexc_type = NULL; - tstate->curexc_value = NULL; - tstate->curexc_traceback = NULL; - - tstate->exc_type = NULL; - tstate->exc_value = NULL; - tstate->exc_traceback = NULL; - - tstate->c_profilefunc = NULL; - tstate->c_tracefunc = NULL; - tstate->c_profileobj = NULL; - tstate->c_traceobj = NULL; - -#ifdef WITH_THREAD - _PyGILState_NoteThreadState(tstate); -#endif - - HEAD_LOCK(); - tstate->next = interp->tstate_head; - interp->tstate_head = tstate; - HEAD_UNLOCK(); - } - - return tstate; -} - - -void -PyThreadState_Clear(PyThreadState *tstate) -{ - if (Py_VerboseFlag && tstate->frame != NULL) - fprintf(stderr, - "PyThreadState_Clear: warning: thread still has a frame\n"); - - Py_CLEAR(tstate->frame); - - Py_CLEAR(tstate->dict); - Py_CLEAR(tstate->async_exc); - - Py_CLEAR(tstate->curexc_type); - Py_CLEAR(tstate->curexc_value); - Py_CLEAR(tstate->curexc_traceback); - - Py_CLEAR(tstate->exc_type); - Py_CLEAR(tstate->exc_value); - Py_CLEAR(tstate->exc_traceback); - - tstate->c_profilefunc = NULL; - tstate->c_tracefunc = NULL; - Py_CLEAR(tstate->c_profileobj); - Py_CLEAR(tstate->c_traceobj); -} - - -/* Common code for PyThreadState_Delete() and PyThreadState_DeleteCurrent() */ -static void -tstate_delete_common(PyThreadState *tstate) -{ - PyInterpreterState *interp; - PyThreadState **p; - if (tstate == NULL) - Py_FatalError("PyThreadState_Delete: NULL tstate"); - interp = tstate->interp; - if (interp == NULL) - Py_FatalError("PyThreadState_Delete: NULL interp"); - HEAD_LOCK(); - for (p = &interp->tstate_head; ; p = &(*p)->next) { - if (*p == NULL) - Py_FatalError( - "PyThreadState_Delete: invalid tstate"); - if (*p == tstate) - break; - } - *p = tstate->next; - HEAD_UNLOCK(); - free(tstate); -} - - -void -PyThreadState_Delete(PyThreadState *tstate) -{ - if (tstate == _PyThreadState_Current) - Py_FatalError("PyThreadState_Delete: tstate is still current"); - tstate_delete_common(tstate); -#ifdef WITH_THREAD - if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate) - PyThread_delete_key_value(autoTLSkey); -#endif /* WITH_THREAD */ -} - - -#ifdef WITH_THREAD -void -PyThreadState_DeleteCurrent() -{ - PyThreadState *tstate = _PyThreadState_Current; - if (tstate == NULL) - Py_FatalError( - "PyThreadState_DeleteCurrent: no current tstate"); - _PyThreadState_Current = NULL; - tstate_delete_common(tstate); - if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate) - PyThread_delete_key_value(autoTLSkey); - PyEval_ReleaseLock(); -} -#endif /* WITH_THREAD */ - - -PyThreadState * -PyThreadState_Get(void) -{ - if (_PyThreadState_Current == NULL) - Py_FatalError("PyThreadState_Get: no current thread"); - - return _PyThreadState_Current; -} - - -PyThreadState * -PyThreadState_Swap(PyThreadState *newts) -{ - PyThreadState *oldts = _PyThreadState_Current; - - _PyThreadState_Current = newts; - /* It should not be possible for more than one thread state - to be used for a thread. Check this the best we can in debug - builds. - */ -#if defined(Py_DEBUG) && defined(WITH_THREAD) - if (newts) { - /* This can be called from PyEval_RestoreThread(). Similar - to it, we need to ensure errno doesn't change. - */ - int err = errno; - PyThreadState *check = PyGILState_GetThisThreadState(); - if (check && check->interp == newts->interp && check != newts) - Py_FatalError("Invalid thread state for this thread"); - errno = err; - } -#endif - return oldts; -} - -/* An extension mechanism to store arbitrary additional per-thread state. - PyThreadState_GetDict() returns a dictionary that can be used to hold such - state; the caller should pick a unique key and store its state there. If - PyThreadState_GetDict() returns NULL, an exception has *not* been raised - and the caller should assume no per-thread state is available. */ - -PyObject * -PyThreadState_GetDict(void) -{ - if (_PyThreadState_Current == NULL) - return NULL; - - if (_PyThreadState_Current->dict == NULL) { - PyObject *d; - _PyThreadState_Current->dict = d = PyDict_New(); - if (d == NULL) - PyErr_Clear(); - } - return _PyThreadState_Current->dict; -} - - -/* Asynchronously raise an exception in a thread. - Requested by Just van Rossum and Alex Martelli. - To prevent naive misuse, you must write your own extension - to call this, or use ctypes. Must be called with the GIL held. - Returns the number of tstates modified (normally 1, but 0 if `id` didn't - match any known thread id). Can be called with exc=NULL to clear an - existing async exception. This raises no exceptions. */ - -int -PyThreadState_SetAsyncExc(long id, PyObject *exc) { - PyThreadState *tstate = PyThreadState_GET(); - PyInterpreterState *interp = tstate->interp; - PyThreadState *p; - - /* Although the GIL is held, a few C API functions can be called - * without the GIL held, and in particular some that create and - * destroy thread and interpreter states. Those can mutate the - * list of thread states we're traversing, so to prevent that we lock - * head_mutex for the duration. - */ - HEAD_LOCK(); - for (p = interp->tstate_head; p != NULL; p = p->next) { - if (p->thread_id == id) { - /* Tricky: we need to decref the current value - * (if any) in p->async_exc, but that can in turn - * allow arbitrary Python code to run, including - * perhaps calls to this function. To prevent - * deadlock, we need to release head_mutex before - * the decref. - */ - PyObject *old_exc = p->async_exc; - Py_XINCREF(exc); - p->async_exc = exc; - HEAD_UNLOCK(); - Py_XDECREF(old_exc); - return 1; - } - } - HEAD_UNLOCK(); - return 0; -} - - -/* Routines for advanced debuggers, requested by David Beazley. - Don't use unless you know what you are doing! */ - -PyInterpreterState * -PyInterpreterState_Head(void) -{ - return interp_head; -} - -PyInterpreterState * -PyInterpreterState_Next(PyInterpreterState *interp) { - return interp->next; -} - -PyThreadState * -PyInterpreterState_ThreadHead(PyInterpreterState *interp) { - return interp->tstate_head; -} - -PyThreadState * -PyThreadState_Next(PyThreadState *tstate) { - return tstate->next; -} - -/* The implementation of sys._current_frames(). This is intended to be - called with the GIL held, as it will be when called via - sys._current_frames(). It's possible it would work fine even without - the GIL held, but haven't thought enough about that. -*/ -PyObject * -_PyThread_CurrentFrames(void) -{ - PyObject *result; - PyInterpreterState *i; - - result = PyDict_New(); - if (result == NULL) - return NULL; - - /* for i in all interpreters: - * for t in all of i's thread states: - * if t's frame isn't NULL, map t's id to its frame - * Because these lists can mutute even when the GIL is held, we - * need to grab head_mutex for the duration. - */ - HEAD_LOCK(); - for (i = interp_head; i != NULL; i = i->next) { - PyThreadState *t; - for (t = i->tstate_head; t != NULL; t = t->next) { - PyObject *id; - int stat; - struct _frame *frame = t->frame; - if (frame == NULL) - continue; - id = PyInt_FromLong(t->thread_id); - if (id == NULL) - goto Fail; - stat = PyDict_SetItem(result, id, (PyObject *)frame); - Py_DECREF(id); - if (stat < 0) - goto Fail; - } - } - HEAD_UNLOCK(); - return result; - - Fail: - HEAD_UNLOCK(); - Py_DECREF(result); - return NULL; -} - -/* Python "auto thread state" API. */ -#ifdef WITH_THREAD - -/* Keep this as a static, as it is not reliable! It can only - ever be compared to the state for the *current* thread. - * If not equal, then it doesn't matter that the actual - value may change immediately after comparison, as it can't - possibly change to the current thread's state. - * If equal, then the current thread holds the lock, so the value can't - change until we yield the lock. -*/ -static int -PyThreadState_IsCurrent(PyThreadState *tstate) -{ - /* Must be the tstate for this thread */ - assert(PyGILState_GetThisThreadState()==tstate); - /* On Windows at least, simple reads and writes to 32 bit values - are atomic. - */ - return tstate == _PyThreadState_Current; -} - -/* Internal initialization/finalization functions called by - Py_Initialize/Py_Finalize -*/ -void -_PyGILState_Init(PyInterpreterState *i, PyThreadState *t) -{ - assert(i && t); /* must init with valid states */ - autoTLSkey = PyThread_create_key(); - autoInterpreterState = i; - assert(PyThread_get_key_value(autoTLSkey) == NULL); - assert(t->gilstate_counter == 0); - - _PyGILState_NoteThreadState(t); -} - -void -_PyGILState_Fini(void) -{ - PyThread_delete_key(autoTLSkey); - autoTLSkey = 0; - autoInterpreterState = NULL; -} - -/* When a thread state is created for a thread by some mechanism other than - PyGILState_Ensure, it's important that the GILState machinery knows about - it so it doesn't try to create another thread state for the thread (this is - a better fix for SF bug #1010677 than the first one attempted). -*/ -static void -_PyGILState_NoteThreadState(PyThreadState* tstate) -{ - /* If autoTLSkey is 0, this must be the very first threadstate created - in Py_Initialize(). Don't do anything for now (we'll be back here - when _PyGILState_Init is called). */ - if (!autoTLSkey) - return; - - /* Stick the thread state for this thread in thread local storage. - - The only situation where you can legitimately have more than one - thread state for an OS level thread is when there are multiple - interpreters, when: - - a) You shouldn't really be using the PyGILState_ APIs anyway, - and: - - b) The slightly odd way PyThread_set_key_value works (see - comments by its implementation) means that the first thread - state created for that given OS level thread will "win", - which seems reasonable behaviour. - */ - if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0) - Py_FatalError("Couldn't create autoTLSkey mapping"); - - /* PyGILState_Release must not try to delete this thread state. */ - tstate->gilstate_counter = 1; -} - -/* The public functions */ -PyThreadState * -PyGILState_GetThisThreadState(void) -{ - if (autoInterpreterState == NULL || autoTLSkey == 0) - return NULL; - return (PyThreadState *)PyThread_get_key_value(autoTLSkey); -} - -PyGILState_STATE -PyGILState_Ensure(void) -{ - int current; - PyThreadState *tcur; - /* Note that we do not auto-init Python here - apart from - potential races with 2 threads auto-initializing, pep-311 - spells out other issues. Embedders are expected to have - called Py_Initialize() and usually PyEval_InitThreads(). - */ - assert(autoInterpreterState); /* Py_Initialize() hasn't been called! */ - tcur = (PyThreadState *)PyThread_get_key_value(autoTLSkey); - if (tcur == NULL) { - /* Create a new thread state for this thread */ - tcur = PyThreadState_New(autoInterpreterState); - if (tcur == NULL) - Py_FatalError("Couldn't create thread-state for new thread"); - /* This is our thread state! We'll need to delete it in the - matching call to PyGILState_Release(). */ - tcur->gilstate_counter = 0; - current = 0; /* new thread state is never current */ - } - else - current = PyThreadState_IsCurrent(tcur); - if (current == 0) - PyEval_RestoreThread(tcur); - /* Update our counter in the thread-state - no need for locks: - - tcur will remain valid as we hold the GIL. - - the counter is safe as we are the only thread "allowed" - to modify this value - */ - ++tcur->gilstate_counter; - return current ? PyGILState_LOCKED : PyGILState_UNLOCKED; -} - -void -PyGILState_Release(PyGILState_STATE oldstate) -{ - PyThreadState *tcur = (PyThreadState *)PyThread_get_key_value( - autoTLSkey); - if (tcur == NULL) - Py_FatalError("auto-releasing thread-state, " - "but no thread-state for this thread"); - /* We must hold the GIL and have our thread state current */ - /* XXX - remove the check - the assert should be fine, - but while this is very new (April 2003), the extra check - by release-only users can't hurt. - */ - if (! PyThreadState_IsCurrent(tcur)) - Py_FatalError("This thread state must be current when releasing"); - assert(PyThreadState_IsCurrent(tcur)); - --tcur->gilstate_counter; - assert(tcur->gilstate_counter >= 0); /* illegal counter value */ - - /* If we're going to destroy this thread-state, we must - * clear it while the GIL is held, as destructors may run. - */ - if (tcur->gilstate_counter == 0) { - /* can't have been locked when we created it */ - assert(oldstate == PyGILState_UNLOCKED); - PyThreadState_Clear(tcur); - /* Delete the thread-state. Note this releases the GIL too! - * It's vital that the GIL be held here, to avoid shutdown - * races; see bugs 225673 and 1061968 (that nasty bug has a - * habit of coming back). - */ - PyThreadState_DeleteCurrent(); - } - /* Release the lock if necessary */ - else if (oldstate == PyGILState_UNLOCKED) - PyEval_SaveThread(); -} - -#ifdef __cplusplus -} -#endif - -#endif /* WITH_THREAD */ - - diff --git a/sys/src/cmd/python/Python/pystrtod.c b/sys/src/cmd/python/Python/pystrtod.c deleted file mode 100644 index 6c19b45fd..000000000 --- a/sys/src/cmd/python/Python/pystrtod.c +++ /dev/null @@ -1,248 +0,0 @@ -/* -*- Mode: C; c-file-style: "python" -*- */ - -#include <Python.h> -#include <locale.h> - -/* ascii character tests (as opposed to locale tests) */ -#define ISSPACE(c) ((c) == ' ' || (c) == '\f' || (c) == '\n' || \ - (c) == '\r' || (c) == '\t' || (c) == '\v') -#define ISDIGIT(c) ((c) >= '0' && (c) <= '9') -#define ISXDIGIT(c) (ISDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) - - -/** - * PyOS_ascii_strtod: - * @nptr: the string to convert to a numeric value. - * @endptr: if non-%NULL, it returns the character after - * the last character used in the conversion. - * - * Converts a string to a #gdouble value. - * This function behaves like the standard strtod() function - * does in the C locale. It does this without actually - * changing the current locale, since that would not be - * thread-safe. - * - * This function is typically used when reading configuration - * files or other non-user input that should be locale independent. - * To handle input from the user you should normally use the - * locale-sensitive system strtod() function. - * - * If the correct value would cause overflow, plus or minus %HUGE_VAL - * is returned (according to the sign of the value), and %ERANGE is - * stored in %errno. If the correct value would cause underflow, - * zero is returned and %ERANGE is stored in %errno. - * If memory allocation fails, %ENOMEM is stored in %errno. - * - * This function resets %errno before calling strtod() so that - * you can reliably detect overflow and underflow. - * - * Return value: the #gdouble value. - **/ -double -PyOS_ascii_strtod(const char *nptr, char **endptr) -{ - char *fail_pos; - double val = -1.0; - struct lconv *locale_data; - const char *decimal_point; - size_t decimal_point_len; - const char *p, *decimal_point_pos; - const char *end = NULL; /* Silence gcc */ - - assert(nptr != NULL); - - fail_pos = NULL; - - locale_data = localeconv(); - decimal_point = locale_data->decimal_point; - decimal_point_len = strlen(decimal_point); - - assert(decimal_point_len != 0); - - decimal_point_pos = NULL; - if (decimal_point[0] != '.' || - decimal_point[1] != 0) - { - p = nptr; - /* Skip leading space */ - while (ISSPACE(*p)) - p++; - - /* Skip leading optional sign */ - if (*p == '+' || *p == '-') - p++; - - while (ISDIGIT(*p)) - p++; - - if (*p == '.') - { - decimal_point_pos = p++; - - while (ISDIGIT(*p)) - p++; - - if (*p == 'e' || *p == 'E') - p++; - if (*p == '+' || *p == '-') - p++; - while (ISDIGIT(*p)) - p++; - end = p; - } - else if (strncmp(p, decimal_point, decimal_point_len) == 0) - { - /* Python bug #1417699 */ - *endptr = (char*)nptr; - errno = EINVAL; - return val; - } - /* For the other cases, we need not convert the decimal point */ - } - - /* Set errno to zero, so that we can distinguish zero results - and underflows */ - errno = 0; - - if (decimal_point_pos) - { - char *copy, *c; - - /* We need to convert the '.' to the locale specific decimal point */ - copy = (char *)PyMem_MALLOC(end - nptr + 1 + decimal_point_len); - if (copy == NULL) { - if (endptr) - *endptr = (char *)nptr; - errno = ENOMEM; - return val; - } - - c = copy; - memcpy(c, nptr, decimal_point_pos - nptr); - c += decimal_point_pos - nptr; - memcpy(c, decimal_point, decimal_point_len); - c += decimal_point_len; - memcpy(c, decimal_point_pos + 1, end - (decimal_point_pos + 1)); - c += end - (decimal_point_pos + 1); - *c = 0; - - val = strtod(copy, &fail_pos); - - if (fail_pos) - { - if (fail_pos > decimal_point_pos) - fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1); - else - fail_pos = (char *)nptr + (fail_pos - copy); - } - - PyMem_FREE(copy); - - } - else { - unsigned i = 0; - if (nptr[i] == '-') - i++; - if (nptr[i] == '0' && (nptr[i+1] == 'x' || nptr[i+1] == 'X')) - fail_pos = (char*)nptr; - else - val = strtod(nptr, &fail_pos); - } - - if (endptr) - *endptr = fail_pos; - - return val; -} - - -/** - * PyOS_ascii_formatd: - * @buffer: A buffer to place the resulting string in - * @buf_len: The length of the buffer. - * @format: The printf()-style format to use for the - * code to use for converting. - * @d: The #gdouble to convert - * - * Converts a #gdouble to a string, using the '.' as - * decimal point. To format the number you pass in - * a printf()-style format string. Allowed conversion - * specifiers are 'e', 'E', 'f', 'F', 'g' and 'G'. - * - * Return value: The pointer to the buffer with the converted string. - **/ -char * -PyOS_ascii_formatd(char *buffer, - size_t buf_len, - const char *format, - double d) -{ - struct lconv *locale_data; - const char *decimal_point; - size_t decimal_point_len, rest_len; - char *p; - char format_char; - -/* g_return_val_if_fail (buffer != NULL, NULL); */ -/* g_return_val_if_fail (format[0] == '%', NULL); */ -/* g_return_val_if_fail (strpbrk (format + 1, "'l%") == NULL, NULL); */ - - format_char = format[strlen(format) - 1]; - -/* g_return_val_if_fail (format_char == 'e' || format_char == 'E' || */ -/* format_char == 'f' || format_char == 'F' || */ -/* format_char == 'g' || format_char == 'G', */ -/* NULL); */ - - if (format[0] != '%') - return NULL; - - if (strpbrk(format + 1, "'l%")) - return NULL; - - if (!(format_char == 'e' || format_char == 'E' || - format_char == 'f' || format_char == 'F' || - format_char == 'g' || format_char == 'G')) - return NULL; - - - PyOS_snprintf(buffer, buf_len, format, d); - - locale_data = localeconv(); - decimal_point = locale_data->decimal_point; - decimal_point_len = strlen(decimal_point); - - assert(decimal_point_len != 0); - - if (decimal_point[0] != '.' || - decimal_point[1] != 0) - { - p = buffer; - - if (*p == '+' || *p == '-') - p++; - - while (isdigit((unsigned char)*p)) - p++; - - if (strncmp(p, decimal_point, decimal_point_len) == 0) - { - *p = '.'; - p++; - if (decimal_point_len > 1) { - rest_len = strlen(p + (decimal_point_len - 1)); - memmove(p, p + (decimal_point_len - 1), - rest_len); - p[rest_len] = 0; - } - } - } - - return buffer; -} - -double -PyOS_ascii_atof(const char *nptr) -{ - return PyOS_ascii_strtod(nptr, NULL); -} diff --git a/sys/src/cmd/python/Python/pythonrun.c b/sys/src/cmd/python/Python/pythonrun.c deleted file mode 100644 index 75241fe91..000000000 --- a/sys/src/cmd/python/Python/pythonrun.c +++ /dev/null @@ -1,1857 +0,0 @@ - -/* Python interpreter top-level routines, including init/exit */ - -#include "Python.h" - -#include "Python-ast.h" -#include "grammar.h" -#include "node.h" -#include "token.h" -#include "parsetok.h" -#include "errcode.h" -#include "code.h" -#include "compile.h" -#include "symtable.h" -#include "pyarena.h" -#include "ast.h" -#include "eval.h" -#include "marshal.h" - -#ifdef HAVE_SIGNAL_H -#include <signal.h> -#endif - -#ifdef HAVE_LANGINFO_H -#include <locale.h> -#include <langinfo.h> -#endif - -#ifdef MS_WINDOWS -#undef BYTE -#include "windows.h" -#endif - -#ifndef Py_REF_DEBUG -#define PRINT_TOTAL_REFS() -#else /* Py_REF_DEBUG */ -#define PRINT_TOTAL_REFS() fprintf(stderr, \ - "[%" PY_FORMAT_SIZE_T "d refs]\n", \ - _Py_GetRefTotal()) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -extern char *Py_GetPath(void); - -extern grammar _PyParser_Grammar; /* From graminit.c */ - -/* Forward */ -static void initmain(void); -static void initsite(void); -static PyObject *run_mod(mod_ty, const char *, PyObject *, PyObject *, - PyCompilerFlags *, PyArena *); -static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *, - PyCompilerFlags *); -static void err_input(perrdetail *); -static void initsigs(void); -static void call_sys_exitfunc(void); -static void call_ll_exitfuncs(void); -extern void _PyUnicode_Init(void); -extern void _PyUnicode_Fini(void); - -#ifdef WITH_THREAD -extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *); -extern void _PyGILState_Fini(void); -#endif /* WITH_THREAD */ - -int Py_DebugFlag; /* Needed by parser.c */ -int Py_VerboseFlag; /* Needed by import.c */ -int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */ -int Py_NoSiteFlag; /* Suppress 'import site' */ -int Py_UseClassExceptionsFlag = 1; /* Needed by bltinmodule.c: deprecated */ -int Py_FrozenFlag; /* Needed by getpath.c */ -int Py_UnicodeFlag = 0; /* Needed by compile.c */ -int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */ -/* _XXX Py_QnewFlag should go away in 2.3. It's true iff -Qnew is passed, - on the command line, and is used in 2.2 by ceval.c to make all "/" divisions - true divisions (which they will be in 2.3). */ -int _Py_QnewFlag = 0; - -/* Reference to 'warnings' module, to avoid importing it - on the fly when the import lock may be held. See 683658/771097 -*/ -static PyObject *warnings_module = NULL; - -/* Returns a borrowed reference to the 'warnings' module, or NULL. - If the module is returned, it is guaranteed to have been obtained - without acquiring the import lock -*/ -PyObject *PyModule_GetWarningsModule(void) -{ - PyObject *typ, *val, *tb; - PyObject *all_modules; - /* If we managed to get the module at init time, just use it */ - if (warnings_module) - return warnings_module; - /* If it wasn't available at init time, it may be available - now in sys.modules (common scenario is frozen apps: import - at init time fails, but the frozen init code sets up sys.path - correctly, then does an implicit import of warnings for us - */ - /* Save and restore any exceptions */ - PyErr_Fetch(&typ, &val, &tb); - - all_modules = PySys_GetObject("modules"); - if (all_modules) { - warnings_module = PyDict_GetItemString(all_modules, "warnings"); - /* We keep a ref in the global */ - Py_XINCREF(warnings_module); - } - PyErr_Restore(typ, val, tb); - return warnings_module; -} - -static int initialized = 0; - -/* API to access the initialized flag -- useful for esoteric use */ - -int -Py_IsInitialized(void) -{ - return initialized; -} - -/* Global initializations. Can be undone by Py_Finalize(). Don't - call this twice without an intervening Py_Finalize() call. When - initializations fail, a fatal error is issued and the function does - not return. On return, the first thread and interpreter state have - been created. - - Locking: you must hold the interpreter lock while calling this. - (If the lock has not yet been initialized, that's equivalent to - having the lock, but you cannot use multiple threads.) - -*/ - -static int -add_flag(int flag, const char *envs) -{ - int env = atoi(envs); - if (flag < env) - flag = env; - if (flag < 1) - flag = 1; - return flag; -} - -void -Py_InitializeEx(int install_sigs) -{ - PyInterpreterState *interp; - PyThreadState *tstate; - PyObject *bimod, *sysmod; - char *p; -#if defined(Py_USING_UNICODE) && defined(HAVE_LANGINFO_H) && defined(CODESET) - char *codeset; - char *saved_locale; - PyObject *sys_stream, *sys_isatty; -#endif - extern void _Py_ReadyTypes(void); - - if (initialized) - return; - initialized = 1; - - if ((p = Py_GETENV("PYTHONDEBUG")) && *p != '\0') - Py_DebugFlag = add_flag(Py_DebugFlag, p); - if ((p = Py_GETENV("PYTHONVERBOSE")) && *p != '\0') - Py_VerboseFlag = add_flag(Py_VerboseFlag, p); - if ((p = Py_GETENV("PYTHONOPTIMIZE")) && *p != '\0') - Py_OptimizeFlag = add_flag(Py_OptimizeFlag, p); - - interp = PyInterpreterState_New(); - if (interp == NULL) - Py_FatalError("Py_Initialize: can't make first interpreter"); - - tstate = PyThreadState_New(interp); - if (tstate == NULL) - Py_FatalError("Py_Initialize: can't make first thread"); - (void) PyThreadState_Swap(tstate); - - _Py_ReadyTypes(); - - if (!_PyFrame_Init()) - Py_FatalError("Py_Initialize: can't init frames"); - - if (!_PyInt_Init()) - Py_FatalError("Py_Initialize: can't init ints"); - - _PyFloat_Init(); - - interp->modules = PyDict_New(); - if (interp->modules == NULL) - Py_FatalError("Py_Initialize: can't make modules dictionary"); - interp->modules_reloading = PyDict_New(); - if (interp->modules_reloading == NULL) - Py_FatalError("Py_Initialize: can't make modules_reloading dictionary"); - -#ifdef Py_USING_UNICODE - /* Init Unicode implementation; relies on the codec registry */ - _PyUnicode_Init(); -#endif - - bimod = _PyBuiltin_Init(); - if (bimod == NULL) - Py_FatalError("Py_Initialize: can't initialize __builtin__"); - interp->builtins = PyModule_GetDict(bimod); - if (interp->builtins == NULL) - Py_FatalError("Py_Initialize: can't initialize builtins dict"); - Py_INCREF(interp->builtins); - - sysmod = _PySys_Init(); - if (sysmod == NULL) - Py_FatalError("Py_Initialize: can't initialize sys"); - interp->sysdict = PyModule_GetDict(sysmod); - if (interp->sysdict == NULL) - Py_FatalError("Py_Initialize: can't initialize sys dict"); - Py_INCREF(interp->sysdict); - _PyImport_FixupExtension("sys", "sys"); - PySys_SetPath(Py_GetPath()); - PyDict_SetItemString(interp->sysdict, "modules", - interp->modules); - - _PyImport_Init(); - - /* initialize builtin exceptions */ - _PyExc_Init(); - _PyImport_FixupExtension("exceptions", "exceptions"); - - /* phase 2 of builtins */ - _PyImport_FixupExtension("__builtin__", "__builtin__"); - - _PyImportHooks_Init(); - - if (install_sigs) - initsigs(); /* Signal handling stuff, including initintr() */ - - initmain(); /* Module __main__ */ - if (!Py_NoSiteFlag) - initsite(); /* Module site */ - - /* auto-thread-state API, if available */ -#ifdef WITH_THREAD - _PyGILState_Init(interp, tstate); -#endif /* WITH_THREAD */ - - warnings_module = PyImport_ImportModule("warnings"); - if (!warnings_module) - PyErr_Clear(); - -#if defined(Py_USING_UNICODE) && defined(HAVE_LANGINFO_H) && defined(CODESET) - /* On Unix, set the file system encoding according to the - user's preference, if the CODESET names a well-known - Python codec, and Py_FileSystemDefaultEncoding isn't - initialized by other means. Also set the encoding of - stdin and stdout if these are terminals. */ - - saved_locale = strdup(setlocale(LC_CTYPE, NULL)); - setlocale(LC_CTYPE, ""); - codeset = nl_langinfo(CODESET); - if (codeset && *codeset) { - PyObject *enc = PyCodec_Encoder(codeset); - if (enc) { - codeset = strdup(codeset); - Py_DECREF(enc); - } else { - codeset = NULL; - PyErr_Clear(); - } - } else - codeset = NULL; - setlocale(LC_CTYPE, saved_locale); - free(saved_locale); - - if (codeset) { - sys_stream = PySys_GetObject("stdin"); - sys_isatty = PyObject_CallMethod(sys_stream, "isatty", ""); - if (!sys_isatty) - PyErr_Clear(); - if(sys_isatty && PyObject_IsTrue(sys_isatty) && - PyFile_Check(sys_stream)) { - if (!PyFile_SetEncoding(sys_stream, codeset)) - Py_FatalError("Cannot set codeset of stdin"); - } - Py_XDECREF(sys_isatty); - - sys_stream = PySys_GetObject("stdout"); - sys_isatty = PyObject_CallMethod(sys_stream, "isatty", ""); - if (!sys_isatty) - PyErr_Clear(); - if(sys_isatty && PyObject_IsTrue(sys_isatty) && - PyFile_Check(sys_stream)) { - if (!PyFile_SetEncoding(sys_stream, codeset)) - Py_FatalError("Cannot set codeset of stdout"); - } - Py_XDECREF(sys_isatty); - - sys_stream = PySys_GetObject("stderr"); - sys_isatty = PyObject_CallMethod(sys_stream, "isatty", ""); - if (!sys_isatty) - PyErr_Clear(); - if(sys_isatty && PyObject_IsTrue(sys_isatty) && - PyFile_Check(sys_stream)) { - if (!PyFile_SetEncoding(sys_stream, codeset)) - Py_FatalError("Cannot set codeset of stderr"); - } - Py_XDECREF(sys_isatty); - - if (!Py_FileSystemDefaultEncoding) - Py_FileSystemDefaultEncoding = codeset; - else - free(codeset); - } -#endif -} - -void -Py_Initialize(void) -{ - Py_InitializeEx(1); -} - - -#ifdef COUNT_ALLOCS -extern void dump_counts(FILE*); -#endif - -/* Undo the effect of Py_Initialize(). - - Beware: if multiple interpreter and/or thread states exist, these - are not wiped out; only the current thread and interpreter state - are deleted. But since everything else is deleted, those other - interpreter and thread states should no longer be used. - - (XXX We should do better, e.g. wipe out all interpreters and - threads.) - - Locking: as above. - -*/ - -void -Py_Finalize(void) -{ - PyInterpreterState *interp; - PyThreadState *tstate; - - if (!initialized) - return; - - /* The interpreter is still entirely intact at this point, and the - * exit funcs may be relying on that. In particular, if some thread - * or exit func is still waiting to do an import, the import machinery - * expects Py_IsInitialized() to return true. So don't say the - * interpreter is uninitialized until after the exit funcs have run. - * Note that Threading.py uses an exit func to do a join on all the - * threads created thru it, so this also protects pending imports in - * the threads created via Threading. - */ - call_sys_exitfunc(); - initialized = 0; - - /* Get current thread state and interpreter pointer */ - tstate = PyThreadState_GET(); - interp = tstate->interp; - - /* Disable signal handling */ - PyOS_FiniInterrupts(); - - /* drop module references we saved */ - Py_XDECREF(warnings_module); - warnings_module = NULL; - - /* Collect garbage. This may call finalizers; it's nice to call these - * before all modules are destroyed. - * XXX If a __del__ or weakref callback is triggered here, and tries to - * XXX import a module, bad things can happen, because Python no - * XXX longer believes it's initialized. - * XXX Fatal Python error: Interpreter not initialized (version mismatch?) - * XXX is easy to provoke that way. I've also seen, e.g., - * XXX Exception exceptions.ImportError: 'No module named sha' - * XXX in <function callback at 0x008F5718> ignored - * XXX but I'm unclear on exactly how that one happens. In any case, - * XXX I haven't seen a real-life report of either of these. - */ - PyGC_Collect(); -#ifdef COUNT_ALLOCS - /* With COUNT_ALLOCS, it helps to run GC multiple times: - each collection might release some types from the type - list, so they become garbage. */ - while (PyGC_Collect() > 0) - /* nothing */; -#endif - - /* Destroy all modules */ - PyImport_Cleanup(); - - /* Collect final garbage. This disposes of cycles created by - * new-style class definitions, for example. - * XXX This is disabled because it caused too many problems. If - * XXX a __del__ or weakref callback triggers here, Python code has - * XXX a hard time running, because even the sys module has been - * XXX cleared out (sys.stdout is gone, sys.excepthook is gone, etc). - * XXX One symptom is a sequence of information-free messages - * XXX coming from threads (if a __del__ or callback is invoked, - * XXX other threads can execute too, and any exception they encounter - * XXX triggers a comedy of errors as subsystem after subsystem - * XXX fails to find what it *expects* to find in sys to help report - * XXX the exception and consequent unexpected failures). I've also - * XXX seen segfaults then, after adding print statements to the - * XXX Python code getting called. - */ -#if 0 - PyGC_Collect(); -#endif - - /* Destroy the database used by _PyImport_{Fixup,Find}Extension */ - _PyImport_Fini(); - - /* Debugging stuff */ -#ifdef COUNT_ALLOCS - dump_counts(stdout); -#endif - - PRINT_TOTAL_REFS(); - -#ifdef Py_TRACE_REFS - /* Display all objects still alive -- this can invoke arbitrary - * __repr__ overrides, so requires a mostly-intact interpreter. - * Alas, a lot of stuff may still be alive now that will be cleaned - * up later. - */ - if (Py_GETENV("PYTHONDUMPREFS")) - _Py_PrintReferences(stderr); -#endif /* Py_TRACE_REFS */ - - /* Cleanup auto-thread-state */ -#ifdef WITH_THREAD - _PyGILState_Fini(); -#endif /* WITH_THREAD */ - - /* Clear interpreter state */ - PyInterpreterState_Clear(interp); - - /* Now we decref the exception classes. After this point nothing - can raise an exception. That's okay, because each Fini() method - below has been checked to make sure no exceptions are ever - raised. - */ - - _PyExc_Fini(); - - /* Delete current thread */ - PyThreadState_Swap(NULL); - PyInterpreterState_Delete(interp); - - /* Sundry finalizers */ - PyMethod_Fini(); - PyFrame_Fini(); - PyCFunction_Fini(); - PyTuple_Fini(); - PyList_Fini(); - PySet_Fini(); - PyString_Fini(); - PyInt_Fini(); - PyFloat_Fini(); - -#ifdef Py_USING_UNICODE - /* Cleanup Unicode implementation */ - _PyUnicode_Fini(); -#endif - - /* XXX Still allocated: - - various static ad-hoc pointers to interned strings - - int and float free list blocks - - whatever various modules and libraries allocate - */ - - PyGrammar_RemoveAccelerators(&_PyParser_Grammar); - -#ifdef Py_TRACE_REFS - /* Display addresses (& refcnts) of all objects still alive. - * An address can be used to find the repr of the object, printed - * above by _Py_PrintReferences. - */ - if (Py_GETENV("PYTHONDUMPREFS")) - _Py_PrintReferenceAddresses(stderr); -#endif /* Py_TRACE_REFS */ -#ifdef PYMALLOC_DEBUG - if (Py_GETENV("PYTHONMALLOCSTATS")) - _PyObject_DebugMallocStats(); -#endif - - call_ll_exitfuncs(); -} - -/* Create and initialize a new interpreter and thread, and return the - new thread. This requires that Py_Initialize() has been called - first. - - Unsuccessful initialization yields a NULL pointer. Note that *no* - exception information is available even in this case -- the - exception information is held in the thread, and there is no - thread. - - Locking: as above. - -*/ - -PyThreadState * -Py_NewInterpreter(void) -{ - PyInterpreterState *interp; - PyThreadState *tstate, *save_tstate; - PyObject *bimod, *sysmod; - - if (!initialized) - Py_FatalError("Py_NewInterpreter: call Py_Initialize first"); - - interp = PyInterpreterState_New(); - if (interp == NULL) - return NULL; - - tstate = PyThreadState_New(interp); - if (tstate == NULL) { - PyInterpreterState_Delete(interp); - return NULL; - } - - save_tstate = PyThreadState_Swap(tstate); - - /* XXX The following is lax in error checking */ - - interp->modules = PyDict_New(); - interp->modules_reloading = PyDict_New(); - - bimod = _PyImport_FindExtension("__builtin__", "__builtin__"); - if (bimod != NULL) { - interp->builtins = PyModule_GetDict(bimod); - if (interp->builtins == NULL) - goto handle_error; - Py_INCREF(interp->builtins); - } - sysmod = _PyImport_FindExtension("sys", "sys"); - if (bimod != NULL && sysmod != NULL) { - interp->sysdict = PyModule_GetDict(sysmod); - if (interp->sysdict == NULL) - goto handle_error; - Py_INCREF(interp->sysdict); - PySys_SetPath(Py_GetPath()); - PyDict_SetItemString(interp->sysdict, "modules", - interp->modules); - _PyImportHooks_Init(); - initmain(); - if (!Py_NoSiteFlag) - initsite(); - } - - if (!PyErr_Occurred()) - return tstate; - -handle_error: - /* Oops, it didn't work. Undo it all. */ - - PyErr_Print(); - PyThreadState_Clear(tstate); - PyThreadState_Swap(save_tstate); - PyThreadState_Delete(tstate); - PyInterpreterState_Delete(interp); - - return NULL; -} - -/* Delete an interpreter and its last thread. This requires that the - given thread state is current, that the thread has no remaining - frames, and that it is its interpreter's only remaining thread. - It is a fatal error to violate these constraints. - - (Py_Finalize() doesn't have these constraints -- it zaps - everything, regardless.) - - Locking: as above. - -*/ - -void -Py_EndInterpreter(PyThreadState *tstate) -{ - PyInterpreterState *interp = tstate->interp; - - if (tstate != PyThreadState_GET()) - Py_FatalError("Py_EndInterpreter: thread is not current"); - if (tstate->frame != NULL) - Py_FatalError("Py_EndInterpreter: thread still has a frame"); - if (tstate != interp->tstate_head || tstate->next != NULL) - Py_FatalError("Py_EndInterpreter: not the last thread"); - - PyImport_Cleanup(); - PyInterpreterState_Clear(interp); - PyThreadState_Swap(NULL); - PyInterpreterState_Delete(interp); -} - -static char *progname = "python"; - -void -Py_SetProgramName(char *pn) -{ - if (pn && *pn) - progname = pn; -} - -char * -Py_GetProgramName(void) -{ - return progname; -} - -static char *default_home = NULL; - -void -Py_SetPythonHome(char *home) -{ - default_home = home; -} - -char * -Py_GetPythonHome(void) -{ - char *home = default_home; - if (home == NULL && !Py_IgnoreEnvironmentFlag) - home = Py_GETENV("PYTHONHOME"); - return home; -} - -/* Create __main__ module */ - -static void -initmain(void) -{ - PyObject *m, *d; - m = PyImport_AddModule("__main__"); - if (m == NULL) - Py_FatalError("can't create __main__ module"); - d = PyModule_GetDict(m); - if (PyDict_GetItemString(d, "__builtins__") == NULL) { - PyObject *bimod = PyImport_ImportModule("__builtin__"); - if (bimod == NULL || - PyDict_SetItemString(d, "__builtins__", bimod) != 0) - Py_FatalError("can't add __builtins__ to __main__"); - Py_DECREF(bimod); - } -} - -/* Import the site module (not into __main__ though) */ - -static void -initsite(void) -{ - PyObject *m, *f; - m = PyImport_ImportModule("site"); - if (m == NULL) { - f = PySys_GetObject("stderr"); - if (Py_VerboseFlag) { - PyFile_WriteString( - "'import site' failed; traceback:\n", f); - PyErr_Print(); - } - else { - PyFile_WriteString( - "'import site' failed; use -v for traceback\n", f); - PyErr_Clear(); - } - } - else { - Py_DECREF(m); - } -} - -/* Parse input from a file and execute it */ - -int -PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit, - PyCompilerFlags *flags) -{ - if (filename == NULL) - filename = "???"; - if (Py_FdIsInteractive(fp, filename)) { - int err = PyRun_InteractiveLoopFlags(fp, filename, flags); - if (closeit) - fclose(fp); - return err; - } - else - return PyRun_SimpleFileExFlags(fp, filename, closeit, flags); -} - -int -PyRun_InteractiveLoopFlags(FILE *fp, const char *filename, PyCompilerFlags *flags) -{ - PyObject *v; - int ret; - PyCompilerFlags local_flags; - - if (flags == NULL) { - flags = &local_flags; - local_flags.cf_flags = 0; - } - v = PySys_GetObject("ps1"); - if (v == NULL) { - PySys_SetObject("ps1", v = PyString_FromString(">>> ")); - Py_XDECREF(v); - } - v = PySys_GetObject("ps2"); - if (v == NULL) { - PySys_SetObject("ps2", v = PyString_FromString("... ")); - Py_XDECREF(v); - } - for (;;) { - ret = PyRun_InteractiveOneFlags(fp, filename, flags); - PRINT_TOTAL_REFS(); - if (ret == E_EOF) - return 0; - /* - if (ret == E_NOMEM) - return -1; - */ - } -} - -/* compute parser flags based on compiler flags */ -#define PARSER_FLAGS(flags) \ - ((flags) ? ((((flags)->cf_flags & PyCF_DONT_IMPLY_DEDENT) ? \ - PyPARSE_DONT_IMPLY_DEDENT : 0) \ - | ((flags)->cf_flags & CO_FUTURE_WITH_STATEMENT ? \ - PyPARSE_WITH_IS_KEYWORD : 0)) : 0) - -int -PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags) -{ - PyObject *m, *d, *v, *w; - mod_ty mod; - PyArena *arena; - char *ps1 = "", *ps2 = ""; - int errcode = 0; - - v = PySys_GetObject("ps1"); - if (v != NULL) { - v = PyObject_Str(v); - if (v == NULL) - PyErr_Clear(); - else if (PyString_Check(v)) - ps1 = PyString_AsString(v); - } - w = PySys_GetObject("ps2"); - if (w != NULL) { - w = PyObject_Str(w); - if (w == NULL) - PyErr_Clear(); - else if (PyString_Check(w)) - ps2 = PyString_AsString(w); - } - arena = PyArena_New(); - if (arena == NULL) { - Py_XDECREF(v); - Py_XDECREF(w); - return -1; - } - mod = PyParser_ASTFromFile(fp, filename, - Py_single_input, ps1, ps2, - flags, &errcode, arena); - Py_XDECREF(v); - Py_XDECREF(w); - if (mod == NULL) { - PyArena_Free(arena); - if (errcode == E_EOF) { - PyErr_Clear(); - return E_EOF; - } - PyErr_Print(); - return -1; - } - m = PyImport_AddModule("__main__"); - if (m == NULL) { - PyArena_Free(arena); - return -1; - } - d = PyModule_GetDict(m); - v = run_mod(mod, filename, d, d, flags, arena); - PyArena_Free(arena); - if (v == NULL) { - PyErr_Print(); - return -1; - } - Py_DECREF(v); - if (Py_FlushLine()) - PyErr_Clear(); - return 0; -} - -/* Check whether a file maybe a pyc file: Look at the extension, - the file type, and, if we may close it, at the first few bytes. */ - -static int -maybe_pyc_file(FILE *fp, const char* filename, const char* ext, int closeit) -{ - if (strcmp(ext, ".pyc") == 0 || strcmp(ext, ".pyo") == 0) - return 1; - - /* Only look into the file if we are allowed to close it, since - it then should also be seekable. */ - if (closeit) { - /* Read only two bytes of the magic. If the file was opened in - text mode, the bytes 3 and 4 of the magic (\r\n) might not - be read as they are on disk. */ - unsigned int halfmagic = PyImport_GetMagicNumber() & 0xFFFF; - unsigned char buf[2]; - /* Mess: In case of -x, the stream is NOT at its start now, - and ungetc() was used to push back the first newline, - which makes the current stream position formally undefined, - and a x-platform nightmare. - Unfortunately, we have no direct way to know whether -x - was specified. So we use a terrible hack: if the current - stream position is not 0, we assume -x was specified, and - give up. Bug 132850 on SourceForge spells out the - hopelessness of trying anything else (fseek and ftell - don't work predictably x-platform for text-mode files). - */ - int ispyc = 0; - if (ftell(fp) == 0) { - if (fread(buf, 1, 2, fp) == 2 && - ((unsigned int)buf[1]<<8 | buf[0]) == halfmagic) - ispyc = 1; - rewind(fp); - } - return ispyc; - } - return 0; -} - -int -PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, - PyCompilerFlags *flags) -{ - PyObject *m, *d, *v; - const char *ext; - - m = PyImport_AddModule("__main__"); - if (m == NULL) - return -1; - d = PyModule_GetDict(m); - if (PyDict_GetItemString(d, "__file__") == NULL) { - PyObject *f = PyString_FromString(filename); - if (f == NULL) - return -1; - if (PyDict_SetItemString(d, "__file__", f) < 0) { - Py_DECREF(f); - return -1; - } - Py_DECREF(f); - } - ext = filename + strlen(filename) - 4; - if (maybe_pyc_file(fp, filename, ext, closeit)) { - /* Try to run a pyc file. First, re-open in binary */ - if (closeit) - fclose(fp); - if ((fp = fopen(filename, "rb")) == NULL) { - fprintf(stderr, "python: Can't reopen .pyc file\n"); - return -1; - } - /* Turn on optimization if a .pyo file is given */ - if (strcmp(ext, ".pyo") == 0) - Py_OptimizeFlag = 1; - v = run_pyc_file(fp, filename, d, d, flags); - } else { - v = PyRun_FileExFlags(fp, filename, Py_file_input, d, d, - closeit, flags); - } - if (v == NULL) { - PyErr_Print(); - return -1; - } - Py_DECREF(v); - if (Py_FlushLine()) - PyErr_Clear(); - return 0; -} - -int -PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags) -{ - PyObject *m, *d, *v; - m = PyImport_AddModule("__main__"); - if (m == NULL) - return -1; - d = PyModule_GetDict(m); - v = PyRun_StringFlags(command, Py_file_input, d, d, flags); - if (v == NULL) { - PyErr_Print(); - return -1; - } - Py_DECREF(v); - if (Py_FlushLine()) - PyErr_Clear(); - return 0; -} - -static int -parse_syntax_error(PyObject *err, PyObject **message, const char **filename, - int *lineno, int *offset, const char **text) -{ - long hold; - PyObject *v; - - /* old style errors */ - if (PyTuple_Check(err)) - return PyArg_ParseTuple(err, "O(ziiz)", message, filename, - lineno, offset, text); - - /* new style errors. `err' is an instance */ - - if (! (v = PyObject_GetAttrString(err, "msg"))) - goto finally; - *message = v; - - if (!(v = PyObject_GetAttrString(err, "filename"))) - goto finally; - if (v == Py_None) - *filename = NULL; - else if (! (*filename = PyString_AsString(v))) - goto finally; - - Py_DECREF(v); - if (!(v = PyObject_GetAttrString(err, "lineno"))) - goto finally; - hold = PyInt_AsLong(v); - Py_DECREF(v); - v = NULL; - if (hold < 0 && PyErr_Occurred()) - goto finally; - *lineno = (int)hold; - - if (!(v = PyObject_GetAttrString(err, "offset"))) - goto finally; - if (v == Py_None) { - *offset = -1; - Py_DECREF(v); - v = NULL; - } else { - hold = PyInt_AsLong(v); - Py_DECREF(v); - v = NULL; - if (hold < 0 && PyErr_Occurred()) - goto finally; - *offset = (int)hold; - } - - if (!(v = PyObject_GetAttrString(err, "text"))) - goto finally; - if (v == Py_None) - *text = NULL; - else if (! (*text = PyString_AsString(v))) - goto finally; - Py_DECREF(v); - return 1; - -finally: - Py_XDECREF(v); - return 0; -} - -void -PyErr_Print(void) -{ - PyErr_PrintEx(1); -} - -static void -print_error_text(PyObject *f, int offset, const char *text) -{ - char *nl; - if (offset >= 0) { - if (offset > 0 && offset == (int)strlen(text)) - offset--; - for (;;) { - nl = strchr(text, '\n'); - if (nl == NULL || nl-text >= offset) - break; - offset -= (int)(nl+1-text); - text = nl+1; - } - while (*text == ' ' || *text == '\t') { - text++; - offset--; - } - } - PyFile_WriteString(" ", f); - PyFile_WriteString(text, f); - if (*text == '\0' || text[strlen(text)-1] != '\n') - PyFile_WriteString("\n", f); - if (offset == -1) - return; - PyFile_WriteString(" ", f); - offset--; - while (offset > 0) { - PyFile_WriteString(" ", f); - offset--; - } - PyFile_WriteString("^\n", f); -} - -static void -handle_system_exit(void) -{ - PyObject *exception, *value, *tb; - int exitcode = 0; - - PyErr_Fetch(&exception, &value, &tb); - if (Py_FlushLine()) - PyErr_Clear(); - fflush(stdout); - if (value == NULL || value == Py_None) - goto done; - if (PyExceptionInstance_Check(value)) { - /* The error code should be in the `code' attribute. */ - PyObject *code = PyObject_GetAttrString(value, "code"); - if (code) { - Py_DECREF(value); - value = code; - if (value == Py_None) - goto done; - } - /* If we failed to dig out the 'code' attribute, - just let the else clause below print the error. */ - } - if (PyInt_Check(value)) - exitcode = (int)PyInt_AsLong(value); - else { - PyObject_Print(value, stderr, Py_PRINT_RAW); - PySys_WriteStderr("\n"); - exitcode = 1; - } - done: - /* Restore and clear the exception info, in order to properly decref - * the exception, value, and traceback. If we just exit instead, - * these leak, which confuses PYTHONDUMPREFS output, and may prevent - * some finalizers from running. - */ - PyErr_Restore(exception, value, tb); - PyErr_Clear(); - Py_Exit(exitcode); - /* NOTREACHED */ -} - -void -PyErr_PrintEx(int set_sys_last_vars) -{ - PyObject *exception, *v, *tb, *hook; - - if (PyErr_ExceptionMatches(PyExc_SystemExit)) { - handle_system_exit(); - } - PyErr_Fetch(&exception, &v, &tb); - if (exception == NULL) - return; - PyErr_NormalizeException(&exception, &v, &tb); - if (exception == NULL) - return; - /* Now we know v != NULL too */ - if (set_sys_last_vars) { - PySys_SetObject("last_type", exception); - PySys_SetObject("last_value", v); - PySys_SetObject("last_traceback", tb); - } - hook = PySys_GetObject("excepthook"); - if (hook) { - PyObject *args = PyTuple_Pack(3, - exception, v, tb ? tb : Py_None); - PyObject *result = PyEval_CallObject(hook, args); - if (result == NULL) { - PyObject *exception2, *v2, *tb2; - if (PyErr_ExceptionMatches(PyExc_SystemExit)) { - handle_system_exit(); - } - PyErr_Fetch(&exception2, &v2, &tb2); - PyErr_NormalizeException(&exception2, &v2, &tb2); - /* It should not be possible for exception2 or v2 - to be NULL. However PyErr_Display() can't - tolerate NULLs, so just be safe. */ - if (exception2 == NULL) { - exception2 = Py_None; - Py_INCREF(exception2); - } - if (v2 == NULL) { - v2 = Py_None; - Py_INCREF(v2); - } - if (Py_FlushLine()) - PyErr_Clear(); - fflush(stdout); - PySys_WriteStderr("Error in sys.excepthook:\n"); - PyErr_Display(exception2, v2, tb2); - PySys_WriteStderr("\nOriginal exception was:\n"); - PyErr_Display(exception, v, tb); - Py_DECREF(exception2); - Py_DECREF(v2); - Py_XDECREF(tb2); - } - Py_XDECREF(result); - Py_XDECREF(args); - } else { - PySys_WriteStderr("sys.excepthook is missing\n"); - PyErr_Display(exception, v, tb); - } - Py_XDECREF(exception); - Py_XDECREF(v); - Py_XDECREF(tb); -} - -void -PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb) -{ - int err = 0; - PyObject *f = PySys_GetObject("stderr"); - Py_INCREF(value); - if (f == NULL) - fprintf(stderr, "lost sys.stderr\n"); - else { - if (Py_FlushLine()) - PyErr_Clear(); - fflush(stdout); - if (tb && tb != Py_None) - err = PyTraceBack_Print(tb, f); - if (err == 0 && - PyObject_HasAttrString(value, "print_file_and_line")) - { - PyObject *message; - const char *filename, *text; - int lineno, offset; - if (!parse_syntax_error(value, &message, &filename, - &lineno, &offset, &text)) - PyErr_Clear(); - else { - char buf[10]; - PyFile_WriteString(" File \"", f); - if (filename == NULL) - PyFile_WriteString("<string>", f); - else - PyFile_WriteString(filename, f); - PyFile_WriteString("\", line ", f); - PyOS_snprintf(buf, sizeof(buf), "%d", lineno); - PyFile_WriteString(buf, f); - PyFile_WriteString("\n", f); - if (text != NULL) - print_error_text(f, offset, text); - Py_DECREF(value); - value = message; - /* Can't be bothered to check all those - PyFile_WriteString() calls */ - if (PyErr_Occurred()) - err = -1; - } - } - if (err) { - /* Don't do anything else */ - } - else if (PyExceptionClass_Check(exception)) { - PyObject* moduleName; - char* className = PyExceptionClass_Name(exception); - if (className != NULL) { - char *dot = strrchr(className, '.'); - if (dot != NULL) - className = dot+1; - } - - moduleName = PyObject_GetAttrString(exception, "__module__"); - if (moduleName == NULL) - err = PyFile_WriteString("<unknown>", f); - else { - char* modstr = PyString_AsString(moduleName); - if (modstr && strcmp(modstr, "exceptions")) - { - err = PyFile_WriteString(modstr, f); - err += PyFile_WriteString(".", f); - } - Py_DECREF(moduleName); - } - if (err == 0) { - if (className == NULL) - err = PyFile_WriteString("<unknown>", f); - else - err = PyFile_WriteString(className, f); - } - } - else - err = PyFile_WriteObject(exception, f, Py_PRINT_RAW); - if (err == 0 && (value != Py_None)) { - PyObject *s = PyObject_Str(value); - /* only print colon if the str() of the - object is not the empty string - */ - if (s == NULL) - err = -1; - else if (!PyString_Check(s) || - PyString_GET_SIZE(s) != 0) - err = PyFile_WriteString(": ", f); - if (err == 0) - err = PyFile_WriteObject(s, f, Py_PRINT_RAW); - Py_XDECREF(s); - } - if (err == 0) - err = PyFile_WriteString("\n", f); - } - Py_DECREF(value); - /* If an error happened here, don't show it. - XXX This is wrong, but too many callers rely on this behavior. */ - if (err != 0) - PyErr_Clear(); -} - -PyObject * -PyRun_StringFlags(const char *str, int start, PyObject *globals, - PyObject *locals, PyCompilerFlags *flags) -{ - PyObject *ret = NULL; - mod_ty mod; - PyArena *arena = PyArena_New(); - if (arena == NULL) - return NULL; - - mod = PyParser_ASTFromString(str, "<string>", start, flags, arena); - if (mod != NULL) - ret = run_mod(mod, "<string>", globals, locals, flags, arena); - PyArena_Free(arena); - return ret; -} - -PyObject * -PyRun_FileExFlags(FILE *fp, const char *filename, int start, PyObject *globals, - PyObject *locals, int closeit, PyCompilerFlags *flags) -{ - PyObject *ret; - mod_ty mod; - PyArena *arena = PyArena_New(); - if (arena == NULL) - return NULL; - - mod = PyParser_ASTFromFile(fp, filename, start, 0, 0, - flags, NULL, arena); - if (closeit) - fclose(fp); - if (mod == NULL) { - PyArena_Free(arena); - return NULL; - } - ret = run_mod(mod, filename, globals, locals, flags, arena); - PyArena_Free(arena); - return ret; -} - -static PyObject * -run_mod(mod_ty mod, const char *filename, PyObject *globals, PyObject *locals, - PyCompilerFlags *flags, PyArena *arena) -{ - PyCodeObject *co; - PyObject *v; - co = PyAST_Compile(mod, filename, flags, arena); - if (co == NULL) - return NULL; - v = PyEval_EvalCode(co, globals, locals); - Py_DECREF(co); - return v; -} - -static PyObject * -run_pyc_file(FILE *fp, const char *filename, PyObject *globals, - PyObject *locals, PyCompilerFlags *flags) -{ - PyCodeObject *co; - PyObject *v; - long magic; - long PyImport_GetMagicNumber(void); - - magic = PyMarshal_ReadLongFromFile(fp); - if (magic != PyImport_GetMagicNumber()) { - PyErr_SetString(PyExc_RuntimeError, - "Bad magic number in .pyc file"); - return NULL; - } - (void) PyMarshal_ReadLongFromFile(fp); - v = PyMarshal_ReadLastObjectFromFile(fp); - fclose(fp); - if (v == NULL || !PyCode_Check(v)) { - Py_XDECREF(v); - PyErr_SetString(PyExc_RuntimeError, - "Bad code object in .pyc file"); - return NULL; - } - co = (PyCodeObject *)v; - v = PyEval_EvalCode(co, globals, locals); - if (v && flags) - flags->cf_flags |= (co->co_flags & PyCF_MASK); - Py_DECREF(co); - return v; -} - -PyObject * -Py_CompileStringFlags(const char *str, const char *filename, int start, - PyCompilerFlags *flags) -{ - PyCodeObject *co; - mod_ty mod; - PyArena *arena = PyArena_New(); - if (arena == NULL) - return NULL; - - mod = PyParser_ASTFromString(str, filename, start, flags, arena); - if (mod == NULL) { - PyArena_Free(arena); - return NULL; - } - if (flags && (flags->cf_flags & PyCF_ONLY_AST)) { - PyObject *result = PyAST_mod2obj(mod); - PyArena_Free(arena); - return result; - } - co = PyAST_Compile(mod, filename, flags, arena); - PyArena_Free(arena); - return (PyObject *)co; -} - -struct symtable * -Py_SymtableString(const char *str, const char *filename, int start) -{ - struct symtable *st; - mod_ty mod; - PyArena *arena = PyArena_New(); - if (arena == NULL) - return NULL; - - mod = PyParser_ASTFromString(str, filename, start, NULL, arena); - if (mod == NULL) { - PyArena_Free(arena); - return NULL; - } - st = PySymtable_Build(mod, filename, 0); - PyArena_Free(arena); - return st; -} - -/* Preferred access to parser is through AST. */ -mod_ty -PyParser_ASTFromString(const char *s, const char *filename, int start, - PyCompilerFlags *flags, PyArena *arena) -{ - mod_ty mod; - perrdetail err; - node *n = PyParser_ParseStringFlagsFilename(s, filename, - &_PyParser_Grammar, start, &err, - PARSER_FLAGS(flags)); - if (n) { - mod = PyAST_FromNode(n, flags, filename, arena); - PyNode_Free(n); - return mod; - } - else { - err_input(&err); - return NULL; - } -} - -mod_ty -PyParser_ASTFromFile(FILE *fp, const char *filename, int start, char *ps1, - char *ps2, PyCompilerFlags *flags, int *errcode, - PyArena *arena) -{ - mod_ty mod; - perrdetail err; - node *n = PyParser_ParseFileFlags(fp, filename, &_PyParser_Grammar, - start, ps1, ps2, &err, PARSER_FLAGS(flags)); - if (n) { - mod = PyAST_FromNode(n, flags, filename, arena); - PyNode_Free(n); - return mod; - } - else { - err_input(&err); - if (errcode) - *errcode = err.error; - return NULL; - } -} - -/* Simplified interface to parsefile -- return node or set exception */ - -node * -PyParser_SimpleParseFileFlags(FILE *fp, const char *filename, int start, int flags) -{ - perrdetail err; - node *n = PyParser_ParseFileFlags(fp, filename, &_PyParser_Grammar, - start, NULL, NULL, &err, flags); - if (n == NULL) - err_input(&err); - - return n; -} - -/* Simplified interface to parsestring -- return node or set exception */ - -node * -PyParser_SimpleParseStringFlags(const char *str, int start, int flags) -{ - perrdetail err; - node *n = PyParser_ParseStringFlags(str, &_PyParser_Grammar, - start, &err, flags); - if (n == NULL) - err_input(&err); - return n; -} - -node * -PyParser_SimpleParseStringFlagsFilename(const char *str, const char *filename, - int start, int flags) -{ - perrdetail err; - node *n = PyParser_ParseStringFlagsFilename(str, filename, - &_PyParser_Grammar, start, &err, flags); - if (n == NULL) - err_input(&err); - return n; -} - -node * -PyParser_SimpleParseStringFilename(const char *str, const char *filename, int start) -{ - return PyParser_SimpleParseStringFlagsFilename(str, filename, start, 0); -} - -/* May want to move a more generalized form of this to parsetok.c or - even parser modules. */ - -void -PyParser_SetError(perrdetail *err) -{ - err_input(err); -} - -/* Set the error appropriate to the given input error code (see errcode.h) */ - -static void -err_input(perrdetail *err) -{ - PyObject *v, *w, *errtype; - PyObject* u = NULL; - char *msg = NULL; - errtype = PyExc_SyntaxError; - switch (err->error) { - case E_SYNTAX: - errtype = PyExc_IndentationError; - if (err->expected == INDENT) - msg = "expected an indented block"; - else if (err->token == INDENT) - msg = "unexpected indent"; - else if (err->token == DEDENT) - msg = "unexpected unindent"; - else { - errtype = PyExc_SyntaxError; - msg = "invalid syntax"; - } - break; - case E_TOKEN: - msg = "invalid token"; - break; - case E_EOFS: - msg = "EOF while scanning triple-quoted string"; - break; - case E_EOLS: - msg = "EOL while scanning single-quoted string"; - break; - case E_INTR: - if (!PyErr_Occurred()) - PyErr_SetNone(PyExc_KeyboardInterrupt); - return; - case E_NOMEM: - PyErr_NoMemory(); - return; - case E_EOF: - msg = "unexpected EOF while parsing"; - break; - case E_TABSPACE: - errtype = PyExc_TabError; - msg = "inconsistent use of tabs and spaces in indentation"; - break; - case E_OVERFLOW: - msg = "expression too long"; - break; - case E_DEDENT: - errtype = PyExc_IndentationError; - msg = "unindent does not match any outer indentation level"; - break; - case E_TOODEEP: - errtype = PyExc_IndentationError; - msg = "too many levels of indentation"; - break; - case E_DECODE: { - PyObject *type, *value, *tb; - PyErr_Fetch(&type, &value, &tb); - if (value != NULL) { - u = PyObject_Str(value); - if (u != NULL) { - msg = PyString_AsString(u); - } - } - if (msg == NULL) - msg = "unknown decode error"; - Py_XDECREF(type); - Py_XDECREF(value); - Py_XDECREF(tb); - break; - } - case E_LINECONT: - msg = "unexpected character after line continuation character"; - break; - default: - fprintf(stderr, "error=%d\n", err->error); - msg = "unknown parsing error"; - break; - } - v = Py_BuildValue("(ziiz)", err->filename, - err->lineno, err->offset, err->text); - if (err->text != NULL) { - PyObject_FREE(err->text); - err->text = NULL; - } - w = NULL; - if (v != NULL) - w = Py_BuildValue("(sO)", msg, v); - Py_XDECREF(u); - Py_XDECREF(v); - PyErr_SetObject(errtype, w); - Py_XDECREF(w); -} - -/* Print fatal error message and abort */ - -void -Py_FatalError(const char *msg) -{ - fprintf(stderr, "Fatal Python error: %s\n", msg); -#ifdef MS_WINDOWS - OutputDebugString("Fatal Python error: "); - OutputDebugString(msg); - OutputDebugString("\n"); -#ifdef _DEBUG - DebugBreak(); -#endif -#endif /* MS_WINDOWS */ - abort(); -} - -/* Clean up and exit */ - -#ifdef WITH_THREAD -#include "pythread.h" -#endif - -#define NEXITFUNCS 32 -static void (*exitfuncs[NEXITFUNCS])(void); -static int nexitfuncs = 0; - -int Py_AtExit(void (*func)(void)) -{ - if (nexitfuncs >= NEXITFUNCS) - return -1; - exitfuncs[nexitfuncs++] = func; - return 0; -} - -static void -call_sys_exitfunc(void) -{ - PyObject *exitfunc = PySys_GetObject("exitfunc"); - - if (exitfunc) { - PyObject *res; - Py_INCREF(exitfunc); - PySys_SetObject("exitfunc", (PyObject *)NULL); - res = PyEval_CallObject(exitfunc, (PyObject *)NULL); - if (res == NULL) { - if (!PyErr_ExceptionMatches(PyExc_SystemExit)) { - PySys_WriteStderr("Error in sys.exitfunc:\n"); - } - PyErr_Print(); - } - Py_DECREF(exitfunc); - } - - if (Py_FlushLine()) - PyErr_Clear(); -} - -static void -call_ll_exitfuncs(void) -{ - while (nexitfuncs > 0) - (*exitfuncs[--nexitfuncs])(); - - fflush(stdout); - fflush(stderr); -} - -void -Py_Exit(int sts) -{ - Py_Finalize(); - - exit(sts); -} - -static void -initsigs(void) -{ -#ifdef SIGPIPE - PyOS_setsig(SIGPIPE, SIG_IGN); -#endif -#ifdef SIGXFZ - PyOS_setsig(SIGXFZ, SIG_IGN); -#endif -#ifdef SIGXFSZ - PyOS_setsig(SIGXFSZ, SIG_IGN); -#endif - PyOS_InitInterrupts(); /* May imply initsignal() */ -} - - -/* - * The file descriptor fd is considered ``interactive'' if either - * a) isatty(fd) is TRUE, or - * b) the -i flag was given, and the filename associated with - * the descriptor is NULL or "<stdin>" or "???". - */ -int -Py_FdIsInteractive(FILE *fp, const char *filename) -{ - if (isatty((int)fileno(fp))) - return 1; - if (!Py_InteractiveFlag) - return 0; - return (filename == NULL) || - (strcmp(filename, "<stdin>") == 0) || - (strcmp(filename, "???") == 0); -} - - -#if defined(USE_STACKCHECK) -#if defined(WIN32) && defined(_MSC_VER) - -/* Stack checking for Microsoft C */ - -#include <malloc.h> -#include <excpt.h> - -/* - * Return non-zero when we run out of memory on the stack; zero otherwise. - */ -int -PyOS_CheckStack(void) -{ - __try { - /* alloca throws a stack overflow exception if there's - not enough space left on the stack */ - alloca(PYOS_STACK_MARGIN * sizeof(void*)); - return 0; - } __except (EXCEPTION_EXECUTE_HANDLER) { - /* just ignore all errors */ - } - return 1; -} - -#endif /* WIN32 && _MSC_VER */ - -/* Alternate implementations can be added here... */ - -#endif /* USE_STACKCHECK */ - - -/* Wrappers around sigaction() or signal(). */ - -PyOS_sighandler_t -PyOS_getsig(int sig) -{ -#ifdef HAVE_SIGACTION - struct sigaction context; - if (sigaction(sig, NULL, &context) == -1) - return SIG_ERR; - return context.sa_handler; -#else - PyOS_sighandler_t handler; -/* Special signal handling for the secure CRT in Visual Studio 2005 */ -#if defined(_MSC_VER) && _MSC_VER >= 1400 - switch (sig) { - /* Only these signals are valid */ - case SIGINT: - case SIGILL: - case SIGFPE: - case SIGSEGV: - case SIGTERM: - case SIGBREAK: - case SIGABRT: - break; - /* Don't call signal() with other values or it will assert */ - default: - return SIG_ERR; - } -#endif /* _MSC_VER && _MSC_VER >= 1400 */ - handler = signal(sig, SIG_IGN); - if (handler != SIG_ERR) - signal(sig, handler); - return handler; -#endif -} - -PyOS_sighandler_t -PyOS_setsig(int sig, PyOS_sighandler_t handler) -{ -#ifdef HAVE_SIGACTION - struct sigaction context, ocontext; - context.sa_handler = handler; - sigemptyset(&context.sa_mask); - context.sa_flags = 0; - if (sigaction(sig, &context, &ocontext) == -1) - return SIG_ERR; - return ocontext.sa_handler; -#else - PyOS_sighandler_t oldhandler; - oldhandler = signal(sig, handler); -#ifdef HAVE_SIGINTERRUPT - siginterrupt(sig, 1); -#endif - return oldhandler; -#endif -} - -/* Deprecated C API functions still provided for binary compatiblity */ - -#undef PyParser_SimpleParseFile -PyAPI_FUNC(node *) -PyParser_SimpleParseFile(FILE *fp, const char *filename, int start) -{ - return PyParser_SimpleParseFileFlags(fp, filename, start, 0); -} - -#undef PyParser_SimpleParseString -PyAPI_FUNC(node *) -PyParser_SimpleParseString(const char *str, int start) -{ - return PyParser_SimpleParseStringFlags(str, start, 0); -} - -#undef PyRun_AnyFile -PyAPI_FUNC(int) -PyRun_AnyFile(FILE *fp, const char *name) -{ - return PyRun_AnyFileExFlags(fp, name, 0, NULL); -} - -#undef PyRun_AnyFileEx -PyAPI_FUNC(int) -PyRun_AnyFileEx(FILE *fp, const char *name, int closeit) -{ - return PyRun_AnyFileExFlags(fp, name, closeit, NULL); -} - -#undef PyRun_AnyFileFlags -PyAPI_FUNC(int) -PyRun_AnyFileFlags(FILE *fp, const char *name, PyCompilerFlags *flags) -{ - return PyRun_AnyFileExFlags(fp, name, 0, flags); -} - -#undef PyRun_File -PyAPI_FUNC(PyObject *) -PyRun_File(FILE *fp, const char *p, int s, PyObject *g, PyObject *l) -{ - return PyRun_FileExFlags(fp, p, s, g, l, 0, NULL); -} - -#undef PyRun_FileEx -PyAPI_FUNC(PyObject *) -PyRun_FileEx(FILE *fp, const char *p, int s, PyObject *g, PyObject *l, int c) -{ - return PyRun_FileExFlags(fp, p, s, g, l, c, NULL); -} - -#undef PyRun_FileFlags -PyAPI_FUNC(PyObject *) -PyRun_FileFlags(FILE *fp, const char *p, int s, PyObject *g, PyObject *l, - PyCompilerFlags *flags) -{ - return PyRun_FileExFlags(fp, p, s, g, l, 0, flags); -} - -#undef PyRun_SimpleFile -PyAPI_FUNC(int) -PyRun_SimpleFile(FILE *f, const char *p) -{ - return PyRun_SimpleFileExFlags(f, p, 0, NULL); -} - -#undef PyRun_SimpleFileEx -PyAPI_FUNC(int) -PyRun_SimpleFileEx(FILE *f, const char *p, int c) -{ - return PyRun_SimpleFileExFlags(f, p, c, NULL); -} - - -#undef PyRun_String -PyAPI_FUNC(PyObject *) -PyRun_String(const char *str, int s, PyObject *g, PyObject *l) -{ - return PyRun_StringFlags(str, s, g, l, NULL); -} - -#undef PyRun_SimpleString -PyAPI_FUNC(int) -PyRun_SimpleString(const char *s) -{ - return PyRun_SimpleStringFlags(s, NULL); -} - -#undef Py_CompileString -PyAPI_FUNC(PyObject *) -Py_CompileString(const char *str, const char *p, int s) -{ - return Py_CompileStringFlags(str, p, s, NULL); -} - -#undef PyRun_InteractiveOne -PyAPI_FUNC(int) -PyRun_InteractiveOne(FILE *f, const char *p) -{ - return PyRun_InteractiveOneFlags(f, p, NULL); -} - -#undef PyRun_InteractiveLoop -PyAPI_FUNC(int) -PyRun_InteractiveLoop(FILE *f, const char *p) -{ - return PyRun_InteractiveLoopFlags(f, p, NULL); -} - -#ifdef __cplusplus -} -#endif - diff --git a/sys/src/cmd/python/Python/sigcheck.c b/sys/src/cmd/python/Python/sigcheck.c deleted file mode 100644 index 022d0e8ac..000000000 --- a/sys/src/cmd/python/Python/sigcheck.c +++ /dev/null @@ -1,19 +0,0 @@ - -/* Sigcheck is similar to intrcheck() but sets an exception when an - interrupt occurs. It can't be in the intrcheck.c file since that - file (and the whole directory it is in) doesn't know about objects - or exceptions. It can't be in errors.c because it can be - overridden (at link time) by a more powerful version implemented in - signalmodule.c. */ - -#include "Python.h" - -/* ARGSUSED */ -int -PyErr_CheckSignals(void) -{ - if (!PyOS_InterruptOccurred()) - return 0; - PyErr_SetNone(PyExc_KeyboardInterrupt); - return -1; -} diff --git a/sys/src/cmd/python/Python/strdup.c b/sys/src/cmd/python/Python/strdup.c deleted file mode 100644 index 20187e0f0..000000000 --- a/sys/src/cmd/python/Python/strdup.c +++ /dev/null @@ -1,14 +0,0 @@ -/* strdup() replacement (from stdwin, if you must know) */ - -#include "pgenheaders.h" - -char * -strdup(const char *str) -{ - if (str != NULL) { - register char *copy = malloc(strlen(str) + 1); - if (copy != NULL) - return strcpy(copy, str); - } - return NULL; -} diff --git a/sys/src/cmd/python/Python/strerror.c b/sys/src/cmd/python/Python/strerror.c deleted file mode 100644 index 55f8342ec..000000000 --- a/sys/src/cmd/python/Python/strerror.c +++ /dev/null @@ -1,19 +0,0 @@ - -/* PD implementation of strerror() for systems that don't have it. - Author: Guido van Rossum, CWI Amsterdam, Oct. 1990, <guido@cwi.nl>. */ - -#include <stdio.h> -#include "Python.h" - -extern int sys_nerr; -extern char *sys_errlist[]; - -char * -strerror(int err) -{ - static char buf[20]; - if (err >= 0 && err < sys_nerr) - return sys_errlist[err]; - PyOS_snprintf(buf, sizeof(buf), "Unknown errno %d", err); - return buf; -} diff --git a/sys/src/cmd/python/Python/strtod.c b/sys/src/cmd/python/Python/strtod.c deleted file mode 100644 index 5c084a4de..000000000 --- a/sys/src/cmd/python/Python/strtod.c +++ /dev/null @@ -1,156 +0,0 @@ -#include "pyconfig.h" - -/* comp.sources.misc strtod(), as posted in comp.lang.tcl, - with bugfix for "123000.0" and acceptance of space after 'e' sign nuked. - - ************************************************************ - * YOU MUST EDIT THE MACHINE-DEPENDENT DEFINITIONS BELOW!!! * - ************************************************************ -*/ - -/* File : stdtod.c (Modified version of str2dbl.c) - Author : Richard A. O'Keefe @ Quintus Computer Systems, Inc. - Updated: Tuesday August 2nd, 1988 - Defines: double strtod (char *str, char**ptr) -*/ - -/* This is an implementation of the strtod() function described in the - System V manuals, with a different name to avoid linker problems. - All that str2dbl() does itself is check that the argument is well-formed - and is in range. It leaves the work of conversion to atof(), which is - assumed to exist and deliver correct results (if they can be represented). - - There are two reasons why this should be provided to the net: - (a) some UNIX systems do not yet have strtod(), or do not have it - available in the BSD "universe" (but they do have atof()). - (b) some of the UNIX systems that *do* have it get it wrong. - (some crash with large arguments, some assign the wrong *ptr value). - There is a reason why *we* are providing it: we need a correct version - of strtod(), and if we give this one away maybe someone will look for - mistakes in it and fix them for us (:-). -*/ - -/* The following constants are machine-specific. MD{MIN,MAX}EXPT are - integers and MD{MIN,MAX}FRAC are strings such that - 0.${MDMAXFRAC}e${MDMAXEXPT} is the largest representable double, - 0.${MDMINFRAC}e${MDMINEXPT} is the smallest representable +ve double - MD{MIN,MAX}FRAC must not have any trailing zeros. - The values here are for IEEE-754 64-bit floats. - It is not perfectly clear to me whether an IEEE infinity should be - returned for overflow, nor what a portable way of writing one is, - so HUGE is just 0.MAXFRAC*10**MAXEXPT (this seems still to be the - UNIX convention). - - I do know about <values.h>, but the whole point of this file is that - we can't always trust that stuff to be there or to be correct. -*/ -static int MDMINEXPT = {-323}; -static char MDMINFRAC[] = "494065645841246544"; -static double ZERO = 0.0; - -static int MDMAXEXPT = { 309}; -static char MDMAXFRAC[] = "17976931348623157"; -static double HUGE = 1.7976931348623157e308; - -extern double atof(const char *); /* Only called when result known to be ok */ - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -extern int errno; - -double strtod(char *str, char **ptr) -{ - int sign, scale, dotseen; - int esign, expt; - char *save; - register char *sp, *dp; - register int c; - char *buforg, *buflim; - char buffer[64]; /* 45-digit significant + */ - /* 13-digit exponent */ - sp = str; - while (*sp == ' ') sp++; - sign = 1; - if (*sp == '-') sign -= 2, sp++; - dotseen = 0, scale = 0; - dp = buffer; - *dp++ = '0'; *dp++ = '.'; - buforg = dp, buflim = buffer+48; - for (save = sp; c = *sp; sp++) - if (c == '.') { - if (dotseen) break; - dotseen++; - } else - if ((unsigned)(c-'0') > (unsigned)('9'-'0')) { - break; - } else - if (c == '0') { - if (dp != buforg) { - /* This is not the first digit, so we want to keep it */ - if (dp < buflim) *dp++ = c; - if (!dotseen) scale++; - } else { - /* No non-zero digits seen yet */ - /* If a . has been seen, scale must be adjusted */ - if (dotseen) scale--; - } - } else { - /* This is a nonzero digit, so we want to keep it */ - if (dp < buflim) *dp++ = c; - /* If it precedes a ., scale must be adjusted */ - if (!dotseen) scale++; - } - if (sp == save) { - if (ptr) *ptr = str; - errno = EDOM; /* what should this be? */ - return ZERO; - } - - while (dp > buforg && dp[-1] == '0') --dp; - if (dp == buforg) *dp++ = '0'; - *dp = '\0'; - /* Now the contents of buffer are - +--+--------+-+--------+ - |0.|fraction|\|leftover| - +--+--------+-+--------+ - ^dp points here - where fraction begins with 0 iff it is "0", and has at most - 45 digits in it, and leftover is at least 16 characters. - */ - save = sp, expt = 0, esign = 1; - do { - c = *sp++; - if (c != 'e' && c != 'E') break; - c = *sp++; - if (c == '-') esign -= 2, c = *sp++; else - if (c == '+' /* || c == ' ' */ ) c = *sp++; - if ((unsigned)(c-'0') > (unsigned)('9'-'0')) break; - while (c == '0') c = *sp++; - for (; (unsigned)(c-'0') <= (unsigned)('9'-'0'); c = *sp++) - expt = expt*10 + c-'0'; - if (esign < 0) expt = -expt; - save = sp-1; - } while (0); - if (ptr) *ptr = save; - expt += scale; - /* Now the number is sign*0.fraction*10**expt */ - errno = ERANGE; - if (expt > MDMAXEXPT) { - return HUGE*sign; - } else - if (expt == MDMAXEXPT) { - if (strcmp(buforg, MDMAXFRAC) > 0) return HUGE*sign; - } else - if (expt < MDMINEXPT) { - return ZERO*sign; - } else - if (expt == MDMINEXPT) { - if (strcmp(buforg, MDMINFRAC) < 0) return ZERO*sign; - } - /* We have now established that the number can be */ - /* represented without overflow or underflow */ - (void) sprintf(dp, "E%d", expt); - errno = 0; - return atof(buffer)*sign; -} diff --git a/sys/src/cmd/python/Python/structmember.c b/sys/src/cmd/python/Python/structmember.c deleted file mode 100644 index 03934c0c8..000000000 --- a/sys/src/cmd/python/Python/structmember.c +++ /dev/null @@ -1,312 +0,0 @@ - -/* Map C struct members to Python object attributes */ - -#include "Python.h" - -#include "structmember.h" - -static PyObject * -listmembers(struct memberlist *mlist) -{ - int i, n; - PyObject *v; - for (n = 0; mlist[n].name != NULL; n++) - ; - v = PyList_New(n); - if (v != NULL) { - for (i = 0; i < n; i++) - PyList_SetItem(v, i, - PyString_FromString(mlist[i].name)); - if (PyErr_Occurred()) { - Py_DECREF(v); - v = NULL; - } - else { - PyList_Sort(v); - } - } - return v; -} - -PyObject * -PyMember_Get(const char *addr, struct memberlist *mlist, const char *name) -{ - struct memberlist *l; - - if (strcmp(name, "__members__") == 0) - return listmembers(mlist); - for (l = mlist; l->name != NULL; l++) { - if (strcmp(l->name, name) == 0) { - PyMemberDef copy; - copy.name = l->name; - copy.type = l->type; - copy.offset = l->offset; - copy.flags = l->flags; - copy.doc = NULL; - return PyMember_GetOne(addr, ©); - } - } - PyErr_SetString(PyExc_AttributeError, name); - return NULL; -} - -PyObject * -PyMember_GetOne(const char *addr, PyMemberDef *l) -{ - PyObject *v; - if ((l->flags & READ_RESTRICTED) && - PyEval_GetRestricted()) { - PyErr_SetString(PyExc_RuntimeError, "restricted attribute"); - return NULL; - } - addr += l->offset; - switch (l->type) { - case T_BYTE: - v = PyInt_FromLong(*(char*)addr); - break; - case T_UBYTE: - v = PyLong_FromUnsignedLong(*(unsigned char*)addr); - break; - case T_SHORT: - v = PyInt_FromLong(*(short*)addr); - break; - case T_USHORT: - v = PyLong_FromUnsignedLong(*(unsigned short*)addr); - break; - case T_INT: - v = PyInt_FromLong(*(int*)addr); - break; - case T_UINT: - v = PyLong_FromUnsignedLong(*(unsigned int*)addr); - break; - case T_LONG: - v = PyInt_FromLong(*(long*)addr); - break; - case T_ULONG: - v = PyLong_FromUnsignedLong(*(unsigned long*)addr); - break; - case T_FLOAT: - v = PyFloat_FromDouble((double)*(float*)addr); - break; - case T_DOUBLE: - v = PyFloat_FromDouble(*(double*)addr); - break; - case T_STRING: - if (*(char**)addr == NULL) { - Py_INCREF(Py_None); - v = Py_None; - } - else - v = PyString_FromString(*(char**)addr); - break; - case T_STRING_INPLACE: - v = PyString_FromString((char*)addr); - break; - case T_CHAR: - v = PyString_FromStringAndSize((char*)addr, 1); - break; - case T_OBJECT: - v = *(PyObject **)addr; - if (v == NULL) - v = Py_None; - Py_INCREF(v); - break; - case T_OBJECT_EX: - v = *(PyObject **)addr; - if (v == NULL) - PyErr_SetString(PyExc_AttributeError, l->name); - Py_XINCREF(v); - break; -#ifdef HAVE_LONG_LONG - case T_LONGLONG: - v = PyLong_FromLongLong(*(PY_LONG_LONG *)addr); - break; - case T_ULONGLONG: - v = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)addr); - break; -#endif /* HAVE_LONG_LONG */ - default: - PyErr_SetString(PyExc_SystemError, "bad memberdescr type"); - v = NULL; - } - return v; -} - -int -PyMember_Set(char *addr, struct memberlist *mlist, const char *name, PyObject *v) -{ - struct memberlist *l; - - for (l = mlist; l->name != NULL; l++) { - if (strcmp(l->name, name) == 0) { - PyMemberDef copy; - copy.name = l->name; - copy.type = l->type; - copy.offset = l->offset; - copy.flags = l->flags; - copy.doc = NULL; - return PyMember_SetOne(addr, ©, v); - } - } - - PyErr_SetString(PyExc_AttributeError, name); - return -1; -} - -int -PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v) -{ - PyObject *oldv; - - if ((l->flags & READONLY) || l->type == T_STRING) - { - PyErr_SetString(PyExc_TypeError, "readonly attribute"); - return -1; - } - if ((l->flags & WRITE_RESTRICTED) && PyEval_GetRestricted()) { - PyErr_SetString(PyExc_RuntimeError, "restricted attribute"); - return -1; - } - if (v == NULL && l->type != T_OBJECT_EX && l->type != T_OBJECT) { - PyErr_SetString(PyExc_TypeError, - "can't delete numeric/char attribute"); - return -1; - } - addr += l->offset; - switch (l->type) { - case T_BYTE:{ - long long_val; - long_val = PyInt_AsLong(v); - if ((long_val == -1) && PyErr_Occurred()) - return -1; - *(char*)addr = (char)long_val; - break; - } - case T_UBYTE:{ - long long_val; - long_val = PyInt_AsLong(v); - if ((long_val == -1) && PyErr_Occurred()) - return -1; - *(unsigned char*)addr = (unsigned char)long_val; - break; - } - case T_SHORT:{ - long long_val; - long_val = PyInt_AsLong(v); - if ((long_val == -1) && PyErr_Occurred()) - return -1; - *(short*)addr = (short)long_val; - break; - } - case T_USHORT:{ - long long_val; - long_val = PyInt_AsLong(v); - if ((long_val == -1) && PyErr_Occurred()) - return -1; - *(unsigned short*)addr = (unsigned short)long_val; - break; - } - case T_INT:{ - long long_val; - long_val = PyInt_AsLong(v); - if ((long_val == -1) && PyErr_Occurred()) - return -1; - *(int *)addr = (int)long_val; - break; - } - case T_UINT:{ - unsigned long ulong_val; - ulong_val = PyLong_AsUnsignedLong(v); - if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) { - /* XXX: For compatibility, accept negative int values - as well. */ - PyErr_Clear(); - ulong_val = PyLong_AsLong(v); - if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) - return -1; - } - *(unsigned int *)addr = (unsigned int)ulong_val; - break; - } - case T_LONG:{ - *(long*)addr = PyLong_AsLong(v); - if ((*(long*)addr == -1) && PyErr_Occurred()) - return -1; - break; - } - case T_ULONG:{ - *(unsigned long*)addr = PyLong_AsUnsignedLong(v); - if ((*(unsigned long*)addr == (unsigned long)-1) - && PyErr_Occurred()) { - /* XXX: For compatibility, accept negative int values - as well. */ - PyErr_Clear(); - *(unsigned long*)addr = PyLong_AsLong(v); - if ((*(unsigned long*)addr == (unsigned int)-1) && PyErr_Occurred()) - return -1; - } - break; - } - case T_FLOAT:{ - double double_val; - double_val = PyFloat_AsDouble(v); - if ((double_val == -1) && PyErr_Occurred()) - return -1; - *(float*)addr = (float)double_val; - break; - } - case T_DOUBLE: - *(double*)addr = PyFloat_AsDouble(v); - if ((*(double*)addr == -1) && PyErr_Occurred()) - return -1; - break; - case T_OBJECT: - case T_OBJECT_EX: - Py_XINCREF(v); - oldv = *(PyObject **)addr; - *(PyObject **)addr = v; - Py_XDECREF(oldv); - break; - case T_CHAR: - if (PyString_Check(v) && PyString_Size(v) == 1) { - *(char*)addr = PyString_AsString(v)[0]; - } - else { - PyErr_BadArgument(); - return -1; - } - break; -#ifdef HAVE_LONG_LONG - case T_LONGLONG: - if (!PyLong_Check(v)) { - PyErr_BadArgument(); - return -1; - } else { - PY_LONG_LONG value; - *(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v); - if ((value == -1) && PyErr_Occurred()) { - return -1; - } - } - break; - case T_ULONGLONG: - if (!PyLong_Check(v)) { - PyErr_BadArgument(); - return -1; - } else { - unsigned PY_LONG_LONG value; - *(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v); - if ((value == (unsigned PY_LONG_LONG)-1) && - PyErr_Occurred()) { - return -1; - } - } - break; -#endif /* HAVE_LONG_LONG */ - default: - PyErr_Format(PyExc_SystemError, - "bad memberdescr type for %s", l->name); - return -1; - } - return 0; -} diff --git a/sys/src/cmd/python/Python/symtable.c b/sys/src/cmd/python/Python/symtable.c deleted file mode 100644 index 3e58b5034..000000000 --- a/sys/src/cmd/python/Python/symtable.c +++ /dev/null @@ -1,1425 +0,0 @@ -#include "Python.h" -#include "Python-ast.h" -#include "code.h" -#include "symtable.h" -#include "structmember.h" - -/* error strings used for warnings */ -#define GLOBAL_AFTER_ASSIGN \ -"name '%.400s' is assigned to before global declaration" - -#define GLOBAL_AFTER_USE \ -"name '%.400s' is used prior to global declaration" - -#define IMPORT_STAR_WARNING "import * only allowed at module level" - -#define RETURN_VAL_IN_GENERATOR \ - "'return' with argument inside generator" - -/* XXX(nnorwitz): change name since static? */ -static PySTEntryObject * -PySTEntry_New(struct symtable *st, identifier name, _Py_block_ty block, - void *key, int lineno) -{ - PySTEntryObject *ste = NULL; - PyObject *k; - - k = PyLong_FromVoidPtr(key); - if (k == NULL) - goto fail; - ste = (PySTEntryObject *)PyObject_New(PySTEntryObject, - &PySTEntry_Type); - ste->ste_table = st; - ste->ste_id = k; - ste->ste_tmpname = 0; - - ste->ste_name = name; - Py_INCREF(name); - - ste->ste_symbols = NULL; - ste->ste_varnames = NULL; - ste->ste_children = NULL; - - ste->ste_symbols = PyDict_New(); - if (ste->ste_symbols == NULL) - goto fail; - - ste->ste_varnames = PyList_New(0); - if (ste->ste_varnames == NULL) - goto fail; - - ste->ste_children = PyList_New(0); - if (ste->ste_children == NULL) - goto fail; - - ste->ste_type = block; - ste->ste_unoptimized = 0; - ste->ste_nested = 0; - ste->ste_free = 0; - ste->ste_varargs = 0; - ste->ste_varkeywords = 0; - ste->ste_opt_lineno = 0; - ste->ste_tmpname = 0; - ste->ste_lineno = lineno; - - if (st->st_cur != NULL && - (st->st_cur->ste_nested || - st->st_cur->ste_type == FunctionBlock)) - ste->ste_nested = 1; - ste->ste_child_free = 0; - ste->ste_generator = 0; - ste->ste_returns_value = 0; - - if (PyDict_SetItem(st->st_symbols, ste->ste_id, (PyObject *)ste) < 0) - goto fail; - - return ste; - fail: - Py_XDECREF(ste); - return NULL; -} - -static PyObject * -ste_repr(PySTEntryObject *ste) -{ - char buf[256]; - - PyOS_snprintf(buf, sizeof(buf), - "<symtable entry %.100s(%ld), line %d>", - PyString_AS_STRING(ste->ste_name), - PyInt_AS_LONG(ste->ste_id), ste->ste_lineno); - return PyString_FromString(buf); -} - -static void -ste_dealloc(PySTEntryObject *ste) -{ - ste->ste_table = NULL; - Py_XDECREF(ste->ste_id); - Py_XDECREF(ste->ste_name); - Py_XDECREF(ste->ste_symbols); - Py_XDECREF(ste->ste_varnames); - Py_XDECREF(ste->ste_children); - PyObject_Del(ste); -} - -#define OFF(x) offsetof(PySTEntryObject, x) - -static PyMemberDef ste_memberlist[] = { - {"id", T_OBJECT, OFF(ste_id), READONLY}, - {"name", T_OBJECT, OFF(ste_name), READONLY}, - {"symbols", T_OBJECT, OFF(ste_symbols), READONLY}, - {"varnames", T_OBJECT, OFF(ste_varnames), READONLY}, - {"children", T_OBJECT, OFF(ste_children), READONLY}, - {"type", T_INT, OFF(ste_type), READONLY}, - {"lineno", T_INT, OFF(ste_lineno), READONLY}, - {NULL} -}; - -PyTypeObject PySTEntry_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, - "symtable entry", - sizeof(PySTEntryObject), - 0, - (destructor)ste_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - (reprfunc)ste_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - ste_memberlist, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - -static int symtable_analyze(struct symtable *st); -static int symtable_warn(struct symtable *st, char *msg, int lineno); -static int symtable_enter_block(struct symtable *st, identifier name, - _Py_block_ty block, void *ast, int lineno); -static int symtable_exit_block(struct symtable *st, void *ast); -static int symtable_visit_stmt(struct symtable *st, stmt_ty s); -static int symtable_visit_expr(struct symtable *st, expr_ty s); -static int symtable_visit_genexp(struct symtable *st, expr_ty s); -static int symtable_visit_arguments(struct symtable *st, arguments_ty); -static int symtable_visit_excepthandler(struct symtable *st, excepthandler_ty); -static int symtable_visit_alias(struct symtable *st, alias_ty); -static int symtable_visit_comprehension(struct symtable *st, comprehension_ty); -static int symtable_visit_keyword(struct symtable *st, keyword_ty); -static int symtable_visit_slice(struct symtable *st, slice_ty); -static int symtable_visit_params(struct symtable *st, asdl_seq *args, int top); -static int symtable_visit_params_nested(struct symtable *st, asdl_seq *args); -static int symtable_implicit_arg(struct symtable *st, int pos); - - -static identifier top = NULL, lambda = NULL, genexpr = NULL; - -#define GET_IDENTIFIER(VAR) \ - ((VAR) ? (VAR) : ((VAR) = PyString_InternFromString(# VAR))) - -#define DUPLICATE_ARGUMENT \ -"duplicate argument '%s' in function definition" - -static struct symtable * -symtable_new(void) -{ - struct symtable *st; - - st = (struct symtable *)PyMem_Malloc(sizeof(struct symtable)); - if (st == NULL) - return NULL; - - st->st_filename = NULL; - st->st_symbols = NULL; - - if ((st->st_stack = PyList_New(0)) == NULL) - goto fail; - if ((st->st_symbols = PyDict_New()) == NULL) - goto fail; - st->st_cur = NULL; - st->st_tmpname = 0; - st->st_private = NULL; - return st; - fail: - PySymtable_Free(st); - return NULL; -} - -struct symtable * -PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future) -{ - struct symtable *st = symtable_new(); - asdl_seq *seq; - int i; - - if (st == NULL) - return st; - st->st_filename = filename; - st->st_future = future; - if (!symtable_enter_block(st, GET_IDENTIFIER(top), ModuleBlock, - (void *)mod, 0)) { - PySymtable_Free(st); - return NULL; - } - - st->st_top = st->st_cur; - st->st_cur->ste_unoptimized = OPT_TOPLEVEL; - /* Any other top-level initialization? */ - switch (mod->kind) { - case Module_kind: - seq = mod->v.Module.body; - for (i = 0; i < asdl_seq_LEN(seq); i++) - if (!symtable_visit_stmt(st, - (stmt_ty)asdl_seq_GET(seq, i))) - goto error; - break; - case Expression_kind: - if (!symtable_visit_expr(st, mod->v.Expression.body)) - goto error; - break; - case Interactive_kind: - seq = mod->v.Interactive.body; - for (i = 0; i < asdl_seq_LEN(seq); i++) - if (!symtable_visit_stmt(st, - (stmt_ty)asdl_seq_GET(seq, i))) - goto error; - break; - case Suite_kind: - PyErr_SetString(PyExc_RuntimeError, - "this compiler does not handle Suites"); - goto error; - } - if (!symtable_exit_block(st, (void *)mod)) { - PySymtable_Free(st); - return NULL; - } - if (symtable_analyze(st)) - return st; - PySymtable_Free(st); - return NULL; - error: - (void) symtable_exit_block(st, (void *)mod); - PySymtable_Free(st); - return NULL; -} - -void -PySymtable_Free(struct symtable *st) -{ - Py_XDECREF(st->st_symbols); - Py_XDECREF(st->st_stack); - PyMem_Free((void *)st); -} - -PySTEntryObject * -PySymtable_Lookup(struct symtable *st, void *key) -{ - PyObject *k, *v; - - k = PyLong_FromVoidPtr(key); - if (k == NULL) - return NULL; - v = PyDict_GetItem(st->st_symbols, k); - if (v) { - assert(PySTEntry_Check(v)); - Py_INCREF(v); - } - else { - PyErr_SetString(PyExc_KeyError, - "unknown symbol table entry"); - } - - Py_DECREF(k); - return (PySTEntryObject *)v; -} - -int -PyST_GetScope(PySTEntryObject *ste, PyObject *name) -{ - PyObject *v = PyDict_GetItem(ste->ste_symbols, name); - if (!v) - return 0; - assert(PyInt_Check(v)); - return (PyInt_AS_LONG(v) >> SCOPE_OFF) & SCOPE_MASK; -} - - -/* Analyze raw symbol information to determine scope of each name. - - The next several functions are helpers for PySymtable_Analyze(), - which determines whether a name is local, global, or free. In addition, - it determines which local variables are cell variables; they provide - bindings that are used for free variables in enclosed blocks. - - There are also two kinds of free variables, implicit and explicit. An - explicit global is declared with the global statement. An implicit - global is a free variable for which the compiler has found no binding - in an enclosing function scope. The implicit global is either a global - or a builtin. Python's module and class blocks use the xxx_NAME opcodes - to handle these names to implement slightly odd semantics. In such a - block, the name is treated as global until it is assigned to; then it - is treated as a local. - - The symbol table requires two passes to determine the scope of each name. - The first pass collects raw facts from the AST: the name is a parameter - here, the name is used by not defined here, etc. The second pass analyzes - these facts during a pass over the PySTEntryObjects created during pass 1. - - When a function is entered during the second pass, the parent passes - the set of all name bindings visible to its children. These bindings - are used to determine if the variable is free or an implicit global. - After doing the local analysis, it analyzes each of its child blocks - using an updated set of name bindings. - - The children update the free variable set. If a local variable is free - in a child, the variable is marked as a cell. The current function must - provide runtime storage for the variable that may outlive the function's - frame. Cell variables are removed from the free set before the analyze - function returns to its parent. - - The sets of bound and free variables are implemented as dictionaries - mapping strings to None. -*/ - -#define SET_SCOPE(DICT, NAME, I) { \ - PyObject *o = PyInt_FromLong(I); \ - if (!o) \ - return 0; \ - if (PyDict_SetItem((DICT), (NAME), o) < 0) { \ - Py_DECREF(o); \ - return 0; \ - } \ - Py_DECREF(o); \ -} - -/* Decide on scope of name, given flags. - - The dicts passed in as arguments are modified as necessary. - ste is passed so that flags can be updated. -*/ - -static int -analyze_name(PySTEntryObject *ste, PyObject *dict, PyObject *name, long flags, - PyObject *bound, PyObject *local, PyObject *free, - PyObject *global) -{ - if (flags & DEF_GLOBAL) { - if (flags & DEF_PARAM) { - PyErr_Format(PyExc_SyntaxError, - "name '%s' is local and global", - PyString_AS_STRING(name)); - return 0; - } - SET_SCOPE(dict, name, GLOBAL_EXPLICIT); - if (PyDict_SetItem(global, name, Py_None) < 0) - return 0; - if (bound && PyDict_GetItem(bound, name)) { - if (PyDict_DelItem(bound, name) < 0) - return 0; - } - return 1; - } - if (flags & DEF_BOUND) { - SET_SCOPE(dict, name, LOCAL); - if (PyDict_SetItem(local, name, Py_None) < 0) - return 0; - if (PyDict_GetItem(global, name)) { - if (PyDict_DelItem(global, name) < 0) - return 0; - } - return 1; - } - /* If an enclosing block has a binding for this name, it - is a free variable rather than a global variable. - Note that having a non-NULL bound implies that the block - is nested. - */ - if (bound && PyDict_GetItem(bound, name)) { - SET_SCOPE(dict, name, FREE); - ste->ste_free = 1; - if (PyDict_SetItem(free, name, Py_None) < 0) - return 0; - return 1; - } - /* If a parent has a global statement, then call it global - explicit? It could also be global implicit. - */ - else if (global && PyDict_GetItem(global, name)) { - SET_SCOPE(dict, name, GLOBAL_EXPLICIT); - return 1; - } - else { - if (ste->ste_nested) - ste->ste_free = 1; - SET_SCOPE(dict, name, GLOBAL_IMPLICIT); - return 1; - } - return 0; /* Can't get here */ -} - -#undef SET_SCOPE - -/* If a name is defined in free and also in locals, then this block - provides the binding for the free variable. The name should be - marked CELL in this block and removed from the free list. - - Note that the current block's free variables are included in free. - That's safe because no name can be free and local in the same scope. -*/ - -static int -analyze_cells(PyObject *scope, PyObject *free) -{ - PyObject *name, *v, *w; - int success = 0; - Py_ssize_t pos = 0; - - w = PyInt_FromLong(CELL); - if (!w) - return 0; - while (PyDict_Next(scope, &pos, &name, &v)) { - long flags; - assert(PyInt_Check(v)); - flags = PyInt_AS_LONG(v); - if (flags != LOCAL) - continue; - if (!PyDict_GetItem(free, name)) - continue; - /* Replace LOCAL with CELL for this name, and remove - from free. It is safe to replace the value of name - in the dict, because it will not cause a resize. - */ - if (PyDict_SetItem(scope, name, w) < 0) - goto error; - if (!PyDict_DelItem(free, name) < 0) - goto error; - } - success = 1; - error: - Py_DECREF(w); - return success; -} - -/* Check for illegal statements in unoptimized namespaces */ -static int -check_unoptimized(const PySTEntryObject* ste) { - char buf[300]; - const char* trailer; - - if (ste->ste_type != FunctionBlock || !ste->ste_unoptimized - || !(ste->ste_free || ste->ste_child_free)) - return 1; - - trailer = (ste->ste_child_free ? - "contains a nested function with free variables" : - "is a nested function"); - - switch (ste->ste_unoptimized) { - case OPT_TOPLEVEL: /* exec / import * at top-level is fine */ - case OPT_EXEC: /* qualified exec is fine */ - return 1; - case OPT_IMPORT_STAR: - PyOS_snprintf(buf, sizeof(buf), - "import * is not allowed in function '%.100s' " - "because it is %s", - PyString_AS_STRING(ste->ste_name), trailer); - break; - case OPT_BARE_EXEC: - PyOS_snprintf(buf, sizeof(buf), - "unqualified exec is not allowed in function " - "'%.100s' it %s", - PyString_AS_STRING(ste->ste_name), trailer); - break; - default: - PyOS_snprintf(buf, sizeof(buf), - "function '%.100s' uses import * and bare exec, " - "which are illegal because it %s", - PyString_AS_STRING(ste->ste_name), trailer); - break; - } - - PyErr_SetString(PyExc_SyntaxError, buf); - PyErr_SyntaxLocation(ste->ste_table->st_filename, - ste->ste_opt_lineno); - return 0; -} - -/* Enter the final scope information into the st_symbols dict. - * - * All arguments are dicts. Modifies symbols, others are read-only. -*/ -static int -update_symbols(PyObject *symbols, PyObject *scope, - PyObject *bound, PyObject *free, int classflag) -{ - PyObject *name, *v, *u, *w, *free_value = NULL; - Py_ssize_t pos = 0; - - while (PyDict_Next(symbols, &pos, &name, &v)) { - long i, flags; - assert(PyInt_Check(v)); - flags = PyInt_AS_LONG(v); - w = PyDict_GetItem(scope, name); - assert(w && PyInt_Check(w)); - i = PyInt_AS_LONG(w); - flags |= (i << SCOPE_OFF); - u = PyInt_FromLong(flags); - if (!u) - return 0; - if (PyDict_SetItem(symbols, name, u) < 0) { - Py_DECREF(u); - return 0; - } - Py_DECREF(u); - } - - free_value = PyInt_FromLong(FREE << SCOPE_OFF); - if (!free_value) - return 0; - - /* add a free variable when it's only use is for creating a closure */ - pos = 0; - while (PyDict_Next(free, &pos, &name, &v)) { - PyObject *o = PyDict_GetItem(symbols, name); - - if (o) { - /* It could be a free variable in a method of - the class that has the same name as a local - or global in the class scope. - */ - if (classflag && - PyInt_AS_LONG(o) & (DEF_BOUND | DEF_GLOBAL)) { - long i = PyInt_AS_LONG(o) | DEF_FREE_CLASS; - o = PyInt_FromLong(i); - if (!o) { - Py_DECREF(free_value); - return 0; - } - if (PyDict_SetItem(symbols, name, o) < 0) { - Py_DECREF(o); - Py_DECREF(free_value); - return 0; - } - Py_DECREF(o); - } - /* else it's not free, probably a cell */ - continue; - } - if (!PyDict_GetItem(bound, name)) - continue; /* it's a global */ - - if (PyDict_SetItem(symbols, name, free_value) < 0) { - Py_DECREF(free_value); - return 0; - } - } - Py_DECREF(free_value); - return 1; -} - -/* Make final symbol table decisions for block of ste. - Arguments: - ste -- current symtable entry (input/output) - bound -- set of variables bound in enclosing scopes (input) - free -- set of free variables in enclosed scopes (output) - globals -- set of declared global variables in enclosing scopes (input) -*/ - -static int -analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, - PyObject *global) -{ - PyObject *name, *v, *local = NULL, *scope = NULL, *newbound = NULL; - PyObject *newglobal = NULL, *newfree = NULL; - int i, success = 0; - Py_ssize_t pos = 0; - - local = PyDict_New(); - if (!local) - goto error; - scope = PyDict_New(); - if (!scope) - goto error; - newglobal = PyDict_New(); - if (!newglobal) - goto error; - newfree = PyDict_New(); - if (!newfree) - goto error; - newbound = PyDict_New(); - if (!newbound) - goto error; - - if (ste->ste_type == ClassBlock) { - /* make a copy of globals before calling analyze_name(), - because global statements in the class have no effect - on nested functions. - */ - if (PyDict_Update(newglobal, global) < 0) - goto error; - if (bound) - if (PyDict_Update(newbound, bound) < 0) - goto error; - } - - assert(PySTEntry_Check(ste)); - assert(PyDict_Check(ste->ste_symbols)); - while (PyDict_Next(ste->ste_symbols, &pos, &name, &v)) { - long flags = PyInt_AS_LONG(v); - if (!analyze_name(ste, scope, name, flags, bound, local, free, - global)) - goto error; - } - - if (ste->ste_type != ClassBlock) { - if (ste->ste_type == FunctionBlock) { - if (PyDict_Update(newbound, local) < 0) - goto error; - } - if (bound) { - if (PyDict_Update(newbound, bound) < 0) - goto error; - } - if (PyDict_Update(newglobal, global) < 0) - goto error; - } - - /* Recursively call analyze_block() on each child block */ - for (i = 0; i < PyList_GET_SIZE(ste->ste_children); ++i) { - PyObject *c = PyList_GET_ITEM(ste->ste_children, i); - PySTEntryObject* entry; - assert(c && PySTEntry_Check(c)); - entry = (PySTEntryObject*)c; - if (!analyze_block(entry, newbound, newfree, newglobal)) - goto error; - if (entry->ste_free || entry->ste_child_free) - ste->ste_child_free = 1; - } - - if (ste->ste_type == FunctionBlock && !analyze_cells(scope, newfree)) - goto error; - if (!update_symbols(ste->ste_symbols, scope, bound, newfree, - ste->ste_type == ClassBlock)) - goto error; - if (!check_unoptimized(ste)) - goto error; - - if (PyDict_Update(free, newfree) < 0) - goto error; - success = 1; - error: - Py_XDECREF(local); - Py_XDECREF(scope); - Py_XDECREF(newbound); - Py_XDECREF(newglobal); - Py_XDECREF(newfree); - if (!success) - assert(PyErr_Occurred()); - return success; -} - -static int -symtable_analyze(struct symtable *st) -{ - PyObject *free, *global; - int r; - - free = PyDict_New(); - if (!free) - return 0; - global = PyDict_New(); - if (!global) { - Py_DECREF(free); - return 0; - } - r = analyze_block(st->st_top, NULL, free, global); - Py_DECREF(free); - Py_DECREF(global); - return r; -} - - -static int -symtable_warn(struct symtable *st, char *msg, int lineno) -{ - if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, st->st_filename, - lineno, NULL, NULL) < 0) { - if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) { - PyErr_SetString(PyExc_SyntaxError, msg); - PyErr_SyntaxLocation(st->st_filename, - st->st_cur->ste_lineno); - } - return 0; - } - return 1; -} - -/* symtable_enter_block() gets a reference via PySTEntry_New(). - This reference is released when the block is exited, via the DECREF - in symtable_exit_block(). -*/ - -static int -symtable_exit_block(struct symtable *st, void *ast) -{ - Py_ssize_t end; - - Py_CLEAR(st->st_cur); - end = PyList_GET_SIZE(st->st_stack) - 1; - if (end >= 0) { - st->st_cur = (PySTEntryObject *)PyList_GET_ITEM(st->st_stack, - end); - if (st->st_cur == NULL) - return 0; - Py_INCREF(st->st_cur); - if (PySequence_DelItem(st->st_stack, end) < 0) - return 0; - } - return 1; -} - -static int -symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block, - void *ast, int lineno) -{ - PySTEntryObject *prev = NULL; - - if (st->st_cur) { - prev = st->st_cur; - if (PyList_Append(st->st_stack, (PyObject *)st->st_cur) < 0) { - return 0; - } - Py_DECREF(st->st_cur); - } - st->st_cur = PySTEntry_New(st, name, block, ast, lineno); - if (st->st_cur == NULL) - return 0; - if (name == GET_IDENTIFIER(top)) - st->st_global = st->st_cur->ste_symbols; - if (prev) { - if (PyList_Append(prev->ste_children, - (PyObject *)st->st_cur) < 0) { - return 0; - } - } - return 1; -} - -static long -symtable_lookup(struct symtable *st, PyObject *name) -{ - PyObject *o; - PyObject *mangled = _Py_Mangle(st->st_private, name); - if (!mangled) - return 0; - o = PyDict_GetItem(st->st_cur->ste_symbols, mangled); - Py_DECREF(mangled); - if (!o) - return 0; - return PyInt_AsLong(o); -} - -static int -symtable_add_def(struct symtable *st, PyObject *name, int flag) -{ - PyObject *o; - PyObject *dict; - long val; - PyObject *mangled = _Py_Mangle(st->st_private, name); - - if (!mangled) - return 0; - dict = st->st_cur->ste_symbols; - if ((o = PyDict_GetItem(dict, mangled))) { - val = PyInt_AS_LONG(o); - if ((flag & DEF_PARAM) && (val & DEF_PARAM)) { - /* Is it better to use 'mangled' or 'name' here? */ - PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT, - PyString_AsString(name)); - PyErr_SyntaxLocation(st->st_filename, - st->st_cur->ste_lineno); - goto error; - } - val |= flag; - } else - val = flag; - o = PyInt_FromLong(val); - if (o == NULL) - goto error; - if (PyDict_SetItem(dict, mangled, o) < 0) { - Py_DECREF(o); - goto error; - } - Py_DECREF(o); - - if (flag & DEF_PARAM) { - if (PyList_Append(st->st_cur->ste_varnames, mangled) < 0) - goto error; - } else if (flag & DEF_GLOBAL) { - /* XXX need to update DEF_GLOBAL for other flags too; - perhaps only DEF_FREE_GLOBAL */ - val = flag; - if ((o = PyDict_GetItem(st->st_global, mangled))) { - val |= PyInt_AS_LONG(o); - } - o = PyInt_FromLong(val); - if (o == NULL) - goto error; - if (PyDict_SetItem(st->st_global, mangled, o) < 0) { - Py_DECREF(o); - goto error; - } - Py_DECREF(o); - } - Py_DECREF(mangled); - return 1; - -error: - Py_DECREF(mangled); - return 0; -} - -/* VISIT, VISIT_SEQ and VIST_SEQ_TAIL take an ASDL type as their second argument. - They use the ASDL name to synthesize the name of the C type and the visit - function. - - VISIT_SEQ_TAIL permits the start of an ASDL sequence to be skipped, which is - useful if the first node in the sequence requires special treatment. -*/ - -#define VISIT(ST, TYPE, V) \ - if (!symtable_visit_ ## TYPE((ST), (V))) \ - return 0; - -#define VISIT_IN_BLOCK(ST, TYPE, V, S) \ - if (!symtable_visit_ ## TYPE((ST), (V))) { \ - symtable_exit_block((ST), (S)); \ - return 0; \ - } - -#define VISIT_SEQ(ST, TYPE, SEQ) { \ - int i; \ - asdl_seq *seq = (SEQ); /* avoid variable capture */ \ - for (i = 0; i < asdl_seq_LEN(seq); i++) { \ - TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ - if (!symtable_visit_ ## TYPE((ST), elt)) \ - return 0; \ - } \ -} - -#define VISIT_SEQ_IN_BLOCK(ST, TYPE, SEQ, S) { \ - int i; \ - asdl_seq *seq = (SEQ); /* avoid variable capture */ \ - for (i = 0; i < asdl_seq_LEN(seq); i++) { \ - TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ - if (!symtable_visit_ ## TYPE((ST), elt)) { \ - symtable_exit_block((ST), (S)); \ - return 0; \ - } \ - } \ -} - -#define VISIT_SEQ_TAIL(ST, TYPE, SEQ, START) { \ - int i; \ - asdl_seq *seq = (SEQ); /* avoid variable capture */ \ - for (i = (START); i < asdl_seq_LEN(seq); i++) { \ - TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ - if (!symtable_visit_ ## TYPE((ST), elt)) \ - return 0; \ - } \ -} - -#define VISIT_SEQ_TAIL_IN_BLOCK(ST, TYPE, SEQ, START, S) { \ - int i; \ - asdl_seq *seq = (SEQ); /* avoid variable capture */ \ - for (i = (START); i < asdl_seq_LEN(seq); i++) { \ - TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ - if (!symtable_visit_ ## TYPE((ST), elt)) { \ - symtable_exit_block((ST), (S)); \ - return 0; \ - } \ - } \ -} - -static int -symtable_new_tmpname(struct symtable *st) -{ - char tmpname[256]; - identifier tmp; - - PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", - ++st->st_cur->ste_tmpname); - tmp = PyString_InternFromString(tmpname); - if (!tmp) - return 0; - if (!symtable_add_def(st, tmp, DEF_LOCAL)) - return 0; - Py_DECREF(tmp); - return 1; -} - -static int -symtable_visit_stmt(struct symtable *st, stmt_ty s) -{ - switch (s->kind) { - case FunctionDef_kind: - if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL)) - return 0; - if (s->v.FunctionDef.args->defaults) - VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults); - if (s->v.FunctionDef.decorators) - VISIT_SEQ(st, expr, s->v.FunctionDef.decorators); - if (!symtable_enter_block(st, s->v.FunctionDef.name, - FunctionBlock, (void *)s, s->lineno)) - return 0; - VISIT_IN_BLOCK(st, arguments, s->v.FunctionDef.args, s); - VISIT_SEQ_IN_BLOCK(st, stmt, s->v.FunctionDef.body, s); - if (!symtable_exit_block(st, s)) - return 0; - break; - case ClassDef_kind: { - PyObject *tmp; - if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL)) - return 0; - VISIT_SEQ(st, expr, s->v.ClassDef.bases); - if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, - (void *)s, s->lineno)) - return 0; - tmp = st->st_private; - st->st_private = s->v.ClassDef.name; - VISIT_SEQ_IN_BLOCK(st, stmt, s->v.ClassDef.body, s); - st->st_private = tmp; - if (!symtable_exit_block(st, s)) - return 0; - break; - } - case Return_kind: - if (s->v.Return.value) { - VISIT(st, expr, s->v.Return.value); - st->st_cur->ste_returns_value = 1; - if (st->st_cur->ste_generator) { - PyErr_SetString(PyExc_SyntaxError, - RETURN_VAL_IN_GENERATOR); - PyErr_SyntaxLocation(st->st_filename, - s->lineno); - return 0; - } - } - break; - case Delete_kind: - VISIT_SEQ(st, expr, s->v.Delete.targets); - break; - case Assign_kind: - VISIT_SEQ(st, expr, s->v.Assign.targets); - VISIT(st, expr, s->v.Assign.value); - break; - case AugAssign_kind: - VISIT(st, expr, s->v.AugAssign.target); - VISIT(st, expr, s->v.AugAssign.value); - break; - case Print_kind: - if (s->v.Print.dest) - VISIT(st, expr, s->v.Print.dest); - VISIT_SEQ(st, expr, s->v.Print.values); - break; - case For_kind: - VISIT(st, expr, s->v.For.target); - VISIT(st, expr, s->v.For.iter); - VISIT_SEQ(st, stmt, s->v.For.body); - if (s->v.For.orelse) - VISIT_SEQ(st, stmt, s->v.For.orelse); - break; - case While_kind: - VISIT(st, expr, s->v.While.test); - VISIT_SEQ(st, stmt, s->v.While.body); - if (s->v.While.orelse) - VISIT_SEQ(st, stmt, s->v.While.orelse); - break; - case If_kind: - /* XXX if 0: and lookup_yield() hacks */ - VISIT(st, expr, s->v.If.test); - VISIT_SEQ(st, stmt, s->v.If.body); - if (s->v.If.orelse) - VISIT_SEQ(st, stmt, s->v.If.orelse); - break; - case Raise_kind: - if (s->v.Raise.type) { - VISIT(st, expr, s->v.Raise.type); - if (s->v.Raise.inst) { - VISIT(st, expr, s->v.Raise.inst); - if (s->v.Raise.tback) - VISIT(st, expr, s->v.Raise.tback); - } - } - break; - case TryExcept_kind: - VISIT_SEQ(st, stmt, s->v.TryExcept.body); - VISIT_SEQ(st, stmt, s->v.TryExcept.orelse); - VISIT_SEQ(st, excepthandler, s->v.TryExcept.handlers); - break; - case TryFinally_kind: - VISIT_SEQ(st, stmt, s->v.TryFinally.body); - VISIT_SEQ(st, stmt, s->v.TryFinally.finalbody); - break; - case Assert_kind: - VISIT(st, expr, s->v.Assert.test); - if (s->v.Assert.msg) - VISIT(st, expr, s->v.Assert.msg); - break; - case Import_kind: - VISIT_SEQ(st, alias, s->v.Import.names); - /* XXX Don't have the lineno available inside - visit_alias */ - if (st->st_cur->ste_unoptimized && !st->st_cur->ste_opt_lineno) - st->st_cur->ste_opt_lineno = s->lineno; - break; - case ImportFrom_kind: - VISIT_SEQ(st, alias, s->v.ImportFrom.names); - /* XXX Don't have the lineno available inside - visit_alias */ - if (st->st_cur->ste_unoptimized && !st->st_cur->ste_opt_lineno) - st->st_cur->ste_opt_lineno = s->lineno; - break; - case Exec_kind: - VISIT(st, expr, s->v.Exec.body); - if (!st->st_cur->ste_opt_lineno) - st->st_cur->ste_opt_lineno = s->lineno; - if (s->v.Exec.globals) { - st->st_cur->ste_unoptimized |= OPT_EXEC; - VISIT(st, expr, s->v.Exec.globals); - if (s->v.Exec.locals) - VISIT(st, expr, s->v.Exec.locals); - } else { - st->st_cur->ste_unoptimized |= OPT_BARE_EXEC; - } - break; - case Global_kind: { - int i; - asdl_seq *seq = s->v.Global.names; - for (i = 0; i < asdl_seq_LEN(seq); i++) { - identifier name = (identifier)asdl_seq_GET(seq, i); - char *c_name = PyString_AS_STRING(name); - long cur = symtable_lookup(st, name); - if (cur < 0) - return 0; - if (cur & (DEF_LOCAL | USE)) { - char buf[256]; - if (cur & DEF_LOCAL) - PyOS_snprintf(buf, sizeof(buf), - GLOBAL_AFTER_ASSIGN, - c_name); - else - PyOS_snprintf(buf, sizeof(buf), - GLOBAL_AFTER_USE, - c_name); - if (!symtable_warn(st, buf, s->lineno)) - return 0; - } - if (!symtable_add_def(st, name, DEF_GLOBAL)) - return 0; - } - break; - } - case Expr_kind: - VISIT(st, expr, s->v.Expr.value); - break; - case Pass_kind: - case Break_kind: - case Continue_kind: - /* nothing to do here */ - break; - case With_kind: - if (!symtable_new_tmpname(st)) - return 0; - VISIT(st, expr, s->v.With.context_expr); - if (s->v.With.optional_vars) { - if (!symtable_new_tmpname(st)) - return 0; - VISIT(st, expr, s->v.With.optional_vars); - } - VISIT_SEQ(st, stmt, s->v.With.body); - break; - } - return 1; -} - -static int -symtable_visit_expr(struct symtable *st, expr_ty e) -{ - switch (e->kind) { - case BoolOp_kind: - VISIT_SEQ(st, expr, e->v.BoolOp.values); - break; - case BinOp_kind: - VISIT(st, expr, e->v.BinOp.left); - VISIT(st, expr, e->v.BinOp.right); - break; - case UnaryOp_kind: - VISIT(st, expr, e->v.UnaryOp.operand); - break; - case Lambda_kind: { - if (!symtable_add_def(st, GET_IDENTIFIER(lambda), DEF_LOCAL)) - return 0; - if (e->v.Lambda.args->defaults) - VISIT_SEQ(st, expr, e->v.Lambda.args->defaults); - /* XXX how to get line numbers for expressions */ - if (!symtable_enter_block(st, GET_IDENTIFIER(lambda), - FunctionBlock, (void *)e, 0)) - return 0; - VISIT_IN_BLOCK(st, arguments, e->v.Lambda.args, (void*)e); - VISIT_IN_BLOCK(st, expr, e->v.Lambda.body, (void*)e); - if (!symtable_exit_block(st, (void *)e)) - return 0; - break; - } - case IfExp_kind: - VISIT(st, expr, e->v.IfExp.test); - VISIT(st, expr, e->v.IfExp.body); - VISIT(st, expr, e->v.IfExp.orelse); - break; - case Dict_kind: - VISIT_SEQ(st, expr, e->v.Dict.keys); - VISIT_SEQ(st, expr, e->v.Dict.values); - break; - case ListComp_kind: - if (!symtable_new_tmpname(st)) - return 0; - VISIT(st, expr, e->v.ListComp.elt); - VISIT_SEQ(st, comprehension, e->v.ListComp.generators); - break; - case GeneratorExp_kind: - if (!symtable_visit_genexp(st, e)) - return 0; - break; - case Yield_kind: - if (e->v.Yield.value) - VISIT(st, expr, e->v.Yield.value); - st->st_cur->ste_generator = 1; - if (st->st_cur->ste_returns_value) { - PyErr_SetString(PyExc_SyntaxError, - RETURN_VAL_IN_GENERATOR); - PyErr_SyntaxLocation(st->st_filename, - e->lineno); - return 0; - } - break; - case Compare_kind: - VISIT(st, expr, e->v.Compare.left); - VISIT_SEQ(st, expr, e->v.Compare.comparators); - break; - case Call_kind: - VISIT(st, expr, e->v.Call.func); - VISIT_SEQ(st, expr, e->v.Call.args); - VISIT_SEQ(st, keyword, e->v.Call.keywords); - if (e->v.Call.starargs) - VISIT(st, expr, e->v.Call.starargs); - if (e->v.Call.kwargs) - VISIT(st, expr, e->v.Call.kwargs); - break; - case Repr_kind: - VISIT(st, expr, e->v.Repr.value); - break; - case Num_kind: - case Str_kind: - /* Nothing to do here. */ - break; - /* The following exprs can be assignment targets. */ - case Attribute_kind: - VISIT(st, expr, e->v.Attribute.value); - break; - case Subscript_kind: - VISIT(st, expr, e->v.Subscript.value); - VISIT(st, slice, e->v.Subscript.slice); - break; - case Name_kind: - if (!symtable_add_def(st, e->v.Name.id, - e->v.Name.ctx == Load ? USE : DEF_LOCAL)) - return 0; - break; - /* child nodes of List and Tuple will have expr_context set */ - case List_kind: - VISIT_SEQ(st, expr, e->v.List.elts); - break; - case Tuple_kind: - VISIT_SEQ(st, expr, e->v.Tuple.elts); - break; - } - return 1; -} - -static int -symtable_implicit_arg(struct symtable *st, int pos) -{ - PyObject *id = PyString_FromFormat(".%d", pos); - if (id == NULL) - return 0; - if (!symtable_add_def(st, id, DEF_PARAM)) { - Py_DECREF(id); - return 0; - } - Py_DECREF(id); - return 1; -} - -static int -symtable_visit_params(struct symtable *st, asdl_seq *args, int toplevel) -{ - int i; - - /* go through all the toplevel arguments first */ - for (i = 0; i < asdl_seq_LEN(args); i++) { - expr_ty arg = (expr_ty)asdl_seq_GET(args, i); - if (arg->kind == Name_kind) { - assert(arg->v.Name.ctx == Param || - (arg->v.Name.ctx == Store && !toplevel)); - if (!symtable_add_def(st, arg->v.Name.id, DEF_PARAM)) - return 0; - } - else if (arg->kind == Tuple_kind) { - assert(arg->v.Tuple.ctx == Store); - if (toplevel) { - if (!symtable_implicit_arg(st, i)) - return 0; - } - } - else { - PyErr_SetString(PyExc_SyntaxError, - "invalid expression in parameter list"); - PyErr_SyntaxLocation(st->st_filename, - st->st_cur->ste_lineno); - return 0; - } - } - - if (!toplevel) { - if (!symtable_visit_params_nested(st, args)) - return 0; - } - - return 1; -} - -static int -symtable_visit_params_nested(struct symtable *st, asdl_seq *args) -{ - int i; - for (i = 0; i < asdl_seq_LEN(args); i++) { - expr_ty arg = (expr_ty)asdl_seq_GET(args, i); - if (arg->kind == Tuple_kind && - !symtable_visit_params(st, arg->v.Tuple.elts, 0)) - return 0; - } - - return 1; -} - -static int -symtable_visit_arguments(struct symtable *st, arguments_ty a) -{ - /* skip default arguments inside function block - XXX should ast be different? - */ - if (a->args && !symtable_visit_params(st, a->args, 1)) - return 0; - if (a->vararg) { - if (!symtable_add_def(st, a->vararg, DEF_PARAM)) - return 0; - st->st_cur->ste_varargs = 1; - } - if (a->kwarg) { - if (!symtable_add_def(st, a->kwarg, DEF_PARAM)) - return 0; - st->st_cur->ste_varkeywords = 1; - } - if (a->args && !symtable_visit_params_nested(st, a->args)) - return 0; - return 1; -} - - -static int -symtable_visit_excepthandler(struct symtable *st, excepthandler_ty eh) -{ - if (eh->type) - VISIT(st, expr, eh->type); - if (eh->name) - VISIT(st, expr, eh->name); - VISIT_SEQ(st, stmt, eh->body); - return 1; -} - - -static int -symtable_visit_alias(struct symtable *st, alias_ty a) -{ - /* Compute store_name, the name actually bound by the import - operation. It is diferent than a->name when a->name is a - dotted package name (e.g. spam.eggs) - */ - PyObject *store_name; - PyObject *name = (a->asname == NULL) ? a->name : a->asname; - const char *base = PyString_AS_STRING(name); - char *dot = strchr(base, '.'); - if (dot) { - store_name = PyString_FromStringAndSize(base, dot - base); - if (!store_name) - return 0; - } - else { - store_name = name; - Py_INCREF(store_name); - } - if (strcmp(PyString_AS_STRING(name), "*")) { - int r = symtable_add_def(st, store_name, DEF_IMPORT); - Py_DECREF(store_name); - return r; - } - else { - if (st->st_cur->ste_type != ModuleBlock) { - int lineno = st->st_cur->ste_lineno; - if (!symtable_warn(st, IMPORT_STAR_WARNING, lineno)) { - Py_DECREF(store_name); - return 0; - } - } - st->st_cur->ste_unoptimized |= OPT_IMPORT_STAR; - Py_DECREF(store_name); - return 1; - } -} - - -static int -symtable_visit_comprehension(struct symtable *st, comprehension_ty lc) -{ - VISIT(st, expr, lc->target); - VISIT(st, expr, lc->iter); - VISIT_SEQ(st, expr, lc->ifs); - return 1; -} - - -static int -symtable_visit_keyword(struct symtable *st, keyword_ty k) -{ - VISIT(st, expr, k->value); - return 1; -} - - -static int -symtable_visit_slice(struct symtable *st, slice_ty s) -{ - switch (s->kind) { - case Slice_kind: - if (s->v.Slice.lower) - VISIT(st, expr, s->v.Slice.lower) - if (s->v.Slice.upper) - VISIT(st, expr, s->v.Slice.upper) - if (s->v.Slice.step) - VISIT(st, expr, s->v.Slice.step) - break; - case ExtSlice_kind: - VISIT_SEQ(st, slice, s->v.ExtSlice.dims) - break; - case Index_kind: - VISIT(st, expr, s->v.Index.value) - break; - case Ellipsis_kind: - break; - } - return 1; -} - -static int -symtable_visit_genexp(struct symtable *st, expr_ty e) -{ - comprehension_ty outermost = ((comprehension_ty) - (asdl_seq_GET(e->v.GeneratorExp.generators, 0))); - /* Outermost iterator is evaluated in current scope */ - VISIT(st, expr, outermost->iter); - /* Create generator scope for the rest */ - if (!symtable_enter_block(st, GET_IDENTIFIER(genexpr), - FunctionBlock, (void *)e, 0)) { - return 0; - } - st->st_cur->ste_generator = 1; - /* Outermost iter is received as an argument */ - if (!symtable_implicit_arg(st, 0)) { - symtable_exit_block(st, (void *)e); - return 0; - } - VISIT_IN_BLOCK(st, expr, outermost->target, (void*)e); - VISIT_SEQ_IN_BLOCK(st, expr, outermost->ifs, (void*)e); - VISIT_SEQ_TAIL_IN_BLOCK(st, comprehension, - e->v.GeneratorExp.generators, 1, (void*)e); - VISIT_IN_BLOCK(st, expr, e->v.GeneratorExp.elt, (void*)e); - if (!symtable_exit_block(st, (void *)e)) - return 0; - return 1; -} diff --git a/sys/src/cmd/python/Python/sysmodule.c b/sys/src/cmd/python/Python/sysmodule.c deleted file mode 100644 index f2c42b962..000000000 --- a/sys/src/cmd/python/Python/sysmodule.c +++ /dev/null @@ -1,1468 +0,0 @@ - -/* System module */ - -/* -Various bits of information used by the interpreter are collected in -module 'sys'. -Function member: -- exit(sts): raise SystemExit -Data members: -- stdin, stdout, stderr: standard file objects -- modules: the table of modules (dictionary) -- path: module search path (list of strings) -- argv: script arguments (list of strings) -- ps1, ps2: optional primary and secondary prompts (strings) -*/ - -#include "Python.h" -#include "code.h" -#include "frameobject.h" -#include "eval.h" - -#include "osdefs.h" - -#ifdef MS_WINDOWS -#define WIN32_LEAN_AND_MEAN -#include "windows.h" -#endif /* MS_WINDOWS */ - -#ifdef MS_COREDLL -extern void *PyWin_DLLhModule; -/* A string loaded from the DLL at startup: */ -extern const char *PyWin_DLLVersionString; -#endif - -#ifdef __VMS -#include <unixlib.h> -#endif - -#ifdef MS_WINDOWS -#include <windows.h> -#endif - -#ifdef HAVE_LANGINFO_H -#include <locale.h> -#include <langinfo.h> -#endif - -PyObject * -PySys_GetObject(char *name) -{ - PyThreadState *tstate = PyThreadState_GET(); - PyObject *sd = tstate->interp->sysdict; - if (sd == NULL) - return NULL; - return PyDict_GetItemString(sd, name); -} - -FILE * -PySys_GetFile(char *name, FILE *def) -{ - FILE *fp = NULL; - PyObject *v = PySys_GetObject(name); - if (v != NULL && PyFile_Check(v)) - fp = PyFile_AsFile(v); - if (fp == NULL) - fp = def; - return fp; -} - -int -PySys_SetObject(char *name, PyObject *v) -{ - PyThreadState *tstate = PyThreadState_GET(); - PyObject *sd = tstate->interp->sysdict; - if (v == NULL) { - if (PyDict_GetItemString(sd, name) == NULL) - return 0; - else - return PyDict_DelItemString(sd, name); - } - else - return PyDict_SetItemString(sd, name, v); -} - -static PyObject * -sys_displayhook(PyObject *self, PyObject *o) -{ - PyObject *outf; - PyInterpreterState *interp = PyThreadState_GET()->interp; - PyObject *modules = interp->modules; - PyObject *builtins = PyDict_GetItemString(modules, "__builtin__"); - - if (builtins == NULL) { - PyErr_SetString(PyExc_RuntimeError, "lost __builtin__"); - return NULL; - } - - /* Print value except if None */ - /* After printing, also assign to '_' */ - /* Before, set '_' to None to avoid recursion */ - if (o == Py_None) { - Py_INCREF(Py_None); - return Py_None; - } - if (PyObject_SetAttrString(builtins, "_", Py_None) != 0) - return NULL; - if (Py_FlushLine() != 0) - return NULL; - outf = PySys_GetObject("stdout"); - if (outf == NULL) { - PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout"); - return NULL; - } - if (PyFile_WriteObject(o, outf, 0) != 0) - return NULL; - PyFile_SoftSpace(outf, 1); - if (Py_FlushLine() != 0) - return NULL; - if (PyObject_SetAttrString(builtins, "_", o) != 0) - return NULL; - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(displayhook_doc, -"displayhook(object) -> None\n" -"\n" -"Print an object to sys.stdout and also save it in __builtin__.\n" -); - -static PyObject * -sys_excepthook(PyObject* self, PyObject* args) -{ - PyObject *exc, *value, *tb; - if (!PyArg_UnpackTuple(args, "excepthook", 3, 3, &exc, &value, &tb)) - return NULL; - PyErr_Display(exc, value, tb); - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(excepthook_doc, -"excepthook(exctype, value, traceback) -> None\n" -"\n" -"Handle an exception by displaying it with a traceback on sys.stderr.\n" -); - -static PyObject * -sys_exc_info(PyObject *self, PyObject *noargs) -{ - PyThreadState *tstate; - tstate = PyThreadState_GET(); - return Py_BuildValue( - "(OOO)", - tstate->exc_type != NULL ? tstate->exc_type : Py_None, - tstate->exc_value != NULL ? tstate->exc_value : Py_None, - tstate->exc_traceback != NULL ? - tstate->exc_traceback : Py_None); -} - -PyDoc_STRVAR(exc_info_doc, -"exc_info() -> (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." -); - -static PyObject * -sys_exc_clear(PyObject *self, PyObject *noargs) -{ - PyThreadState *tstate = PyThreadState_GET(); - PyObject *tmp_type, *tmp_value, *tmp_tb; - tmp_type = tstate->exc_type; - tmp_value = tstate->exc_value; - tmp_tb = tstate->exc_traceback; - tstate->exc_type = NULL; - tstate->exc_value = NULL; - tstate->exc_traceback = NULL; - Py_XDECREF(tmp_type); - Py_XDECREF(tmp_value); - Py_XDECREF(tmp_tb); - /* For b/w compatibility */ - PySys_SetObject("exc_type", Py_None); - PySys_SetObject("exc_value", Py_None); - PySys_SetObject("exc_traceback", Py_None); - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(exc_clear_doc, -"exc_clear() -> None\n\ -\n\ -Clear global information on the current exception. Subsequent calls to\n\ -exc_info() will return (None,None,None) until another exception is raised\n\ -in the current thread or the execution stack returns to a frame where\n\ -another exception is being handled." -); - -static PyObject * -sys_exit(PyObject *self, PyObject *args) -{ - PyObject *exit_code = 0; - if (!PyArg_UnpackTuple(args, "exit", 0, 1, &exit_code)) - return NULL; - /* Raise SystemExit so callers may catch it or clean up. */ - PyErr_SetObject(PyExc_SystemExit, exit_code); - return NULL; -} - -PyDoc_STRVAR(exit_doc, -"exit([status])\n\ -\n\ -Exit the interpreter by raising SystemExit(status).\n\ -If the status is omitted or None, it defaults to zero (i.e., success).\n\ -If the status is numeric, 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)." -); - -#ifdef Py_USING_UNICODE - -static PyObject * -sys_getdefaultencoding(PyObject *self) -{ - return PyString_FromString(PyUnicode_GetDefaultEncoding()); -} - -PyDoc_STRVAR(getdefaultencoding_doc, -"getdefaultencoding() -> string\n\ -\n\ -Return the current default string encoding used by the Unicode \n\ -implementation." -); - -static PyObject * -sys_setdefaultencoding(PyObject *self, PyObject *args) -{ - char *encoding; - if (!PyArg_ParseTuple(args, "s:setdefaultencoding", &encoding)) - return NULL; - if (PyUnicode_SetDefaultEncoding(encoding)) - return NULL; - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(setdefaultencoding_doc, -"setdefaultencoding(encoding)\n\ -\n\ -Set the current default string encoding used by the Unicode implementation." -); - -static PyObject * -sys_getfilesystemencoding(PyObject *self) -{ - if (Py_FileSystemDefaultEncoding) - return PyString_FromString(Py_FileSystemDefaultEncoding); - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(getfilesystemencoding_doc, -"getfilesystemencoding() -> string\n\ -\n\ -Return the encoding used to convert Unicode filenames in\n\ -operating system filenames." -); - -#endif - -/* - * Cached interned string objects used for calling the profile and - * trace functions. Initialized by trace_init(). - */ -static PyObject *whatstrings[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL}; - -static int -trace_init(void) -{ - static char *whatnames[7] = {"call", "exception", "line", "return", - "c_call", "c_exception", "c_return"}; - PyObject *name; - int i; - for (i = 0; i < 7; ++i) { - if (whatstrings[i] == NULL) { - name = PyString_InternFromString(whatnames[i]); - if (name == NULL) - return -1; - whatstrings[i] = name; - } - } - return 0; -} - - -static PyObject * -call_trampoline(PyThreadState *tstate, PyObject* callback, - PyFrameObject *frame, int what, PyObject *arg) -{ - PyObject *args = PyTuple_New(3); - PyObject *whatstr; - PyObject *result; - - if (args == NULL) - return NULL; - Py_INCREF(frame); - whatstr = whatstrings[what]; - Py_INCREF(whatstr); - if (arg == NULL) - arg = Py_None; - Py_INCREF(arg); - PyTuple_SET_ITEM(args, 0, (PyObject *)frame); - PyTuple_SET_ITEM(args, 1, whatstr); - PyTuple_SET_ITEM(args, 2, arg); - - /* call the Python-level function */ - PyFrame_FastToLocals(frame); - result = PyEval_CallObject(callback, args); - PyFrame_LocalsToFast(frame, 1); - if (result == NULL) - PyTraceBack_Here(frame); - - /* cleanup */ - Py_DECREF(args); - return result; -} - -static int -profile_trampoline(PyObject *self, PyFrameObject *frame, - int what, PyObject *arg) -{ - PyThreadState *tstate = frame->f_tstate; - PyObject *result; - - if (arg == NULL) - arg = Py_None; - result = call_trampoline(tstate, self, frame, what, arg); - if (result == NULL) { - PyEval_SetProfile(NULL, NULL); - return -1; - } - Py_DECREF(result); - return 0; -} - -static int -trace_trampoline(PyObject *self, PyFrameObject *frame, - int what, PyObject *arg) -{ - PyThreadState *tstate = frame->f_tstate; - PyObject *callback; - PyObject *result; - - if (what == PyTrace_CALL) - callback = self; - else - callback = frame->f_trace; - if (callback == NULL) - return 0; - result = call_trampoline(tstate, callback, frame, what, arg); - if (result == NULL) { - PyEval_SetTrace(NULL, NULL); - Py_XDECREF(frame->f_trace); - frame->f_trace = NULL; - return -1; - } - if (result != Py_None) { - PyObject *temp = frame->f_trace; - frame->f_trace = NULL; - Py_XDECREF(temp); - frame->f_trace = result; - } - else { - Py_DECREF(result); - } - return 0; -} - -static PyObject * -sys_settrace(PyObject *self, PyObject *args) -{ - if (trace_init() == -1) - return NULL; - if (args == Py_None) - PyEval_SetTrace(NULL, NULL); - else - PyEval_SetTrace(trace_trampoline, args); - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(settrace_doc, -"settrace(function)\n\ -\n\ -Set the global debug tracing function. It will be called on each\n\ -function call. See the debugger chapter in the library manual." -); - -static PyObject * -sys_setprofile(PyObject *self, PyObject *args) -{ - if (trace_init() == -1) - return NULL; - if (args == Py_None) - PyEval_SetProfile(NULL, NULL); - else - PyEval_SetProfile(profile_trampoline, args); - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(setprofile_doc, -"setprofile(function)\n\ -\n\ -Set the profiling function. It will be called on each function call\n\ -and return. See the profiler chapter in the library manual." -); - -static PyObject * -sys_setcheckinterval(PyObject *self, PyObject *args) -{ - if (!PyArg_ParseTuple(args, "i:setcheckinterval", &_Py_CheckInterval)) - return NULL; - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(setcheckinterval_doc, -"setcheckinterval(n)\n\ -\n\ -Tell the Python interpreter to check for asynchronous events every\n\ -n instructions. This also affects how often thread switches occur." -); - -static PyObject * -sys_getcheckinterval(PyObject *self, PyObject *args) -{ - return PyInt_FromLong(_Py_CheckInterval); -} - -PyDoc_STRVAR(getcheckinterval_doc, -"getcheckinterval() -> current check interval; see setcheckinterval()." -); - -#ifdef WITH_TSC -static PyObject * -sys_settscdump(PyObject *self, PyObject *args) -{ - int bool; - PyThreadState *tstate = PyThreadState_Get(); - - if (!PyArg_ParseTuple(args, "i:settscdump", &bool)) - return NULL; - if (bool) - tstate->interp->tscdump = 1; - else - tstate->interp->tscdump = 0; - Py_INCREF(Py_None); - return Py_None; - -} - -PyDoc_STRVAR(settscdump_doc, -"settscdump(bool)\n\ -\n\ -If true, tell the Python interpreter to dump VM measurements to\n\ -stderr. If false, turn off dump. The measurements are based on the\n\ -processor's time-stamp counter." -); -#endif /* TSC */ - -static PyObject * -sys_setrecursionlimit(PyObject *self, PyObject *args) -{ - int new_limit; - if (!PyArg_ParseTuple(args, "i:setrecursionlimit", &new_limit)) - return NULL; - if (new_limit <= 0) { - PyErr_SetString(PyExc_ValueError, - "recursion limit must be positive"); - return NULL; - } - Py_SetRecursionLimit(new_limit); - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(setrecursionlimit_doc, -"setrecursionlimit(n)\n\ -\n\ -Set the maximum depth of the Python interpreter stack to n. This\n\ -limit prevents infinite recursion from causing an overflow of the C\n\ -stack and crashing Python. The highest possible limit is platform-\n\ -dependent." -); - -static PyObject * -sys_getrecursionlimit(PyObject *self) -{ - return PyInt_FromLong(Py_GetRecursionLimit()); -} - -PyDoc_STRVAR(getrecursionlimit_doc, -"getrecursionlimit()\n\ -\n\ -Return the current value of the recursion limit, the maximum depth\n\ -of the Python interpreter stack. This limit prevents infinite\n\ -recursion from causing an overflow of the C stack and crashing Python." -); - -#ifdef MS_WINDOWS -PyDoc_STRVAR(getwindowsversion_doc, -"getwindowsversion()\n\ -\n\ -Return information about the running version of Windows.\n\ -The result is a tuple of (major, minor, build, platform, text)\n\ -All elements are numbers, except text which is a string.\n\ -Platform may be 0 for win32s, 1 for Windows 9x/ME, 2 for Windows NT/2000/XP\n\ -" -); - -static PyObject * -sys_getwindowsversion(PyObject *self) -{ - OSVERSIONINFO ver; - ver.dwOSVersionInfoSize = sizeof(ver); - if (!GetVersionEx(&ver)) - return PyErr_SetFromWindowsErr(0); - return Py_BuildValue("HHHHs", - ver.dwMajorVersion, - ver.dwMinorVersion, - ver.dwBuildNumber, - ver.dwPlatformId, - ver.szCSDVersion); -} - -#endif /* MS_WINDOWS */ - -#ifdef HAVE_DLOPEN -static PyObject * -sys_setdlopenflags(PyObject *self, PyObject *args) -{ - int new_val; - PyThreadState *tstate = PyThreadState_GET(); - if (!PyArg_ParseTuple(args, "i:setdlopenflags", &new_val)) - return NULL; - if (!tstate) - return NULL; - tstate->interp->dlopenflags = new_val; - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(setdlopenflags_doc, -"setdlopenflags(n) -> None\n\ -\n\ -Set the flags that will be used for dlopen() calls. Among other\n\ -things, this will enable a lazy resolving of symbols when importing\n\ -a module, if called as sys.setdlopenflags(0)\n\ -To share symbols across extension modules, call as\n\ -sys.setdlopenflags(dl.RTLD_NOW|dl.RTLD_GLOBAL)" -); - -static PyObject * -sys_getdlopenflags(PyObject *self, PyObject *args) -{ - PyThreadState *tstate = PyThreadState_GET(); - if (!tstate) - return NULL; - return PyInt_FromLong(tstate->interp->dlopenflags); -} - -PyDoc_STRVAR(getdlopenflags_doc, -"getdlopenflags() -> int\n\ -\n\ -Return the current value of the flags that are used for dlopen()\n\ -calls. The flag constants are defined in the dl module." -); -#endif - -#ifdef USE_MALLOPT -/* Link with -lmalloc (or -lmpc) on an SGI */ -#include <malloc.h> - -static PyObject * -sys_mdebug(PyObject *self, PyObject *args) -{ - int flag; - if (!PyArg_ParseTuple(args, "i:mdebug", &flag)) - return NULL; - mallopt(M_DEBUG, flag); - Py_INCREF(Py_None); - return Py_None; -} -#endif /* USE_MALLOPT */ - -static PyObject * -sys_getrefcount(PyObject *self, PyObject *arg) -{ - return PyInt_FromSsize_t(arg->ob_refcnt); -} - -#ifdef Py_REF_DEBUG -static PyObject * -sys_gettotalrefcount(PyObject *self) -{ - return PyInt_FromSsize_t(_Py_GetRefTotal()); -} -#endif /* Py_REF_DEBUG */ - -PyDoc_STRVAR(getrefcount_doc, -"getrefcount(object) -> integer\n\ -\n\ -Return the reference count of object. The count returned is generally\n\ -one higher than you might expect, because it includes the (temporary)\n\ -reference as an argument to getrefcount()." -); - -#ifdef COUNT_ALLOCS -static PyObject * -sys_getcounts(PyObject *self) -{ - extern PyObject *get_counts(void); - - return get_counts(); -} -#endif - -PyDoc_STRVAR(getframe_doc, -"_getframe([depth]) -> frameobject\n\ -\n\ -Return a frame object from the call stack. If optional integer depth is\n\ -given, return the frame object that many calls below the top of the stack.\n\ -If that is deeper than the call stack, ValueError is raised. The default\n\ -for depth is zero, returning the frame at the top of the call stack.\n\ -\n\ -This function should be used for internal and specialized\n\ -purposes only." -); - -static PyObject * -sys_getframe(PyObject *self, PyObject *args) -{ - PyFrameObject *f = PyThreadState_GET()->frame; - int depth = -1; - - if (!PyArg_ParseTuple(args, "|i:_getframe", &depth)) - return NULL; - - while (depth > 0 && f != NULL) { - f = f->f_back; - --depth; - } - if (f == NULL) { - PyErr_SetString(PyExc_ValueError, - "call stack is not deep enough"); - return NULL; - } - Py_INCREF(f); - return (PyObject*)f; -} - -PyDoc_STRVAR(current_frames_doc, -"_current_frames() -> dictionary\n\ -\n\ -Return a dictionary mapping each current thread T's thread id to T's\n\ -current stack frame.\n\ -\n\ -This function should be used for specialized purposes only." -); - -static PyObject * -sys_current_frames(PyObject *self, PyObject *noargs) -{ - return _PyThread_CurrentFrames(); -} - -PyDoc_STRVAR(call_tracing_doc, -"call_tracing(func, args) -> object\n\ -\n\ -Call func(*args), while tracing is enabled. The tracing state is\n\ -saved, and restored afterwards. This is intended to be called from\n\ -a debugger from a checkpoint, to recursively debug some other code." -); - -static PyObject * -sys_call_tracing(PyObject *self, PyObject *args) -{ - PyObject *func, *funcargs; - if (!PyArg_UnpackTuple(args, "call_tracing", 2, 2, &func, &funcargs)) - return NULL; - return _PyEval_CallTracing(func, funcargs); -} - -PyDoc_STRVAR(callstats_doc, -"callstats() -> tuple of integers\n\ -\n\ -Return a tuple of function call statistics, if CALL_PROFILE was defined\n\ -when Python was built. Otherwise, return None.\n\ -\n\ -When enabled, this function returns detailed, implementation-specific\n\ -details about the number of function calls executed. The return value is\n\ -a 11-tuple where the entries in the tuple are counts of:\n\ -0. all function calls\n\ -1. calls to PyFunction_Type objects\n\ -2. PyFunction calls that do not create an argument tuple\n\ -3. PyFunction calls that do not create an argument tuple\n\ - and bypass PyEval_EvalCodeEx()\n\ -4. PyMethod calls\n\ -5. PyMethod calls on bound methods\n\ -6. PyType calls\n\ -7. PyCFunction calls\n\ -8. generator calls\n\ -9. All other calls\n\ -10. Number of stack pops performed by call_function()" -); - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef Py_TRACE_REFS -/* Defined in objects.c because it uses static globals if that file */ -extern PyObject *_Py_GetObjects(PyObject *, PyObject *); -#endif - -#ifdef DYNAMIC_EXECUTION_PROFILE -/* Defined in ceval.c because it uses static globals if that file */ -extern PyObject *_Py_GetDXProfile(PyObject *, PyObject *); -#endif - -#ifdef __cplusplus -} -#endif - -static PyMethodDef sys_methods[] = { - /* Might as well keep this in alphabetic order */ - {"callstats", (PyCFunction)PyEval_GetCallStats, METH_NOARGS, - callstats_doc}, - {"_current_frames", sys_current_frames, METH_NOARGS, - current_frames_doc}, - {"displayhook", sys_displayhook, METH_O, displayhook_doc}, - {"exc_info", sys_exc_info, METH_NOARGS, exc_info_doc}, - {"exc_clear", sys_exc_clear, METH_NOARGS, exc_clear_doc}, - {"excepthook", sys_excepthook, METH_VARARGS, excepthook_doc}, - {"exit", sys_exit, METH_VARARGS, exit_doc}, -#ifdef Py_USING_UNICODE - {"getdefaultencoding", (PyCFunction)sys_getdefaultencoding, - METH_NOARGS, getdefaultencoding_doc}, -#endif -#ifdef HAVE_DLOPEN - {"getdlopenflags", (PyCFunction)sys_getdlopenflags, METH_NOARGS, - getdlopenflags_doc}, -#endif -#ifdef COUNT_ALLOCS - {"getcounts", (PyCFunction)sys_getcounts, METH_NOARGS}, -#endif -#ifdef DYNAMIC_EXECUTION_PROFILE - {"getdxp", _Py_GetDXProfile, METH_VARARGS}, -#endif -#ifdef Py_USING_UNICODE - {"getfilesystemencoding", (PyCFunction)sys_getfilesystemencoding, - METH_NOARGS, getfilesystemencoding_doc}, -#endif -#ifdef Py_TRACE_REFS - {"getobjects", _Py_GetObjects, METH_VARARGS}, -#endif -#ifdef Py_REF_DEBUG - {"gettotalrefcount", (PyCFunction)sys_gettotalrefcount, METH_NOARGS}, -#endif - {"getrefcount", (PyCFunction)sys_getrefcount, METH_O, getrefcount_doc}, - {"getrecursionlimit", (PyCFunction)sys_getrecursionlimit, METH_NOARGS, - getrecursionlimit_doc}, - {"_getframe", sys_getframe, METH_VARARGS, getframe_doc}, -#ifdef MS_WINDOWS - {"getwindowsversion", (PyCFunction)sys_getwindowsversion, METH_NOARGS, - getwindowsversion_doc}, -#endif /* MS_WINDOWS */ -#ifdef USE_MALLOPT - {"mdebug", sys_mdebug, METH_VARARGS}, -#endif -#ifdef Py_USING_UNICODE - {"setdefaultencoding", sys_setdefaultencoding, METH_VARARGS, - setdefaultencoding_doc}, -#endif - {"setcheckinterval", sys_setcheckinterval, METH_VARARGS, - setcheckinterval_doc}, - {"getcheckinterval", sys_getcheckinterval, METH_NOARGS, - getcheckinterval_doc}, -#ifdef HAVE_DLOPEN - {"setdlopenflags", sys_setdlopenflags, METH_VARARGS, - setdlopenflags_doc}, -#endif - {"setprofile", sys_setprofile, METH_O, setprofile_doc}, - {"setrecursionlimit", sys_setrecursionlimit, METH_VARARGS, - setrecursionlimit_doc}, -#ifdef WITH_TSC - {"settscdump", sys_settscdump, METH_VARARGS, settscdump_doc}, -#endif - {"settrace", sys_settrace, METH_O, settrace_doc}, - {"call_tracing", sys_call_tracing, METH_VARARGS, call_tracing_doc}, - {NULL, NULL} /* sentinel */ -}; - -static PyObject * -list_builtin_module_names(void) -{ - PyObject *list = PyList_New(0); - int i; - if (list == NULL) - return NULL; - for (i = 0; PyImport_Inittab[i].name != NULL; i++) { - PyObject *name = PyString_FromString( - PyImport_Inittab[i].name); - if (name == NULL) - break; - PyList_Append(list, name); - Py_DECREF(name); - } - if (PyList_Sort(list) != 0) { - Py_DECREF(list); - list = NULL; - } - if (list) { - PyObject *v = PyList_AsTuple(list); - Py_DECREF(list); - list = v; - } - return list; -} - -static PyObject *warnoptions = NULL; - -void -PySys_ResetWarnOptions(void) -{ - if (warnoptions == NULL || !PyList_Check(warnoptions)) - return; - PyList_SetSlice(warnoptions, 0, PyList_GET_SIZE(warnoptions), NULL); -} - -void -PySys_AddWarnOption(char *s) -{ - PyObject *str; - - if (warnoptions == NULL || !PyList_Check(warnoptions)) { - Py_XDECREF(warnoptions); - warnoptions = PyList_New(0); - if (warnoptions == NULL) - return; - } - str = PyString_FromString(s); - if (str != NULL) { - PyList_Append(warnoptions, str); - Py_DECREF(str); - } -} - -/* XXX This doc string is too long to be a single string literal in VC++ 5.0. - Two literals concatenated works just fine. If you have a K&R compiler - or other abomination that however *does* understand longer strings, - get rid of the !!! comment in the middle and the quotes that surround it. */ -PyDoc_VAR(sys_doc) = -PyDoc_STR( -"This module provides access to some objects used or maintained by the\n\ -interpreter and to functions that interact strongly with the interpreter.\n\ -\n\ -Dynamic objects:\n\ -\n\ -argv -- command line arguments; argv[0] is the script pathname if known\n\ -path -- module search path; path[0] is the script directory, else ''\n\ -modules -- dictionary of loaded modules\n\ -\n\ -displayhook -- called to show results in an interactive session\n\ -excepthook -- called to handle any uncaught exception other than SystemExit\n\ - To customize printing in an interactive session or to install a custom\n\ - top-level exception handler, assign other functions to replace these.\n\ -\n\ -exitfunc -- if sys.exitfunc exists, this routine is called when Python exits\n\ - Assigning to sys.exitfunc is deprecated; use the atexit module instead.\n\ -\n\ -stdin -- standard input file object; used by raw_input() and input()\n\ -stdout -- standard output file object; used by the print statement\n\ -stderr -- standard error object; used for error messages\n\ - By assigning other file objects (or objects that behave like files)\n\ - to these, it is possible to redirect all of the interpreter's I/O.\n\ -\n\ -last_type -- type of last uncaught exception\n\ -last_value -- value of last uncaught exception\n\ -last_traceback -- traceback of last uncaught exception\n\ - These three are only available in an interactive session after a\n\ - traceback has been printed.\n\ -\n\ -exc_type -- type of exception currently being handled\n\ -exc_value -- value of exception currently being handled\n\ -exc_traceback -- traceback of exception currently being handled\n\ - The function exc_info() should be used instead of these three,\n\ - because it is thread-safe.\n\ -" -) -/* concatenating string here */ -PyDoc_STR( -"\n\ -Static objects:\n\ -\n\ -maxint -- the largest supported integer (the smallest is -maxint-1)\n\ -maxunicode -- the largest supported character\n\ -builtin_module_names -- tuple of module names built into this interpreter\n\ -version -- the version of this interpreter as a string\n\ -version_info -- version information as a tuple\n\ -hexversion -- version information encoded as a single integer\n\ -copyright -- copyright notice pertaining to this interpreter\n\ -platform -- platform identifier\n\ -executable -- pathname of this Python interpreter\n\ -prefix -- prefix used to find the Python library\n\ -exec_prefix -- prefix used to find the machine-specific Python library\n\ -" -) -#ifdef MS_WINDOWS -/* concatenating string here */ -PyDoc_STR( -"dllhandle -- [Windows only] integer handle of the Python DLL\n\ -winver -- [Windows only] version number of the Python DLL\n\ -" -) -#endif /* MS_WINDOWS */ -PyDoc_STR( -"__stdin__ -- the original stdin; don't touch!\n\ -__stdout__ -- the original stdout; don't touch!\n\ -__stderr__ -- the original stderr; don't touch!\n\ -__displayhook__ -- the original displayhook; don't touch!\n\ -__excepthook__ -- the original excepthook; don't touch!\n\ -\n\ -Functions:\n\ -\n\ -displayhook() -- print an object to the screen, and save it in __builtin__._\n\ -excepthook() -- print an exception and its traceback to sys.stderr\n\ -exc_info() -- return thread-safe information about the current exception\n\ -exc_clear() -- clear the exception state for the current thread\n\ -exit() -- exit the interpreter by raising SystemExit\n\ -getdlopenflags() -- returns flags to be used for dlopen() calls\n\ -getrefcount() -- return the reference count for an object (plus one :-)\n\ -getrecursionlimit() -- return the max recursion depth for the interpreter\n\ -setcheckinterval() -- control how often the interpreter checks for events\n\ -setdlopenflags() -- set the flags to be used for dlopen() calls\n\ -setprofile() -- set the global profiling function\n\ -setrecursionlimit() -- set the max recursion depth for the interpreter\n\ -settrace() -- set the global debug tracing function\n\ -" -) -/* end of sys_doc */ ; - -static int -_check_and_flush (FILE *stream) -{ - int prev_fail = ferror (stream); - return fflush (stream) || prev_fail ? EOF : 0; -} - -/* Subversion branch and revision management */ -static const char _patchlevel_revision[] = PY_PATCHLEVEL_REVISION; -static const char headurl[] = "$HeadURL: svn+ssh://pythondev@svn.python.org/python/tags/r251/Python/sysmodule.c $"; -static int svn_initialized; -static char patchlevel_revision[50]; /* Just the number */ -static char branch[50]; -static char shortbranch[50]; -static const char *svn_revision; - -static void -svnversion_init(void) -{ - const char *python, *br_start, *br_end, *br_end2, *svnversion; - Py_ssize_t len; - int istag; - - if (svn_initialized) - return; - - python = strstr(headurl, "/python/"); - if (!python) - Py_FatalError("subversion keywords missing"); - - br_start = python + 8; - br_end = strchr(br_start, '/'); - assert(br_end); - - /* Works even for trunk, - as we are in trunk/Python/sysmodule.c */ - br_end2 = strchr(br_end+1, '/'); - - istag = strncmp(br_start, "tags", 4) == 0; - if (strncmp(br_start, "trunk", 5) == 0) { - strcpy(branch, "trunk"); - strcpy(shortbranch, "trunk"); - - } - else if (istag || strncmp(br_start, "branches", 8) == 0) { - len = br_end2 - br_start; - strncpy(branch, br_start, len); - branch[len] = '\0'; - - len = br_end2 - (br_end + 1); - strncpy(shortbranch, br_end + 1, len); - shortbranch[len] = '\0'; - } - else { - Py_FatalError("bad HeadURL"); - return; - } - - - svnversion = _Py_svnversion(); - if (strcmp(svnversion, "exported") != 0) - svn_revision = svnversion; - else if (istag) { - len = strlen(_patchlevel_revision); - strncpy(patchlevel_revision, _patchlevel_revision + 11, - len - 13); - patchlevel_revision[len - 13] = '\0'; - svn_revision = patchlevel_revision; - } - else - svn_revision = ""; - - svn_initialized = 1; -} - -/* Return svnversion output if available. - Else return Revision of patchlevel.h if on branch. - Else return empty string */ -const char* -Py_SubversionRevision() -{ - svnversion_init(); - return svn_revision; -} - -const char* -Py_SubversionShortBranch() -{ - svnversion_init(); - return shortbranch; -} - -PyObject * -_PySys_Init(void) -{ - PyObject *m, *v, *sysdict; - PyObject *sysin, *sysout, *syserr; - char *s; -#ifdef MS_WINDOWS - char buf[128]; -#endif - - m = Py_InitModule3("sys", sys_methods, sys_doc); - if (m == NULL) - return NULL; - sysdict = PyModule_GetDict(m); - - { - /* XXX: does this work on Win/Win64? (see posix_fstat) */ - struct stat sb; - if (fstat(fileno(stdin), &sb) == 0 && - S_ISDIR(sb.st_mode)) { - /* There's nothing more we can do. */ - /* Py_FatalError() will core dump, so just exit. */ - PySys_WriteStderr("Python error: <stdin> is a directory, cannot continue\n"); - exit(EXIT_FAILURE); - } - } - - /* Closing the standard FILE* if sys.std* goes aways causes problems - * for embedded Python usages. Closing them when somebody explicitly - * invokes .close() might be possible, but the FAQ promises they get - * never closed. However, we still need to get write errors when - * writing fails (e.g. because stdout is redirected), so we flush the - * streams and check for errors before the file objects are deleted. - * On OS X, fflush()ing stdin causes an error, so we exempt stdin - * from that procedure. - */ - sysin = PyFile_FromFile(stdin, "<stdin>", "r", NULL); - sysout = PyFile_FromFile(stdout, "<stdout>", "w", _check_and_flush); - syserr = PyFile_FromFile(stderr, "<stderr>", "w", _check_and_flush); - if (PyErr_Occurred()) - return NULL; -#ifdef MS_WINDOWS - if(isatty(_fileno(stdin)) && PyFile_Check(sysin)) { - sprintf(buf, "cp%d", GetConsoleCP()); - if (!PyFile_SetEncoding(sysin, buf)) - return NULL; - } - if(isatty(_fileno(stdout)) && PyFile_Check(sysout)) { - sprintf(buf, "cp%d", GetConsoleOutputCP()); - if (!PyFile_SetEncoding(sysout, buf)) - return NULL; - } - if(isatty(_fileno(stderr)) && PyFile_Check(syserr)) { - sprintf(buf, "cp%d", GetConsoleOutputCP()); - if (!PyFile_SetEncoding(syserr, buf)) - return NULL; - } -#endif - - PyDict_SetItemString(sysdict, "stdin", sysin); - PyDict_SetItemString(sysdict, "stdout", sysout); - PyDict_SetItemString(sysdict, "stderr", syserr); - /* Make backup copies for cleanup */ - PyDict_SetItemString(sysdict, "__stdin__", sysin); - PyDict_SetItemString(sysdict, "__stdout__", sysout); - PyDict_SetItemString(sysdict, "__stderr__", syserr); - PyDict_SetItemString(sysdict, "__displayhook__", - PyDict_GetItemString(sysdict, "displayhook")); - PyDict_SetItemString(sysdict, "__excepthook__", - PyDict_GetItemString(sysdict, "excepthook")); - Py_XDECREF(sysin); - Py_XDECREF(sysout); - Py_XDECREF(syserr); - PyDict_SetItemString(sysdict, "version", - v = PyString_FromString(Py_GetVersion())); - Py_XDECREF(v); - PyDict_SetItemString(sysdict, "hexversion", - v = PyInt_FromLong(PY_VERSION_HEX)); - Py_XDECREF(v); - svnversion_init(); - v = Py_BuildValue("(ssz)", "CPython", branch, svn_revision); - PyDict_SetItemString(sysdict, "subversion", v); - Py_XDECREF(v); - /* - * These release level checks are mutually exclusive and cover - * the field, so don't get too fancy with the pre-processor! - */ -#if PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_ALPHA - s = "alpha"; -#elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_BETA - s = "beta"; -#elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_GAMMA - s = "candidate"; -#elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_FINAL - s = "final"; -#endif - -#define SET_SYS_FROM_STRING(key, value) \ - v = value; \ - if (v != NULL) \ - PyDict_SetItemString(sysdict, key, v); \ - Py_XDECREF(v) - - SET_SYS_FROM_STRING("version_info", - Py_BuildValue("iiisi", PY_MAJOR_VERSION, - PY_MINOR_VERSION, - PY_MICRO_VERSION, s, - PY_RELEASE_SERIAL)); - SET_SYS_FROM_STRING("api_version", - PyInt_FromLong(PYTHON_API_VERSION)); - SET_SYS_FROM_STRING("copyright", - PyString_FromString(Py_GetCopyright())); - SET_SYS_FROM_STRING("platform", - PyString_FromString(Py_GetPlatform())); - SET_SYS_FROM_STRING("executable", - PyString_FromString(Py_GetProgramFullPath())); - SET_SYS_FROM_STRING("prefix", - PyString_FromString(Py_GetPrefix())); - SET_SYS_FROM_STRING("exec_prefix", - PyString_FromString(Py_GetExecPrefix())); - SET_SYS_FROM_STRING("maxint", - PyInt_FromLong(PyInt_GetMax())); -#ifdef Py_USING_UNICODE - SET_SYS_FROM_STRING("maxunicode", - PyInt_FromLong(PyUnicode_GetMax())); -#endif - SET_SYS_FROM_STRING("builtin_module_names", - list_builtin_module_names()); - { - /* Assumes that longs are at least 2 bytes long. - Should be safe! */ - unsigned long number = 1; - char *value; - - s = (char *) &number; - if (s[0] == 0) - value = "big"; - else - value = "little"; - SET_SYS_FROM_STRING("byteorder", - PyString_FromString(value)); - } -#ifdef MS_COREDLL - SET_SYS_FROM_STRING("dllhandle", - PyLong_FromVoidPtr(PyWin_DLLhModule)); - SET_SYS_FROM_STRING("winver", - PyString_FromString(PyWin_DLLVersionString)); -#endif -#undef SET_SYS_FROM_STRING - if (warnoptions == NULL) { - warnoptions = PyList_New(0); - } - else { - Py_INCREF(warnoptions); - } - if (warnoptions != NULL) { - PyDict_SetItemString(sysdict, "warnoptions", warnoptions); - } - - if (PyErr_Occurred()) - return NULL; - return m; -} - -static PyObject * -makepathobject(char *path, int delim) -{ - int i, n; - char *p; - PyObject *v, *w; - - n = 1; - p = path; - while ((p = strchr(p, delim)) != NULL) { - n++; - p++; - } - v = PyList_New(n); - if (v == NULL) - return NULL; - for (i = 0; ; i++) { - p = strchr(path, delim); - if (p == NULL) - p = strchr(path, '\0'); /* End of string */ - w = PyString_FromStringAndSize(path, (Py_ssize_t) (p - path)); - if (w == NULL) { - Py_DECREF(v); - return NULL; - } - PyList_SetItem(v, i, w); - if (*p == '\0') - break; - path = p+1; - } - return v; -} - -void -PySys_SetPath(char *path) -{ - PyObject *v; - if ((v = makepathobject(path, DELIM)) == NULL) - Py_FatalError("can't create sys.path"); - if (PySys_SetObject("path", v) != 0) - Py_FatalError("can't assign sys.path"); - Py_DECREF(v); -} - -static PyObject * -makeargvobject(int argc, char **argv) -{ - PyObject *av; - if (argc <= 0 || argv == NULL) { - /* Ensure at least one (empty) argument is seen */ - static char *empty_argv[1] = {""}; - argv = empty_argv; - argc = 1; - } - av = PyList_New(argc); - if (av != NULL) { - int i; - for (i = 0; i < argc; i++) { -#ifdef __VMS - PyObject *v; - - /* argv[0] is the script pathname if known */ - if (i == 0) { - char* fn = decc$translate_vms(argv[0]); - if ((fn == (char *)0) || fn == (char *)-1) - v = PyString_FromString(argv[0]); - else - v = PyString_FromString( - decc$translate_vms(argv[0])); - } else - v = PyString_FromString(argv[i]); -#else - PyObject *v = PyString_FromString(argv[i]); -#endif - if (v == NULL) { - Py_DECREF(av); - av = NULL; - break; - } - PyList_SetItem(av, i, v); - } - } - return av; -} - -void -PySys_SetArgv(int argc, char **argv) -{ -#if defined(HAVE_REALPATH) - char fullpath[MAXPATHLEN]; -#elif defined(MS_WINDOWS) - char fullpath[MAX_PATH]; -#endif - PyObject *av = makeargvobject(argc, argv); - PyObject *path = PySys_GetObject("path"); - if (av == NULL) - Py_FatalError("no mem for sys.argv"); - if (PySys_SetObject("argv", av) != 0) - Py_FatalError("can't assign sys.argv"); - if (path != NULL) { - char *argv0 = argv[0]; - char *p = NULL; - Py_ssize_t n = 0; - PyObject *a; -#ifdef HAVE_READLINK - char link[MAXPATHLEN+1]; - char argv0copy[2*MAXPATHLEN+1]; - int nr = 0; - if (argc > 0 && argv0 != NULL && strcmp(argv0, "-c") != 0) - nr = readlink(argv0, link, MAXPATHLEN); - if (nr > 0) { - /* It's a symlink */ - link[nr] = '\0'; - if (link[0] == SEP) - argv0 = link; /* Link to absolute path */ - else if (strchr(link, SEP) == NULL) - ; /* Link without path */ - else { - /* Must join(dirname(argv0), link) */ - char *q = strrchr(argv0, SEP); - if (q == NULL) - argv0 = link; /* argv0 without path */ - else { - /* Must make a copy */ - strcpy(argv0copy, argv0); - q = strrchr(argv0copy, SEP); - strcpy(q+1, link); - argv0 = argv0copy; - } - } - } -#endif /* HAVE_READLINK */ -#if SEP == '\\' /* Special case for MS filename syntax */ - if (argc > 0 && argv0 != NULL && strcmp(argv0, "-c") != 0) { - char *q; -#ifdef MS_WINDOWS - char *ptemp; - if (GetFullPathName(argv0, - sizeof(fullpath), - fullpath, - &ptemp)) { - argv0 = fullpath; - } -#endif - p = strrchr(argv0, SEP); - /* Test for alternate separator */ - q = strrchr(p ? p : argv0, '/'); - if (q != NULL) - p = q; - if (p != NULL) { - n = p + 1 - argv0; - if (n > 1 && p[-1] != ':') - n--; /* Drop trailing separator */ - } - } -#else /* All other filename syntaxes */ - if (argc > 0 && argv0 != NULL && strcmp(argv0, "-c") != 0) { -#if defined(HAVE_REALPATH) - if (realpath(argv0, fullpath)) { - argv0 = fullpath; - } -#endif - p = strrchr(argv0, SEP); - } - if (p != NULL) { -#ifndef RISCOS - n = p + 1 - argv0; -#else /* don't include trailing separator */ - n = p - argv0; -#endif /* RISCOS */ -#if SEP == '/' /* Special case for Unix filename syntax */ - if (n > 1) - n--; /* Drop trailing separator */ -#endif /* Unix */ - } -#endif /* All others */ - a = PyString_FromStringAndSize(argv0, n); - if (a == NULL) - Py_FatalError("no mem for sys.path insertion"); - if (PyList_Insert(path, 0, a) < 0) - Py_FatalError("sys.path.insert(0) failed"); - Py_DECREF(a); - } - Py_DECREF(av); -} - - -/* APIs to write to sys.stdout or sys.stderr using a printf-like interface. - Adapted from code submitted by Just van Rossum. - - PySys_WriteStdout(format, ...) - PySys_WriteStderr(format, ...) - - The first function writes to sys.stdout; the second to sys.stderr. When - there is a problem, they write to the real (C level) stdout or stderr; - no exceptions are raised. - - Both take a printf-style format string as their first argument followed - by a variable length argument list determined by the format string. - - *** WARNING *** - - The format should limit the total size of the formatted output string to - 1000 bytes. In particular, this means that no unrestricted "%s" formats - should occur; these should be limited using "%.<N>s where <N> is a - decimal number calculated so that <N> plus the maximum size of other - formatted text does not exceed 1000 bytes. Also watch out for "%f", - which can print hundreds of digits for very large numbers. - - */ - -static void -mywrite(char *name, FILE *fp, const char *format, va_list va) -{ - PyObject *file; - PyObject *error_type, *error_value, *error_traceback; - - PyErr_Fetch(&error_type, &error_value, &error_traceback); - file = PySys_GetObject(name); - if (file == NULL || PyFile_AsFile(file) == fp) - vfprintf(fp, format, va); - else { - char buffer[1001]; - const int written = PyOS_vsnprintf(buffer, sizeof(buffer), - format, va); - if (PyFile_WriteString(buffer, file) != 0) { - PyErr_Clear(); - fputs(buffer, fp); - } - if (written < 0 || (size_t)written >= sizeof(buffer)) { - const char *truncated = "... truncated"; - if (PyFile_WriteString(truncated, file) != 0) { - PyErr_Clear(); - fputs(truncated, fp); - } - } - } - PyErr_Restore(error_type, error_value, error_traceback); -} - -void -PySys_WriteStdout(const char *format, ...) -{ - va_list va; - - va_start(va, format); - mywrite("stdout", stdout, format, va); - va_end(va); -} - -void -PySys_WriteStderr(const char *format, ...) -{ - va_list va; - - va_start(va, format); - mywrite("stderr", stderr, format, va); - va_end(va); -} diff --git a/sys/src/cmd/python/Python/thread.c b/sys/src/cmd/python/Python/thread.c deleted file mode 100644 index 3a2c7af6f..000000000 --- a/sys/src/cmd/python/Python/thread.c +++ /dev/null @@ -1,384 +0,0 @@ - -/* Thread package. - This is intended to be usable independently from Python. - The implementation for system foobar is in a file thread_foobar.h - which is included by this file dependent on config settings. - Stuff shared by all thread_*.h files is collected here. */ - -#include "Python.h" - - -#ifndef _POSIX_THREADS -/* This means pthreads are not implemented in libc headers, hence the macro - not present in unistd.h. But they still can be implemented as an external - library (e.g. gnu pth in pthread emulation) */ -# ifdef HAVE_PTHREAD_H -# include <pthread.h> /* _POSIX_THREADS */ -# endif -#endif - -#ifndef DONT_HAVE_STDIO_H -#include <stdio.h> -#endif - -#include <stdlib.h> - -#ifdef __sgi -#ifndef HAVE_PTHREAD_H /* XXX Need to check in configure.in */ -#undef _POSIX_THREADS -#endif -#endif - -#include "pythread.h" - -#ifndef _POSIX_THREADS - -#ifdef __sgi -#define SGI_THREADS -#endif - -#ifdef HAVE_THREAD_H -#define SOLARIS_THREADS -#endif - -#if defined(sun) && !defined(SOLARIS_THREADS) -#define SUN_LWP -#endif - -/* Check if we're running on HP-UX and _SC_THREADS is defined. If so, then - enough of the Posix threads package is implimented to support python - threads. - - This is valid for HP-UX 11.23 running on an ia64 system. If needed, add - a check of __ia64 to verify that we're running on a ia64 system instead - of a pa-risc system. -*/ -#ifdef __hpux -#ifdef _SC_THREADS -#define _POSIX_THREADS -#endif -#endif - -#endif /* _POSIX_THREADS */ - - -#ifdef Py_DEBUG -static int thread_debug = 0; -#define dprintf(args) (void)((thread_debug & 1) && printf args) -#define d2printf(args) ((thread_debug & 8) && printf args) -#else -#define dprintf(args) -#define d2printf(args) -#endif - -static int initialized; - -static void PyThread__init_thread(void); /* Forward */ - -void -PyThread_init_thread(void) -{ -#ifdef Py_DEBUG - char *p = getenv("THREADDEBUG"); - - if (p) { - if (*p) - thread_debug = atoi(p); - else - thread_debug = 1; - } -#endif /* Py_DEBUG */ - if (initialized) - return; - initialized = 1; - dprintf(("PyThread_init_thread called\n")); - PyThread__init_thread(); -} - -/* Support for runtime thread stack size tuning. - A value of 0 means using the platform's default stack size - or the size specified by the THREAD_STACK_SIZE macro. */ -static size_t _pythread_stacksize = 0; - -#ifdef SGI_THREADS -#include "thread_sgi.h" -#endif - -#ifdef SOLARIS_THREADS -#include "thread_solaris.h" -#endif - -#ifdef SUN_LWP -#include "thread_lwp.h" -#endif - -#ifdef HAVE_PTH -#include "thread_pth.h" -#undef _POSIX_THREADS -#endif - -#ifdef _POSIX_THREADS -#include "thread_pthread.h" -#endif - -#ifdef C_THREADS -#include "thread_cthread.h" -#endif - -#ifdef NT_THREADS -#include "thread_nt.h" -#endif - -#ifdef OS2_THREADS -#include "thread_os2.h" -#endif - -#ifdef BEOS_THREADS -#include "thread_beos.h" -#endif - -#ifdef WINCE_THREADS -#include "thread_wince.h" -#endif - -#ifdef PLAN9_THREADS -#include "thread_plan9.h" -#endif - -#ifdef ATHEOS_THREADS -#include "thread_atheos.h" -#endif - -/* -#ifdef FOOBAR_THREADS -#include "thread_foobar.h" -#endif -*/ - -/* return the current thread stack size */ -size_t -PyThread_get_stacksize(void) -{ - return _pythread_stacksize; -} - -/* Only platforms defining a THREAD_SET_STACKSIZE() macro - in thread_<platform>.h support changing the stack size. - Return 0 if stack size is valid, - -1 if stack size value is invalid, - -2 if setting stack size is not supported. */ -int -PyThread_set_stacksize(size_t size) -{ -#if defined(THREAD_SET_STACKSIZE) - return THREAD_SET_STACKSIZE(size); -#else - return -2; -#endif -} - -#ifndef Py_HAVE_NATIVE_TLS -/* If the platform has not supplied a platform specific - TLS implementation, provide our own. - - This code stolen from "thread_sgi.h", where it was the only - implementation of an existing Python TLS API. -*/ -/* ------------------------------------------------------------------------ -Per-thread data ("key") support. - -Use PyThread_create_key() to create a new key. This is typically shared -across threads. - -Use PyThread_set_key_value(thekey, value) to associate void* value with -thekey in the current thread. Each thread has a distinct mapping of thekey -to a void* value. Caution: if the current thread already has a mapping -for thekey, value is ignored. - -Use PyThread_get_key_value(thekey) to retrieve the void* value associated -with thekey in the current thread. This returns NULL if no value is -associated with thekey in the current thread. - -Use PyThread_delete_key_value(thekey) to forget the current thread's associated -value for thekey. PyThread_delete_key(thekey) forgets the values associated -with thekey across *all* threads. - -While some of these functions have error-return values, none set any -Python exception. - -None of the functions does memory management on behalf of the void* values. -You need to allocate and deallocate them yourself. If the void* values -happen to be PyObject*, these functions don't do refcount operations on -them either. - -The GIL does not need to be held when calling these functions; they supply -their own locking. This isn't true of PyThread_create_key(), though (see -next paragraph). - -There's a hidden assumption that PyThread_create_key() will be called before -any of the other functions are called. There's also a hidden assumption -that calls to PyThread_create_key() are serialized externally. ------------------------------------------------------------------------- */ - -/* A singly-linked list of struct key objects remembers all the key->value - * associations. File static keyhead heads the list. keymutex is used - * to enforce exclusion internally. - */ -struct key { - /* Next record in the list, or NULL if this is the last record. */ - struct key *next; - - /* The thread id, according to PyThread_get_thread_ident(). */ - long id; - - /* The key and its associated value. */ - int key; - void *value; -}; - -static struct key *keyhead = NULL; -static PyThread_type_lock keymutex = NULL; -static int nkeys = 0; /* PyThread_create_key() hands out nkeys+1 next */ - -/* Internal helper. - * If the current thread has a mapping for key, the appropriate struct key* - * is returned. NB: value is ignored in this case! - * If there is no mapping for key in the current thread, then: - * If value is NULL, NULL is returned. - * Else a mapping of key to value is created for the current thread, - * and a pointer to a new struct key* is returned; except that if - * malloc() can't find room for a new struct key*, NULL is returned. - * So when value==NULL, this acts like a pure lookup routine, and when - * value!=NULL, this acts like dict.setdefault(), returning an existing - * mapping if one exists, else creating a new mapping. - * - * Caution: this used to be too clever, trying to hold keymutex only - * around the "p->next = keyhead; keyhead = p" pair. That allowed - * another thread to mutate the list, via key deletion, concurrent with - * find_key() crawling over the list. Hilarity ensued. For example, when - * the for-loop here does "p = p->next", p could end up pointing at a - * record that PyThread_delete_key_value() was concurrently free()'ing. - * That could lead to anything, from failing to find a key that exists, to - * segfaults. Now we lock the whole routine. - */ -static struct key * -find_key(int key, void *value) -{ - struct key *p; - long id = PyThread_get_thread_ident(); - - if (!keymutex) - return NULL; - PyThread_acquire_lock(keymutex, 1); - for (p = keyhead; p != NULL; p = p->next) { - if (p->id == id && p->key == key) - goto Done; - } - if (value == NULL) { - assert(p == NULL); - goto Done; - } - p = (struct key *)malloc(sizeof(struct key)); - if (p != NULL) { - p->id = id; - p->key = key; - p->value = value; - p->next = keyhead; - keyhead = p; - } - Done: - PyThread_release_lock(keymutex); - return p; -} - -/* Return a new key. This must be called before any other functions in - * this family, and callers must arrange to serialize calls to this - * function. No violations are detected. - */ -int -PyThread_create_key(void) -{ - /* All parts of this function are wrong if it's called by multiple - * threads simultaneously. - */ - if (keymutex == NULL) - keymutex = PyThread_allocate_lock(); - return ++nkeys; -} - -/* Forget the associations for key across *all* threads. */ -void -PyThread_delete_key(int key) -{ - struct key *p, **q; - - PyThread_acquire_lock(keymutex, 1); - q = &keyhead; - while ((p = *q) != NULL) { - if (p->key == key) { - *q = p->next; - free((void *)p); - /* NB This does *not* free p->value! */ - } - else - q = &p->next; - } - PyThread_release_lock(keymutex); -} - -/* Confusing: If the current thread has an association for key, - * value is ignored, and 0 is returned. Else an attempt is made to create - * an association of key to value for the current thread. 0 is returned - * if that succeeds, but -1 is returned if there's not enough memory - * to create the association. value must not be NULL. - */ -int -PyThread_set_key_value(int key, void *value) -{ - struct key *p; - - assert(value != NULL); - p = find_key(key, value); - if (p == NULL) - return -1; - else - return 0; -} - -/* Retrieve the value associated with key in the current thread, or NULL - * if the current thread doesn't have an association for key. - */ -void * -PyThread_get_key_value(int key) -{ - struct key *p = find_key(key, NULL); - - if (p == NULL) - return NULL; - else - return p->value; -} - -/* Forget the current thread's association for key, if any. */ -void -PyThread_delete_key_value(int key) -{ - long id = PyThread_get_thread_ident(); - struct key *p, **q; - - PyThread_acquire_lock(keymutex, 1); - q = &keyhead; - while ((p = *q) != NULL) { - if (p->key == key && p->id == id) { - *q = p->next; - free((void *)p); - /* NB This does *not* free p->value! */ - break; - } - else - q = &p->next; - } - PyThread_release_lock(keymutex); -} - -#endif /* Py_HAVE_NATIVE_TLS */ diff --git a/sys/src/cmd/python/Python/thread_atheos.h b/sys/src/cmd/python/Python/thread_atheos.h deleted file mode 100644 index c9f5e2318..000000000 --- a/sys/src/cmd/python/Python/thread_atheos.h +++ /dev/null @@ -1,300 +0,0 @@ -/* Threading for AtheOS. - Based on thread_beos.h. */ - -#include <atheos/threads.h> -#include <atheos/semaphore.h> -#include <atheos/atomic.h> -#include <errno.h> -#include <string.h> - -/* Missing decl from threads.h */ -extern int exit_thread(int); - - -/* Undefine FASTLOCK to play with simple semaphores. */ -#define FASTLOCK - - -#ifdef FASTLOCK - -/* Use an atomic counter and a semaphore for maximum speed. */ -typedef struct fastmutex { - sem_id sem; - atomic_t count; -} fastmutex_t; - - -static int fastmutex_create(const char *name, fastmutex_t * mutex); -static int fastmutex_destroy(fastmutex_t * mutex); -static int fastmutex_lock(fastmutex_t * mutex); -static int fastmutex_timedlock(fastmutex_t * mutex, bigtime_t timeout); -static int fastmutex_unlock(fastmutex_t * mutex); - - -static int fastmutex_create(const char *name, fastmutex_t * mutex) -{ - mutex->count = 0; - mutex->sem = create_semaphore(name, 0, 0); - return (mutex->sem < 0) ? -1 : 0; -} - - -static int fastmutex_destroy(fastmutex_t * mutex) -{ - if (fastmutex_timedlock(mutex, 0) == 0 || errno == EWOULDBLOCK) { - return delete_semaphore(mutex->sem); - } - return 0; -} - - -static int fastmutex_lock(fastmutex_t * mutex) -{ - atomic_t prev = atomic_add(&mutex->count, 1); - if (prev > 0) - return lock_semaphore(mutex->sem); - return 0; -} - - -static int fastmutex_timedlock(fastmutex_t * mutex, bigtime_t timeout) -{ - atomic_t prev = atomic_add(&mutex->count, 1); - if (prev > 0) - return lock_semaphore_x(mutex->sem, 1, 0, timeout); - return 0; -} - - -static int fastmutex_unlock(fastmutex_t * mutex) -{ - atomic_t prev = atomic_add(&mutex->count, -1); - if (prev > 1) - return unlock_semaphore(mutex->sem); - return 0; -} - - -#endif /* FASTLOCK */ - - -/* - * Initialization. - * - */ -static void PyThread__init_thread(void) -{ - /* Do nothing. */ - return; -} - - -/* - * Thread support. - * - */ - -static atomic_t thread_count = 0; - -long PyThread_start_new_thread(void (*func) (void *), void *arg) -{ - status_t success = -1; - thread_id tid; - char name[OS_NAME_LENGTH]; - atomic_t this_thread; - - dprintf(("PyThread_start_new_thread called\n")); - - this_thread = atomic_add(&thread_count, 1); - PyOS_snprintf(name, sizeof(name), "python thread (%d)", this_thread); - - tid = spawn_thread(name, func, NORMAL_PRIORITY, 0, arg); - if (tid < 0) { - dprintf(("PyThread_start_new_thread spawn_thread failed: %s\n", strerror(errno))); - } else { - success = resume_thread(tid); - if (success < 0) { - dprintf(("PyThread_start_new_thread resume_thread failed: %s\n", strerror(errno))); - } - } - - return (success < 0 ? -1 : tid); -} - - -long PyThread_get_thread_ident(void) -{ - return get_thread_id(NULL); -} - - -static void do_PyThread_exit_thread(int no_cleanup) -{ - dprintf(("PyThread_exit_thread called\n")); - - /* Thread-safe way to read a variable without a mutex: */ - if (atomic_add(&thread_count, 0) == 0) { - /* No threads around, so exit main(). */ - if (no_cleanup) - _exit(0); - else - exit(0); - } else { - /* We're a thread */ - exit_thread(0); - } -} - - -void PyThread_exit_thread(void) -{ - do_PyThread_exit_thread(0); -} - - -void PyThread__exit_thread(void) -{ - do_PyThread_exit_thread(1); -} - - -#ifndef NO_EXIT_PROG -static void do_PyThread_exit_prog(int status, int no_cleanup) -{ - dprintf(("PyThread_exit_prog(%d) called\n", status)); - - /* No need to do anything, the threads get torn down if main()exits. */ - if (no_cleanup) - _exit(status); - else - exit(status); -} - - -void PyThread_exit_prog(int status) -{ - do_PyThread_exit_prog(status, 0); -} - - -void PyThread__exit_prog(int status) -{ - do_PyThread_exit_prog(status, 1); -} -#endif /* NO_EXIT_PROG */ - - -/* - * Lock support. - * - */ - -static atomic_t lock_count = 0; - -PyThread_type_lock PyThread_allocate_lock(void) -{ -#ifdef FASTLOCK - fastmutex_t *lock; -#else - sem_id sema; -#endif - char name[OS_NAME_LENGTH]; - atomic_t this_lock; - - dprintf(("PyThread_allocate_lock called\n")); - -#ifdef FASTLOCK - lock = (fastmutex_t *) malloc(sizeof(fastmutex_t)); - if (lock == NULL) { - dprintf(("PyThread_allocate_lock failed: out of memory\n")); - return (PyThread_type_lock) NULL; - } -#endif - this_lock = atomic_add(&lock_count, 1); - PyOS_snprintf(name, sizeof(name), "python lock (%d)", this_lock); - -#ifdef FASTLOCK - if (fastmutex_create(name, lock) < 0) { - dprintf(("PyThread_allocate_lock failed: %s\n", - strerror(errno))); - free(lock); - lock = NULL; - } - dprintf(("PyThread_allocate_lock()-> %p\n", lock)); - return (PyThread_type_lock) lock; -#else - sema = create_semaphore(name, 1, 0); - if (sema < 0) { - dprintf(("PyThread_allocate_lock failed: %s\n", - strerror(errno))); - sema = 0; - } - dprintf(("PyThread_allocate_lock()-> %p\n", sema)); - return (PyThread_type_lock) sema; -#endif -} - - -void PyThread_free_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_free_lock(%p) called\n", lock)); - -#ifdef FASTLOCK - if (fastmutex_destroy((fastmutex_t *) lock) < 0) { - dprintf(("PyThread_free_lock(%p) failed: %s\n", lock, - strerror(errno))); - } - free(lock); -#else - if (delete_semaphore((sem_id) lock) < 0) { - dprintf(("PyThread_free_lock(%p) failed: %s\n", lock, - strerror(errno))); - } -#endif -} - - -int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - int retval; - - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, - waitflag)); - -#ifdef FASTLOCK - if (waitflag) - retval = fastmutex_lock((fastmutex_t *) lock); - else - retval = fastmutex_timedlock((fastmutex_t *) lock, 0); -#else - if (waitflag) - retval = lock_semaphore((sem_id) lock); - else - retval = lock_semaphore_x((sem_id) lock, 1, 0, 0); -#endif - if (retval < 0) { - dprintf(("PyThread_acquire_lock(%p, %d) failed: %s\n", - lock, waitflag, strerror(errno))); - } - dprintf(("PyThread_acquire_lock(%p, %d)-> %d\n", lock, waitflag, - retval)); - return retval < 0 ? 0 : 1; -} - - -void PyThread_release_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_release_lock(%p) called\n", lock)); - -#ifdef FASTLOCK - if (fastmutex_unlock((fastmutex_t *) lock) < 0) { - dprintf(("PyThread_release_lock(%p) failed: %s\n", lock, - strerror(errno))); - } -#else - if (unlock_semaphore((sem_id) lock) < 0) { - dprintf(("PyThread_release_lock(%p) failed: %s\n", lock, - strerror(errno))); - } -#endif -} diff --git a/sys/src/cmd/python/Python/thread_beos.h b/sys/src/cmd/python/Python/thread_beos.h deleted file mode 100644 index 82f99ded3..000000000 --- a/sys/src/cmd/python/Python/thread_beos.h +++ /dev/null @@ -1,287 +0,0 @@ -#include <kernel/OS.h> -#include <support/SupportDefs.h> -#include <errno.h> - -/* ---------------------------------------------------------------------- - * Fast locking mechanism described by Benoit Schillings (benoit@be.com) - * in the Be Developer's Newsletter, Issue #26 (http://www.be.com/). - */ -typedef struct benaphore { - sem_id _sem; - int32 _atom; -} benaphore_t; - -static status_t benaphore_create( const char *name, benaphore_t *ben ); -static status_t benaphore_destroy( benaphore_t *ben ); -static status_t benaphore_lock( benaphore_t *ben ); -static status_t benaphore_timedlock( benaphore_t *ben, bigtime_t micros ); -static status_t benaphore_unlock( benaphore_t *ben ); - -static status_t benaphore_create( const char *name, benaphore_t *ben ) -{ - if( ben != NULL ) { - ben->_atom = 0; - ben->_sem = create_sem( 0, name ); - - if( ben->_sem < B_NO_ERROR ) { - return B_BAD_SEM_ID; - } - } else { - return EFAULT; - } - - return EOK; -} - -static status_t benaphore_destroy( benaphore_t *ben ) -{ - if( ben->_sem >= B_NO_ERROR ) { - status_t retval = benaphore_timedlock( ben, 0 ); - - if( retval == EOK || retval == EWOULDBLOCK ) { - status_t del_retval = delete_sem( ben->_sem ); - - return del_retval; - } - } - - return B_BAD_SEM_ID; -} - -static status_t benaphore_lock( benaphore_t *ben ) -{ - int32 prev = atomic_add( &(ben->_atom), 1 ); - - if( prev > 0 ) { - return acquire_sem( ben->_sem ); - } - - return EOK; -} - -static status_t benaphore_timedlock( benaphore_t *ben, bigtime_t micros ) -{ - int32 prev = atomic_add( &(ben->_atom), 1 ); - - if( prev > 0 ) { - status_t retval = acquire_sem_etc( ben->_sem, 1, B_TIMEOUT, micros ); - - switch( retval ) { - case B_WOULD_BLOCK: /* Fall through... */ - case B_TIMED_OUT: - return EWOULDBLOCK; - break; - case B_OK: - return EOK; - break; - default: - return retval; - break; - } - } - - return EOK; -} - -static status_t benaphore_unlock( benaphore_t *ben ) -{ - int32 prev = atomic_add( &(ben->_atom), -1 ); - - if( prev > 1 ) { - return release_sem( ben->_sem ); - } - - return EOK; -} - -/* ---------------------------------------------------------------------- - * Initialization. - */ -static void PyThread__init_thread( void ) -{ - /* Do nothing. */ - return; -} - -/* ---------------------------------------------------------------------- - * Thread support. - * - * Only ANSI C, renamed functions here; you can't use K&R on BeOS, - * and there's no legacy thread module to support. - */ - -static int32 thread_count = 0; - -long PyThread_start_new_thread( void (*func)(void *), void *arg ) -{ - status_t success = 0; - thread_id tid; - char name[B_OS_NAME_LENGTH]; - int32 this_thread; - - dprintf(("PyThread_start_new_thread called\n")); - - /* We are so very thread-safe... */ - this_thread = atomic_add( &thread_count, 1 ); - PyOS_snprintf(name, sizeof(name), - "python thread (%d)", this_thread ); - - tid = spawn_thread( (thread_func)func, name, - B_NORMAL_PRIORITY, arg ); - if( tid > B_NO_ERROR ) { - success = resume_thread( tid ); - } - - return ( success == B_NO_ERROR ? tid : -1 ); -} - -long PyThread_get_thread_ident( void ) -{ - /* Presumed to return the current thread's ID... */ - thread_id tid; - tid = find_thread( NULL ); - - return ( tid != B_NAME_NOT_FOUND ? tid : -1 ); -} - -static void do_PyThread_exit_thread( int no_cleanup ) -{ - int32 threads; - - dprintf(("PyThread_exit_thread called\n")); - - /* Thread-safe way to read a variable without a mutex: */ - threads = atomic_add( &thread_count, 0 ); - - if( threads == 0 ) { - /* No threads around, so exit main(). */ - if( no_cleanup ) { - _exit(0); - } else { - exit(0); - } - } else { - /* Oh, we're a thread, let's try to exit gracefully... */ - exit_thread( B_NO_ERROR ); - } -} - -void PyThread_exit_thread( void ) -{ - do_PyThread_exit_thread(0); -} - -void PyThread__exit_thread( void ) -{ - do_PyThread_exit_thread(1); -} - -#ifndef NO_EXIT_PROG -static void do_PyThread_exit_prog( int status, int no_cleanup ) -{ - dprintf(("PyThread_exit_prog(%d) called\n", status)); - - /* No need to do anything, the threads get torn down if main() exits. */ - - if (no_cleanup) { - _exit(status); - } else { - exit(status); - } -} - -void PyThread_exit_prog( int status ) -{ - do_PyThread_exit_prog(status, 0); -} - -void PyThread__exit_prog( int status ) -{ - do_PyThread_exit_prog(status, 1); -} -#endif /* NO_EXIT_PROG */ - -/* ---------------------------------------------------------------------- - * Lock support. - */ - -static int32 lock_count = 0; - -PyThread_type_lock PyThread_allocate_lock( void ) -{ - benaphore_t *lock; - status_t retval; - char name[B_OS_NAME_LENGTH]; - int32 this_lock; - - dprintf(("PyThread_allocate_lock called\n")); - - lock = (benaphore_t *)malloc( sizeof( benaphore_t ) ); - if( lock == NULL ) { - /* TODO: that's bad, raise MemoryError */ - return (PyThread_type_lock)NULL; - } - - this_lock = atomic_add( &lock_count, 1 ); - PyOS_snprintf(name, sizeof(name), "python lock (%d)", this_lock); - - retval = benaphore_create( name, lock ); - if( retval != EOK ) { - /* TODO: that's bad, raise an exception */ - return (PyThread_type_lock)NULL; - } - - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock) lock; -} - -void PyThread_free_lock( PyThread_type_lock lock ) -{ - status_t retval; - - dprintf(("PyThread_free_lock(%p) called\n", lock)); - - retval = benaphore_destroy( (benaphore_t *)lock ); - if( retval != EOK ) { - /* TODO: that's bad, raise an exception */ - return; - } -} - -int PyThread_acquire_lock( PyThread_type_lock lock, int waitflag ) -{ - int success; - status_t retval; - - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - - if( waitflag ) { - retval = benaphore_lock( (benaphore_t *)lock ); - } else { - retval = benaphore_timedlock( (benaphore_t *)lock, 0 ); - } - - if( retval == EOK ) { - success = 1; - } else { - success = 0; - - /* TODO: that's bad, raise an exception */ - } - - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; -} - -void PyThread_release_lock( PyThread_type_lock lock ) -{ - status_t retval; - - dprintf(("PyThread_release_lock(%p) called\n", lock)); - - retval = benaphore_unlock( (benaphore_t *)lock ); - if( retval != EOK ) { - /* TODO: that's bad, raise an exception */ - return; - } -} diff --git a/sys/src/cmd/python/Python/thread_cthread.h b/sys/src/cmd/python/Python/thread_cthread.h deleted file mode 100644 index ca776c636..000000000 --- a/sys/src/cmd/python/Python/thread_cthread.h +++ /dev/null @@ -1,156 +0,0 @@ - -#ifdef MACH_C_THREADS -#include <mach/cthreads.h> -#endif - -#ifdef HURD_C_THREADS -#include <cthreads.h> -#endif - -/* - * Initialization. - */ -static void -PyThread__init_thread(void) -{ -#ifndef HURD_C_THREADS - /* Roland McGrath said this should not be used since this is - done while linking to threads */ - cthread_init(); -#else -/* do nothing */ - ; -#endif -} - -/* - * Thread support. - */ -long -PyThread_start_new_thread(void (*func)(void *), void *arg) -{ - int success = 0; /* init not needed when SOLARIS_THREADS and */ - /* C_THREADS implemented properly */ - - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); - /* looks like solaris detaches the thread to never rejoin - * so well do it here - */ - cthread_detach(cthread_fork((cthread_fn_t) func, arg)); - return success < 0 ? -1 : 0; -} - -long -PyThread_get_thread_ident(void) -{ - if (!initialized) - PyThread_init_thread(); - return (long) cthread_self(); -} - -static void -do_PyThread_exit_thread(int no_cleanup) -{ - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) - if (no_cleanup) - _exit(0); - else - exit(0); - cthread_exit(0); -} - -void -PyThread_exit_thread(void) -{ - do_PyThread_exit_thread(0); -} - -void -PyThread__exit_thread(void) -{ - do_PyThread_exit_thread(1); -} - -#ifndef NO_EXIT_PROG -static -void do_PyThread_exit_prog(int status, int no_cleanup) -{ - dprintf(("PyThread_exit_prog(%d) called\n", status)); - if (!initialized) - if (no_cleanup) - _exit(status); - else - exit(status); - if (no_cleanup) - _exit(status); - else - exit(status); -} - -void -PyThread_exit_prog(int status) -{ - do_PyThread_exit_prog(status, 0); -} - -void -PyThread__exit_prog(int status) -{ - do_PyThread_exit_prog(status, 1); -} -#endif /* NO_EXIT_PROG */ - -/* - * Lock support. - */ -PyThread_type_lock -PyThread_allocate_lock(void) -{ - mutex_t lock; - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - lock = mutex_alloc(); - if (mutex_init(lock)) { - perror("mutex_init"); - free((void *) lock); - lock = 0; - } - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock) lock; -} - -void -PyThread_free_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_free_lock(%p) called\n", lock)); - mutex_free(lock); -} - -int -PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - int success = FALSE; - - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - if (waitflag) { /* blocking */ - mutex_lock((mutex_t)lock); - success = TRUE; - } else { /* non blocking */ - success = mutex_try_lock((mutex_t)lock); - } - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; -} - -void -PyThread_release_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_release_lock(%p) called\n", lock)); - mutex_unlock((mutex_t )lock); -} diff --git a/sys/src/cmd/python/Python/thread_foobar.h b/sys/src/cmd/python/Python/thread_foobar.h deleted file mode 100644 index 67491a167..000000000 --- a/sys/src/cmd/python/Python/thread_foobar.h +++ /dev/null @@ -1,115 +0,0 @@ - -/* - * Initialization. - */ -static void -PyThread__init_thread(void) -{ -} - -/* - * Thread support. - */ -long -PyThread_start_new_thread(void (*func)(void *), void *arg) -{ - int success = 0; /* init not needed when SOLARIS_THREADS and */ - /* C_THREADS implemented properly */ - - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); - return success < 0 ? -1 : 0; -} - -long -PyThread_get_thread_ident(void) -{ - if (!initialized) - PyThread_init_thread(); -} - -static -void do_PyThread_exit_thread(int no_cleanup) -{ - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) - if (no_cleanup) - _exit(0); - else - exit(0); -} - -void -PyThread_exit_thread(void) -{ - do_PyThread_exit_thread(0); -} - -void -PyThread__exit_thread(void) -{ - do_PyThread_exit_thread(1); -} - -#ifndef NO_EXIT_PROG -static -void do_PyThread_exit_prog(int status, int no_cleanup) -{ - dprintf(("PyThread_exit_prog(%d) called\n", status)); - if (!initialized) - if (no_cleanup) - _exit(status); - else - exit(status); -} - -void -PyThread_exit_prog(int status) -{ - do_PyThread_exit_prog(status, 0); -} - -void -PyThread__exit_prog(int status) -{ - do_PyThread_exit_prog(status, 1); -} -#endif /* NO_EXIT_PROG */ - -/* - * Lock support. - */ -PyThread_type_lock -PyThread_allocate_lock(void) -{ - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock) lock; -} - -void -PyThread_free_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_free_lock(%p) called\n", lock)); -} - -int -PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - int success; - - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; -} - -void -PyThread_release_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_release_lock(%p) called\n", lock)); -} diff --git a/sys/src/cmd/python/Python/thread_lwp.h b/sys/src/cmd/python/Python/thread_lwp.h deleted file mode 100644 index e93d65aa3..000000000 --- a/sys/src/cmd/python/Python/thread_lwp.h +++ /dev/null @@ -1,149 +0,0 @@ - -#include <stdlib.h> -#include <lwp/lwp.h> -#include <lwp/stackdep.h> - -#define STACKSIZE 1000 /* stacksize for a thread */ -#define NSTACKS 2 /* # stacks to be put in cache initially */ - -struct lock { - int lock_locked; - cv_t lock_condvar; - mon_t lock_monitor; -}; - - -/* - * Initialization. - */ -static void PyThread__init_thread(void) -{ - lwp_setstkcache(STACKSIZE, NSTACKS); -} - -/* - * Thread support. - */ - - -long PyThread_start_new_thread(void (*func)(void *), void *arg) -{ - thread_t tid; - int success; - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); - success = lwp_create(&tid, func, MINPRIO, 0, lwp_newstk(), 1, arg); - return success < 0 ? -1 : 0; -} - -long PyThread_get_thread_ident(void) -{ - thread_t tid; - if (!initialized) - PyThread_init_thread(); - if (lwp_self(&tid) < 0) - return -1; - return tid.thread_id; -} - -static void do_PyThread_exit_thread(int no_cleanup) -{ - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) - if (no_cleanup) - _exit(0); - else - exit(0); - lwp_destroy(SELF); -} - -void PyThread_exit_thread(void) -{ - do_PyThread_exit_thread(0); -} - -void PyThread__exit_thread(void) -{ - do_PyThread_exit_thread(1); -} - -#ifndef NO_EXIT_PROG -static void do_PyThread_exit_prog(int status, int no_cleanup) -{ - dprintf(("PyThread_exit_prog(%d) called\n", status)); - if (!initialized) - if (no_cleanup) - _exit(status); - else - exit(status); - pod_exit(status); -} - -void PyThread_exit_prog(int status) -{ - do_PyThread_exit_prog(status, 0); -} - -void PyThread__exit_prog(int status) -{ - do_PyThread_exit_prog(status, 1); -} -#endif /* NO_EXIT_PROG */ - -/* - * Lock support. - */ -PyThread_type_lock PyThread_allocate_lock(void) -{ - struct lock *lock; - extern char *malloc(size_t); - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - lock = (struct lock *) malloc(sizeof(struct lock)); - lock->lock_locked = 0; - (void) mon_create(&lock->lock_monitor); - (void) cv_create(&lock->lock_condvar, lock->lock_monitor); - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock) lock; -} - -void PyThread_free_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_free_lock(%p) called\n", lock)); - mon_destroy(((struct lock *) lock)->lock_monitor); - free((char *) lock); -} - -int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - int success; - - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - success = 0; - - (void) mon_enter(((struct lock *) lock)->lock_monitor); - if (waitflag) - while (((struct lock *) lock)->lock_locked) - cv_wait(((struct lock *) lock)->lock_condvar); - if (!((struct lock *) lock)->lock_locked) { - success = 1; - ((struct lock *) lock)->lock_locked = 1; - } - cv_broadcast(((struct lock *) lock)->lock_condvar); - mon_exit(((struct lock *) lock)->lock_monitor); - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; -} - -void PyThread_release_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_release_lock(%p) called\n", lock)); - (void) mon_enter(((struct lock *) lock)->lock_monitor); - ((struct lock *) lock)->lock_locked = 0; - cv_broadcast(((struct lock *) lock)->lock_condvar); - mon_exit(((struct lock *) lock)->lock_monitor); -} diff --git a/sys/src/cmd/python/Python/thread_nt.h b/sys/src/cmd/python/Python/thread_nt.h deleted file mode 100644 index 67f5ed517..000000000 --- a/sys/src/cmd/python/Python/thread_nt.h +++ /dev/null @@ -1,364 +0,0 @@ - -/* This code implemented by Dag.Gruneau@elsa.preseco.comm.se */ -/* Fast NonRecursiveMutex support by Yakov Markovitch, markovitch@iso.ru */ -/* Eliminated some memory leaks, gsw@agere.com */ - -#include <windows.h> -#include <limits.h> -#ifdef HAVE_PROCESS_H -#include <process.h> -#endif - -typedef struct NRMUTEX { - LONG owned ; - DWORD thread_id ; - HANDLE hevent ; -} NRMUTEX, *PNRMUTEX ; - -typedef PVOID WINAPI interlocked_cmp_xchg_t(PVOID *dest, PVOID exc, PVOID comperand) ; - -/* Sorry mate, but we haven't got InterlockedCompareExchange in Win95! */ -static PVOID WINAPI -interlocked_cmp_xchg(PVOID *dest, PVOID exc, PVOID comperand) -{ - static LONG spinlock = 0 ; - PVOID result ; - DWORD dwSleep = 0; - - /* Acqire spinlock (yielding control to other threads if cant aquire for the moment) */ - while(InterlockedExchange(&spinlock, 1)) - { - // Using Sleep(0) can cause a priority inversion. - // Sleep(0) only yields the processor if there's - // another thread of the same priority that's - // ready to run. If a high-priority thread is - // trying to acquire the lock, which is held by - // a low-priority thread, then the low-priority - // thread may never get scheduled and hence never - // free the lock. NT attempts to avoid priority - // inversions by temporarily boosting the priority - // of low-priority runnable threads, but the problem - // can still occur if there's a medium-priority - // thread that's always runnable. If Sleep(1) is used, - // then the thread unconditionally yields the CPU. We - // only do this for the second and subsequent even - // iterations, since a millisecond is a long time to wait - // if the thread can be scheduled in again sooner - // (~100,000 instructions). - // Avoid priority inversion: 0, 1, 0, 1,... - Sleep(dwSleep); - dwSleep = !dwSleep; - } - result = *dest ; - if (result == comperand) - *dest = exc ; - /* Release spinlock */ - spinlock = 0 ; - return result ; -} ; - -static interlocked_cmp_xchg_t *ixchg; - -BOOL -InitializeNonRecursiveMutex(PNRMUTEX mutex) -{ - if (!ixchg) - { - /* Sorely, Win95 has no InterlockedCompareExchange API (Win98 has), so we have to use emulation */ - HANDLE kernel = GetModuleHandle("kernel32.dll") ; - if (!kernel || (ixchg = (interlocked_cmp_xchg_t *)GetProcAddress(kernel, "InterlockedCompareExchange")) == NULL) - ixchg = interlocked_cmp_xchg ; - } - - mutex->owned = -1 ; /* No threads have entered NonRecursiveMutex */ - mutex->thread_id = 0 ; - mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ; - return mutex->hevent != NULL ; /* TRUE if the mutex is created */ -} - -#ifdef InterlockedCompareExchange -#undef InterlockedCompareExchange -#endif -#define InterlockedCompareExchange(dest,exchange,comperand) (ixchg((dest), (exchange), (comperand))) - -VOID -DeleteNonRecursiveMutex(PNRMUTEX mutex) -{ - /* No in-use check */ - CloseHandle(mutex->hevent) ; - mutex->hevent = NULL ; /* Just in case */ -} - -DWORD -EnterNonRecursiveMutex(PNRMUTEX mutex, BOOL wait) -{ - /* Assume that the thread waits successfully */ - DWORD ret ; - - /* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */ - if (!wait) - { - if (InterlockedCompareExchange((PVOID *)&mutex->owned, (PVOID)0, (PVOID)-1) != (PVOID)-1) - return WAIT_TIMEOUT ; - ret = WAIT_OBJECT_0 ; - } - else - ret = InterlockedIncrement(&mutex->owned) ? - /* Some thread owns the mutex, let's wait... */ - WaitForSingleObject(mutex->hevent, INFINITE) : WAIT_OBJECT_0 ; - - mutex->thread_id = GetCurrentThreadId() ; /* We own it */ - return ret ; -} - -BOOL -LeaveNonRecursiveMutex(PNRMUTEX mutex) -{ - /* We don't own the mutex */ - mutex->thread_id = 0 ; - return - InterlockedDecrement(&mutex->owned) < 0 || - SetEvent(mutex->hevent) ; /* Other threads are waiting, wake one on them up */ -} - -PNRMUTEX -AllocNonRecursiveMutex(void) -{ - PNRMUTEX mutex = (PNRMUTEX)malloc(sizeof(NRMUTEX)) ; - if (mutex && !InitializeNonRecursiveMutex(mutex)) - { - free(mutex) ; - mutex = NULL ; - } - return mutex ; -} - -void -FreeNonRecursiveMutex(PNRMUTEX mutex) -{ - if (mutex) - { - DeleteNonRecursiveMutex(mutex) ; - free(mutex) ; - } -} - -long PyThread_get_thread_ident(void); - -/* - * Initialization of the C package, should not be needed. - */ -static void -PyThread__init_thread(void) -{ -} - -/* - * Thread support. - */ - -typedef struct { - void (*func)(void*); - void *arg; - long id; - HANDLE done; -} callobj; - -static int -bootstrap(void *call) -{ - callobj *obj = (callobj*)call; - /* copy callobj since other thread might free it before we're done */ - void (*func)(void*) = obj->func; - void *arg = obj->arg; - - obj->id = PyThread_get_thread_ident(); - ReleaseSemaphore(obj->done, 1, NULL); - func(arg); - return 0; -} - -long -PyThread_start_new_thread(void (*func)(void *), void *arg) -{ - Py_uintptr_t rv; - callobj obj; - - dprintf(("%ld: PyThread_start_new_thread called\n", - PyThread_get_thread_ident())); - if (!initialized) - PyThread_init_thread(); - - obj.id = -1; /* guilty until proved innocent */ - obj.func = func; - obj.arg = arg; - obj.done = CreateSemaphore(NULL, 0, 1, NULL); - if (obj.done == NULL) - return -1; - - rv = _beginthread(bootstrap, _pythread_stacksize, &obj); - if (rv == (Py_uintptr_t)-1) { - /* I've seen errno == EAGAIN here, which means "there are - * too many threads". - */ - dprintf(("%ld: PyThread_start_new_thread failed: %p errno %d\n", - PyThread_get_thread_ident(), rv, errno)); - obj.id = -1; - } - else { - dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n", - PyThread_get_thread_ident(), rv)); - /* wait for thread to initialize, so we can get its id */ - WaitForSingleObject(obj.done, INFINITE); - assert(obj.id != -1); - } - CloseHandle((HANDLE)obj.done); - return obj.id; -} - -/* - * Return the thread Id instead of an handle. The Id is said to uniquely identify the - * thread in the system - */ -long -PyThread_get_thread_ident(void) -{ - if (!initialized) - PyThread_init_thread(); - - return GetCurrentThreadId(); -} - -static void -do_PyThread_exit_thread(int no_cleanup) -{ - dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident())); - if (!initialized) - if (no_cleanup) - _exit(0); - else - exit(0); - _endthread(); -} - -void -PyThread_exit_thread(void) -{ - do_PyThread_exit_thread(0); -} - -void -PyThread__exit_thread(void) -{ - do_PyThread_exit_thread(1); -} - -#ifndef NO_EXIT_PROG -static void -do_PyThread_exit_prog(int status, int no_cleanup) -{ - dprintf(("PyThread_exit_prog(%d) called\n", status)); - if (!initialized) - if (no_cleanup) - _exit(status); - else - exit(status); -} - -void -PyThread_exit_prog(int status) -{ - do_PyThread_exit_prog(status, 0); -} - -void -PyThread__exit_prog(int status) -{ - do_PyThread_exit_prog(status, 1); -} -#endif /* NO_EXIT_PROG */ - -/* - * Lock support. It has too be implemented as semaphores. - * I [Dag] tried to implement it with mutex but I could find a way to - * tell whether a thread already own the lock or not. - */ -PyThread_type_lock -PyThread_allocate_lock(void) -{ - PNRMUTEX aLock; - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - aLock = AllocNonRecursiveMutex() ; - - dprintf(("%ld: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock)); - - return (PyThread_type_lock) aLock; -} - -void -PyThread_free_lock(PyThread_type_lock aLock) -{ - dprintf(("%ld: PyThread_free_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); - - FreeNonRecursiveMutex(aLock) ; -} - -/* - * Return 1 on success if the lock was acquired - * - * and 0 if the lock was not acquired. This means a 0 is returned - * if the lock has already been acquired by this thread! - */ -int -PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag) -{ - int success ; - - dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", PyThread_get_thread_ident(),aLock, waitflag)); - - success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (waitflag ? INFINITE : 0)) == WAIT_OBJECT_0 ; - - dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n", PyThread_get_thread_ident(),aLock, waitflag, success)); - - return success; -} - -void -PyThread_release_lock(PyThread_type_lock aLock) -{ - dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); - - if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock))) - dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", PyThread_get_thread_ident(), aLock, GetLastError())); -} - -/* minimum/maximum thread stack sizes supported */ -#define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */ -#define THREAD_MAX_STACKSIZE 0x10000000 /* 256MB */ - -/* set the thread stack size. - * Return 0 if size is valid, -1 otherwise. - */ -static int -_pythread_nt_set_stacksize(size_t size) -{ - /* set to default */ - if (size == 0) { - _pythread_stacksize = 0; - return 0; - } - - /* valid range? */ - if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) { - _pythread_stacksize = size; - return 0; - } - - return -1; -} - -#define THREAD_SET_STACKSIZE(x) _pythread_nt_set_stacksize(x) diff --git a/sys/src/cmd/python/Python/thread_os2.h b/sys/src/cmd/python/Python/thread_os2.h deleted file mode 100644 index 12eeed51c..000000000 --- a/sys/src/cmd/python/Python/thread_os2.h +++ /dev/null @@ -1,307 +0,0 @@ -/* This code implemented by cvale@netcom.com */ - -#define INCL_DOSPROCESS -#define INCL_DOSSEMAPHORES -#include "os2.h" -#include "limits.h" - -#include "process.h" - -#if defined(PYCC_GCC) -#include <sys/builtin.h> -#include <sys/fmutex.h> -#else -long PyThread_get_thread_ident(void); -#endif - -/* default thread stack size of 64kB */ -#if !defined(THREAD_STACK_SIZE) -#define THREAD_STACK_SIZE 0x10000 -#endif - -#define OS2_STACKSIZE(x) (x ? x : THREAD_STACK_SIZE) - -/* - * Initialization of the C package, should not be needed. - */ -static void -PyThread__init_thread(void) -{ -} - -/* - * Thread support. - */ -long -PyThread_start_new_thread(void (*func)(void *), void *arg) -{ - int thread_id; - - thread_id = _beginthread(func, - NULL, - OS2_STACKSIZE(_pythread_stacksize), - arg); - - if (thread_id == -1) { - dprintf(("_beginthread failed. return %ld\n", errno)); - } - - return thread_id; -} - -long -PyThread_get_thread_ident(void) -{ -#if !defined(PYCC_GCC) - PPIB pib; - PTIB tib; -#endif - - if (!initialized) - PyThread_init_thread(); - -#if defined(PYCC_GCC) - return _gettid(); -#else - DosGetInfoBlocks(&tib, &pib); - return tib->tib_ptib2->tib2_ultid; -#endif -} - -static void -do_PyThread_exit_thread(int no_cleanup) -{ - dprintf(("%ld: PyThread_exit_thread called\n", - PyThread_get_thread_ident())); - if (!initialized) - if (no_cleanup) - _exit(0); - else - exit(0); - _endthread(); -} - -void -PyThread_exit_thread(void) -{ - do_PyThread_exit_thread(0); -} - -void -PyThread__exit_thread(void) -{ - do_PyThread_exit_thread(1); -} - -#ifndef NO_EXIT_PROG -static void -do_PyThread_exit_prog(int status, int no_cleanup) -{ - dprintf(("PyThread_exit_prog(%d) called\n", status)); - if (!initialized) - if (no_cleanup) - _exit(status); - else - exit(status); -} - -void -PyThread_exit_prog(int status) -{ - do_PyThread_exit_prog(status, 0); -} - -void -PyThread__exit_prog(int status) -{ - do_PyThread_exit_prog(status, 1); -} -#endif /* NO_EXIT_PROG */ - -/* - * Lock support. This is implemented with an event semaphore and critical - * sections to make it behave more like a posix mutex than its OS/2 - * counterparts. - */ - -typedef struct os2_lock_t { - int is_set; - HEV changed; -} *type_os2_lock; - -PyThread_type_lock -PyThread_allocate_lock(void) -{ -#if defined(PYCC_GCC) - _fmutex *sem = malloc(sizeof(_fmutex)); - if (!initialized) - PyThread_init_thread(); - dprintf(("%ld: PyThread_allocate_lock() -> %lx\n", - PyThread_get_thread_ident(), - (long)sem)); - if (_fmutex_create(sem, 0)) { - free(sem); - sem = NULL; - } - return (PyThread_type_lock)sem; -#else - APIRET rc; - type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t)); - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - lock->is_set = 0; - - DosCreateEventSem(NULL, &lock->changed, 0, 0); - - dprintf(("%ld: PyThread_allocate_lock() -> %p\n", - PyThread_get_thread_ident(), - lock->changed)); - - return (PyThread_type_lock)lock; -#endif -} - -void -PyThread_free_lock(PyThread_type_lock aLock) -{ -#if !defined(PYCC_GCC) - type_os2_lock lock = (type_os2_lock)aLock; -#endif - - dprintf(("%ld: PyThread_free_lock(%p) called\n", - PyThread_get_thread_ident(),aLock)); - -#if defined(PYCC_GCC) - if (aLock) { - _fmutex_close((_fmutex *)aLock); - free((_fmutex *)aLock); - } -#else - DosCloseEventSem(lock->changed); - free(aLock); -#endif -} - -/* - * Return 1 on success if the lock was acquired - * - * and 0 if the lock was not acquired. - */ -int -PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag) -{ -#if !defined(PYCC_GCC) - int done = 0; - ULONG count; - PID pid = 0; - TID tid = 0; - type_os2_lock lock = (type_os2_lock)aLock; -#endif - - dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", - PyThread_get_thread_ident(), - aLock, - waitflag)); - -#if defined(PYCC_GCC) - /* always successful if the lock doesn't exist */ - if (aLock && - _fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT)) - return 0; -#else - while (!done) { - /* if the lock is currently set, we have to wait for - * the state to change - */ - if (lock->is_set) { - if (!waitflag) - return 0; - DosWaitEventSem(lock->changed, SEM_INDEFINITE_WAIT); - } - - /* enter a critical section and try to get the semaphore. If - * it is still locked, we will try again. - */ - if (DosEnterCritSec()) - return 0; - - if (!lock->is_set) { - lock->is_set = 1; - DosResetEventSem(lock->changed, &count); - done = 1; - } - - DosExitCritSec(); - } -#endif - - return 1; -} - -void -PyThread_release_lock(PyThread_type_lock aLock) -{ -#if !defined(PYCC_GCC) - type_os2_lock lock = (type_os2_lock)aLock; -#endif - - dprintf(("%ld: PyThread_release_lock(%p) called\n", - PyThread_get_thread_ident(), - aLock)); - -#if defined(PYCC_GCC) - if (aLock) - _fmutex_release((_fmutex *)aLock); -#else - if (!lock->is_set) { - dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", - PyThread_get_thread_ident(), - aLock, - GetLastError())); - return; - } - - if (DosEnterCritSec()) { - dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", - PyThread_get_thread_ident(), - aLock, - GetLastError())); - return; - } - - lock->is_set = 0; - DosPostEventSem(lock->changed); - - DosExitCritSec(); -#endif -} - -/* minimum/maximum thread stack sizes supported */ -#define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */ -#define THREAD_MAX_STACKSIZE 0x2000000 /* 32MB */ - -/* set the thread stack size. - * Return 0 if size is valid, -1 otherwise. - */ -static int -_pythread_os2_set_stacksize(size_t size) -{ - /* set to default */ - if (size == 0) { - _pythread_stacksize = 0; - return 0; - } - - /* valid range? */ - if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) { - _pythread_stacksize = size; - return 0; - } - - return -1; -} - -#define THREAD_SET_STACKSIZE(x) _pythread_os2_set_stacksize(x) diff --git a/sys/src/cmd/python/Python/thread_plan9.h b/sys/src/cmd/python/Python/thread_plan9.h deleted file mode 100644 index d0504806e..000000000 --- a/sys/src/cmd/python/Python/thread_plan9.h +++ /dev/null @@ -1,135 +0,0 @@ -#define _PLAN9_SOURCE -#include <u.h> -#include <lib9.h> -#include <qlock.h> - -/* - * Initialization. - */ -static void -PyThread__init_thread(void) -{ -} - -/* - * Thread support. - */ -long -PyThread_start_new_thread(void (*func)(void *), void *arg) -{ - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); - switch(rfork(RFPROC|RFMEM)){ - case -1: - printf("rfork: %r\n"); - return -1; - case 0: - _threadarg->fn = func; - _threadarg->arg = arg; - longjmp(_threadarg->jb, 1); - default: - return 0; - } -} - -long -PyThread_get_thread_ident(void) -{ - if (!initialized) - PyThread_init_thread(); - return getpid(); -} - -void -PyThread_exit_thread(void) -{ - if(initialized) - _exit(0); - exit(0); -} - -void -PyThread__exit_thread(void) -{ - _exit(0); -} - -#ifndef NO_EXIT_PROG -static -void do_PyThread_exit_prog(int status, int no_cleanup) -{ - /* - * BUG BUG BUG - */ - - dprintf(("PyThread_exit_prog(%d) called\n", status)); - if (!initialized) - if (no_cleanup) - _exit(status); - else - exit(status); -} - -void -PyThread_exit_prog(int status) -{ - do_PyThread_exit_prog(status, 0); -} - -void -PyThread__exit_prog(int status) -{ - do_PyThread_exit_prog(status, 1); -} -#endif /* NO_EXIT_PROG */ - -/* - * Lock support. - */ -PyThread_type_lock -PyThread_allocate_lock(void) -{ - QLock *lk; - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - lk = malloc(sizeof(*lk)); - memset(lk, 0, sizeof(*lk)); - dprintf(("PyThread_allocate_lock() -> %p\n", lk)); - return lk; -} - -void -PyThread_free_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_free_lock(%p) called\n", lock)); - free(lock); -} - -int -PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - int success; - - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - if(lock == nil) - success = 0; - else if(waitflag){ - qlock(lock); - success = 1; - }else - success = canqlock(lock); - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; -} - -void -PyThread_release_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_release_lock(%p) called\n", lock)); - qunlock(lock); -} - diff --git a/sys/src/cmd/python/Python/thread_pth.h b/sys/src/cmd/python/Python/thread_pth.h deleted file mode 100644 index 8c7dbe925..000000000 --- a/sys/src/cmd/python/Python/thread_pth.h +++ /dev/null @@ -1,213 +0,0 @@ - -/* GNU pth threads interface - http://www.gnu.org/software/pth - 2000-05-03 Andy Dustman <andy@dustman.net> - - Adapted from Posix threads interface - 12 May 1997 -- david arnold <davida@pobox.com> - */ - -#include <stdlib.h> -#include <string.h> -#include <pth.h> - -/* A pth mutex isn't sufficient to model the Python lock type - * because pth mutexes can be acquired multiple times by the - * same thread. - * - * The pth_lock struct implements a Python lock as a "locked?" bit - * and a <condition, mutex> pair. In general, if the bit can be acquired - * instantly, it is, else the pair is used to block the thread until the - * bit is cleared. - */ - -typedef struct { - char locked; /* 0=unlocked, 1=locked */ - /* a <cond, mutex> pair to handle an acquire of a locked lock */ - pth_cond_t lock_released; - pth_mutex_t mut; -} pth_lock; - -#define CHECK_STATUS(name) if (status == -1) { printf("%d ", status); perror(name); error = 1; } - -pth_attr_t PyThread_attr; - -/* - * Initialization. - */ - -static void PyThread__init_thread(void) -{ - pth_init(); - PyThread_attr = pth_attr_new(); - pth_attr_set(PyThread_attr, PTH_ATTR_STACK_SIZE, 1<<18); - pth_attr_set(PyThread_attr, PTH_ATTR_JOINABLE, FALSE); -} - -/* - * Thread support. - */ - - -long PyThread_start_new_thread(void (*func)(void *), void *arg) -{ - pth_t th; - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); - - th = pth_spawn(PyThread_attr, - (void* (*)(void *))func, - (void *)arg - ); - - return th; -} - -long PyThread_get_thread_ident(void) -{ - volatile pth_t threadid; - if (!initialized) - PyThread_init_thread(); - /* Jump through some hoops for Alpha OSF/1 */ - threadid = pth_self(); - return (long) *(long *) &threadid; -} - -static void do_PyThread_exit_thread(int no_cleanup) -{ - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) { - if (no_cleanup) - _exit(0); - else - exit(0); - } -} - -void PyThread_exit_thread(void) -{ - do_PyThread_exit_thread(0); -} - -void PyThread__exit_thread(void) -{ - do_PyThread_exit_thread(1); -} - -#ifndef NO_EXIT_PROG -static void do_PyThread_exit_prog(int status, int no_cleanup) -{ - dprintf(("PyThread_exit_prog(%d) called\n", status)); - if (!initialized) - if (no_cleanup) - _exit(status); - else - exit(status); -} - -void PyThread_exit_prog(int status) -{ - do_PyThread_exit_prog(status, 0); -} - -void PyThread__exit_prog(int status) -{ - do_PyThread_exit_prog(status, 1); -} -#endif /* NO_EXIT_PROG */ - -/* - * Lock support. - */ -PyThread_type_lock PyThread_allocate_lock(void) -{ - pth_lock *lock; - int status, error = 0; - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - lock = (pth_lock *) malloc(sizeof(pth_lock)); - memset((void *)lock, '\0', sizeof(pth_lock)); - if (lock) { - lock->locked = 0; - status = pth_mutex_init(&lock->mut); - CHECK_STATUS("pth_mutex_init"); - status = pth_cond_init(&lock->lock_released); - CHECK_STATUS("pth_cond_init"); - if (error) { - free((void *)lock); - lock = NULL; - } - } - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock) lock; -} - -void PyThread_free_lock(PyThread_type_lock lock) -{ - pth_lock *thelock = (pth_lock *)lock; - - dprintf(("PyThread_free_lock(%p) called\n", lock)); - - free((void *)thelock); -} - -int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - int success; - pth_lock *thelock = (pth_lock *)lock; - int status, error = 0; - - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - - status = pth_mutex_acquire(&thelock->mut, !waitflag, NULL); - CHECK_STATUS("pth_mutex_acquire[1]"); - success = thelock->locked == 0; - if (success) thelock->locked = 1; - status = pth_mutex_release( &thelock->mut ); - CHECK_STATUS("pth_mutex_release[1]"); - - if ( !success && waitflag ) { - /* continue trying until we get the lock */ - - /* mut must be locked by me -- part of the condition - * protocol */ - status = pth_mutex_acquire( &thelock->mut, !waitflag, NULL ); - CHECK_STATUS("pth_mutex_acquire[2]"); - while ( thelock->locked ) { - status = pth_cond_await(&thelock->lock_released, - &thelock->mut, NULL); - CHECK_STATUS("pth_cond_await"); - } - thelock->locked = 1; - status = pth_mutex_release( &thelock->mut ); - CHECK_STATUS("pth_mutex_release[2]"); - success = 1; - } - if (error) success = 0; - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; -} - -void PyThread_release_lock(PyThread_type_lock lock) -{ - pth_lock *thelock = (pth_lock *)lock; - int status, error = 0; - - dprintf(("PyThread_release_lock(%p) called\n", lock)); - - status = pth_mutex_acquire( &thelock->mut, 0, NULL ); - CHECK_STATUS("pth_mutex_acquire[3]"); - - thelock->locked = 0; - - status = pth_mutex_release( &thelock->mut ); - CHECK_STATUS("pth_mutex_release[3]"); - - /* wake up someone (anyone, if any) waiting on the lock */ - status = pth_cond_notify( &thelock->lock_released, 0 ); - CHECK_STATUS("pth_cond_notify"); -} diff --git a/sys/src/cmd/python/Python/thread_pthread.h b/sys/src/cmd/python/Python/thread_pthread.h deleted file mode 100644 index 60d2fb216..000000000 --- a/sys/src/cmd/python/Python/thread_pthread.h +++ /dev/null @@ -1,533 +0,0 @@ - -/* Posix threads interface */ - -#include <stdlib.h> -#include <string.h> -#if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR) -#define destructor xxdestructor -#endif -#include <pthread.h> -#if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR) -#undef destructor -#endif -#include <signal.h> - -/* The POSIX spec requires that use of pthread_attr_setstacksize - be conditional on _POSIX_THREAD_ATTR_STACKSIZE being defined. */ -#ifdef _POSIX_THREAD_ATTR_STACKSIZE -#ifndef THREAD_STACK_SIZE -#define THREAD_STACK_SIZE 0 /* use default stack size */ -#endif -/* for safety, ensure a viable minimum stacksize */ -#define THREAD_STACK_MIN 0x8000 /* 32kB */ -#else /* !_POSIX_THREAD_ATTR_STACKSIZE */ -#ifdef THREAD_STACK_SIZE -#error "THREAD_STACK_SIZE defined but _POSIX_THREAD_ATTR_STACKSIZE undefined" -#endif -#endif - -/* The POSIX spec says that implementations supporting the sem_* - family of functions must indicate this by defining - _POSIX_SEMAPHORES. */ -#ifdef _POSIX_SEMAPHORES -/* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so - we need to add 0 to make it work there as well. */ -#if (_POSIX_SEMAPHORES+0) == -1 -#define HAVE_BROKEN_POSIX_SEMAPHORES -#else -#include <semaphore.h> -#include <errno.h> -#endif -#endif - -/* Before FreeBSD 5.4, system scope threads was very limited resource - in default setting. So the process scope is preferred to get - enough number of threads to work. */ -#ifdef __FreeBSD__ -#include <osreldate.h> -#if __FreeBSD_version >= 500000 && __FreeBSD_version < 504101 -#undef PTHREAD_SYSTEM_SCHED_SUPPORTED -#endif -#endif - -#if !defined(pthread_attr_default) -# define pthread_attr_default ((pthread_attr_t *)NULL) -#endif -#if !defined(pthread_mutexattr_default) -# define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL) -#endif -#if !defined(pthread_condattr_default) -# define pthread_condattr_default ((pthread_condattr_t *)NULL) -#endif - - -/* Whether or not to use semaphores directly rather than emulating them with - * mutexes and condition variables: - */ -#if defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES) -# define USE_SEMAPHORES -#else -# undef USE_SEMAPHORES -#endif - - -/* On platforms that don't use standard POSIX threads pthread_sigmask() - * isn't present. DEC threads uses sigprocmask() instead as do most - * other UNIX International compliant systems that don't have the full - * pthread implementation. - */ -#if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK) -# define SET_THREAD_SIGMASK pthread_sigmask -#else -# define SET_THREAD_SIGMASK sigprocmask -#endif - - -/* A pthread mutex isn't sufficient to model the Python lock type - * because, according to Draft 5 of the docs (P1003.4a/D5), both of the - * following are undefined: - * -> a thread tries to lock a mutex it already has locked - * -> a thread tries to unlock a mutex locked by a different thread - * pthread mutexes are designed for serializing threads over short pieces - * of code anyway, so wouldn't be an appropriate implementation of - * Python's locks regardless. - * - * The pthread_lock struct implements a Python lock as a "locked?" bit - * and a <condition, mutex> pair. In general, if the bit can be acquired - * instantly, it is, else the pair is used to block the thread until the - * bit is cleared. 9 May 1994 tim@ksr.com - */ - -typedef struct { - char locked; /* 0=unlocked, 1=locked */ - /* a <cond, mutex> pair to handle an acquire of a locked lock */ - pthread_cond_t lock_released; - pthread_mutex_t mut; -} pthread_lock; - -#define CHECK_STATUS(name) if (status != 0) { perror(name); error = 1; } - -/* - * Initialization. - */ - -#ifdef _HAVE_BSDI -static -void _noop(void) -{ -} - -static void -PyThread__init_thread(void) -{ - /* DO AN INIT BY STARTING THE THREAD */ - static int dummy = 0; - pthread_t thread1; - pthread_create(&thread1, NULL, (void *) _noop, &dummy); - pthread_join(thread1, NULL); -} - -#else /* !_HAVE_BSDI */ - -static void -PyThread__init_thread(void) -{ -#if defined(_AIX) && defined(__GNUC__) - pthread_init(); -#endif -} - -#endif /* !_HAVE_BSDI */ - -/* - * Thread support. - */ - - -long -PyThread_start_new_thread(void (*func)(void *), void *arg) -{ - pthread_t th; - int status; -#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) - pthread_attr_t attrs; -#endif -#if defined(THREAD_STACK_SIZE) - size_t tss; -#endif - - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); - -#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) - if (pthread_attr_init(&attrs) != 0) - return -1; -#endif -#if defined(THREAD_STACK_SIZE) - tss = (_pythread_stacksize != 0) ? _pythread_stacksize - : THREAD_STACK_SIZE; - if (tss != 0) { - if (pthread_attr_setstacksize(&attrs, tss) != 0) { - pthread_attr_destroy(&attrs); - return -1; - } - } -#endif -#if defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) - pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM); -#endif - - status = pthread_create(&th, -#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) - &attrs, -#else - (pthread_attr_t*)NULL, -#endif - (void* (*)(void *))func, - (void *)arg - ); - -#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) - pthread_attr_destroy(&attrs); -#endif - if (status != 0) - return -1; - - pthread_detach(th); - -#if SIZEOF_PTHREAD_T <= SIZEOF_LONG - return (long) th; -#else - return (long) *(long *) &th; -#endif -} - -/* XXX This implementation is considered (to quote Tim Peters) "inherently - hosed" because: - - It does not guarantee the promise that a non-zero integer is returned. - - The cast to long is inherently unsafe. - - It is not clear that the 'volatile' (for AIX?) and ugly casting in the - latter return statement (for Alpha OSF/1) are any longer necessary. -*/ -long -PyThread_get_thread_ident(void) -{ - volatile pthread_t threadid; - if (!initialized) - PyThread_init_thread(); - /* Jump through some hoops for Alpha OSF/1 */ - threadid = pthread_self(); -#if SIZEOF_PTHREAD_T <= SIZEOF_LONG - return (long) threadid; -#else - return (long) *(long *) &threadid; -#endif -} - -static void -do_PyThread_exit_thread(int no_cleanup) -{ - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) { - if (no_cleanup) - _exit(0); - else - exit(0); - } -} - -void -PyThread_exit_thread(void) -{ - do_PyThread_exit_thread(0); -} - -void -PyThread__exit_thread(void) -{ - do_PyThread_exit_thread(1); -} - -#ifndef NO_EXIT_PROG -static void -do_PyThread_exit_prog(int status, int no_cleanup) -{ - dprintf(("PyThread_exit_prog(%d) called\n", status)); - if (!initialized) - if (no_cleanup) - _exit(status); - else - exit(status); -} - -void -PyThread_exit_prog(int status) -{ - do_PyThread_exit_prog(status, 0); -} - -void -PyThread__exit_prog(int status) -{ - do_PyThread_exit_prog(status, 1); -} -#endif /* NO_EXIT_PROG */ - -#ifdef USE_SEMAPHORES - -/* - * Lock support. - */ - -PyThread_type_lock -PyThread_allocate_lock(void) -{ - sem_t *lock; - int status, error = 0; - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - lock = (sem_t *)malloc(sizeof(sem_t)); - - if (lock) { - status = sem_init(lock,0,1); - CHECK_STATUS("sem_init"); - - if (error) { - free((void *)lock); - lock = NULL; - } - } - - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock)lock; -} - -void -PyThread_free_lock(PyThread_type_lock lock) -{ - sem_t *thelock = (sem_t *)lock; - int status, error = 0; - - dprintf(("PyThread_free_lock(%p) called\n", lock)); - - if (!thelock) - return; - - status = sem_destroy(thelock); - CHECK_STATUS("sem_destroy"); - - free((void *)thelock); -} - -/* - * As of February 2002, Cygwin thread implementations mistakenly report error - * codes in the return value of the sem_ calls (like the pthread_ functions). - * Correct implementations return -1 and put the code in errno. This supports - * either. - */ -static int -fix_status(int status) -{ - return (status == -1) ? errno : status; -} - -int -PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - int success; - sem_t *thelock = (sem_t *)lock; - int status, error = 0; - - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - - do { - if (waitflag) - status = fix_status(sem_wait(thelock)); - else - status = fix_status(sem_trywait(thelock)); - } while (status == EINTR); /* Retry if interrupted by a signal */ - - if (waitflag) { - CHECK_STATUS("sem_wait"); - } else if (status != EAGAIN) { - CHECK_STATUS("sem_trywait"); - } - - success = (status == 0) ? 1 : 0; - - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; -} - -void -PyThread_release_lock(PyThread_type_lock lock) -{ - sem_t *thelock = (sem_t *)lock; - int status, error = 0; - - dprintf(("PyThread_release_lock(%p) called\n", lock)); - - status = sem_post(thelock); - CHECK_STATUS("sem_post"); -} - -#else /* USE_SEMAPHORES */ - -/* - * Lock support. - */ -PyThread_type_lock -PyThread_allocate_lock(void) -{ - pthread_lock *lock; - int status, error = 0; - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - lock = (pthread_lock *) malloc(sizeof(pthread_lock)); - if (lock) { - memset((void *)lock, '\0', sizeof(pthread_lock)); - lock->locked = 0; - - status = pthread_mutex_init(&lock->mut, - pthread_mutexattr_default); - CHECK_STATUS("pthread_mutex_init"); - - status = pthread_cond_init(&lock->lock_released, - pthread_condattr_default); - CHECK_STATUS("pthread_cond_init"); - - if (error) { - free((void *)lock); - lock = 0; - } - } - - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock) lock; -} - -void -PyThread_free_lock(PyThread_type_lock lock) -{ - pthread_lock *thelock = (pthread_lock *)lock; - int status, error = 0; - - dprintf(("PyThread_free_lock(%p) called\n", lock)); - - status = pthread_mutex_destroy( &thelock->mut ); - CHECK_STATUS("pthread_mutex_destroy"); - - status = pthread_cond_destroy( &thelock->lock_released ); - CHECK_STATUS("pthread_cond_destroy"); - - free((void *)thelock); -} - -int -PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - int success; - pthread_lock *thelock = (pthread_lock *)lock; - int status, error = 0; - - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - - status = pthread_mutex_lock( &thelock->mut ); - CHECK_STATUS("pthread_mutex_lock[1]"); - success = thelock->locked == 0; - - if ( !success && waitflag ) { - /* continue trying until we get the lock */ - - /* mut must be locked by me -- part of the condition - * protocol */ - while ( thelock->locked ) { - status = pthread_cond_wait(&thelock->lock_released, - &thelock->mut); - CHECK_STATUS("pthread_cond_wait"); - } - success = 1; - } - if (success) thelock->locked = 1; - status = pthread_mutex_unlock( &thelock->mut ); - CHECK_STATUS("pthread_mutex_unlock[1]"); - - if (error) success = 0; - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; -} - -void -PyThread_release_lock(PyThread_type_lock lock) -{ - pthread_lock *thelock = (pthread_lock *)lock; - int status, error = 0; - - dprintf(("PyThread_release_lock(%p) called\n", lock)); - - status = pthread_mutex_lock( &thelock->mut ); - CHECK_STATUS("pthread_mutex_lock[3]"); - - thelock->locked = 0; - - status = pthread_mutex_unlock( &thelock->mut ); - CHECK_STATUS("pthread_mutex_unlock[3]"); - - /* wake up someone (anyone, if any) waiting on the lock */ - status = pthread_cond_signal( &thelock->lock_released ); - CHECK_STATUS("pthread_cond_signal"); -} - -#endif /* USE_SEMAPHORES */ - -/* set the thread stack size. - * Return 0 if size is valid, -1 if size is invalid, - * -2 if setting stack size is not supported. - */ -static int -_pythread_pthread_set_stacksize(size_t size) -{ -#if defined(THREAD_STACK_SIZE) - pthread_attr_t attrs; - size_t tss_min; - int rc = 0; -#endif - - /* set to default */ - if (size == 0) { - _pythread_stacksize = 0; - return 0; - } - -#if defined(THREAD_STACK_SIZE) -#if defined(PTHREAD_STACK_MIN) - tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN - : THREAD_STACK_MIN; -#else - tss_min = THREAD_STACK_MIN; -#endif - if (size >= tss_min) { - /* validate stack size by setting thread attribute */ - if (pthread_attr_init(&attrs) == 0) { - rc = pthread_attr_setstacksize(&attrs, size); - pthread_attr_destroy(&attrs); - if (rc == 0) { - _pythread_stacksize = size; - return 0; - } - } - } - return -1; -#else - return -2; -#endif -} - -#define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x) diff --git a/sys/src/cmd/python/Python/thread_sgi.h b/sys/src/cmd/python/Python/thread_sgi.h deleted file mode 100644 index 234665848..000000000 --- a/sys/src/cmd/python/Python/thread_sgi.h +++ /dev/null @@ -1,375 +0,0 @@ - -#include <stdlib.h> -#include <stdio.h> -#include <signal.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/prctl.h> -#include <ulocks.h> -#include <errno.h> - -#define HDR_SIZE 2680 /* sizeof(ushdr_t) */ -#define MAXPROC 100 /* max # of threads that can be started */ - -static usptr_t *shared_arena; -static ulock_t count_lock; /* protection for some variables */ -static ulock_t wait_lock; /* lock used to wait for other threads */ -static int waiting_for_threads; /* protected by count_lock */ -static int nthreads; /* protected by count_lock */ -static int exit_status; -#ifndef NO_EXIT_PROG -static int do_exit; /* indicates that the program is to exit */ -#endif -static int exiting; /* we're already exiting (for maybe_exit) */ -static pid_t my_pid; /* PID of main thread */ -static struct pidlist { - pid_t parent; - pid_t child; -} pidlist[MAXPROC]; /* PIDs of other threads; protected by count_lock */ -static int maxpidindex; /* # of PIDs in pidlist */ - -#ifndef NO_EXIT_PROG -/* - * This routine is called as a signal handler when another thread - * exits. When that happens, we must see whether we have to exit as - * well (because of an PyThread_exit_prog()) or whether we should continue on. - */ -static void exit_sig(void) -{ - d2printf(("exit_sig called\n")); - if (exiting && getpid() == my_pid) { - d2printf(("already exiting\n")); - return; - } - if (do_exit) { - d2printf(("exiting in exit_sig\n")); -#ifdef Py_DEBUG - if ((thread_debug & 8) == 0) - thread_debug &= ~1; /* don't produce debug messages */ -#endif - PyThread_exit_thread(); - } -} - -/* - * This routine is called when a process calls exit(). If that wasn't - * done from the library, we do as if an PyThread_exit_prog() was intended. - */ -static void maybe_exit(void) -{ - dprintf(("maybe_exit called\n")); - if (exiting) { - dprintf(("already exiting\n")); - return; - } - PyThread_exit_prog(0); -} -#endif /* NO_EXIT_PROG */ - -/* - * Initialization. - */ -static void PyThread__init_thread(void) -{ -#ifndef NO_EXIT_PROG - struct sigaction s; -#endif /* NO_EXIT_PROG */ -#ifdef USE_DL - long addr, size; -#endif /* USE_DL */ - - -#ifdef USE_DL - if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0) - perror("usconfig - CONF_INITSIZE (check)"); - if (usconfig(CONF_INITSIZE, size) < 0) - perror("usconfig - CONF_INITSIZE (reset)"); - addr = (long) dl_getrange(size + HDR_SIZE); - dprintf(("trying to use addr %p-%p for shared arena\n", addr, addr+size)); - errno = 0; - if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0) - perror("usconfig - CONF_ATTACHADDR (set)"); -#endif /* USE_DL */ - if (usconfig(CONF_INITUSERS, 16) < 0) - perror("usconfig - CONF_INITUSERS"); - my_pid = getpid(); /* so that we know which is the main thread */ -#ifndef NO_EXIT_PROG - atexit(maybe_exit); - s.sa_handler = exit_sig; - sigemptyset(&s.sa_mask); - /*sigaddset(&s.sa_mask, SIGUSR1);*/ - s.sa_flags = 0; - sigaction(SIGUSR1, &s, 0); - if (prctl(PR_SETEXITSIG, SIGUSR1) < 0) - perror("prctl - PR_SETEXITSIG"); -#endif /* NO_EXIT_PROG */ - if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0) - perror("usconfig - CONF_ARENATYPE"); - usconfig(CONF_LOCKTYPE, US_DEBUG); /* XXX */ -#ifdef Py_DEBUG - if (thread_debug & 4) - usconfig(CONF_LOCKTYPE, US_DEBUGPLUS); - else if (thread_debug & 2) - usconfig(CONF_LOCKTYPE, US_DEBUG); -#endif /* Py_DEBUG */ - if ((shared_arena = usinit(tmpnam(0))) == 0) - perror("usinit"); -#ifdef USE_DL - if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */ - perror("usconfig - CONF_ATTACHADDR (reset)"); -#endif /* USE_DL */ - if ((count_lock = usnewlock(shared_arena)) == NULL) - perror("usnewlock (count_lock)"); - (void) usinitlock(count_lock); - if ((wait_lock = usnewlock(shared_arena)) == NULL) - perror("usnewlock (wait_lock)"); - dprintf(("arena start: %p, arena size: %ld\n", shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena))); -} - -/* - * Thread support. - */ - -static void clean_threads(void) -{ - int i, j; - pid_t mypid, pid; - - /* clean up any exited threads */ - mypid = getpid(); - i = 0; - while (i < maxpidindex) { - if (pidlist[i].parent == mypid && (pid = pidlist[i].child) > 0) { - pid = waitpid(pid, 0, WNOHANG); - if (pid > 0) { - /* a thread has exited */ - pidlist[i] = pidlist[--maxpidindex]; - /* remove references to children of dead proc */ - for (j = 0; j < maxpidindex; j++) - if (pidlist[j].parent == pid) - pidlist[j].child = -1; - continue; /* don't increment i */ - } - } - i++; - } - /* clean up the list */ - i = 0; - while (i < maxpidindex) { - if (pidlist[i].child == -1) { - pidlist[i] = pidlist[--maxpidindex]; - continue; /* don't increment i */ - } - i++; - } -} - -long PyThread_start_new_thread(void (*func)(void *), void *arg) -{ -#ifdef USE_DL - long addr, size; - static int local_initialized = 0; -#endif /* USE_DL */ - int success = 0; /* init not needed when SOLARIS_THREADS and */ - /* C_THREADS implemented properly */ - - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); - switch (ussetlock(count_lock)) { - case 0: return 0; - case -1: perror("ussetlock (count_lock)"); - } - if (maxpidindex >= MAXPROC) - success = -1; - else { -#ifdef USE_DL - if (!local_initialized) { - if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0) - perror("usconfig - CONF_INITSIZE (check)"); - if (usconfig(CONF_INITSIZE, size) < 0) - perror("usconfig - CONF_INITSIZE (reset)"); - addr = (long) dl_getrange(size + HDR_SIZE); - dprintf(("trying to use addr %p-%p for sproc\n", - addr, addr+size)); - errno = 0; - if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && - errno != 0) - perror("usconfig - CONF_ATTACHADDR (set)"); - } -#endif /* USE_DL */ - clean_threads(); - if ((success = sproc(func, PR_SALL, arg)) < 0) - perror("sproc"); -#ifdef USE_DL - if (!local_initialized) { - if (usconfig(CONF_ATTACHADDR, addr) < 0) - /* reset address */ - perror("usconfig - CONF_ATTACHADDR (reset)"); - local_initialized = 1; - } -#endif /* USE_DL */ - if (success >= 0) { - nthreads++; - pidlist[maxpidindex].parent = getpid(); - pidlist[maxpidindex++].child = success; - dprintf(("pidlist[%d] = %d\n", - maxpidindex-1, success)); - } - } - if (usunsetlock(count_lock) < 0) - perror("usunsetlock (count_lock)"); - return success; -} - -long PyThread_get_thread_ident(void) -{ - return getpid(); -} - -static void do_PyThread_exit_thread(int no_cleanup) -{ - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) - if (no_cleanup) - _exit(0); - else - exit(0); - if (ussetlock(count_lock) < 0) - perror("ussetlock (count_lock)"); - nthreads--; - if (getpid() == my_pid) { - /* main thread; wait for other threads to exit */ - exiting = 1; -#ifndef NO_EXIT_PROG - if (do_exit) { - int i; - - /* notify other threads */ - clean_threads(); - if (nthreads >= 0) { - dprintf(("kill other threads\n")); - for (i = 0; i < maxpidindex; i++) - if (pidlist[i].child > 0) - (void) kill(pidlist[i].child, - SIGKILL); - _exit(exit_status); - } - } -#endif /* NO_EXIT_PROG */ - waiting_for_threads = 1; - if (ussetlock(wait_lock) < 0) - perror("ussetlock (wait_lock)"); - for (;;) { - if (nthreads < 0) { - dprintf(("really exit (%d)\n", exit_status)); - if (no_cleanup) - _exit(exit_status); - else - exit(exit_status); - } - if (usunsetlock(count_lock) < 0) - perror("usunsetlock (count_lock)"); - dprintf(("waiting for other threads (%d)\n", nthreads)); - if (ussetlock(wait_lock) < 0) - perror("ussetlock (wait_lock)"); - if (ussetlock(count_lock) < 0) - perror("ussetlock (count_lock)"); - } - } - /* not the main thread */ - if (waiting_for_threads) { - dprintf(("main thread is waiting\n")); - if (usunsetlock(wait_lock) < 0) - perror("usunsetlock (wait_lock)"); - } -#ifndef NO_EXIT_PROG - else if (do_exit) - (void) kill(my_pid, SIGUSR1); -#endif /* NO_EXIT_PROG */ - if (usunsetlock(count_lock) < 0) - perror("usunsetlock (count_lock)"); - _exit(0); -} - -void PyThread_exit_thread(void) -{ - do_PyThread_exit_thread(0); -} - -void PyThread__exit_thread(void) -{ - do_PyThread_exit_thread(1); -} - -#ifndef NO_EXIT_PROG -static void do_PyThread_exit_prog(int status, int no_cleanup) -{ - dprintf(("PyThread_exit_prog(%d) called\n", status)); - if (!initialized) - if (no_cleanup) - _exit(status); - else - exit(status); - do_exit = 1; - exit_status = status; - do_PyThread_exit_thread(no_cleanup); -} - -void PyThread_exit_prog(int status) -{ - do_PyThread_exit_prog(status, 0); -} - -void PyThread__exit_prog(int status) -{ - do_PyThread_exit_prog(status, 1); -} -#endif /* NO_EXIT_PROG */ - -/* - * Lock support. - */ -PyThread_type_lock PyThread_allocate_lock(void) -{ - ulock_t lock; - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - if ((lock = usnewlock(shared_arena)) == NULL) - perror("usnewlock"); - (void) usinitlock(lock); - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock) lock; -} - -void PyThread_free_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_free_lock(%p) called\n", lock)); - usfreelock((ulock_t) lock, shared_arena); -} - -int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - int success; - - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - errno = 0; /* clear it just in case */ - if (waitflag) - success = ussetlock((ulock_t) lock); - else - success = uscsetlock((ulock_t) lock, 1); /* Try it once */ - if (success < 0) - perror(waitflag ? "ussetlock" : "uscsetlock"); - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; -} - -void PyThread_release_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_release_lock(%p) called\n", lock)); - if (usunsetlock((ulock_t) lock) < 0) - perror("usunsetlock"); -} diff --git a/sys/src/cmd/python/Python/thread_solaris.h b/sys/src/cmd/python/Python/thread_solaris.h deleted file mode 100644 index ff3e6f359..000000000 --- a/sys/src/cmd/python/Python/thread_solaris.h +++ /dev/null @@ -1,174 +0,0 @@ - -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include </usr/include/thread.h> -#undef _POSIX_THREADS - - -/* - * Initialization. - */ -static void PyThread__init_thread(void) -{ -} - -/* - * Thread support. - */ -struct func_arg { - void (*func)(void *); - void *arg; -}; - -static void * -new_func(void *funcarg) -{ - void (*func)(void *); - void *arg; - - func = ((struct func_arg *) funcarg)->func; - arg = ((struct func_arg *) funcarg)->arg; - free(funcarg); - (*func)(arg); - return 0; -} - - -long -PyThread_start_new_thread(void (*func)(void *), void *arg) -{ - thread_t tid; - struct func_arg *funcarg; - - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); - funcarg = (struct func_arg *) malloc(sizeof(struct func_arg)); - funcarg->func = func; - funcarg->arg = arg; - if (thr_create(0, 0, new_func, funcarg, - THR_DETACHED | THR_NEW_LWP, &tid)) { - perror("thr_create"); - free((void *) funcarg); - return -1; - } - return tid; -} - -long -PyThread_get_thread_ident(void) -{ - if (!initialized) - PyThread_init_thread(); - return thr_self(); -} - -static void -do_PyThread_exit_thread(int no_cleanup) -{ - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) - if (no_cleanup) - _exit(0); - else - exit(0); - thr_exit(0); -} - -void -PyThread_exit_thread(void) -{ - do_PyThread_exit_thread(0); -} - -void -PyThread__exit_thread(void) -{ - do_PyThread_exit_thread(1); -} - -#ifndef NO_EXIT_PROG -static void -do_PyThread_exit_prog(int status, int no_cleanup) -{ - dprintf(("PyThread_exit_prog(%d) called\n", status)); - if (!initialized) - if (no_cleanup) - _exit(status); - else - exit(status); - if (no_cleanup) - _exit(status); - else - exit(status); -} - -void -PyThread_exit_prog(int status) -{ - do_PyThread_exit_prog(status, 0); -} - -void -PyThread__exit_prog(int status) -{ - do_PyThread_exit_prog(status, 1); -} -#endif /* NO_EXIT_PROG */ - -/* - * Lock support. - */ -PyThread_type_lock -PyThread_allocate_lock(void) -{ - mutex_t *lock; - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - lock = (mutex_t *) malloc(sizeof(mutex_t)); - if (mutex_init(lock, USYNC_THREAD, 0)) { - perror("mutex_init"); - free((void *) lock); - lock = 0; - } - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock) lock; -} - -void -PyThread_free_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_free_lock(%p) called\n", lock)); - mutex_destroy((mutex_t *) lock); - free((void *) lock); -} - -int -PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - int success; - - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - if (waitflag) - success = mutex_lock((mutex_t *) lock); - else - success = mutex_trylock((mutex_t *) lock); - if (success < 0) - perror(waitflag ? "mutex_lock" : "mutex_trylock"); - else - success = !success; /* solaris does it the other way round */ - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; -} - -void -PyThread_release_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_release_lock(%p) called\n", lock)); - if (mutex_unlock((mutex_t *) lock)) - perror("mutex_unlock"); -} diff --git a/sys/src/cmd/python/Python/thread_wince.h b/sys/src/cmd/python/Python/thread_wince.h deleted file mode 100644 index e16f5d141..000000000 --- a/sys/src/cmd/python/Python/thread_wince.h +++ /dev/null @@ -1,171 +0,0 @@ - -/* This code implemented by Mark Hammond (MHammond@skippinet.com.au) */ - -#include <windows.h> -#include <limits.h> -#include <pydebug.h> - -long PyThread_get_thread_ident(void); - -/* - * Change all headers to pure ANSI as no one will use K&R style on an - * NT - */ - -/* - * Initialization of the C package, should not be needed. - */ -static void PyThread__init_thread(void) -{ -} - -/* - * Thread support. - */ -long PyThread_start_new_thread(void (*func)(void *), void *arg) -{ - long rv; - int success = -1; - - dprintf(("%ld: PyThread_start_new_thread called\n", PyThread_get_thread_ident())); - if (!initialized) - PyThread_init_thread(); - - rv = _beginthread(func, 0, arg); /* use default stack size */ - - if (rv != -1) { - success = 0; - dprintf(("%ld: PyThread_start_new_thread succeeded:\n", PyThread_get_thread_ident())); - } - - return success; -} - -/* - * Return the thread Id instead of an handle. The Id is said to uniquely identify the - * thread in the system - */ -long PyThread_get_thread_ident(void) -{ - if (!initialized) - PyThread_init_thread(); - - return GetCurrentThreadId(); -} - -static void do_PyThread_exit_thread(int no_cleanup) -{ - dprintf(("%ld: do_PyThread_exit_thread called\n", PyThread_get_thread_ident())); - if (!initialized) - if (no_cleanup) - exit(0); /* XXX - was _exit()!! */ - else - exit(0); - _endthread(); -} - -void PyThread_exit_thread(void) -{ - do_PyThread_exit_thread(0); -} - -void PyThread__exit_thread(void) -{ - do_PyThread_exit_thread(1); -} - -#ifndef NO_EXIT_PROG -static void do_PyThread_exit_prog(int status, int no_cleanup) -{ - dprintf(("PyThread_exit_prog(%d) called\n", status)); - if (!initialized) - if (no_cleanup) - _exit(status); - else - exit(status); -} - -void PyThread_exit_prog(int status) -{ - do_PyThread_exit_prog(status, 0); -} - -void PyThread__exit_prog(int status) -{ - do_PyThread_exit_prog(status, 1); -} -#endif /* NO_EXIT_PROG */ - -/* - * Lock support. It has to be implemented using Mutexes, as - * CE doesnt support semaphores. Therefore we use some hacks to - * simulate the non reentrant requirements of Python locks - */ -PyThread_type_lock PyThread_allocate_lock(void) -{ - HANDLE aLock; - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - aLock = CreateEvent(NULL, /* Security attributes */ - 0, /* Manual-Reset */ - 1, /* Is initially signalled */ - NULL); /* Name of event */ - - dprintf(("%ld: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock)); - - return (PyThread_type_lock) aLock; -} - -void PyThread_free_lock(PyThread_type_lock aLock) -{ - dprintf(("%ld: PyThread_free_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); - - CloseHandle(aLock); -} - -/* - * Return 1 on success if the lock was acquired - * - * and 0 if the lock was not acquired. This means a 0 is returned - * if the lock has already been acquired by this thread! - */ -int PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag) -{ - int success = 1; - DWORD waitResult; - - dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", PyThread_get_thread_ident(),aLock, waitflag)); - -#ifndef DEBUG - waitResult = WaitForSingleObject(aLock, (waitflag ? INFINITE : 0)); -#else - /* To aid in debugging, we regularly wake up. This allows us to - break into the debugger */ - while (TRUE) { - waitResult = WaitForSingleObject(aLock, waitflag ? 3000 : 0); - if (waitflag==0 || (waitflag && waitResult == WAIT_OBJECT_0)) - break; - } -#endif - - if (waitResult != WAIT_OBJECT_0) { - success = 0; /* We failed */ - } - - dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n", PyThread_get_thread_ident(),aLock, waitflag, success)); - - return success; -} - -void PyThread_release_lock(PyThread_type_lock aLock) -{ - dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); - - if (!SetEvent(aLock)) - dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", PyThread_get_thread_ident(), aLock, GetLastError())); -} - - diff --git a/sys/src/cmd/python/Python/traceback.c b/sys/src/cmd/python/Python/traceback.c deleted file mode 100644 index 4ddee2c73..000000000 --- a/sys/src/cmd/python/Python/traceback.c +++ /dev/null @@ -1,262 +0,0 @@ - -/* Traceback implementation */ - -#include "Python.h" - -#include "code.h" -#include "frameobject.h" -#include "structmember.h" -#include "osdefs.h" -#include "traceback.h" - -#define OFF(x) offsetof(PyTracebackObject, x) - -static struct memberlist tb_memberlist[] = { - {"tb_next", T_OBJECT, OFF(tb_next)}, - {"tb_frame", T_OBJECT, OFF(tb_frame)}, - {"tb_lasti", T_INT, OFF(tb_lasti)}, - {"tb_lineno", T_INT, OFF(tb_lineno)}, - {NULL} /* Sentinel */ -}; - -static PyObject * -tb_getattr(PyTracebackObject *tb, char *name) -{ - return PyMember_Get((char *)tb, tb_memberlist, name); -} - -static void -tb_dealloc(PyTracebackObject *tb) -{ - PyObject_GC_UnTrack(tb); - Py_TRASHCAN_SAFE_BEGIN(tb) - Py_XDECREF(tb->tb_next); - Py_XDECREF(tb->tb_frame); - PyObject_GC_Del(tb); - Py_TRASHCAN_SAFE_END(tb) -} - -static int -tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg) -{ - Py_VISIT(tb->tb_next); - Py_VISIT(tb->tb_frame); - return 0; -} - -static void -tb_clear(PyTracebackObject *tb) -{ - Py_CLEAR(tb->tb_next); - Py_CLEAR(tb->tb_frame); -} - -PyTypeObject PyTraceBack_Type = { - PyObject_HEAD_INIT(&PyType_Type) - 0, - "traceback", - sizeof(PyTracebackObject), - 0, - (destructor)tb_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - (getattrfunc)tb_getattr, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - 0, /* tp_doc */ - (traverseproc)tb_traverse, /* tp_traverse */ - (inquiry)tb_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ -}; - -static PyTracebackObject * -newtracebackobject(PyTracebackObject *next, PyFrameObject *frame) -{ - PyTracebackObject *tb; - if ((next != NULL && !PyTraceBack_Check(next)) || - frame == NULL || !PyFrame_Check(frame)) { - PyErr_BadInternalCall(); - return NULL; - } - tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type); - if (tb != NULL) { - Py_XINCREF(next); - tb->tb_next = next; - Py_XINCREF(frame); - tb->tb_frame = frame; - tb->tb_lasti = frame->f_lasti; - tb->tb_lineno = PyCode_Addr2Line(frame->f_code, - frame->f_lasti); - PyObject_GC_Track(tb); - } - return tb; -} - -int -PyTraceBack_Here(PyFrameObject *frame) -{ - PyThreadState *tstate = PyThreadState_GET(); - PyTracebackObject *oldtb = (PyTracebackObject *) tstate->curexc_traceback; - PyTracebackObject *tb = newtracebackobject(oldtb, frame); - if (tb == NULL) - return -1; - tstate->curexc_traceback = (PyObject *)tb; - Py_XDECREF(oldtb); - return 0; -} - -static int -tb_displayline(PyObject *f, char *filename, int lineno, char *name) -{ - int err = 0; - FILE *xfp; - char linebuf[2000]; - int i; - if (filename == NULL || name == NULL) - return -1; - /* This is needed by Emacs' compile command */ -#define FMT " File \"%.500s\", line %d, in %.500s\n" - xfp = fopen(filename, "r" PY_STDIOTEXTMODE); - if (xfp == NULL) { - /* Search tail of filename in sys.path before giving up */ - PyObject *path; - char *tail = strrchr(filename, SEP); - if (tail == NULL) - tail = filename; - else - tail++; - path = PySys_GetObject("path"); - if (path != NULL && PyList_Check(path)) { - Py_ssize_t _npath = PyList_Size(path); - int npath = Py_SAFE_DOWNCAST(_npath, Py_ssize_t, int); - size_t taillen = strlen(tail); - char namebuf[MAXPATHLEN+1]; - for (i = 0; i < npath; i++) { - PyObject *v = PyList_GetItem(path, i); - if (v == NULL) { - PyErr_Clear(); - break; - } - if (PyString_Check(v)) { - size_t len; - len = PyString_GET_SIZE(v); - if (len + 1 + taillen >= MAXPATHLEN) - continue; /* Too long */ - strcpy(namebuf, PyString_AsString(v)); - if (strlen(namebuf) != len) - continue; /* v contains '\0' */ - if (len > 0 && namebuf[len-1] != SEP) - namebuf[len++] = SEP; - strcpy(namebuf+len, tail); - xfp = fopen(namebuf, "r" PY_STDIOTEXTMODE); - if (xfp != NULL) { - filename = namebuf; - break; - } - } - } - } - } - PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name); - err = PyFile_WriteString(linebuf, f); - if (xfp == NULL) - return err; - else if (err != 0) { - fclose(xfp); - return err; - } - for (i = 0; i < lineno; i++) { - char* pLastChar = &linebuf[sizeof(linebuf)-2]; - do { - *pLastChar = '\0'; - if (Py_UniversalNewlineFgets(linebuf, sizeof linebuf, xfp, NULL) == NULL) - break; - /* fgets read *something*; if it didn't get as - far as pLastChar, it must have found a newline - or hit the end of the file; if pLastChar is \n, - it obviously found a newline; else we haven't - yet seen a newline, so must continue */ - } while (*pLastChar != '\0' && *pLastChar != '\n'); - } - if (i == lineno) { - char *p = linebuf; - while (*p == ' ' || *p == '\t' || *p == '\014') - p++; - err = PyFile_WriteString(" ", f); - if (err == 0) { - err = PyFile_WriteString(p, f); - if (err == 0 && strchr(p, '\n') == NULL) - err = PyFile_WriteString("\n", f); - } - } - fclose(xfp); - return err; -} - -static int -tb_printinternal(PyTracebackObject *tb, PyObject *f, int limit) -{ - int err = 0; - int depth = 0; - PyTracebackObject *tb1 = tb; - while (tb1 != NULL) { - depth++; - tb1 = tb1->tb_next; - } - while (tb != NULL && err == 0) { - if (depth <= limit) { - err = tb_displayline(f, - PyString_AsString( - tb->tb_frame->f_code->co_filename), - tb->tb_lineno, - PyString_AsString(tb->tb_frame->f_code->co_name)); - } - depth--; - tb = tb->tb_next; - if (err == 0) - err = PyErr_CheckSignals(); - } - return err; -} - -int -PyTraceBack_Print(PyObject *v, PyObject *f) -{ - int err; - PyObject *limitv; - int limit = 1000; - if (v == NULL) - return 0; - if (!PyTraceBack_Check(v)) { - PyErr_BadInternalCall(); - return -1; - } - limitv = PySys_GetObject("tracebacklimit"); - if (limitv && PyInt_Check(limitv)) { - limit = PyInt_AsLong(limitv); - if (limit <= 0) - return 0; - } - err = PyFile_WriteString("Traceback (most recent call last):\n", f); - if (!err) - err = tb_printinternal((PyTracebackObject *)v, f, limit); - return err; -} |